From d1f1ae09184f8698224d49e4922253133135a21d Mon Sep 17 00:00:00 2001 From: ruti <> Date: Thu, 6 Feb 2025 17:44:40 +0300 Subject: [PATCH] Fix tamper after timeout/pollout --- conev.c | 7 ++- conev.h | 11 ++--- desync.c | 36 ++++++++------- desync.h | 2 +- extend.c | 138 ++++++++++++++++++++----------------------------------- extend.h | 6 +-- proxy.c | 13 +++--- 7 files changed, 90 insertions(+), 123 deletions(-) diff --git a/conev.c b/conev.c index 217d0be..a2b3455 100644 --- a/conev.c +++ b/conev.c @@ -93,7 +93,12 @@ void del_event(struct poolhd *pool, struct eval *val) epoll_ctl(pool->efd, EPOLL_CTL_DEL, val->fd, 0); #endif if (val->buff) { - buff_unlock(val); + buff_unlock(val->buff); + val->buff = 0; + } + if (val->sq_buff) { + buff_unlock(val->sq_buff); + val->sq_buff = 0; } close(val->fd); val->fd = -1; diff --git a/conev.h b/conev.h index 16c2bc1..6962efc 100644 --- a/conev.h +++ b/conev.h @@ -53,7 +53,7 @@ union sockaddr_u { struct buffer { size_t size; unsigned int offset; - size_t lock; + ssize_t lock; struct buffer *next; char data[]; }; @@ -68,7 +68,7 @@ struct eval { struct eval *tv_next, *tv_prev; struct eval *pair; - struct buffer *buff; + struct buffer *buff, *sq_buff; int flag; union sockaddr_u addr; ssize_t recv_count; @@ -121,9 +121,8 @@ struct buffer *buff_get(struct buffer *root, size_t size); void buff_destroy(struct buffer *root); -#define buff_unlock(val) \ - val->buff->lock = 0; \ - val->buff->offset = 0; \ - val->buff = 0; +#define buff_unlock(buff) \ + buff->lock = 0; \ + buff->offset = 0; #endif diff --git a/desync.c b/desync.c index 6b9e741..7bc4140 100644 --- a/desync.c +++ b/desync.c @@ -476,16 +476,16 @@ static long gen_offset(long pos, int flag, } -static ssize_t tamp(char *buffer, size_t bfsize, ssize_t n, +static void tamp(char *buffer, size_t bfsize, ssize_t *n, const struct desync_params *dp, struct proto_info *info) { - if (dp->mod_http && is_http(buffer, n)) { - LOG(LOG_S, "modify HTTP: n=%zd\n", n); - if (mod_http(buffer, n, dp->mod_http)) { + if (dp->mod_http && is_http(buffer, *n)) { + LOG(LOG_S, "modify HTTP: n=%zd\n", *n); + if (mod_http(buffer, *n, dp->mod_http)) { LOG(LOG_E, "mod http error\n"); } } - else if (dp->tlsrec_n && is_tls_chello(buffer, n)) { + else if (dp->tlsrec_n && is_tls_chello(buffer, *n)) { long lp = 0; struct part part; int i = 0, r = 0, rc = 0; @@ -497,7 +497,7 @@ static ssize_t tamp(char *buffer, size_t bfsize, ssize_t n, } long pos = rc * 5; pos += gen_offset(part.pos, - part.flag, buffer, n - pos, lp, info); + part.flag, buffer, *n - pos, lp, info); if (part.pos < 0 || part.flag) { pos -= 5; @@ -508,21 +508,20 @@ static ssize_t tamp(char *buffer, size_t bfsize, ssize_t n, break; } if (!part_tls(buffer + lp, - bfsize - lp, n - lp, pos - lp)) { - LOG(LOG_E, "tlsrec error: pos=%ld, n=%zd\n", pos, n); + bfsize - lp, *n - lp, pos - lp)) { + LOG(LOG_E, "tlsrec error: pos=%ld, n=%zd\n", pos, *n); break; } - LOG(LOG_S, "tlsrec: pos=%ld, n=%zd\n", pos, n); - n += 5; + LOG(LOG_S, "tlsrec: pos=%ld, n=%zd\n", pos, *n); + *n += 5; lp = pos + 5; } } - return n; } ssize_t desync(struct poolhd *pool, - struct eval *val, struct buffer *buff, ssize_t n) + struct eval *val, struct buffer *buff, ssize_t *np) { struct desync_params dp = params.dp[val->pair->attempt]; struct proto_info info = { 0 }; @@ -533,18 +532,21 @@ ssize_t desync(struct poolhd *pool, ssize_t offset = buff->offset; ssize_t skip = val->pair->round_sent; - if (!val->recv_count && params.debug) { - init_proto_info(buffer, n, &info); + if (!skip && params.debug) { + init_proto_info(buffer, *np, &info); if (info.host_pos) { LOG(LOG_S, "host: %.*s (%d)\n", info.host_len, buffer + info.host_pos, info.host_pos); } else { - INIT_HEX_STR(buffer, (n > 16 ? 16 : n)); - LOG(LOG_S, "bytes: %s (%zd)\n", HEX_STR, n); + INIT_HEX_STR(buffer, (*np > 16 ? 16 : *np)); + LOG(LOG_S, "bytes: %s (%zd)\n", HEX_STR, *np); } } - n = tamp(buffer, bfsize, n, &dp, &info); + if (!skip) { + tamp(buffer, bfsize, np, &dp, &info); + } + ssize_t n = *np; long lp = offset; struct part part; diff --git a/desync.h b/desync.h index f07a2f7..f6060ae 100644 --- a/desync.h +++ b/desync.h @@ -12,7 +12,7 @@ #include #endif -ssize_t desync(struct poolhd *pool, struct eval *val, struct buffer *buff, ssize_t n); +ssize_t desync(struct poolhd *pool, struct eval *val, struct buffer *buff, ssize_t *n); ssize_t desync_udp(int sfd, char *buffer, ssize_t n, const struct sockaddr *dst, int dp_c); diff --git a/extend.c b/extend.c index bacf404..8c4d147 100644 --- a/extend.c +++ b/extend.c @@ -155,14 +155,21 @@ static int reconnect(struct poolhd *pool, struct eval *val, int m) struct eval *client = val->pair; - if (create_conn(pool, client, &val->addr, &on_first_tunnel)) { + if (create_conn(pool, client, &val->addr, &on_tunnel)) { return -1; } val->pair = 0; del_event(pool, val); + client->cb = &on_tunnel; client->attempt = m; client->cache = 1; + + struct buffer *buff = buff_get(pool->root_buff, client->sq_buff->size); + buff->lock = client->sq_buff->lock; + memcpy(buff->data, client->sq_buff->data, buff->lock); + + client->buff = buff; client->buff->offset = 0; client->round_sent = 0; return 0; @@ -257,7 +264,7 @@ static int on_trigger(int type, struct poolhd *pool, struct eval *val) { int m = val->pair->attempt + 1; - struct buffer *pair_buff = val->pair->buff; + struct buffer *pair_buff = val->pair->sq_buff; bool can_reconn = ( pair_buff && pair_buff->lock && !val->recv_count && params.auto_level > AUTO_NOBUFF @@ -317,8 +324,8 @@ static int on_response(struct poolhd *pool, struct eval *val, { int m = val->pair->attempt + 1; - char *req = val->pair->buff->data; - ssize_t qn = val->pair->buff->size; + char *req = val->pair->sq_buff->data; + ssize_t qn = val->pair->sq_buff->size; for (; m < params.dp_count; m++) { struct desync_params *dp = ¶ms.dp[m]; @@ -344,9 +351,8 @@ static int on_response(struct poolhd *pool, struct eval *val, static inline void free_first_req(struct eval *client) { - client->cb = &on_tunnel; - client->pair->cb = &on_tunnel; - buff_unlock(client); + buff_unlock(client->sq_buff); + client->sq_buff = 0; } @@ -396,84 +402,8 @@ static int cancel_setup(struct eval *remote) } -static int send_saved_req(struct poolhd *pool, struct eval *client) -{ - struct buffer *buff = buff_get(pool->root_buff, params.bfsize), - *cb = client->buff; - - ssize_t n = cb->lock - cb->offset; - memcpy(buff->data, cb->data, cb->lock); - buff->offset = cb->offset; - - ssize_t sn = tcp_send_hook(pool, client->pair, buff, cb->lock); - if (sn < 0) { - return -1; - } - cb->offset += sn; - if (sn < n) { - if (mod_etype(pool, client->pair, !client->pair->tv_ms ? POLLOUT : 0) || - mod_etype(pool, client, 0)) { - uniperror("mod_etype"); - return -1; - } - } - buff->offset = 0; - return 0; -} - - -int on_first_tunnel(struct poolhd *pool, struct eval *val, int etype) -{ - struct buffer *buff = buff_get(pool->root_buff, params.bfsize); - - if (val->flag == FLAG_CONN - && ((etype & POLLOUT) || etype == POLLTIMEOUT)) { - if (mod_etype(pool, val, POLLIN) || - mod_etype(pool, val->pair, POLLIN)) { - uniperror("mod_etype"); - return -1; - } - val->pair->cb = &on_first_tunnel; - return send_saved_req(pool, val->pair); - } - ssize_t n = tcp_recv_hook(pool, val, buff); - if (n < 1) { - return n; - } - if (val->flag != FLAG_CONN) { - if (!val->buff) { - val->buff = buff; - } - val->buff->lock += n; - if (val->buff->lock >= val->buff->size) { - free_first_req(val); - } - else { - if (buff != val->buff) - memcpy(val->buff->data + val->buff->lock - n, buff->data, n); - return send_saved_req(pool, val); - } - } - else { - if (on_response(pool, val, buff->data, n) == 0) { - return 0; - } - free_first_req(val->pair); - int m = val->pair->attempt; - - if (val->pair->cache && cache_add(&val->addr, m) < 0) { - return -1; - } - } - if (tcp_send_hook(pool, val->pair, buff, n) < n) { - return -1; - } - return 0; -} - - ssize_t tcp_send_hook(struct poolhd *pool, - struct eval *remote, struct buffer *buff, ssize_t n) + struct eval *remote, struct buffer *buff, ssize_t *n) { ssize_t sn = -1; int skip = remote->flag != FLAG_CONN; @@ -482,8 +412,8 @@ ssize_t tcp_send_hook(struct poolhd *pool, if (!skip) { struct eval *client = remote->pair; - if (client->recv_count == n - && setup_conn(client, buff->data, n) < 0) { + if (client->recv_count == *n + && setup_conn(client, buff->data, *n) < 0) { return -1; } int m = client->attempt, r = client->round_count; @@ -496,7 +426,7 @@ ssize_t tcp_send_hook(struct poolhd *pool, } } if (skip) { - sn = send(remote->fd, buff->data + off, n - off, 0); + sn = send(remote->fd, buff->data + off, *n - off, 0); if (sn < 0 && get_e() == EAGAIN) { return 0; } @@ -546,6 +476,40 @@ ssize_t tcp_recv_hook(struct poolhd *pool, return -1; } } + // + if (val->flag != FLAG_CONN + && !val->pair->recv_count + && params.auto_level > AUTO_NOBUFF + && (val->sq_buff || val->recv_count == n)) + { + if (!val->sq_buff) { + buff->lock = 1; + { + struct buffer *b = buff_get(pool->root_buff, buff->size); + val->sq_buff = b; + } + buff->lock = 0; + } + val->sq_buff->lock += n; + + if ((size_t )val->sq_buff->lock >= val->sq_buff->size) { + free_first_req(val); + } + else { + memcpy(val->sq_buff->data + val->sq_buff->lock - n, buff->data, n); + } + } + else if (val->pair->sq_buff) { + if (on_response(pool, val, buff->data, n) == 0) { + return 0; + } + free_first_req(val->pair); + int m = val->pair->attempt; + + if (val->pair->cache && cache_add(&val->addr, m) < 0) { + return -1; + } + } return n; } diff --git a/extend.h b/extend.h index e940a31..ed8a0e8 100644 --- a/extend.h +++ b/extend.h @@ -11,16 +11,14 @@ int connect_hook(struct poolhd *pool, struct eval *val, const union sockaddr_u *dst, evcb_t next); ssize_t tcp_send_hook(struct poolhd *pool, - struct eval *remote, struct buffer *buff, ssize_t n); + struct eval *remote, struct buffer *buff, ssize_t *n); ssize_t tcp_recv_hook(struct poolhd *pool, struct eval *val, struct buffer *buff); ssize_t udp_hook(struct eval *val, char *buffer, ssize_t n, const union sockaddr_u *dst); - -int on_first_tunnel(struct poolhd *pool, struct eval *val, int etype); - + #ifdef __linux__ static int protect(int conn_fd, const char *path); #else diff --git a/proxy.c b/proxy.c index f83ab77..c1da781 100644 --- a/proxy.c +++ b/proxy.c @@ -662,7 +662,7 @@ int on_tunnel(struct poolhd *pool, struct eval *val, int etype) } n = val->buff->lock - val->buff->offset; - ssize_t sn = tcp_send_hook(pool, pair, val->buff, val->buff->lock); + ssize_t sn = tcp_send_hook(pool, pair, val->buff, &val->buff->lock); if (sn < 0) { uniperror("send"); return -1; @@ -671,7 +671,8 @@ int on_tunnel(struct poolhd *pool, struct eval *val, int etype) val->buff->offset += sn; return 0; } - buff_unlock(val); + buff_unlock(val->buff); + val->buff = 0; if (mod_etype(pool, val, POLLIN) || mod_etype(pool, pair, POLLIN)) { @@ -689,7 +690,7 @@ int on_tunnel(struct poolhd *pool, struct eval *val, int etype) if (n < 0) { return -1; } - ssize_t sn = tcp_send_hook(pool, pair, buff, n); + ssize_t sn = tcp_send_hook(pool, pair, buff, &n); if (sn < 0) { uniperror("send"); return -1; @@ -903,10 +904,8 @@ int on_connect(struct poolhd *pool, struct eval *val, int et) uniperror("mod_etype"); return -1; } - evcb_t t = params.auto_level <= AUTO_NOBUFF - ? &on_tunnel : &on_first_tunnel; - val->cb = t; - val->pair->cb = t; + val->cb = &on_tunnel; + val->pair->cb = &on_tunnel; } if (resp_error(val->pair->fd, error, val->pair->flag) < 0) {