diff --git a/shadowsocksr-libev/patches/103-Add-TPROXY-support-for-TCP-ssr-redir.patch b/shadowsocksr-libev/patches/103-Add-TPROXY-support-for-TCP-ssr-redir.patch index cac967cb4..317d819db 100644 --- a/shadowsocksr-libev/patches/103-Add-TPROXY-support-for-TCP-ssr-redir.patch +++ b/shadowsocksr-libev/patches/103-Add-TPROXY-support-for-TCP-ssr-redir.patch @@ -1,154 +1,154 @@ ---- a/completions/bash/ss-redir -+++ b/completions/bash/ss-redir -@@ -2,7 +2,7 @@ - { - 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 @@ - 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 @@ - 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 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 @@ - 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 @@ - - 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 @@ - case 'U': - mode = UDP_ONLY; - break; -+ case 'T': -+ tcp_tproxy = 1; -+ break; - case 'v': - verbose = 1; - break; -@@ -1255,6 +1293,9 @@ - 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 @@ - #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"); +--- 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");