Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-17 15:09:45 +00:00

42 Commits

Author SHA1 Message Date
bol-van
927cca3d44 AI fixes 2026-02-06 16:42:18 +03:00
bol-van
162e8906a6 nfqws2: use mktime instead of timelocal 2026-02-06 15:53:50 +03:00
bol-van
3f7180379b update docs 2026-02-06 15:47:34 +03:00
bol-van
5d0af6b058 nfqws2: load wlanapi.dll dynamically only if required 2026-02-06 15:42:36 +03:00
bol-van
392e1cc1ef nfqws2: fix sz=0 case in fill_random_bytes 2026-02-06 14:58:24 +03:00
bol-van
8a5643851d zapret-tests: fix ip_len in csum tests 2026-02-06 12:01:31 +03:00
bol-van
6299a46ab7 nfqws2: 1ULL in proto/payload 2026-02-06 11:31:47 +03:00
bol-van
c5ecc0493d nfqws2: check malloc result 2026-02-06 11:05:54 +03:00
bol-van
7bb8b1d7b3 nfqws2: clear partially allocated windivert filters 2026-02-06 11:04:27 +03:00
bol-van
401bd83f82 nfqws2: use malloc in fuzz for packet data 2026-02-06 11:03:51 +03:00
bol-van
c117c30849 nfqws2: AI fixes 2026-02-06 10:47:29 +03:00
bol-van
6828e7352c antivirus issue ban warning 2026-02-06 10:10:09 +03:00
bol-van
943e548f93 mdig: minor change 2026-02-05 18:51:36 +03:00
bol-van
539c329da3 update docs 2026-02-05 14:35:14 +03:00
bol-van
4c6902c17c update docs 2026-02-05 14:34:41 +03:00
bol-van
9121d949f6 update docs 2026-02-05 14:34:17 +03:00
bol-van
64c1f96f80 nfqws2: time convert functions 2026-02-05 14:33:15 +03:00
bol-van
3334786fe3 AI fixes 2026-02-05 12:54:59 +03:00
bol-van
20a0fa671d AI fixes 2026-02-05 12:36:27 +03:00
bol-van
747de07c85 update docs 2026-02-05 12:22:50 +03:00
bol-van
6384af6607 update docs 2026-02-05 12:22:18 +03:00
bol-van
3046dd8013 nfqws2: bt and utp_bt protocol detectors 2026-02-05 12:19:31 +03:00
bol-van
c80ae95a09 nfqws2: hidden packet data fuzz option 2026-02-05 11:06:32 +03:00
bol-van
d7e5fc1a7c nfqws2: AI fixes 2026-02-05 09:37:34 +03:00
bol-van
97a6b9dd5b nfqws2: AI inspired fixes 2026-02-04 22:06:23 +03:00
bol-van
cfd2df41c4 nfqws2: tls debug ssl 3.0 2026-02-04 17:54:07 +03:00
bol-van
f47f4a0cae blockcheck2: small fixes 2026-02-04 17:35:07 +03:00
bol-van
823a2e2e5d update docs 2026-02-04 15:18:57 +03:00
bol-van
0cdbedde74 update docs 2026-02-04 15:17:27 +03:00
bol-van
36e243863b update docs 2026-02-04 15:15:47 +03:00
bol-van
181395be87 nfqws2: compile compat 2026-02-04 15:14:49 +03:00
bol-van
fb71a41ea5 nfqws2: compile compat 2026-02-04 15:12:23 +03:00
bol-van
7f8f64a355 nfqws2: compile compat 2026-02-04 15:04:59 +03:00
bol-van
7e31dc9d89 update docs 2026-02-04 14:24:34 +03:00
bol-van
4a9072a949 nfqws2: unblocked bcryptorandom, --new=name, AI fixes 2026-02-04 14:24:10 +03:00
bol-van
4b0e3af020 update docs 2026-02-03 22:42:03 +03:00
bol-van
d442a38774 update docs 2026-02-03 22:40:48 +03:00
bol-van
ede3515fa3 update docs 2026-02-03 22:37:59 +03:00
bol-van
831cf02ad5 update docs 2026-02-03 22:33:10 +03:00
bol-van
c436470b18 nfqws2: type field in stat table 2026-02-03 22:32:57 +03:00
bol-van
56b4ce0b2a nfqws2: clock_getfloattime() 2026-02-03 22:03:56 +03:00
bol-van
18b33008af nfqws2: stat luacall 2026-02-03 21:58:14 +03:00
31 changed files with 908 additions and 265 deletions

View File

@@ -18,5 +18,7 @@ Discussions - место для обсуждения вопросов между
Если вы игнорируете данное требование, вы не достигните своих целей , а только добавите желания удалить ваш issue или при настойчивости забанить.
Идите в дискуссии, не захламляйте issues.
Так же будут немедленно удаляться любые issue, связанные с реакцией антивирусов. При агрессии или настойчивости - бан. (подсказка : вирусов нет, удаляйте если не верите)
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.

View File

@@ -5,9 +5,9 @@ pktws_oob()
# $1 - test function
# $2 - domain
local dropacks urp
local urp
for urp in b 0 2 midsld; do
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp$dropack
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp
done
}

View File

@@ -63,7 +63,7 @@ pktws_seqovl_tests_tls()
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
f="$(extract_arg 1 $split)"
f2="$(extract_arg 2 $split)"
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
done
[ "$ok" = 1 ] && ok_any=1

View File

@@ -11,7 +11,7 @@ pktws_check_http()
for split in '' multisplit $MULTIDISORDER; do
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http ${split:+$PAYLOAD --lua-desync=$split}
done
}

View File

@@ -69,11 +69,11 @@ pktws_fake_https_vary_()
{
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
shift; shift; shift
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
[ "$ok_any" = 1 ] && ok=1
}

View File

@@ -214,3 +214,17 @@ v0.8.1
* nfqws2: conntrack_feed
* winws2: use windivert bulk mode
* nfqws2: template free import
0.9.1
* nfqws2: 'stat', 'clock_getfloattime' luacalls
* nfqws2: bcryptorandom normalize behavior when system entropy is low. prevent blocks
* nfqws2: --new[=name]
* winws2: fix not setting signal handlers
0.9.2
nfqws2: bt and utp_bt protocol detectors
nfqws2: localtime,gmtime,timelocal,timegm luacalls
winws2: load wlanapi.dll dynamically only if needed
winws2: fixed lost windivert deinit on logical network disappear

View File

@@ -75,6 +75,8 @@
- [uname](#uname)
- [clock\_gettime](#clock_gettime)
- [getpid](#getpid)
- [stat](#stat)
- [time](#time)
- [Packet handling options](#packet-handling-options)
- [standard reconstruct](#standard-reconstruct)
- [standard rawsend](#standard-rawsend)
@@ -648,10 +650,10 @@ DESYNC ENGINE INIT:
--lua-gc=<int> ; Lua garbage collector invocation interval in seconds. 0 disables periodic calls.
MULTI-STRATEGY:
--new ; start a new profile
--new[=name] ; start a new profile. optionally assign a name
--skip ; ignore the profile
--name=<name> ; set the profile name
--template[=<name>] ; use the profile as a template and assign a name
--template[=<name>] ; use the profile as a template and optionally assign a name
--cookie[=<string>] ; set the value of the "desync.cookie" Lua variable passed to each instance of this profile
--import=<name> ; copy settings from a template into the current profile, overwriting all existing settings
--filter-l3=ipv4|ipv6 ; profile filter: IP protocol version
@@ -750,9 +752,11 @@ Table of recognizable payload types and flow protocols
| tls | tcp | tls_client_hello<br>tls_server_hello |
| xmpp | tcp | xmpp_stream<br>xmpp_starttls<br>xmpp_proceed<br>xmpp_features |
| mtproto | tcp | mtproto_initial |
| bt | tcp | bt_handshake |
| quic | udp | quic_initial |
| wireguard | udp | wireguard_initiation<br>wireguard_response<br>wireguard_cookie<br>wireguard_keepalive |
| dht | udp | dht |
| utp_bt | udp | utp_bt_handshake |
| discord | udp | discord_ip_discovery |
| stun | udp | stun |
| dns | udp | dns_query dns_response |
@@ -1827,8 +1831,10 @@ function bcryptorandom(size)
```
Generates a raw string containing a cryptographically secure block of random data of the specified size. The source is `/dev/random`.
If the entropy pool is exhausted, this function may cause the process to hang (block). To prevent this, install `haveged` or `rngd`.
This should not be used for random data that does not require cryptographic security.
Random data source - getrandom() (Linux), getentropy() (BSD), `/dev/random`.
`/dev/urandom` is used as a fallback if the previous sources failed or block.
lack of entropy pool is typical Android problem.
#### bxor,bor,band
@@ -1954,9 +1960,11 @@ On Windows, it returns a string starting with "CYGWIN" followed by the version.
```
function clock_gettime()
function clock_getfloattime()
```
Retrieves the precise time. Returns two values: Unix time in seconds and the nanosecond component. The built-in `os.time()` function does not provide nanoseconds.
clock_gettime retrieves the precise time. Returns two values: Unix time in seconds and the nanosecond component. The built-in `os.time()` function does not provide nanoseconds.
clock_getfloattime returns unixtime in the floating point format. Nanoseconds go to the fractional part.
#### getpid
@@ -1968,6 +1976,52 @@ function gettid()
- `getpid()` returns the current process identifier (PID).
- `gettid()` returns the current thread identifier (TID).
#### stat
```
function stat(filename)
```
If successful returns the following table :
| Field | Type | Description |
| :------- | :----- | :---------- |
| type | string | file type : file, dir, socket, blockdev, chardev, fifo, unknown |
| size | number | file size |
| mtime | number | modification unixtime in floating point format |
| inode | number | inode. In Windows doesn't fit into number datatype of luajit but fits into integer datatype of Lua5.3+ |
| dev | number | device id |
In case of error returns 3 values : nil, error string, error number (errno).
#### time
```
function localtime(unixtime)
function gmtime(unixtime)
function timelocal(tm)
function timegm(tm)
```
localtime and gmtime return dissected unixtime similar to C "struct tm". timelocal and timegm are reverse functions.
| Field | Type | Description |
| :------- | :----- | :---------- |
| sec* | number | second |
| min* | number | minute |
| hour* | number | hour |
| mon* | number | month starting from 0 |
| mday* | number | day of month starting from 1 |
| year* | number | full year, not from 1900 |
| wday | number | day of week. 0 = sunday |
| yday | number | day of year starting from 0 |
| isdst* | number | not zero if summer time in effect |
| zone | string | time zone |
| str | string | formatted string: "dd.mm.yyyy hh:mi:ss" |
Fields marked with `*` are required for reverse translation.
### Packet handling options
The following functions use standard sets of options: `rawsend` and `reconstruct`.
@@ -5021,7 +5075,7 @@ filter_apply_hostlist_target()
# $1 - name of the variable containing nfqws2 options
```
Replaces the `<HOSTLIST>` and `<HOSTLIST_AUTO>` markers in $1 depending on the [MODE_FILTER](#config-file) and the presence of list files in ipset.
Replaces the `<HOSTLIST>` and `<HOSTLIST_NOAUTO>` markers in $1 depending on the [MODE_FILTER](#config-file) and the presence of list files in ipset.
```
standard_mode_daemons()
@@ -5401,8 +5455,8 @@ There are several options :
## Windows Server
winws2 is linked against wlanapi.dll which is absent by default.
To solve this problem run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
To use `--ssid-filter` install wireless networking feature.
Run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
Then reboot the system.
## Windows ARM64

View File

@@ -38,7 +38,7 @@
- [Структура track](#структура-track)
- [Особенности обработки icmp](#особенности-обработки-icmp)
- [Особенности обработки raw ip](#особенности-обработки-raw-ip)
- [C интерфейс nfqws2](#c-интерфейс-nfqws2)
- [С интерфейс nfqws2](#с-интерфейс-nfqws2)
- [Базовые константы](#базовые-константы)
- [Стандартные блобы](#стандартные-блобы)
- [Переменные окружения](#переменные-окружения)
@@ -72,6 +72,8 @@
- [uname](#uname)
- [clock\_gettime](#clock_gettime)
- [getpid](#getpid)
- [stat](#stat)
- [time](#time)
- [Опции по работе с пакетами](#опции-по-работе-с-пакетами)
- [standard reconstruct](#standard-reconstruct)
- [standard rawsend](#standard-rawsend)
@@ -149,7 +151,7 @@
- [rawsend\_dissect\_segmented](#rawsend_dissect_segmented)
- [rawsend\_payload\_segmented](#rawsend_payload_segmented)
- [Стандартные фильтры direction и payload](#стандартные-фильтры-direction-и-payload)
- [Работа с многопакетными пейлоадами](#работа-с-многопакетными-пейлоадами)
- [Работа с многопакетными пейлоадам](#работа-с-многопакетными-пейлоадам)
- [Оркестрация](#оркестрация)
- [instance\_cutoff\_shim](#instance_cutoff_shim)
- [cutoff\_shim\_check](#cutoff_shim_check)
@@ -707,7 +709,7 @@ DESYNC ENGINE INIT:
--lua-gc=<int> ; интервал вызова сборщика мусора Lua в секундах. 0 отключает периодический вызов.
MULTI-STRATEGY:
--new ; начало нового профиля
--new[=name] ; начало нового профиля. опционально установка имени профиля
--skip ; игнорировать профиль
--name=<name> ; установить имя профиля
--template[=<name>] ; использовать профиль как шаблон, задать имя
@@ -724,9 +726,9 @@ MULTI-STRATEGY:
--ipset-exclude=<filename> ; фильтр профиля : исключающий список ip адресов или подсетей из файла. может быть смешанным ipv4+ipv6.
--ipset-exclude-ip=<ip_list> ; фильтр профиля : исключающий фиксированный список ip адресов или подсетей через запятую
--hostlist=<filename> ; фильтр профиля : включающий список доменов из файла
--hostlist-domains=<domain_list> ; фильтр профиля : включающий фиксированный список доменов из файла
--hostlist-domains=<domain_list> ; фильтр профиля : включающий фиксированный список доменов через запятую
--hostlist-exclude=<filename> ; фильтр профиля : исключающий список доменов из файла
--hostlist-exclude-domains=<domain_list> ; фильтр профиля : исключающий фиксированный список доменов из файла
--hostlist-exclude-domains=<domain_list> ; фильтр профиля : исключающий фиксированный список доменов через запятую
--hostlist-auto=<filename> ; фильтр профиля : автоматически пополняемый по обратной связи включающий фильтр доменов
--hostlist-auto-fail-threshold=<int> ; параметр автолиста : количество неудач подряд для занесения в лист. по умолчанию 3
--hostlist-auto-fail-time=<int> ; параметр автолиста : максимальное время между неудачами без сброса счетчика. по умолчанию 60 секунд
@@ -809,9 +811,11 @@ nfqws2 сигнатурно распознает типы пейлоадов о
| tls | tcp | tls_client_hello<br>tls_server_hello |
| xmpp | tcp | xmpp_stream<br>xmpp_starttls<br>xmpp_proceed<br>xmpp_features |
| mtproto | tcp | mtproto_initial |
| bt | tcp | bt_handshake |
| quic | udp | quic_initial |
| wireguard | udp | wireguard_initiation<br>wireguard_response<br>wireguard_cookie<br>wireguard_keepalive |
| dht | udp | dht |
| utp_bt | udp | utp_bt_handshake |
| discord | udp | discord_ip_discovery |
| stun | udp | stun |
| dns | udp | dns_query<br>dns_response |
@@ -1973,9 +1977,10 @@ nfqws2 не использует никакие криптобиблиотеки
function bcryptorandom(size)
```
Генерирует raw строку - криптографически стойкий блок случайных данных указанного размера. Источник - `/dev/random`.
Если пул энтропии исчерпывается, может вызывать зависания. Чтобы этого не было - установите haveged или rngd.
Не стоит использовать для получения случайных данных, не требующих крипто-стойкости.
Генерирует raw строку - криптографически стойкий блок случайных данных указанного размера.
Источник - getrandom() (Linux), getentropy() (BSD), `/dev/random`.
`/dev/urandom` используется как fallback, если остальные варианты не работают или блокируют.
Отсутствие данных в `/dev/random` - типичная проблема для Android.
#### bxor,bor,band
@@ -2101,9 +2106,11 @@ function uname()
```
function clock_gettime()
function clock_getfloattime()
```
Узнать точное время. Возвращает 2 значения - unixtime в секундах и наносекунды. Встроенная функция `os.time()` не выдает наносекунды.
Узнать точное время. clock_gettime возвращает 2 значения - unixtime в секундах и наносекунды. Встроенная функция `os.time()` не выдает наносекунды.
clock_getfloattime возвращает unixtime в формате с плавающей точкой. Наносекунды идут в дробную часть.
#### getpid
@@ -2115,6 +2122,51 @@ function gettid()
- getpid() возвращает идентификатор текущего процесса - PID
- gettid() возвращает идентификатор текущего потока - TID
#### stat
```
function stat(filename)
```
В случае успеха возвращает таблицу :
| Поле | Тип | Описание |
| :------- | :----- | :---------- |
| type | string | тип файла : file, dir, socket, blockdev, chardev, fifo, unknown |
| size | number | размер файла |
| mtime | number | unixtime время модификации в формате с плавающей точкой |
| inode | number | inode. на Windows не влезает в тип number luajit, но влезает в integer Lua 5.3+ |
| dev | number | device id |
В случае неудачи возвращает 3 значения : nil, строка ошибки, код ошибки errno.
#### time
```
function localtime(unixtime)
function gmtime(unixtime)
function timelocal(tm)
function timegm(tm)
```
Функции localtime и gmtime возвращают таблицу, аналогичную struct tm в C. timelocal и timegm - обратные функции.
| Поле | Тип | Описание |
| :------- | :----- | :---------- |
| sec* | number | секунды |
| min* | number | минуты |
| hour* | number | часы |
| mon* | number | месяц, начиная с 0 |
| mday* | number | день месяца |
| year* | number | год - полный, не с 1900 года |
| wday | number | день недели. 0 - воскресенье, 6 - суббота |
| yday | number | номер дня в году, начиная с 0 |
| isdst* | number | не 0, если включен переход на летнее/зимнее время |
| zone | string | часовой пояс (timezone) |
| str | string | отформатированная строка dd.mm.yyyy hh:mi:ss |
Поля, помеченные `*`, нужны для обратного перевода. Остальные не учитываются.
### Опции по работе с пакетами
В следующих функциях будут использоваться стандартные наборы опций - rawsend и reconstruct.
@@ -4711,7 +4763,7 @@ blockcheck2 способен определить подменяется ли DN
Ситуация нестабильности стратегий - явление частое. Бывает у провайдера балансировка нагрузки , и разные запросы проходят через разные DPI. То работает, то не работает. Стабильность стратегий тестируется за счет множественных повторений - попыток. Количество попыток задается в диалоге или через [shell переменные](#shell-переменные).
[Поддерживается](#shell-переменные) параллельный режим. В нем каждая попытка выполняется в отдельном дочернем процессе, а потом собираются результаты со всех процессов. Режим включается только через (переменную PARALLEL](#shell-переменные). Может значительно ускорить тестирование, но так же может и нарваться на rate limit - ситуацию, когда сервер вас ограничивает или банит из-за слишком частой долбежки.
[Поддерживается](#shell-переменные) параллельный режим. В нем каждая попытка выполняется в отдельном дочернем процессе, а потом собираются результаты со всех процессов. Режим включается только через [переменную PARALLEL](#shell-переменные). Может значительно ускорить тестирование, но так же может и нарваться на rate limit - ситуацию, когда сервер вас ограничивает или банит из-за слишком частой долбежки.
### Уровни сканирования
@@ -5203,7 +5255,7 @@ filter_apply_hostlist_target()
# $1 - имя переменной с опциями nfqws2
```
Осуществляет замену маркеров `<HOSTLIST>` и `<HOSTLIST_AUTO>` в $1 зависимости от режима фильтрации [MODE_FILTER](#файл-config) и наличия файлов листов в ipset.
Осуществляет замену маркеров `<HOSTLIST>` и `<HOSTLIST_NOAUTO>` в $1 зависимости от режима фильтрации [MODE_FILTER](#файл-config) и наличия файлов листов в ipset.
```
standard_mode_daemons()
@@ -5611,8 +5663,8 @@ WinDivert 2.2.2-A, который идет в поставке zapret.
## Windows Server
winws2 слинкован с wlanapi.dll, который по умолчанию не установлен в Windows Server.
Для решения этой проблемы запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
Для работы `--ssid-filter` необходимо установить поддержку беспроводных сетей.
Запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
После чего перезагрузите систему.
## Windows ARM64

View File

@@ -107,10 +107,10 @@ end
-- hostname is original hostname
function is_dpi_redirect(hostname, location)
local ds = dissect_url(location)
if ds.domain then
if ds and ds.domain then
local sld1 = dissect_nld(hostname,2)
local sld2 = dissect_nld(ds.domain,2)
return sld2 and sld1~=sld2
return sld2 and sld1~=sld2 and true or false
end
return false
end

View File

@@ -14,7 +14,7 @@ end
function test_all(...)
test_run({
test_crypto, test_bin, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
test_crypto, test_bin, test_time, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
test_get_source_ip, test_ifaddrs, test_rawsend},...)
end
@@ -415,6 +415,33 @@ function test_bin(...)
test_run({test_ub, test_bit, test_swap, test_ux},...)
end
function test_time(...)
print("* time")
local unixtime=os.time()
local tm = localtime(unixtime);
print()
print("now: "..tm.str.." "..tm.zone.." = "..unixtime)
local tm = gmtime(unixtime);
print("gmt: "..tm.str.." "..tm.zone.." = "..unixtime)
print()
for i=1,20 do
unixtime = math.random(0,10000000000);
tm = localtime(unixtime);
local t = timelocal(tm)
print("timelocal: "..tm.str.." "..tm.zone.." = "..t)
print( t==unixtime and "LOCALTIME OK" or "LOCALTIME FAILED" )
test_assert(t==unixtime)
unixtime = math.random(0,10000000000);
tm = gmtime(unixtime);
t = timegm(tm)
print("timegm: "..tm.str.." "..tm.zone.." = "..t)
print( t==unixtime and "GMTIME OK" or "GMTIME FAILED" )
test_assert(t==unixtime)
end
end
function test_gzip()
print("* gzip")
@@ -695,6 +722,8 @@ function test_csum()
raw = reconstruct_dissect({ip=ip, tcp=tcp, payload=payload})
dis1 = dissect(raw)
ip.ip_len = IP_BASE_LEN + #ip.options + #tcpb + #payload
ip4b = reconstruct_iphdr(ip)
tcpb = csum_tcp_fix(ip4b,tcpb,payload)
dis2 = dissect(ip4b..tcpb..payload)
print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP4 CSUM OK" or "TCP+IP4 CSUM FAILED" )
@@ -751,6 +780,8 @@ function test_csum()
raw = reconstruct_dissect({ip=ip, udp=udp, payload=payload})
dis1 = dissect(raw)
ip.ip_len = IP_BASE_LEN + #ip.options + #udpb + #payload
ip4b = reconstruct_iphdr(ip)
udpb = csum_udp_fix(ip4b,udpb,payload)
dis2 = dissect(ip4b..udpb..payload)
print( dis1.udp.uh_sum==dis2.udp.uh_sum and "UDP+IP4 CSUM OK" or "UDP+IP4 CSUM FAILED" )

View File

@@ -220,7 +220,7 @@ static void *t_resolver(void *arg)
{
if ((family == AF_INET && (glob.family & FAMILY4)) || (family == AF_INET6 && (glob.family & FAMILY6)))
{
unsigned int mask;
unsigned int mask=0;
bool mask_needed = false;
if (s_mask)
{

View File

@@ -6,12 +6,13 @@ CFLAGS_LINUX = -Wno-alloc-size-larger-than
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
CFLAGS_UBSAN = -fsanitize=undefined,alignment -fno-sanitize-recover=undefined,alignment
LDFLAGS_ANDROID = -llog
LIBS =
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
LIBS_SYSTEMD = -lsystemd
LIBS_BSD = -lz -lm
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32 -liphlpapi -lntdll
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lole32 -loleaut32 -liphlpapi -lntdll
LIBS_CYGWIN32 = -lwindivert32
LIBS_CYGWIN64 = -lwindivert64
RES_CYGWIN32 = windows/res/winws_res32.o
@@ -135,6 +136,9 @@ all: nfqws2
nfqws2: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
ubsan: $(SRC_FILES)
$(CC) $(CFLAGS_UBSAN) $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
systemd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)

View File

@@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include "conntrack.h"
#include "darkmagic.h"
#include <arpa/inet.h>
@@ -66,7 +67,7 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
p->timeout_fin = timeout_fin;
p->timeout_udp = timeout_udp;
p->t_purge_interval = purge_interval;
time(&p->t_last_purge);
p->t_last_purge = boottime();
p->pool = NULL;
}
@@ -215,7 +216,7 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect
ConntrackApplyPos(t, bReverse, dis);
}
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
clock_gettime(CLOCK_BOOT_OR_UPTIME, &t->pos.t_last);
// make sure t_start gets exactly the same value as first t_last
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
}
@@ -314,14 +315,14 @@ bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis)
void ConntrackPoolPurge(t_conntrack *p)
{
time_t tidle;
struct timespec tnow;
time_t tnow;
t_conntrack_pool *t, *tmp;
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
if (!(tnow=boottime())) return;
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
{
HASH_ITER(hh, p->pool, t, tmp) {
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
tidle = tnow - t->track.pos.t_last.tv_sec;
if (t->track.b_cutoff ||
(t->conn.l4proto == IPPROTO_TCP && (
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
@@ -333,7 +334,7 @@ void ConntrackPoolPurge(t_conntrack *p)
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
}
}
p->t_last_purge = tnow.tv_sec;
p->t_last_purge = tnow;
}
}
@@ -345,10 +346,10 @@ static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsiz
void ConntrackPoolDump(const t_conntrack *p)
{
t_conntrack_pool *t, *tmp;
struct timespec tnow;
time_t tnow;
char sa1[40], sa2[40];
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
if (!(tnow=boottime())) return;
HASH_ITER(hh, p->pool, t, tmp) {
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
@@ -356,7 +357,7 @@ void ConntrackPoolDump(const t_conntrack *p)
proto_name(t->conn.l4proto),
sa1, t->conn.sport, sa2, t->conn.dport,
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow.tv_sec - t->track.pos.t_last.tv_sec),
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow - t->track.pos.t_last.tv_sec),
(unsigned long long)t->track.pos.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
(unsigned long long)t->track.pos.server.pdcounter, (unsigned long long)t->track.pos.server.pcounter, (unsigned long long)t->track.pos.server.pbcounter);
if (t->conn.l4proto == IPPROTO_TCP)
@@ -418,7 +419,7 @@ bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t le
if ((reasm->size_present - neg_overlap + szcopy) > reasm->size)
return false; // buffer overflow
// in case of seq overlap new data replaces old - unix behavior
memcpy(reasm->packet + reasm->size_present - neg_overlap, payload + szignore, szcopy);
memcpy(reasm->packet + reasm->size_present - neg_overlap, (const uint8_t*)payload + szignore, szcopy);
if (szcopy>neg_overlap)
{
reasm->size_present += szcopy - neg_overlap;

View File

@@ -258,6 +258,8 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
size_t use_len; // byte count to process, up to 16 bytes
size_t i; // local loop iterator
if (iv_len!=12) return -1;
// since the context might be reused under the same key
// we zero the working buffers for this next new process
memset(ctx->y, 0x00, sizeof(ctx->y));
@@ -391,7 +393,9 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
uint64_t orig_add_len = ctx->add_len * 8;
size_t i;
if (tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len);
if (tag_len>16) return -1;
if (tag_len) memcpy(tag, ctx->base_ectr, tag_len);
if (orig_len || orig_add_len) {
memset(work_buf, 0x00, 16);
@@ -443,10 +447,12 @@ int gcm_crypt_and_tag(
prepare the gcm context with the keying material, we simply
invoke each of the three GCM sub-functions in turn...
*/
gcm_start(ctx, mode, iv, iv_len, add, add_len);
gcm_update(ctx, length, input, output);
gcm_finish(ctx, tag, tag_len);
return(0);
if (iv_len!=12 || tag_len>16) return -1;
int ret;
if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret;
if ((ret=gcm_update(ctx, length, input, output))) return ret;
return gcm_finish(ctx, tag, tag_len);
}
@@ -477,6 +483,9 @@ int gcm_auth_decrypt(
uchar check_tag[16]; // the tag generated and returned by decryption
int diff; // an ORed flag to detect authentication errors
size_t i; // our local iterator
if (iv_len!=12 || tag_len>16) return -1;
/*
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
(which is an identical XORing to reverse the previous one)

View File

@@ -102,8 +102,8 @@ bool tcp_syn_segment(const struct tcphdr *tcphdr)
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr,uint8_t *proto, uint16_t *sport, uint16_t *dport)
{
if (sport) *sport = htons(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0);
if (dport) *dport = htons(tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0);
if (sport) *sport = ntohs(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0);
if (dport) *dport = ntohs(tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0);
if (proto) *proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
}
@@ -178,8 +178,8 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
}
else
{
memset(src,0,sizeof(*src));
memset(dst,0,sizeof(*dst));
if (src) memset(src,0,sizeof(*src));
if (dst) memset(dst,0,sizeof(*dst));
}
}
@@ -378,6 +378,10 @@ bool proto_check_ipv4(const uint8_t *data, size_t len)
uint8_t off = ((struct ip*)data)->ip_hl << 2;
return off>=sizeof(struct ip) && len>=off;
}
bool proto_check_ipv4_payload(const uint8_t *data, size_t len)
{
return len >= ntohs(((struct ip*)data)->ip_len);
}
// move to transport protocol
void proto_skip_ipv4(const uint8_t **data, size_t *len)
{
@@ -537,7 +541,7 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
dis->data_pkt = data;
dis->len_pkt = len;
if (proto_check_ipv4(data, len))
if (proto_check_ipv4(data, len) && (no_payload_check || proto_check_ipv4_payload(data, len)))
{
dis->ip = (const struct ip *) data;
dis->proto = dis->ip->ip_p;
@@ -1148,6 +1152,42 @@ static bool AdapterID2Name(const GUID *guid,char *name,DWORD name_len)
return bRet;
}
typedef DWORD (WINAPI *t_WlanOpenHandle)(
DWORD dwClientVersion,
PVOID pReserved,
PDWORD pdwNegotiatedVersion,
PHANDLE phClientHandle
);
typedef DWORD (WINAPI *t_WlanCloseHandle)(
HANDLE hClientHandle,
PVOID pReserved
);
typedef DWORD (WINAPI *t_WlanEnumInterfaces)(
HANDLE hClientHandle,
PVOID pReserved,
PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
);
typedef DWORD (WINAPI *t_WlanQueryInterface)(
HANDLE hClientHandle,
const GUID *pInterfaceGuid,
WLAN_INTF_OPCODE OpCode,
PVOID pReserved,
PDWORD pdwDataSize,
PVOID *ppData,
PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType
);
typedef DWORD (WINAPI *t_WlanFreeMemory)(
PVOID pMemory
);
t_WlanOpenHandle f_WlanOpenHandle = NULL;
t_WlanCloseHandle f_WlanCloseHandle = NULL;
t_WlanEnumInterfaces f_WlanEnumInterfaces = NULL;
t_WlanQueryInterface f_WlanQueryInterface = NULL;
t_WlanFreeMemory f_WlanFreeMemory = NULL;
HMODULE hdll_wlanapi = NULL;
bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_list_head *nlm_filter)
{
win_dark_deinit();
@@ -1161,12 +1201,38 @@ bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_lis
if (FAILED(w_win32_error = CoCreateInstance(&CLSID_NetworkListManager, NULL, CLSCTX_ALL, &IID_INetworkListManager, (LPVOID*)&pNetworkListManager)))
{
CoUninitialize();
DLOG_ERR("could not create CLSID_NetworkListManager. win32 error %u\n", w_win32_error);
return false;
}
}
else
return false;
}
if (ssid_filter)
{
// dont load any crap from current dir
hdll_wlanapi = LoadLibraryExW(L"wlanapi.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!hdll_wlanapi)
{
w_win32_error = GetLastError();
DLOG_ERR("could not load wlanapi.dll. win32 error %u\n", w_win32_error);
win_dark_deinit();
return false;
}
f_WlanOpenHandle = (t_WlanOpenHandle)GetProcAddress(hdll_wlanapi,"WlanOpenHandle");
f_WlanCloseHandle = (t_WlanCloseHandle)GetProcAddress(hdll_wlanapi,"WlanCloseHandle");
f_WlanEnumInterfaces = (t_WlanEnumInterfaces)GetProcAddress(hdll_wlanapi,"WlanEnumInterfaces");
f_WlanQueryInterface = (t_WlanQueryInterface)GetProcAddress(hdll_wlanapi,"WlanQueryInterface");
f_WlanFreeMemory = (t_WlanFreeMemory)GetProcAddress(hdll_wlanapi,"WlanFreeMemory");
if (!f_WlanOpenHandle || !f_WlanCloseHandle || !f_WlanEnumInterfaces || !f_WlanQueryInterface || !f_WlanFreeMemory)
{
w_win32_error = GetLastError();
DLOG_ERR("could not import all required functions from wlanapi.dll\n");
win_dark_deinit();
return false;
}
}
nlm_filter_net = nlm_filter;
wlan_filter_ssid = ssid_filter;
return true;
@@ -1180,6 +1246,16 @@ void win_dark_deinit(void)
}
if (nlm_filter_net) CoUninitialize();
wlan_filter_ssid = nlm_filter_net = NULL;
if (hdll_wlanapi)
{
FreeLibrary(hdll_wlanapi);
hdll_wlanapi = NULL;
f_WlanOpenHandle = NULL;
f_WlanCloseHandle = NULL;
f_WlanEnumInterfaces = NULL;
f_WlanQueryInterface = NULL;
f_WlanFreeMemory = NULL;
}
}
@@ -1361,16 +1437,16 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
return true;
}
w_win32_error = WlanOpenHandle(2, NULL, &dwCurVersion, &hClient);
w_win32_error = f_WlanOpenHandle(2, NULL, &dwCurVersion, &hClient);
if (w_win32_error != ERROR_SUCCESS) goto fail;
w_win32_error = WlanEnumInterfaces(hClient, NULL, &pIfList);
w_win32_error = f_WlanEnumInterfaces(hClient, NULL, &pIfList);
if (w_win32_error != ERROR_SUCCESS) goto fail;
for (k = 0; k < pIfList->dwNumberOfItems; k++)
{
pIfInfo = pIfList->InterfaceInfo + k;
if (pIfInfo->isState == wlan_interface_state_connected)
{
w_win32_error = WlanQueryInterface(hClient,
w_win32_error = f_WlanQueryInterface(hClient,
&pIfInfo->InterfaceGuid,
wlan_intf_opcode_current_connection,
NULL,
@@ -1386,20 +1462,20 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
len = strlen(ssid->str);
if (len==pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength && !memcmp(ssid->str,pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID,len))
{
WlanFreeMemory(pConnectInfo);
f_WlanFreeMemory(pConnectInfo);
goto found;
}
}
WlanFreeMemory(pConnectInfo);
f_WlanFreeMemory(pConnectInfo);
}
}
w_win32_error = 0;
fail:
bRes = false;
ex:
if (pIfList) WlanFreeMemory(pIfList);
if (hClient) WlanCloseHandle(hClient, 0);
if (pIfList) f_WlanFreeMemory(pIfList);
if (hClient) f_WlanCloseHandle(hClient, 0);
return bRes;
found:
w_win32_error = 0;
@@ -2169,7 +2245,7 @@ static time_t wlan_info_last = 0;
static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
{
bool bres = true;
time_t now = time(NULL);
time_t now = boottime();
// do not purge too often to save resources
if (wlan_info_last != now)

View File

@@ -174,6 +174,7 @@ void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr);
void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp);
bool proto_check_ipv4(const uint8_t *data, size_t len);
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
void proto_skip_ipv4(const uint8_t **data, size_t *len);
bool proto_check_ipv6(const uint8_t *data, size_t len);
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);

View File

@@ -609,7 +609,8 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
// so we need to workaround this.
// SYN and SYN,ACK checks are for conntrack-less mode
if (ctrack && (params.server ? ctrack->pos.server.pcounter : ctrack->pos.client.pcounter) == 1 || dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
if (ctrack && (params.server ? ctrack->pos.server.pcounter : ctrack->pos.client.pcounter) == 1 ||
!ctrack && dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
{
if (dis->len_pkt > *len_mod_pkt)
DLOG_ERR("linux postnat conntrack workaround cannot be applied\n");
@@ -729,7 +730,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
if (!params.cache_hostname)
{
*hostname = 0;
return true;
return false;
}
if (params.debug)
{
@@ -737,13 +738,8 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
ntopa46(a4, a6, s, sizeof(s));
DLOG("ipcache hostname search for %s\n", s);
}
ip_cache_item *ipc = ipcacheTouch(&params.ipcache, a4, a6, NULL);
if (!ipc)
{
DLOG_ERR("ipcache_get_hostname: out of memory\n");
return false;
}
if (ipc->hostname)
ip_cache_item *ipc = ipcacheFind(&params.ipcache, a4, a6, NULL);
if (ipc && ipc->hostname)
{
if (params.debug)
{
@@ -756,31 +752,36 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
}
else
*hostname = 0;
return true;
return *hostname;
}
static void ipcache_update_ttl(t_ctrack *ctrack, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
{
// no need to cache ttl in server mode because first packet is incoming
if (ctrack && !params.server)
{
ip_cache_item *ipc = ipcacheTouch(&params.ipcache, a4, a6, iface);
if (!ipc)
{
DLOG_ERR("ipcache: out of memory\n");
return;
}
ip_cache_item *ipc;
if (ctrack->incoming_ttl)
{
ipc = ipcacheTouch(&params.ipcache, a4, a6, iface);
if (!ipc)
{
DLOG_ERR("ipcache: out of memory\n");
return;
}
if (ipc->ttl != ctrack->incoming_ttl)
{
DLOG("updated ttl cache\n");
ipc->ttl = ctrack->incoming_ttl;
}
}
else if (ipc->ttl)
else
{
DLOG("got cached ttl %u\n", ipc->ttl);
ctrack->incoming_ttl = ipc->ttl;
ipc = ipcacheFind(&params.ipcache, a4, a6, iface);
if (ipc && ipc->ttl)
{
DLOG("got cached ttl %u\n", ipc->ttl);
ctrack->incoming_ttl = ipc->ttl;
}
}
}
}
@@ -789,10 +790,8 @@ static void ipcache_get_ttl(t_ctrack *ctrack, const struct in_addr *a4, const st
// no need to cache ttl in server mode because first packet is incoming
if (ctrack && !ctrack->incoming_ttl && !params.server)
{
ip_cache_item *ipc = ipcacheTouch(&params.ipcache, a4, a6, iface);
if (!ipc)
DLOG_ERR("ipcache: out of memory\n");
else if (ipc->ttl)
ip_cache_item *ipc = ipcacheFind(&params.ipcache, a4, a6, iface);
if (ipc && ipc->ttl)
{
DLOG("got cached ttl %u\n", ipc->ttl);
ctrack->incoming_ttl = ipc->ttl;
@@ -896,7 +895,7 @@ static uint8_t desync(
if (LIST_FIRST(&dp->lua_desync))
{
lua_rawgeti(params.L, LUA_REGISTRYINDEX, params.ref_desync_ctx);
t_lua_desync_context *ctx = (t_lua_desync_context *)luaL_checkudata(params.L, 1, "desync_ctx");
t_lua_desync_context *ctx = (t_lua_desync_context *)luaL_checkudata(params.L, -1, "desync_ctx");
// this is singleton stored in the registry. safe to pop
lua_pop(params.L,1);
@@ -1263,7 +1262,7 @@ static bool play_prolog(
hostname_is_ip = ps->ctrack->hostname_is_ip;
if (!hostname && !ps->bReverse)
{
if (ipcache_get_hostname(ps->sdip4, ps->sdip6, ps->host, sizeof(ps->host), &hostname_is_ip) && *ps->host)
if (ipcache_get_hostname(ps->sdip4, ps->sdip6, ps->host, sizeof(ps->host), &hostname_is_ip))
if (!(hostname = ps->ctrack->hostname = strdup(ps->host)))
DLOG_ERR("strdup(host): out of memory\n");
}
@@ -1451,7 +1450,8 @@ static uint8_t dpi_desync_tcp_packet_play(
{L7P_HTTP_REPLY,L7_HTTP,IsHttpReply,false},
{L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false},
{L7P_XMPP_PROCEED,L7_XMPP,IsXMPPProceedTLS,false},
{L7P_XMPP_FEATURES,L7_XMPP,IsXMPPFeatures,false}
{L7P_XMPP_FEATURES,L7_XMPP,IsXMPPFeatures,false},
{L7P_BT_HANDSHAKE,L7_BT,IsBTHandshake,false}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ps.ctrack, &ps.l7proto, &ps.l7payload);
@@ -1531,10 +1531,11 @@ static uint8_t dpi_desync_tcp_packet_play(
if (!ps.ctrack_replay || ReasmIsEmpty(&ps.ctrack_replay->reasm_client))
{
t_protocol_probe testers[] = {
{L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial},
{L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial,false},
{L7P_HTTP_REQ,L7_HTTP,IsHttp,false},
{L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false},
{L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false}
{L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false},
{L7P_BT_HANDSHAKE,L7_BT,IsBTHandshake,false}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), rdata_payload, rlen_payload, ps.ctrack_replay, &ps.l7proto, &ps.l7payload);
@@ -1544,7 +1545,7 @@ static uint8_t dpi_desync_tcp_packet_play(
if (ps.tpos && (ps.tpos->client.seq_last - ps.tpos->client.seq0)==1)
{
t_protocol_probe testers[] = {
{L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto}
{L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto,false}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), rdata_payload, rlen_payload, ps.ctrack_replay, &ps.l7proto, &ps.l7payload);
}
@@ -1627,6 +1628,7 @@ static void udp_standard_protocol_probe(const uint8_t *data_payload, size_t len_
{L7P_DHT,L7_DHT,IsDht,false},
{L7P_DTLS_CLIENT_HELLO,L7_DTLS,IsDTLSClientHello,false},
{L7P_DTLS_SERVER_HELLO,L7_DTLS,IsDTLSServerHello,false},
{L7P_UTP_BT_HANDSHAKE,L7_UTP_BT,IsUTP_BTHandshake,false},
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
@@ -1644,7 +1646,7 @@ static const uint8_t *dns_extract_name(const uint8_t *a, const uint8_t *b, const
if (bptr)
{
if (a>=e) return NULL;
if (a+1>=e) return NULL;
// name pointer
off = (*a & 0x3F)<<8 | a[1];
p = b + off;
@@ -1981,8 +1983,8 @@ static uint8_t dpi_desync_icmp_packet(
hostname = ctrack->hostname;
hostname_is_ip = ctrack->hostname_is_ip;
}
else if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host ||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip) && *host)
else if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) ||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip))
{
hostname = host;
}
@@ -2029,7 +2031,7 @@ static uint8_t dpi_desync_ip_packet(
if (!!dis->ip == !!dis->ip6) return verdict;
struct sockaddr_storage src, dst;
const char *ssid;
const char *ssid = NULL;
struct desync_profile *dp;
extract_endpoints(dis->ip, dis->ip6, NULL, NULL, &src, &dst);
@@ -2048,8 +2050,8 @@ static uint8_t dpi_desync_ip_packet(
bool hostname_is_ip = false;
const char *hostname = NULL;
char host[256];
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host ||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip) && *host)
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) ||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip))
{
hostname = host;
}
@@ -2128,6 +2130,8 @@ static uint8_t dpi_desync_packet_play(
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
}
}
else
DLOG("invalid packet - neither ipv4 or ipv6\n");
return verdict;
}
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt)

View File

@@ -18,6 +18,7 @@ bool pf_parse(const char *s, port_filter *pf)
if (*s=='*' && s[1]==0)
{
pf->from=1; pf->to=0xFFFF;
pf->neg=false;
return true;
}
if (*s=='~')

View File

@@ -1,6 +1,7 @@
#define _GNU_SOURCE
#include "helpers.h"
#include "random.h"
#include <stdio.h>
#include <string.h>
@@ -9,6 +10,7 @@
#include <ctype.h>
#include <libgen.h>
#include <errno.h>
#include <sys/param.h>
#define UNIQ_SORT \
{ \
@@ -454,8 +456,14 @@ bool file_open_test(const char *filename, int flags)
void fill_random_bytes(uint8_t *p,size_t sz)
{
size_t k;
for (k=0 ; (k+1)<sz ; k+=2) phton16(p+k, (uint16_t)random());
if (sz & 1) p[sz-1]=(uint8_t)random();
if (sz)
{
// alignment
if ((size_t)p & 1) { *p=(uint8_t)random(); sz--; p++; }
// random has only 31 bits of entropy. not 32 bits
for (k=0 ; (k+1)<sz ; k+=2) *(uint16_t*)(p+k) = (uint16_t)random();
if (sz & 1) p[sz-1]=(uint8_t)random();
}
}
void fill_random_az(uint8_t *p,size_t sz)
{
@@ -472,14 +480,72 @@ void fill_random_az09(uint8_t *p,size_t sz)
p[k] = rnd<10 ? rnd+'0' : 'a'+rnd-10;
}
}
#if defined(__FreeBSD__) && __FreeBSD_version <= 1200000
#include <sys/sysctl.h>
int getentropy(void *buf, size_t len)
{
int mib[2];
size_t size = len;
// Check for reasonable length (getentropy limits to 256)
if (len > 256) {
errno = EIO;
return -1;
}
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
if (sysctl(mib, 2, buf, &size, NULL, 0) == -1) {
return -1;
}
return (size == len) ? 0 : -1;
}
#endif
bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
{
bool b;
FILE *F = fopen("/dev/random","rb");
if (!F) return false;
b = fread(p,sz,1,F)==1;
fclose(F);
return b;
ssize_t rd;
int fd;
#if defined(__linux__) || defined(__CYGWIN__)
for(; sz && (rd=getrandom(p,sz,GRND_NONBLOCK))>0 ; p+=rd, sz-=rd);
if (sz)
#elif defined(BSD)
while(sz)
{
rd = sz<256 ? sz : 256; // BSD limitation
if (getentropy(p,rd)) break;
p+=rd; sz-=rd;
}
if (sz)
#endif
{
if ((fd = open("/dev/random",O_NONBLOCK))>=0)
{
do
{
if ((rd=read(fd,p,sz))>0)
{
p+=rd; sz-=rd;
}
} while(sz && rd>0);
close(fd);
}
if (sz && (fd = open("/dev/urandom",0))>=0)
{
do
{
if ((rd=read(fd,p,sz))>0)
{
p+=rd; sz-=rd;
}
} while(sz && rd>0);
close(fd);
}
}
return !sz;
}
#if defined(__GNUC__) && !defined(__llvm__)
@@ -581,3 +647,9 @@ const struct in6_addr *mask_from_bitcount6(uint32_t zct)
{
return ip6_mask+zct;
}
time_t boottime(void)
{
struct timespec ts;
return clock_gettime(CLOCK_BOOT_OR_UPTIME, &ts) ? 0 : ts.tv_sec;
}

View File

@@ -85,6 +85,10 @@ time_t file_mod_time(const char *filename);
bool file_size(const char *filename, off_t *size);
bool file_open_test(const char *filename, int flags);
#if defined(__FreeBSD__) && __FreeBSD_version <= 1200000
int getentropy(void *buf, size_t len);
#endif
void fill_random_bytes(uint8_t *p,size_t sz);
void fill_random_az(uint8_t *p,size_t sz);
void fill_random_az09(uint8_t *p,size_t sz);
@@ -104,3 +108,13 @@ bool parse_int16(const char *p, int16_t *v);
uint32_t mask_from_bitcount(uint32_t zct);
void mask_from_bitcount6_prepare(void);
const struct in6_addr *mask_from_bitcount6(uint32_t zct);
#ifdef CLOCK_BOOTTIME
#define CLOCK_BOOT_OR_UPTIME CLOCK_BOOTTIME
#elif defined(CLOCK_UPTIME)
#define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME
#else
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTINIC
#endif
time_t boottime(void);

View File

@@ -465,41 +465,41 @@ static int luacall_divint(lua_State *L)
static int luacall_brandom(lua_State *L)
{
lua_check_argc(L,"brandom",1);
LUA_STACK_GUARD_ENTER(L)
lua_Integer len = luaL_checkinteger(L,1);
if (len<0) luaL_error(L, "brandom: invalid arg");
uint8_t *p = malloc(len);
if (!p) luaL_error(L, "out of memory");
uint8_t *p = lua_newuserdata(L, len);
fill_random_bytes(p,len);
// in out of memory condition this will leave p unfreed
lua_pushlstring(L,(char*)p,len);
free(p);
return 1;
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
static int luacall_brandom_az(lua_State *L)
{
lua_check_argc(L,"brandom_az",1);
LUA_STACK_GUARD_ENTER(L)
lua_Integer len = luaL_checkinteger(L,1);
if (len<0) luaL_error(L, "brandom_az: invalid arg");
uint8_t *p = malloc(len);
if (!p) luaL_error(L, "out of memory");
if (len<0) luaL_error(L, "brandom: invalid arg");
uint8_t *p = lua_newuserdata(L, len);
fill_random_az(p,len);
// in out of memory condition this will leave p unfreed
lua_pushlstring(L,(char*)p,len);
free(p);
return 1;
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
static int luacall_brandom_az09(lua_State *L)
{
lua_check_argc(L,"brandom_az09",1);
LUA_STACK_GUARD_ENTER(L)
lua_Integer len = luaL_checkinteger(L,1);
if (len<0) luaL_error(L, "brandom_az09: invalid arg");
uint8_t *p = malloc(len);
if (!p) luaL_error(L, "out of memory");
if (len<0) luaL_error(L, "brandom: invalid arg");
uint8_t *p = lua_newuserdata(L, len);
fill_random_az09(p,len);
// in out of memory condition this will leave p unfreed
lua_pushlstring(L,(char*)p,len);
free(p);
return 1;
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
// hacky function. breaks immutable string behavior.
@@ -537,16 +537,14 @@ static int luacall_parse_hex(lua_State *L)
const char *hex = lua_reqlstring(L,1,&l);
if ((l&1)) goto err;
l>>=1;
uint8_t *p = malloc(l);
if (!p) goto err;
uint8_t *p = lua_newuserdata(L, l);
if (!parse_hex_str(hex,p,&l))
{
free(p);
lua_pop(L,1);
goto err;
}
// in out of memory condition this will leave p unfreed
lua_pushlstring(L,(char*)p,l);
free(p);
lua_remove(L,-2);
ex:
LUA_STACK_GUARD_RETURN(L,1)
err:
@@ -577,18 +575,15 @@ static int luacall_bcryptorandom(lua_State *L)
lua_Integer len = luaL_checkinteger(L,1);
if (len<0) luaL_error(L, "bcryptorandom: invalid arg");
uint8_t *p = malloc(len);
if (!p) luaL_error(L, "out of memory");
uint8_t *p = lua_newuserdata(L, len);
if (!fill_crypto_random_bytes(p,len))
{
free(p);
// this is fatal. they expect us to give them crypto secure random blob
luaL_error(L, "could not read random data from /dev/random");
luaL_error(L, "could not get entropy bytes");
}
lua_pushlstring(L,(char*)p,len);
free(p);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -603,13 +598,12 @@ static int luac_bop(lua_State *L, const char *name, void (*op)(const uint8_t *x1
const uint8_t *d1 = (const uint8_t*)lua_reqlstring(L,1,&sz1);
const uint8_t *d2 = (const uint8_t*)lua_reqlstring(L,2,&sz2);
if (sz1!=sz2) luaL_error(L, "string lengths must be the same\n");
uint8_t *d3 = malloc(sz1);
if (!d3) luaL_error(L, "out of memory");
uint8_t *d3 = lua_newuserdata(L, sz1);
op(d1,d2,d3,sz1);
lua_pushlstring(L,(char*)d3,sz1);
free(d3);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -699,8 +693,7 @@ static int luacall_aes_gcm(lua_State *L)
const uint8_t *add = lua_isnoneornil(L,5) ? NULL : (uint8_t*)lua_reqlstring(L,5,&add_len);
uint8_t atag[16];
uint8_t *output = malloc(input_len);
if (!output) luaL_error(L, "out of memory");
uint8_t *output = lua_newuserdata(L, input_len);
if (aes_gcm_crypt(bEncrypt, output, input, input_len, key, key_len, iv, iv_len, add, add_len, atag, sizeof(atag)))
{
@@ -712,7 +705,7 @@ static int luacall_aes_gcm(lua_State *L)
lua_pushlstring(L,(const char*)output,input_len);
lua_pushlstring(L,(const char*)atag,sizeof(atag));
}
free(output);
lua_remove(L,-3);
LUA_STACK_GUARD_RETURN(L,2)
}
@@ -737,14 +730,14 @@ static int luacall_aes_ctr(lua_State *L)
size_t input_len;
const uint8_t *input = (uint8_t*)luaL_checklstring(L,3,&input_len);
uint8_t *output = malloc(input_len);
if (!output) luaL_error(L, "out of memory");
uint8_t *output = lua_newuserdata(L, input_len);
if (aes_ctr_crypt(key, key_len, iv, input, input_len, output))
lua_pushnil(L);
else
lua_pushlstring(L,(const char*)output,input_len);
free(output);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -768,15 +761,14 @@ static int luacall_hkdf(lua_State *L)
lua_Integer okm_len = luaL_checkinteger(L,5);
if (okm_len<0) luaL_error(L, "hkdf: invalid arg");
uint8_t *okm = malloc(okm_len);
if (!okm) luaL_error(L, "out of memory");
uint8_t *okm = lua_newuserdata(L, okm_len);
if (hkdf(sha_ver, salt, salt_len, ikm, ikm_len, info, info_len, okm, okm_len))
lua_pushnil(L);
else
lua_pushlstring(L,(const char*)okm, okm_len);
free(okm);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -846,8 +838,23 @@ static int luacall_clock_gettime(lua_State *L)
lua_pushlint(L, ts.tv_sec);
lua_pushinteger(L, ts.tv_nsec);
}
LUA_STACK_GUARD_RETURN(L,2)
}
static int luacall_clock_getfloattime(lua_State *L)
{
lua_check_argc(L,"clock_getfloattime", 0);
LUA_STACK_GUARD_ENTER(L)
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts))
lua_pushnil(L);
else
lua_pushnumber(L, ts.tv_sec + ts.tv_nsec/1000000000.);
LUA_STACK_GUARD_RETURN(L,1)
}
static void lua_mt_init_desync_ctx(lua_State *L)
{
@@ -1046,7 +1053,7 @@ static int luacall_execution_plan(lua_State *L)
{
for (pl=0 ; pl<L7P_LAST ; pl++)
{
if (func->payload_type & (1<<pl))
if (func->payload_type & (1ULL<<pl))
{
if ((pls = l7payload_str(pl)))
{
@@ -2653,8 +2660,7 @@ static int luacall_csum_tcp_fix(lua_State *L)
luaL_error(L, "invalid payload length");
size_t l_tpl = l_tcp + l_pl;
uint8_t *tpl = malloc(l_tpl);
if (!tpl) luaL_error(L, "out of memory");
uint8_t *tpl = lua_newuserdata(L, l_tpl);
memcpy(tpl, b_tcp, l_tcp);
memcpy(tpl+l_tcp, b_pl, l_pl);
@@ -2662,7 +2668,7 @@ static int luacall_csum_tcp_fix(lua_State *L)
tcp_fix_checksum(tcp, l_tpl, ip, ip6);
lua_pushlstring(L,(char*)tpl,l_tcp);
free(tpl);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -2696,8 +2702,7 @@ static int luacall_csum_udp_fix(lua_State *L)
luaL_error(L, "invalid payload length");
size_t l_tpl = l_udp + l_pl;
uint8_t *tpl = malloc(l_tpl);
if (!tpl) luaL_error(L, "out of memory");
uint8_t *tpl = lua_newuserdata(L, l_tpl);
memcpy(tpl, b_udp, l_udp);
memcpy(tpl+l_udp, b_pl, l_pl);
@@ -2705,7 +2710,7 @@ static int luacall_csum_udp_fix(lua_State *L)
udp_fix_checksum(udp, l_tpl, ip, ip6);
lua_pushlstring(L,(char*)tpl,l_udp);
free(tpl);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -2739,8 +2744,7 @@ static int luacall_csum_icmp_fix(lua_State *L)
luaL_error(L, "invalid payload length");
size_t l_tpl = l_icmp + l_pl;
uint8_t *tpl = malloc(l_tpl);
if (!tpl) luaL_error(L, "out of memory");
uint8_t *tpl = lua_newuserdata(L, l_tpl);
memcpy(tpl, b_icmp, l_icmp);
memcpy(tpl+l_icmp, b_pl, l_pl);
@@ -2748,7 +2752,7 @@ static int luacall_csum_icmp_fix(lua_State *L)
icmp_fix_checksum(icmp, l_tpl, ip6);
lua_pushlstring(L,(char*)tpl,l_icmp);
free(tpl);
lua_remove(L,-2);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -2999,74 +3003,71 @@ static int lua_get_ifaddrs(lua_State *L)
ULONG Size=0;
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAGS, NULL, NULL, &Size)==ERROR_BUFFER_OVERFLOW)
{
PIP_ADAPTER_ADDRESSES pip, pips = (PIP_ADAPTER_ADDRESSES)malloc(Size);
if (pips)
PIP_ADAPTER_ADDRESSES pip, pips = (PIP_ADAPTER_ADDRESSES)lua_newuserdata(L, Size);
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAGS, NULL, pips, &Size)==ERROR_SUCCESS)
{
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAGS, NULL, pips, &Size)==ERROR_SUCCESS)
lua_newtable(L);
for(pip=pips; pip ; pip=pip->Next)
{
lua_newtable(L);
for(pip=pips; pip ; pip=pip->Next)
if (!pip->FirstUnicastAddress || pip->OperStatus!=IfOperStatusUp) continue; // disconnected ?
char ifname[16];
snprintf(ifname,sizeof(ifname),"%u.0",pip->IfIndex);
lua_pushf_table(L,ifname);
lua_getfield(L,-1,ifname);
lua_pushf_str(L, "guid", pip->AdapterName);
if (pip->PhysicalAddressLength) lua_pushf_lstr(L, "phys", pip->PhysicalAddress, pip->PhysicalAddressLength);
lua_pushf_int(L, "index", pip->IfIndex);
lua_pushf_int(L, "index6", pip->Ipv6IfIndex);
lua_pushf_int(L, "flags", pip->Flags);
lua_pushf_lint(L, "mtu", pip->Mtu);
lua_pushf_int(L, "iftype", pip->IfType);
lua_pushf_lint(L, "speed_xmit", pip->TransmitLinkSpeed);
lua_pushf_lint(L, "speed_recv", pip->ReceiveLinkSpeed);
lua_pushf_lint(L, "metric4", pip->Ipv4Metric);
lua_pushf_lint(L, "metric6", pip->Ipv6Metric);
lua_pushf_lint(L, "conntype", pip->ConnectionType);
lua_pushf_lint(L, "tunneltype", pip->TunnelType);
lua_pushf_table(L,"addr");
lua_getfield(L,-1,"addr");
int n;
uint32_t a4,a44;
PIP_ADAPTER_UNICAST_ADDRESS_LH pa;
for(pa=pip->FirstUnicastAddress, n=1; pa ; pa=pa->Next, n++)
{
if (!pip->FirstUnicastAddress || pip->OperStatus!=IfOperStatusUp) continue; // disconnected ?
char ifname[16];
snprintf(ifname,sizeof(ifname),"%u.0",pip->IfIndex);
lua_pushf_table(L,ifname);
lua_getfield(L,-1,ifname);
lua_pushf_str(L, "guid", pip->AdapterName);
if (pip->PhysicalAddressLength) lua_pushf_lstr(L, "phys", pip->PhysicalAddress, pip->PhysicalAddressLength);
lua_pushf_int(L, "index", pip->IfIndex);
lua_pushf_int(L, "index6", pip->Ipv6IfIndex);
lua_pushf_int(L, "flags", pip->Flags);
lua_pushf_lint(L, "mtu", pip->Mtu);
lua_pushf_int(L, "iftype", pip->IfType);
lua_pushf_lint(L, "speed_xmit", pip->TransmitLinkSpeed);
lua_pushf_lint(L, "speed_recv", pip->ReceiveLinkSpeed);
lua_pushf_lint(L, "metric4", pip->Ipv4Metric);
lua_pushf_lint(L, "metric6", pip->Ipv6Metric);
lua_pushf_lint(L, "conntype", pip->ConnectionType);
lua_pushf_lint(L, "tunneltype", pip->TunnelType);
lua_pushf_table(L,"addr");
lua_getfield(L,-1,"addr");
int n;
uint32_t a4,a44;
PIP_ADAPTER_UNICAST_ADDRESS_LH pa;
for(pa=pip->FirstUnicastAddress, n=1; pa ; pa=pa->Next, n++)
lua_pushi_table(L, n);
lua_rawgeti(L, -1, n);
lua_pushf_ipaddr(L, "addr", pa->Address.lpSockaddr);
switch(pa->Address.lpSockaddr->sa_family)
{
lua_pushi_table(L, n);
lua_rawgeti(L, -1, n);
lua_pushf_ipaddr(L, "addr", pa->Address.lpSockaddr);
switch(pa->Address.lpSockaddr->sa_family)
{
case AF_INET:
if (pa->OnLinkPrefixLength<=32)
{
a44 = mask_from_bitcount(pa->OnLinkPrefixLength);
a4 = ~a44;
lua_pushf_lstr(L, "netmask", (const char*)&a4, 4);
a4 &= ((struct sockaddr_in*)pa->Address.lpSockaddr)->sin_addr.s_addr;
a4 |= a44;
lua_pushf_lstr(L, "broadcast", (const char*)&a4, 4);
}
break;
case AF_INET6:
if (pa->OnLinkPrefixLength<=128)
{
lua_pushf_lstr(L, "netmask", (const char*)mask_from_bitcount6(128 - pa->OnLinkPrefixLength), 16);
}
break;
}
lua_pushf_ipaddr(L, "addr", pa->Address.lpSockaddr);
lua_pop(L,1);
case AF_INET:
if (pa->OnLinkPrefixLength<=32)
{
a44 = mask_from_bitcount(pa->OnLinkPrefixLength);
a4 = ~a44;
lua_pushf_lstr(L, "netmask", (const char*)&a4, 4);
a4 &= ((struct sockaddr_in*)pa->Address.lpSockaddr)->sin_addr.s_addr;
a4 |= a44;
lua_pushf_lstr(L, "broadcast", (const char*)&a4, 4);
}
break;
case AF_INET6:
if (pa->OnLinkPrefixLength<=128)
{
lua_pushf_lstr(L, "netmask", (const char*)mask_from_bitcount6(128 - pa->OnLinkPrefixLength), 16);
}
break;
}
lua_pop(L,2);
lua_pushf_ipaddr(L, "addr", pa->Address.lpSockaddr);
lua_pop(L,1);
}
lua_pop(L,2);
}
free (pips);
lua_remove(L,-2);
goto ok;
}
lua_remove(L,-1);
}
lua_pushnil(L);
@@ -3294,14 +3295,14 @@ static int luacall_tls_mod(lua_State *L)
if (mod.mod)
{
size_t newlen = fake_tls_len, maxlen = fake_tls_len + sizeof(mod.sni) + 4;
uint8_t *newtls = malloc(maxlen);
if (!newtls) luaL_error(L, "out of memory");
uint8_t *newtls = lua_newuserdata(L, maxlen);
memcpy(newtls, fake_tls, newlen);
bRes = TLSMod(&mod, payload, payload_len, newtls, &newlen, maxlen);
lua_pushlstring(L,(char*)newtls,newlen);
free(newtls);
lua_remove(L,-2);
}
else
{
@@ -3568,6 +3569,135 @@ zerr:
goto end;
}
static int luacall_stat(lua_State *L)
{
// stat(filename) return stat_table or nil,strerror,errno
lua_check_argc(L,"stat",1);
int n=1;
struct stat st;
if (stat(luaL_checkstring(L,1), &st))
{
lua_pushnil(L);
const char *err = strerror(errno);
if (err)
{
lua_pushstring(L,err);
lua_pushinteger(L,errno);
return 3;
}
}
else
{
lua_createtable(L, 0, 5);
lua_pushf_lint(L,"dev", st.st_dev);
lua_pushf_lint(L,"inode", st.st_ino);
lua_pushf_lint(L,"size", st.st_size);
lua_pushf_number(L,"mtime", st.st_mtim.tv_sec + st.st_mtim.tv_nsec/1000000000.);
const char *ftype;
switch(st.st_mode & S_IFMT)
{
case S_IFREG: ftype="file"; break;
case S_IFDIR: ftype="dir"; break;
case S_IFLNK: ftype="symlink"; break;
case S_IFSOCK: ftype="socket"; break;
case S_IFBLK: ftype="blockdev"; break;
case S_IFCHR: ftype="chardev"; break;
case S_IFIFO: ftype="fifo"; break;
default: ftype="unknown"; break;
}
lua_pushf_str(L, "type", ftype);
}
return 1;
}
static void lua_xtime(lua_State *L, struct tm *(*timefunc)(const time_t *,struct tm *))
{
struct tm t;
time_t unixtime = (time_t)luaL_checklint(L,1);
if (!timefunc(&unixtime, &t))
{
lua_pushnil(L);
}
else
{
lua_createtable(L, 0, 11);
lua_pushf_int(L,"sec", t.tm_sec);
lua_pushf_int(L,"min", t.tm_min);
lua_pushf_int(L,"hour", t.tm_hour);
lua_pushf_int(L,"mday", t.tm_mday);
lua_pushf_int(L,"mon", t.tm_mon);
lua_pushf_int(L,"year", t.tm_year+1900);
lua_pushf_int(L,"wday", t.tm_wday);
lua_pushf_int(L,"yday", t.tm_yday);
lua_pushf_int(L,"isdst", t.tm_isdst);
lua_pushf_str(L,"zone", t.tm_zone);
char s[24];
snprintf(s,sizeof(s),"%02d.%02d.%04d %02d:%02d:%02d", t.tm_mday, t.tm_mon + 1, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec);
lua_pushf_str(L,"str", s);
}
}
static int luacall_localtime(lua_State *L)
{
// localtime(unixtime)
lua_check_argc(L,"localtime",1);
lua_xtime(L, localtime_r);
return 1;
}
static int luacall_gmtime(lua_State *L)
{
// gmtime(unixtime)
lua_check_argc(L,"gmtime",1);
lua_xtime(L, gmtime_r);
return 1;
}
#define TIMEX_VAL(v) \
lua_getfield(L,1,#v); \
if (lua_type(L,-1)!=LUA_TNUMBER) luaL_error(L,"invalid tm." #v); \
t.tm_##v = lua_tointeger(L,-1); \
lua_pop(L,1);
static void lua_timex(lua_State *L, time_t (*timefunc)(struct tm *))
{
if (lua_type(L,1)!=LUA_TTABLE) luaL_error(L,"invalid tm structure");
struct tm t;
TIMEX_VAL(sec)
TIMEX_VAL(min)
TIMEX_VAL(hour)
TIMEX_VAL(mday)
TIMEX_VAL(mon)
TIMEX_VAL(year)
t.tm_year-=1900;
TIMEX_VAL(isdst)
time_t unixtime = timefunc(&t);
if (unixtime==(time_t)-1)
{
lua_pushnil(L);
}
else
lua_pushlint(L,unixtime);
}
static int luacall_timelocal(lua_State *L)
{
// timelocal(tm)
lua_check_argc(L,"timelocal",1);
lua_timex(L, mktime);
return 1;
}
static int luacall_timegm(lua_State *L)
{
// timegm(tm)
lua_check_argc(L,"timegm",1);
lua_timex(L, timegm);
return 1;
}
// ----------------------------------------
void lua_cleanup(lua_State *L)
@@ -4029,7 +4159,6 @@ static void lua_init_const(void)
{"ICMP6_PARAMPROB_HEADER",ICMP6_PARAMPROB_HEADER},
{"ICMP6_PARAMPROB_NEXTHEADER",ICMP6_PARAMPROB_NEXTHEADER},
{"ICMP6_PARAMPROB_OPTION",ICMP6_PARAMPROB_OPTION}
};
DLOG("\nLUA NUMERIC:");
for (int i=0;i<sizeof(cuint)/sizeof(*cuint);i++)
@@ -4161,6 +4290,7 @@ static void lua_init_functions(void)
// system functions
{"uname",luacall_uname},
{"clock_gettime",luacall_clock_gettime},
{"clock_getfloattime",luacall_clock_getfloattime},
{"getpid",luacall_getpid},
{"gettid",luacall_gettid},
@@ -4209,7 +4339,16 @@ static void lua_init_functions(void)
// gzip compress
{"gzip_init",luacall_gzip_init},
{"gzip_end",luacall_gzip_end},
{"gzip_deflate",luacall_gzip_deflate}
{"gzip_deflate",luacall_gzip_deflate},
// stat() - file size, mod time
{"stat",luacall_stat},
// time
{"localtime",luacall_localtime},
{"gmtime",luacall_gmtime},
{"timelocal",luacall_timelocal},
{"timegm",luacall_timegm}
};
for(int i=0;i<(sizeof(lfunc)/sizeof(*lfunc));i++)
lua_register(params.L,lfunc[i].name,lfunc[i].f);

View File

@@ -156,6 +156,40 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifin, const char *i
return dpi_desync_packet(*mark, ifin, ifout, data_pkt, len_pkt, mod_pkt, len_mod_pkt);
}
#define FUZZ_MAX_PACKET_SIZE (RECONSTRUCT_MAX_SIZE+4096)
static void fuzzPacketData(unsigned int count)
{
uint8_t *packet,mod[RECONSTRUCT_MAX_SIZE+4096];
size_t len, modlen;
unsigned int k;
uint32_t mark=0;
uint8_t verdict;
for(k=0;k<count;k++)
{
if (bQuit) break;
if (!(k%1000)) DLOG_CONDUP("fuzz ct=%u\n",k);
len = random()%(FUZZ_MAX_PACKET_SIZE+1);
if (!(packet = malloc(len))) return; // alloc every time to catch uninitialized reads
fill_random_bytes(packet,len);
if (len)
{
// simulate ipv4 or ipv6 and invalid packet with low probability
*packet = *packet ? (*packet & 1) ? 0x40 : 0x60 | (*packet & 0x0F) : (uint8_t)random();
}
modlen = random()%(sizeof(mod)+1);
verdict = processPacketData(&mark,random()%1 ? "ifin" : NULL,random()%1 ? "ifout" : NULL,packet,len,mod,&modlen);
free(packet);
}
}
static void do_fuzz(void)
{
if (params.fuzz)
{
DLOG_CONDUP("fuzz packet data count=%u\n",params.fuzz);
fuzzPacketData(params.fuzz);
}
}
static bool test_list_files()
{
@@ -381,9 +415,11 @@ static int nfq_main(void)
if (!lua_init())
goto err;
do_fuzz();
if (!params.intercept)
{
DLOG("no intercept quit\n");
DLOG_CONDUP("no intercept quit\n");
goto exok;
}
@@ -426,7 +462,10 @@ static int nfq_main(void)
if (r) DLOG_ERR("nfq_handle_packet error %d\n", r);
}
else
DLOG("recv from nfq returned 0 !\n");
{
DLOG_ERR("recv from nfq returned 0 !\n");
goto err;
}
}
if (errno==EINTR)
{
@@ -545,6 +584,8 @@ static int dvt_main(void)
if (!lua_init())
goto exiterr;
do_fuzz();
if (!params.intercept)
{
DLOG("no intercept quit\n");
@@ -695,6 +736,8 @@ static int win_main()
res=ERROR_NOT_ENOUGH_MEMORY; goto ex;
}
catch_signals();
for (;;)
{
if (!logical_net_filter_match())
@@ -732,6 +775,8 @@ static int win_main()
res=ERROR_INVALID_PARAMETER; goto ex;
}
do_fuzz();
if (!params.intercept)
{
DLOG("no intercept quit\n");
@@ -751,7 +796,8 @@ static int win_main()
}
else if (errno == ENODEV)
{
DLOG_CONDUP("logical network disappeared. deinitializing windivert.\n");
DLOG_CONDUP("\nlogical network disappeared. deinitializing windivert.\n");
rawsend_cleanup();
break;
}
else if (errno == EINTR)
@@ -1052,7 +1098,7 @@ static bool parse_l7_list(char *opt, uint64_t *l7)
break;
}
else
*l7 |= 1<<proto;
*l7 |= 1ULL<<proto;
if (e) *e++ = c;
p = e;
@@ -1080,7 +1126,7 @@ static bool parse_l7p_list(char *opt, uint64_t *l7p)
break;
}
else
*l7p |= 1<<payload;
*l7p |= 1ULL<<payload;
if (e) *e++ = c;
p = e;
@@ -1334,7 +1380,7 @@ static void LuaDesyncDebug(struct desync_profile *dp, const char *entity)
if (func->payload_type)
{
for(i=0;i<L7P_LAST;i++)
if (func->payload_type & (1<<i))
if (func->payload_type & (1ULL<<i))
DLOG(" %s", l7payload_str(i));
}
else
@@ -1676,7 +1722,7 @@ static void exithelp(void)
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved. gzipped files are supported.\n"
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
"\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t\t\t; begin new profile\n"
" --new[=<name>]\t\t\t\t\t\t\t; begin new profile. optionally set name\n"
" --skip\t\t\t\t\t\t\t; do not use this profile\n"
" --name=<name>\t\t\t\t\t\t; set profile name\n"
" --template[=<name>]\t\t\t\t\t; use this profile as template (must be named or will be useless)\n"
@@ -1778,6 +1824,7 @@ enum opt_indices {
IDX_DEBUG,
IDX_DRY_RUN,
IDX_INTERCEPT,
IDX_FUZZ,
IDX_VERSION,
IDX_COMMENT,
#ifdef __linux__
@@ -1881,6 +1928,7 @@ static const struct option long_options[] = {
[IDX_DEBUG] = {"debug", optional_argument, 0, 0},
[IDX_DRY_RUN] = {"dry-run", no_argument, 0, 0},
[IDX_INTERCEPT] = {"intercept", optional_argument, 0, 0},
[IDX_FUZZ] = {"fuzz", required_argument, 0, 0},
[IDX_VERSION] = {"version", no_argument, 0, 0},
[IDX_COMMENT] = {"comment", optional_argument, 0, 0},
#ifdef __linux__
@@ -1926,7 +1974,7 @@ static const struct option long_options[] = {
[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},
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
[IDX_NEW] = {"new", no_argument, 0, 0},
[IDX_NEW] = {"new", optional_argument, 0, 0},
[IDX_SKIP] = {"skip", no_argument, 0, 0},
[IDX_NAME] = {"name", required_argument, 0, 0},
[IDX_TEMPLATE] = {"template", optional_argument, 0, 0},
@@ -2156,6 +2204,10 @@ int main(int argc, char **argv)
case IDX_INTERCEPT:
params.intercept = !optarg || atoi(optarg);
break;
case IDX_FUZZ:
params.fuzz = atoi(optarg);
params.intercept = false;
break;
case IDX_VERSION:
exit_clean(0);
break;
@@ -2486,6 +2538,11 @@ int main(int argc, char **argv)
dp = &dpl->dp;
dp->n = desync_profile_count;
}
if (optarg && !(dp->name = strdup(optarg)))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
payload_type = 0;

View File

@@ -446,7 +446,7 @@ bool dp_copy(struct desync_profile *to, const struct desync_profile *from)
free(to->cookie);
if (!(to->cookie = strdup(from->cookie))) return false;
}
if (from->hostlist_auto)
if (from->hostlist_auto && from->hostlist_auto!=to->hostlist_auto)
{
if (to->hostlist_auto)
{
@@ -532,14 +532,15 @@ bool alloc_windivert_portfilters(struct params_s *params)
&params->wf_ipf_in, &params->wf_ipf_out};
for (int i=0 ; i<(sizeof(wdbufs)/sizeof(*wdbufs)) ; i++)
{
if (!(*wdbufs[i] = malloc(WINDIVERT_PORTFILTER_MAX)))
return false;
if (!(*wdbufs[i] = malloc(WINDIVERT_PORTFILTER_MAX))) goto err;
**wdbufs[i] = 0;
}
if (!(params->wf_raw_filter = malloc(WINDIVERT_MAX)))
return false;
if (!(params->wf_raw_filter = malloc(WINDIVERT_MAX))) goto err;
*params->wf_raw_filter = 0;
return true;
err:
cleanup_windivert_portfilters(params);
return false;
}
#endif
void cleanup_params(struct params_s *params)
@@ -593,7 +594,7 @@ void init_params(struct params_s *params)
LIST_INIT(&params->blobs);
LIST_INIT(&params->lua_init_scripts);
params->reasm_payload_disable = params->payload_disable = 1<<L7P_NONE;
params->reasm_payload_disable = params->payload_disable = 1ULL<<L7P_NONE;
#ifdef __CYGWIN__
LIST_INIT(&params->ssid_filter);
@@ -607,5 +608,4 @@ void init_params(struct params_s *params)
params->droproot = true;
}
#endif
}

View File

@@ -133,6 +133,7 @@ struct params_s
bool debug;
bool daemon, intercept;
unsigned int fuzz;
#ifdef __linux__
int qnum;

View File

@@ -86,7 +86,7 @@ hostfail_pool * HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time)
{
size_t slen = strlen(s);
ADD_STR_POOL(hostfail_pool, pp, s, slen)
elem->expire = time(NULL) + fail_time;
elem->expire = boottime() + fail_time;
elem->counter = 0;
return elem;
}
@@ -105,7 +105,7 @@ void HostFailPoolDel(hostfail_pool **p, hostfail_pool *elem)
void HostFailPoolPurge(hostfail_pool **pp)
{
hostfail_pool *elem, *tmp;
time_t now = time(NULL);
time_t now = boottime();
HASH_ITER(hh, *pp, elem, tmp)
{
if (now >= elem->expire)
@@ -114,7 +114,7 @@ void HostFailPoolPurge(hostfail_pool **pp)
}
void HostFailPoolPurgeRateLimited(hostfail_pool **pp, time_t *purge_prev)
{
time_t now = time(NULL);
time_t now = boottime();
// do not purge too often to save resources
if (*purge_prev != now)
{
@@ -125,7 +125,7 @@ void HostFailPoolPurgeRateLimited(hostfail_pool **pp, time_t *purge_prev)
void HostFailPoolDump(hostfail_pool *p)
{
hostfail_pool *elem, *tmp;
time_t now = time(NULL);
time_t now = boottime();
HASH_ITER(hh, p, elem, tmp)
printf("host=%s counter=%d time_left=%lld\n",elem->str,elem->counter,(long long int)elem->expire-now);
}
@@ -524,10 +524,15 @@ struct kavl_bit_elem *kavl_bit_get(const struct kavl_bit_elem *hdr, const void *
static bool ipset_kavl_add(struct kavl_bit_elem **ipset, const void *a, uint8_t preflen)
{
uint8_t bytelen = (preflen+7)>>3;
uint8_t *abuf = malloc(bytelen);
if (!abuf) return false;
memcpy(abuf,a,bytelen);
uint8_t *abuf, bytelen = (preflen+7)>>3;
if (bytelen)
{
abuf = malloc(bytelen);
if (!abuf) return false;
memcpy(abuf,a,bytelen);
}
else
abuf = NULL;
if (!kavl_bit_add(ipset,abuf,preflen,0))
{
free(abuf);
@@ -912,12 +917,15 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
{
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (!entry) return NULL;
if (!(entry->data = malloc(size+size_reserve)))
if (size+size_reserve)
{
free(entry);
return NULL;
if (!(entry->data = malloc(size+size_reserve)))
{
free(entry);
return NULL;
}
if (data) memcpy(entry->data,data,size);
}
if (data) memcpy(entry->data,data,size);
entry->size = size;
entry->size_buf = size+size_reserve;
@@ -966,7 +974,7 @@ struct blob_item *blob_collection_search_name(struct blob_collection_head *head,
static void ipcache_item_touch(ip_cache_item *item)
{
time(&item->last);
item->last = boottime();
}
static void ipcache_item_init(ip_cache_item *item)
{
@@ -1029,7 +1037,7 @@ static void ipcache4Print(ip_cache4 *ipcache)
time_t now;
ip_cache4 *ipc, *tmp;
time(&now);
now = boottime();
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
@@ -1087,7 +1095,7 @@ static void ipcache6Print(ip_cache6 *ipcache)
time_t now;
ip_cache6 *ipc, *tmp;
time(&now);
now = boottime();
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
@@ -1107,6 +1115,22 @@ void ipcachePrint(ip_cache *ipcache)
ipcache6Print(ipcache->ipcache6);
}
ip_cache_item *ipcacheFind(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
if (a4)
{
if ((ipcache4 = ipcache4Find(ipcache->ipcache4,a4,iface)))
return &ipcache4->data;
}
else if (a6)
{
if ((ipcache6 = ipcache6Find(ipcache->ipcache6,a6,iface)))
return &ipcache6->data;
}
return NULL;
}
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
{
ip_cache4 *ipcache4;
@@ -1133,7 +1157,7 @@ ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const s
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
{
ip_cache4 *elem, *tmp;
time_t now = time(NULL);
time_t now = boottime();
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
@@ -1147,7 +1171,7 @@ static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
{
ip_cache6 *elem, *tmp;
time_t now = time(NULL);
time_t now = boottime();
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
@@ -1169,7 +1193,7 @@ static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
static time_t ipcache_purge_prev=0;
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
{
time_t now = time(NULL);
time_t now = boottime();
// do not purge too often to save resources
if (ipcache_purge_prev != now)
{

View File

@@ -4,7 +4,6 @@
#include <ctype.h>
#include <sys/queue.h>
#include <net/if.h>
#include <time.h>
#include "helpers.h"
#include "filter.h"
@@ -266,6 +265,7 @@ typedef struct ip_cache
} ip_cache;
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
ip_cache_item *ipcacheFind(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
void ipcacheDestroy(ip_cache *ipcache);
void ipcachePrint(ip_cache *ipcache);

View File

@@ -30,7 +30,7 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
}
static const char *l7proto_name[] = {
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto","bt","utp_bt"
};
const char *l7proto_str(t_l7proto l7)
{
@@ -44,7 +44,7 @@ t_l7proto l7proto_from_name(const char *name)
}
bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
{
return filter_l7==L7_ALL || (filter_l7 & (1<<l7proto)) || (filter_l7 & (1<<L7_KNOWN)) && l7proto>L7_KNOWN && l7proto<L7_LAST;
return filter_l7==L7_ALL || (filter_l7 & (1ULL<<l7proto)) || (filter_l7 & (1ULL<<L7_KNOWN)) && l7proto>L7_KNOWN && l7proto<L7_LAST;
}
static const char *l7payload_name[] = {
@@ -58,7 +58,9 @@ static const char *l7payload_name[] = {
"dht","discord_ip_discovery","stun",
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
"dns_query", "dns_response",
"mtproto_initial"};
"mtproto_initial",
"bt_handshake", "utp_bt_handshake"
};
t_l7payload l7payload_from_name(const char *name)
{
int idx = str_index(l7payload_name,sizeof(l7payload_name)/sizeof(*l7payload_name),name);
@@ -71,7 +73,7 @@ const char *l7payload_str(t_l7payload l7)
}
bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p)
{
return filter_l7p==L7P_ALL || (filter_l7p & (1<<l7payload)) || (filter_l7p & (1<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
return filter_l7p==L7P_ALL || (filter_l7p & (1ULL<<l7payload)) || (filter_l7p & (1ULL<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
}
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
{
@@ -89,7 +91,7 @@ bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
}
for(pl=0, p=buf, e=p+size, *buf=0 ; pl<L7P_LAST ; pl++)
{
if (l7p & (1<<pl))
if (l7p & (1ULL<<pl))
{
pstr = l7payload_str(pl);
lstr = strlen(pstr);
@@ -413,7 +415,7 @@ ssize_t HttpPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
if (*method=='\n' || *method=='\r') method++;
if (*method=='\n' || *method=='\r') method++;
// max length is PROPPATCH
for (p=method,i=0;i<9;i++) if (*p>='A' && *p<='Z') p++;
for (p=method,i=0; i<9 && *p>='A' && *p<='Z'; i++,p++);
if (i<3 || *p!=' ') break;
return CheckPos(sz,method-data+pos);
case PM_HOST:
@@ -444,6 +446,7 @@ const char *TLSVersionStr(uint16_t tlsver)
{
switch(tlsver)
{
case 0x0300: return "SSL 3.0";
case 0x0301: return "TLS 1.0";
case 0x0302: return "TLS 1.1";
case 0x0303: return "TLS 1.2";
@@ -1348,6 +1351,7 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
offset += 1 + data[offset];
// token length
if (offset>=len || (offset + tvb_get_size(data[offset])) > len) return false;
offset += tvb_get_varint(data + offset, &sz);
offset += sz;
if (offset >= len) return false;
@@ -1484,3 +1488,14 @@ bool IsDTLSServerHello(const uint8_t *data, size_t len)
{
return IsDTLS(data,len) && data[0]==0x16 && data[13]==2;
}
bool IsBTHandshake(const uint8_t *data, size_t len)
{
// len, pstrlen, reserved, sha1, peer id
return len>=(1+19+8+20+20) && !memcmp(data,"\x13" "BitTorrent protocol",20);
}
bool IsUTP_BTHandshake(const uint8_t *data, size_t len)
{
// len, pstrlen, reserved, sha1, peer id
return len>=(20+1+19+8+20+20) && data[0]==0x01 && !memcmp(data+20,"\x13" "BitTorrent protocol",20);;
}

View File

@@ -20,6 +20,8 @@ typedef enum {
L7_XMPP,
L7_DNS,
L7_MTPROTO,
L7_BT,
L7_UTP_BT,
L7_LAST, L7_INVALID=L7_LAST, L7_NONE=L7_LAST
} t_l7proto;
const char *l7proto_str(t_l7proto l7);
@@ -56,6 +58,8 @@ typedef enum {
L7P_DNS_QUERY,
L7P_DNS_RESPONSE,
L7P_MTPROTO_INITIAL,
L7P_BT_HANDSHAKE,
L7P_UTP_BT_HANDSHAKE,
L7P_LAST, L7P_INVALID=L7P_LAST, L7P_NONE=L7P_LAST
} t_l7payload;
t_l7payload l7payload_from_name(const char *name);
@@ -160,7 +164,8 @@ 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);
bool IsBTHandshake(const uint8_t *data, size_t len);
bool IsUTP_BTHandshake(const uint8_t *data, size_t len);
#define QUIC_MAX_CID_LENGTH 20
typedef struct quic_cid {

36
nfq2/random.c Normal file
View File

@@ -0,0 +1,36 @@
#include "random.h"
#ifdef NEED_GETRANDOM
#include <unistd.h>
#ifndef SYS_getrandom
#if defined(__aarch64__)
#define SYS_getrandom 278
#elif defined(__arm__)
/* ARM EABI */
#define SYS_getrandom 384
#elif defined(__x86_64__)
#define SYS_getrandom 318
#elif defined(__i386__)
#define SYS_getrandom 355
#elif defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32
#define SYS_getrandom 4353
#else
#error "Unsupported architecture: SYS_getrandom not defined"
#endif
#endif
ssize_t getrandom(void *ptr, size_t len, unsigned int flags)
{
return syscall(SYS_getrandom, ptr, len, flags);
}
#endif

31
nfq2/random.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
// shim for old NDK and old gcc linux compilers
#if defined(__linux__)
#include <sys/syscall.h>
#if defined(__ANDROID__) && __ANDROID_API__ < 28 || !defined(SYS_getrandom)
#define NEED_GETRANDOM
#include <sys/types.h>
/* getrandom flags */
#define GRND_NONBLOCK 1
#define GRND_RANDOM 2
ssize_t getrandom(void *ptr, size_t len, unsigned int flags);
#else
#include <sys/random.h>
#endif
#elif defined(__CYGWIN__)
#include <sys/random.h>
#endif

View File

@@ -210,10 +210,10 @@ int getmaxcap(void)
}
bool dropcaps(void)
{
uint64_t caps = (1<<CAP_NET_ADMIN)|(1<<CAP_NET_RAW);
uint64_t caps = (1ULL<<CAP_NET_ADMIN)|(1ULL<<CAP_NET_RAW);
int maxcap = getmaxcap();
if (setpcap(caps|(1<<CAP_SETPCAP)))
if (setpcap(caps|(1ULL<<CAP_SETPCAP)))
{
for (int cap = 0; cap <= maxcap; cap++)
{
@@ -249,7 +249,7 @@ bool can_drop_root(void)
{
#ifdef __linux__
// has some caps
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID));
return checkpcap((1ULL<<CAP_SETUID)|(1ULL<<CAP_SETGID));
#else
// effective root
return !geteuid();