diff --git a/desync.c b/desync.c index e6368cb..fb6232a 100644 --- a/desync.c +++ b/desync.c @@ -76,9 +76,46 @@ static inline void delay(long ms) #define delay(ms) Sleep(ms) #endif +#ifdef __linux__ +void wait_send(int sfd) +{ + for (int i = 0; params.wait_send; i++) { + struct { + uint8_t state; + uint8_t r[3]; + uint32_t rr[35]; + uint32_t notsent_bytes; + } tcpi = {}; + socklen_t ts = sizeof(tcpi); + if (getsockopt(sfd, IPPROTO_TCP, + TCP_INFO, (char *)&tcpi, &ts) < 0) { + perror("getsockopt TCP_INFO"); + break; + } + if (ts < sizeof(tcpi)) { + LOG(LOG_E, "tcpi_notsent_bytes not provided\n"); + params.wait_send = 0; + break; + } + if (tcpi.state != 1) { + LOG(LOG_E, "state: %d\n", tcpi.state); + return; + } + if (tcpi.notsent_bytes == 0) { + return; + } + LOG(LOG_S, "not sent after %d ms\n", i); + delay(1); + } + delay(params.sfdelay); +} +#else +#define wait_send(sfd) delay(params.sfdelay) +#endif + #ifdef __linux__ int send_fake(int sfd, char *buffer, - int cnt, long pos, int fa, int ttl) + int cnt, long pos, int fa, struct desync_params *opt) { struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http; size_t psz = pkt.size; @@ -104,19 +141,31 @@ int send_fake(int sfd, char *buffer, } memcpy(p, pkt.data, psz < pos ? psz : pos); - if (setttl(sfd, ttl, fa) < 0) { + if (setttl(sfd, opt->ttl ? opt->ttl : 8, fa) < 0) { + break; + } + if (opt->ip_options + && setsockopt(sfd, IPPROTO_IP, IP_OPTIONS, + opt->ip_options, opt->ip_options_len) < 0) { + perror("setsockopt IP_OPTIONS"); break; } if (sendfile(sfd, ffd, 0, pos) < 0) { uniperror("sendfile"); break; } - delay(params.sfdelay); + wait_send(sfd); memcpy(p, buffer, pos); if (setttl(sfd, params.def_ttl, fa) < 0) { break; } + if (opt->ip_options + && setsockopt(sfd, IPPROTO_IP, + IP_OPTIONS, opt->ip_options, 0) < 0) { + perror("setsockopt IP_OPTIONS"); + break; + } status = 0; } if (p) munmap(p, pos); @@ -127,7 +176,7 @@ int send_fake(int sfd, char *buffer, #ifdef _WIN32 int send_fake(int sfd, char *buffer, - int cnt, long pos, int fa, int ttl) + int cnt, long pos, int fa, struct desync_params *opt) { struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http; size_t psz = pkt.size; @@ -180,7 +229,13 @@ int send_fake(int sfd, char *buffer, uniperror("SetFilePointer"); break; } - if (setttl(sfd, ttl, fa) < 0) { + if (setttl(sfd, opt->ttl ? opt->ttl : 8, fa) < 0) { + break; + } + if (opt->ip_options + && setsockopt(sfd, IPPROTO_IP, IP_OPTIONS, + opt->ip_options, opt->ip_options_len) < 0) { + perror("setsockopt IP_OPTIONS"); break; } if (!TransmitFile(sfd, hfile, pos, pos, &ov, @@ -204,6 +259,12 @@ int send_fake(int sfd, char *buffer, if (setttl(sfd, params.def_ttl, fa) < 0) { break; } + if (opt->ip_options + && setsockopt(sfd, IPPROTO_IP, IP_OPTIONS, + opt->ip_options, 0) < 0) { + perror("setsockopt IP_OPTIONS"); + break; + } status = 0; } if (!CloseHandle(hfile)) { @@ -231,17 +292,14 @@ int send_oob(int sfd, char *buffer, return -1; } buffer[pos] = rchar; - if (size) { - delay(params.sfdelay); - } + wait_send(sfd); + for (long i = 0; i < size; i++) { if (send(sfd, data + i, 1, MSG_OOB) < 0) { uniperror("send"); return -1; } - if (size != 1) { - delay(params.sfdelay); - } + wait_send(sfd); } return 0; } @@ -267,7 +325,7 @@ int send_disorder(int sfd, } -int desync(int sfd, char *buffer, size_t bfsize, +ssize_t desync(int sfd, char *buffer, size_t bfsize, ssize_t n, ssize_t offset, struct sockaddr *dst, int dp_c) { struct desync_params dp = params.dp[dp_c]; @@ -364,7 +422,7 @@ int desync(int sfd, char *buffer, size_t bfsize, #ifdef FAKE_SUPPORT case DESYNC_FAKE: s = send_fake(sfd, - buffer + lp, type, pos - lp, fa, dp.ttl ? dp.ttl : 8); + buffer + lp, type, pos - lp, fa, &dp); break; #endif case DESYNC_DISORDER: diff --git a/desync.h b/desync.h index 0ea058b..9e480e9 100644 --- a/desync.h +++ b/desync.h @@ -1 +1 @@ -int desync(int sfd, char *buffer, size_t bfsize, ssize_t n, ssize_t offset, struct sockaddr *dst, int dp_c); +ssize_t desync(int sfd, char *buffer, size_t bfsize, ssize_t n, ssize_t offset, struct sockaddr *dst, int dp_c); diff --git a/main.c b/main.c index 30fcae7..289adeb 100644 --- a/main.c +++ b/main.c @@ -39,6 +39,7 @@ oob_data = { struct params params = { .sfdelay = 3, + .wait_send = 1, .def_ttl = 0, .custom_ttl = 0, .de_known = 0, @@ -85,6 +86,7 @@ const char help_text[] = { #ifdef FAKE_SUPPORT " -f, --fake Split and send fake packet\n" " -t, --ttl TTL of fake packets, default 8\n" + " -k, --ip-opt IP options of fake packets\n" " -l, --fake-tls \n" " -j, --fake-http Set custom fake packet\n" " -n, --tls-sni Change SNI in fake ClientHello\n" @@ -123,6 +125,7 @@ const struct option options[] = { #ifdef FAKE_SUPPORT {"fake", 1, 0, 'f'}, {"ttl", 1, 0, 't'}, + {"ip-opt", 1, 0, 'k'}, {"fake-tls", 1, 0, 'l'}, {"fake-http", 1, 0, 'j'}, {"tls-sni", 1, 0, 'n'}, @@ -132,6 +135,7 @@ const struct option options[] = { {"tlsrec", 1, 0, 'r'}, {"def-ttl", 1, 0, 'g'}, {"delay", 1, 0, 'w'}, // + {"not-wait-send", 1, 0, 'W'}, // {0} }; @@ -484,6 +488,14 @@ int main(int argc, char **argv) dp->ttl = val; break; + case 'k': + dp->ip_options = ftob(optarg, &dp->ip_options_len); + if (!dp->ip_options) { + uniperror("read/parse"); + return -1; + } + break; + case 'n': if (change_tls_sni(optarg, fake_tls.data, fake_tls.size)) { fprintf(stderr, "error chsni\n"); @@ -567,7 +579,11 @@ int main(int argc, char **argv) || params.sfdelay >= 1000 || *end) invalid = 1; break; - + + case 'W': + params.wait_send = 0; + break; + case 0: break; diff --git a/params.h b/params.h index 7276229..17f9e39 100644 --- a/params.h +++ b/params.h @@ -31,6 +31,8 @@ struct part { struct desync_params { int ttl; + char *ip_options; + ssize_t ip_options_len; int parts_n; struct part *parts; int mod_http; @@ -43,6 +45,7 @@ struct params { int dp_count; struct desync_params *dp; long sfdelay; + char wait_send; int def_ttl; char custom_ttl; diff --git a/proxy.c b/proxy.c index ccb9789..f181179 100644 --- a/proxy.c +++ b/proxy.c @@ -350,6 +350,9 @@ int create_conn(struct poolhd *pool, return -1; } int status = connect(sfd, &addr.sa, sizeof(addr)); + if (status == 0 && params.tfo) { + LOG(LOG_S, "TFO supported!\n"); + } if (status < 0 && get_e() != EINPROGRESS && get_e() != EAGAIN) { uniperror("connect"); @@ -733,7 +736,7 @@ int on_desync(struct poolhd *pool, struct eval *val, if (sn < 0) { return -1; } - if (sn != n) { + if (sn < n) { val->buff.offset = sn; if (mod_etype(pool, val->pair, POLLOUT, 1)) { uniperror("mod_etype");