Преглед изворни кода

shadowsocksr-libev: add TPROXY support for TCP (ssr-redir)

xiaorouji пре 4 година
родитељ
комит
5c3542623c

+ 1 - 1
shadowsocksr-libev/Makefile

@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=shadowsocksr-libev
 PKG_VERSION:=2.5.6
-PKG_RELEASE:=8
+PKG_RELEASE:=9
 
 PKG_SOURCE_PROTO:=git
 PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev

+ 154 - 0
shadowsocksr-libev/patches/103-Add-TPROXY-support-for-TCP-ssr-redir.patch

@@ -0,0 +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");