replace --tr with --detect

This commit is contained in:
ruti 2024-04-03 22:51:02 +03:00
parent 6f82bb1eff
commit 50c350c6ae
7 changed files with 193 additions and 97 deletions

54
main.c
View File

@ -22,7 +22,7 @@
#define close(fd) closesocket(fd)
#endif
#define VERSION 7
#define VERSION 8
#define MPOOL_INC 16
char oob_char[1] = "a";
@ -75,7 +75,7 @@ const char help_text[] = {
#ifdef TIMEOUT_SUPPORT
" -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
#endif
" -P, --tr <s:e:f|:str> Auto trigger data in first response\n"
" -D, --detect <r,c,s,a> Detect: redirect,cl_err,sid_inv,alert\n"
" -s, --split <n[+s]> Split packet at n\n"
" +s - add SNI offset\n"
" +h - add HTTP Host offset\n"
@ -119,7 +119,7 @@ const struct option options[] = {
#ifdef TIMEOUT_SUPPORT
{"timeout", 1, 0, 'T'},
#endif
{"tr", 1, 0, 'P'},
{"detect", 1, 0, 'D'},
{"split", 1, 0, 's'},
{"disorder", 1, 0, 'd'},
{"oob", 1, 0, 'o'},
@ -317,17 +317,6 @@ void clear_params(void)
free(s.parts);
s.parts = 0;
}
if (s.spos) {
for (int x = 0; x < s.spos_n; x++) {
struct spos p = s.spos[x];
if (p.data != 0) {
free(p.data);
p.data = 0;;
}
}
free(s.spos);
s.spos = 0;
}
}
free(params.dp);
params.dp = 0;
@ -494,23 +483,28 @@ int main(int argc, char **argv)
params.timeout = val;
break;
case 'P':;
struct spos *spos = add((void *)&dp->spos,
&dp->spos_n, sizeof(struct spos));
if (!spos) {
clear_params();
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");
invalid = 1;
case 'D':;
end = optarg;
while (end && !invalid) {
switch (*end) {
case 'r':
dp->detect |= DETECT_HTTP_LOCAT;
break;
case 'c':
dp->detect |= DETECT_HTTP_CLERR;
break;
case 's':
dp->detect |= DETECT_TLS_INVSID;
break;
case 'a':
dp->detect |= DETECT_TLS_ALERT;
break;
default:
invalid = 1;
continue;
}
end = strchr(end, ',');
if (end) end++;
}
break;

138
packets.c
View File

@ -53,6 +53,24 @@ char http_data[43] = {
};
char *strncasestr(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 (!strncasecmp(p, b, bs)) {
return p;
}
}
return 0;
}
int find_tls_ext_offset(uint16_t type, char *data, size_t size)
{
if (size < 44) {
@ -145,26 +163,18 @@ int parse_tls(char *buffer, size_t bsize, char **hs)
int parse_http(char *buffer, size_t bsize, char **hs, uint16_t *port)
{
char *host = buffer, *h_end;
size_t osz = bsize;
char *buff_end = buffer + bsize;
if (bsize < 16 || *buffer > 'T' || *buffer < 'C') {
return 0;
}
while (1) {
host = memchr(host, '\n', osz);
if (!host)
return 0;
host++;
osz = bsize - (host - buffer);
if (osz < 6)
return 0;
if (!strncasecmp(host, "Host:", 5))
break;
}
host += 5; osz -= 5;
for (; osz && isblank(*host); host++, osz--) {}
host = strncasestr(buffer, bsize, "\nHost:", 6);
host += 6;
char *l_end = memchr(host, '\n', osz);
while ((buff_end - host) > 0 && isblank(*host)) {
host++;
}
char *l_end = memchr(host, '\n', buff_end - host);
if (!l_end) {
return 0;
}
@ -200,6 +210,104 @@ int parse_http(char *buffer, size_t bsize, char **hs, uint16_t *port)
}
int get_http_code(char *b, ssize_t n)
{
if (n < 13) return 0;
if (strncmp(b, "HTTP/1.", 7)) {
return 0;
}
if (!memchr(b + 13, '\n', n)) {
return 0;
}
char *e;
long num = strtol(b + 9, &e, 10);
if (num < 100 || num > 511 || !isspace(*e)) {
return 0;
}
return (int )num;
}
int is_http_redirect(char *req, ssize_t qn, char *resp, ssize_t sn)
{
char *host = 0;
int len = parse_http(req, qn, &host, 0);
if (len <= 0 || sn < 29) {
return 0;
}
int code = get_http_code(resp, sn);
if (code > 308 || code < 300) {
return 0;
}
char *location = strncasestr(resp, sn, "\nLocation:", 10);
if (!location) {
return 0;
}
location += 11;
if ((location + 8) >= (resp + sn)) {
return 0;
}
char *l_end = memchr(location, '\n', sn - (location - resp));
if (!l_end) {
return 0;
}
for (; isspace(*(l_end - 1)); l_end--) {}
if ((l_end - location) > 7) {
if (!strncmp(location, "http://", 7)) {
location += 7;
}
else if (!strncmp(location, "https://", 8)) {
location += 8;
}
}
char *e = memchr(location, '/', l_end - location);
if (!e) e = l_end;
for (; (e - location) > len; location++) {
location = memchr(location, '.', e - location);
if (!location) {
return 1;
}
}
for (; len > (e - location); host++) {
char *p = memchr(host, '.', len);
if (!p) {
return 1;
}
len -= (host - p) + 1;
host = p;
}
return (((e - location) != len)
|| strncmp(host, location, len));
}
int neq_tls_sid(char *req, ssize_t qn, char *resp, ssize_t sn)
{
if (qn < 75 || sn < 75) {
return 0;
}
if (ANTOHS(req, 0) != 0x1603
|| ANTOHS(resp, 0) != 0x1603) {
return 0;
}
if (req[43] != resp[43]) {
return 1;
}
uint8_t sid_len = req[43];
return memcmp(req + 44, resp + 44, sid_len);
}
int is_tls_alert(char *resp, ssize_t sn) {
return (sn >= 7
&& !memcmp(resp, "\x15\x03\x01\x00\x02\x02", 6));
}
int mod_http(char *buffer, size_t bsize, int m)
{
char *host = 0, *par;

View File

@ -21,4 +21,12 @@ int parse_http(char *buffer, size_t bsize, char **hs, uint16_t *port);
int mod_http(char *buffer, size_t bsize, int m);
int get_http_code(char *b, ssize_t n);
int is_http_redirect(char *req, ssize_t qn, char *resp, ssize_t sn);
int neq_tls_sid(char *req, ssize_t qn, char *resp, ssize_t sn);
int is_tls_alert(char *resp, ssize_t sn);
int part_tls(char *buffer, size_t bsize, ssize_t n, int pos);

View File

@ -15,6 +15,11 @@
#define OFFSET_SNI 1
#define OFFSET_HOST 2
#define DETECT_HTTP_LOCAT 1
#define DETECT_HTTP_CLERR 2
#define DETECT_TLS_INVSID 4
#define DETECT_TLS_ALERT 8
enum demode {
DESYNC_NONE,
DESYNC_SPLIT,
@ -49,8 +54,7 @@ struct desync_params {
int mod_http;
int tlsrec_n;
struct part *tlsrec;
int spos_n;
struct spos *spos;
int detect;
};
struct params {
@ -84,9 +88,4 @@ extern struct packet fake_tls;
extern struct packet fake_http;
extern struct packet oob_data;
struct spos {
ssize_t start, end, size;
char *data;
};
extern char ip_option[1];

39
proxy.c
View File

@ -11,6 +11,7 @@
#include <params.h>
#include <conev.h>
#include <desync.h>
#include <packets.h>
#include <error.h>
#ifdef _WIN32
@ -600,7 +601,7 @@ int try_again(struct poolhd *pool, struct eval *val, char data)
if (!data) for (; m < params.dp_count; m++) {
struct desync_params dp = params.dp[m];
if (!dp.spos_n) break;
if (dp.detect == 0) break;
}
if (m >= params.dp_count) {
mode_add_get(
@ -621,23 +622,27 @@ int try_again(struct poolhd *pool, struct eval *val, char data)
}
int find_bad_data(char *buffer, ssize_t n, int m)
int find_bad_data(char *req, ssize_t qn,
char *resp, ssize_t sn, int m)
{
for (; m < params.dp_count; m++) {
struct desync_params dp = params.dp[m];
for (int i = 0; i < dp.spos_n; i++) {
struct spos bad_data = dp.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) {
if ((dp.detect & DETECT_HTTP_LOCAT)
&& is_http_redirect(req, qn, resp, sn)) {
return m;
}
if ((dp.detect & DETECT_TLS_INVSID)
&& neq_tls_sid(req, qn, resp, sn)) {
return m;
}
if ((dp.detect & DETECT_TLS_ALERT)
&& is_tls_alert(resp, sn)) {
return m;
}
if (dp.detect & DETECT_HTTP_CLERR) {
int code = get_http_code(resp, sn);
if (code > 400 && code < 451 && code != 429) {
return m;
}
}
@ -664,12 +669,14 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val,
return try_again(pool, val, 0);
}
//
int d = find_bad_data(buffer, n, val->pair->attempt + 1);
struct eval *pair = val->pair;
int d = find_bad_data(pair->buff.data, pair->buff.size,
buffer, n, pair->attempt + 1);
if (d) {
val->pair->attempt = d - 1;
return try_again(pool, val, 1);
}
struct eval *pair = val->pair;
ssize_t sn = send(pair->fd, buffer, n, 0);
if (n != sn) {

19
proxy.h
View File

@ -94,25 +94,6 @@ enum s4_rep {
#define S_SIZE_I6 22
#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 event_loop(int srvfd);
int run(struct sockaddr_ina *srv);

View File

@ -47,7 +47,7 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
Можно указывать несколько групп параметров, раделяя их данным флагом
Если соединение успешно прошло, то параметры для данного IP будут закешированны
Параметры, которые можно вынести в отдельную группу:
tr, split, disorder, oob, fake, ttl, ip-opt, md5sig, mod-http, tlsrec
detect, split, disorder, oob, fake, ttl, ip-opt, md5sig, mod-http, tlsrec
-u, --cache-ttl <sec>
Время жизни значения в кеше, по умолчанию 100800 (28 часов)
@ -57,9 +57,14 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
В Linux переводится в миллисекунды, поэтому можно указать дробное число
Истечение таймаута будет обработано --auto
-P, --tr <s:e:file|:str>
Поиск строки в первом ответе от сервера, начиная с s и заканчивая e
Является триггером для --auto в указнной группе
-D, --detect <r,c,s,a>
Обнаружить некорректный ответ от сервера:
redirect: HTTP Redirect с Location, домен которого не совпадает и исходящим
cl_err : HTTP ответ, код которого равен 40x, но не 429
sid_inv : session_id в TLS ServerHello и ClientHello не совпадают
alert : TLS Error Alert в ответе
Является триггером для --auto в указанной группе, пример:
--auto --detect redirect --split 1+h --auto --split 2+s
-s, --split <n[+s]>
Разбить запрос по указанному смещению
@ -118,12 +123,6 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
-r, --tlsrec <n[+s]>
Разделить ClientHello на отдельные записи по указанному смещению
Можно указывать несколько раз
-m, --mss <size>
Установить опцию MSS для TCP соединения
Можно использовать для того, чтобы вынудить сервер разбить свой ответ
При низких значениях сильно сказывается на скорости
Поддерживается только в Linux
-------
Сборка: