From 0c6f95070c8eb2e62a26e859b1a549315c03a695 Mon Sep 17 00:00:00 2001 From: ruti <> Date: Wed, 13 Mar 2024 22:18:16 +0300 Subject: [PATCH] Add timeout --- desync.c | 18 +++++-------- main.c | 56 +++++++++++++++++--------------------- params.h | 1 + proxy.c | 79 +++++++++++++++++++++++++++++++++++++++--------------- readme.txt | 8 ++++-- 5 files changed, 97 insertions(+), 65 deletions(-) diff --git a/desync.c b/desync.c index f56875e..a654278 100644 --- a/desync.c +++ b/desync.c @@ -8,22 +8,18 @@ #include #include #include - #include #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) - #endif - + #include + #include + #ifdef MFD_CLOEXEC #include #define memfd_create(name, flags) syscall(__NR_memfd_create, name, flags); #else #define memfd_create(name, flags) fileno(tmpfile()) #endif + #endif #else #include #include @@ -79,7 +75,7 @@ static inline void delay(long ms) #define delay(ms) Sleep(ms) #endif -#ifndef _WIN32 +#ifdef __linux__ int send_fake(int sfd, char *buffer, int cnt, long pos, int fa, int ttl) { @@ -110,7 +106,7 @@ int send_fake(int sfd, char *buffer, if (setttl(sfd, ttl, fa) < 0) { break; } - if (_sendfile(sfd, ffd, 0, pos) < 0) { + if (sendfile(sfd, ffd, 0, pos) < 0) { uniperror("sendfile"); break; } @@ -267,7 +263,7 @@ int desync(int sfd, char *buffer, size_t bfsize, int s = 0; switch (part.m) { - #ifndef _WIN32 + #ifdef __linux__ case DESYNC_FAKE: s = send_fake(sfd, buffer + lp, type, pos - lp, fa, dp.ttl ? dp.ttl : 8); diff --git a/main.c b/main.c index 53064eb..ca0f877 100644 --- a/main.c +++ b/main.c @@ -19,13 +19,15 @@ #ifdef __linux__ #define FAKE_SUPPORT 1 + #define TIMEOUT_SUPPORT 1 #endif #else #include #define close(fd) closesocket(fd) + #define TIMEOUT_SUPPORT 1 #endif -#define VERSION 5 +#define VERSION 6 #define MPOOL_INC 16 @@ -46,7 +48,8 @@ struct params params = { .custom_ttl = 0, .de_known = 0, - .cache_ttl = 21600, + .timeout = 0, + .cache_ttl = 100800, .ipv6 = 1, .resolve = 1, .max_open = 512, @@ -71,6 +74,9 @@ const char help_text[] = { " -K, --desync-known Desync only HTTP and TLS with SNI\n" " -A, --auto Try desync params after this option\n" " -u, --cache-ttl Lifetime of cached desync params for IP\n" + #ifdef TIMEOUT_SUPPORT + " -T, --timeout Timeout waiting for response\n" + #endif " -s, --split Split packet at n\n" " +s - add SNI offset\n" " +h - add HTTP Host offset\n" @@ -104,6 +110,9 @@ const struct option options[] = { {"desync-known ", 0, 0, 'K'}, {"auto", 0, 0, 'A'}, {"cache-ttl", 1, 0, 'u'}, + #ifdef TIMEOUT_SUPPORT + {"timeout", 1, 0, 'T'}, + #endif {"split", 1, 0, 's'}, {"disorder", 1, 0, 'd'}, {"oob", 1, 0, 'o'}, @@ -157,38 +166,13 @@ char *ftob(char *name, ssize_t *sl) int get_addr(char *str, struct sockaddr_ina *addr) { - uint16_t port = 0; - char *s = str, *e = 0; - char *end = 0, *p = str; - - if (*str == '[') { - e = strchr(str, ']'); - if (!e) return -1; - s++; p = e + 1; - } - p = strchr(p, ':'); - if (p) { - long val = strtol(p + 1, &end, 0); - if (val <= 0 || val > 0xffff || *end) - return -1; - else - port = htons(val); - if (!e) e = p; - } - if ((e - s) < 7) { - return -1; - } - char str_ip[(e - s) + 1]; - memcpy(str_ip, s, e - s); - str_ip[e - s] = 0; - struct addrinfo hints = {0}, *res = 0; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(str_ip, 0, &hints, &res) || !res) { + if (getaddrinfo(str, 0, &hints, &res) || !res) { return -1; } if (res->ai_addr->sa_family == AF_INET6) @@ -197,9 +181,6 @@ int get_addr(char *str, struct sockaddr_ina *addr) addr->in = *(struct sockaddr_in *)res->ai_addr; freeaddrinfo(res); - if (port) { - addr->in6.sin6_port = port; - } return 0; } @@ -399,6 +380,19 @@ int main(int argc, char **argv) else params.cache_ttl = val; break; + + case 'T':; + #ifdef __linux__ + float f = strtof(optarg, &end); + val = (long)(f * 1000); + #else + val = strtol(optarg, &end, 0); + #endif + if (val <= 0 || val > UINT_MAX || *end) + invalid = 1; + else + params.timeout = val; + break; case 's': case 'd': diff --git a/params.h b/params.h index 09a36eb..e624ee5 100644 --- a/params.h +++ b/params.h @@ -41,6 +41,7 @@ struct params { int def_ttl; char custom_ttl; + unsigned int timeout; long cache_ttl; char ipv6; char resolve; diff --git a/proxy.c b/proxy.c index f795985..52d62b3 100644 --- a/proxy.c +++ b/proxy.c @@ -18,6 +18,9 @@ #include #define close(fd) closesocket(fd) + #ifndef TCP_MAXRT + #define TCP_MAXRT 5 + #endif #else #include #include @@ -92,6 +95,27 @@ static inline int nb_socket(int domain, int type) } +int set_timeout(int fd, unsigned int s) +{ + #ifdef __linux__ + if (setsockopt(fd, IPPROTO_TCP, + TCP_USER_TIMEOUT, (char *)&s, sizeof(s))) { + uniperror("setsockopt TCP_USER_TIMEOUT"); + return -1; + } + #else + #ifdef _WIN32 + if (setsockopt(fd, IPPROTO_TCP, + TCP_MAXRT, (char *)&s, sizeof(s))) { + uniperror("setsockopt TCP_MAXRT"); + return -1; + } + #endif + #endif + return 0; +} + + int resolve(char *host, int len, struct sockaddr_ina *addr) { @@ -219,6 +243,10 @@ int s4_get_addr(char *buff, size_t n, int s5_get_addr(char *buffer, ssize_t n, struct sockaddr_ina *addr) { + if (n < S_SIZE_MIN) { + LOG(LOG_E, "ss: request to small\n"); + return -1; + } struct s5_req *r = (struct s5_req *)buffer; int o = (r->atp == S_ATP_I4 ? S_SIZE_I4 : @@ -507,8 +535,6 @@ static inline int on_request(struct poolhd *pool, struct eval *val, if (n) uniperror("ss recv"); return -1; } - int e = 0, s5e = 0; - if (*buffer == S_VER5) { if (val->flag != FLAG_S5) { if (auth_socks5(val->fd, buffer, n)) { @@ -517,33 +543,33 @@ static inline int on_request(struct poolhd *pool, struct eval *val, val->flag = FLAG_S5; return 0; } - if (n < S_SIZE_MIN) { - LOG(LOG_E, "ss: request to small\n"); + int s5e = s5_get_addr(buffer, n, &dst); + if (!s5e && + create_conn(pool, val, &dst, EV_CONNECT)) { + s5e = S_ER_GEN; + } + if (s5e) { + resp_s5_error(val->fd, s5e); return -1; } - e = s5_get_addr(buffer, n, &dst); - s5e = e; } else if (*buffer == S_VER4) { val->flag = FLAG_S4; - e = s4_get_addr(buffer, n, &dst); + + int error = s4_get_addr(buffer, n, &dst); + if (!error) { + error = create_conn(pool, val, &dst, EV_CONNECT); + } + if (error) { + if (resp_error(val->fd, error, FLAG_S4) < 0) + uniperror("send"); + return -1; + } } else { LOG(LOG_E, "ss: invalid version: 0x%x (%lu)\n", *buffer, n); return -1; } - if (!e) { - e = create_conn(pool, val, &dst, EV_CONNECT); - } - if (e) { - if (s5e) { - resp_s5_error(val->fd, s5e); - } - else if (resp_error(val->fd, e, val->flag) < 0) { - uniperror("ss: send"); - } - return -1; - } int m = mode_add_get(&dst, -1); if (m >= 0) { val->attempt = m; @@ -587,8 +613,11 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val, return e; } if (e) { - if (unie(e) != ECONNRESET) { - return -1; + switch (unie(e)) { + case ECONNRESET: + case ETIMEDOUT: + break; + default: return -1; } return try_again(pool, val); } @@ -600,6 +629,10 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val, pair->buff.data = 0; pair->buff.size = 0; + if (params.timeout && + set_timeout(val->fd, 0)) { + return -1; + } int m = pair->attempt; if ((m == 0 && val->attempt < 0) @@ -651,6 +684,10 @@ int on_desync(struct poolhd *pool, struct eval *val, n = val->buff.size; memcpy(buffer, val->buff.data, n); } + if (params.timeout && + set_timeout(val->pair->fd, params.timeout)) { + return -1; + } if (desync(val->pair->fd, buffer, bfsize, n, (struct sockaddr *)&val->pair->in6, m)) { return -1; diff --git a/readme.txt b/readme.txt index 5fc6cf5..a4dff85 100644 --- a/readme.txt +++ b/readme.txt @@ -37,13 +37,17 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s -A, --auto Автоматический режим - Если сервер сразу сбросил подключение после первого запроса, + Если сервер сбросил подключение после первого запроса, то будут применены параметры обхода, следующие за данной опцией Можно указывать несколько групп параметров, раделяя их данным флагом Если соединение успешно прошло, то параметры для данного IP будут закешированны -u, --cache-ttl - Время жизни значения в кеше, указывается в секундах + Время жизни значения в кеше, по умолчанию 100800 (28 часов) + +-T, --timeout + Таймаут ожидания первого ответа от сервера в секундах + В Linux переводится в миллисекунды, поэтому можно указать дробное число -s, --split Разбить запрос по указанному смещению