mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-19 07:45:49 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46a7632f59 | ||
|
|
0642969a2d | ||
|
|
13af2ec1be | ||
|
|
50a1bb72d9 | ||
|
|
1696f1b552 | ||
|
|
b0ce5c0c1b | ||
|
|
87943846d9 | ||
|
|
8b359d0410 | ||
|
|
0430d9d9cd | ||
|
|
efcc1477dd | ||
|
|
100fff0461 | ||
|
|
1d14f8b0a4 | ||
|
|
6e5c6511d3 | ||
|
|
491a24d671 | ||
|
|
505e8ff82c | ||
|
|
1bbc56dc1b | ||
|
|
ad60550bf3 | ||
|
|
3043963e28 | ||
|
|
664bc60175 | ||
|
|
815801a7db | ||
|
|
05f54086cf | ||
|
|
b7a5f0410f | ||
|
|
da8bb9f5b8 | ||
|
|
9e52d767d1 | ||
|
|
3ff06303cb | ||
|
|
2a5c036909 | ||
|
|
a6e11540ff | ||
|
|
347c35e588 | ||
|
|
ea28460f1d | ||
|
|
0ac5df9d0e | ||
|
|
63767929a0 | ||
|
|
026c832f3f | ||
|
|
53ef85773e | ||
|
|
c41353cb8a | ||
|
|
d2f6c18adf | ||
|
|
00d1406791 | ||
|
|
a38acae652 | ||
|
|
90a991b5ee | ||
|
|
686721f96a | ||
|
|
479b067f1a | ||
|
|
ea1f34c833 | ||
|
|
b4fe028cb7 | ||
|
|
39c3640477 | ||
|
|
2236a95d49 | ||
|
|
8bb03d68b5 | ||
|
|
7b2a9a26ed |
@@ -25,7 +25,7 @@ filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of nfqws params
|
||||
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parmNA
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 param11 param12 param13 parmNA
|
||||
eval v="\$$1"
|
||||
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||
@@ -40,14 +40,15 @@ filter_apply_hostlist_target()
|
||||
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
|
||||
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
||||
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm9="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm11="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm12="--hostlist=$HOSTLIST_AUTO"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_RESET:+--hostlist-auto-retrans-reset=$AUTOHOSTLIST_RETRANS_RESET}"
|
||||
parm9="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm11="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm12="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm13="--hostlist=$HOSTLIST_AUTO"
|
||||
}
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm10:+ $parm12}"
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}${parm12:+ $parm12}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm13:+ $parm13}"
|
||||
}
|
||||
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
|
||||
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
||||
|
||||
@@ -30,6 +30,7 @@ IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||
# NOTE : set PKT_IN, PKT_OUT variables appropriately
|
||||
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
|
||||
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
|
||||
AUTOHOSTLIST_RETRANS_RESET=1
|
||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_TIME=60
|
||||
|
||||
@@ -125,3 +125,11 @@ v0.7.5
|
||||
* ipset: remove get_reestr_hostlist.sh and get_reestr_resolve.sh because zapret-info does not and will probably not ever update
|
||||
* nfqws2: fix "reasm cancelled" if no incoming traffic redirected
|
||||
* blockcheck2: MULTIDISORDER=multidisorder_legacy
|
||||
|
||||
v0.7.6
|
||||
|
||||
* nfqws2: reevaluate profile on l7/host discovery in any direction
|
||||
* nfqws2: dtls protocol detection
|
||||
* nfqws2: autohostlist reset retransmitter to break long wait
|
||||
* zapret-auto: stadard_failure_detector reset retransmitter to break long wait
|
||||
* nfqws2, init.d, windivert : dht and wg detection changes
|
||||
|
||||
1921
docs/manual.md
1921
docs/manual.md
File diff suppressed because it is too large
Load Diff
@@ -301,18 +301,15 @@ nfqws2 --lua-desync=send:ipfrag:ipfrag_pos_udp=8 --lua-desync=drop
|
||||
Но это решаемо. А что не решаемо - это перехват вторых частей kyber tls hello. Их невозможно опознать без связи с предыдущими фрагментами. Поэтому перехватывается весь порт.
|
||||
Для HTTP вопрос решаемый, поскольку там нет реассемблирования запросов, но http сейчас стал настолько редким, что и смысла нет заморачиваться.
|
||||
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`.
|
||||
Зачем ? В основном для сокращения вызовов LUA кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с LUA - ни о каком вызове кода LUA речи быть не может.
|
||||
Если пакет попал в профиль с LUA, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все LUA инстансы входят в состояние instance cutoff,
|
||||
соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов LUA не будет вообще. Не просто вызовов, а даже обращения к движку LUA
|
||||
с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`. Зачем ? В основном для сокращения вызовов LUA кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с LUA - ни о каком вызове кода LUA речи быть не может. Если пакет попал в профиль с LUA, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все LUA инстансы входят в состояние instance cutoff, соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов LUA не будет вообще. Не просто вызовов, а даже обращения к движку LUA с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
|
||||
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы LUA даже в пределах первых 10 пакетов с данными.
|
||||
С другой стороны, даже при совпадении протокола соединения (`--filter-l7`) может пробежать не интересующий нас пейлоад.
|
||||
По умолчанию многие функции из `zapret-antidpi.lua` реагируют только на известные типы пейлоада, но не на конкретные, а на любые известные.
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp,
|
||||
то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp, то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
пейлоады могут проскакивать нескольких типов вполне ожидаемо. Но работать надо не по всем.
|
||||
|
||||
В фейке для TLS по умолчанию - fake_default_tls - однократно при старте меняется SNI с "www.microsoft.com" на случайный и рандомизируется поле "random" в TLS handshake.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
|
||||
# this custom script runs desync to DHT packets with udp payload length >=5 , without ipset/hostlist filtering
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
@@ -21,9 +21,9 @@ zapret_custom_firewall()
|
||||
local f uf4 uf6
|
||||
local first_packet_only="$ipt_connbytes 1:1"
|
||||
|
||||
f='-p udp -m length --length 109:407 -m u32 --u32'
|
||||
uf4='0>>22&0x3C@8>>16=0x6431'
|
||||
uf6='48>>16=0x6431'
|
||||
f='-p udp -m u32 --u32'
|
||||
uf4='0>>22&0x3C@4>>16=13:0xFFFF&&0>>22&0x3C@8>>16=0x6431:0x6432'
|
||||
uf6='44>>16=13:0xFFFF&&48>>16=0x6431:0x6432'
|
||||
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
@@ -33,6 +33,6 @@ zapret_custom_firewall_nft()
|
||||
local f
|
||||
local first_packet_only="$nft_connbytes 1"
|
||||
|
||||
f="meta length 109-407 meta l4proto udp @ih,0,16 0x6431"
|
||||
f="udp length ge 13 meta l4proto udp @ih,0,16 0x6431-0x6432"
|
||||
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
|
||||
}
|
||||
|
||||
1
init.d/windivert.filter.examples/windivert_part.dht.txt
Normal file
1
init.d/windivert.filter.examples/windivert_part.dht.txt
Normal file
@@ -0,0 +1 @@
|
||||
udp.Length>=5 and udp.Payload[0]=0x64 and udp.Payload[1]>=0x31 and udp.Payload[1]<=0x32
|
||||
@@ -1,4 +1,4 @@
|
||||
outbound and
|
||||
udp.PayloadLength>=256 and
|
||||
udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and
|
||||
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||
@@ -1,3 +1,3 @@
|
||||
outbound and
|
||||
udp.PayloadLength=148 and
|
||||
udp.Payload[0]=0x01
|
||||
udp.PayloadLength=148 and udp.Payload[0]=0x01 or
|
||||
udp.PayloadLength=92 and udp.Payload[0]=0x02 or
|
||||
udp.PayloadLength=64 and udp.Payload[0]=0x03
|
||||
@@ -122,7 +122,8 @@ function standard_detector_defaults(arg)
|
||||
udp_in = tonumber(arg.udp_in) or 1,
|
||||
udp_out = tonumber(arg.udp_out) or 4,
|
||||
no_http_redirect = arg.no_http_redirect,
|
||||
no_rst = arg.no_rst
|
||||
no_rst = arg.no_rst,
|
||||
reset = arg.reset
|
||||
}
|
||||
end
|
||||
|
||||
@@ -135,6 +136,7 @@ end
|
||||
-- udp too much out with too few in
|
||||
-- arg: maxseq=<rseq> - tcp: test retransmissions only within this relative sequence. default is 32K
|
||||
-- arg: retrans=N - tcp: retrans count threshold. default is 3
|
||||
-- arg: reset - send RST to retransmitter to break long wait
|
||||
-- arg: inseq=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 4K
|
||||
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
|
||||
-- arg: no_rst - tcp: disable incoming RST trigger
|
||||
@@ -151,6 +153,19 @@ function standard_failure_detector(desync, crec)
|
||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
|
||||
trigger = crec.retrans>=arg.retrans
|
||||
if trigger and arg.reset then
|
||||
local dis = deepcopy(desync.dis)
|
||||
dis.payload = nil
|
||||
dis_reverse(dis)
|
||||
dis.tcp.th_flags = TH_RST
|
||||
dis.tcp.th_win = desync.track and desync.track.pos.reverse.tcp.winsize or 64
|
||||
dis.tcp.options = nil
|
||||
if dis.ip6 then
|
||||
dis.ip6.ip6_flow = (desync.track and desync.track.pos.reverse.ip6_flow) and desync.track.pos.reverse.ip6_flow or 0x60000000;
|
||||
end
|
||||
DLOG("standard_failure_detector: sending RST to retransmitter")
|
||||
rawsend_dissect(dis, {ifout = desync.ifin})
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
@@ -762,6 +762,22 @@ function fix_ip6_next(ip6, last_proto)
|
||||
end
|
||||
end
|
||||
|
||||
-- reverses ip addresses, ports and seq/ack
|
||||
function dis_reverse(dis)
|
||||
if dis.ip then
|
||||
dis.ip.ip_src, dis.ip.ip_dst = dis.ip.ip_dst, dis.ip.ip_src
|
||||
end
|
||||
if dis.ip6 then
|
||||
dis.ip6.ip6_src, dis.ip6.ip6_dst = dis.ip6.ip6_dst, dis.ip6.ip6_src
|
||||
end
|
||||
if dis.tcp then
|
||||
dis.tcp.th_sport, dis.tcp.th_dport = dis.tcp.th_dport, dis.tcp.th_sport
|
||||
dis.tcp.th_ack, dis.tcp.th_seq = dis.tcp.th_seq, dis.tcp.th_ack
|
||||
end
|
||||
if dis.udp then
|
||||
dis.udp.uh_sport, dis.udp.uh_dport = dis.udp.uh_dport, dis.udp.uh_sport
|
||||
end
|
||||
end
|
||||
|
||||
-- parse autottl : delta,min-max
|
||||
function parse_autottl(s)
|
||||
@@ -1300,7 +1316,7 @@ function wsize_rewrite(dis, arg)
|
||||
local b = false
|
||||
if arg.wsize then
|
||||
local wsize = tonumber(arg.wsize)
|
||||
DLOG("window size "..dis.tcp.th_win.." => "..wsize)
|
||||
DLOG("wsize_rewrite: window size "..dis.tcp.th_win.." => "..wsize)
|
||||
dis.tcp.th_win = tonumber(arg.wsize)
|
||||
b = true
|
||||
end
|
||||
@@ -1310,9 +1326,9 @@ function wsize_rewrite(dis, arg)
|
||||
if i then
|
||||
local oldscale = u8(dis.tcp.options[i].data)
|
||||
if scale>oldscale then
|
||||
DLOG("not increasing scale factor")
|
||||
DLOG("wsize_rewrite: not increasing scale factor")
|
||||
elseif scale<oldscale then
|
||||
DLOG("scale factor "..oldscale.." => "..scale)
|
||||
DLOG("wsize_rewrite: scale factor "..oldscale.." => "..scale)
|
||||
dis.tcp.options[i].data = bu8(scale)
|
||||
b = true
|
||||
end
|
||||
|
||||
@@ -6,7 +6,6 @@ function pcap_write_packet(file, raw)
|
||||
local sec, nsec = clock_gettime();
|
||||
file:write(bu32(sec)..bu32(nsec)..bu32(#raw)..bu32(#raw))
|
||||
file:write(raw)
|
||||
file:close()
|
||||
end
|
||||
function pcap_write(file, raw)
|
||||
local pos = file:seek()
|
||||
@@ -36,4 +35,5 @@ function pcap(ctx, desync)
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
pcap_write(f, raw_packet(ctx))
|
||||
f:close()
|
||||
end
|
||||
|
||||
@@ -2,64 +2,65 @@
|
||||
#include "checksum.h"
|
||||
#include <netinet/in.h>
|
||||
|
||||
//#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
//#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
// #define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
// #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
|
||||
static uint16_t from64to16(uint64_t x)
|
||||
{
|
||||
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x>>16) + (uint16_t)(x>>32) + (uint16_t)(x>>48);
|
||||
return (uint16_t)u + (uint16_t)(u>>16);
|
||||
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x >> 16) + (uint16_t)(x >> 32) + (uint16_t)(x >> 48);
|
||||
return (uint16_t)u + (uint16_t)(u >> 16);
|
||||
}
|
||||
|
||||
// this function preserves data alignment requirements (otherwise it will be damn slow on mips arch)
|
||||
// and uses 64-bit arithmetics to improve speed
|
||||
// taken from linux source code
|
||||
static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
static uint16_t do_csum(const uint8_t *buff, size_t len)
|
||||
{
|
||||
uint8_t odd;
|
||||
size_t count;
|
||||
uint64_t result,w,carry=0;
|
||||
uint64_t result, w, carry = 0;
|
||||
uint16_t u16;
|
||||
|
||||
if (!len) return 0;
|
||||
if (!len)
|
||||
return 0;
|
||||
odd = (uint8_t)(1 & (size_t)buff);
|
||||
if (odd)
|
||||
{
|
||||
// any endian compatible
|
||||
u16 = 0;
|
||||
*((uint8_t*)&u16+1) = *buff;
|
||||
*((uint8_t *)&u16 + 1) = *buff;
|
||||
result = u16;
|
||||
len--;
|
||||
buff++;
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
count = len >> 1; /* nr of 16-bit words.. */
|
||||
count = len >> 1; /* nr of 16-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
if (2 & (size_t) buff)
|
||||
if (2 & (size_t)buff)
|
||||
{
|
||||
result += *(uint16_t *) buff;
|
||||
result += *(uint16_t *)buff;
|
||||
count--;
|
||||
len -= 2;
|
||||
buff += 2;
|
||||
}
|
||||
count >>= 1; /* nr of 32-bit words.. */
|
||||
count >>= 1; /* nr of 32-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
if (4 & (size_t) buff)
|
||||
if (4 & (size_t)buff)
|
||||
{
|
||||
result += *(uint32_t *) buff;
|
||||
result += *(uint32_t *)buff;
|
||||
count--;
|
||||
len -= 4;
|
||||
buff += 4;
|
||||
}
|
||||
count >>= 1; /* nr of 64-bit words.. */
|
||||
count >>= 1; /* nr of 64-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
do
|
||||
{
|
||||
w = *(uint64_t *) buff;
|
||||
w = *(uint64_t *)buff;
|
||||
count--;
|
||||
buff += 8;
|
||||
result += carry;
|
||||
@@ -71,13 +72,13 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
}
|
||||
if (len & 4)
|
||||
{
|
||||
result += *(uint32_t *) buff;
|
||||
result += *(uint32_t *)buff;
|
||||
buff += 4;
|
||||
}
|
||||
}
|
||||
if (len & 2)
|
||||
{
|
||||
result += *(uint16_t *) buff;
|
||||
result += *(uint16_t *)buff;
|
||||
buff += 2;
|
||||
}
|
||||
}
|
||||
@@ -85,54 +86,54 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
{
|
||||
// any endian compatible
|
||||
u16 = 0;
|
||||
*(uint8_t*)&u16 = *buff;
|
||||
*(uint8_t *)&u16 = *buff;
|
||||
result += u16;
|
||||
}
|
||||
u16 = from64to16(result);
|
||||
if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
|
||||
if (odd)
|
||||
u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
|
||||
return u16;
|
||||
}
|
||||
|
||||
uint16_t csum_partial(const void *buff, size_t len)
|
||||
{
|
||||
return do_csum(buff,len);
|
||||
return do_csum(buff, len);
|
||||
}
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len+proto));
|
||||
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len + proto));
|
||||
}
|
||||
|
||||
uint16_t ip4_compute_csum(const void *buff, size_t len)
|
||||
{
|
||||
return ~from64to16(do_csum(buff,len));
|
||||
return ~from64to16(do_csum(buff, len));
|
||||
}
|
||||
void ip4_fix_checksum(struct ip *ip)
|
||||
{
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl<<2);
|
||||
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl << 2);
|
||||
}
|
||||
|
||||
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
uint64_t a = (uint64_t)sum + htonl(len+proto) +
|
||||
*(uint32_t*)saddr + *((uint32_t*)saddr+1) + *((uint32_t*)saddr+2) + *((uint32_t*)saddr+3) +
|
||||
*(uint32_t*)daddr + *((uint32_t*)daddr+1) + *((uint32_t*)daddr+2) + *((uint32_t*)daddr+3);
|
||||
uint64_t a = (uint64_t)sum + htonl(len + proto) +
|
||||
*(uint32_t *)saddr + *((uint32_t *)saddr + 1) + *((uint32_t *)saddr + 2) + *((uint32_t *)saddr + 3) +
|
||||
*(uint32_t *)daddr + *((uint32_t *)daddr + 1) + *((uint32_t *)daddr + 2) + *((uint32_t *)daddr + 3);
|
||||
return ~from64to16(a);
|
||||
}
|
||||
|
||||
|
||||
void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
void tcp4_fix_checksum(struct tcphdr *tcp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
{
|
||||
tcp->th_sum = 0;
|
||||
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
|
||||
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
|
||||
}
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
tcp->th_sum = 0;
|
||||
tcp->th_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
|
||||
tcp->th_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
|
||||
}
|
||||
void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
|
||||
void tcp_fix_checksum(struct tcphdr *tcp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip)
|
||||
tcp4_fix_checksum(tcp, len, &ip->ip_src, &ip->ip_dst);
|
||||
@@ -140,17 +141,17 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
|
||||
tcp6_fix_checksum(tcp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
|
||||
}
|
||||
|
||||
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
void udp4_fix_checksum(struct udphdr *udp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
{
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_UDP,csum_partial(udp,len));
|
||||
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_UDP, csum_partial(udp, len));
|
||||
}
|
||||
void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
void udp6_fix_checksum(struct udphdr *udp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_UDP,csum_partial(udp,len));
|
||||
udp->uh_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_UDP, csum_partial(udp, len));
|
||||
}
|
||||
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
|
||||
void udp_fix_checksum(struct udphdr *udp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip)
|
||||
udp4_fix_checksum(udp, len, &ip->ip_src, &ip->ip_dst);
|
||||
|
||||
@@ -70,24 +70,24 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
|
||||
p->pool = NULL;
|
||||
}
|
||||
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
memset(c, 0, sizeof(*c));
|
||||
if (ip)
|
||||
if (dis->ip)
|
||||
{
|
||||
c->l3proto = IPPROTO_IP;
|
||||
c->dst.ip = bReverse ? ip->ip_src : ip->ip_dst;
|
||||
c->src.ip = bReverse ? ip->ip_dst : ip->ip_src;
|
||||
c->dst.ip = bReverse ? dis->ip->ip_src : dis->ip->ip_dst;
|
||||
c->src.ip = bReverse ? dis->ip->ip_dst : dis->ip->ip_src;
|
||||
}
|
||||
else if (ip6)
|
||||
else if (dis->ip6)
|
||||
{
|
||||
c->l3proto = IPPROTO_IPV6;
|
||||
c->dst.ip6 = bReverse ? ip6->ip6_src : ip6->ip6_dst;
|
||||
c->src.ip6 = bReverse ? ip6->ip6_dst : ip6->ip6_src;
|
||||
c->dst.ip6 = bReverse ? dis->ip6->ip6_src : dis->ip6->ip6_dst;
|
||||
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
|
||||
}
|
||||
else
|
||||
c->l3proto = -1;
|
||||
extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||
return ctnew;
|
||||
}
|
||||
|
||||
static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bReverse, uint32_t len_payload)
|
||||
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
@@ -136,21 +136,23 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever
|
||||
direct = bReverse ? &t->pos.server : &t->pos.client;
|
||||
reverse = bReverse ? &t->pos.client : &t->pos.server;
|
||||
|
||||
scale = tcp_find_scale_factor(tcp);
|
||||
mss = ntohs(tcp_find_mss(tcp));
|
||||
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
|
||||
|
||||
direct->seq_last = ntohl(tcp->th_seq);
|
||||
direct->pos = direct->seq_last + len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(tcp->th_ack);
|
||||
scale = tcp_find_scale_factor(dis->tcp);
|
||||
mss = ntohs(tcp_find_mss(dis->tcp));
|
||||
|
||||
direct->seq_last = ntohl(dis->tcp->th_seq);
|
||||
direct->pos = direct->seq_last + dis->len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack);
|
||||
if (t->pos.state == SYN)
|
||||
direct->uppos_prev = direct->uppos = direct->pos;
|
||||
else if (len_payload)
|
||||
else if (dis->len_payload)
|
||||
{
|
||||
direct->uppos_prev = direct->uppos;
|
||||
if (!((direct->pos - direct->uppos) & 0x80000000))
|
||||
direct->uppos = direct->pos;
|
||||
}
|
||||
direct->winsize = ntohs(tcp->th_win);
|
||||
direct->winsize = ntohs(dis->tcp->th_win);
|
||||
direct->winsize_calc = direct->winsize;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
@@ -162,8 +164,7 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever
|
||||
reverse->rseq_over_2G = true;
|
||||
}
|
||||
|
||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
@@ -171,34 +172,34 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.server.pcounter++;
|
||||
t->pos.server.pdcounter += !!len_payload;
|
||||
t->pos.server.pbcounter += len_payload;
|
||||
t->pos.server.pdcounter += !!dis->len_payload;
|
||||
t->pos.server.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
t->pos.client.pcounter++;
|
||||
t->pos.client.pdcounter += !!len_payload;
|
||||
t->pos.client.pbcounter += len_payload;
|
||||
t->pos.client.pdcounter += !!dis->len_payload;
|
||||
t->pos.client.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
if (tcphdr)
|
||||
if (dis->tcp)
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
if (tcp_syn_segment(dis->tcp))
|
||||
{
|
||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->pos.client.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.client.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
else if (tcp_synack_segment(dis->tcp))
|
||||
{
|
||||
// ignore SA dups
|
||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
|
||||
ConntrackReInitTrack(t); // erase current entry
|
||||
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
|
||||
t->pos.server.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.server.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||
else if (dis->tcp->th_flags & (TH_FIN | TH_RST))
|
||||
{
|
||||
t->pos.state = FIN;
|
||||
}
|
||||
@@ -207,11 +208,11 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
t->pos.state = ESTABLISHED;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
ConntrackApplyPos(tcphdr, t, bReverse, len_payload);
|
||||
ConntrackApplyPos(t, bReverse, dis);
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
|
||||
@@ -219,12 +220,12 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (!t->t_start.tv_sec) t->t_start = t->pos.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)
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
if (bReverse) *bReverse = false;
|
||||
@@ -243,22 +244,22 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip
|
||||
}
|
||||
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)
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse);
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, dis, 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 dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
bool b_rev;
|
||||
uint8_t proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
|
||||
goto ok;
|
||||
}
|
||||
else
|
||||
@@ -266,16 +267,16 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, co
|
||||
connswap(&conn, &connswp);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &connswp)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = true), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = true), dis);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
b_rev = tcphdr && tcp_synack_segment(tcphdr);
|
||||
if ((tcphdr && tcp_syn_segment(tcphdr)) || b_rev || udphdr)
|
||||
b_rev = dis->tcp && tcp_synack_segment(dis->tcp);
|
||||
if ((dis->tcp && tcp_syn_segment(dis->tcp)) || b_rev || dis->udp)
|
||||
{
|
||||
if ((ctr = ConntrackNew(pp, b_rev ? &connswp : &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, dis);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
@@ -286,16 +287,16 @@ ok:
|
||||
if (bReverse) *bReverse = b_rev;
|
||||
return true;
|
||||
}
|
||||
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 dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ConntrackPoolFeedPool(&p->pool, ip, ip6, tcphdr, udphdr, len_payload, ctrack, bReverse);
|
||||
return ConntrackPoolFeedPool(&p->pool, dis, ctrack, bReverse);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *dis)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *t;
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if (!(t = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
connswap(&conn, &connswp);
|
||||
@@ -305,9 +306,9 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co
|
||||
HASH_DEL(*pp, t); ConntrackFreeElem(t);
|
||||
return true;
|
||||
}
|
||||
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 dissect *dis)
|
||||
{
|
||||
return ConntrackPoolDropPool(&p->pool, ip, ip6, tcphdr, udphdr);
|
||||
return ConntrackPoolDropPool(&p->pool, dis);
|
||||
}
|
||||
|
||||
void ConntrackPoolPurge(t_conntrack *p)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "conntrack_base.h"
|
||||
#include "packet_queue.h"
|
||||
#include "protocol.h"
|
||||
#include "darkmagic.h"
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
@@ -100,11 +101,11 @@ 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 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 dissect *dis, 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);
|
||||
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
|
||||
void ConntrackPoolDump(const t_conntrack *p);
|
||||
void ConntrackPoolPurge(t_conntrack *p);
|
||||
void ConntrackClearHostname(t_ctrack *track);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#define CTRACK_T_SYN 60
|
||||
@@ -17,6 +18,7 @@ typedef struct
|
||||
uint64_t pcounter; // packet counter
|
||||
uint64_t pdcounter; // data packet counter (with payload)
|
||||
uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t ip6flow;
|
||||
|
||||
// tcp only state, not used in udp
|
||||
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
|
||||
@@ -547,6 +547,33 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6)
|
||||
{
|
||||
if (ip)
|
||||
{
|
||||
struct in_addr temp = ip->ip_src;
|
||||
ip->ip_src = ip->ip_dst;
|
||||
ip->ip_dst = temp;
|
||||
ip4_fix_checksum(ip);
|
||||
}
|
||||
if (ip6)
|
||||
{
|
||||
struct in6_addr temp = ip6->ip6_src;
|
||||
ip6->ip6_src = ip6->ip6_dst;
|
||||
ip6->ip6_dst = temp;
|
||||
}
|
||||
}
|
||||
void reverse_tcp(struct tcphdr *tcp)
|
||||
{
|
||||
uint16_t tport = tcp->th_sport;
|
||||
tcp->th_sport = tcp->th_dport;
|
||||
tcp->th_dport = tport;
|
||||
|
||||
uint32_t tseq = tcp->th_seq;
|
||||
tcp->th_seq = tcp->th_ack;
|
||||
tcp->th_ack = tseq;
|
||||
}
|
||||
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6)
|
||||
{
|
||||
@@ -1277,14 +1304,21 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
|
||||
{
|
||||
WINDIVERT_ADDRESS wa;
|
||||
|
||||
if (!ifout) return false;
|
||||
|
||||
memset(&wa,0,sizeof(wa));
|
||||
// pseudo interface id IfIdx.SubIfIdx
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
if (ifout && *ifout)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1 - typically loopback
|
||||
wa.Network.IfIdx=1;
|
||||
wa.Network.SubIfIdx=0;
|
||||
}
|
||||
wa.Outbound=1;
|
||||
wa.IPChecksum=1;
|
||||
|
||||
@@ -162,6 +162,8 @@ struct dissect
|
||||
size_t len_payload;
|
||||
};
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
||||
void reverse_tcp(struct tcphdr *tcp);
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
|
||||
|
||||
|
||||
393
nfq2/desync.c
393
nfq2/desync.c
@@ -246,11 +246,13 @@ static bool is_retransmission(const t_ctrack_position *pos)
|
||||
}
|
||||
|
||||
// return true if retrans trigger fires
|
||||
static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int threshold, const char *client_ip_port, t_l7proto l7proto)
|
||||
static bool auto_hostlist_retrans
|
||||
(t_ctrack *ctrack, const struct dissect *dis, int threshold, const char *client_ip_port, t_l7proto l7proto,
|
||||
const struct sockaddr *client, const char *ifclient)
|
||||
{
|
||||
if (ctrack && ctrack->dp && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP)
|
||||
{
|
||||
if (l4proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
|
||||
if (dis->proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
|
||||
{
|
||||
if (!seq_within(ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq))
|
||||
{
|
||||
@@ -269,6 +271,46 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
|
||||
DLOG("retrans threshold reached : %u/%u\n", ctrack->req_retrans_counter, threshold);
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
ctrack->failure_detect_finalized = true;
|
||||
if (dis->tcp && ctrack->dp->hostlist_auto_retrans_reset && (dis->ip || dis->ip6))
|
||||
{
|
||||
uint8_t pkt[sizeof(struct ip6_hdr)+sizeof(struct tcphdr)];
|
||||
struct ip *ip;
|
||||
struct ip6_hdr *ip6;
|
||||
struct tcphdr *tcp;
|
||||
uint16_t pktlen;
|
||||
|
||||
if (dis->ip)
|
||||
{
|
||||
ip = (struct ip*)pkt; ip6=NULL;
|
||||
pktlen = sizeof(struct ip) + sizeof(struct tcphdr);
|
||||
*ip = *dis->ip;
|
||||
ip->ip_hl = sizeof(struct ip)/4; // remove ip options
|
||||
ip->ip_len = htons(pktlen);
|
||||
ip->ip_id=0;
|
||||
tcp = (struct tcphdr*)(ip+1);
|
||||
*tcp = *dis->tcp;
|
||||
}
|
||||
else if (dis->ip6)
|
||||
{
|
||||
ip6 = (struct ip6_hdr*)pkt; ip=NULL;
|
||||
pktlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
|
||||
*ip6 = *dis->ip6;
|
||||
ip6->ip6_plen = htons(sizeof(struct tcphdr));
|
||||
ip6->ip6_nxt = IPPROTO_TCP;
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(ctrack->pos.server.ip6flow ? ctrack->pos.server.ip6flow : 0x60000000);
|
||||
tcp = (struct tcphdr*)(ip6+1);
|
||||
*tcp = *dis->tcp;
|
||||
}
|
||||
reverse_ip(ip,ip6); // also fixes ip4 checksum
|
||||
reverse_tcp(tcp);
|
||||
tcp->th_off = sizeof(struct tcphdr)/4; // remove tcp options
|
||||
tcp->th_flags = TH_RST;
|
||||
tcp->th_win = ctrack->pos.server.winsize;
|
||||
tcp_fix_checksum(tcp, sizeof(struct tcphdr), ip, ip6);
|
||||
|
||||
DLOG("sending RST to retransmitter. ifname=%s\n", ifclient ? ifclient : "");
|
||||
rawsend(client,0,ifclient,pkt,pktlen);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
DLOG("retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold);
|
||||
@@ -330,13 +372,13 @@ static void fill_client_ip_port(const struct sockaddr *client, char *client_ip_p
|
||||
else
|
||||
*client_ip_port = 0;
|
||||
}
|
||||
static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct sockaddr *client)
|
||||
static void process_retrans_fail(t_ctrack *ctrack, const struct dissect *dis, struct sockaddr *client, const char *ifclient)
|
||||
{
|
||||
if (params.server) return; // no autohostlists in server mode
|
||||
|
||||
char client_ip_port[48];
|
||||
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto))
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, dis, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto, client, ifclient))
|
||||
{
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(ctrack->dp), client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
@@ -1036,7 +1078,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
// in replay mode conntrack_replay is not NULL and ctrack is NULL
|
||||
|
||||
//ConntrackPoolDump(¶ms.conntrack);
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, &ctrack_replay, &bReverse) || bReverse)
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis, &ctrack_replay, &bReverse) || bReverse)
|
||||
return verdict;
|
||||
bReverseFixed = bReverse ^ params.server;
|
||||
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
|
||||
@@ -1068,7 +1110,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (!params.ctrack_disable)
|
||||
{
|
||||
ConntrackPoolPurge(¶ms.conntrack);
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, dis->len_payload, &ctrack, &bReverse))
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis, &ctrack, &bReverse))
|
||||
{
|
||||
dp = ctrack->dp;
|
||||
ctrack_replay = ctrack;
|
||||
@@ -1144,6 +1186,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
else
|
||||
bCheckDone = bCheckResult = bCheckExcluded = false;
|
||||
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (bReverse)
|
||||
{
|
||||
// protocol detection
|
||||
@@ -1215,7 +1258,6 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
struct blob_collection_head *fake;
|
||||
uint8_t *p, *phost = NULL;
|
||||
int i;
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
|
||||
if (replay_piece_count)
|
||||
{
|
||||
@@ -1228,7 +1270,8 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
rlen_payload = ctrack->reasm_client.size_present;
|
||||
}
|
||||
|
||||
process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src);
|
||||
process_retrans_fail(ctrack, dis, (struct sockaddr*)&src, ifin);
|
||||
|
||||
if (IsHttp(rdata_payload, rlen_payload))
|
||||
{
|
||||
DLOG("packet contains HTTP request\n");
|
||||
@@ -1313,91 +1356,90 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
{
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass_reasm_cancel;
|
||||
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
}
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (ctrack_replay)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp) goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp) goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
{
|
||||
if (!bCheckDone)
|
||||
if (ctrack_replay)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
}
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
{
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
if (!ctrack_replay->hostname_ah_check)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
}
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
if (!ctrack_replay->hostname_ah_check)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1430,6 +1472,25 @@ static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
||||
DLOG("%s\n", reason);
|
||||
}
|
||||
|
||||
static void udp_standard_protocol_probe(const uint8_t *data_payload, size_t len_payload, t_ctrack *ctrack, t_l7proto *l7proto, t_l7payload *l7payload)
|
||||
{
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
|
||||
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_DTLS_CLIENT_HELLO,L7_DTLS,IsDTLSClientHello,false},
|
||||
{L7P_DTLS_SERVER_HELLO,L7_DTLS,IsDTLSServerHello,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
|
||||
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}};
|
||||
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), data_payload, len_payload, ctrack, l7proto, l7payload);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t dpi_desync_udp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
@@ -1480,7 +1541,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
// in replay mode conntrack_replay is not NULL and ctrack is NULL
|
||||
|
||||
//ConntrackPoolDump(¶ms.conntrack);
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis->ip, dis->ip6, NULL, dis->udp, &ctrack_replay, &bReverse) || bReverse)
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis, &ctrack_replay, &bReverse) || bReverse)
|
||||
return verdict;
|
||||
bReverseFixed = bReverse ^ params.server;
|
||||
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
|
||||
@@ -1512,7 +1573,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
if (!params.ctrack_disable)
|
||||
{
|
||||
ConntrackPoolPurge(¶ms.conntrack);
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis->ip, dis->ip6, NULL, dis->udp, dis->len_payload, &ctrack, &bReverse))
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis, &ctrack, &bReverse))
|
||||
{
|
||||
dp = ctrack->dp;
|
||||
ctrack_replay = ctrack;
|
||||
@@ -1589,24 +1650,14 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
|
||||
if (dis->len_payload)
|
||||
{
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (bReverse)
|
||||
{
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
|
||||
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct blob_collection_head *fake;
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
||||
{
|
||||
DLOG("packet contains QUIC initial\n");
|
||||
@@ -1739,115 +1790,97 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
}
|
||||
else // not QUIC initial
|
||||
{
|
||||
// received payload without host. it means we are out of the request retransmission phase. stop counter
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
|
||||
// not quic initial - stop reasm
|
||||
reasm_client_cancel(ctrack);
|
||||
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
|
||||
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
}
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
{
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass;
|
||||
}
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass;
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass;
|
||||
}
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (ctrack_replay)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp)
|
||||
goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
else if (ctrack_replay)
|
||||
{
|
||||
bCheckDone = ctrack_replay->bCheckDone;
|
||||
bCheckResult = ctrack_replay->bCheckResult;
|
||||
bCheckExcluded = ctrack_replay->bCheckExcluded;
|
||||
}
|
||||
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp)
|
||||
goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
else if (ctrack_replay)
|
||||
{
|
||||
bCheckDone = ctrack_replay->bCheckDone;
|
||||
bCheckResult = ctrack_replay->bCheckResult;
|
||||
bCheckExcluded = ctrack_replay->bCheckExcluded;
|
||||
}
|
||||
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
}
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
{
|
||||
if (ctrack_replay)
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
}
|
||||
}
|
||||
if (!bCheckResult && ctrack_replay)
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
}
|
||||
|
||||
process_udp_fail(ctrack_replay, tpos, (struct sockaddr*)&src);
|
||||
|
||||
@@ -412,7 +412,7 @@ static int luacall_parse_hex(lua_State *L)
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
size_t l;
|
||||
const char *hex = lua_tolstring(L,1,&l);
|
||||
const char *hex = luaL_checklstring(L,1,&l);
|
||||
if ((l&1)) goto err;
|
||||
l>>=1;
|
||||
uint8_t *p = malloc(l);
|
||||
@@ -1276,6 +1276,7 @@ void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
lua_pushf_lint("pcounter", pos->pcounter);
|
||||
lua_pushf_lint("pdcounter", pos->pdcounter);
|
||||
lua_pushf_lint("pbcounter", pos->pbcounter);
|
||||
if (pos->ip6flow) lua_pushf_int("ip6_flow", pos->ip6flow);
|
||||
if (ctrack->ipproto == IPPROTO_TCP)
|
||||
{
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
@@ -1658,7 +1659,7 @@ bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len)
|
||||
if (lua_type(params.L,-1)==LUA_TSTRING)
|
||||
{
|
||||
p = lua_tolstring(params.L,-1,&lopt);
|
||||
if (lopt)
|
||||
if (p && lopt)
|
||||
{
|
||||
if (lopt>40 || ((sizeof(struct ip) + ((lopt+3)&~3)) > *len)) goto err;
|
||||
memcpy(ip+1,p,lopt);
|
||||
@@ -1990,7 +1991,7 @@ bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bo
|
||||
|
||||
lua_getfield(params.L,idx,"payload");
|
||||
p = lua_tolstring(params.L,-1,&lpayload);
|
||||
if (lpayload)
|
||||
if (p && lpayload)
|
||||
{
|
||||
if (left<lpayload) goto err;
|
||||
memcpy(data,p,lpayload);
|
||||
@@ -3004,6 +3005,8 @@ static void lua_init_const(void)
|
||||
{"IPTOS_ECN_CE",IPTOS_ECN_CE},
|
||||
{"IPTOS_DSCP_MASK",0xF0},
|
||||
{"IP6F_MORE_FRAG",0x0001}, // in ip6.h it's defined depending of machine byte order
|
||||
{"IPV6_FLOWLABEL_MASK",0x000FFFFF},
|
||||
{"IPV6_FLOWINFO_MASK",0x0FFFFFFF},
|
||||
|
||||
{"IPPROTO_IP",IPPROTO_IP},
|
||||
{"IPPROTO_IPV6",IPPROTO_IPV6},
|
||||
|
||||
@@ -538,7 +538,7 @@ static int dvt_main(void)
|
||||
|
||||
DLOG("\npacket: id=%u len=%zu ifin=%s ifout=%s\n", id, len, ifin, ifout);
|
||||
modlen = sizeof(buf);
|
||||
verdict = processPacketData(&mark, NULL, NULL, buf, len, buf, &modlen);
|
||||
verdict = processPacketData(&mark, ifin, ifout, buf, len, buf, &modlen);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_PASS:
|
||||
@@ -726,6 +726,7 @@ ex:
|
||||
static void exit_clean(int code)
|
||||
{
|
||||
cleanup_params(¶ms);
|
||||
|
||||
exit(code);
|
||||
}
|
||||
|
||||
@@ -1435,6 +1436,7 @@ static void exithelp(void)
|
||||
" --hostlist-auto-fail-time=<int>\t\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
" --hostlist-auto-retrans-threshold=<int>\t\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
||||
" --hostlist-auto-retrans-maxseq=<int>\t\t\t; count retransmissions only within this relative sequence (default : %u)\n"
|
||||
" --hostlist-auto-retrans-reset=[0|1]\t\t\t; send RST to retransmitter to break long wait (default: 1)\n"
|
||||
" --hostlist-auto-incoming-maxseq=<int>\t\t\t; treat tcp connection as successful if incoming relative sequence exceedes this threshold (default : %u)\n"
|
||||
" --hostlist-auto-udp-out=<int>\t\t\t\t; udp failure condition : sent at least `udp_out` packets (default : %u)\n"
|
||||
" --hostlist-auto-udp-in=<int>\t\t\t\t; udp failure condition : received not more than `udp_in` packets (default : %u)\n"
|
||||
@@ -1553,6 +1555,7 @@ enum opt_indices {
|
||||
IDX_HOSTLIST_AUTO_FAIL_TIME,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_RESET,
|
||||
IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ,
|
||||
IDX_HOSTLIST_AUTO_UDP_IN,
|
||||
IDX_HOSTLIST_AUTO_UDP_OUT,
|
||||
@@ -1641,6 +1644,7 @@ static const struct option long_options[] = {
|
||||
[IDX_HOSTLIST_AUTO_FAIL_TIME] = {"hostlist-auto-fail-time", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD] = {"hostlist-auto-retrans-threshold", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ] = {"hostlist-auto-retrans-maxseq", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_RESET] = {"hostlist-auto-retrans-reset", optional_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ] = {"hostlist-auto-incoming-maxseq", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_UDP_IN] = {"hostlist-auto-udp-in", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_UDP_OUT] = {"hostlist-auto-udp-out", required_argument, 0, 0},
|
||||
@@ -2099,6 +2103,9 @@ int main(int argc, char **argv)
|
||||
case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ:
|
||||
dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_RETRANS_RESET:
|
||||
dp->hostlist_auto_retrans_reset = !optarg || !!atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_UDP_OUT:
|
||||
dp->hostlist_auto_udp_out = atoi(optarg);
|
||||
break;
|
||||
|
||||
@@ -350,6 +350,7 @@ void dp_init(struct desync_profile *dp)
|
||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
|
||||
dp->hostlist_auto_retrans_maxseq = HOSTLIST_AUTO_RETRANS_MAXSEQ;
|
||||
dp->hostlist_auto_retrans_reset = true;
|
||||
dp->hostlist_auto_incoming_maxseq = HOSTLIST_AUTO_INCOMING_MAXSEQ;
|
||||
dp->hostlist_auto_udp_out = HOSTLIST_AUTO_UDP_OUT;
|
||||
dp->hostlist_auto_udp_in = HOSTLIST_AUTO_UDP_IN;
|
||||
|
||||
@@ -84,6 +84,7 @@ struct desync_profile
|
||||
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
|
||||
int hostlist_auto_udp_in, hostlist_auto_udp_out;
|
||||
uint32_t hostlist_auto_retrans_maxseq, hostlist_auto_incoming_maxseq;
|
||||
bool hostlist_auto_retrans_reset;
|
||||
|
||||
hostfail_pool *hostlist_auto_fail_counters;
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *l7proto_name[] = {"all","unknown","known","http","tls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"};
|
||||
static const char *l7proto_name[] = {
|
||||
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"
|
||||
};
|
||||
const char *l7proto_str(t_l7proto l7)
|
||||
{
|
||||
if (l7>=L7_LAST) return NULL;
|
||||
@@ -46,7 +48,11 @@ bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
|
||||
}
|
||||
|
||||
static const char *l7payload_name[] = {
|
||||
"all","unknown","empty","known","http_req","http_reply","tls_client_hello","tls_server_hello","quic_initial",
|
||||
"all","unknown","empty","known",
|
||||
"http_req","http_reply",
|
||||
"tls_client_hello","tls_server_hello",
|
||||
"dtls_client_hello","dtls_server_hello",
|
||||
"quic_initial",
|
||||
"wireguard_initiation","wireguard_response","wireguard_cookie","wireguard_keepalive","wireguard_data",
|
||||
"dht","discord_ip_discovery","stun",
|
||||
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
|
||||
@@ -458,9 +464,10 @@ bool IsTLSRecordFull(const uint8_t *data, size_t len)
|
||||
}
|
||||
bool IsTLSHandshakeHello(const uint8_t *data, size_t len, uint8_t type, bool bPartialIsOK)
|
||||
{
|
||||
// return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
|
||||
|
||||
return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
|
||||
return len >= 6 &&
|
||||
(type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) &&
|
||||
data[4]==0x03 && data[5] <= 0x03 &&
|
||||
(bPartialIsOK || IsTLSHandshakeFull(data,len));
|
||||
}
|
||||
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len, bool bPartialIsOK)
|
||||
{
|
||||
@@ -1401,7 +1408,11 @@ bool IsWireguardKeepalive(const uint8_t *data, size_t len)
|
||||
}
|
||||
bool IsDht(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=7 && data[0]=='d' && (data[1]=='1' || data[1]=='2') && data[2]==':' && data[len-1]=='e';
|
||||
return len>=5 && data[0]=='d' && data[2]==':' && data[len-1]=='e' &&
|
||||
(data[1]=='1' && data[3]=='a' && data[4]=='d' ||
|
||||
data[1]=='1' && data[3]=='r' && data[4]=='d' ||
|
||||
data[1]=='2' && data[3]=='i' && data[4]=='p' ||
|
||||
data[1]=='1' && data[3]=='e' && data[4]=='l');
|
||||
}
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
|
||||
{
|
||||
@@ -1445,3 +1456,22 @@ bool IsMTProto(const uint8_t *data, size_t len)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsDTLS(const uint8_t *data, size_t len)
|
||||
{
|
||||
return ((len > 13) &&
|
||||
(data[0]>=0x14 && data[0]<=0x17) && /* Handshake, change-cipher-spec, Application-Data, Alert */
|
||||
((data[1] == 0xfe && data[2] == 0xff) || /* Versions */
|
||||
(data[1] == 0xfe && data[2] == 0xfd) ||
|
||||
(data[1] == 0xfe && data[2] == 0xfc) ||
|
||||
(data[1] == 0x01 && data[2] == 0x00)) &&
|
||||
(pntoh16(data+11)+13)<=len);
|
||||
}
|
||||
bool IsDTLSClientHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return IsDTLS(data,len) && data[0]==0x16 && data[13]==1;
|
||||
}
|
||||
bool IsDTLSServerHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return IsDTLS(data,len) && data[0]==0x16 && data[13]==2;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef enum {
|
||||
L7_KNOWN,
|
||||
L7_HTTP,
|
||||
L7_TLS,
|
||||
L7_DTLS,
|
||||
L7_QUIC,
|
||||
L7_WIREGUARD,
|
||||
L7_DHT,
|
||||
@@ -34,6 +35,8 @@ typedef enum {
|
||||
L7P_HTTP_REPLY,
|
||||
L7P_TLS_CLIENT_HELLO,
|
||||
L7P_TLS_SERVER_HELLO,
|
||||
L7P_DTLS_CLIENT_HELLO,
|
||||
L7P_DTLS_SERVER_HELLO,
|
||||
L7P_QUIC_INITIAL,
|
||||
L7P_WIREGUARD_INITIATION,
|
||||
L7P_WIREGUARD_RESPONSE,
|
||||
@@ -155,6 +158,10 @@ bool IsDht(const uint8_t *data, size_t len);
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len);
|
||||
bool IsStunMessage(const uint8_t *data, size_t len);
|
||||
bool IsMTProto(const uint8_t *data, size_t len);
|
||||
bool IsDTLS(const uint8_t *data, size_t len);
|
||||
bool IsDTLSClientHello(const uint8_t *data, size_t len);
|
||||
bool IsDTLSServerHello(const uint8_t *data, size_t len);
|
||||
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
typedef struct quic_cid {
|
||||
|
||||
Reference in New Issue
Block a user