Auto as tunnel hooks, --repeats

This commit is contained in:
ruti 2024-10-15 01:06:38 +03:00
parent 6dca571567
commit 6ce89b63aa
6 changed files with 185 additions and 208 deletions

View File

@ -37,9 +37,7 @@ enum eid {
EV_CONNECT,
EV_IGNORE,
EV_TUNNEL,
EV_PRE_TUNNEL,
EV_UDP_TUNNEL,
EV_DESYNC
EV_UDP_TUNNEL
};
#define FLAG_S4 1
@ -53,9 +51,7 @@ char *eid_name[] = {
"EV_CONNECT",
"EV_IGNORE",
"EV_TUNNEL",
"EV_PRE_TUNNEL",
"EV_UDP_TUNNEL",
"EV_DESYNC"
"EV_UDP_TUNNEL"
};
#endif
@ -63,6 +59,7 @@ struct buffer {
ssize_t size;
int offset;
char *data;
char locked;
};
struct eval {

259
extend.c
View File

@ -153,16 +153,18 @@ int socket_mod(int fd, struct sockaddr *dst)
int reconnect(struct poolhd *pool, struct eval *val, int m)
{
assert(val->flag == FLAG_CONN);
struct eval *client = val->pair;
if (create_conn(pool, client,
(struct sockaddr_ina *)&val->in6, EV_DESYNC)) {
(struct sockaddr_ina *)&val->in6, EV_TUNNEL)) {
return -1;
}
val->pair = 0;
del_event(pool, val);
client->type = EV_IGNORE;
//client->type = EV_IGNORE;
client->attempt = m;
client->cache = 1;
client->buff.offset = 0;
@ -269,7 +271,7 @@ int on_fin(struct poolhd *pool, struct eval *val)
ssl_err = is_tls_chello(req, qn);
}
else if (val->mark && val->round_count <= 1) {
else if (val->pair->mark && val->round_count <= 1) {
ssl_err = 1;
}
if (!ssl_err) {
@ -328,156 +330,143 @@ int on_response(struct poolhd *pool, struct eval *val,
}
static inline void to_tunnel(struct eval *client)
static inline void free_first_req(struct eval *client)
{
client->pair->type = EV_TUNNEL;
client->type = EV_TUNNEL;
assert(client->buff.data);
free(client->buff.data);
client->buff.data = 0;
client->buff.size = 0;
client->buff.offset = 0;
memset(&client->buff, 0, sizeof(client->buff));
}
int on_tunnel_check(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, int out)
ssize_t on_first_send(struct eval *client, char *buffer, ssize_t bfsize)
{
assert(!out);
ssize_t n = recv(val->fd, buffer, bfsize, 0);
if (n < 1) {
if (!n) {
return on_fin(pool, val);
}
uniperror("recv");
switch (get_e()) {
case ECONNRESET:
case ECONNREFUSED:
case ETIMEDOUT:
return on_torst(pool, val);
}
return -1;
}
//
if (on_response(pool, val, buffer, n) == 0) {
return 0;
}
val->recv_count += n;
val->round_count = 1;
val->last_round = 1;
struct eval *pair = val->pair;
int m = client->attempt;
ssize_t sn = send(pair->fd, buffer, n, 0);
if (n != sn) {
uniperror("send");
return -1;
}
if (params.auto_level > 0 && params.dp_count > 1) {
val->mark = is_tls_chello(pair->buff.data, pair->buff.size);
}
to_tunnel(pair);
if (params.timeout && params.auto_level < 1 &&
set_timeout(val->fd, 0)) {
return -1;
}
int m = pair->attempt;
if (post_desync(val->fd, m)) {
return -1;
}
if (!pair->cache) {
return 0;
}
return mode_add_get((struct sockaddr_ina *)&val->in6, m);
}
int on_desync_again(struct poolhd *pool,
struct eval *val, char *buffer, size_t bfsize)
{
if (val->flag == FLAG_CONN) {
if (mod_etype(pool, val, POLLIN) ||
mod_etype(pool, val->pair, POLLIN)) {
uniperror("mod_etype");
return -1;
}
val = val->pair;
}
int m = val->attempt;
LOG((m ? LOG_S : LOG_L), "desync params index: %d\n", m);
ssize_t n = val->buff.size;
assert(n > 0 && n <= params.bfsize);
memcpy(buffer, val->buff.data, n);
if (params.timeout &&
set_timeout(val->pair->fd, params.timeout)) {
return -1;
}
ssize_t sn = desync(val->pair->fd, buffer, bfsize, n,
val->buff.offset, (struct sockaddr *)&val->pair->in6, m);
if (sn < 0) {
return -1;
}
val->buff.offset += sn;
if (sn < n) {
if (mod_etype(pool, val->pair, POLLOUT)) {
uniperror("mod_etype");
return -1;
}
val->pair->type = EV_DESYNC;
return 0;
}
val->pair->type = EV_PRE_TUNNEL;
return 0;
}
int on_desync(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, int out)
{
if (out) {
return on_desync_again(pool, val, buffer, bfsize);
}
if (val->buff.size == bfsize) {
to_tunnel(val);
return 0;
}
ssize_t n = recv(val->fd, buffer, bfsize - val->buff.size, 0);
if (n <= 0) {
if (n) uniperror("recv data");
return -1;
}
val->buff.size += n;
val->recv_count += n;
val->round_count = 1;
val->buff.data = realloc(val->buff.data, val->buff.size);
if (val->buff.data == 0) {
uniperror("realloc");
return -1;
}
memcpy(val->buff.data + val->buff.size - n, buffer, n);
int m = val->attempt;
if (!m) for (; m < params.dp_count; m++) {
struct desync_params *dp = &params.dp[m];
if (!dp->detect &&
(!dp->pf[0] || check_port(dp->pf, &val->pair->in6)) &&
(!dp->proto || check_proto_tcp(dp->proto, val)) &&
(!dp->hosts || check_host(dp->hosts, val))) {
(!dp->pf[0] || check_port(dp->pf, &client->pair->in6)) &&
(!dp->proto || check_proto_tcp(dp->proto, client)) &&
(!dp->hosts || check_host(dp->hosts, client))) {
break;
}
}
if (m >= params.dp_count) {
return -1;
}
val->attempt = m;
if (params.auto_level > 0 && params.dp_count > 1) {
client->mark = is_tls_chello(client->buff.data, client->buff.size);
}
client->attempt = m;
return on_desync_again(pool, val, buffer, bfsize);
if (params.timeout
&& set_timeout(client->pair->fd, params.timeout)) {
return -1;
}
assert(bfsize >= client->buff.size);
memcpy(buffer, client->buff.data, client->buff.size);
return client->buff.size;
}
ssize_t tcp_send_hook(struct poolhd *pool, struct eval *remote,
char *buffer, size_t bfsize, ssize_t n)
{
ssize_t sn = -1;
if (remote->flag != FLAG_CONN
|| remote->pair->round_count > params.repeats) {
sn = send(remote->fd, buffer, n, 0);
if (sn < 0 && get_e() == EAGAIN) {
return 0;
}
return sn;
}
struct eval *client = remote->pair;
int m = client->attempt;
if (client->recv_count == n) {
n = on_first_send(client, buffer, bfsize);
if (n < 0) {
return -1;
}
}
LOG((m ? LOG_S : LOG_L), "desync params index: %d\n", m);
sn = desync(remote->fd, buffer, bfsize, n,
0, (struct sockaddr *)&remote->in6, m);
return sn;
}
ssize_t tcp_recv_hook(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize)
{
ssize_t n = recv(val->fd, buffer, bfsize, 0);
if (n < 1) {
if (!n) {
if (val->flag != FLAG_CONN) {
val = val->pair;
}
return on_fin(pool, val);
}
if (get_e() == EAGAIN) {
return 0;
}
uniperror("recv");
switch (get_e()) {
case ECONNRESET:
case ECONNREFUSED:
case ETIMEDOUT:
if (val->flag == FLAG_CONN)
return on_torst(pool, val);
else
return on_fin(pool, val->pair);
}
return -1;
}
if (val->flag != FLAG_CONN && val->pair->recv_count == 0)
{
val->buff.size += n;
if (val->buff.size >= bfsize) {
free_first_req(val);
return n;
}
val->buff.locked = 1;
val->buff.data = realloc(val->buff.data, val->buff.size);
if (val->buff.data == 0) {
uniperror("realloc");
return -1;
}
memcpy(val->buff.data + val->buff.size - n, buffer, n);
}
else if (val->recv_count == 0 && val->flag == FLAG_CONN)
{
if (val->pair->buff.locked) {
if (on_response(pool, val, buffer, n) == 0) {
return 0;
}
free_first_req(val->pair);
}
if (params.timeout && params.auto_level < 1 &&
set_timeout(val->fd, 0)) {
return -1;
}
int m = val->pair->attempt;
if (post_desync(val->fd, m)) {
return -1;
}
if (val->pair->cache &&
mode_add_get((struct sockaddr_ina *)&val->in6, m) < 0) {
return -1;
}
}
return n;
}

View File

@ -10,19 +10,15 @@ int socket_mod(int fd, struct sockaddr *dst);
int connect_hook(struct poolhd *pool, struct eval *val,
struct sockaddr_ina *dst, int next);
int on_tunnel_check(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, int out);
int on_desync(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, int out);
ssize_t tcp_send_hook(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, ssize_t n);
ssize_t tcp_recv_hook(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize);
ssize_t udp_hook(struct eval *val,
char *buffer, size_t bfsize, ssize_t n, struct sockaddr_ina *dst);
int on_torst(struct poolhd *pool, struct eval *val);
int on_fin(struct poolhd *pool, struct eval *val);
#ifdef __linux__
int protect(int conn_fd, const char *path);
#else

16
main.c
View File

@ -54,8 +54,9 @@ struct params params = {
.laddr = {
.sin6_family = AF_INET
},
.repeats = 1,
.debug = 0,
.auto_level = 0
.auto_level = -1
};
@ -80,6 +81,7 @@ const char help_text[] = {
" Detect: torst,redirect,ssl_err,none\n"
" -L, --auto-mode <0|1> 1 - handle trigger after several packets\n"
" -u, --cache-ttl <sec> Lifetime of cached desync params for IP\n"
" -R, --repeats <num> Number of requests to which desync will be applied\n"
#ifdef TIMEOUT_SUPPORT
" -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
#endif
@ -134,6 +136,7 @@ const struct option options[] = {
#endif
{"auto", 1, 0, 'A'},
{"auto-mode", 1, 0, 'L'},
{"repeats", 1, 0, 'R'},
{"cache-ttl", 1, 0, 'u'},
#ifdef TIMEOUT_SUPPORT
{"timeout", 1, 0, 'T'},
@ -616,6 +619,14 @@ int main(int argc, char **argv)
params.auto_level = val;
break;
case 'R':
val = strtol(optarg, &end, 0);
if (val < 1 || val > INT_MAX || *end)
invalid = 1;
else
params.repeats = val;
break;
case 'A':
if (!(dp->hosts || dp->proto || dp->pf[0] || dp->detect)) {
all_limited = 0;
@ -648,6 +659,9 @@ int main(int argc, char **argv)
end = strchr(end, ',');
if (end) end++;
}
if (dp->detect && params.auto_level == -1) {
params.auto_level = 0;
}
break;
case 'u':

View File

@ -114,6 +114,8 @@ struct params {
struct mphdr *mempool;
char *protect_path;
int repeats;
};
extern struct params params;

91
proxy.c
View File

@ -424,7 +424,7 @@ int create_conn(struct poolhd *pool,
pair->in6 = dst->in6;
#endif
pair->flag = FLAG_CONN;
val->type = EV_IGNORE;
//val->type = EV_IGNORE;
if (params.debug) {
INIT_ADDR_STR((*dst));
@ -641,17 +641,18 @@ int on_tunnel(struct poolhd *pool, struct eval *val,
LOG(LOG_S, "pollout (fd=%d)\n", val->fd);
val = pair;
pair = val->pair;
}
if (val->buff.data) {
assert(val->buff.data);
if (etype & POLLHUP) {
return -1;
}
n = val->buff.size - val->buff.offset;
ssize_t sn = send(pair->fd,
val->buff.data + val->buff.offset, n, 0);
if (sn != n) {
if (sn < 0 && get_e() != EAGAIN) {
ssize_t sn = tcp_send_hook(pool, pair,
val->buff.data + val->buff.offset, n, n);
if (sn < n) {
if (sn < 0) {
uniperror("send");
return -1;
}
@ -659,10 +660,12 @@ int on_tunnel(struct poolhd *pool, struct eval *val,
val->buff.offset += sn;
return 0;
}
free(val->buff.data);
val->buff.data = 0;
val->buff.size = 0;
val->buff.offset = 0;
if (!val->buff.locked) {
free(val->buff.data);
val->buff.data = 0;
val->buff.size = 0;
val->buff.offset = 0;
}
if (mod_etype(pool, val, POLLIN) ||
mod_etype(pool, pair, POLLIN)) {
@ -670,27 +673,16 @@ int on_tunnel(struct poolhd *pool, struct eval *val,
return -1;
}
}
if (val->buff.data && !val->buff.locked) {
return 0;
}
do {
n = recv(val->fd, buffer, bfsize, 0);
if (n < 0 && get_e() == EAGAIN) {
n = tcp_recv_hook(pool, val, buffer, bfsize);
//if (n < 0 && get_e() == EAGAIN) {
if (n == 0) {
break;
}
if (n == 0) {
if (val->flag != FLAG_CONN)
val = val->pair;
on_fin(pool, val);
return -1;
}
if (n < 0) {
uniperror("recv");
switch (get_e()) {
case ECONNRESET:
case ETIMEDOUT:
if (val->flag == FLAG_CONN)
on_torst(pool, val);
else
on_fin(pool, val->pair);
}
return -1;
}
val->recv_count += n;
@ -700,25 +692,24 @@ int on_tunnel(struct poolhd *pool, struct eval *val,
pair->last_round = 0;
}
ssize_t sn = send(pair->fd, buffer, n, 0);
if (sn != n) {
ssize_t sn = tcp_send_hook(pool, pair, buffer, bfsize, n);
if (sn < n) {
if (sn < 0) {
if (get_e() != EAGAIN) {
uniperror("send");
return -1;
}
sn = 0;
}
LOG(LOG_S, "send: %zd != %zd (fd: %d)\n", sn, n, pair->fd);
assert(!(val->buff.size || val->buff.offset));
val->buff.size = n - sn;
if (!(val->buff.data = malloc(n - sn))) {
uniperror("malloc");
uniperror("send");
return -1;
}
memcpy(val->buff.data, buffer + sn, n - sn);
LOG(LOG_S, "send: %zd != %zd (fd: %d)\n", sn, n, pair->fd);
assert(val->buff.locked
|| !(val->buff.size || val->buff.offset));
if (!val->buff.locked) {
val->buff.size = n - sn;
if (!(val->buff.data = malloc(n - sn))) {
uniperror("malloc");
return -1;
}
memcpy(val->buff.data, buffer + sn, n - sn);
}
if (mod_etype(pool, val, 0) ||
mod_etype(pool, pair, POLLOUT)) {
uniperror("mod_etype");
@ -907,7 +898,7 @@ static inline int on_connect(struct poolhd *pool, struct eval *val, int e)
return -1;
}
val->type = EV_TUNNEL;
val->pair->type = EV_DESYNC;
val->pair->type = EV_TUNNEL;
}
if (resp_error(val->pair->fd,
error, val->pair->flag) < 0) {
@ -977,12 +968,6 @@ int event_loop(int srvfd)
close_conn(pool, val);
continue;
case EV_PRE_TUNNEL:
if (on_tunnel_check(pool, val,
buffer, bfsize, etype & POLLOUT))
close_conn(pool, val);
continue;
case EV_TUNNEL:
if (on_tunnel(pool, val, buffer, bfsize, etype))
close_conn(pool, val);
@ -998,12 +983,6 @@ int event_loop(int srvfd)
close_conn(pool, val);
continue;
case EV_DESYNC:
if (on_desync(pool, val,
buffer, bfsize, etype & POLLOUT))
close_conn(pool, val);
continue;
case EV_IGNORE:
if (etype & (POLLHUP | POLLERR | POLLRDHUP))
close_conn(pool, val);