From c4dc80498b7e40abc6edac6c29a8842a396b3b1c Mon Sep 17 00:00:00 2001 From: ruti <> Date: Mon, 3 Jul 2023 19:59:39 +0200 Subject: [PATCH] set ttl and EAGAIN handler --- conev.c | 16 ++++++++-- conev.h | 4 ++- desync.c | 57 +++++++++++++++++++++++----------- main.c | 3 -- params.h | 1 - proxy.c | 94 +++++++++++++++++++++----------------------------------- 6 files changed, 91 insertions(+), 84 deletions(-) diff --git a/conev.c b/conev.c index fdc05cb..3cfceb9 100644 --- a/conev.c +++ b/conev.c @@ -51,7 +51,9 @@ struct eval *add_event(struct poolhd *pool, enum eid type, val->index = pool->count; val->type = type; val->pair = 0; - val->send_count = 0; + val->tmpbuf = 0; + val->size = 0; + val->offset = 0; val->flag = 0; #ifndef NOEPOLL @@ -80,6 +82,10 @@ void del_event(struct poolhd *pool, struct eval *val) if (!val->fd) { return; } + if (val->tmpbuf) { + free(val->tmpbuf); + val->tmpbuf = 0; + } close(val->fd); val->fd = 0; pool->count--; @@ -106,7 +112,13 @@ void destroy_pool(struct poolhd *pool) { for (int x = 0; x < pool->count; x++) { struct eval *val = pool->links[x]; - if (val->fd) close(val->fd); + if (val->fd) { + close(val->fd); + } + if (val->tmpbuf) { + free(val->tmpbuf); + val->tmpbuf = 0; + } } if (pool->items) { free(pool->items); diff --git a/conev.h b/conev.h index 726c86e..adf1144 100644 --- a/conev.h +++ b/conev.h @@ -48,7 +48,9 @@ struct eval { int index; enum eid type; struct eval *pair; - size_t send_count; + char *tmpbuf; + ssize_t size; + int offset; int flag; #ifndef NOEPOLL uint32_t events; diff --git a/desync.c b/desync.c index a966791..3196a4e 100644 --- a/desync.c +++ b/desync.c @@ -10,9 +10,10 @@ #ifdef __linux__ #include +#define _sendfile(outfd, infd, start, len) sendfile(outfd, infd, start, len) #else #include -#define sendfile(outfd, infd, start, len) sendfile(infd, outfd, start, len, 0, 0) +#define _sendfile(outfd, infd, start, len) sendfile(infd, outfd, start, len, 0, 0) #endif #ifdef MFD_CLOEXEC @@ -26,7 +27,25 @@ #include -int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos) +int setttl(int fd, int ttl, int family) { + int _ttl = ttl; + if (family == AF_INET) { + if (setsockopt(fd, IPPROTO_IP, IP_TTL, + &_ttl, sizeof(_ttl)) < 0) { + perror("setsockopt IP_TTL"); + return -1; + } + } + else if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + &_ttl, sizeof(_ttl)) < 0) { + perror("setsockopt IPV6_UNICAST_HOPS"); + return -1; + } + return 0; +} + + +int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos, int fa) { struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http; size_t psz = pkt.size; @@ -51,12 +70,10 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos) } memcpy(p, pkt.data, psz < pos ? psz : pos); - if (setsockopt(sfd, IPPROTO_IP, IP_TTL, - ¶ms.ttl, sizeof(params.ttl)) < 0) { - perror("setsockopt IP_TTL"); + if (setttl(sfd, params.ttl, fa) < 0) { break; } - if (sendfile(sfd, ffd, 0, pos) < 0) { + if (_sendfile(sfd, ffd, 0, pos) < 0) { perror("sendfile"); break; } @@ -66,9 +83,7 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos) nanosleep(&delay, 0); memcpy(p, buffer, pos); - if (setsockopt(sfd, IPPROTO_IP, IP_TTL, - ¶ms.def_ttl, sizeof(int)) < 0) { - perror("setsockopt IP_TTL"); + if (setttl(sfd, params.def_ttl, fa) < 0) { break; } if (send(sfd, buffer + pos, n - pos, 0) < 0) { @@ -83,21 +98,17 @@ int fake_attack(int sfd, char *buffer, ssize_t n, int cnt, int pos) } -int disorder_attack(int sfd, char *buffer, ssize_t n, int pos) +int disorder_attack(int sfd, char *buffer, ssize_t n, int pos, int fa) { int bttl = 1; - if (setsockopt(sfd, IPPROTO_IP, IP_TTL, - (char *)&bttl, sizeof(bttl)) < 0) { - perror("setsockopt IP_TTL"); + if (setttl(sfd, bttl, fa) < 0) { return -1; } if (send(sfd, buffer, pos, 0) < 0) { perror("send"); return -1; } - if (setsockopt(sfd, IPPROTO_IP, IP_TTL, - (char *)¶ms.def_ttl, sizeof(int)) < 0) { - perror("setsockopt IP_TTL"); + if (setttl(sfd, params.def_ttl, fa) < 0) { return -1; } if (send(sfd, buffer + pos, n - pos, 0) < 0) { @@ -114,6 +125,15 @@ int desync(int sfd, char *buffer, ssize_t n) char *host = 0; int len = 0, type = 0; + struct sockaddr sa; + socklen_t alen = sizeof(sa); + + if (getsockname(sfd, &sa, &alen)) { + perror("getsockname"); + return -1; + } + int fa = sa.sa_family; + if ((len = parse_tls(buffer, n, &host))) { type = IS_HTTPS; } @@ -146,10 +166,11 @@ int desync(int sfd, char *buffer, ssize_t n) } else switch (params.attack) { case DESYNC_FAKE: - return fake_attack(sfd, buffer, n, type, pos); + return fake_attack(sfd, buffer, n, type, pos, fa); case DESYNC_DISORDER: - return disorder_attack(sfd, buffer, n, pos); + printf("disorder attack\n"); + return disorder_attack(sfd, buffer, n, pos, fa); case DESYNC_SPLIT: default: diff --git a/main.c b/main.c index 0c941d7..3bd567f 100644 --- a/main.c +++ b/main.c @@ -40,7 +40,6 @@ struct params params = { .bfsize = 16384, .send_bfsz = 65536, - .nack_max = 65536 * 2 - 16384, .debug = 0 }; @@ -369,8 +368,6 @@ int main(int argc, char **argv) if (params.send_bfsz * 2 <= params.bfsize) { fprintf(stderr, "send buffer too small\n"); return -1; - } else { - params.nack_max = val * 2 - params.bfsize; } FILE *file; if (pidfile) { diff --git a/params.h b/params.h index 6f86985..3130d33 100644 --- a/params.h +++ b/params.h @@ -30,7 +30,6 @@ struct params { int debug; size_t bfsize; - size_t nack_max; int send_bfsz; }; diff --git a/proxy.c b/proxy.c index 486e1c0..91a3962 100644 --- a/proxy.c +++ b/proxy.c @@ -283,24 +283,6 @@ int handle_http(int fd, char *buffer, } -int nsendc(int fd, int *wn) -{ - #ifdef SO_NWRITE - socklen_t len = sizeof(*wn); - if (getsockopt(fd, SOL_SOCKET, SO_NWRITE, wn, &len) < 0) { - perror("getsockopt SO_NWRITE"); - return -1; - } - #else - if (ioctl(fd, TIOCOUTQ, wn) < 0 ) { - perror("ioctl"); - return -1; - } - #endif - return 0; -} - - static inline int create_conn(struct poolhd *pool, struct eval *val, enum eid nxt, struct sockaddr_ina *dst) { @@ -519,12 +501,10 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val, char *buffer, size_t bfsize, int out) { ssize_t n = 0; - int peek = 0; + char *rb = buffer; struct eval *pair = val->pair; - if (val->flag & FLAG_NOSEND && out) { - val->flag &= ~FLAG_NOSEND; - + if (pair->tmpbuf && out) { mod_etype(pool, val, POLLOUT, 0); mod_etype(pool, val->pair, POLLIN, 1); @@ -532,48 +512,45 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val, val = val->pair; } do { - if (pair->send_count >= params.nack_max) { - int wn = 0; - if (nsendc(pair->fd, &wn)) { + if (val->tmpbuf) { + n = val->size - val->offset; + rb = val->tmpbuf + val->offset; + } else { + n = recv(val->fd, buffer, bfsize, 0); + if (n < 0 && errno == EAGAIN) + break; + if (n < 1) { + if (n) perror("recv server"); return -1; } - pair->send_count = wn; - if (wn) { - LOG(LOG_S, "not ack: %d (fd: %d)\n", wn, pair->fd); - } - if (wn >= params.nack_max) { - peek = MSG_PEEK; - } } - n = recv(val->fd, buffer, bfsize, peek); - - if (n < 0 && errno == EAGAIN) - break; - if (n < 1) { - if (n) perror("recv server"); - return -1; - } - if (send(pair->fd, buffer, n, 0) < 0) { - if (errno == EAGAIN && peek) { - LOG(LOG_S, "EAGAIN, set POLLOUT (fd: %d)\n", pair->fd); - - mod_etype(pool, val, POLLIN, 0); - mod_etype(pool, pair, POLLOUT, 1); - - pair->flag |= FLAG_NOSEND; + ssize_t sn = send(pair->fd, rb, n, 0); + if (sn != n) { + if (sn < 0 && errno != EAGAIN) { + perror("send"); + return -1; + } + LOG(LOG_S, "EAGAIN, set POLLOUT (fd: %d)\n", pair->fd); + mod_etype(pool, val, POLLIN, 0); + mod_etype(pool, pair, POLLOUT, 1); + + if (val->tmpbuf) { + LOG(LOG_S, "EAGAIN, AGAIN ! (fd: %d)\n", pair->fd); + if (sn > 0) + val->offset += sn; break; } - perror("send"); - return -1; + val->size = sn > 0 ? n - sn : n; + val->tmpbuf = malloc(val->size); + memcpy(val->tmpbuf, buffer + (sn > 0 ? sn : 0), val->size); + break; } - if (peek) { - if (recv(val->fd, buffer, n, 0) != n) { - perror("recv"); - return -1; - } + else if (val->tmpbuf) { + free(val->tmpbuf); + val->tmpbuf = 0; + rb = buffer; + continue; } - pair->send_count += n; - } while (n == bfsize); return 0; } @@ -624,8 +601,7 @@ int big_loop(int srvfd) continue; case EV_TUNNEL: - if ((etype & POLLHUP) || - on_tunnel(pool, val, buffer, bfsize, etype & POLLOUT)) + if (on_tunnel(pool, val, buffer, bfsize, etype & POLLOUT)) del_event(pool, val); continue;