mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-26 20:20:53 +03:00
nfqws: wssize
This commit is contained in:
parent
76e52c350b
commit
53f36c7297
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.
@ -90,10 +90,10 @@ iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -m s
|
|||||||
Some DPIs catch only the first http request, ignoring subsequent requests in a keep-alive session.
|
Some DPIs catch only the first http request, ignoring subsequent requests in a keep-alive session.
|
||||||
Then we can reduce CPU load, refusing to process unnecessary packets.
|
Then we can reduce CPU load, refusing to process unnecessary packets.
|
||||||
|
|
||||||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
|
|
||||||
Mark filter does not allow nfqws-generated packets to enter the queue again.
|
Mark filter does not allow nfqws-generated packets to enter the queue again.
|
||||||
Its necessary to use this filter when also using "connbytes 2:4". Without it packet ordering can be changed breaking the whole idea.
|
Its necessary to use this filter when also using "connbytes 1:4". Without it packet ordering can be changed breaking the whole idea.
|
||||||
|
|
||||||
|
|
||||||
ip6tables
|
ip6tables
|
||||||
@ -134,6 +134,8 @@ nfqws takes the following parameters:
|
|||||||
--debug=0|1 ; 1=print debug info
|
--debug=0|1 ; 1=print debug info
|
||||||
--qnum=<nfqueue_number>
|
--qnum=<nfqueue_number>
|
||||||
--wsize=<window_size> ; set window size. 0 = do not modify (obsolete !)
|
--wsize=<window_size> ; set window size. 0 = do not modify (obsolete !)
|
||||||
|
--wsize=<winsize>[:<scale_factor>] ; change window size in SYN,ACK packets. default is not to change scale factor (OBSOLETE !)
|
||||||
|
--wssize=<winsize>[:<scale_factor>] ; change window size in all packets except SYN,ACK. default scale factor is 0.
|
||||||
--hostcase ; change Host: => host:
|
--hostcase ; change Host: => host:
|
||||||
--hostspell=HoSt ; exact spelling of the "Host" header. must be 4 chars. default is "host"
|
--hostspell=HoSt ; exact spelling of the "Host" header. must be 4 chars. default is "host"
|
||||||
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
||||||
@ -228,12 +230,12 @@ Subdomains are applied automatically. gzip lists are supported.
|
|||||||
|
|
||||||
iptables for performing the attack on the first packet :
|
iptables for performing the attack on the first packet :
|
||||||
|
|
||||||
iptables -t mangle -I POSTROUTING -o <external_interface> -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 -o <external_interface> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
|
|
||||||
This is good if DPI does not track all requests in http keep-alive session.
|
This is good if DPI does not track all requests in http keep-alive session.
|
||||||
If it does, then pass all outgoing packets for http and only first data packet for https :
|
If it does, then pass all outgoing packets for http and only first data packet for https :
|
||||||
|
|
||||||
iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 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 -o <external_interface> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
|
|
||||||
mark is needed to keep away generated packets from NFQUEUE. nfqws sets fwmark when it sends generated packets.
|
mark is needed to keep away generated packets from NFQUEUE. nfqws sets fwmark when it sends generated packets.
|
||||||
|
@ -110,10 +110,10 @@ iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp
|
|||||||
DPI может ловить только первый http запрос, игнорируя последующие запросы в keep-alive сессии.
|
DPI может ловить только первый http запрос, игнорируя последующие запросы в keep-alive сессии.
|
||||||
Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов.
|
Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов.
|
||||||
|
|
||||||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
|
|
||||||
Фильтр по mark нужен для отсечения от очереди пакетов, сгенерированных внутри nfqws.
|
Фильтр по mark нужен для отсечения от очереди пакетов, сгенерированных внутри nfqws.
|
||||||
Если применяется фильтр по connbytes 2:4, то обязательно добавлять в iptables и фильтр по mark. Иначе возможно
|
Если применяется фильтр по connbytes 1:4, то обязательно добавлять в iptables и фильтр по mark. Иначе возможно
|
||||||
перепутывания порядка следования пакетов, что приведет к неработоспособности метода.
|
перепутывания порядка следования пакетов, что приведет к неработоспособности метода.
|
||||||
|
|
||||||
|
|
||||||
@ -177,8 +177,9 @@ nfqws
|
|||||||
--pidfile=<file> ; сохранить PID в файл
|
--pidfile=<file> ; сохранить PID в файл
|
||||||
--user=<username> ; менять uid процесса
|
--user=<username> ; менять uid процесса
|
||||||
--uid=uid[:gid] ; менять uid процесса
|
--uid=uid[:gid] ; менять uid процесса
|
||||||
--qnum=200 ; номер очереди
|
--qnum=N ; номер очереди N
|
||||||
--wsize=4 ; менять tcp window size на указанный размер (устарело !)
|
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
||||||
|
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер во всех пакетах, кроме SYN,ACK. scale_factor по умолчанию 0.
|
||||||
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
||||||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||||
@ -274,12 +275,12 @@ DPI может отстать от потока, если ClientHello его у
|
|||||||
|
|
||||||
iptables для задействования атаки на первый пакет данных :
|
iptables для задействования атаки на первый пакет данных :
|
||||||
|
|
||||||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -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 -o <внешний_интерфейс> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
|
|
||||||
Этот вариант применяем, когда DPI не следит за всеми запросами http внутри keep-alive сессии.
|
Этот вариант применяем, когда DPI не следит за всеми запросами http внутри keep-alive сессии.
|
||||||
Если следит, направляем только первый пакет от https и все пакеты от http :
|
Если следит, направляем только первый пакет от https и все пакеты от http :
|
||||||
|
|
||||||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 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 -o <внешний_интерфейс> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||||
|
|
||||||
mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку. nfqws выставляет fwmark при его отсылке.
|
mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку. nfqws выставляет fwmark при его отсылке.
|
||||||
@ -290,7 +291,11 @@ mark нужен, чтобы сгенерированный поддельный
|
|||||||
При отсутствии ограничения на connbytes, атака будет работать и без фильтра по mark.
|
При отсутствии ограничения на connbytes, атака будет работать и без фильтра по mark.
|
||||||
Но лучше его все же оставить для увеличения скорости.
|
Но лучше его все же оставить для увеличения скорости.
|
||||||
|
|
||||||
Почему --connbytes 2:4 : 2 - иногда данные идут в 3-м пакете 3-way handshake. 3 - стандартная ситуация. 4 - для надежности. на случай, если выполнялась одна ретрансмиссия
|
Почему --connbytes 1:4 :
|
||||||
|
1 - для работы параметра wssize. scaling factor обычно устанавливается инициатором соединения в SYN пакете
|
||||||
|
2 - иногда данные идут в 3-м пакете 3-way handshake
|
||||||
|
3 - стандартная ситуация
|
||||||
|
4 - для надежности. на случай, если выполнялась одна ретрансмиссия
|
||||||
|
|
||||||
КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
|
КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
|
||||||
В параметре dpi-desync можно указать 2 режима через запятую.
|
В параметре dpi-desync можно указать 2 режима через запятую.
|
||||||
|
@ -24,7 +24,7 @@ zapret_custom_daemons()
|
|||||||
zapret_custom_firewall()
|
zapret_custom_firewall()
|
||||||
{
|
{
|
||||||
local f4 f6
|
local f4 f6
|
||||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4"
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||||
|
|
||||||
[ "$MODE_HTTP" = "1" ] && {
|
[ "$MODE_HTTP" = "1" ] && {
|
||||||
|
@ -20,7 +20,7 @@ zapret_custom_daemons()
|
|||||||
zapret_custom_firewall()
|
zapret_custom_firewall()
|
||||||
{
|
{
|
||||||
local f4 f6
|
local f4 f6
|
||||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4"
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||||
|
|
||||||
[ "$MODE_HTTP" = "1" ] && {
|
[ "$MODE_HTTP" = "1" ] && {
|
||||||
|
@ -371,7 +371,7 @@ flow_offloading_exempt()
|
|||||||
|
|
||||||
zapret_apply_firewall()
|
zapret_apply_firewall()
|
||||||
{
|
{
|
||||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4"
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||||
local f4 f6
|
local f4 f6
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ zapret_custom_daemons()
|
|||||||
zapret_custom_firewall()
|
zapret_custom_firewall()
|
||||||
{
|
{
|
||||||
local f4 f6
|
local f4 f6
|
||||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4"
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||||
|
|
||||||
[ "$MODE_HTTP" = "1" ] && {
|
[ "$MODE_HTTP" = "1" ] && {
|
||||||
|
@ -20,7 +20,7 @@ zapret_custom_daemons()
|
|||||||
zapret_custom_firewall()
|
zapret_custom_firewall()
|
||||||
{
|
{
|
||||||
local f4 f6
|
local f4 f6
|
||||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4"
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||||
|
|
||||||
[ "$MODE_HTTP" = "1" ] && {
|
[ "$MODE_HTTP" = "1" ] && {
|
||||||
|
@ -455,7 +455,7 @@ zapret_do_firewall()
|
|||||||
{
|
{
|
||||||
# $1 - 1 - add, 0 - del
|
# $1 - 1 - add, 0 - del
|
||||||
|
|
||||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4"
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||||
local f4 f6
|
local f4 f6
|
||||||
|
|
||||||
|
@ -648,3 +648,42 @@ bool tcp_synack_segment(const struct tcphdr *tcphdr)
|
|||||||
/* check for set bits in TCP hdr */
|
/* check for set bits in TCP hdr */
|
||||||
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == (TH_ACK|TH_SYN));
|
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == (TH_ACK|TH_SYN));
|
||||||
}
|
}
|
||||||
|
bool tcp_syn_segment(const struct tcphdr *tcphdr)
|
||||||
|
{
|
||||||
|
/* check for set bits in TCP hdr */
|
||||||
|
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == TH_SYN);
|
||||||
|
}
|
||||||
|
bool tcp_ack_segment(const struct tcphdr *tcphdr)
|
||||||
|
{
|
||||||
|
/* check for set bits in TCP hdr */
|
||||||
|
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == TH_ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor)
|
||||||
|
{
|
||||||
|
uint8_t *scale,scale_factor_old;
|
||||||
|
|
||||||
|
if (scale_factor!=(uint8_t)-1)
|
||||||
|
{
|
||||||
|
scale = tcp_find_option(tcp,3); // tcp option 3 - scale factor
|
||||||
|
if (scale && scale[1]==3) // length should be 3
|
||||||
|
{
|
||||||
|
scale_factor_old=scale[2];
|
||||||
|
scale[2]=scale_factor;
|
||||||
|
if (scale_factor_old!=scale_factor)
|
||||||
|
DLOG("Scale factor change %u => %u\n", scale_factor_old, scale_factor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// scale_factor=-1 - do not change
|
||||||
|
void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_factor)
|
||||||
|
{
|
||||||
|
uint16_t winsize_old;
|
||||||
|
uint8_t *scale,scale_factor_old;
|
||||||
|
|
||||||
|
winsize_old = htons(tcp->th_win); // << scale_factor;
|
||||||
|
tcp->th_win = htons(winsize);
|
||||||
|
DLOG("Window size change %u => %u\n", winsize_old, winsize)
|
||||||
|
|
||||||
|
tcp_rewrite_wscale(tcp, scale_factor);
|
||||||
|
}
|
||||||
|
@ -73,4 +73,10 @@ bool proto_check_tcp(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_ipv6(uint8_t *data, size_t len);
|
bool proto_check_ipv6(uint8_t *data, size_t len);
|
||||||
void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type);
|
void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type);
|
||||||
|
|
||||||
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_ack_segment(const struct tcphdr *tcphdr);
|
||||||
|
// scale_factor=-1 - do not change
|
||||||
|
void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor);
|
||||||
|
void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_factor);
|
||||||
|
12
nfq/desync.c
12
nfq/desync.c
@ -105,6 +105,18 @@ packet_process_result dpi_desync_packet(uint8_t *data_pkt, size_t len_pkt, struc
|
|||||||
packet_process_result res=pass;
|
packet_process_result res=pass;
|
||||||
|
|
||||||
if (!!ip == !!ip6hdr) return res; // one and only one must be present
|
if (!!ip == !!ip6hdr) return res; // one and only one must be present
|
||||||
|
|
||||||
|
if (params.wsize && tcp_synack_segment(tcphdr))
|
||||||
|
{
|
||||||
|
tcp_rewrite_winsize(tcphdr, params.wsize, params.wscale);
|
||||||
|
res=modify;
|
||||||
|
}
|
||||||
|
if (params.wssize && !tcp_synack_segment(tcphdr))
|
||||||
|
{
|
||||||
|
tcp_rewrite_winsize(tcphdr, params.wssize, params.wsscale);
|
||||||
|
res=modify;
|
||||||
|
}
|
||||||
|
|
||||||
if (params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu
|
if (params.desync_mode==DESYNC_NONE && !params.hostcase && !params.hostnospace && !params.domcase) return res; // nothing to do. do not waste cpu
|
||||||
|
|
||||||
if (!(tcphdr->th_flags & TH_SYN) && len_payload)
|
if (!(tcphdr->th_flags & TH_SYN) && len_payload)
|
||||||
|
141
nfq/nfqws.c
141
nfq/nfqws.c
@ -66,28 +66,6 @@ static void dohup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize)
|
|
||||||
{
|
|
||||||
uint16_t winsize_old;
|
|
||||||
winsize_old = htons(tcp->th_win); // << scale_factor;
|
|
||||||
tcp->th_win = htons(winsize);
|
|
||||||
DLOG("Window size change %u => %u\n", winsize_old, winsize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// data/len points to data payload
|
|
||||||
static bool modify_tcp_packet(uint8_t *data, size_t len, struct tcphdr *tcphdr)
|
|
||||||
{
|
|
||||||
if (tcp_synack_segment(tcphdr) && params.wsize)
|
|
||||||
{
|
|
||||||
tcp_rewrite_winsize(tcphdr, (uint16_t)params.wsize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt, uint32_t *mark)
|
static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt, uint32_t *mark)
|
||||||
#else
|
#else
|
||||||
@ -99,7 +77,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
|||||||
struct tcphdr *tcphdr = NULL;
|
struct tcphdr *tcphdr = NULL;
|
||||||
size_t len = len_pkt, len_tcp;
|
size_t len = len_pkt, len_tcp;
|
||||||
uint8_t *data = data_pkt;
|
uint8_t *data = data_pkt;
|
||||||
packet_process_result res = pass, res2;
|
packet_process_result res = pass;
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -152,11 +130,7 @@ static packet_process_result processPacketData(uint8_t *data_pkt, size_t len_pkt
|
|||||||
|
|
||||||
if (len) { DLOG("TCP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
if (len) { DLOG("TCP: ") hexdump_limited_dlog(data, len, 32); DLOG("\n") }
|
||||||
|
|
||||||
if (modify_tcp_packet(data, len, tcphdr))
|
res = dpi_desync_packet(data_pkt, len_pkt, ip, ip6hdr, tcphdr, len_tcp, data, len);
|
||||||
res = modify;
|
|
||||||
|
|
||||||
res2 = dpi_desync_packet(data_pkt, len_pkt, ip, ip6hdr, tcphdr, len_tcp, data, len);
|
|
||||||
res = (res2==pass && res==modify) ? modify : res2;
|
|
||||||
// in my FreeBSD divert tests only ipv4 packets were reinjected with correct checksum
|
// in my FreeBSD divert tests only ipv4 packets were reinjected with correct checksum
|
||||||
// ipv6 packets were with incorrect checksum
|
// ipv6 packets were with incorrect checksum
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
@ -444,6 +418,33 @@ exiterr:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static bool parse_scale_factor(char *s, uint16_t *wsize, uint8_t *wscale)
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if ((p = strchr(s,':'))) *p++=0;
|
||||||
|
v = atoi(s);
|
||||||
|
if (v < 0 || v>65535)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad wsize\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*wsize=(uint16_t)v;
|
||||||
|
if (p && *p)
|
||||||
|
{
|
||||||
|
v = atoi(p);
|
||||||
|
if (v < 0 || v>255)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad wscale\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*wscale = (uint8_t)v;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void exithelp()
|
static void exithelp()
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
@ -457,7 +458,8 @@ static void exithelp()
|
|||||||
" --pidfile=<filename>\t\t\t; write pid to file\n"
|
" --pidfile=<filename>\t\t\t; write pid to file\n"
|
||||||
" --user=<username>\t\t\t; drop root privs\n"
|
" --user=<username>\t\t\t; drop root privs\n"
|
||||||
" --uid=uid[:gid]\t\t\t; drop root privs\n"
|
" --uid=uid[:gid]\t\t\t; drop root privs\n"
|
||||||
" --wsize=<window_size>\t\t\t; set window size. 0 = do not modify. OBSOLETE !\n"
|
" --wsize=<window_size>[:<scale_factor>]\t; set window size. 0 = do not modify. OBSOLETE !\n"
|
||||||
|
" --wssize=<window_size>[:<scale_factor>]; set window size for server. 0 = do not modify.\n"
|
||||||
" --hostcase\t\t\t\t; change Host: => host:\n"
|
" --hostcase\t\t\t\t; change Host: => host:\n"
|
||||||
" --hostspell\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
" --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"
|
" --hostnospace\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||||
@ -528,6 +530,8 @@ int main(int argc, char **argv)
|
|||||||
memcpy(params.fake_tls,fake_tls_clienthello_default,params.fake_tls_size);
|
memcpy(params.fake_tls,fake_tls_clienthello_default,params.fake_tls_size);
|
||||||
params.fake_http_size = strlen(fake_http_request_default);
|
params.fake_http_size = strlen(fake_http_request_default);
|
||||||
memcpy(params.fake_http,fake_http_request_default,params.fake_http_size);
|
memcpy(params.fake_http,fake_http_request_default,params.fake_http_size);
|
||||||
|
params.wscale=-1; // default - dont change scale factor (client)
|
||||||
|
|
||||||
if (can_drop_root()) // are we root ?
|
if (can_drop_root()) // are we root ?
|
||||||
{
|
{
|
||||||
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
||||||
@ -548,28 +552,29 @@ int main(int argc, char **argv)
|
|||||||
{"user",required_argument,0,0 }, // optidx=4
|
{"user",required_argument,0,0 }, // optidx=4
|
||||||
{"uid",required_argument,0,0 }, // optidx=5
|
{"uid",required_argument,0,0 }, // optidx=5
|
||||||
{"wsize",required_argument,0,0}, // optidx=6
|
{"wsize",required_argument,0,0}, // optidx=6
|
||||||
{"hostcase",no_argument,0,0}, // optidx=7
|
{"wssize",required_argument,0,0}, // optidx=7
|
||||||
{"hostspell",required_argument,0,0}, // optidx=8
|
{"hostcase",no_argument,0,0}, // optidx=8
|
||||||
{"hostnospace",no_argument,0,0}, // optidx=9
|
{"hostspell",required_argument,0,0}, // optidx=9
|
||||||
{"domcase",no_argument,0,0 }, // optidx=10
|
{"hostnospace",no_argument,0,0}, // optidx=10
|
||||||
{"dpi-desync",required_argument,0,0}, // optidx=11
|
{"domcase",no_argument,0,0 }, // optidx=11
|
||||||
|
{"dpi-desync",required_argument,0,0}, // optidx=12
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=12
|
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=13
|
||||||
#elif defined(SO_USER_COOKIE)
|
#elif defined(SO_USER_COOKIE)
|
||||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=12
|
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=13
|
||||||
#else
|
#else
|
||||||
{"disabled_argument_2",no_argument,0,0}, // optidx=12
|
{"disabled_argument_2",no_argument,0,0}, // optidx=13
|
||||||
#endif
|
#endif
|
||||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=13
|
{"dpi-desync-ttl",required_argument,0,0}, // optidx=14
|
||||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=14
|
{"dpi-desync-fooling",required_argument,0,0}, // optidx=15
|
||||||
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=15
|
{"dpi-desync-retrans",optional_argument,0,0}, // optidx=16
|
||||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=16
|
{"dpi-desync-repeats",required_argument,0,0}, // optidx=17
|
||||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=17
|
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=18
|
||||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=18
|
{"dpi-desync-split-pos",required_argument,0,0},// optidx=19
|
||||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=19
|
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=20
|
||||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=20
|
{"dpi-desync-fake-http",required_argument,0,0},// optidx=21
|
||||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=21
|
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=22
|
||||||
{"hostlist",required_argument,0,0}, // optidx=22
|
{"hostlist",required_argument,0,0}, // optidx=23
|
||||||
{NULL,0,NULL,0}
|
{NULL,0,NULL,0}
|
||||||
};
|
};
|
||||||
if (argc < 2) exithelp();
|
if (argc < 2) exithelp();
|
||||||
@ -631,17 +636,17 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6: /* wsize */
|
case 6: /* wsize */
|
||||||
params.wsize = atoi(optarg);
|
if (!parse_scale_factor(optarg,¶ms.wsize,¶ms.wscale))
|
||||||
if (params.wsize < 0 || params.wsize>65535)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "bad wsize\n");
|
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 7: /* hostcase */
|
case 7: /* wssize */
|
||||||
|
if (!parse_scale_factor(optarg,¶ms.wssize,¶ms.wsscale))
|
||||||
|
exit_clean(1);
|
||||||
|
break;
|
||||||
|
case 8: /* hostcase */
|
||||||
params.hostcase = true;
|
params.hostcase = true;
|
||||||
break;
|
break;
|
||||||
case 8: /* hostspell */
|
case 9: /* hostspell */
|
||||||
if (strlen(optarg) != 4)
|
if (strlen(optarg) != 4)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "hostspell must be exactly 4 chars long\n");
|
fprintf(stderr, "hostspell must be exactly 4 chars long\n");
|
||||||
@ -650,13 +655,13 @@ int main(int argc, char **argv)
|
|||||||
params.hostcase = true;
|
params.hostcase = true;
|
||||||
memcpy(params.hostspell, optarg, 4);
|
memcpy(params.hostspell, optarg, 4);
|
||||||
break;
|
break;
|
||||||
case 9: /* hostnospace */
|
case 10: /* hostnospace */
|
||||||
params.hostnospace = true;
|
params.hostnospace = true;
|
||||||
break;
|
break;
|
||||||
case 10: /* domcase */
|
case 11: /* domcase */
|
||||||
params.domcase = true;
|
params.domcase = true;
|
||||||
break;
|
break;
|
||||||
case 11: /* dpi-desync */
|
case 12: /* dpi-desync */
|
||||||
{
|
{
|
||||||
char *mode2;
|
char *mode2;
|
||||||
mode2 = optarg ? strchr(optarg,',') : NULL;
|
mode2 = optarg ? strchr(optarg,',') : NULL;
|
||||||
@ -676,7 +681,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 12: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
case 13: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||||
params.desync_fwmark = 0;
|
params.desync_fwmark = 0;
|
||||||
if (!sscanf(optarg, "0x%X", ¶ms.desync_fwmark)) sscanf(optarg, "%u", ¶ms.desync_fwmark);
|
if (!sscanf(optarg, "0x%X", ¶ms.desync_fwmark)) sscanf(optarg, "%u", ¶ms.desync_fwmark);
|
||||||
@ -690,10 +695,10 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 13: /* dpi-desync-ttl */
|
case 14: /* dpi-desync-ttl */
|
||||||
params.desync_ttl = (uint8_t)atoi(optarg);
|
params.desync_ttl = (uint8_t)atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 14: /* dpi-desync-fooling */
|
case 15: /* dpi-desync-fooling */
|
||||||
{
|
{
|
||||||
char *e,*p = optarg;
|
char *e,*p = optarg;
|
||||||
while (p)
|
while (p)
|
||||||
@ -722,7 +727,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 15: /* dpi-desync-retrans */
|
case 16: /* dpi-desync-retrans */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.desync_retrans = !optarg || atoi(optarg);
|
params.desync_retrans = !optarg || atoi(optarg);
|
||||||
#else
|
#else
|
||||||
@ -730,7 +735,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 16: /* dpi-desync-repeats */
|
case 17: /* dpi-desync-repeats */
|
||||||
params.desync_repeats = atoi(optarg);
|
params.desync_repeats = atoi(optarg);
|
||||||
if (params.desync_repeats<=0 || params.desync_repeats>20)
|
if (params.desync_repeats<=0 || params.desync_repeats>20)
|
||||||
{
|
{
|
||||||
@ -738,10 +743,10 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 17: /* dpi-desync-skip-nosni */
|
case 18: /* dpi-desync-skip-nosni */
|
||||||
params.desync_skip_nosni = !optarg || atoi(optarg);
|
params.desync_skip_nosni = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 18: /* dpi-desync-split-pos */
|
case 19: /* dpi-desync-split-pos */
|
||||||
params.desync_split_pos = atoi(optarg);
|
params.desync_split_pos = atoi(optarg);
|
||||||
if (params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN)
|
if (params.desync_split_pos<1 || params.desync_split_pos>DPI_DESYNC_MAX_FAKE_LEN)
|
||||||
{
|
{
|
||||||
@ -749,10 +754,10 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 19: /* dpi-desync-any-protocol */
|
case 20: /* dpi-desync-any-protocol */
|
||||||
params.desync_any_proto = !optarg || atoi(optarg);
|
params.desync_any_proto = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 20: /* dpi-desync-fake-http */
|
case 21: /* dpi-desync-fake-http */
|
||||||
params.fake_http_size = sizeof(params.fake_http);
|
params.fake_http_size = sizeof(params.fake_http);
|
||||||
if (!load_file_nonempty(optarg,params.fake_http,¶ms.fake_http_size))
|
if (!load_file_nonempty(optarg,params.fake_http,¶ms.fake_http_size))
|
||||||
{
|
{
|
||||||
@ -760,7 +765,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 21: /* dpi-desync-fake-tls */
|
case 22: /* dpi-desync-fake-tls */
|
||||||
params.fake_tls_size = sizeof(params.fake_tls);
|
params.fake_tls_size = sizeof(params.fake_tls);
|
||||||
if (!load_file_nonempty(optarg,params.fake_tls,¶ms.fake_tls_size))
|
if (!load_file_nonempty(optarg,params.fake_tls,¶ms.fake_tls_size))
|
||||||
{
|
{
|
||||||
@ -768,7 +773,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 22: /* hostlist */
|
case 23: /* hostlist */
|
||||||
if (!LoadHostList(¶ms.hostlist, optarg))
|
if (!LoadHostList(¶ms.hostlist, optarg))
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
|
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
struct params_s
|
struct params_s
|
||||||
{
|
{
|
||||||
bool debug;
|
bool debug;
|
||||||
int wsize;
|
uint16_t wsize,wssize;
|
||||||
|
uint8_t wscale,wsscale;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int qnum;
|
int qnum;
|
||||||
#elif defined(BSD)
|
#elif defined(BSD)
|
||||||
|
Loading…
Reference in New Issue
Block a user