kenzok8-package/shadowsocksr-libev/patches/103-Add-TPROXY-support-for-TCP-ssr-redir.patch
2024-02-15 23:34:51 +08:00

155 lines
4.8 KiB
Diff

--- a/completions/bash/ss-redir
+++ b/completions/bash/ss-redir
@@ -2,7 +2,7 @@ _ss_redir()
{
local cur prev opts ciphers
ciphers='rc4-md5 table rc4 aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr bf-cfb camellia-128-cfb camellia-192-cfb camellia-256-cfb cast5-cfb des-cfb idea-cfb rc2-cfb seed-cfb salsa20 chacha20 and chacha20-ietf'
- opts='-s -b -p -k -f -t -m -c -a -n -u -U -v -h -A --mtu --help --mptcp -l'
+ opts='-s -b -p -k -f -t -m -c -a -n -u -U -T -v -h -A --mtu --help --mptcp -l'
cur=${COMP_WORDS[COMP_CWORD]}
prev="${COMP_WORDS[COMP_CWORD-1]}"
case "$prev" in
--- a/src/jconf.c
+++ b/src/jconf.c
@@ -338,7 +338,11 @@ read_jconf(const char *file)
check_json_value_type(value, json_boolean,
"invalid config file: option 'ipv6_first' must be a boolean");
conf.ipv6_first = value->u.boolean;
- }
+ } else if (strcmp(name, "tcp_tproxy") == 0) {
+ check_json_value_type(value, json_boolean,
+ "invalid config file: option 'tcp_tproxy' must be a boolean");
+ conf.tcp_tproxy = value->u.boolean;
+ }
}
}
} else {
--- a/src/jconf.h
+++ b/src/jconf.h
@@ -105,6 +105,7 @@ typedef struct {
int mtu;
int mptcp;
int ipv6_first;
+ int tcp_tproxy;
} jconf_t;
jconf_t *read_jconf(const char *file);
--- a/src/redir.c
+++ b/src/redir.c
@@ -71,6 +71,14 @@
#define IP6T_SO_ORIGINAL_DST 80
#endif
+#ifndef IP_TRANSPARENT
+#define IP_TRANSPARENT 19
+#endif
+
+#ifndef IPV6_TRANSPARENT
+#define IPV6_TRANSPARENT 75
+#endif
+
#include "includeobfs.h" // I don't want to modify makefile
#include "jconf.h"
@@ -101,18 +109,28 @@ static struct cork_dllist inactive_profi
static listen_ctx_t *current_profile;
static struct cork_dllist all_connections;
+static int tcp_tproxy = 0; /* use tproxy instead of redirect (for tcp) */
+
int
getdestaddr(int fd, struct sockaddr_storage *destaddr)
{
socklen_t socklen = sizeof(*destaddr);
int error = 0;
- error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
- if (error) { // Didn't find a proper way to detect IP version.
- error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
- if (error) {
- return -1;
- }
+ if (tcp_tproxy) {
+ error = getsockname(fd, (void *)destaddr, &socklen);
+ } else {
+ error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
+ if (error) { // Didn't find a proper way to detect IP version.
+ error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
+ if (error) {
+ return -1;
+ }
+ }
+ }
+
+ if (error) {
+ return -1;
}
return 0;
}
@@ -164,6 +182,23 @@ create_and_bind(const char *addr, const
if (err == 0) {
LOGI("tcp port reuse enabled");
}
+
+ if (tcp_tproxy) {
+ int level = 0, optname = 0;
+ if (rp->ai_family == AF_INET) {
+ level = IPPROTO_IP;
+ optname = IP_TRANSPARENT;
+ } else {
+ level = IPPROTO_IPV6;
+ optname = IPV6_TRANSPARENT;
+ }
+
+ if (setsockopt(listen_sock, level, optname, &opt, sizeof(opt)) != 0) {
+ ERROR("setsockopt IP_TRANSPARENT");
+ exit(EXIT_FAILURE);
+ }
+ LOGI("tcp tproxy mode enabled");
+ }
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
@@ -1094,7 +1129,7 @@ main(int argc, char **argv)
USE_TTY();
- while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6"
+ while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUTvA6"
"O:o:G:g:",
long_options, &option_index)) != -1) {
switch (c) {
@@ -1169,6 +1204,9 @@ main(int argc, char **argv)
case 'U':
mode = UDP_ONLY;
break;
+ case 'T':
+ tcp_tproxy = 1;
+ break;
case 'v':
verbose = 1;
break;
@@ -1255,6 +1293,9 @@ main(int argc, char **argv)
if (mode == TCP_ONLY) {
mode = conf->mode;
}
+ if (tcp_tproxy == 0) {
+ tcp_tproxy = conf->tcp_tproxy;
+ }
if (mtu == 0) {
mtu = conf->mtu;
}
--- a/src/utils.c
+++ b/src/utils.c
@@ -342,6 +342,10 @@ usage()
#endif
printf(
" [-U] Enable UDP relay and disable TCP relay.\n");
+#ifdef MODULE_REDIR
+ printf(
+ " [-T] Use tproxy instead of redirect (for tcp).\n");
+#endif
#ifdef MODULE_REMOTE
printf(
" [-6] Resovle hostname to IPv6 address first.\n");