Browse Source

add `tcp_tproxy` option, use tproxy instead of redirect (tcp)

pull/2736/head
zfl9 4 years ago
parent
commit
78784507f1
No known key found for this signature in database GPG Key ID: C6A9D94D899807DB
4 changed files with 54 additions and 6 deletions
  1. 5
      src/jconf.c
  2. 1
      src/jconf.h
  3. 50
      src/redir.c
  4. 4
      src/utils.c

5
src/jconf.c

@ -338,6 +338,11 @@ read_jconf(const char *file)
value, json_boolean, value, json_boolean,
"invalid config file: option 'no_delay' must be a boolean"); "invalid config file: option 'no_delay' must be a boolean");
conf.no_delay = value->u.boolean; conf.no_delay = 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 if (strcmp(name, "workdir") == 0) { } else if (strcmp(name, "workdir") == 0) {
conf.workdir = to_string(value); conf.workdir = to_string(value);
} else if (strcmp(name, "acl") == 0) { } else if (strcmp(name, "acl") == 0) {

1
src/jconf.h

@ -82,6 +82,7 @@ typedef struct {
int mptcp; int mptcp;
int ipv6_first; int ipv6_first;
int no_delay; int no_delay;
int tcp_tproxy;
char *workdir; char *workdir;
char *acl; char *acl;
char *manager_address; char *manager_address;

50
src/redir.c

@ -65,6 +65,14 @@
#define IP6T_SO_ORIGINAL_DST 80 #define IP6T_SO_ORIGINAL_DST 80
#endif #endif
#ifndef IP_TRANSPARENT
#define IP_TRANSPARENT 19
#endif
#ifndef IPV6_TRANSPARENT
#define IPV6_TRANSPARENT 75
#endif
static void accept_cb(EV_P_ ev_io *w, int revents); static void accept_cb(EV_P_ ev_io *w, int revents);
static void server_recv_cb(EV_P_ ev_io *w, int revents); static void server_recv_cb(EV_P_ ev_io *w, int revents);
static void server_send_cb(EV_P_ ev_io *w, int revents); static void server_send_cb(EV_P_ ev_io *w, int revents);
@ -97,19 +105,26 @@ static struct ev_signal sigint_watcher;
static struct ev_signal sigterm_watcher; static struct ev_signal sigterm_watcher;
static struct ev_signal sigchld_watcher; static struct ev_signal sigchld_watcher;
static int tcp_tproxy = 0; /* use tproxy instead of redirect (for tcp) */
static int static int
getdestaddr(int fd, struct sockaddr_storage *destaddr) getdestaddr(int fd, struct sockaddr_storage *destaddr)
{ {
socklen_t socklen = sizeof(*destaddr); socklen_t socklen = sizeof(*destaddr);
int error = 0; 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;
}
return 0; return 0;
} }
@ -165,6 +180,23 @@ create_and_bind(const char *addr, const char *port)
} }
} }
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); s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) { if (s == 0) {
/* We managed to bind successfully! */ /* We managed to bind successfully! */
@ -882,7 +914,7 @@ main(int argc, char **argv)
USE_TTY(); USE_TTY();
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6A",
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUTv6A",
long_options, NULL)) != -1) { long_options, NULL)) != -1) {
switch (c) { switch (c) {
case GETOPT_VAL_FAST_OPEN: case GETOPT_VAL_FAST_OPEN:
@ -957,6 +989,9 @@ main(int argc, char **argv)
case 'U': case 'U':
mode = UDP_ONLY; mode = UDP_ONLY;
break; break;
case 'T':
tcp_tproxy = 1;
break;
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
@ -1029,6 +1064,9 @@ main(int argc, char **argv)
if (mode == TCP_ONLY) { if (mode == TCP_ONLY) {
mode = conf->mode; mode = conf->mode;
} }
if (tcp_tproxy == 0) {
tcp_tproxy = conf->tcp_tproxy;
}
if (mtu == 0) { if (mtu == 0) {
mtu = conf->mtu; mtu = conf->mtu;
} }

4
src/utils.c

@ -360,6 +360,10 @@ usage()
#endif #endif
printf( printf(
" [-U] Enable UDP relay and disable TCP relay.\n"); " [-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 #ifdef MODULE_REMOTE
printf( printf(
" [-6] Resovle hostname to IPv6 address first.\n"); " [-6] Resovle hostname to IPv6 address first.\n");

Loading…
Cancel
Save