mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-30 05:50:53 +03:00
Compare commits
2 Commits
2e6ddc4756
...
e8f6b89efd
Author | SHA1 | Date | |
---|---|---|---|
|
e8f6b89efd | ||
|
51c0d1ce3c |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -274,3 +274,12 @@ v56
|
|||||||
|
|
||||||
tpws: mss fooling
|
tpws: mss fooling
|
||||||
tpws: multi thread resolver. eliminates blocks related to hostname resolve.
|
tpws: multi thread resolver. eliminates blocks related to hostname resolve.
|
||||||
|
|
||||||
|
v57
|
||||||
|
|
||||||
|
tpws: --nosplice option
|
||||||
|
nfqws: postnat fixes
|
||||||
|
nfqws: --dpi-desync-start option
|
||||||
|
nfqws: packet delay for kyber TLS and QUIC
|
||||||
|
nfqws: --dpi-desync-retrans obsolete
|
||||||
|
nfqws: --qnum is mandatory, no more default queue 0
|
||||||
|
@ -173,7 +173,6 @@ nfqws takes the following parameters:
|
|||||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; auto ttl mode for both ipv4 and ipv6. default: 1:3-20
|
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; auto ttl mode for both ipv4 and ipv6. default: 1:3-20
|
||||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only
|
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only
|
||||||
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
|
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
|
||||||
--dpi-desync-retrans=0|1 ; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission
|
|
||||||
--dpi-desync-repeats=<N> ; send every desync packet N times
|
--dpi-desync-repeats=<N> ; send every desync packet N times
|
||||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
|
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
|
||||||
--dpi-desync-split-pos=<1..9216> ; data payload split position
|
--dpi-desync-split-pos=<1..9216> ; data payload split position
|
||||||
@ -263,10 +262,7 @@ add tcp option **MD5 signature**. All of them have their own disadvantages :
|
|||||||
|
|
||||||
`--dpi-desync-fooling` takes multiple comma separated values.
|
`--dpi-desync-fooling` takes multiple comma separated values.
|
||||||
|
|
||||||
For fake,rst,rstack modes original packet can be sent after the fake one or just dropped.
|
For fake,rst,rstack modes original packet is sent after the fake.
|
||||||
If its dropped OS will perform first retransmission after 0.2 sec, then the delay increases exponentially.
|
|
||||||
Delay can help to make sure fake and original packets are properly ordered and processed on DPI.
|
|
||||||
When `dpi-desync-retrans=1` its mandatory to use connbytes in iptables rule. Otherwise loop happens.
|
|
||||||
|
|
||||||
Disorder mode splits original packet and sends packets in the following order :
|
Disorder mode splits original packet and sends packets in the following order :
|
||||||
1. 2nd segment
|
1. 2nd segment
|
||||||
@ -461,6 +457,16 @@ If the connection falls out of the conntrack and --dpi-desync-cutoff is set, dpi
|
|||||||
|
|
||||||
Set conntrack timeouts appropriately.
|
Set conntrack timeouts appropriately.
|
||||||
|
|
||||||
|
### Reassemble
|
||||||
|
|
||||||
|
nfqws supports reassemble of TLS and QUIC ClientHello.
|
||||||
|
They can consist of multiple packets if kyber crypto is used (default from chromium 124).
|
||||||
|
Chromium randomizes TLS fingerprint. SNI can be in any packet.
|
||||||
|
Stateful DPIs usually reassemble all packets in the request then apply block decision.
|
||||||
|
If nfqws receives a partial ClientHello it begins reassemble session. Packets are delayed until it's finished.
|
||||||
|
Then the first packet goes through desync using fully reassembled message. Other packets are sent
|
||||||
|
without desync. On any error reassemble is cancelled and all delayed packets are sent immediately without desync.
|
||||||
|
|
||||||
### UDP support
|
### UDP support
|
||||||
|
|
||||||
UDP attacks are limited. Its not possible to fragment UDP on transport level, only on network (ip) level.
|
UDP attacks are limited. Its not possible to fragment UDP on transport level, only on network (ip) level.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
zapret v.56
|
zapret v.57
|
||||||
|
|
||||||
English
|
English
|
||||||
-------
|
-------
|
||||||
@ -246,7 +246,6 @@ nfqws
|
|||||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
|
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
|
||||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
|
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
|
||||||
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||||||
--dpi-desync-retrans=0|1 ; (только для fake,rst,rstack) 0(default)=отправлять оригинал следом за фейком 1=дропать оригинал, заставляя ОС выполнять ретрансмиссию через 0.2 сек
|
|
||||||
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
||||||
--dpi-desync-skip-nosni=0| 1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
--dpi-desync-skip-nosni=0| 1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||||
--dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции
|
--dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции
|
||||||
@ -352,11 +351,7 @@ fakeknown отличается от fake тем, что применяется
|
|||||||
|
|
||||||
Режимы дурения могут сочетаться в любых комбинациях. --dpi-desync-fooling берет множество значений через запятую.
|
Режимы дурения могут сочетаться в любых комбинациях. --dpi-desync-fooling берет множество значений через запятую.
|
||||||
|
|
||||||
Для режимов fake, rst, rstack после фейка отправляем оригинальный пакет. Можно его отправить сразу следом за фейком, а можно его просто дропнуть.
|
Для режимов fake, rst, rstack после фейка отправляем оригинальный пакет.
|
||||||
Если его дропнуть, ОС выполнит ретрансмиссию. Первая ретрансмиссия случается через 0.2 сек, потом задержка увеличивается экспоненциально.
|
|
||||||
Задержка может дать надежную гарантию, что пакеты пойдут именно в нужном порядке и будут именно в нем обработаны на DPI.
|
|
||||||
По умолчанию используется первый вариант, т.к. он быстрее.
|
|
||||||
При использовании dpi-desync-retrans=1 обязательно вставлять ограничитель connbytes в iptables, иначе получим зацикливание.
|
|
||||||
|
|
||||||
Режим disorder делит оригинальный пакет на 2 части и отправляет следующую комбинацию в указанном порядке :
|
Режим disorder делит оригинальный пакет на 2 части и отправляет следующую комбинацию в указанном порядке :
|
||||||
1. 2-я часть пакета
|
1. 2-я часть пакета
|
||||||
@ -529,16 +524,17 @@ window size итоговый размер окна стал максимальн
|
|||||||
На склонных к бездействию соединениях следует изменить таймауты conntrack.
|
На склонных к бездействию соединениях следует изменить таймауты conntrack.
|
||||||
Если соединение выпало из conntrack и задана опция --dpi-desync-cutoff, dpi desync применяться не будет.
|
Если соединение выпало из conntrack и задана опция --dpi-desync-cutoff, dpi desync применяться не будет.
|
||||||
|
|
||||||
РЕАССЕМБЛИНГ TCP
|
РЕАССЕМБЛИНГ
|
||||||
nfqws поддерживает реассемблинг некоторых видов tcp запросов.
|
nfqws поддерживает реассемблинг некоторых видов запросов.
|
||||||
На текущий момент это TLS ClientHello. Он бывает длинным, если в chrome включить пост-квантовую
|
На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую
|
||||||
криптографию tls-kyber, и занимает как правило 2 пакета.
|
криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124.
|
||||||
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
|
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
|
||||||
попасть в 1 или 2 пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
|
попасть любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
|
||||||
принимает решение о блокировке.
|
принимает решение о блокировке.
|
||||||
nfqws реагирует десинхронизацией на каждый пакет из TLSClientHello, если задана опция
|
В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты
|
||||||
--dpi-desync-skip-nosni=0. В противном случае десинхронизация идет на сам пакет,
|
задерживаются и не отсылаются до ее окончания. По окончании сборки первый пакет проходит через десинхронизацию
|
||||||
включающий SNI, и все последующие.
|
на основании полностью собранного ClientHello. Остальные пакеты отсылаются без десинхронизации.
|
||||||
|
При любой ошибке в процессе сборки задержанные пакеты немедленно отсылаются в сеть, а десинхронизация отменяется.
|
||||||
|
|
||||||
ПОДДЕРЖКА UDP
|
ПОДДЕРЖКА UDP
|
||||||
Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip.
|
Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip.
|
||||||
|
@ -37,6 +37,7 @@ static void ConntrackClearTrack(t_ctrack *track)
|
|||||||
{
|
{
|
||||||
ConntrackClearHostname(track);
|
ConntrackClearHostname(track);
|
||||||
ReasmClear(&track->reasm_orig);
|
ReasmClear(&track->reasm_orig);
|
||||||
|
rawpacket_queue_destroy(&track->delayed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ConntrackFreeElem(t_conntrack_pool *elem)
|
static void ConntrackFreeElem(t_conntrack_pool *elem)
|
||||||
@ -99,19 +100,24 @@ static void ConntrackInitTrack(t_ctrack *t)
|
|||||||
memset(t,0,sizeof(*t));
|
memset(t,0,sizeof(*t));
|
||||||
t->scale_orig = t->scale_reply = SCALE_NONE;
|
t->scale_orig = t->scale_reply = SCALE_NONE;
|
||||||
time(&t->t_start);
|
time(&t->t_start);
|
||||||
|
rawpacket_queue_init(&t->delayed);
|
||||||
|
}
|
||||||
|
static void ConntrackReInitTrack(t_ctrack *t)
|
||||||
|
{
|
||||||
|
ConntrackClearTrack(t);
|
||||||
|
ConntrackInitTrack(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||||
{
|
{
|
||||||
t_conntrack_pool *new;
|
t_conntrack_pool *ctnew;
|
||||||
if (!(new = malloc(sizeof(*new)))) return NULL;
|
if (!(ctnew = malloc(sizeof(*ctnew)))) return NULL;
|
||||||
new->conn = *c;
|
ctnew->conn = *c;
|
||||||
oom = false;
|
oom = false;
|
||||||
HASH_ADD(hh, *pp, conn, sizeof(*c), new);
|
HASH_ADD(hh, *pp, conn, sizeof(*c), ctnew);
|
||||||
if (oom) { free(new); return NULL; }
|
if (oom) { free(ctnew); return NULL; }
|
||||||
ConntrackInitTrack(&new->track);
|
ConntrackInitTrack(&ctnew->track);
|
||||||
return new;
|
return ctnew;
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||||
@ -135,12 +141,12 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
{
|
{
|
||||||
if (tcp_syn_segment(tcphdr))
|
if (tcp_syn_segment(tcphdr))
|
||||||
{
|
{
|
||||||
if (t->state!=SYN) ConntrackInitTrack(t); // erase current entry
|
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||||
t->seq0 = htonl(tcphdr->th_seq);
|
t->seq0 = htonl(tcphdr->th_seq);
|
||||||
}
|
}
|
||||||
else if (tcp_synack_segment(tcphdr))
|
else if (tcp_synack_segment(tcphdr))
|
||||||
{
|
{
|
||||||
if (t->state!=SYN) ConntrackInitTrack(t); // erase current entry
|
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
|
||||||
if (!t->seq0) t->seq0 = htonl(tcphdr->th_ack)-1;
|
if (!t->seq0) t->seq0 = htonl(tcphdr->th_ack)-1;
|
||||||
t->ack0 = htonl(tcphdr->th_seq);
|
t->ack0 = htonl(tcphdr->th_seq);
|
||||||
}
|
}
|
||||||
@ -192,6 +198,35 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
|||||||
time(&t->t_last);
|
time(&t->t_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||||
|
{
|
||||||
|
bool b_rev;
|
||||||
|
t_conn conn,connswp;
|
||||||
|
t_conntrack_pool *ctr;
|
||||||
|
|
||||||
|
ConntrackExtractConn(&conn,false,ip,ip6,tcphdr,udphdr);
|
||||||
|
if ((ctr=ConntrackPoolSearch(*pp,&conn)))
|
||||||
|
{
|
||||||
|
if (bReverse) *bReverse = false;
|
||||||
|
if (ctrack) *ctrack = &ctr->track;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connswap(&conn,&connswp);
|
||||||
|
if ((ctr=ConntrackPoolSearch(*pp,&connswp)))
|
||||||
|
{
|
||||||
|
if (bReverse) *bReverse = true;
|
||||||
|
if (ctrack) *ctrack = &ctr->track;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||||
|
{
|
||||||
|
return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse);
|
||||||
|
}
|
||||||
|
|
||||||
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||||
{
|
{
|
||||||
@ -343,9 +378,18 @@ bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start)
|
|||||||
reasm->seq = seq_start;
|
reasm->seq = seq_start;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool ReasmResize(t_reassemble *reasm, size_t new_size)
|
||||||
|
{
|
||||||
|
uint8_t *p = realloc(reasm->packet, new_size);
|
||||||
|
if (!p) return false;
|
||||||
|
reasm->packet = p;
|
||||||
|
reasm->size = new_size;
|
||||||
|
if (reasm->size_present > new_size) reasm->size_present = new_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
|
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
|
||||||
{
|
{
|
||||||
if (reasm->seq!=seq) return false; // fail session if out of sequence
|
if (seq!=-1 && reasm->seq!=seq) return false; // fail session if out of sequence
|
||||||
|
|
||||||
size_t szcopy;
|
size_t szcopy;
|
||||||
szcopy = reasm->size - reasm->size_present;
|
szcopy = reasm->size - reasm->size_present;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <netinet/udp.h>
|
#include <netinet/udp.h>
|
||||||
|
|
||||||
|
#include "packet_queue.h"
|
||||||
|
|
||||||
//#define HASH_BLOOM 20
|
//#define HASH_BLOOM 20
|
||||||
#define HASH_NONFATAL_OOM 1
|
#define HASH_NONFATAL_OOM 1
|
||||||
#undef HASH_FUNCTION
|
#undef HASH_FUNCTION
|
||||||
@ -63,7 +65,7 @@ typedef struct
|
|||||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
||||||
|
|
||||||
uint8_t req_retrans_counter; // number of request retransmissions
|
uint8_t req_retrans_counter; // number of request retransmissions
|
||||||
bool req_seq_start_present, req_seq_present;
|
bool req_seq_present,req_seq_finalized;
|
||||||
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
||||||
|
|
||||||
uint8_t autottl;
|
uint8_t autottl;
|
||||||
@ -71,10 +73,11 @@ typedef struct
|
|||||||
bool b_cutoff; // mark for deletion
|
bool b_cutoff; // mark for deletion
|
||||||
bool b_wssize_cutoff, b_desync_cutoff;
|
bool b_wssize_cutoff, b_desync_cutoff;
|
||||||
|
|
||||||
t_reassemble reasm_orig;
|
|
||||||
|
|
||||||
t_l7proto l7proto;
|
t_l7proto l7proto;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
|
|
||||||
|
t_reassemble reasm_orig;
|
||||||
|
struct rawpacket_tailhead delayed;
|
||||||
} t_ctrack;
|
} t_ctrack;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -94,6 +97,8 @@ typedef struct
|
|||||||
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
|
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
|
||||||
void ConntrackPoolDestroy(t_conntrack *p);
|
void ConntrackPoolDestroy(t_conntrack *p);
|
||||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
|
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
|
||||||
|
// do not create, do not update. only find existing
|
||||||
|
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse);
|
||||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||||
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||||
void ConntrackPoolDump(const t_conntrack *p);
|
void ConntrackPoolDump(const t_conntrack *p);
|
||||||
@ -101,6 +106,7 @@ void ConntrackPoolPurge(t_conntrack *p);
|
|||||||
void ConntrackClearHostname(t_ctrack *track);
|
void ConntrackClearHostname(t_ctrack *track);
|
||||||
|
|
||||||
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start);
|
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start);
|
||||||
|
bool ReasmResize(t_reassemble *reasm, size_t new_size);
|
||||||
void ReasmClear(t_reassemble *reasm);
|
void ReasmClear(t_reassemble *reasm);
|
||||||
// false means reassemble session has failed and we should ReasmClear() it
|
// false means reassemble session has failed and we should ReasmClear() it
|
||||||
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len);
|
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "params.h"
|
||||||
|
|
||||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||||
{
|
{
|
||||||
@ -840,6 +840,64 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
|
|||||||
// we have garbage
|
// we have garbage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void proto_dissect_l3l4(
|
||||||
|
uint8_t *data, size_t len,
|
||||||
|
struct ip **ip, struct ip6_hdr **ip6,
|
||||||
|
uint8_t *proto,
|
||||||
|
struct tcphdr **tcp,
|
||||||
|
struct udphdr **udp,
|
||||||
|
size_t *transport_len,
|
||||||
|
uint8_t **data_payload, size_t *len_payload)
|
||||||
|
{
|
||||||
|
*ip = NULL;
|
||||||
|
*ip6 = NULL;
|
||||||
|
*proto = 0;
|
||||||
|
*tcp = NULL;
|
||||||
|
*transport_len = 0;
|
||||||
|
*udp = NULL;
|
||||||
|
*data_payload = NULL;
|
||||||
|
*len_payload = 0;
|
||||||
|
|
||||||
|
if (proto_check_ipv4(data, len))
|
||||||
|
{
|
||||||
|
*ip = (struct ip *) data;
|
||||||
|
*proto = (*ip)->ip_p;
|
||||||
|
proto_skip_ipv4(&data, &len);
|
||||||
|
}
|
||||||
|
else if (proto_check_ipv6(data, len))
|
||||||
|
{
|
||||||
|
*ip6 = (struct ip6_hdr *) data;
|
||||||
|
proto_skip_ipv6(&data, &len, proto, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
||||||
|
{
|
||||||
|
*tcp = (struct tcphdr *) data;
|
||||||
|
*transport_len = len;
|
||||||
|
|
||||||
|
proto_skip_tcp(&data, &len);
|
||||||
|
|
||||||
|
*data_payload = data;
|
||||||
|
*len_payload = len;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (*proto==IPPROTO_UDP && proto_check_udp(data, len))
|
||||||
|
{
|
||||||
|
*udp = (struct udphdr *) data;
|
||||||
|
*transport_len = len;
|
||||||
|
|
||||||
|
proto_skip_udp(&data, &len);
|
||||||
|
|
||||||
|
*data_payload = data;
|
||||||
|
*len_payload = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool tcp_synack_segment(const struct tcphdr *tcphdr)
|
bool tcp_synack_segment(const struct tcphdr *tcphdr)
|
||||||
{
|
{
|
||||||
/* check for set bits in TCP hdr */
|
/* check for set bits in TCP hdr */
|
||||||
@ -1204,6 +1262,20 @@ nofix:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rawsend_rp(const struct rawpacket *rp)
|
||||||
|
{
|
||||||
|
return rawsend((struct sockaddr*)&rp->dst,rp->fwmark,rp->ifout,rp->packet,rp->len);
|
||||||
|
}
|
||||||
|
bool rawsend_queue(struct rawpacket_tailhead *q)
|
||||||
|
{
|
||||||
|
struct rawpacket *rp;
|
||||||
|
bool b;
|
||||||
|
for (b=true; (rp=rawpacket_dequeue(q)) ; rawpacket_free(rp))
|
||||||
|
b &= rawsend_rp(rp);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
|
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
|
||||||
// ttl = TTL of incoming packet
|
// ttl = TTL of incoming packet
|
||||||
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
||||||
@ -1233,3 +1305,27 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
|||||||
|
|
||||||
return fake;
|
return fake;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||||
|
{
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||||
|
#else
|
||||||
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||||
|
#endif
|
||||||
|
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
|
||||||
|
}
|
||||||
|
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||||
|
{
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||||
|
#else
|
||||||
|
// if original packet was tampered earlier it needs checksum fixed
|
||||||
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||||
|
#endif
|
||||||
|
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include "packet_queue.h"
|
||||||
|
|
||||||
#ifndef IPPROTO_DIVERT
|
#ifndef IPPROTO_DIVERT
|
||||||
#define IPPROTO_DIVERT 258
|
#define IPPROTO_DIVERT 258
|
||||||
#endif
|
#endif
|
||||||
@ -39,6 +41,12 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
|||||||
|
|
||||||
#define SCALE_NONE ((uint8_t)-1)
|
#define SCALE_NONE ((uint8_t)-1)
|
||||||
|
|
||||||
|
#define VERDICT_PASS 0
|
||||||
|
#define VERDICT_MODIFY 1
|
||||||
|
#define VERDICT_DROP 2
|
||||||
|
#define VERDICT_MASK 3
|
||||||
|
#define VERDICT_NOCSUM 4
|
||||||
|
|
||||||
// seq and wsize have network byte order
|
// seq and wsize have network byte order
|
||||||
bool prepare_tcp_segment4(
|
bool prepare_tcp_segment4(
|
||||||
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
const struct sockaddr_in *src, const struct sockaddr_in *dst,
|
||||||
@ -136,6 +144,9 @@ bool tcp_has_fastopen(const struct tcphdr *tcp);
|
|||||||
|
|
||||||
// auto creates internal socket and uses it for subsequent calls
|
// auto creates internal socket and uses it for subsequent calls
|
||||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len);
|
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len);
|
||||||
|
bool rawsend_rp(const struct rawpacket *rp);
|
||||||
|
// return trues if all packets were send successfully
|
||||||
|
bool rawsend_queue(struct rawpacket_tailhead *q);
|
||||||
// should pre-do it if dropping privileges. otherwise its not necessary
|
// should pre-do it if dropping privileges. otherwise its not necessary
|
||||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
||||||
// cleans up socket autocreated by rawsend
|
// cleans up socket autocreated by rawsend
|
||||||
@ -158,6 +169,14 @@ bool proto_check_tcp(const uint8_t *data, size_t len);
|
|||||||
void proto_skip_tcp(uint8_t **data, size_t *len);
|
void proto_skip_tcp(uint8_t **data, size_t *len);
|
||||||
bool proto_check_udp(const uint8_t *data, size_t len);
|
bool proto_check_udp(const uint8_t *data, size_t len);
|
||||||
void proto_skip_udp(uint8_t **data, size_t *len);
|
void proto_skip_udp(uint8_t **data, size_t *len);
|
||||||
|
void proto_dissect_l3l4(
|
||||||
|
uint8_t *data, size_t len,
|
||||||
|
struct ip **ip, struct ip6_hdr **ip6,
|
||||||
|
uint8_t *proto,
|
||||||
|
struct tcphdr **tcp,
|
||||||
|
struct udphdr **udp,
|
||||||
|
size_t *transport_len,
|
||||||
|
uint8_t **data_payload, size_t *len_payload);
|
||||||
|
|
||||||
bool tcp_synack_segment(const struct tcphdr *tcphdr);
|
bool tcp_synack_segment(const struct tcphdr *tcphdr);
|
||||||
bool tcp_syn_segment(const struct tcphdr *tcphdr);
|
bool tcp_syn_segment(const struct tcphdr *tcphdr);
|
||||||
@ -177,3 +196,6 @@ typedef struct
|
|||||||
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
|
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
|
||||||
|
|
||||||
uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
|
uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
|
||||||
|
|
||||||
|
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
|
||||||
|
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
|
||||||
|
634
nfq/desync.c
634
nfq/desync.c
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "darkmagic.h"
|
#include "darkmagic.h"
|
||||||
#include "nfqws.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -51,5 +50,4 @@ bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
|
|||||||
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
|
||||||
|
|
||||||
void desync_init(void);
|
void desync_init(void);
|
||||||
uint8_t dpi_desync_tcp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt, struct ip *ip, struct ip6_hdr *ip6hdr, struct tcphdr *tcphdr, size_t len_tcp, uint8_t *data_payload, size_t len_payload);
|
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);
|
||||||
uint8_t dpi_desync_udp_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt, struct ip *ip, struct ip6_hdr *ip6hdr, struct udphdr *udphdr, uint8_t *data_payload, size_t len_payload);
|
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <time.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "params.h"
|
||||||
|
|
||||||
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
||||||
{
|
{
|
||||||
size_t k;
|
size_t k;
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
#include "params.h"
|
|
||||||
|
|
||||||
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit);
|
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit);
|
||||||
char *strncasestr(const char *s,const char *find, size_t slen);
|
char *strncasestr(const char *s,const char *find, size_t slen);
|
||||||
|
236
nfq/nfqws.c
236
nfq/nfqws.c
@ -79,108 +79,16 @@ static void onusr2(int sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
|
static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
|
||||||
{
|
{
|
||||||
struct ip *ip = NULL;
|
|
||||||
struct ip6_hdr *ip6hdr = NULL;
|
|
||||||
struct tcphdr *tcphdr = NULL;
|
|
||||||
struct udphdr *udphdr = NULL;
|
|
||||||
size_t len = *len_pkt, len_with_th;
|
|
||||||
uint8_t *data = data_pkt;
|
|
||||||
uint8_t res = VERDICT_PASS;
|
|
||||||
uint8_t proto;
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (*mark & params.desync_fwmark)
|
if (*mark & params.desync_fwmark)
|
||||||
{
|
{
|
||||||
DLOG("ignoring generated packet\n")
|
DLOG("ignoring generated packet\n")
|
||||||
return res;
|
return VERDICT_PASS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return dpi_desync_packet(*mark, ifout, data_pkt, len_pkt);
|
||||||
if (proto_check_ipv4(data, len))
|
|
||||||
{
|
|
||||||
ip = (struct ip *) data;
|
|
||||||
proto = ip->ip_p;
|
|
||||||
proto_skip_ipv4(&data, &len);
|
|
||||||
if (params.debug)
|
|
||||||
{
|
|
||||||
printf("IP4: ");
|
|
||||||
print_ip(ip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (proto_check_ipv6(data, len))
|
|
||||||
{
|
|
||||||
ip6hdr = (struct ip6_hdr *) data;
|
|
||||||
proto_skip_ipv6(&data, &len, &proto, NULL);
|
|
||||||
if (params.debug)
|
|
||||||
{
|
|
||||||
printf("IP6: ");
|
|
||||||
print_ip6hdr(ip6hdr, proto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// not ipv6 and not ipv4
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
|
||||||
{
|
|
||||||
tcphdr = (struct tcphdr *) data;
|
|
||||||
len_with_th = len;
|
|
||||||
proto_skip_tcp(&data, &len);
|
|
||||||
|
|
||||||
if (params.debug)
|
|
||||||
{
|
|
||||||
printf(" ");
|
|
||||||
print_tcphdr(tcphdr);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len) { DLOG("TCP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
|
||||||
|
|
||||||
res = dpi_desync_tcp_packet(*mark, ifout, data_pkt, len_pkt, ip, ip6hdr, tcphdr, len_with_th, data, len);
|
|
||||||
// in my FreeBSD divert tests only ipv4 packets were reinjected with correct checksum
|
|
||||||
// ipv6 packets were with incorrect checksum
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
|
||||||
if (!(res & VERDICT_NOCSUM) && ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr && (res & VERDICT_MASK)==VERDICT_PASS))
|
|
||||||
#else
|
|
||||||
if (!(res & VERDICT_NOCSUM) && (res & VERDICT_MASK)==VERDICT_MODIFY)
|
|
||||||
#endif
|
|
||||||
tcp_fix_checksum(tcphdr,len_with_th,ip,ip6hdr);
|
|
||||||
}
|
|
||||||
else if (proto==IPPROTO_UDP && proto_check_udp(data, len))
|
|
||||||
{
|
|
||||||
udphdr = (struct udphdr *) data;
|
|
||||||
len_with_th = len;
|
|
||||||
proto_skip_udp(&data, &len);
|
|
||||||
|
|
||||||
if (params.debug)
|
|
||||||
{
|
|
||||||
printf(" ");
|
|
||||||
print_udphdr(udphdr);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
if (len) { DLOG("UDP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
|
||||||
|
|
||||||
res = dpi_desync_udp_packet(*mark, ifout, data_pkt, len_pkt, ip, ip6hdr, udphdr, data, len);
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
|
||||||
if (!(res & VERDICT_NOCSUM) && ((res & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr && (res & VERDICT_MASK)==VERDICT_PASS))
|
|
||||||
#else
|
|
||||||
if (!(res & VERDICT_NOCSUM) && (res & VERDICT_MASK)==VERDICT_MODIFY)
|
|
||||||
#endif
|
|
||||||
udp_fix_checksum(udphdr,len_with_th,ip,ip6hdr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (params.debug) printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -214,8 +122,8 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
|||||||
if (ilen >= 0)
|
if (ilen >= 0)
|
||||||
{
|
{
|
||||||
len = ilen;
|
len = ilen;
|
||||||
uint8_t res = processPacketData(&mark, ifout, data, &len);
|
uint8_t verdict = processPacketData(&mark, ifout, data, &len);
|
||||||
switch(res & VERDICT_MASK)
|
switch(verdict & VERDICT_MASK)
|
||||||
{
|
{
|
||||||
case VERDICT_MODIFY:
|
case VERDICT_MODIFY:
|
||||||
DLOG("packet: id=%d pass modified. len=%zu\n", id, len);
|
DLOG("packet: id=%d pass modified. len=%zu\n", id, len);
|
||||||
@ -438,16 +346,16 @@ static int dvt_main(void)
|
|||||||
else if (rd>0)
|
else if (rd>0)
|
||||||
{
|
{
|
||||||
uint32_t mark=0;
|
uint32_t mark=0;
|
||||||
uint8_t res;
|
uint8_t verdict;
|
||||||
size_t len = rd;
|
size_t len = rd;
|
||||||
|
|
||||||
DLOG("packet: id=%u len=%zu\n", id, len)
|
DLOG("packet: id=%u len=%zu\n", id, len)
|
||||||
res = processPacketData(&mark, NULL, buf, &len);
|
verdict = processPacketData(&mark, NULL, buf, &len);
|
||||||
switch (res & VERDICT_MASK)
|
switch (verdict & VERDICT_MASK)
|
||||||
{
|
{
|
||||||
case VERDICT_PASS:
|
case VERDICT_PASS:
|
||||||
case VERDICT_MODIFY:
|
case VERDICT_MODIFY:
|
||||||
if ((res & VERDICT_MASK)==VERDICT_PASS)
|
if ((verdict & VERDICT_MASK)==VERDICT_PASS)
|
||||||
DLOG("packet: id=%u reinject unmodified\n", id)
|
DLOG("packet: id=%u reinject unmodified\n", id)
|
||||||
else
|
else
|
||||||
DLOG("packet: id=%u reinject modified len=%zu\n", id, len)
|
DLOG("packet: id=%u reinject modified len=%zu\n", id, len)
|
||||||
@ -544,9 +452,6 @@ static void exithelp(void)
|
|||||||
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %u:%u-%u\n"
|
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]]\t; auto ttl mode for both ipv4 and ipv6. default: %u:%u-%u\n"
|
||||||
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only\n"
|
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only\n"
|
||||||
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2\n"
|
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2\n"
|
||||||
#ifdef __linux__
|
|
||||||
" --dpi-desync-retrans=0|1\t\t\t; 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission\n"
|
|
||||||
#endif
|
|
||||||
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
|
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
|
||||||
" --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n"
|
" --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n"
|
||||||
" --dpi-desync-split-pos=<1..%u>\t\t; data payload split position\n"
|
" --dpi-desync-split-pos=<1..%u>\t\t; data payload split position\n"
|
||||||
@ -765,38 +670,37 @@ int main(int argc, char **argv)
|
|||||||
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=18
|
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=18
|
||||||
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=19
|
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=19
|
||||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=20
|
{"dpi-desync-fooling",required_argument,0,0}, // optidx=20
|
||||||
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=21
|
{"dpi-desync-repeats",required_argument,0,0}, // optidx=21
|
||||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=22
|
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=22
|
||||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=23
|
{"dpi-desync-split-pos",required_argument,0,0},// optidx=23
|
||||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=24
|
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=24
|
||||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=25
|
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=25
|
||||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=26
|
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=26
|
||||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=27
|
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=27
|
||||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=28
|
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=28
|
||||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=29
|
{"dpi-desync-fake-http",required_argument,0,0},// optidx=29
|
||||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=30
|
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=30
|
||||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=31
|
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=31
|
||||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=32
|
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=32
|
||||||
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=33
|
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=33
|
||||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=34
|
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=34
|
||||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=35
|
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=35
|
||||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=36
|
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=36
|
||||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=37
|
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=37
|
||||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=38
|
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=38
|
||||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=39
|
{"dpi-desync-cutoff",required_argument,0,0},// optidx=39
|
||||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=40
|
{"dpi-desync-start",required_argument,0,0},// optidx=40
|
||||||
{"dpi-desync-start",required_argument,0,0},// optidx=41
|
{"hostlist",required_argument,0,0}, // optidx=41
|
||||||
{"hostlist",required_argument,0,0}, // optidx=42
|
{"hostlist-exclude",required_argument,0,0}, // optidx=42
|
||||||
{"hostlist-exclude",required_argument,0,0}, // optidx=43
|
{"hostlist-auto",required_argument,0,0}, // optidx=43
|
||||||
{"hostlist-auto",required_argument,0,0}, // optidx=44
|
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=44
|
||||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=45
|
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=45
|
||||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=46
|
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=46
|
||||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=47
|
{"hostlist-auto-debug",required_argument,0,0}, // optidx=47
|
||||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=48
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"bind-fix4",no_argument,0,0}, // optidx=49
|
{"bind-fix4",no_argument,0,0}, // optidx=48
|
||||||
{"bind-fix6",no_argument,0,0}, // optidx=50
|
{"bind-fix6",no_argument,0,0}, // optidx=49
|
||||||
#endif
|
#endif
|
||||||
{NULL,0,NULL,0}
|
{NULL,0,NULL,0}
|
||||||
};
|
};
|
||||||
@ -1012,32 +916,24 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 21: /* dpi-desync-retrans */
|
case 21: /* dpi-desync-repeats */
|
||||||
#ifdef __linux__
|
|
||||||
params.desync_retrans = !optarg || atoi(optarg);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "dpi-desync-retrans is only supported in linux\n");
|
|
||||||
exit_clean(1);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 22: /* dpi-desync-repeats */
|
|
||||||
if (sscanf(optarg,"%u",¶ms.desync_repeats)<1 || !params.desync_repeats || params.desync_repeats>20)
|
if (sscanf(optarg,"%u",¶ms.desync_repeats)<1 || !params.desync_repeats || params.desync_repeats>20)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-repeats must be within 1..20\n");
|
fprintf(stderr, "dpi-desync-repeats must be within 1..20\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 23: /* dpi-desync-skip-nosni */
|
case 22: /* dpi-desync-skip-nosni */
|
||||||
params.desync_skip_nosni = !optarg || atoi(optarg);
|
params.desync_skip_nosni = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 24: /* dpi-desync-split-pos */
|
case 23: /* dpi-desync-split-pos */
|
||||||
if (sscanf(optarg,"%u",¶ms.desync_split_pos)<1 || params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN)
|
if (sscanf(optarg,"%u",¶ms.desync_split_pos)<1 || params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-split-pos must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
fprintf(stderr, "dpi-desync-split-pos must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 25: /* dpi-desync-ipfrag-pos-tcp */
|
case 24: /* dpi-desync-ipfrag-pos-tcp */
|
||||||
if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_tcp)<1 || params.desync_ipfrag_pos_tcp<1 || params.desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
|
if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_tcp)<1 || params.desync_ipfrag_pos_tcp<1 || params.desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
fprintf(stderr, "dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||||
@ -1049,7 +945,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 26: /* dpi-desync-ipfrag-pos-udp */
|
case 25: /* dpi-desync-ipfrag-pos-udp */
|
||||||
if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_udp)<1 || params.desync_ipfrag_pos_udp<1 || params.desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
|
if (sscanf(optarg,"%u",¶ms.desync_ipfrag_pos_udp)<1 || params.desync_ipfrag_pos_udp<1 || params.desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
fprintf(stderr, "dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||||
@ -1061,63 +957,63 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 27: /* dpi-desync-badseq-increments */
|
case 26: /* dpi-desync-badseq-increments */
|
||||||
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_increment))
|
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_increment))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 28: /* dpi-desync-badack-increment */
|
case 27: /* dpi-desync-badack-increment */
|
||||||
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_ack_increment))
|
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_ack_increment))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
fprintf(stderr, "dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 29: /* dpi-desync-any-protocol */
|
case 28: /* dpi-desync-any-protocol */
|
||||||
params.desync_any_proto = !optarg || atoi(optarg);
|
params.desync_any_proto = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 30: /* dpi-desync-fake-http */
|
case 29: /* dpi-desync-fake-http */
|
||||||
params.fake_http_size = sizeof(params.fake_http);
|
params.fake_http_size = sizeof(params.fake_http);
|
||||||
load_file_or_exit(optarg,params.fake_http,¶ms.fake_http_size);
|
load_file_or_exit(optarg,params.fake_http,¶ms.fake_http_size);
|
||||||
break;
|
break;
|
||||||
case 31: /* dpi-desync-fake-tls */
|
case 30: /* dpi-desync-fake-tls */
|
||||||
params.fake_tls_size = sizeof(params.fake_tls);
|
params.fake_tls_size = sizeof(params.fake_tls);
|
||||||
load_file_or_exit(optarg,params.fake_tls,¶ms.fake_tls_size);
|
load_file_or_exit(optarg,params.fake_tls,¶ms.fake_tls_size);
|
||||||
break;
|
break;
|
||||||
case 32: /* dpi-desync-fake-unknown */
|
case 31: /* dpi-desync-fake-unknown */
|
||||||
params.fake_unknown_size = sizeof(params.fake_unknown);
|
params.fake_unknown_size = sizeof(params.fake_unknown);
|
||||||
load_file_or_exit(optarg,params.fake_unknown,¶ms.fake_unknown_size);
|
load_file_or_exit(optarg,params.fake_unknown,¶ms.fake_unknown_size);
|
||||||
break;
|
break;
|
||||||
case 33: /* dpi-desync-fake-syndata */
|
case 32: /* dpi-desync-fake-syndata */
|
||||||
params.fake_syndata_size = sizeof(params.fake_syndata);
|
params.fake_syndata_size = sizeof(params.fake_syndata);
|
||||||
load_file_or_exit(optarg,params.fake_syndata,¶ms.fake_syndata_size);
|
load_file_or_exit(optarg,params.fake_syndata,¶ms.fake_syndata_size);
|
||||||
break;
|
break;
|
||||||
case 34: /* dpi-desync-fake-quic */
|
case 33: /* dpi-desync-fake-quic */
|
||||||
params.fake_quic_size = sizeof(params.fake_quic);
|
params.fake_quic_size = sizeof(params.fake_quic);
|
||||||
load_file_or_exit(optarg,params.fake_quic,¶ms.fake_quic_size);
|
load_file_or_exit(optarg,params.fake_quic,¶ms.fake_quic_size);
|
||||||
break;
|
break;
|
||||||
case 35: /* dpi-desync-fake-wireguard */
|
case 34: /* dpi-desync-fake-wireguard */
|
||||||
params.fake_wg_size = sizeof(params.fake_wg);
|
params.fake_wg_size = sizeof(params.fake_wg);
|
||||||
load_file_or_exit(optarg,params.fake_wg,¶ms.fake_wg_size);
|
load_file_or_exit(optarg,params.fake_wg,¶ms.fake_wg_size);
|
||||||
break;
|
break;
|
||||||
case 36: /* dpi-desync-fake-dht */
|
case 35: /* dpi-desync-fake-dht */
|
||||||
params.fake_dht_size = sizeof(params.fake_dht);
|
params.fake_dht_size = sizeof(params.fake_dht);
|
||||||
load_file_or_exit(optarg,params.fake_dht,¶ms.fake_dht_size);
|
load_file_or_exit(optarg,params.fake_dht,¶ms.fake_dht_size);
|
||||||
break;
|
break;
|
||||||
case 37: /* dpi-desync-fake-unknown-udp */
|
case 36: /* dpi-desync-fake-unknown-udp */
|
||||||
params.fake_unknown_udp_size = sizeof(params.fake_unknown_udp);
|
params.fake_unknown_udp_size = sizeof(params.fake_unknown_udp);
|
||||||
load_file_or_exit(optarg,params.fake_unknown_udp,¶ms.fake_unknown_udp_size);
|
load_file_or_exit(optarg,params.fake_unknown_udp,¶ms.fake_unknown_udp_size);
|
||||||
break;
|
break;
|
||||||
case 38: /* dpi-desync-udplen-increment */
|
case 37: /* dpi-desync-udplen-increment */
|
||||||
if (sscanf(optarg,"%d",¶ms.udplen_increment)<1 || params.udplen_increment>0x7FFF || params.udplen_increment<-0x8000)
|
if (sscanf(optarg,"%d",¶ms.udplen_increment)<1 || params.udplen_increment>0x7FFF || params.udplen_increment<-0x8000)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
fprintf(stderr, "dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 39: /* dpi-desync-udplen-pattern */
|
case 38: /* dpi-desync-udplen-pattern */
|
||||||
{
|
{
|
||||||
char buf[sizeof(params.udplen_pattern)];
|
char buf[sizeof(params.udplen_pattern)];
|
||||||
size_t sz=sizeof(buf);
|
size_t sz=sizeof(buf);
|
||||||
@ -1125,35 +1021,35 @@ int main(int argc, char **argv)
|
|||||||
fill_pattern(params.udplen_pattern,sizeof(params.udplen_pattern),buf,sz);
|
fill_pattern(params.udplen_pattern,sizeof(params.udplen_pattern),buf,sz);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 40: /* desync-cutoff */
|
case 39: /* desync-cutoff */
|
||||||
if (!parse_cutoff(optarg, ¶ms.desync_cutoff, ¶ms.desync_cutoff_mode))
|
if (!parse_cutoff(optarg, ¶ms.desync_cutoff, ¶ms.desync_cutoff_mode))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "invalid desync-cutoff value\n");
|
fprintf(stderr, "invalid desync-cutoff value\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 41: /* desync-start */
|
case 40: /* desync-start */
|
||||||
if (!parse_cutoff(optarg, ¶ms.desync_start, ¶ms.desync_start_mode))
|
if (!parse_cutoff(optarg, ¶ms.desync_start, ¶ms.desync_start_mode))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "invalid desync-start value\n");
|
fprintf(stderr, "invalid desync-start value\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 42: /* hostlist */
|
case 41: /* hostlist */
|
||||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "strlist_add failed\n");
|
fprintf(stderr, "strlist_add failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 43: /* hostlist-exclude */
|
case 42: /* hostlist-exclude */
|
||||||
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "strlist_add failed\n");
|
fprintf(stderr, "strlist_add failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 44: /* hostlist-auto */
|
case 43: /* hostlist-auto */
|
||||||
if (*params.hostlist_auto_filename)
|
if (*params.hostlist_auto_filename)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "only one auto hostlist is supported\n");
|
fprintf(stderr, "only one auto hostlist is supported\n");
|
||||||
@ -1184,7 +1080,7 @@ int main(int argc, char **argv)
|
|||||||
strncpy(params.hostlist_auto_filename, optarg, sizeof(params.hostlist_auto_filename));
|
strncpy(params.hostlist_auto_filename, optarg, sizeof(params.hostlist_auto_filename));
|
||||||
params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0';
|
params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0';
|
||||||
break;
|
break;
|
||||||
case 45: /* hostlist-auto-fail-threshold */
|
case 44: /* hostlist-auto-fail-threshold */
|
||||||
params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||||
if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20)
|
if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20)
|
||||||
{
|
{
|
||||||
@ -1192,7 +1088,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 46: /* hostlist-auto-fail-time */
|
case 45: /* hostlist-auto-fail-time */
|
||||||
params.hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
params.hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||||
if (params.hostlist_auto_fail_time<1)
|
if (params.hostlist_auto_fail_time<1)
|
||||||
{
|
{
|
||||||
@ -1200,7 +1096,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 47: /* hostlist-auto-retrans-threshold */
|
case 46: /* hostlist-auto-retrans-threshold */
|
||||||
params.hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
params.hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
||||||
if (params.hostlist_auto_retrans_threshold<2 || params.hostlist_auto_retrans_threshold>10)
|
if (params.hostlist_auto_retrans_threshold<2 || params.hostlist_auto_retrans_threshold>10)
|
||||||
{
|
{
|
||||||
@ -1208,7 +1104,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 48: /* hostlist-auto-debug */
|
case 47: /* hostlist-auto-debug */
|
||||||
{
|
{
|
||||||
FILE *F = fopen(optarg,"a+t");
|
FILE *F = fopen(optarg,"a+t");
|
||||||
if (!F)
|
if (!F)
|
||||||
@ -1224,10 +1120,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
case 49: /* bind-fix4 */
|
case 48: /* bind-fix4 */
|
||||||
params.bind_fix4 = true;
|
params.bind_fix4 = true;
|
||||||
break;
|
break;
|
||||||
case 50: /* bind-fix6 */
|
case 49: /* bind-fix6 */
|
||||||
params.bind_fix6 = true;
|
params.bind_fix6 = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERDICT_PASS 0
|
|
||||||
#define VERDICT_MODIFY 1
|
|
||||||
#define VERDICT_DROP 2
|
|
||||||
#define VERDICT_MASK 3
|
|
||||||
#define VERDICT_NOCSUM 4
|
|
||||||
|
67
nfq/packet_queue.c
Normal file
67
nfq/packet_queue.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "packet_queue.h"
|
||||||
|
|
||||||
|
void rawpacket_queue_init(struct rawpacket_tailhead *q)
|
||||||
|
{
|
||||||
|
TAILQ_INIT(q);
|
||||||
|
}
|
||||||
|
void rawpacket_free(struct rawpacket *rp)
|
||||||
|
{
|
||||||
|
if (rp) free(rp->packet);
|
||||||
|
free(rp);
|
||||||
|
}
|
||||||
|
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q)
|
||||||
|
{
|
||||||
|
struct rawpacket *rp;
|
||||||
|
rp = TAILQ_FIRST(q);
|
||||||
|
if (rp) TAILQ_REMOVE(q, rp, next);
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
|
||||||
|
{
|
||||||
|
struct rawpacket *rp;
|
||||||
|
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len)
|
||||||
|
{
|
||||||
|
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||||
|
if (!rp) return NULL;
|
||||||
|
|
||||||
|
rp->packet = malloc(len);
|
||||||
|
if (!rp->packet)
|
||||||
|
{
|
||||||
|
free(rp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rp->dst = *dst;
|
||||||
|
rp->fwmark = fwmark;
|
||||||
|
if (ifout)
|
||||||
|
{
|
||||||
|
strncpy(rp->ifout,ifout,sizeof(rp->ifout));
|
||||||
|
rp->ifout[sizeof(rp->ifout)-1]=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rp->ifout[0]=0;
|
||||||
|
memcpy(rp->packet,data,len);
|
||||||
|
rp->len=len;
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(q, rp, next);
|
||||||
|
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q)
|
||||||
|
{
|
||||||
|
const struct rawpacket *rp;
|
||||||
|
unsigned int ct=0;
|
||||||
|
TAILQ_FOREACH(rp, q, next) ct++;
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q)
|
||||||
|
{
|
||||||
|
return !TAILQ_FIRST(q);
|
||||||
|
}
|
26
nfq/packet_queue.h
Normal file
26
nfq/packet_queue.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
struct rawpacket
|
||||||
|
{
|
||||||
|
struct sockaddr_storage dst;
|
||||||
|
char ifout[IFNAMSIZ+1];
|
||||||
|
uint32_t fwmark;
|
||||||
|
size_t len;
|
||||||
|
uint8_t *packet;
|
||||||
|
TAILQ_ENTRY(rawpacket) next;
|
||||||
|
};
|
||||||
|
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
|
||||||
|
|
||||||
|
void rawpacket_queue_init(struct rawpacket_tailhead *q);
|
||||||
|
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
||||||
|
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
||||||
|
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
||||||
|
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len);
|
||||||
|
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||||
|
void rawpacket_free(struct rawpacket *rp);
|
@ -125,6 +125,20 @@ bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK)
|
|||||||
return len >= 6 && data[0] == 0x16 && data[1] == 0x03 && data[2] >= 0x01 && data[2] <= 0x03 && data[5] == 0x01 && (bPartialIsOK || TLSRecordLen(data) <= len);
|
return len >= 6 && data[0] == 0x16 && data[1] == 0x03 && data[2] >= 0x01 && data[2] <= 0x03 && data[5] == 0x01 && (bPartialIsOK || TLSRecordLen(data) <= len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t TLSHandshakeLen(const uint8_t *data)
|
||||||
|
{
|
||||||
|
return data[1] << 16 | data[2] << 8 | data[3]; // HandshakeProtocol length
|
||||||
|
}
|
||||||
|
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
return len>=4 && data[0]==0x01;
|
||||||
|
}
|
||||||
|
bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
return (4+TLSHandshakeLen(data))<=len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// bPartialIsOK=true - accept partial packets not containing the whole TLS message
|
// bPartialIsOK=true - accept partial packets not containing the whole TLS message
|
||||||
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK)
|
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK)
|
||||||
{
|
{
|
||||||
@ -143,14 +157,11 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
|
|||||||
|
|
||||||
size_t l, ll;
|
size_t l, ll;
|
||||||
|
|
||||||
|
if (!bPartialIsOK && !IsTLSHandshakeFull(data,len)) return false;
|
||||||
|
|
||||||
l = 1 + 3 + 2 + 32;
|
l = 1 + 3 + 2 + 32;
|
||||||
// SessionIDLength
|
// SessionIDLength
|
||||||
if (len < (l + 1)) return false;
|
if (len < (l + 1)) return false;
|
||||||
if (!bPartialIsOK)
|
|
||||||
{
|
|
||||||
ll = data[1] << 16 | data[2] << 8 | data[3]; // HandshakeProtocol length
|
|
||||||
if (len < (ll + 4)) return false;
|
|
||||||
}
|
|
||||||
l += data[l] + 1;
|
l += data[l] + 1;
|
||||||
// CipherSuitesLength
|
// CipherSuitesLength
|
||||||
if (len < (l + 2)) return false;
|
if (len < (l + 2)) return false;
|
||||||
@ -276,7 +287,7 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
|
|||||||
// offset must be 0 if it's a full segment, not just a chunk
|
// offset must be 0 if it's a full segment, not just a chunk
|
||||||
if (coff || (offset+tvb_get_size(data[offset])) >= len) return false;
|
if (coff || (offset+tvb_get_size(data[offset])) >= len) return false;
|
||||||
offset += tvb_get_varint(data + offset, &clen);
|
offset += tvb_get_varint(data + offset, &clen);
|
||||||
if (data[offset] != 0x01 || (offset + clen) > len) return false;
|
if ((offset + clen) > len || !IsTLSHandshakeClientHello(data+offset,clen)) return false;
|
||||||
if (hello_offset) *hello_offset = offset;
|
if (hello_offset) *hello_offset = offset;
|
||||||
if (hello_len) *hello_len = (size_t)clen;
|
if (hello_len) *hello_len = (size_t)clen;
|
||||||
return true;
|
return true;
|
||||||
|
@ -22,6 +22,9 @@ uint16_t TLSRecordDataLen(const uint8_t *data);
|
|||||||
size_t TLSRecordLen(const uint8_t *data);
|
size_t TLSRecordLen(const uint8_t *data);
|
||||||
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
bool IsTLSRecordFull(const uint8_t *data, size_t len);
|
||||||
bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK);
|
bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK);
|
||||||
|
size_t TLSHandshakeLen(const uint8_t *data);
|
||||||
|
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len);
|
||||||
|
bool IsTLSHandshakeFull(const uint8_t *data, size_t len);
|
||||||
bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
||||||
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
||||||
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
||||||
|
Loading…
Reference in New Issue
Block a user