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