mirror of
https://github.com/hufrea/byedpi.git
synced 2024-12-22 14:25:44 +00:00
Add --tr
This commit is contained in:
parent
0c6f95070c
commit
6b39efdd7a
126
main.c
126
main.c
@ -75,8 +75,9 @@ const char help_text[] = {
|
||||
" -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"
|
||||
" -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"
|
||||
" -s, --split <n[+s]> Split packet at n\n"
|
||||
" +s - add SNI offset\n"
|
||||
" +h - add HTTP Host offset\n"
|
||||
@ -85,13 +86,13 @@ const char help_text[] = {
|
||||
#ifdef FAKE_SUPPORT
|
||||
" -f, --fake <n[+s]> Split and send fake packet\n"
|
||||
" -t, --ttl <num> TTL of fake packets, default 8\n"
|
||||
" -l, --fake-tls <file>\n"
|
||||
" -j, --fake-http <file> Set custom fake packet\n"
|
||||
" -l, --fake-tls <f|:str>\n"
|
||||
" -j, --fake-http <f|:str> Set custom fake packet\n"
|
||||
" -n, --tls-sni <str> Change SNI in fake ClientHello\n"
|
||||
#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"
|
||||
" -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
|
||||
{"timeout", 1, 0, 'T'},
|
||||
#endif
|
||||
{"tr", 1, 0, 'P'},
|
||||
{"split", 1, 0, 's'},
|
||||
{"disorder", 1, 0, 'd'},
|
||||
{"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;
|
||||
long size;
|
||||
|
||||
FILE *file = fopen(name, "rb");
|
||||
FILE *file = fopen(str, "rb");
|
||||
if (!file)
|
||||
return 0;
|
||||
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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
char *end = 0;
|
||||
@ -239,19 +272,17 @@ int parse_offset(struct part *part, const char *str)
|
||||
}
|
||||
|
||||
|
||||
struct desync_params *add_dparams(
|
||||
struct desync_params **root, int *n)
|
||||
void *add(void **root, int *n, size_t ss)
|
||||
{
|
||||
struct desync_params *p = realloc(
|
||||
*root, sizeof(struct desync_params) * (*n + 1));
|
||||
void *p = realloc(*root, ss * (*n + 1));
|
||||
if (!p) {
|
||||
uniperror("realloc");
|
||||
return 0;
|
||||
}
|
||||
*root = p;
|
||||
p = ((*root) + ((*n) * ss));
|
||||
memset(p, 0, ss);
|
||||
*n = *n + 1;
|
||||
p = &((*root)[(*n) - 1]);
|
||||
memset(p, 0, sizeof(*p));
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -296,8 +327,8 @@ int main(int argc, char **argv)
|
||||
|
||||
uint16_t port = htons(1080);
|
||||
|
||||
struct desync_params *dp = add_dparams(
|
||||
¶ms.dp, ¶ms.dp_count);
|
||||
struct desync_params *dp = add((void *)¶ms.dp,
|
||||
¶ms.dp_count, sizeof(struct desync_params));
|
||||
if (!dp) {
|
||||
return -1;
|
||||
}
|
||||
@ -367,7 +398,8 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
dp = add_dparams(¶ms.dp, ¶ms.dp_count);
|
||||
dp = add((void *)¶ms.dp, ¶ms.dp_count,
|
||||
sizeof(struct desync_params));
|
||||
if (!dp) {
|
||||
return -1;
|
||||
}
|
||||
@ -394,13 +426,32 @@ int main(int argc, char **argv)
|
||||
params.timeout = val;
|
||||
break;
|
||||
|
||||
case 'P':;
|
||||
struct spos *spos = add((void *)¶ms.spos,
|
||||
¶ms.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 'd':
|
||||
case 'o':
|
||||
case 'f':
|
||||
;
|
||||
struct part *part = add_part(
|
||||
&dp->parts, &dp->parts_n);
|
||||
struct part *part = add((void *)&dp->parts,
|
||||
&dp->parts_n, sizeof(struct part));
|
||||
if (!part) {
|
||||
return -1;
|
||||
}
|
||||
@ -438,7 +489,7 @@ int main(int argc, char **argv)
|
||||
case 'l':
|
||||
fake_tls.data = ftob(optarg, &fake_tls.size);
|
||||
if (!fake_tls.data) {
|
||||
uniperror("read file");
|
||||
uniperror("read/parse");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
@ -446,7 +497,7 @@ int main(int argc, char **argv)
|
||||
case 'j':
|
||||
fake_http.data = ftob(optarg, &fake_http.size);
|
||||
if (!fake_http.data) {
|
||||
uniperror("read file");
|
||||
uniperror("read/parse");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
@ -454,7 +505,7 @@ int main(int argc, char **argv)
|
||||
case 'e':
|
||||
oob_data.data = ftob(optarg, &oob_data.size);
|
||||
if (!oob_data.data) {
|
||||
uniperror("read file");
|
||||
uniperror("read/parse");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
@ -482,7 +533,8 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
part = add_part(&dp->tlsrec, &dp->tlsrec_n);
|
||||
part = add((void *)&dp->tlsrec,
|
||||
&dp->tlsrec_n, sizeof(struct part));
|
||||
if (!part) {
|
||||
return -1;
|
||||
}
|
||||
|
7
params.h
7
params.h
@ -43,6 +43,8 @@ struct params {
|
||||
|
||||
unsigned int timeout;
|
||||
long cache_ttl;
|
||||
int spos_n;
|
||||
struct spos *spos;
|
||||
char ipv6;
|
||||
char resolve;
|
||||
int max_open;
|
||||
@ -61,3 +63,8 @@ struct packet {
|
||||
extern struct packet fake_tls;
|
||||
extern struct packet fake_http;
|
||||
extern struct packet oob_data;
|
||||
|
||||
struct spos {
|
||||
ssize_t start, end, size;
|
||||
char *data;
|
||||
};
|
117
proxy.c
117
proxy.c
@ -447,7 +447,7 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
|
||||
break;
|
||||
if (n < 1) {
|
||||
if (n) uniperror("recv");
|
||||
return get_e();
|
||||
return -1;
|
||||
}
|
||||
val->recv_count += n;
|
||||
|
||||
@ -603,51 +603,82 @@ 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,
|
||||
char *buffer, size_t bfsize, int out)
|
||||
{
|
||||
int e = on_tunnel(pool, val, buffer, bfsize, out);
|
||||
|
||||
if (val->flag == FLAG_CONN) {
|
||||
if (out) {
|
||||
return e;
|
||||
}
|
||||
if (e) {
|
||||
switch (unie(e)) {
|
||||
case ECONNRESET:
|
||||
case ETIMEDOUT:
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
return try_again(pool, val);
|
||||
}
|
||||
struct eval *pair = val->pair;
|
||||
val->type = EV_TUNNEL;
|
||||
pair->type = EV_TUNNEL;
|
||||
|
||||
free(pair->buff.data);
|
||||
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)
|
||||
|| (m && m == val->attempt)) {
|
||||
return 0;
|
||||
}
|
||||
if (m == 0) {
|
||||
LOG(LOG_S, "delete ip: m=%d\n", m);
|
||||
} else {
|
||||
LOG(LOG_S, "save ip: m=%d\n", m);
|
||||
}
|
||||
return mode_add_get(
|
||||
(struct sockaddr_ina *)&val->in6, m);
|
||||
if (out) {
|
||||
return on_tunnel(pool, val, buffer, bfsize, out);
|
||||
}
|
||||
return e;
|
||||
ssize_t n = recv(val->fd, buffer, bfsize, 0);
|
||||
if (n < 1) {
|
||||
uniperror("recv");
|
||||
switch (unie(get_e())) {
|
||||
case ECONNRESET:
|
||||
case ETIMEDOUT:
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
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;
|
||||
|
||||
ssize_t sn = send(pair->fd, buffer, n, 0);
|
||||
if (n != sn) {
|
||||
uniperror("send");
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_TUNNEL;
|
||||
pair->type = EV_TUNNEL;
|
||||
|
||||
free(pair->buff.data);
|
||||
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)
|
||||
|| (m && m == val->attempt)
|
||||
|| found_bd) {
|
||||
return 0;
|
||||
}
|
||||
if (m == 0) {
|
||||
LOG(LOG_S, "delete ip: m=%d\n", m);
|
||||
} else {
|
||||
LOG(LOG_S, "save ip: m=%d\n", m);
|
||||
}
|
||||
return mode_add_get(
|
||||
(struct sockaddr_ina *)&val->in6, m);
|
||||
}
|
||||
|
||||
|
||||
@ -692,7 +723,7 @@ int on_desync(struct poolhd *pool, struct eval *val,
|
||||
(struct sockaddr *)&val->pair->in6, m)) {
|
||||
return -1;
|
||||
}
|
||||
val->type = EV_PRE_TUNNEL;
|
||||
val->type = EV_TUNNEL;
|
||||
val->pair->type = EV_PRE_TUNNEL;
|
||||
return 0;
|
||||
}
|
||||
|
19
proxy.h
19
proxy.h
@ -94,6 +94,25 @@ 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);
|
||||
|
17
readme.txt
17
readme.txt
@ -37,10 +37,12 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
|
||||
-A, --auto
|
||||
Автоматический режим
|
||||
Если сервер сбросил подключение после первого запроса,
|
||||
Если сервер сбросил подключение, превышено время ожидания, сработал --tr,
|
||||
то будут применены параметры обхода, следующие за данной опцией
|
||||
Можно указывать несколько групп параметров, раделяя их данным флагом
|
||||
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
||||
Параметры, которые можно вынести в отдельную группу:
|
||||
split, disorder, oob, fake, ttl, mod-http, tlsrec
|
||||
|
||||
-u, --cache-ttl <sec>
|
||||
Время жизни значения в кеше, по умолчанию 100800 (28 часов)
|
||||
@ -48,10 +50,15 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
-T, --timeout <sec>
|
||||
Таймаут ожидания первого ответа от сервера в секундах
|
||||
В Linux переводится в миллисекунды, поэтому можно указать дробное число
|
||||
Истечение таймаута будет обработано --auto
|
||||
|
||||
-P, --tr <s:e:file|:str>
|
||||
Поиск строки в первом ответе от сервера, начиная с s и заканчивая e
|
||||
Является триггером для --auto
|
||||
|
||||
-s, --split <n[+s]>
|
||||
Разбить запрос по указанному смещению
|
||||
После числа можно добавить флаг:
|
||||
После числа можно добавить флаг:
|
||||
+s: добавить смещение SNI
|
||||
+h: добавить смещение Host
|
||||
Можно указывать несколько раз, чтобы разбить запрос по нескольким позициям
|
||||
@ -72,11 +79,11 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
TTL для поддельного пакета, по умолчанию 8
|
||||
Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI
|
||||
|
||||
-l, --fake-tls <file>
|
||||
-j, --fake-http <file>
|
||||
-l, --fake-tls <file|:str>
|
||||
-j, --fake-http <file|:str>
|
||||
Указать свои поддельные пакеты, вместо дефолтных
|
||||
|
||||
-e, --oob-data <file>
|
||||
-e, --oob-data <file|:str>
|
||||
Данные, отсылаемые вне основного потока, по умолчанию один байт 'a'
|
||||
! При размере более одного байта может работать нестабильно
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user