0
0
mirror of https://github.com/hufrea/byedpi.git synced 2025-06-30 18:43:04 +00:00

Fix tamper after timeout/pollout

This commit is contained in:
ruti 2025-02-06 17:44:40 +03:00
parent 764136eaad
commit d1f1ae0918
7 changed files with 90 additions and 123 deletions

View File

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

11
conev.h
View File

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

View File

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

View File

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

138
extend.c
View File

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

View File

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

13
proxy.c
View File

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