This commit is contained in:
ruti 2024-03-17 00:19:14 +03:00
parent 0c6f95070c
commit 6b39efdd7a
5 changed files with 201 additions and 85 deletions

126
main.c
View File

@ -75,8 +75,9 @@ const char help_text[] = {
" -A, --auto Try desync params after this option\n" " -A, --auto Try desync params after this option\n"
" -u, --cache-ttl <sec> Lifetime of cached desync params for IP\n" " -u, --cache-ttl <sec> Lifetime of cached desync params for IP\n"
#ifdef TIMEOUT_SUPPORT #ifdef TIMEOUT_SUPPORT
" -T, --timeout <sec> Timeout waiting for response\n" " -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
#endif #endif
" -P, --tr <s:e:f|:str> Auto trigger data in first response\n"
" -s, --split <n[+s]> Split packet at n\n" " -s, --split <n[+s]> Split packet at n\n"
" +s - add SNI offset\n" " +s - add SNI offset\n"
" +h - add HTTP Host offset\n" " +h - add HTTP Host offset\n"
@ -85,13 +86,13 @@ const char help_text[] = {
#ifdef FAKE_SUPPORT #ifdef FAKE_SUPPORT
" -f, --fake <n[+s]> Split and send fake packet\n" " -f, --fake <n[+s]> Split and send fake packet\n"
" -t, --ttl <num> TTL of fake packets, default 8\n" " -t, --ttl <num> TTL of fake packets, default 8\n"
" -l, --fake-tls <file>\n" " -l, --fake-tls <f|:str>\n"
" -j, --fake-http <file> Set custom fake packet\n" " -j, --fake-http <f|:str> Set custom fake packet\n"
" -n, --tls-sni <str> Change SNI in fake ClientHello\n" " -n, --tls-sni <str> Change SNI in fake ClientHello\n"
#endif #endif
" -e, --oob-data <file> Set custom OOB data\n" " -e, --oob-data <f|:str> Set custom OOB data, filename or :string\n"
" -M, --mod-http <h,d,r> Modify HTTP: hcsmix,dcsmix,rmspace\n" " -M, --mod-http <h,d,r> Modify HTTP: hcsmix,dcsmix,rmspace\n"
" -r, --tlsrec <n[+s]> Make TLS record at offset\n" " -r, --tlsrec <n[+s]> Make TLS record at position\n"
}; };
@ -113,6 +114,7 @@ const struct option options[] = {
#ifdef TIMEOUT_SUPPORT #ifdef TIMEOUT_SUPPORT
{"timeout", 1, 0, 'T'}, {"timeout", 1, 0, 'T'},
#endif #endif
{"tr", 1, 0, 'P'},
{"split", 1, 0, 's'}, {"split", 1, 0, 's'},
{"disorder", 1, 0, 'd'}, {"disorder", 1, 0, 'd'},
{"oob", 1, 0, 'o'}, {"oob", 1, 0, 'o'},
@ -132,12 +134,57 @@ const struct option options[] = {
}; };
char *ftob(char *name, ssize_t *sl) char *parse_cform(const char *str, ssize_t *size)
{ {
ssize_t len = strlen(str);
char *d = malloc(len);
if (!d) {
return 0;
}
static char esca[] = {
'r','\r','n','\n','t','\t','\\','\\',
'f','\f','b','\b','v','\v','a','\a', 0
};
ssize_t i = 0, p = 0;
for (; p < len; ++p && ++i) {
if (str[p] != '\\') {
d[i] = str[p];
continue;
}
p++;
char *e = esca;
for (; *e; e += 2) {
if (*e == str[p]) {
d[i] = *(e + 1);
break;
}
}
if (*e) {
continue;
}
int n = 0;
if (sscanf(&str[p], "x%2hhx%n", &d[i], &n) == 1
|| sscanf(&str[p], "%3hho%n", &d[i], &n) == 1) {
p += (n - 1);
continue;
}
i--; p--;
}
*size = i;
char *m = realloc(d, i);
return m ? m : d;
}
char *ftob(const char *str, ssize_t *sl)
{
if (*str == ':') {
return parse_cform(str + 1, sl);
}
char *buffer = 0; char *buffer = 0;
long size; long size;
FILE *file = fopen(name, "rb"); FILE *file = fopen(str, "rb");
if (!file) if (!file)
return 0; return 0;
do { do {
@ -164,7 +211,7 @@ char *ftob(char *name, ssize_t *sl)
} }
int get_addr(char *str, struct sockaddr_ina *addr) int get_addr(const char *str, struct sockaddr_ina *addr)
{ {
struct addrinfo hints = {0}, *res = 0; struct addrinfo hints = {0}, *res = 0;
@ -203,20 +250,6 @@ int get_default_ttl()
} }
struct part *add_part(struct part **root, int *n)
{
struct part *p = realloc(
*root, sizeof(struct part) * (*n + 1));
if (!p) {
uniperror("realloc");
return 0;
}
*root = p;
*n = *n + 1;
return &((*root)[(*n) - 1]);
}
int parse_offset(struct part *part, const char *str) int parse_offset(struct part *part, const char *str)
{ {
char *end = 0; char *end = 0;
@ -239,19 +272,17 @@ int parse_offset(struct part *part, const char *str)
} }
struct desync_params *add_dparams( void *add(void **root, int *n, size_t ss)
struct desync_params **root, int *n)
{ {
struct desync_params *p = realloc( void *p = realloc(*root, ss * (*n + 1));
*root, sizeof(struct desync_params) * (*n + 1));
if (!p) { if (!p) {
uniperror("realloc"); uniperror("realloc");
return 0; return 0;
} }
*root = p; *root = p;
p = ((*root) + ((*n) * ss));
memset(p, 0, ss);
*n = *n + 1; *n = *n + 1;
p = &((*root)[(*n) - 1]);
memset(p, 0, sizeof(*p));
return p; return p;
} }
@ -296,8 +327,8 @@ int main(int argc, char **argv)
uint16_t port = htons(1080); uint16_t port = htons(1080);
struct desync_params *dp = add_dparams( struct desync_params *dp = add((void *)&params.dp,
&params.dp, &params.dp_count); &params.dp_count, sizeof(struct desync_params));
if (!dp) { if (!dp) {
return -1; return -1;
} }
@ -367,7 +398,8 @@ int main(int argc, char **argv)
break; break;
case 'A': case 'A':
dp = add_dparams(&params.dp, &params.dp_count); dp = add((void *)&params.dp, &params.dp_count,
sizeof(struct desync_params));
if (!dp) { if (!dp) {
return -1; return -1;
} }
@ -394,13 +426,32 @@ int main(int argc, char **argv)
params.timeout = val; params.timeout = val;
break; break;
case 'P':;
struct spos *spos = add((void *)&params.spos,
&params.spos_n, sizeof(struct spos));
if (!spos) {
return -1;
}
sscanf(optarg, "%zi:%zi:%zn", &spos->start, &spos->end, &val);
if (val == 0 || !optarg[val]) {
invalid = 1;
}
else {
spos->data = ftob(&optarg[val], &spos->size);
if (!spos->data) {
uniperror("read/parse");
return -1;
}
}
break;
case 's': case 's':
case 'd': case 'd':
case 'o': case 'o':
case 'f': case 'f':
; ;
struct part *part = add_part( struct part *part = add((void *)&dp->parts,
&dp->parts, &dp->parts_n); &dp->parts_n, sizeof(struct part));
if (!part) { if (!part) {
return -1; return -1;
} }
@ -438,7 +489,7 @@ int main(int argc, char **argv)
case 'l': case 'l':
fake_tls.data = ftob(optarg, &fake_tls.size); fake_tls.data = ftob(optarg, &fake_tls.size);
if (!fake_tls.data) { if (!fake_tls.data) {
uniperror("read file"); uniperror("read/parse");
return -1; return -1;
} }
break; break;
@ -446,7 +497,7 @@ int main(int argc, char **argv)
case 'j': case 'j':
fake_http.data = ftob(optarg, &fake_http.size); fake_http.data = ftob(optarg, &fake_http.size);
if (!fake_http.data) { if (!fake_http.data) {
uniperror("read file"); uniperror("read/parse");
return -1; return -1;
} }
break; break;
@ -454,7 +505,7 @@ int main(int argc, char **argv)
case 'e': case 'e':
oob_data.data = ftob(optarg, &oob_data.size); oob_data.data = ftob(optarg, &oob_data.size);
if (!oob_data.data) { if (!oob_data.data) {
uniperror("read file"); uniperror("read/parse");
return -1; return -1;
} }
break; break;
@ -482,7 +533,8 @@ int main(int argc, char **argv)
break; break;
case 'r': case 'r':
part = add_part(&dp->tlsrec, &dp->tlsrec_n); part = add((void *)&dp->tlsrec,
&dp->tlsrec_n, sizeof(struct part));
if (!part) { if (!part) {
return -1; return -1;
} }

View File

@ -43,6 +43,8 @@ struct params {
unsigned int timeout; unsigned int timeout;
long cache_ttl; long cache_ttl;
int spos_n;
struct spos *spos;
char ipv6; char ipv6;
char resolve; char resolve;
int max_open; int max_open;
@ -61,3 +63,8 @@ struct packet {
extern struct packet fake_tls; extern struct packet fake_tls;
extern struct packet fake_http; extern struct packet fake_http;
extern struct packet oob_data; extern struct packet oob_data;
struct spos {
ssize_t start, end, size;
char *data;
};

53
proxy.c
View File

@ -447,7 +447,7 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
break; break;
if (n < 1) { if (n < 1) {
if (n) uniperror("recv"); if (n) uniperror("recv");
return get_e(); return -1;
} }
val->recv_count += n; val->recv_count += n;
@ -603,17 +603,37 @@ int try_again(struct poolhd *pool, struct eval *val)
} }
char find_bad_data(char *buffer, ssize_t n)
{
for (int i = 0; i < params.spos_n; i++) {
struct spos bad_data = params.spos[i];
if (bad_data.start >= n) {
continue;
}
ssize_t end = n;
if (bad_data.end && bad_data.end < n) {
end = bad_data.end;
}
char *found = memmem(buffer + bad_data.start,
end - bad_data.start, bad_data.data, bad_data.size);
if (found) {
return 1;
}
}
return 0;
}
int on_tunnel_check(struct poolhd *pool, struct eval *val, int on_tunnel_check(struct poolhd *pool, struct eval *val,
char *buffer, size_t bfsize, int out) char *buffer, size_t bfsize, int out)
{ {
int e = on_tunnel(pool, val, buffer, bfsize, out);
if (val->flag == FLAG_CONN) {
if (out) { if (out) {
return e; return on_tunnel(pool, val, buffer, bfsize, out);
} }
if (e) { ssize_t n = recv(val->fd, buffer, bfsize, 0);
switch (unie(e)) { if (n < 1) {
uniperror("recv");
switch (unie(get_e())) {
case ECONNRESET: case ECONNRESET:
case ETIMEDOUT: case ETIMEDOUT:
break; break;
@ -621,7 +641,19 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
} }
return try_again(pool, val); return try_again(pool, val);
} }
//
char found_bd = find_bad_data(buffer, n);
if (found_bd &&
!try_again(pool, val)) {
return 0;
}
struct eval *pair = val->pair; struct eval *pair = val->pair;
ssize_t sn = send(pair->fd, buffer, n, 0);
if (n != sn) {
uniperror("send");
return -1;
}
val->type = EV_TUNNEL; val->type = EV_TUNNEL;
pair->type = EV_TUNNEL; pair->type = EV_TUNNEL;
@ -636,7 +668,8 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
int m = pair->attempt; int m = pair->attempt;
if ((m == 0 && val->attempt < 0) if ((m == 0 && val->attempt < 0)
|| (m && m == val->attempt)) { || (m && m == val->attempt)
|| found_bd) {
return 0; return 0;
} }
if (m == 0) { if (m == 0) {
@ -647,8 +680,6 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
return mode_add_get( return mode_add_get(
(struct sockaddr_ina *)&val->in6, m); (struct sockaddr_ina *)&val->in6, m);
} }
return e;
}
int on_desync(struct poolhd *pool, struct eval *val, int on_desync(struct poolhd *pool, struct eval *val,
@ -692,7 +723,7 @@ int on_desync(struct poolhd *pool, struct eval *val,
(struct sockaddr *)&val->pair->in6, m)) { (struct sockaddr *)&val->pair->in6, m)) {
return -1; return -1;
} }
val->type = EV_PRE_TUNNEL; val->type = EV_TUNNEL;
val->pair->type = EV_PRE_TUNNEL; val->pair->type = EV_PRE_TUNNEL;
return 0; return 0;
} }

19
proxy.h
View File

@ -94,6 +94,25 @@ enum s4_rep {
#define S_SIZE_I6 22 #define S_SIZE_I6 22
#define S_SIZE_ID 7 #define S_SIZE_ID 7
#ifndef __linux__
inline char *memmem(char *a, ssize_t as, char *b, ssize_t bs)
{
for (char *p = a; ; p++) {
p = memchr(p, *b, as - (p - a));
if (!p) {
return 0;
}
if ((p + bs) > (a + as)) {
return 0;
}
if (!memcmp(p, b, bs)) {
return p;
}
}
return 0;
}
#endif
int listen_socket(struct sockaddr_ina *srv); int listen_socket(struct sockaddr_ina *srv);
int event_loop(int srvfd); int event_loop(int srvfd);
int run(struct sockaddr_ina *srv); int run(struct sockaddr_ina *srv);

View File

@ -37,10 +37,12 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
-A, --auto -A, --auto
Автоматический режим Автоматический режим
Если сервер сбросил подключение после первого запроса, Если сервер сбросил подключение, превышено время ожидания, сработал --tr,
то будут применены параметры обхода, следующие за данной опцией то будут применены параметры обхода, следующие за данной опцией
Можно указывать несколько групп параметров, раделяя их данным флагом Можно указывать несколько групп параметров, раделяя их данным флагом
Если соединение успешно прошло, то параметры для данного IP будут закешированны Если соединение успешно прошло, то параметры для данного IP будут закешированны
Параметры, которые можно вынести в отдельную группу:
split, disorder, oob, fake, ttl, mod-http, tlsrec
-u, --cache-ttl <sec> -u, --cache-ttl <sec>
Время жизни значения в кеше, по умолчанию 100800 (28 часов) Время жизни значения в кеше, по умолчанию 100800 (28 часов)
@ -48,6 +50,11 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
-T, --timeout <sec> -T, --timeout <sec>
Таймаут ожидания первого ответа от сервера в секундах Таймаут ожидания первого ответа от сервера в секундах
В Linux переводится в миллисекунды, поэтому можно указать дробное число В Linux переводится в миллисекунды, поэтому можно указать дробное число
Истечение таймаута будет обработано --auto
-P, --tr <s:e:file|:str>
Поиск строки в первом ответе от сервера, начиная с s и заканчивая e
Является триггером для --auto
-s, --split <n[+s]> -s, --split <n[+s]>
Разбить запрос по указанному смещению Разбить запрос по указанному смещению
@ -72,11 +79,11 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
TTL для поддельного пакета, по умолчанию 8 TTL для поддельного пакета, по умолчанию 8
Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI
-l, --fake-tls <file> -l, --fake-tls <file|:str>
-j, --fake-http <file> -j, --fake-http <file|:str>
Указать свои поддельные пакеты, вместо дефолтных Указать свои поддельные пакеты, вместо дефолтных
-e, --oob-data <file> -e, --oob-data <file|:str>
Данные, отсылаемые вне основного потока, по умолчанию один байт 'a' Данные, отсылаемые вне основного потока, по умолчанию один байт 'a'
! При размере более одного байта может работать нестабильно ! При размере более одного байта может работать нестабильно