From 83128935b85825cee2d8eb6fe0aa7b88e827eb10 Mon Sep 17 00:00:00 2001 From: ruti <> Date: Mon, 29 Jul 2024 12:26:42 +0300 Subject: [PATCH] UDP desync support --- desync.c | 36 ++++++++++++++++++++++++++++++++++++ desync.h | 2 ++ extend.c | 31 +++++++++++++++++++++++++++++-- extend.h | 3 +++ main.c | 24 ++++++++++++++++++------ packets.c | 2 ++ packets.h | 12 +++++++----- params.h | 2 ++ proxy.c | 3 ++- 9 files changed, 101 insertions(+), 14 deletions(-) diff --git a/desync.c b/desync.c index 258eac4..1b0fbb9 100644 --- a/desync.c +++ b/desync.c @@ -521,3 +521,39 @@ ssize_t desync(int sfd, char *buffer, size_t bfsize, } return n; } + + +ssize_t desync_udp(int sfd, char *buffer, size_t bfsize, + ssize_t n, struct sockaddr *dst, int dp_c) +{ + struct desync_params *dp = ¶ms.dp[dp_c]; + int fa = get_family(dst); + + if (dp->udp_fake_count != 0) { + struct packet pkt; + if (dp->fake_data.data) { + pkt = dp->fake_data; + } + else { + pkt = fake_udp; + } + + int bttl = dp->ttl ? dp->ttl : 8; + if (setttl(sfd, bttl, fa) < 0) { + return -1; + } + for (int i = 0; i < dp->udp_fake_count; i++) { + ssize_t len = sendto(sfd, pkt.data, + pkt.size, 0, dst, sizeof(struct sockaddr_in6)); + if (len < 0) { + uniperror("send"); + return -1; + } + } + if (setttl(sfd, params.def_ttl, fa) < 0) { + return -1; + } + } + return sendto(sfd, buffer, n, 0, + dst, sizeof(struct sockaddr_in6)); +} diff --git a/desync.h b/desync.h index 89989a6..db0632a 100644 --- a/desync.h +++ b/desync.h @@ -1,5 +1,7 @@ ssize_t desync(int sfd, char *buffer, size_t bfsize, ssize_t n, ssize_t offset, struct sockaddr *dst, int dp_c); +ssize_t desync_udp(int sfd, char *buffer, size_t bfsize, ssize_t n, struct sockaddr *dst, int dp_c); + struct tcpi { uint8_t state; uint8_t r[3]; diff --git a/extend.c b/extend.c index 2ab8f64..8b71b0d 100644 --- a/extend.c +++ b/extend.c @@ -146,11 +146,14 @@ bool check_host(struct mphdr *hosts, struct eval *val) bool check_proto_tcp(int proto, struct eval *val) { - if ((proto & IS_HTTP) && + if (proto & IS_TCP) { + return 1; + } + else if ((proto & IS_HTTP) && is_http(val->buff.data, val->buff.size)) { return 1; } - if ((proto & IS_HTTPS) && + else if ((proto & IS_HTTPS) && is_tls_chello(val->buff.data, val->buff.size)) { return 1; } @@ -365,6 +368,30 @@ int on_desync(struct poolhd *pool, struct eval *val, return on_desync_again(pool, val, buffer, bfsize); } + +ssize_t udp_hook(struct eval *val, + char *buffer, size_t bfsize, ssize_t n, struct sockaddr_ina *dst) +{ + if (val->recv_count) { + return send(val->fd, buffer, n, 0); + } + int m = val->attempt; + if (!m) for (; m < params.dp_count; m++) { + struct desync_params *dp = ¶ms.dp[m]; + if (!dp->detect && + (!dp->proto || (dp->proto & IS_UDP))) { + break; + } + } + if (m >= params.dp_count) { + return -1; + } + val->attempt = m; + + return desync_udp(val->fd, buffer, bfsize, n, &dst->sa, 0); +} + + #ifdef __linux__ int protect(int conn_fd, const char *path) { diff --git a/extend.h b/extend.h index 245f31b..d861966 100644 --- a/extend.h +++ b/extend.h @@ -7,6 +7,9 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val, int on_desync(struct poolhd *pool, struct eval *val, char *buffer, size_t bfsize, int out); +ssize_t udp_hook(struct eval *val, + char *buffer, size_t bfsize, ssize_t n, struct sockaddr_ina *dst); + #ifdef __linux__ int protect(int conn_fd, const char *path); #else diff --git a/main.c b/main.c index 5a0116d..487297d 100644 --- a/main.c +++ b/main.c @@ -37,6 +37,9 @@ fake_http = { }, oob_data = { sizeof(oob_char), oob_char +}, +fake_udp = { + sizeof(udp_data), udp_data }; @@ -80,7 +83,7 @@ const char help_text[] = { #ifdef TIMEOUT_SUPPORT " -T, --timeout Timeout waiting for response, after which trigger auto\n" #endif - " -K, --proto[=t,h] Protocol whitelist: tls,http\n" + " -K, --proto Protocol whitelist: tls,http,udp\n" " -H, --hosts Hosts whitelist\n" " -s, --split Split packet at n\n" " +s - add SNI offset\n" @@ -100,6 +103,7 @@ const char help_text[] = { " -e, --oob-data Set custom OOB data, filename or :string\n" " -M, --mod-http Modify HTTP: hcsmix,dcsmix,rmspace\n" " -r, --tlsrec Make TLS record at position\n" + " -a, --udp-fake UDP fake count, default 0\n" }; @@ -124,7 +128,7 @@ const struct option options[] = { #ifdef TIMEOUT_SUPPORT {"timeout", 1, 0, 'T'}, #endif - {"proto", 2, 0, 'K'}, + {"proto", 1, 0, 'K'}, {"hosts", 1, 0, 'H'}, {"split", 1, 0, 's'}, {"disorder", 1, 0, 'd'}, @@ -142,6 +146,7 @@ const struct option options[] = { {"oob-data", 1, 0, 'e'}, {"mod-http", 1, 0, 'M'}, {"tlsrec", 1, 0, 'r'}, + {"udp-fake", 1, 0, 'a'}, {"def-ttl", 1, 0, 'g'}, {"delay", 1, 0, 'w'}, // {"not-wait-send", 0, 0, 'W'}, // @@ -564,10 +569,6 @@ int main(int argc, char **argv) break; case 'K': - if (!optarg) { - dp->proto |= 0xffffffff; - break; - } end = optarg; while (end && !invalid) { switch (*end) { @@ -577,6 +578,9 @@ int main(int argc, char **argv) case 'h': dp->proto |= IS_HTTP; break; + case 'u': + dp->proto |= IS_UDP; + break; default: invalid = 1; continue; @@ -725,6 +729,14 @@ int main(int argc, char **argv) } break; + case 'a': + val = strtol(optarg, &end, 0); + if (val < 0 || val > INT_MAX || *end) + invalid = 1; + else + dp->udp_fake_count = val; + break; + case 'g': val = strtol(optarg, &end, 0); if (val <= 0 || val > 255 || *end) diff --git a/packets.c b/packets.c index 8c04977..64f9c52 100644 --- a/packets.c +++ b/packets.c @@ -53,6 +53,8 @@ char http_data[43] = { "Host: www.wikipedia.org\r\n\r\n" }; +char udp_data[64] = { 0 }; + char *strncasestr(char *a, size_t as, char *b, size_t bs) { diff --git a/packets.h b/packets.h index 46fd482..beae78b 100644 --- a/packets.h +++ b/packets.h @@ -3,11 +3,12 @@ #include #include -#define IS_UNKNOWN 0 -#define IS_HTTP 1 -#define IS_HTTPS 2 -//#define IS_QUIC 4 -//#define IS_DNS 8 +#define IS_TCP 1 +#define IS_UDP 2 +#define IS_HTTP 4 +#define IS_HTTPS 8 +//#define IS_QUIC 16 +//#define IS_DNS 32 #define MH_HMIX 1 #define MH_SPACE 2 @@ -15,6 +16,7 @@ extern char tls_data[517]; extern char http_data[43]; +extern char udp_data[64]; int change_tls_sni(const char *host, char *buffer, size_t bsize); diff --git a/params.h b/params.h index 3f62dad..ffe3c65 100644 --- a/params.h +++ b/params.h @@ -56,6 +56,7 @@ struct desync_params { ssize_t ip_options_len; char md5sig; struct packet fake_data; + int udp_fake_count; int parts_n; struct part *parts; @@ -101,5 +102,6 @@ extern struct params params; extern struct packet fake_tls; extern struct packet fake_http; extern struct packet oob_data; +extern struct packet fake_udp; extern char ip_option[1]; \ No newline at end of file diff --git a/proxy.c b/proxy.c index fbaa89a..092d8e0 100644 --- a/proxy.c +++ b/proxy.c @@ -695,7 +695,8 @@ int on_udp_tunnel(struct eval *val, char *buffer, size_t bfsize) } val->pair->in6 = addr.in6; } - ns = send(val->pair->fd, data + offs, n - offs, 0); + ns = udp_hook(val, data + offs, bfsize - offs, n - offs, + (struct sockaddr_ina *)&val->pair->in6); } else { map_fix(&addr, 0);