mirror of
https://github.com/hufrea/byedpi.git
synced 2025-08-22 19:28:40 +00:00
avl, --hosts, --dst
This commit is contained in:
parent
38d44ec1ca
commit
3b65b275b1
1
conev.h
1
conev.h
@ -73,6 +73,7 @@ struct eval {
|
|||||||
};
|
};
|
||||||
ssize_t recv_count;
|
ssize_t recv_count;
|
||||||
int attempt;
|
int attempt;
|
||||||
|
char cache;
|
||||||
#ifndef NOEPOLL
|
#ifndef NOEPOLL
|
||||||
uint32_t events;
|
uint32_t events;
|
||||||
#endif
|
#endif
|
||||||
|
109
main.c
109
main.c
@ -17,12 +17,13 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#else
|
#else
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#define close(fd) closesocket(fd)
|
#define close(fd) closesocket(fd)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VERSION "8.1"
|
#define VERSION "10"
|
||||||
|
|
||||||
#define MPOOL_INC 16
|
#define MPOOL_INC 16
|
||||||
|
|
||||||
@ -71,12 +72,15 @@ const char help_text[] = {
|
|||||||
#ifdef TCP_FASTOPEN_CONNECT
|
#ifdef TCP_FASTOPEN_CONNECT
|
||||||
" -F, --tfo Enable TCP Fast Open\n"
|
" -F, --tfo Enable TCP Fast Open\n"
|
||||||
#endif
|
#endif
|
||||||
" -A, --auto[=t,r,c,s,a] Try desync params after this option\n"
|
" -L, --late-conn Waiting for request before connecting\n"
|
||||||
" Detect: torst,redirect,cl_err,sid_inv,alert\n"
|
" -A, --auto[=t,r,c,s,a,n] Try desync params after this option\n"
|
||||||
|
" Detect: torst,redirect,cl_err,sid_inv,alert,nop\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, after which trigger auto\n"
|
" -T, --timeout <sec> Timeout waiting for response, after which trigger auto\n"
|
||||||
#endif
|
#endif
|
||||||
|
" -H, --hosts <file|:str> Hosts whitelist\n"
|
||||||
|
" -D, --dst <addr> Custom destination IP\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"
|
||||||
@ -115,11 +119,14 @@ const struct option options[] = {
|
|||||||
#ifdef TCP_FASTOPEN_CONNECT
|
#ifdef TCP_FASTOPEN_CONNECT
|
||||||
{"tfo ", 0, 0, 'F'},
|
{"tfo ", 0, 0, 'F'},
|
||||||
#endif
|
#endif
|
||||||
|
{"late-conn", 0, 0, 'L'},
|
||||||
{"auto", 2, 0, 'A'},
|
{"auto", 2, 0, 'A'},
|
||||||
{"cache-ttl", 1, 0, 'u'},
|
{"cache-ttl", 1, 0, 'u'},
|
||||||
#ifdef TIMEOUT_SUPPORT
|
#ifdef TIMEOUT_SUPPORT
|
||||||
{"timeout", 1, 0, 'T'},
|
{"timeout", 1, 0, 'T'},
|
||||||
#endif
|
#endif
|
||||||
|
{"hosts", 1, 0, 'H'},
|
||||||
|
{"dst", 1, 0, 'D'},
|
||||||
{"split", 1, 0, 's'},
|
{"split", 1, 0, 's'},
|
||||||
{"disorder", 1, 0, 'd'},
|
{"disorder", 1, 0, 'd'},
|
||||||
{"oob", 1, 0, 'o'},
|
{"oob", 1, 0, 'o'},
|
||||||
@ -195,16 +202,27 @@ char *ftob(const char *str, ssize_t *sl)
|
|||||||
long size;
|
long size;
|
||||||
|
|
||||||
FILE *file = fopen(str, "rb");
|
FILE *file = fopen(str, "rb");
|
||||||
if (!file)
|
if (!file) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
if (fseek(file, 0, SEEK_END)) {
|
if (fseek(file, 0, SEEK_END)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size = ftell(file);
|
size = ftell(file);
|
||||||
if (!size || fseek(file, 0, SEEK_SET)) {
|
if (size <= 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (fseek(file, 0, SEEK_SET)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef _WIN32
|
||||||
|
buffer = mmap(0, size, PROT_READ, MAP_PRIVATE, fileno(file), 0);
|
||||||
|
if (buffer == MAP_FAILED) {
|
||||||
|
buffer = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!(buffer = malloc(size))) {
|
if (!(buffer = malloc(size))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -212,6 +230,7 @@ char *ftob(const char *str, ssize_t *sl)
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
buffer = 0;
|
buffer = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} while (0);
|
} while (0);
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
*sl = size;
|
*sl = size;
|
||||||
@ -221,6 +240,33 @@ char *ftob(const char *str, ssize_t *sl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct mphdr *parse_hosts(char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
struct mphdr *hdr = mem_pool(1);
|
||||||
|
if (!hdr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char *end = buffer + size;
|
||||||
|
char *e = buffer, *s = buffer;
|
||||||
|
|
||||||
|
for (; e <= end; e++) {
|
||||||
|
if (*e != ' ' && *e != '\n' && e != end) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (s == e) {
|
||||||
|
s++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mem_add(hdr, s, e - s) == 0) {
|
||||||
|
free(hdr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s = e + 1;
|
||||||
|
}
|
||||||
|
return hdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int get_addr(const 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;
|
||||||
@ -284,18 +330,23 @@ int parse_offset(struct part *part, const char *str)
|
|||||||
|
|
||||||
void *add(void **root, int *n, size_t ss)
|
void *add(void **root, int *n, size_t ss)
|
||||||
{
|
{
|
||||||
void *p = realloc(*root, ss * (*n + 1));
|
char *p = realloc(*root, ss * (*n + 1));
|
||||||
if (!p) {
|
if (!p) {
|
||||||
uniperror("realloc");
|
uniperror("realloc");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*root = p;
|
*root = p;
|
||||||
p = ((*root) + ((*n) * ss));
|
p = (p + ((*n) * ss));
|
||||||
memset(p, 0, ss);
|
memset(p, 0, ss);
|
||||||
*n = *n + 1;
|
*n = *n + 1;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#define FREE(p, s) munmap(p, s)
|
||||||
|
#else
|
||||||
|
#define FREE(p, s) free(p)
|
||||||
|
#endif
|
||||||
|
|
||||||
void clear_params(void)
|
void clear_params(void)
|
||||||
{
|
{
|
||||||
@ -322,15 +373,15 @@ void clear_params(void)
|
|||||||
params.dp = 0;
|
params.dp = 0;
|
||||||
}
|
}
|
||||||
if (fake_tls.data != tls_data) {
|
if (fake_tls.data != tls_data) {
|
||||||
free(fake_tls.data);
|
FREE(fake_tls.data, fake_tls.size);
|
||||||
fake_tls.data = tls_data;
|
fake_tls.data = tls_data;
|
||||||
}
|
}
|
||||||
if (fake_http.data != http_data) {
|
if (fake_http.data != http_data) {
|
||||||
free(fake_http.data);
|
FREE(fake_http.data, fake_http.size);
|
||||||
fake_http.data = http_data;
|
fake_http.data = http_data;
|
||||||
}
|
}
|
||||||
if (oob_data.data != oob_char) {
|
if (oob_data.data != oob_char) {
|
||||||
free(oob_data.data);
|
FREE(oob_data.data, oob_data.size);
|
||||||
oob_data.data = oob_char;
|
oob_data.data = oob_char;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,6 +433,7 @@ int main(int argc, char **argv)
|
|||||||
clear_params();
|
clear_params();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!invalid && (rez = getopt_long_only(
|
while (!invalid && (rez = getopt_long_only(
|
||||||
argc, argv, opt, options, 0)) != -1) {
|
argc, argv, opt, options, 0)) != -1) {
|
||||||
switch (rez) {
|
switch (rez) {
|
||||||
@ -445,6 +497,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// desync options
|
// desync options
|
||||||
|
|
||||||
|
case 'L':
|
||||||
|
params.late_conn = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'K':
|
case 'K':
|
||||||
params.de_known = 1;
|
params.de_known = 1;
|
||||||
break;
|
break;
|
||||||
@ -482,6 +538,8 @@ int main(int argc, char **argv)
|
|||||||
case 'a':
|
case 'a':
|
||||||
dp->detect |= DETECT_TLS_ALERT;
|
dp->detect |= DETECT_TLS_ALERT;
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
invalid = 1;
|
invalid = 1;
|
||||||
continue;
|
continue;
|
||||||
@ -512,6 +570,27 @@ int main(int argc, char **argv)
|
|||||||
params.timeout = val;
|
params.timeout = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'H':;
|
||||||
|
char *data = ftob(optarg, &val);
|
||||||
|
if (!data) {
|
||||||
|
uniperror("read/parse");
|
||||||
|
invalid = 1;
|
||||||
|
}
|
||||||
|
dp->hosts = parse_hosts(data, val);
|
||||||
|
if (!dp->hosts) {
|
||||||
|
perror("parse_hosts");
|
||||||
|
clear_params();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
if (get_addr(optarg, (struct sockaddr_ina *)&dp->addr) < 0)
|
||||||
|
invalid = 1;
|
||||||
|
else
|
||||||
|
dp->to_ip = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'o':
|
case 'o':
|
||||||
@ -671,6 +750,14 @@ int main(int argc, char **argv)
|
|||||||
clear_params();
|
clear_params();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (dp->hosts) {
|
||||||
|
dp = add((void *)¶ms.dp,
|
||||||
|
¶ms.dp_count, sizeof(struct desync_params));
|
||||||
|
if (!dp) {
|
||||||
|
clear_params();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
s.in.sin_port = port;
|
s.in.sin_port = port;
|
||||||
b.in.sin_port = 0;
|
b.in.sin_port = 0;
|
||||||
|
|
||||||
@ -683,7 +770,7 @@ int main(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
params.mempool = mem_pool(MPOOL_INC);
|
params.mempool = mem_pool(0);
|
||||||
if (!params.mempool) {
|
if (!params.mempool) {
|
||||||
uniperror("mem_pool");
|
uniperror("mem_pool");
|
||||||
clear_params();
|
clear_params();
|
||||||
|
147
mpool.c
147
mpool.c
@ -3,129 +3,98 @@
|
|||||||
#include <mpool.h>
|
#include <mpool.h>
|
||||||
|
|
||||||
|
|
||||||
struct mphdr *mem_pool(int count)
|
static inline int scmp(const struct elem *p, const struct elem *q)
|
||||||
{
|
{
|
||||||
struct mphdr *hdr = malloc(sizeof(struct mphdr));
|
if (p->len != q ->len) {
|
||||||
if (!hdr) {
|
return p->len < q->len ? -1 : 1;
|
||||||
return 0;
|
}
|
||||||
|
return memcmp(p->data, q->data, p->len);
|
||||||
}
|
}
|
||||||
hdr->inc = count;
|
|
||||||
hdr->max = count;
|
|
||||||
hdr->count = 0;
|
|
||||||
|
|
||||||
hdr->values = malloc(sizeof(*hdr->values) * count);
|
KAVL_INIT(my, struct elem, head, scmp)
|
||||||
if (!hdr->values) {
|
|
||||||
free(hdr);
|
|
||||||
hdr = 0;
|
struct mphdr *mem_pool(bool cst)
|
||||||
|
{
|
||||||
|
struct mphdr *hdr = calloc(sizeof(struct mphdr), 1);
|
||||||
|
if (hdr) {
|
||||||
|
hdr->stat = cst;
|
||||||
}
|
}
|
||||||
return hdr;
|
return hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mem_index(struct mphdr *hdr, char *str, int len)
|
struct elem *mem_get(struct mphdr *hdr, char *str, int len)
|
||||||
{
|
{
|
||||||
if (!hdr->count) {
|
struct {
|
||||||
return -2;
|
int len;
|
||||||
}
|
char *data;
|
||||||
int s = 0, m, i;
|
} temp = { .len = len, .data = str };
|
||||||
int e = hdr->count - 1;
|
|
||||||
|
|
||||||
while (s <= e) {
|
return kavl_find(my, hdr->root, (struct elem *)&temp, 0);
|
||||||
m = s + (e - s) / 2;
|
|
||||||
|
|
||||||
struct elem *val = hdr->values[m];
|
|
||||||
if (val->len != len)
|
|
||||||
i = len < val->len ? -1 : 1;
|
|
||||||
else
|
|
||||||
i = memcmp(str, val->data, len);
|
|
||||||
|
|
||||||
if (i > 0)
|
|
||||||
s = m + 1;
|
|
||||||
else if (i < 0)
|
|
||||||
e = m - 1;
|
|
||||||
else
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
return -(m + 2 + (i > 0 ? 1 : 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct elem *mem_add(struct mphdr *hdr, char *str, int len, int pos)
|
struct elem *mem_add(struct mphdr *hdr, char *str, int len)
|
||||||
{
|
{
|
||||||
int max = hdr->max;
|
struct elem *v, *e = malloc(sizeof(struct elem));
|
||||||
|
if (!e) {
|
||||||
if (hdr->count >= max) {
|
|
||||||
max += hdr->inc;
|
|
||||||
struct elem **new = realloc(hdr->values, sizeof(*hdr->values) * max);
|
|
||||||
if (!new) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
hdr->max = max;
|
e->len = len;
|
||||||
hdr->values = new;
|
if (!hdr->stat) {
|
||||||
}
|
e->data = malloc(len);
|
||||||
if (pos >= 0) {
|
if (!e->data) {
|
||||||
return hdr->values[pos];
|
free(e);
|
||||||
}
|
|
||||||
pos = -pos - 2;
|
|
||||||
|
|
||||||
struct elem *val = malloc(sizeof(struct elem) + len);
|
|
||||||
if (!val) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(val, 0, sizeof(*val));
|
memcpy(e->data, str, len);
|
||||||
memcpy(val->data, str, len);
|
|
||||||
val->len = len;
|
|
||||||
|
|
||||||
if (pos < hdr->count) {
|
|
||||||
void *p = &hdr->values[pos];
|
|
||||||
void *n = &hdr->values[pos + 1];
|
|
||||||
void *e = &hdr->values[hdr->count];
|
|
||||||
memmove(n, p, e - p);
|
|
||||||
}
|
}
|
||||||
hdr->values[pos] = val;
|
else {
|
||||||
hdr->count++;
|
e->data = str;
|
||||||
return val;
|
}
|
||||||
|
v = kavl_insert(my, &hdr->root, e, 0);
|
||||||
|
if (e != v) {
|
||||||
|
if (!hdr->stat) {
|
||||||
|
free(e->data);
|
||||||
|
}
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mem_delete(struct mphdr *hdr, int pos)
|
void mem_delete(struct mphdr *hdr, char *str, int len)
|
||||||
{
|
{
|
||||||
int max = hdr->max;
|
struct {
|
||||||
if (!hdr->count) {
|
int len;
|
||||||
|
char *data;
|
||||||
|
} temp = { .len = len, .data = str };
|
||||||
|
|
||||||
|
struct elem *e = kavl_erase(my, &hdr->root, (struct elem *)&temp, 0);
|
||||||
|
if (!e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (max > hdr->inc &&
|
if (!hdr->stat) {
|
||||||
(max - hdr->count) > hdr->inc * 2) {
|
free(e->data);
|
||||||
max -= hdr->inc;
|
e->data = 0;
|
||||||
struct elem **new = realloc(hdr->values, sizeof(*hdr->values) * max);
|
|
||||||
if (new) {
|
|
||||||
hdr->max = max;
|
|
||||||
hdr->values = new;
|
|
||||||
}
|
}
|
||||||
}
|
free(e);
|
||||||
free(hdr->values[pos]);
|
|
||||||
|
|
||||||
if (pos < hdr->count) {
|
|
||||||
void *p = &hdr->values[pos];
|
|
||||||
void *n = &hdr->values[pos + 1];
|
|
||||||
void *e = &hdr->values[hdr->count];
|
|
||||||
memmove(p, n, e - n);
|
|
||||||
}
|
|
||||||
hdr->count--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mem_destroy(struct mphdr *hdr)
|
void mem_destroy(struct mphdr *hdr)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < hdr->count && hdr->values; i++) {
|
while (hdr->root) {
|
||||||
struct elem *e = hdr->values[i];
|
struct elem *e = kavl_erase_first(my, &hdr->root);
|
||||||
if (!e) {
|
if (!e) {
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!hdr->stat && e->data) {
|
||||||
|
free(e->data);
|
||||||
|
}
|
||||||
|
e->data = 0;
|
||||||
free(e);
|
free(e);
|
||||||
hdr->values[i] = 0;
|
|
||||||
}
|
}
|
||||||
free(hdr->values);
|
|
||||||
memset(hdr, 0, sizeof(*hdr));
|
|
||||||
free(hdr);
|
free(hdr);
|
||||||
}
|
}
|
27
mpool.h
27
mpool.h
@ -1,19 +1,26 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "kavl.h"
|
||||||
|
|
||||||
struct elem {
|
struct elem {
|
||||||
|
int len;
|
||||||
|
char *data;
|
||||||
int m;
|
int m;
|
||||||
time_t time;
|
time_t time;
|
||||||
int len;
|
KAVL_HEAD(struct elem) head;
|
||||||
char data[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mphdr {
|
struct mphdr {
|
||||||
int max;
|
bool stat;
|
||||||
int inc;
|
struct elem *root;
|
||||||
int count;
|
|
||||||
struct elem **values;
|
|
||||||
};
|
};
|
||||||
struct mphdr *mem_pool(int count);
|
|
||||||
int mem_index(struct mphdr *hdr, char *str, int len);
|
struct mphdr *mem_pool(bool cst);
|
||||||
struct elem *mem_add(struct mphdr *hdr, char *str, int len, int pos);
|
|
||||||
void mem_delete(struct mphdr *hdr, int pos);
|
struct elem *mem_get(struct mphdr *hdr, char *str, int len);
|
||||||
|
|
||||||
|
struct elem *mem_add(struct mphdr *hdr, char *str, int len);
|
||||||
|
|
||||||
|
void mem_delete(struct mphdr *hdr, char *str, int len);
|
||||||
|
|
||||||
void mem_destroy(struct mphdr *hdr);
|
void mem_destroy(struct mphdr *hdr);
|
5
params.h
5
params.h
@ -56,6 +56,10 @@ struct desync_params {
|
|||||||
int tlsrec_n;
|
int tlsrec_n;
|
||||||
struct part *tlsrec;
|
struct part *tlsrec;
|
||||||
int detect;
|
int detect;
|
||||||
|
struct mphdr *hosts;
|
||||||
|
|
||||||
|
char to_ip;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct params {
|
struct params {
|
||||||
@ -67,6 +71,7 @@ struct params {
|
|||||||
int def_ttl;
|
int def_ttl;
|
||||||
char custom_ttl;
|
char custom_ttl;
|
||||||
|
|
||||||
|
char late_conn;
|
||||||
char tfo;
|
char tfo;
|
||||||
unsigned int timeout;
|
unsigned int timeout;
|
||||||
long cache_ttl;
|
long cache_ttl;
|
||||||
|
127
proxy.c
127
proxy.c
@ -497,34 +497,26 @@ static inline int on_tunnel(struct poolhd *pool, struct eval *val,
|
|||||||
int mode_add_get(struct sockaddr_ina *dst, int m)
|
int mode_add_get(struct sockaddr_ina *dst, int m)
|
||||||
{
|
{
|
||||||
// m < 0: get, m > 0: set, m == 0: delete
|
// m < 0: get, m > 0: set, m == 0: delete
|
||||||
int len;
|
|
||||||
time_t t;
|
time_t t;
|
||||||
struct elem *val;
|
struct elem *val;
|
||||||
|
char *str = (char *)&dst->in;
|
||||||
struct {
|
int len = sizeof(dst->sa.sa_family);
|
||||||
uint16_t port;
|
|
||||||
union {
|
|
||||||
struct in_addr ip4;
|
|
||||||
struct in6_addr ip6;
|
|
||||||
};
|
|
||||||
} str = { .port = dst->in.sin_port };
|
|
||||||
|
|
||||||
if (dst->sa.sa_family == AF_INET) {
|
if (dst->sa.sa_family == AF_INET) {
|
||||||
str.ip4 = dst->in.sin_addr;
|
len = sizeof(dst->in);
|
||||||
len = sizeof(str.port) + sizeof(str.ip4);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
str.ip6 = dst->in6.sin6_addr;
|
len = sizeof(dst->in6) - sizeof(dst->in6.sin6_scope_id);
|
||||||
len = sizeof(str);
|
|
||||||
}
|
}
|
||||||
int i = mem_index(params.mempool, (char *)&str, len);
|
len -= sizeof(dst->sa.sa_family);
|
||||||
if (m == 0 && i >= 0) {
|
|
||||||
mem_delete(params.mempool, i);
|
if (m == 0) {
|
||||||
|
mem_delete(params.mempool, str, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (m > 0) {
|
else if (m > 0) {
|
||||||
time(&t);
|
time(&t);
|
||||||
val = mem_add(params.mempool, (char *)&str, len, i);
|
val = mem_add(params.mempool, str, len);
|
||||||
if (!val) {
|
if (!val) {
|
||||||
uniperror("mem_add");
|
uniperror("mem_add");
|
||||||
return -1;
|
return -1;
|
||||||
@ -533,10 +525,10 @@ int mode_add_get(struct sockaddr_ina *dst, int m)
|
|||||||
val->time = t;
|
val->time = t;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (i < 0) {
|
val = mem_get(params.mempool, str, len);
|
||||||
|
if (!val) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
val = params.mempool->values[i];
|
|
||||||
time(&t);
|
time(&t);
|
||||||
if (t > val->time + params.cache_ttl) {
|
if (t > val->time + params.cache_ttl) {
|
||||||
LOG(LOG_S, "time=%ld, now=%ld, ignore\n", val->time, t);
|
LOG(LOG_S, "time=%ld, now=%ld, ignore\n", val->time, t);
|
||||||
@ -546,6 +538,19 @@ int mode_add_get(struct sockaddr_ina *dst, int m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ext_connect(struct poolhd *pool, struct eval *val,
|
||||||
|
struct sockaddr_ina *dst, int next, int m)
|
||||||
|
{
|
||||||
|
struct desync_params *dp = ¶ms.dp[m];
|
||||||
|
if (dp->to_ip == 2) {
|
||||||
|
struct sockaddr_ina addr = { .in6 = dp->addr };
|
||||||
|
addr.in.sin_port = dst->in.sin_port;
|
||||||
|
return create_conn(pool, val, &addr, next);
|
||||||
|
}
|
||||||
|
return create_conn(pool, val, dst, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int on_request(struct poolhd *pool, struct eval *val,
|
static inline int on_request(struct poolhd *pool, struct eval *val,
|
||||||
char *buffer, size_t bfsize)
|
char *buffer, size_t bfsize)
|
||||||
{
|
{
|
||||||
@ -584,18 +589,26 @@ static inline int on_request(struct poolhd *pool, struct eval *val,
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
error = create_conn(pool, val, &dst, EV_CONNECT);
|
if (params.late_conn) {
|
||||||
|
val->type = EV_DESYNC;
|
||||||
|
if (resp_error(val->fd, 0, val->flag) < 0) {
|
||||||
|
perror("send");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
val->in6 = dst.in6;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int m = mode_add_get(&dst, -1);
|
||||||
|
val->cache = (m == 0);
|
||||||
|
val->attempt = m < 0 ? 0 : m;
|
||||||
|
|
||||||
|
error = ext_connect(pool, val, &dst, EV_CONNECT, m);
|
||||||
if (error) {
|
if (error) {
|
||||||
int en = get_e();
|
int en = get_e();
|
||||||
if (resp_error(val->fd, en ? en : error, val->flag) < 0)
|
if (resp_error(val->fd, en ? en : error, val->flag) < 0)
|
||||||
uniperror("send");
|
uniperror("send");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int m = mode_add_get(&dst, -1);
|
|
||||||
if (m >= 0) {
|
|
||||||
val->attempt = m;
|
|
||||||
}
|
|
||||||
val->pair->attempt = m;
|
|
||||||
val->type = EV_IGNORE;
|
val->type = EV_IGNORE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -605,8 +618,8 @@ int reconnect(struct poolhd *pool, struct eval *val, int m)
|
|||||||
{
|
{
|
||||||
struct eval *client = val->pair;
|
struct eval *client = val->pair;
|
||||||
|
|
||||||
if (create_conn(pool, client,
|
if (ext_connect(pool, client,
|
||||||
(struct sockaddr_ina *)&val->in6, EV_DESYNC)) {
|
(struct sockaddr_ina *)&val->in6, EV_DESYNC, m)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
val->pair = 0;
|
val->pair = 0;
|
||||||
@ -614,20 +627,35 @@ int reconnect(struct poolhd *pool, struct eval *val, int m)
|
|||||||
|
|
||||||
client->type = EV_IGNORE;
|
client->type = EV_IGNORE;
|
||||||
client->attempt = m;
|
client->attempt = m;
|
||||||
|
client->cache = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool check_host(struct mphdr *hosts, struct eval *val)
|
||||||
|
{
|
||||||
|
char *host;
|
||||||
|
int len;
|
||||||
|
if (!(len = parse_tls(val->buff.data, val->buff.size, &host))) {
|
||||||
|
len = parse_http(val->buff.data, val->buff.size, &host, 0);
|
||||||
|
}
|
||||||
|
return mem_get(hosts, host, len) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int on_torst(struct poolhd *pool, struct eval *val)
|
int on_torst(struct poolhd *pool, struct eval *val)
|
||||||
{
|
{
|
||||||
int m = val->pair->attempt + 1;
|
int m = val->pair->attempt + 1;
|
||||||
|
|
||||||
for (; m < params.dp_count; m++) {
|
for (; m < params.dp_count; m++) {
|
||||||
struct desync_params dp = params.dp[m];
|
struct desync_params *dp = ¶ms.dp[m];
|
||||||
if (dp.detect == 0
|
if (!(dp->detect & DETECT_TORST)) {
|
||||||
|| (dp.detect & DETECT_TORST))
|
continue;
|
||||||
|
}
|
||||||
|
if (!dp->hosts || check_host(dp->hosts, val->pair)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (m >= params.dp_count) {
|
if (m >= params.dp_count) {
|
||||||
mode_add_get(
|
mode_add_get(
|
||||||
(struct sockaddr_ina *)&val->in6, 0);
|
(struct sockaddr_ina *)&val->in6, 0);
|
||||||
@ -646,26 +674,35 @@ int on_response(struct poolhd *pool, struct eval *val,
|
|||||||
ssize_t qn = val->pair->buff.size;
|
ssize_t qn = val->pair->buff.size;
|
||||||
|
|
||||||
for (; m < params.dp_count; m++) {
|
for (; m < params.dp_count; m++) {
|
||||||
struct desync_params dp = params.dp[m];
|
struct desync_params *dp = ¶ms.dp[m];
|
||||||
|
|
||||||
if ((dp.detect & DETECT_HTTP_LOCAT)
|
switch (0) {
|
||||||
|
default:
|
||||||
|
if ((dp->detect & DETECT_HTTP_LOCAT)
|
||||||
&& is_http_redirect(req, qn, resp, sn)) {
|
&& is_http_redirect(req, qn, resp, sn)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((dp.detect & DETECT_TLS_INVSID)
|
else if ((dp->detect & DETECT_TLS_INVSID)
|
||||||
&& neq_tls_sid(req, qn, resp, sn)) {
|
&& neq_tls_sid(req, qn, resp, sn)
|
||||||
|
&& !neq_tls_sid(
|
||||||
|
fake_tls.data, fake_tls.size, resp, sn)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((dp.detect & DETECT_TLS_ALERT)
|
else if ((dp->detect & DETECT_TLS_ALERT)
|
||||||
&& is_tls_alert(resp, sn)) {
|
&& is_tls_alert(resp, sn)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dp.detect & DETECT_HTTP_CLERR) {
|
else if (dp->detect & DETECT_HTTP_CLERR) {
|
||||||
int code = get_http_code(resp, sn);
|
int code = get_http_code(resp, sn);
|
||||||
if (code > 400 && code < 451 && code != 429) {
|
if (code > 400 && code < 451 && code != 429) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!dp->hosts || check_host(dp->hosts, val->pair)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m < params.dp_count) {
|
if (m < params.dp_count) {
|
||||||
return reconnect(pool, val, m);
|
return reconnect(pool, val, m);
|
||||||
@ -715,8 +752,7 @@ 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 (!pair->cache) {
|
||||||
|| (m && m == val->attempt)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (m == 0) {
|
if (m == 0) {
|
||||||
@ -757,6 +793,21 @@ int on_desync(struct poolhd *pool, struct eval *val,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(val->buff.data, buffer, n);
|
memcpy(val->buff.data, buffer, n);
|
||||||
|
|
||||||
|
if (!m) for (; m < params.dp_count; m++) {
|
||||||
|
struct desync_params *dp = ¶ms.dp[m];
|
||||||
|
if (!dp->detect &&
|
||||||
|
(!dp->hosts || check_host(dp->hosts, val))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m >= params.dp_count) return -1;
|
||||||
|
val->attempt = m;
|
||||||
|
|
||||||
|
if (params.late_conn) {
|
||||||
|
return ext_connect(pool, val,
|
||||||
|
(struct sockaddr_ina *)&val->in6, EV_DESYNC, m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
n = val->buff.size;
|
n = val->buff.size;
|
||||||
|
17
readme.txt
17
readme.txt
@ -40,7 +40,11 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
|||||||
Если сервер его поддерживает, то первый пакет будет отправлен сразу вместе с SYN
|
Если сервер его поддерживает, то первый пакет будет отправлен сразу вместе с SYN
|
||||||
Поддерживается только в Linux (4.11+)
|
Поддерживается только в Linux (4.11+)
|
||||||
|
|
||||||
-A, --auto[=t,r,c,s,a]
|
-L, --late-conn
|
||||||
|
Выполнять настоящее подключение только после получения первого пакета от клиента
|
||||||
|
Полезно при сочетании --hosts с --dst
|
||||||
|
|
||||||
|
-A, --auto[=t,r,c,s,a,n]
|
||||||
Автоматический режим
|
Автоматический режим
|
||||||
Если произошло событие, похожее на блокировку или поломку,
|
Если произошло событие, похожее на блокировку или поломку,
|
||||||
то будут применены параметры обхода, следующие за данной опцией
|
то будут применены параметры обхода, следующие за данной опцией
|
||||||
@ -50,11 +54,12 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
|||||||
cl_err : HTTP ответ, код которого равен 40x, но не 429
|
cl_err : HTTP ответ, код которого равен 40x, но не 429
|
||||||
sid_inv : session_id в TLS ServerHello и ClientHello не совпадают
|
sid_inv : session_id в TLS ServerHello и ClientHello не совпадают
|
||||||
alert : TLS Error Alert в ответе
|
alert : TLS Error Alert в ответе
|
||||||
|
nop : Предыдущая группа пропущена, например из-за ограничения по hosts
|
||||||
По умолчанию обрабатывается только torst
|
По умолчанию обрабатывается только torst
|
||||||
Можно указывать несколько групп опций, раделяя их данным параметром
|
Можно указывать несколько групп опций, раделяя их данным параметром
|
||||||
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
Если соединение успешно прошло, то параметры для данного IP будут закешированны
|
||||||
Параметры, которые можно вынести в отдельную группу:
|
Параметры, которые можно вынести в отдельную группу:
|
||||||
split, disorder, oob, fake, ttl, ip-opt, md5sig, mod-http, tlsrec
|
hosts, dst, split, disorder, oob, fake, ttl, ip-opt, md5sig, mod-http, tlsrec
|
||||||
Пример:
|
Пример:
|
||||||
--auto=redirect --split=1+h --auto=torst --fake -1 --auto=sid_inv,alert --tlsrec 1+s
|
--auto=redirect --split=1+h --auto=torst --fake -1 --auto=sid_inv,alert --tlsrec 1+s
|
||||||
|
|
||||||
@ -66,6 +71,14 @@ $ ./ciadpi --disorder 3 -A --tlsrec 1+s
|
|||||||
В Linux переводится в миллисекунды, поэтому можно указать дробное число
|
В Linux переводится в миллисекунды, поэтому можно указать дробное число
|
||||||
Истечение таймаута будет обработано --auto
|
Истечение таймаута будет обработано --auto
|
||||||
|
|
||||||
|
-H, --hosts <file|:string>
|
||||||
|
Ограничить область действия параметров списком доменов
|
||||||
|
Домены должны быть разделены новой строкой или пробелом
|
||||||
|
|
||||||
|
-D, --dst <ip>
|
||||||
|
Заменить адрес назначения из запроса на указанный
|
||||||
|
Полезно совмещать с --auto и --hosts
|
||||||
|
|
||||||
-s, --split <n[+s]>
|
-s, --split <n[+s]>
|
||||||
Разбить запрос по указанному смещению
|
Разбить запрос по указанному смещению
|
||||||
После числа можно добавить флаг:
|
После числа можно добавить флаг:
|
||||||
|
Loading…
Reference in New Issue
Block a user