UDP desync support

This commit is contained in:
ruti 2024-07-29 12:26:42 +03:00
parent 2ebd982b3d
commit 83128935b8
9 changed files with 101 additions and 14 deletions

View File

@ -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 = &params.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));
}

View File

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

View File

@ -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 = &params.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)
{

View File

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

24
main.c
View File

@ -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 <sec> Timeout waiting for response, after which trigger auto\n"
#endif
" -K, --proto[=t,h] Protocol whitelist: tls,http\n"
" -K, --proto <t,h,u> Protocol whitelist: tls,http,udp\n"
" -H, --hosts <file|:str> Hosts whitelist\n"
" -s, --split <n[+s]> Split packet at n\n"
" +s - add SNI offset\n"
@ -100,6 +103,7 @@ const char help_text[] = {
" -e, --oob-data <f|:str> Set custom OOB data, filename or :string\n"
" -M, --mod-http <h,d,r> Modify HTTP: hcsmix,dcsmix,rmspace\n"
" -r, --tlsrec <n[+s]> Make TLS record at position\n"
" -a, --udp-fake <count> 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)

View File

@ -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)
{

View File

@ -3,11 +3,12 @@
#include <stdbool.h>
#include <sys/types.h>
#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);

View File

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

View File

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