|
@ -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; |
|
|
} |
|
|
} |
|
|