mirror of
https://github.com/hufrea/byedpi.git
synced 2024-12-22 06:15:14 +00:00
wait_send after split, oob, etc; handle different send ret
This commit is contained in:
parent
56a9043dd6
commit
b0d624136e
148
desync.c
148
desync.c
@ -12,6 +12,7 @@
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <desync.h>
|
||||
|
||||
#ifdef MFD_CLOEXEC
|
||||
#include <sys/syscall.h>
|
||||
@ -26,6 +27,7 @@
|
||||
#include <ws2tcpip.h>
|
||||
#include <mswsock.h>
|
||||
#endif
|
||||
#define STR_MODE
|
||||
|
||||
#include <params.h>
|
||||
#include <packets.h>
|
||||
@ -80,27 +82,23 @@ static inline void delay(long ms)
|
||||
void wait_send(int sfd)
|
||||
{
|
||||
for (int i = 0; params.wait_send; i++) {
|
||||
struct {
|
||||
uint8_t state;
|
||||
uint8_t r[3];
|
||||
uint32_t rr[35];
|
||||
uint32_t notsent_bytes;
|
||||
} tcpi = {};
|
||||
struct tcpi tcpi = {};
|
||||
socklen_t ts = sizeof(tcpi);
|
||||
|
||||
if (getsockopt(sfd, IPPROTO_TCP,
|
||||
TCP_INFO, (char *)&tcpi, &ts) < 0) {
|
||||
perror("getsockopt TCP_INFO");
|
||||
break;
|
||||
}
|
||||
if (tcpi.state != 1) {
|
||||
LOG(LOG_E, "state: %d\n", tcpi.state);
|
||||
return;
|
||||
}
|
||||
if (ts < sizeof(tcpi)) {
|
||||
LOG(LOG_E, "tcpi_notsent_bytes not provided\n");
|
||||
params.wait_send = 0;
|
||||
break;
|
||||
}
|
||||
if (tcpi.state != 1) {
|
||||
LOG(LOG_E, "state: %d\n", tcpi.state);
|
||||
return;
|
||||
}
|
||||
if (tcpi.notsent_bytes == 0) {
|
||||
return;
|
||||
}
|
||||
@ -109,12 +107,15 @@ void wait_send(int sfd)
|
||||
}
|
||||
delay(params.sfdelay);
|
||||
}
|
||||
#define wait_send_if_support(sfd) \
|
||||
if (params.wait_send) wait_send(sfd)
|
||||
#else
|
||||
#define wait_send(sfd) delay(params.sfdelay)
|
||||
#define wait_send_if_support(sfd) // :(
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int send_fake(int sfd, char *buffer,
|
||||
ssize_t send_fake(int sfd, char *buffer,
|
||||
int cnt, long pos, int fa, struct desync_params *opt)
|
||||
{
|
||||
struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http;
|
||||
@ -126,9 +127,9 @@ int send_fake(int sfd, char *buffer,
|
||||
return -1;
|
||||
}
|
||||
char *p = 0;
|
||||
int status = -1;
|
||||
ssize_t len = -1;
|
||||
|
||||
while (status) {
|
||||
while (1) {
|
||||
if (ftruncate(ffd, pos) < 0) {
|
||||
uniperror("ftruncate");
|
||||
break;
|
||||
@ -150,7 +151,8 @@ int send_fake(int sfd, char *buffer,
|
||||
perror("setsockopt IP_OPTIONS");
|
||||
break;
|
||||
}
|
||||
if (sendfile(sfd, ffd, 0, pos) < 0) {
|
||||
len = sendfile(sfd, ffd, 0, pos);
|
||||
if (len < 0) {
|
||||
uniperror("sendfile");
|
||||
break;
|
||||
}
|
||||
@ -166,16 +168,16 @@ int send_fake(int sfd, char *buffer,
|
||||
perror("setsockopt IP_OPTIONS");
|
||||
break;
|
||||
}
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
if (p) munmap(p, pos);
|
||||
close(ffd);
|
||||
return status;
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
int send_fake(int sfd, char *buffer,
|
||||
ssize_t send_fake(int sfd, char *buffer,
|
||||
int cnt, long pos, int fa, struct desync_params *opt)
|
||||
{
|
||||
struct packet pkt = cnt != IS_HTTP ? fake_tls : fake_http;
|
||||
@ -202,9 +204,9 @@ int send_fake(int sfd, char *buffer,
|
||||
}
|
||||
|
||||
OVERLAPPED ov = {};
|
||||
int status = -1;
|
||||
ssize_t len = -1;
|
||||
|
||||
while (status) {
|
||||
while (1) {
|
||||
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!ov.hEvent) {
|
||||
uniperror("CreateEvent");
|
||||
@ -235,7 +237,7 @@ int send_fake(int sfd, char *buffer,
|
||||
if (opt->ip_options
|
||||
&& setsockopt(sfd, IPPROTO_IP, IP_OPTIONS,
|
||||
opt->ip_options, opt->ip_options_len) < 0) {
|
||||
perror("setsockopt IP_OPTIONS");
|
||||
uniperror("setsockopt IP_OPTIONS");
|
||||
break;
|
||||
}
|
||||
if (!TransmitFile(sfd, hfile, pos, pos, &ov,
|
||||
@ -246,7 +248,7 @@ int send_fake(int sfd, char *buffer,
|
||||
break;
|
||||
}
|
||||
}
|
||||
delay(params.sfdelay);
|
||||
wait_send(sfd);
|
||||
|
||||
if (SetFilePointer(hfile, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
|
||||
uniperror("SetFilePointer");
|
||||
@ -262,10 +264,11 @@ int send_fake(int sfd, char *buffer,
|
||||
if (opt->ip_options
|
||||
&& setsockopt(sfd, IPPROTO_IP, IP_OPTIONS,
|
||||
opt->ip_options, 0) < 0) {
|
||||
perror("setsockopt IP_OPTIONS");
|
||||
uniperror("setsockopt IP_OPTIONS");
|
||||
break;
|
||||
}
|
||||
status = 0;
|
||||
len = pos;
|
||||
break;
|
||||
}
|
||||
if (!CloseHandle(hfile)) {
|
||||
uniperror("CloseHandle hfile");
|
||||
@ -273,11 +276,11 @@ int send_fake(int sfd, char *buffer,
|
||||
if (ov.hEvent && !CloseHandle(ov.hEvent)) {
|
||||
uniperror("CloseHandle hEvent");
|
||||
}
|
||||
return status;
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
int send_oob(int sfd, char *buffer,
|
||||
ssize_t send_oob(int sfd, char *buffer,
|
||||
ssize_t n, long pos)
|
||||
{
|
||||
ssize_t size = oob_data.size - 1;
|
||||
@ -286,42 +289,53 @@ int send_oob(int sfd, char *buffer,
|
||||
char rchar = buffer[pos];
|
||||
buffer[pos] = oob_data.data[0];
|
||||
|
||||
if (send(sfd, buffer, pos + 1, MSG_OOB) < 0) {
|
||||
ssize_t len = send(sfd, buffer, pos + 1, MSG_OOB);
|
||||
buffer[pos] = rchar;
|
||||
|
||||
if (len < 0) {
|
||||
uniperror("send");
|
||||
buffer[pos] = rchar;
|
||||
return -1;
|
||||
}
|
||||
buffer[pos] = rchar;
|
||||
wait_send(sfd);
|
||||
|
||||
len--;
|
||||
if (len != pos) {
|
||||
return len;
|
||||
}
|
||||
if (size) {
|
||||
wait_send(sfd);
|
||||
}
|
||||
for (long i = 0; i < size; i++) {
|
||||
if (send(sfd, data + i, 1, MSG_OOB) < 0) {
|
||||
uniperror("send");
|
||||
return -1;
|
||||
if (get_e() == EAGAIN) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
if (size != 1) {
|
||||
wait_send(sfd);
|
||||
}
|
||||
wait_send(sfd);
|
||||
}
|
||||
return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int send_disorder(int sfd,
|
||||
ssize_t send_disorder(int sfd,
|
||||
char *buffer, long pos, int fa)
|
||||
{
|
||||
int bttl = 1;
|
||||
int status = 0;
|
||||
|
||||
if (setttl(sfd, bttl, fa) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (send(sfd, buffer, pos, 0) < 0) {
|
||||
ssize_t len = send(sfd, buffer, pos, 0);
|
||||
if (len < 0) {
|
||||
uniperror("send");
|
||||
status = -1;
|
||||
}
|
||||
wait_send_if_support(sfd);
|
||||
|
||||
if (setttl(sfd, params.def_ttl, fa) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return status;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@ -333,7 +347,7 @@ ssize_t desync(int sfd, char *buffer, size_t bfsize,
|
||||
char *host = 0;
|
||||
int len = 0, type = 0;
|
||||
int fa = get_family(dst);
|
||||
|
||||
// parse packet
|
||||
if ((len = parse_tls(buffer, n, &host))) {
|
||||
type = IS_HTTPS;
|
||||
}
|
||||
@ -344,7 +358,7 @@ ssize_t desync(int sfd, char *buffer, size_t bfsize,
|
||||
LOG(LOG_S, "host: %.*s (%ld)\n",
|
||||
len, host, host - buffer);
|
||||
}
|
||||
|
||||
// modify packet
|
||||
if (type == IS_HTTP && dp.mod_http) {
|
||||
LOG(LOG_S, "modify HTTP: n=%ld\n", n);
|
||||
if (mod_http(buffer, n, dp.mod_http)) {
|
||||
@ -378,19 +392,22 @@ ssize_t desync(int sfd, char *buffer, size_t bfsize,
|
||||
lp = pos + 5;
|
||||
}
|
||||
}
|
||||
|
||||
// set custom TTL
|
||||
if (params.custom_ttl) {
|
||||
if (setttl(sfd, params.def_ttl, fa) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// desync
|
||||
long lp = offset;
|
||||
|
||||
if (!type && params.de_known) {
|
||||
// cancel
|
||||
}
|
||||
else for (int i = 0; i < dp.parts_n; i++) {
|
||||
struct part part = dp.parts[i];
|
||||
|
||||
// change pos
|
||||
long pos = part.pos;
|
||||
if (part.flag == OFFSET_SNI) {
|
||||
if (type != IS_HTTPS)
|
||||
@ -415,39 +432,46 @@ ssize_t desync(int sfd, char *buffer, size_t bfsize,
|
||||
LOG(LOG_E, "split cancel: pos=%ld-%ld, n=%ld\n", lp, pos, n);
|
||||
break;
|
||||
}
|
||||
LOG(LOG_S, "split: pos=%ld-%ld, m=%d\n", lp, pos, part.m);
|
||||
// send part
|
||||
LOG(LOG_S, "split: pos=%ld-%ld, m: %s\n", lp, pos, demode_str[part.m]);
|
||||
|
||||
int s = 0;
|
||||
ssize_t s = 0;
|
||||
switch (part.m) {
|
||||
#ifdef FAKE_SUPPORT
|
||||
case DESYNC_FAKE:
|
||||
s = send_fake(sfd,
|
||||
buffer + lp, type, pos - lp, fa, &dp);
|
||||
break;
|
||||
#endif
|
||||
case DESYNC_DISORDER:
|
||||
s = send_disorder(sfd,
|
||||
buffer + lp, pos - lp, fa);
|
||||
break;
|
||||
#ifdef FAKE_SUPPORT
|
||||
case DESYNC_FAKE:
|
||||
s = send_fake(sfd,
|
||||
buffer + lp, type, pos - lp, fa, &dp);
|
||||
break;
|
||||
#endif
|
||||
case DESYNC_DISORDER:
|
||||
s = send_disorder(sfd,
|
||||
buffer + lp, pos - lp, fa);
|
||||
break;
|
||||
|
||||
case DESYNC_OOB:
|
||||
s = send_oob(sfd,
|
||||
buffer + lp, n - lp, pos - lp);
|
||||
break;
|
||||
case DESYNC_OOB:
|
||||
s = send_oob(sfd,
|
||||
buffer + lp, n - lp, pos - lp);
|
||||
wait_send_if_support(sfd);
|
||||
break;
|
||||
|
||||
case DESYNC_SPLIT:
|
||||
default:
|
||||
s = send(sfd, buffer + lp, pos - lp, 0);
|
||||
case DESYNC_SPLIT:
|
||||
default:
|
||||
s = send(sfd, buffer + lp, pos - lp, 0);
|
||||
wait_send_if_support(sfd);
|
||||
}
|
||||
if (s < 0) {
|
||||
if (part.m != DESYNC_FAKE
|
||||
&& get_e() == EAGAIN) {
|
||||
if (get_e() == EAGAIN) {
|
||||
return lp;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else if (s != (pos - lp)) {
|
||||
LOG(LOG_E, "%ld != %ld\n", s, pos - lp);
|
||||
return lp + s;
|
||||
}
|
||||
lp = pos;
|
||||
}
|
||||
// send all/rest
|
||||
if (lp < n) {
|
||||
LOG((lp ? LOG_S : LOG_L), "send: pos=%ld-%ld\n", lp, n);
|
||||
if (send(sfd, buffer + lp, n - lp, 0) < 0) {
|
||||
|
9
desync.h
9
desync.h
@ -1 +1,10 @@
|
||||
ssize_t desync(int sfd, char *buffer, size_t bfsize, ssize_t n, ssize_t offset, struct sockaddr *dst, int dp_c);
|
||||
|
||||
struct tcpi {
|
||||
uint8_t state;
|
||||
uint8_t r[3];
|
||||
uint32_t rr[5];
|
||||
uint32_t unacked;
|
||||
uint32_t rrr[29];
|
||||
uint32_t notsent_bytes;
|
||||
};
|
18
main.c
18
main.c
@ -22,7 +22,7 @@
|
||||
#define close(fd) closesocket(fd)
|
||||
#endif
|
||||
|
||||
#define VERSION 6
|
||||
#define VERSION 7
|
||||
#define MPOOL_INC 16
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ fake_http = {
|
||||
oob_data = {
|
||||
1, "a"
|
||||
};
|
||||
char ip_option[1] = "\0";
|
||||
|
||||
|
||||
struct params params = {
|
||||
@ -65,7 +66,7 @@ const char help_text[] = {
|
||||
" -N, --no-domain Deny domain resolving\n"
|
||||
" -I --conn-ip <ip> Connection binded IP, default ::\n"
|
||||
" -b, --buf-size <size> Buffer size, default 16384\n"
|
||||
" -x, --debug Print logs, 0, 1 or 2\n"
|
||||
" -x, --debug <level> Print logs, 0, 1 or 2\n"
|
||||
" -g, --def-ttl <num> TTL for all outgoing connections\n"
|
||||
// desync options
|
||||
" -K, --desync-known Desync only HTTP and TLS with SNI\n"
|
||||
@ -86,7 +87,7 @@ 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"
|
||||
" -k, --ip-opt <f|:str> IP options of fake packets\n"
|
||||
" -k, --ip-opt [f|:str] IP options of fake packets\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"
|
||||
@ -125,7 +126,7 @@ const struct option options[] = {
|
||||
#ifdef FAKE_SUPPORT
|
||||
{"fake", 1, 0, 'f'},
|
||||
{"ttl", 1, 0, 't'},
|
||||
{"ip-opt", 1, 0, 'k'},
|
||||
{"ip-opt", 2, 0, 'k'},
|
||||
{"fake-tls", 1, 0, 'l'},
|
||||
{"fake-http", 1, 0, 'j'},
|
||||
{"tls-sni", 1, 0, 'n'},
|
||||
@ -489,7 +490,12 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
dp->ip_options = ftob(optarg, &dp->ip_options_len);
|
||||
if (optarg)
|
||||
dp->ip_options = ftob(optarg, &dp->ip_options_len);
|
||||
else {
|
||||
dp->ip_options = ip_option;
|
||||
dp->ip_options_len = sizeof(ip_option);
|
||||
}
|
||||
if (!dp->ip_options) {
|
||||
uniperror("read/parse");
|
||||
return -1;
|
||||
@ -573,7 +579,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w': //
|
||||
case 'V': //
|
||||
params.sfdelay = strtol(optarg, &end, 0);
|
||||
if (params.sfdelay < 0 || optarg == end
|
||||
|| params.sfdelay >= 1000 || *end)
|
||||
|
12
params.h
12
params.h
@ -23,6 +23,16 @@ enum demode {
|
||||
DESYNC_FAKE
|
||||
};
|
||||
|
||||
#ifdef STR_MODE
|
||||
char *demode_str[] = {
|
||||
"DESYNC_NONE",
|
||||
"DESYNC_SPLIT",
|
||||
"DESYNC_DISORDER",
|
||||
"DESYNC_OOB",
|
||||
"DESYNC_FAKE"
|
||||
};
|
||||
#endif
|
||||
|
||||
struct part {
|
||||
int m;
|
||||
int flag;
|
||||
@ -77,3 +87,5 @@ struct spos {
|
||||
ssize_t start, end, size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
extern char ip_option[1];
|
12
readme.txt
12
readme.txt
@ -35,6 +35,11 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
Отключить запутывание для нераспознанных протоколов
|
||||
Распознаваемые протоколы: HTTP и TLS с SNI
|
||||
|
||||
-F, --tfo
|
||||
Включает TCP Fast Open
|
||||
Если сервер его поддерживает, то первый пакет будет отправлен сразу вместе с SYN
|
||||
Поддерживается только в Linux (4.11+)
|
||||
|
||||
-A, --auto
|
||||
Автоматический режим
|
||||
Если сервер сбросил подключение, превышено время ожидания, сработал --tr,
|
||||
@ -42,7 +47,7 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
Можно указывать несколько групп параметров, раделяя их данным флагом
|
||||
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
||||
Параметры, которые можно вынести в отдельную группу:
|
||||
split, disorder, oob, fake, ttl, mod-http, tlsrec
|
||||
split, disorder, oob, fake, ttl, ip-opt, mod-http, tlsrec
|
||||
|
||||
-u, --cache-ttl <sec>
|
||||
Время жизни значения в кеше, по умолчанию 100800 (28 часов)
|
||||
@ -79,6 +84,11 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
||||
TTL для поддельного пакета, по умолчанию 8
|
||||
Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI
|
||||
|
||||
-k, --ip-opt [file|:str]
|
||||
Установить опции для фейкового IP пакета
|
||||
Существенно снизит вероятность, что пакет дойдет до сервера
|
||||
Стоит учесть, что до DPI он также может не дойти
|
||||
|
||||
-l, --fake-tls <file|:str>
|
||||
-j, --fake-http <file|:str>
|
||||
Указать свои поддельные пакеты, вместо дефолтных
|
||||
|
Loading…
Reference in New Issue
Block a user