mirror of
https://github.com/hufrea/byedpi.git
synced 2024-12-22 06:15:14 +00:00
replace --tr with --detect
This commit is contained in:
parent
6f82bb1eff
commit
50c350c6ae
54
main.c
54
main.c
@ -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
138
packets.c
@ -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;
|
||||
|
@ -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);
|
||||
|
13
params.h
13
params.h
@ -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
39
proxy.c
@ -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
19
proxy.h
@ -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);
|
||||
|
19
readme.txt
19
readme.txt
@ -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]>
|
||||
Разбить запрос по указанному смещению
|
||||
@ -119,12 +124,6 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
Разделить ClientHello на отдельные записи по указанному смещению
|
||||
Можно указывать несколько раз
|
||||
|
||||
-m, --mss <size>
|
||||
Установить опцию MSS для TCP соединения
|
||||
Можно использовать для того, чтобы вынудить сервер разбить свой ответ
|
||||
При низких значениях сильно сказывается на скорости
|
||||
Поддерживается только в Linux
|
||||
|
||||
-------
|
||||
Сборка:
|
||||
Для сборки понадобится:
|
||||
|
Loading…
Reference in New Issue
Block a user