mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-30 05:50:53 +03:00
nfqws: ipfrag
This commit is contained in:
parent
44175a5e2d
commit
690d458ec7
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.
@ -27,6 +27,7 @@ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1
|
||||
|
||||
ipfw delete 100
|
||||
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg xmit em0
|
||||
ipfw add 100 divert 989 udp from any to any 443 out not diverted not sockarg xmit em0
|
||||
|
||||
ipfw delete 100
|
||||
ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
|
||||
|
@ -210,3 +210,7 @@ blockcheck.sh
|
||||
v43
|
||||
|
||||
nfqws: UDP desync with conntrack support (any-protocol only for now)
|
||||
|
||||
v44
|
||||
|
||||
nfqws: ipfrag
|
||||
|
@ -5,13 +5,14 @@ iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -
|
||||
|
||||
For outgoing data manipulation ("Host:" case changing) :
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
For dpi desync attack :
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I POSTROUTING -p udp --dport 443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
|
||||
For TPROXY :
|
||||
|
@ -139,7 +139,7 @@ nfqws takes the following parameters:
|
||||
--pidfile=<filename> ; write pid to file
|
||||
--user=<username> ; drop root privs
|
||||
--uid=uid[:gid] ; drop root privs
|
||||
--dpi-desync=[<mode0,]<mode>[,<mode2>] ; desync dpi state. modes : synack fake rst rstack disorder disorder2 split split2
|
||||
--dpi-desync=[<mode0,]<mode>[,<mode2>] ; desync dpi state. modes : synack fake rst rstack disorder disorder2 split split2 ipfrag2
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000
|
||||
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
||||
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used
|
||||
@ -148,6 +148,8 @@ nfqws takes the following parameters:
|
||||
--dpi-desync-repeats=<N> ; send every desync packet N times
|
||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not apply desync to requests without hostname in the SNI
|
||||
--dpi-desync-split-pos=<1..1500> ; (for split* and disorder* only) split TCP packet at specified position
|
||||
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the second header (usually transport header). multiple of 8, default 8.
|
||||
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the second header (usually transport header). multiple of 8, default 32.
|
||||
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
|
||||
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
|
||||
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
||||
@ -391,6 +393,14 @@ parameter of `--ctrack-timeouts`.
|
||||
Fake attack is useful only for stateful DPI and useless for stateless dealing with each packet independently.
|
||||
By default fake payload is 64 zeroes. Can be overriden using `--dpi-desync-fake-unknown-udp`.
|
||||
|
||||
### IP fragmentation
|
||||
|
||||
Modern network is very hostile to IP fragmentation. Fragmented packets are often not delivered or refragmented/reassembled
|
||||
on the way. Linux always reassembles forwarded fragmented ipv6 if possible and it cannot be disablled.
|
||||
But Linux can send fragments.
|
||||
Frag position is set independently for tcp and udp. By default 24 and 8, must be multiple of 8.
|
||||
Offset starts from the header following ip header - transport header in most cases.
|
||||
|
||||
|
||||
## tpws
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
zapret v.43
|
||||
zapret v.44
|
||||
|
||||
English
|
||||
-------
|
||||
@ -187,7 +187,7 @@ nfqws
|
||||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack fake rst rstack disorder disorder2 split split2
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack fake rst rstack disorder disorder2 split split2 ipfrag2
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
|
||||
@ -418,13 +418,20 @@ window size итоговый размер окна стал максимальн
|
||||
|
||||
ПОДДЕРЖКА UDP
|
||||
Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip.
|
||||
ip фрагментация на данный момент не реализована.
|
||||
Пока что реализован только метод десинхронизации fake в режиме --dpi-desync-any-protocol.
|
||||
Реализован conntrack для udp. Можно пользоваться --dpi-desync-cutoff. Таймаут conntrack для udp
|
||||
можно изменить 4-м параметром в --ctrack-timeouts.
|
||||
Атака fake полезна только для stateful DPI, она бесполезна для анализа на уровне отдельных пакетов.
|
||||
По умолчанию fake наполнение - 64 нуля. Можно указать файл в --dpi-desync-fake-unknown-udp.
|
||||
|
||||
IP ФРАГМЕНТАЦИЯ
|
||||
В современной сети с этом все очень плохо. Фрагментированные пакеты застревают по пути, часто отбрасываются.
|
||||
Иногда доходят. Иногда то доходят, то не доходят. Может зависеть от версии ipv4/ipv6.
|
||||
Роутеры на базе linux и freebsd могут самопроизвольно собирать или перефрагментировать пакеты.
|
||||
Linux всегда собирает проходящие ipv6 фрагменты, и это неотключаемо, но может отсылать фрагменты сам.
|
||||
Позиция фрагментации задается отдельно для tcp и udp. По умолчанию 24 и 8 соответственно, должна быть кратна 8.
|
||||
Смещение считается с заголовка, следующего за ip. В большинство случаев это транспортный заголовок.
|
||||
|
||||
tpws
|
||||
-----
|
||||
|
||||
|
@ -307,6 +307,100 @@ bool prepare_udp_segment(
|
||||
|
||||
|
||||
|
||||
// split ipv4 packet into 2 fragments at data payload position frag_pos
|
||||
bool ip_frag4(
|
||||
const uint8_t *pkt, size_t pkt_size,
|
||||
size_t frag_pos, uint32_t ident,
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size)
|
||||
{
|
||||
uint16_t hdrlen, payload_len;
|
||||
// frag_pos must be 8-byte aligned
|
||||
if (frag_pos & 7 || pkt_size < sizeof(struct ip)) return false;
|
||||
payload_len = htons(((struct ip *)pkt)->ip_len);
|
||||
hdrlen = ((struct ip *)pkt)->ip_hl<<2;
|
||||
if (payload_len>pkt_size || hdrlen>pkt_size || hdrlen>payload_len) return false;
|
||||
payload_len -= hdrlen;
|
||||
if (frag_pos>=payload_len || *pkt1_size<(hdrlen+frag_pos) || *pkt2_size<(hdrlen+payload_len-frag_pos)) return false;
|
||||
|
||||
memcpy(pkt1, pkt, hdrlen+frag_pos);
|
||||
((struct ip*)pkt1)->ip_off = htons(IP_MF);
|
||||
((struct ip*)pkt1)->ip_len = htons(hdrlen+frag_pos);
|
||||
if (ident!=(uint32_t)-1) ((struct ip*)pkt1)->ip_id = (uint16_t)ident;
|
||||
|
||||
*pkt1_size=hdrlen+frag_pos;
|
||||
ip4_fix_checksum((struct ip *)pkt1);
|
||||
|
||||
memcpy(pkt2, pkt, hdrlen);
|
||||
memcpy(pkt2+hdrlen, pkt+hdrlen+frag_pos, payload_len-frag_pos);
|
||||
((struct ip*)pkt2)->ip_off = htons((uint16_t)frag_pos>>3 & IP_OFFMASK);
|
||||
((struct ip*)pkt2)->ip_len = htons(hdrlen+payload_len-frag_pos);
|
||||
if (ident!=(uint32_t)-1) ((struct ip*)pkt2)->ip_id = (uint16_t)ident;
|
||||
*pkt2_size=hdrlen+payload_len-frag_pos;
|
||||
ip4_fix_checksum((struct ip *)pkt2);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool ip_frag6(
|
||||
const uint8_t *pkt, size_t pkt_size,
|
||||
size_t frag_pos, uint32_t ident,
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size)
|
||||
{
|
||||
uint16_t payload_len;
|
||||
uint8_t proto;
|
||||
struct ip6_frag *frag;
|
||||
|
||||
if (frag_pos & 7 || pkt_size < sizeof(struct ip6_hdr)) return false;
|
||||
payload_len = htons(((struct ip6_hdr*)pkt)->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
if ((sizeof(struct ip6_hdr)+payload_len)>pkt_size || frag_pos>=payload_len ||
|
||||
*pkt1_size<(sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+frag_pos) ||
|
||||
*pkt2_size<(sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+payload_len-frag_pos))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
proto = ((struct ip6_hdr*)pkt)->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
|
||||
memcpy(pkt1, pkt, sizeof(struct ip6_hdr));
|
||||
((struct ip6_hdr*)pkt1)->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct ip6_frag)+frag_pos);
|
||||
((struct ip6_hdr*)pkt1)->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_FRAGMENT;
|
||||
frag = (struct ip6_frag*)(((struct ip6_hdr*)pkt1)+1);
|
||||
frag->ip6f_nxt = proto;
|
||||
frag->ip6f_reserved = 0;
|
||||
frag->ip6f_offlg = IP6F_MORE_FRAG;
|
||||
frag->ip6f_ident = ident;
|
||||
memcpy(frag+1, pkt+sizeof(struct ip6_hdr), frag_pos);
|
||||
*pkt1_size = sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+frag_pos;
|
||||
|
||||
memcpy(pkt2, pkt, sizeof(struct ip6_hdr));
|
||||
((struct ip6_hdr*)pkt2)->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct ip6_frag)+payload_len-frag_pos);
|
||||
((struct ip6_hdr*)pkt2)->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_FRAGMENT;
|
||||
frag = (struct ip6_frag*)(((struct ip6_hdr*)pkt2)+1);
|
||||
frag->ip6f_nxt = proto;
|
||||
frag->ip6f_reserved = 0;
|
||||
frag->ip6f_offlg = htons(frag_pos);
|
||||
frag->ip6f_ident = ident;
|
||||
memcpy(frag+1, pkt+sizeof(struct ip6_hdr)+frag_pos, payload_len-frag_pos);
|
||||
*pkt2_size = sizeof(struct ip6_hdr)+sizeof(struct ip6_frag)+payload_len-frag_pos;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool ip_frag(
|
||||
const uint8_t *pkt, size_t pkt_size,
|
||||
size_t frag_pos, uint32_t ident,
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size)
|
||||
{
|
||||
if (proto_check_ipv4(pkt,pkt_size))
|
||||
return ip_frag4(pkt,pkt_size,frag_pos,ident,pkt1,pkt1_size,pkt2,pkt2_size);
|
||||
else if (proto_check_ipv6(pkt,pkt_size))
|
||||
return ip_frag6(pkt,pkt_size,frag_pos,ident,pkt1,pkt1_size,pkt2,pkt2_size);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport)
|
||||
{
|
||||
if (sport) *sport = htons(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0);
|
||||
|
@ -84,6 +84,24 @@ bool prepare_udp_segment(
|
||||
uint8_t *buf, size_t *buflen);
|
||||
|
||||
|
||||
// ipv4: ident==-1 - copy ip_id from original ipv4 packet
|
||||
bool ip_frag4(
|
||||
const uint8_t *pkt, size_t pkt_size,
|
||||
size_t frag_pos, uint32_t ident,
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size);
|
||||
bool ip_frag6(
|
||||
const uint8_t *pkt, size_t pkt_size,
|
||||
size_t frag_pos, uint32_t ident,
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size);
|
||||
bool ip_frag(
|
||||
const uint8_t *pkt, size_t pkt_size,
|
||||
size_t frag_pos, uint32_t ident,
|
||||
uint8_t *pkt1, size_t *pkt1_size,
|
||||
uint8_t *pkt2, size_t *pkt2_size);
|
||||
|
||||
|
||||
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
|
||||
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
|
||||
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
|
||||
|
182
nfq/desync.c
182
nfq/desync.c
@ -50,7 +50,8 @@ const uint8_t fake_tls_clienthello_default[517] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#define PKT_MAXDUMP 32
|
||||
#define PKTDATA_MAXDUMP 32
|
||||
#define IP_MAXDUMP 64
|
||||
|
||||
static uint8_t zeropkt[DPI_DESYNC_MAX_FAKE_LEN];
|
||||
|
||||
@ -70,7 +71,7 @@ bool desync_valid_first_stage(enum dpi_desync_mode mode)
|
||||
}
|
||||
bool desync_valid_second_stage(enum dpi_desync_mode mode)
|
||||
{
|
||||
return mode==DESYNC_NONE || mode==DESYNC_DISORDER || mode==DESYNC_DISORDER2 || mode==DESYNC_SPLIT || mode==DESYNC_SPLIT2;
|
||||
return mode==DESYNC_NONE || mode==DESYNC_DISORDER || mode==DESYNC_DISORDER2 || mode==DESYNC_SPLIT || mode==DESYNC_SPLIT2 || mode==DESYNC_IPFRAG2;
|
||||
}
|
||||
enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||
{
|
||||
@ -92,6 +93,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||
return DESYNC_SPLIT;
|
||||
else if (!strcmp(s,"split2"))
|
||||
return DESYNC_SPLIT2;
|
||||
else if (!strcmp(s,"ipfrag2"))
|
||||
return DESYNC_IPFRAG2;
|
||||
return DESYNC_INVALID;
|
||||
}
|
||||
|
||||
@ -151,8 +154,8 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
bool bReverse=false;
|
||||
|
||||
struct sockaddr_storage src, dst;
|
||||
uint8_t newdata[DPI_DESYNC_MAX_FAKE_LEN+100];
|
||||
size_t newlen;
|
||||
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100];
|
||||
size_t pkt1_len, pkt2_len;
|
||||
uint8_t ttl_orig,ttl_fake,flags_orig,scale_factor;
|
||||
uint32_t *timestamps;
|
||||
|
||||
@ -210,15 +213,15 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
if (params.desync_mode0==DESYNC_SYNACK && tcp_syn_segment(tcphdr))
|
||||
{
|
||||
newlen = sizeof(newdata);
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN|TH_ACK, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_fake,params.desync_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
NULL, 0, newdata, &newlen))
|
||||
NULL, 0, pkt1, &pkt1_len))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
DLOG("sending fake SYNACK\n");
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -349,26 +352,26 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
enum dpi_desync_mode desync_mode = params.desync_mode;
|
||||
bool b;
|
||||
|
||||
newlen = sizeof(newdata);
|
||||
pkt1_len = sizeof(pkt1);
|
||||
b = false;
|
||||
switch(desync_mode)
|
||||
{
|
||||
case DESYNC_FAKE:
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_fake,params.desync_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
fake, fake_size, newdata, &newlen))
|
||||
fake, fake_size, pkt1, &pkt1_len))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
DLOG("sending fake request : ");
|
||||
hexdump_limited_dlog(fake,fake_size,PKT_MAXDUMP); DLOG("\n")
|
||||
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
b = true;
|
||||
break;
|
||||
case DESYNC_RST:
|
||||
case DESYNC_RSTACK:
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (desync_mode==DESYNC_RSTACK ? TH_ACK:0), tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_fake,params.desync_fooling_mode,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
NULL, 0, newdata, &newlen))
|
||||
NULL, 0, pkt1, &pkt1_len))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
@ -379,7 +382,7 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
|
||||
if (b)
|
||||
{
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
if (params.desync_mode2==DESYNC_NONE)
|
||||
{
|
||||
@ -406,13 +409,13 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
desync_mode = params.desync_mode2;
|
||||
}
|
||||
|
||||
newlen = sizeof(newdata);
|
||||
size_t split_pos=len_payload>params.desync_split_pos ? params.desync_split_pos : 1;
|
||||
pkt1_len = sizeof(pkt1);
|
||||
switch(desync_mode)
|
||||
{
|
||||
case DESYNC_DISORDER:
|
||||
case DESYNC_DISORDER2:
|
||||
{
|
||||
size_t split_pos=len_payload>params.desync_split_pos ? params.desync_split_pos : 1;
|
||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100];
|
||||
size_t fakeseg_len;
|
||||
|
||||
@ -420,11 +423,11 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
{
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->th_seq,split_pos), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_orig,FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
data_payload+split_pos, len_payload-split_pos, newdata, &newlen))
|
||||
data_payload+split_pos, len_payload-split_pos, pkt1, &pkt1_len))
|
||||
return res;
|
||||
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos)
|
||||
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -437,26 +440,26 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
zeropkt, split_pos, fakeseg, &fakeseg_len))
|
||||
return res;
|
||||
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
newlen = sizeof(newdata);
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_orig,FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
data_payload, split_pos, newdata, &newlen))
|
||||
data_payload, split_pos, pkt1, &pkt1_len))
|
||||
return res;
|
||||
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(data_payload,split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
hexdump_limited_dlog(data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
if (desync_mode==DESYNC_DISORDER)
|
||||
{
|
||||
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
@ -467,7 +470,6 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
case DESYNC_SPLIT:
|
||||
case DESYNC_SPLIT2:
|
||||
{
|
||||
size_t split_pos=len_payload>params.desync_split_pos ? params.desync_split_pos : 1;
|
||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100];
|
||||
size_t fakeseg_len;
|
||||
|
||||
@ -479,45 +481,74 @@ packet_process_result dpi_desync_tcp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
zeropkt, split_pos, fakeseg, &fakeseg_len))
|
||||
return res;
|
||||
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
newlen = sizeof(newdata);
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, tcphdr->th_seq, tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_orig,FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
data_payload, split_pos, newdata, &newlen))
|
||||
data_payload, split_pos, pkt1, &pkt1_len))
|
||||
return res;
|
||||
DLOG("sending 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(data_payload,split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
hexdump_limited_dlog(data_payload,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
if (desync_mode==DESYNC_SPLIT)
|
||||
{
|
||||
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos)
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, fakeseg, fakeseg_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
if (split_pos<len_payload)
|
||||
{
|
||||
newlen = sizeof(newdata);
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(tcphdr->th_seq,split_pos), tcphdr->th_ack, tcphdr->th_win, scale_factor, timestamps,
|
||||
ttl_orig,FOOL_NONE,params.desync_badseq_increment,params.desync_badseq_ack_increment,
|
||||
data_payload+split_pos, len_payload-split_pos, newdata, &newlen))
|
||||
data_payload+split_pos, len_payload-split_pos, pkt1, &pkt1_len))
|
||||
return res;
|
||||
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,len_payload-1, len_payload-split_pos)
|
||||
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKT_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
hexdump_limited_dlog(data_payload+split_pos,len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
}
|
||||
|
||||
return drop;
|
||||
}
|
||||
break;
|
||||
case DESYNC_IPFRAG2:
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (ip6hdr)
|
||||
tcp_fix_checksum(tcphdr,len_tcp,ip,ip6hdr);
|
||||
#endif
|
||||
|
||||
size_t ipfrag_pos = (params.desync_ipfrag_pos_tcp && params.desync_ipfrag_pos_tcp<len_tcp) ? params.desync_ipfrag_pos_tcp : 24;
|
||||
uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()&0xFFFFFFFF);
|
||||
|
||||
pkt1_len = sizeof(pkt1);
|
||||
pkt2_len = sizeof(pkt2);
|
||||
|
||||
if (!ip_frag(data_pkt, len_pkt, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len))
|
||||
return res;
|
||||
|
||||
DLOG("sending 1st ip fragment 0-%zu len=%zu : ", ipfrag_pos-1, ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt1,pkt1_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt2, pkt2_len))
|
||||
return res;
|
||||
|
||||
DLOG("sending 2nd ip fragment %zu-%zu len=%zu : ", ipfrag_pos, len_tcp-1, len_tcp-ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
return frag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,8 +564,8 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
bool bReverse=false;
|
||||
|
||||
struct sockaddr_storage src, dst;
|
||||
uint8_t newdata[DPI_DESYNC_MAX_FAKE_LEN+100];
|
||||
size_t newlen;
|
||||
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100];
|
||||
size_t pkt1_len, pkt2_len;
|
||||
uint8_t ttl_orig,ttl_fake;
|
||||
|
||||
if (!!ip == !!ip6hdr) return res; // one and only one must be present
|
||||
@ -579,6 +610,8 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
if (!params.desync_any_proto) return res;
|
||||
DLOG("applying tampering to unknown protocol\n")
|
||||
|
||||
enum dpi_desync_mode desync_mode = params.desync_mode;
|
||||
|
||||
ttl_orig = ip ? ip->ip_ttl : ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim;
|
||||
if (ip6hdr) ttl_fake = params.desync_ttl6 ? params.desync_ttl6 : ttl_orig;
|
||||
else ttl_fake = params.desync_ttl ? params.desync_ttl : ttl_orig;
|
||||
@ -596,36 +629,77 @@ packet_process_result dpi_desync_udp_packet(uint8_t *data_pkt, size_t len_pkt, s
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
newlen = sizeof(newdata);
|
||||
pkt1_len = sizeof(pkt1);
|
||||
b = false;
|
||||
switch(params.desync_mode)
|
||||
switch(desync_mode)
|
||||
{
|
||||
case DESYNC_FAKE:
|
||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, params.desync_fooling_mode, fake, fake_size, newdata, &newlen))
|
||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, ttl_fake, params.desync_fooling_mode, fake, fake_size, pkt1, &pkt1_len))
|
||||
return res;
|
||||
DLOG("sending fake request : ");
|
||||
hexdump_limited_dlog(fake,fake_size,PKT_MAXDUMP); DLOG("\n")
|
||||
hexdump_limited_dlog(fake,fake_size,PKTDATA_MAXDUMP); DLOG("\n")
|
||||
b = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (b)
|
||||
{
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, newdata, newlen))
|
||||
return res;
|
||||
DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", len_pkt, len_payload)
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (res==modify || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if (res==modify)
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, data_pkt, len_pkt))
|
||||
return res;
|
||||
return drop;
|
||||
if (params.desync_mode2==DESYNC_NONE)
|
||||
{
|
||||
if (!rawsend_rep((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
DLOG("reinjecting original packet. len=%zu len_payload=%zu\n", len_pkt, len_payload)
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (res==modify || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if (res==modify)
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, data_pkt, len_pkt))
|
||||
return res;
|
||||
return drop;
|
||||
}
|
||||
desync_mode = params.desync_mode2;
|
||||
}
|
||||
|
||||
switch(desync_mode)
|
||||
{
|
||||
case DESYNC_IPFRAG2:
|
||||
{
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (ip6hdr)
|
||||
udp_fix_checksum(udphdr,sizeof(struct udphdr)+len_payload,ip,ip6hdr);
|
||||
#endif
|
||||
|
||||
size_t len_transport = len_payload + sizeof(struct udphdr);
|
||||
size_t ipfrag_pos = (params.desync_ipfrag_pos_udp && params.desync_ipfrag_pos_udp<len_transport) ? params.desync_ipfrag_pos_udp : sizeof(struct udphdr);
|
||||
// freebsd do not set ip.id
|
||||
uint32_t ident = ip ? ip->ip_id ? ip->ip_id : htons(1+random()%0xFFFF) : htonl(1+random()&0xFFFFFFFF);
|
||||
|
||||
pkt1_len = sizeof(pkt1);
|
||||
pkt2_len = sizeof(pkt2);
|
||||
|
||||
if (!ip_frag(data_pkt, len_pkt, ipfrag_pos, ident, pkt1, &pkt1_len, pkt2, &pkt2_len))
|
||||
return res;
|
||||
|
||||
DLOG("sending 1st ip fragment 0-%zu len=%zu : ", ipfrag_pos-1, ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt1,pkt1_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt2, pkt2_len))
|
||||
return res;
|
||||
|
||||
DLOG("sending 2nd ip fragment %zu-%zu len=%zu : ", ipfrag_pos, len_transport-1, len_transport-ipfrag_pos)
|
||||
hexdump_limited_dlog(pkt2,pkt2_len,IP_MAXDUMP); DLOG("\n")
|
||||
if (!rawsend((struct sockaddr *)&dst, params.desync_fwmark, pkt1, pkt1_len))
|
||||
return res;
|
||||
|
||||
return frag;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -28,7 +28,8 @@ enum dpi_desync_mode {
|
||||
DESYNC_DISORDER,
|
||||
DESYNC_DISORDER2,
|
||||
DESYNC_SPLIT,
|
||||
DESYNC_SPLIT2
|
||||
DESYNC_SPLIT2,
|
||||
DESYNC_IPFRAG2
|
||||
};
|
||||
|
||||
extern const char *fake_http_request_default;
|
||||
|
90
nfq/nfqws.c
90
nfq/nfqws.c
@ -148,7 +148,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
||||
// ipv6 packets were with incorrect checksum
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (res==modify || ip6hdr)
|
||||
if (res==modify || res!=frag && ip6hdr)
|
||||
#else
|
||||
if (res==modify)
|
||||
#endif
|
||||
@ -171,7 +171,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
||||
res = dpi_desync_udp_packet(data_pkt, len_pkt, ip, ip6hdr, udphdr, data, len);
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if (res==modify || ip6hdr)
|
||||
if (res==modify || res!=frag && ip6hdr)
|
||||
#else
|
||||
if (res==modify)
|
||||
#endif
|
||||
@ -209,6 +209,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
|
||||
DLOG("packet: id=%d pass modified\n", id);
|
||||
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, len, data);
|
||||
case drop:
|
||||
case frag:
|
||||
DLOG("packet: id=%d drop\n", id);
|
||||
return nfq_set_verdict2(qh, id, NF_DROP, mark, 0, NULL);
|
||||
}
|
||||
@ -504,7 +505,7 @@ static void exithelp()
|
||||
" --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
||||
" --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||
" --domcase\t\t\t\t; mix domain case : Host: TeSt.cOm\n"
|
||||
" --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack disorder disorder2 split split2\n"
|
||||
" --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake rst rstack disorder disorder2 split split2 ipfrag2\n"
|
||||
#ifdef __linux__
|
||||
" --dpi-desync-fwmark=<int|0xHEX>\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
@ -518,7 +519,9 @@ static void exithelp()
|
||||
#endif
|
||||
" --dpi-desync-repeats=<N>\t\t; send every desync packet N times\n"
|
||||
" --dpi-desync-skip-nosni=0|1\t\t; 1(default)=do not act on ClientHello without SNI (ESNI ?)\n"
|
||||
" --dpi-desync-split-pos=<1..%u>\t; TCP packet split position\n"
|
||||
" --dpi-desync-split-pos=<1..%u>\t; data payload split position\n"
|
||||
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t; ip frag position starting from the second header (usually transport header). multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t; ip frag position starting from the second header (usually transport header). multiple of 8, default %u.\n"
|
||||
" --dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default %d\n"
|
||||
" --dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default %d\n"
|
||||
" --dpi-desync-any-protocol=0|1\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
||||
@ -533,6 +536,8 @@ static void exithelp()
|
||||
DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT,
|
||||
#endif
|
||||
DPI_DESYNC_MAX_FAKE_LEN,
|
||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT,
|
||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT,
|
||||
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT
|
||||
);
|
||||
exit(1);
|
||||
@ -602,6 +607,8 @@ int main(int argc, char **argv)
|
||||
params.desync_fwmark = DPI_DESYNC_FWMARK_DEFAULT;
|
||||
params.desync_skip_nosni = true;
|
||||
params.desync_split_pos = 2;
|
||||
params.desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
|
||||
params.desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
|
||||
params.desync_repeats = 1;
|
||||
params.fake_tls_size = sizeof(fake_tls_clienthello_default);
|
||||
memcpy(params.fake_tls,fake_tls_clienthello_default,params.fake_tls_size);
|
||||
@ -661,15 +668,17 @@ int main(int argc, char **argv)
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=20
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=21
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=22
|
||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=23
|
||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=24
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=25
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=26
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=27
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=28
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=29
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=30
|
||||
{"hostlist",required_argument,0,0}, // optidx=31
|
||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=24
|
||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=25
|
||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=26
|
||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=27
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=28
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=29
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=30
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=31
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=32
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=33
|
||||
{"hostlist",required_argument,0,0}, // optidx=34
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
if (argc < 2) exithelp();
|
||||
@ -806,6 +815,13 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "invalid desync combo : %s+%s\n", mode,mode2);
|
||||
exit_clean(1);
|
||||
}
|
||||
#if defined(__OpenBSD__)
|
||||
if (params.desync_mode==DESYNC_IPFRAG2 || params.desync_mode2==DESYNC_IPFRAG2)
|
||||
{
|
||||
fprintf(stderr, "OpenBSD has checksum issues with fragmented packets. ipfrag disabled.\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||
@ -866,8 +882,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
break;
|
||||
case 20: /* dpi-desync-repeats */
|
||||
params.desync_repeats = atoi(optarg);
|
||||
if (params.desync_repeats<=0 || params.desync_repeats>20)
|
||||
if (sscanf(optarg,"%u",¶ms.desync_repeats)<1 || params.desync_repeats<=0 || params.desync_repeats>20)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-repeats must be within 1..20\n");
|
||||
exit_clean(1);
|
||||
@ -877,54 +892,77 @@ int main(int argc, char **argv)
|
||||
params.desync_skip_nosni = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 22: /* dpi-desync-split-pos */
|
||||
params.desync_split_pos = atoi(optarg);
|
||||
if (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);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 23: /* dpi-desync-badseq-increments */
|
||||
case 23: /* 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)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
exit_clean(1);
|
||||
}
|
||||
if (params.desync_ipfrag_pos_tcp & 7)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-ipfrag-pos-tcp must be multiple of 8\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 24: /* 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)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
exit_clean(1);
|
||||
}
|
||||
if (params.desync_ipfrag_pos_udp & 7)
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-ipfrag-pos-udp must be multiple of 8\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 25: /* dpi-desync-badseq-increments */
|
||||
if (!parse_badseq_increment(optarg,¶ms.desync_badseq_increment))
|
||||
{
|
||||
fprintf(stderr, "dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 24: /* dpi-desync-badack-increment */
|
||||
case 26: /* dpi-desync-badack-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");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 25: /* dpi-desync-any-protocol */
|
||||
case 27: /* dpi-desync-any-protocol */
|
||||
params.desync_any_proto = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 26: /* dpi-desync-fake-http */
|
||||
case 28: /* dpi-desync-fake-http */
|
||||
params.fake_http_size = sizeof(params.fake_http);
|
||||
load_file_or_exit(optarg,params.fake_http,¶ms.fake_http_size);
|
||||
break;
|
||||
case 27: /* dpi-desync-fake-tls */
|
||||
case 29: /* dpi-desync-fake-tls */
|
||||
params.fake_tls_size = sizeof(params.fake_tls);
|
||||
load_file_or_exit(optarg,params.fake_tls,¶ms.fake_tls_size);
|
||||
break;
|
||||
case 28: /* dpi-desync-fake-unknown */
|
||||
case 30: /* dpi-desync-fake-unknown */
|
||||
params.fake_unknown_size = sizeof(params.fake_unknown);
|
||||
load_file_or_exit(optarg,params.fake_unknown,¶ms.fake_unknown_size);
|
||||
break;
|
||||
case 29: /* dpi-desync-fake-unknown-udp */
|
||||
case 31: /* dpi-desync-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);
|
||||
break;
|
||||
case 30: /* desync-cutoff */
|
||||
case 32: /* desync-cutoff */
|
||||
if (!parse_cutoff(optarg, ¶ms.desync_cutoff, ¶ms.desync_cutoff_mode))
|
||||
{
|
||||
fprintf(stderr, "invalid desync-cutoff value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 31: /* hostlist */
|
||||
case 33: /* hostlist */
|
||||
if (!LoadHostList(¶ms.hostlist, optarg))
|
||||
exit_clean(1);
|
||||
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
|
||||
|
@ -2,5 +2,6 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
pass = 0, modify, drop
|
||||
// frag=drop but do not fix checksum
|
||||
pass = 0, modify, drop, frag
|
||||
} packet_process_result;
|
||||
|
@ -20,6 +20,9 @@
|
||||
#define BADSEQ_INCREMENT_DEFAULT -10000
|
||||
#define BADSEQ_ACK_INCREMENT_DEFAULT -66000
|
||||
|
||||
#define IPFRAG_UDP_DEFAULT 8
|
||||
#define IPFRAG_TCP_DEFAULT 32
|
||||
|
||||
struct params_s
|
||||
{
|
||||
bool debug;
|
||||
@ -36,7 +39,7 @@ struct params_s
|
||||
char hostspell[4];
|
||||
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
||||
bool desync_retrans,desync_skip_nosni,desync_any_proto;
|
||||
int desync_repeats,desync_split_pos;
|
||||
unsigned int desync_repeats,desync_split_pos,desync_ipfrag_pos_tcp,desync_ipfrag_pos_udp;
|
||||
char desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
||||
unsigned int desync_cutoff;
|
||||
uint8_t desync_ttl, desync_ttl6;
|
||||
|
Loading…
Reference in New Issue
Block a user