From ad697d9abd0c328cd0dc510d2b1b7ff7392b8860 Mon Sep 17 00:00:00 2001 From: ruti <> Date: Sun, 8 Oct 2023 13:43:34 +0200 Subject: [PATCH] Fix UDP, SO_SNDBUF/RCVBUF option, custom bind address to out connections --- main.c | 309 ++++++++++++++++++++++++++++++++++++------------------- params.h | 12 ++- proxy.c | 218 ++++++++++++++++++++++++--------------- 3 files changed, 343 insertions(+), 196 deletions(-) diff --git a/main.c b/main.c index de69a3f..f0bcaad 100644 --- a/main.c +++ b/main.c @@ -1,20 +1,26 @@ +#define _GNU_SOURCE + #include #include #include #include #include -#include -#include - -#include -#include #include #include #include +#include +#include +#include +#include + + +#define FAKE_SUPPORT 1 + #define VERSION 2 + struct packet fake_tls = { sizeof(tls_data), tls_data }, @@ -26,7 +32,6 @@ fake_udp = { }; - struct params params = { .ttl = 8, .split = 3, @@ -36,19 +41,96 @@ struct params params = { .split_host = 0, .def_ttl = 0, .mod_http = 0, + .de_known = 0, .ipv6 = 1, .resolve = 1, .udp = 1, - .de_known = 0, .max_open = 512, - .bfsize = 16384, - .send_bfsz = 65536, + .nodelay = 1, + .send_bfsz = 0, + .recv_bfsz = 0, + .baddr = { + .sin6_family = AF_INET6 + }, .debug = 0 }; +const char help_text[] = { + " -i, --ip, Listening IP, default 0.0.0.0\n" + " -p, --port Listening port, default 1080\n" + " -D, --daemon Daemonize\n" + " -f, --pidfile Write pid to file\n" + " -c, --max-conn Connection count limit, default 512\n" + " -N, --no-domain Deny domain resolving\n" + " -U, --no-udp Deny UDP associate\n" + " -I --conn-ip Connection binded IP, default ::\n" + " -b, --bfs Buffer size, default 16384\n" + //" -L, --nodelay <0 or 1> Set TCP_NODELAY option\n" + " -S, --snd-buf Set SO_SNDBUF option\n" + " -R, --rcv-buf Set SO_RCVBUF option\n" + " -x, --debug Print logs, 0, 1 or 2\n" + // desync options + " -K, --desync-known Desync only HTTP and TLS with SNI\n" + #ifdef FAKE_SUPPORT + " -m, --method Desync method: split,disorder,fake\n" + #else + " -m, --method Desync method: split,disorder\n" + #endif + " -s, --split-pos Split position, default 3\n" + " -H, --split-at-host Add Host/SNI offset to split position\n" + #ifdef FAKE_SUPPORT + " -t, --ttl TTL of fake packets, default 8\n" + " -l, --fake-tls \n" + " -o, --fake-http \n" + " -e, --fake-udp Set custom fake packet\n" + " -n, --tls-sni Change SNI in fake CH\n" + #endif + " -M, --mod-http Modify http: hcsmix,dcsmix,rmspace\n" + " -u, --desync-udp UDP desync method: fake\n" +}; + + +const struct option options[] = { + {"daemon", 0, 0, 'D'}, + {"no-domain", 0, 0, 'N'}, + {"no-ipv6", 0, 0, 'X'}, + {"no-udp", 0, 0, 'U'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {"pidfile", 1, 0, 'f'}, + {"ip", 1, 0, 'i'}, + {"port", 1, 0, 'p'}, + {"conn-ip", 1, 0, 'I'}, + {"bfs", 1, 0, 'b'}, + //{"nodelay", 1, 0, 'L'}, + {"snd-buf", 1, 0, 'S'}, + {"rcv-buf", 1, 0, 'R'}, + {"max-conn", 1, 0, 'c'}, + {"debug", 1, 0, 'x'}, + + {"desync-known ", 0, 0, 'K'}, + {"split-at-host", 0, 0, 'H'}, + {"method", 1, 0, 'm'}, + {"split-pos", 1, 0, 's'}, + {"ttl", 1, 0, 't'}, + #ifdef FAKE_SUPPORT + {"fake-tls", 1, 0, 'l'}, + {"fake-http", 1, 0, 'o'}, + {"fake-udp", 1, 0, 'e'}, + {"tls-sni", 1, 0, 'n'}, + #endif + {"mod-http", 1, 0, 'M'}, + {"desync-udp", 1, 0, 'u'}, + {"global-ttl", 1, 0, 'g'}, // + {"delay", 1, 0, 'w'}, // + + {0} +}; + + char *ftob(char *name, ssize_t *sl) { char *buffer = 0; @@ -80,7 +162,6 @@ char *ftob(char *name, ssize_t *sl) return buffer; } - void daemonize(void) { pid_t pid = fork(); @@ -103,6 +184,25 @@ void daemonize(void) dup(0); } +int get_addr(char *str, struct sockaddr_ina *addr) +{ + struct addrinfo hints = {0}, *res = 0; + + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + + if (getaddrinfo(str, 0, &hints, &res) || !res) { + return -1; + } + if (res->ai_addr->sa_family == AF_INET6) + addr->in6 = *(struct sockaddr_in6 *)res->ai_addr; + else + addr->in = *(struct sockaddr_in *)res->ai_addr; + freeaddrinfo(res); + return 0; +} + int main(int argc, char **argv) { @@ -110,80 +210,41 @@ int main(int argc, char **argv) .in = { .sin_family = AF_INET, .sin_port = htons(1080) - }}; + }}, + b = { .in6 = params.baddr }; + + int optc = sizeof(options)/sizeof(*options); + for (int i = 0, e = optc; i < e; i++) + optc += options[i].has_arg; + + char opt[optc + 1]; + opt[optc] = 0; + + for (int i = 0, o = 0; o < optc; i++, o++) { + opt[o] = options[i].val; + for (int c = options[i].has_arg; c; c--) { + o++; + opt[o] = ':'; + } + } char daemon = 0; char *pidfile = 0; - const char help_text[] = { - //"Proxy:\n" - " -i, --ip, Listening IP address\n" - " -p, --port Listening port num\n" - " -D, --daemon Daemonize\n" - " -f, --pidfile Write pid to file\n" - " -c, --max-conn Connection count limit, default 512\n" - " -N, --no-domain Deny domain resolving\n" - " -U, --no-udp Deny UDP associate\n" - " -K, --desync-known Desync only HTTP and TLS with SNI\n" - //"Desync:\n" - " -m, --method Desync method: split,disorder,fake\n" - " -s, --split-pos Split position, default 3\n" - " -H, --split-at-host Add Host/SNI offset to split position\n" - " -t, --ttl TTL of fake packets, default 8\n" - " -l, --fake-tls \n" - " -o, --fake-http \n" - " -e, --fake-udp Set custom fake packet\n" - " -n, --tls-sni Change SNI in fake CH\n" - " -M, --mod-http Modify http: hcsmix,dcsmix,rmspace\n" - " -u, --desync-udp UDP desync method: fake\n" - }; - - const struct option options[] = { - {"daemon", 0, 0, 'D'}, - {"no-domain", 0, 0, 'N'}, - {"no-ipv6", 0, 0, 'X'}, // - {"no-udp", 0, 0, 'U'}, - {"desync-known ", 0, 0, 'K'}, - {"split-at-host", 0, 0, 'H'}, - {"help", 0, 0, 'h'}, - {"version", 0, 0, 'v'}, - {"pidfile", 1, 0, 'f'}, - {"ip", 1, 0, 'i'}, - {"port", 1, 0, 'p'}, - {"bfs", 1, 0, 'b'}, // - {"snd-bfs", 1, 0, 'B'}, // - {"max-conn", 1, 0, 'c'}, - {"method", 1, 0, 'm'}, - {"split-pos", 1, 0, 's'}, - {"ttl", 1, 0, 't'}, - {"fake-tls", 1, 0, 'l'}, - {"fake-http", 1, 0, 'o'}, - {"fake-udp", 1, 0, 'e'}, - {"tls-sni", 1, 0, 'n'}, - {"mod-http", 1, 0, 'M'}, - {"desync-udp", 1, 0, 'u'}, - {"global-ttl", 1, 0, 'g'}, // - {"delay", 1, 0, 'w'}, // - {"debug", 1, 0, 'x'}, // - - {0} - }; int rez; int invalid = 0; long val = 0; char *end = 0; + uint16_t port = htons(1080); - while (!invalid && (rez = getopt_long_only(argc, argv, - "DNXUKHhvf:i:p:b:B:c:m:s:t:l:o:e:n:M:u:g:w:x:", options, 0)) != -1) { + while (!invalid && (rez = getopt_long_only( + argc, argv, opt, options, 0)) != -1) { switch (rez) { case 'D': daemon = 1; break; - case 'f': - pidfile = optarg; - break; case 'N': params.resolve = 0; break; @@ -193,41 +254,18 @@ int main(int argc, char **argv) case 'U': params.udp = 0; break; - case 'K': - params.de_known = 1; - break; case 'h': printf(help_text); return 0; case 'v': printf("%d\n", VERSION); return 0; - - case 'b': // - val = strtol(optarg, &end, 0); - if (val <= 0 || val > INT_MAX/4 || *end) - invalid = 1; - else - params.bfsize = val; + case 'f': + pidfile = optarg; break; - - case 'B': // - val = strtol(optarg, &end, 0); - if (val <= 0 || val > INT_MAX || *end) - invalid = 1; - else - params.send_bfsz = val; - break; - + case 'i': - if (strchr(optarg, ':')) - s.in.sin_family = AF_INET6; - else - s.in.sin_family = AF_INET; - - if (!inet_pton(s.in.sin_family, optarg, - (s.in.sin_family == AF_INET ? - (char *)&s.in.sin_addr : (char *)&s.in6.sin6_addr))) + if (get_addr(optarg, &s) < 0) invalid = 1; break; @@ -236,7 +274,46 @@ int main(int argc, char **argv) if (val <= 0 || val > 0xffff || *end) invalid = 1; else - s.in.sin_port = htons(val); + port = htons(val); + break; + + case 'I': + if (get_addr(optarg, &b) < 0) + invalid = 1; + else + params.baddr = b.in6; + break; + + case 'b': + val = strtol(optarg, &end, 0); + if (val <= 0 || val > INT_MAX/4 || *end) + invalid = 1; + else + params.bfsize = val; + break; + + case 'L': + val = strtol(optarg, &end, 0); + if (val < 0 || val > 1 || *end) + invalid = 1; + else + params.nodelay = val; + break; + + case 'S': + val = strtol(optarg, &end, 0); + if (val <= 0 || val > INT_MAX || *end) + invalid = 1; + else + params.send_bfsz = val; + break; + + case 'R': + val = strtol(optarg, &end, 0); + if (val <= 0 || val > INT_MAX || *end) + invalid = 1; + else + params.recv_bfsz = val; break; case 'c': @@ -247,6 +324,22 @@ int main(int argc, char **argv) params.max_open = val; break; + case 'x': // + params.debug = strtol(optarg, 0, 0); + if (params.debug < 0) + invalid = 1; + break; + + // desync options + + case 'K': + params.de_known = 1; + break; + + case 'H': + params.split_host = 1; + break; + case 'm': if (params.attack != DESYNC_NONE) { fprintf(stderr, "methods incompatible\n"); @@ -275,10 +368,6 @@ int main(int argc, char **argv) params.split = val; break; - case 'H': - params.split_host = 1; - break; - case 't': val = strtol(optarg, &end, 0); if (val <= 0 || val > 255 || *end) @@ -362,11 +451,6 @@ int main(int argc, char **argv) invalid = 1; break; - case 'x': // - params.debug = strtol(optarg, 0, 0); - if (params.debug < 0) - invalid = 1; - break; case 0: break; @@ -383,10 +467,18 @@ int main(int argc, char **argv) fprintf(stderr, "invalid value: -%c %s\n", rez, optarg); return -1; } - if (params.send_bfsz * 2 <= params.bfsize) { + s.in.sin_port = port; + b.in.sin_port = 0; + + if (b.sa.sa_family != AF_INET6) { + params.ipv6 = 0; + } + if (params.send_bfsz && + params.send_bfsz * 2 <= params.bfsize) { fprintf(stderr, "send buffer too small\n"); return -1; } + FILE *file; if (pidfile) { file = fopen(pidfile, "w"); @@ -419,5 +511,6 @@ int main(int argc, char **argv) close(fd); params.def_ttl = orig_ttl; } + return listener(s); -} \ No newline at end of file +} diff --git a/params.h b/params.h index a1838ea..fa317ad 100644 --- a/params.h +++ b/params.h @@ -1,4 +1,5 @@ #include +#include enum demode { DESYNC_NONE, @@ -10,6 +11,7 @@ enum demode { #define DESYNC_UDP_FAKE 1 struct params { + char de_known; int ttl; int split; size_t sfdelay; @@ -22,19 +24,20 @@ struct params { char ipv6; char resolve; char udp; - char de_known; int max_open; - int debug; size_t bfsize; + int nodelay; int send_bfsz; + int recv_bfsz; + struct sockaddr_in6 baddr; }; extern struct params params; struct packet { - ssize_t size; - char *data; + ssize_t size; + char *data; }; extern struct packet fake_tls; extern struct packet fake_http; @@ -45,3 +48,4 @@ extern struct packet fake_udp; #define LOG(s, str, ...) \ if (params.debug >= s) printf(str, ##__VA_ARGS__) + diff --git a/proxy.c b/proxy.c index e3d3544..1773027 100644 --- a/proxy.c +++ b/proxy.c @@ -6,6 +6,11 @@ #include #include +#include +#include +#include +#include + #include #include #include @@ -15,11 +20,7 @@ #include #include -#include -#include -#include -#include - + int NOT_EXIT = 1; static void on_cancel(int sig) { @@ -27,18 +28,18 @@ static void on_cancel(int sig) { } -static inline int ip_cmp( +static inline int ip_equ( struct sockaddr_ina *a, struct sockaddr_ina *b) { if (a->sa.sa_family == AF_INET) { return - *((uint32_t *)(&a->in.sin_addr)) != + *((uint32_t *)(&a->in.sin_addr)) == *((uint32_t *)(&b->in.sin_addr)); } return - *((uint64_t *)(&a->in6.sin6_addr)) != - *((uint64_t *)(&b->in6.sin6_addr)) || - *((uint64_t *)(&a->in6.sin6_addr) + 1) != + *((uint64_t *)(&a->in6.sin6_addr)) == + *((uint64_t *)(&b->in6.sin6_addr)) && + *((uint64_t *)(&a->in6.sin6_addr) + 1) == *((uint64_t *)(&b->in6.sin6_addr) + 1); } @@ -67,7 +68,8 @@ void map_fix(struct sockaddr_ina *addr, char f6) } -static inline int nb_socket(int domain, int type) { +static inline int nb_socket(int domain, int type) +{ #ifdef __linux__ int fd = socket(domain, type | SOCK_NONBLOCK, 0); #else @@ -88,14 +90,38 @@ static inline int nb_socket(int domain, int type) { } +int setopts(int fd) +{ + if (params.nodelay && + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, + (char *)¶ms.nodelay, sizeof(params.nodelay))) { + perror("setsockopt TCP_NODELAY"); + return -1; + } + if (params.send_bfsz && + setsockopt(fd, SOL_SOCKET, SO_SNDBUF, + (char *)¶ms.send_bfsz, sizeof(params.send_bfsz))) { + perror("setsockopt SO_SNDBUF"); + return -1; + } + if (params.recv_bfsz && + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, + (char *)¶ms.recv_bfsz, sizeof(params.recv_bfsz))) { + perror("setsockopt SO_RCVBUF"); + return -1; + } + return 0; +} + + int resolve(char *host, int len, struct sockaddr_ina *addr, int type) { struct addrinfo hints = {0}, *res = 0; hints.ai_socktype = type; - hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_ADDRCONFIG; + hints.ai_family = params.ipv6 ? AF_UNSPEC : AF_INET; char rchar = host[len]; host[len] = '\0'; @@ -141,7 +167,7 @@ int resp_error(int fd, int e, int flag, int re) struct s4_req s4r = { .cmd = e ? S4_ER : S4_OK }; - return send(fd, &s4r, sizeof(s4r), 0); + return send(fd, (char *)&s4r, sizeof(s4r), 0); } else if (flag == FLAG_S5) { uint8_t se; @@ -165,7 +191,7 @@ int resp_error(int fd, int e, int flag, int re) .ver = 0x05, .code = se, .atp = S_ATP_I4 }; - return send(fd, &s5r, sizeof(s5r), 0); + return send(fd, (char *)&s5r, sizeof(s5r), 0); } return 0; } @@ -235,7 +261,7 @@ int s_get_addr(char *buffer, ssize_t n, if (!params.resolve) { return -S_ER_ATP; } - if (r->id.len == 1) { + if (r->id.len == 1 && type == SOCK_DGRAM) { addr->in.sin_family = AF_INET; LOG(LOG_S, "domain len=1\n"); } @@ -291,34 +317,45 @@ int s_set_addr(char *buffer, ssize_t n, int create_conn(struct poolhd *pool, struct eval *val, struct sockaddr_ina *dst) { - int sfd = nb_socket(dst->sa.sa_family, SOCK_STREAM); + struct sockaddr_ina addr = *dst; + + if (params.baddr.sin6_family == AF_INET6) { + map_fix(&addr, 6); + } + int sfd = nb_socket(addr.sa.sa_family, SOCK_STREAM); if (sfd < 0) { perror("socket"); return -1; } + if (addr.sa.sa_family == AF_INET6) { + int no = 0; + if (setsockopt(sfd, IPPROTO_IPV6, + IPV6_V6ONLY, (char *)&no, sizeof(no))) { + perror("setsockopt IPV6_V6ONLY"); + close(sfd); + return -1; + } + } + if (bind(sfd, (struct sockaddr *)¶ms.baddr, + sizeof(params.baddr)) < 0) { + perror("bind"); + close(sfd); + return -1; + } #ifdef __linux__ int syn_count = 1; if (setsockopt(sfd, IPPROTO_TCP, - TCP_SYNCNT, &syn_count, sizeof(syn_count))) { + TCP_SYNCNT, (char *)&syn_count, sizeof(syn_count))) { perror("setsockopt TCP_SYNCNT"); close(sfd); return -1; } #endif - int one = 1; - if (setsockopt(sfd, IPPROTO_TCP, - TCP_NODELAY, (char *)&one, sizeof(one))) { - perror("setsockopt TCP_NODELAY"); + if (setopts(sfd) < 0) { close(sfd); return -1; } - if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, - ¶ms.send_bfsz, sizeof(params.send_bfsz)) < 0) { - close(sfd); - perror("setsockopt SO_SNDBUF"); - return -1; - } - int status = connect(sfd, &dst->sa, sizeof(*dst)); + int status = connect(sfd, &addr.sa, sizeof(addr)); if (status < 0 && errno != EINPROGRESS) { perror("connect"); close(sfd); @@ -340,22 +377,47 @@ int create_conn(struct poolhd *pool, int udp_asc(struct poolhd *pool, struct eval *val, struct sockaddr_ina *dst) { - int ufd = nb_socket(AF_INET6, SOCK_DGRAM); + struct sockaddr_ina bnda = { + .sa = {.sa_family = dst->sa.sa_family}}, dsta = {0}; + socklen_t asz = sizeof(bnda); + + int ip_not_set = ip_equ(&bnda, dst); + bnda.in6 = params.baddr; + + if (ip_not_set) { + dsta.in6 = val->in6; + dsta.in.sin_port = dst->in.sin_port; + } else { + dsta.in6 = dst->in6; + } + + if (bnda.sa.sa_family == AF_INET6) { + map_fix(&dsta, 6); + } + if (dsta.sa.sa_family == AF_INET6) { + map_fix(&bnda, 6); + } + + int ufd = nb_socket(bnda.sa.sa_family, SOCK_DGRAM); if (ufd < 0) { perror("socket"); return -1; } - struct sockaddr_ina addr = {0}; - socklen_t asz = sizeof(addr); - int ip_is_set = ip_cmp(dst, &addr); - - addr.sa.sa_family = AF_INET6; - if (bind(ufd, &addr.sa, sizeof(addr)) < 0) { + if (bnda.sa.sa_family == AF_INET6) { + int no = 0; + if (setsockopt(ufd, IPPROTO_IPV6, + IPV6_V6ONLY, (char *)&no, sizeof(no))) { + perror("setsockopt IPV6_V6ONLY"); + close(ufd); + return -1; + } + } + if (bind(ufd, &bnda.sa, sizeof(bnda)) < 0) { perror("bind"); close(ufd); return -1; } - if (getsockname(ufd, &addr.sa, &asz)) { + if (getsockname(ufd, &bnda.sa, &asz)) { perror("getsockname"); close(ufd); return -1; @@ -365,25 +427,18 @@ int udp_asc(struct poolhd *pool, close(ufd); return -1; } - upair->in6 = dst->in6; - if (!ip_is_set) { - if (dst->sa.sa_family == AF_INET) - upair->in.sin_addr = val->in.sin_addr; - else - upair->in6.sin6_addr = val->in6.sin6_addr; - } - map_fix((struct sockaddr_ina *)&upair->in6, 6); val->pair = upair; upair->pair = val; + upair->in6 = dsta.in6; struct s5_req s5r = { .ver = 0x05 }; - int offs = s_set_addr((char *)&s5r, sizeof(s5r), &addr, 0); + int offs = s_set_addr((char *)&s5r, sizeof(s5r), &bnda, 0); if (offs < 0) { return -1; } - if (send(val->fd, &s5r, offs, 0) < 0) { + if (send(val->fd, (char *)&s5r, offs, 0) < 0) { perror("send"); return -1; } @@ -471,7 +526,8 @@ static inline int on_accept(struct poolhd *pool, struct eval *val) int c = accept(val->fd, &client.sa, &len); #endif if (c < 0) { - if (errno == EAGAIN) + if (errno == EAGAIN || + errno == EINPROGRESS) break; perror("accept"); return -1; @@ -483,16 +539,7 @@ static inline int on_accept(struct poolhd *pool, struct eval *val) continue; } #endif - int one = 1; - if (setsockopt(c, IPPROTO_TCP, - TCP_NODELAY, (char *)&one, sizeof(one))) { - perror("setsockopt TCP_NODELAY"); - close(c); - continue; - } - if (setsockopt(c, SOL_SOCKET, SO_SNDBUF, - ¶ms.send_bfsz, sizeof(params.send_bfsz)) < 0) { - perror("setsockopt SO_SNDBUF"); + if (setopts(c) < 0) { close(c); continue; } @@ -506,22 +553,6 @@ static inline int on_accept(struct poolhd *pool, struct eval *val) } -static inline int on_data(struct eval *val, char *buffer, size_t bfsize) -{ - ssize_t n = recv(val->fd, buffer, bfsize, 0); - if (n <= 0) { - if (n) perror("recv data"); - return -1; - } - if (desync(val->pair->fd, buffer, - n, (struct sockaddr *)&val->pair->in6)) { - return -1; - } - val->type = EV_TUNNEL; - return 0; -} - - static inline int on_connect(struct poolhd *pool, struct eval *val, char *buffer, size_t bfsize, int e) { @@ -546,9 +577,20 @@ static inline int on_connect(struct poolhd *pool, struct eval *val, val->type = EV_TUNNEL; mod_etype(pool, val, POLLOUT, 0); val->pair->type = EV_CONNECT; - return 0; } - return on_data(val, buffer, bfsize); + else { + ssize_t n = recv(val->fd, buffer, bfsize, 0); + if (n <= 0) { + if (n) perror("recv data"); + return -1; + } + if (desync(val->pair->fd, buffer, + n, (struct sockaddr *)&val->pair->in6)) { + return -1; + } + val->type = EV_TUNNEL; + } + return 0; } @@ -618,10 +660,12 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val, int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize) { - struct sockaddr_ina addr; int skip = S_SIZE_I6, offs; do { + struct sockaddr_ina addr = {0}; + struct sockaddr_ina *dst = (struct sockaddr_ina *)&val->in6; socklen_t asz = sizeof(addr); + ssize_t n = recvfrom(val->fd, buffer + skip, bfsize - skip, 0, &addr.sa, &asz), ns; @@ -632,11 +676,11 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize) return -1; } - if (!val->in6.sin6_port) { - val->in6.sin6_port = addr.in6.sin6_port; + if (!dst->in.sin_port) { + dst->in.sin_port = addr.in.sin_port; } - if (!ip_cmp((struct sockaddr_ina *)&val->in6, &addr) && - addr.in6.sin6_port == val->in6.sin6_port) { + + if (ip_equ(dst, &addr) && dst->in.sin_port == addr.in.sin_port) { if (buffer[skip + 2]) { // frag continue; } @@ -644,8 +688,12 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize) if (offs < 0) { return -1; } - map_fix(&addr, 6); - + if (dst->in.sin_family == AF_INET6) { + map_fix(&addr, 6); + } + if (dst->in.sin_family != addr.sa.sa_family) { + return -1; + } if (val->flag == FLAG_CONN) ns = sendto(val->fd, buffer + skip + offs, n - offs, 0, &addr.sa, asz); @@ -661,6 +709,7 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize) if (offs < 0 || offs > skip) { return -1; } + memset(buffer + skip - offs, 0, 3); ns = sendto(val->fd, buffer + skip - offs, n + offs, 0, (struct sockaddr *)&val->in6, sizeof(val->in6)); } @@ -751,9 +800,10 @@ int big_loop(int srvfd) int listener(struct sockaddr_ina srv) { + #ifdef SIGPIPE if (signal(SIGPIPE, SIG_IGN)) perror("signal SIGPIPE!"); - + #endif if (signal(SIGINT, on_cancel)) perror("signal SIGINT!"); @@ -782,4 +832,4 @@ int listener(struct sockaddr_ina srv) int status = big_loop(srvfd); close(srvfd); return status; -} \ No newline at end of file +}