Add timeout

This commit is contained in:
ruti 2024-03-13 22:18:16 +03:00
parent 191f141a08
commit 0c6f95070c
5 changed files with 97 additions and 65 deletions

View file

@ -8,22 +8,18 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/mman.h>
#ifdef __linux__
#include <sys/sendfile.h>
#define _sendfile(outfd, infd, start, len) sendfile(outfd, infd, start, len)
#else
#include <sys/uio.h>
#define _sendfile(outfd, infd, start, len) sendfile(infd, outfd, start, len, 0, 0)
#endif
#include <sys/mman.h>
#include <sys/sendfile.h>
#ifdef MFD_CLOEXEC
#include <sys/syscall.h>
#define memfd_create(name, flags) syscall(__NR_memfd_create, name, flags);
#else
#define memfd_create(name, flags) fileno(tmpfile())
#endif
#endif
#else
#include <winsock2.h>
#include <windows.h>
@ -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);

56
main.c
View file

@ -19,13 +19,15 @@
#ifdef __linux__
#define FAKE_SUPPORT 1
#define TIMEOUT_SUPPORT 1
#endif
#else
#include <ws2tcpip.h>
#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 <sec> Lifetime of cached desync params for IP\n"
#ifdef TIMEOUT_SUPPORT
" -T, --timeout <sec> Timeout waiting for response\n"
#endif
" -s, --split <n[+s]> 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':

View file

@ -41,6 +41,7 @@ struct params {
int def_ttl;
char custom_ttl;
unsigned int timeout;
long cache_ttl;
char ipv6;
char resolve;

79
proxy.c
View file

@ -18,6 +18,9 @@
#include <ws2tcpip.h>
#define close(fd) closesocket(fd)
#ifndef TCP_MAXRT
#define TCP_MAXRT 5
#endif
#else
#include <errno.h>
#include <unistd.h>
@ -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;

View file

@ -37,13 +37,17 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
-A, --auto
Автоматический режим
Если сервер сразу сбросил подключение после первого запроса,
Если сервер сбросил подключение после первого запроса,
то будут применены параметры обхода, следующие за данной опцией
Можно указывать несколько групп параметров, раделяя их данным флагом
Если соединение успешно прошло, то параметры для данного IP будут закешированны
-u, --cache-ttl <sec>
Время жизни значения в кеше, указывается в секундах
Время жизни значения в кеше, по умолчанию 100800 (28 часов)
-T, --timeout <sec>
Таймаут ожидания первого ответа от сервера в секундах
В Linux переводится в миллисекунды, поэтому можно указать дробное число
-s, --split <n[+s]>
Разбить запрос по указанному смещению