17 Commits
v70 ... v70.3

Author SHA1 Message Date
bol-van
8ac4fc0af5 fix wrong var 2025-02-26 01:11:07 +03:00
bol-van
af89d03118 nfqws,tpws: fix hostlist-domains file open test 2025-02-25 13:07:38 +03:00
bol-van
d89daaaeac add localhost to zapret-hosts-user-exclude.txt 2025-02-24 13:10:54 +03:00
bol-van
f62b289cb5 nfqws,tpws: --version 2025-02-05 13:04:24 +03:00
bol-van
5f9fa28251 nfqws,tpws: r/o open instead of stat() for list file check 2025-02-04 23:28:18 +03:00
bol-van
bd67b41f32 nfqws,tpws: check accessibility of list files after droproot 2025-02-03 22:37:08 +03:00
bol-van
00619c8dab nfqws,tpws: show hostlist/ipset stat() error 2025-02-02 22:48:23 +03:00
bol-van
58e26c3e9d Merge pull request #1128 from Yoti/patch-1
quick_start: fix spelling
2025-01-30 22:31:37 +03:00
Yoti
eddbc3c3e0 quick_start: fix spelling 2025-01-30 22:20:15 +03:00
bol-van
2cc73de15c readme: move ip2net/mdig chapters 2025-01-30 12:09:34 +03:00
bol-van
9762f2d22b update docs 2025-01-30 12:03:57 +03:00
bol-van
8c9aa188c3 readme: update flow offload info 2025-01-29 14:57:55 +03:00
bol-van
2f151c0943 readme: update flow offload info 2025-01-29 14:55:11 +03:00
bol-van
9498456c4a readme: update flow offload info 2025-01-29 14:47:20 +03:00
bol-van
860607bce2 config.default: remove obsolete comment 2025-01-29 13:42:34 +03:00
bol-van
94f59511f0 update docs 2025-01-28 21:25:44 +03:00
bol-van
b07ce8d8ca nfqws: --dpi-desync-fake-tls-mod=dupsid 2025-01-28 21:22:33 +03:00
18 changed files with 455 additions and 322 deletions

View File

@@ -97,7 +97,7 @@ NFQWS_OPT="
# none,ipset,hostlist,autohostlist
MODE_FILTER=none
# openwrt only : donttouch,none,software,hardware
# donttouch,none,software,hardware
FLOWOFFLOAD=donttouch
# openwrt: specify networks to be treated as LAN. default is "lan"

View File

@@ -452,3 +452,9 @@ install_easy: dnf packager support
nfqws,tpws: hostlist/ipset track not only file mod time but also file size
nfqws,tpws,ipset: return lists reload on HUP
nfqws,blockcheck: --dpi-desync-fake-tls-mod
v70.3
nfqws: --dpi-desync-fake-tls-mod=dupsid
nfqws,tpws: test accessibility of list files after privs drop
nfqws,tpws: --version

View File

@@ -2,8 +2,8 @@
> [!CAUTION]
> Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как
> запустить", ... То есть все , что касается базовых навыков обращения с ОС
> linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> запустить" и т.п. То есть все, что касается базовых навыков обращения с ОС
> Linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> возникают, рекомендую не использовать данный софт или искать помощь где-то в
> другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы
> все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и
@@ -89,14 +89,15 @@
>
> Проверить работает ли этот вариант можно так:
> ```sh
> $ dig -p 53 @77.88.8.88 rutracker.org dig -p 1253 @77.88.8.88 rutracker.org
> $ dig -p 53 @77.88.8.88 rutracker.org
> $ dig -p 1253 @77.88.8.88 rutracker.org
> ```
>
> Если DNS действительно подменяется, и ответ на эти 2 команды разный,
> значит метод вероятно работает.
>
> В openwrt DNS на нестандартном порту можно прописать в `/etc/config/dhcp`
> таким способом :
> таким способом:
>
> ```
> config dnsmasq
@@ -163,7 +164,7 @@
> Если кратко, то обычно параметры конструируются так:
> ```sh
> "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
> --filter-tcp=80,443 'обьединенные параметры для http и https' <HOSTLIST>"
> --filter-tcp=80,443 'объединенные параметры для http и https' <HOSTLIST>"
> ```
>
> Или так:
@@ -193,7 +194,7 @@
> "--filter-l3=ipv4 --filter-udp=443 lпараметры для quic ipv4' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new
> --filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-udp=443 "параметры для quic ipv6" <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-udp=443 'параметры для quic ipv6' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>"
> ```

View File

@@ -1,4 +1,4 @@
# zapret v70
# zapret v70.1
# SCAMMER WARNING
@@ -133,6 +133,7 @@ nfqws takes the following parameters:
--debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--comment ; any text (ignored)
--qnum=<nfqueue_number>
--daemon ; daemonize
@@ -173,7 +174,7 @@ nfqws takes the following parameters:
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
--dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,padencap
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
@@ -273,10 +274,11 @@ It's possible to use TLS Client Hello with any fingerprint and any SNI.
* `none`. Do not do any mods.
* `rnd`. Randomize `random` and `session id` fields. Applied on every request.
* `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup.
* `dupsid`. Copy `session ID` from original TLS Client Hello. Takes precedence over `rnd`. Applied on every request.
* `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request.
By default if custom fake is not defined `rnd,rndsni` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions.
By default if custom fake is not defined `rnd,rndsni,dupsid` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions with addition of `dupsid`.
### TCP segmentation
@@ -659,6 +661,7 @@ tpws is transparent proxy.
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
--debug-level=0|1|2 ; specify debug level for syslog and @<filename>
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface

View File

@@ -1,4 +1,4 @@
# zapret v70
# zapret v70.1
# ВНИМАНИЕ, остерегайтесь мошенников
@@ -47,9 +47,9 @@ zapret является свободным и open source.
- [СЛУЖЕБНЫЕ ПАРАМЕТРЫ](#служебные-параметры)
- [IPTABLES ДЛЯ TPWS](#iptables-для-tpws)
- [NFTABLES ДЛЯ TPWS](#nftables-для-tpws)
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
- [ip2net](#ip2net)
- [mdig](#mdig)
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
- [Фильтрация по именам доменов](#фильтрация-по-именам-доменов)
- [Режим фильтрации autohostlist](#режим-фильтрации-autohostlist)
- [Проверка провайдера](#проверка-провайдера)
@@ -159,6 +159,7 @@ dvtws, собираемый из тех же исходников (см. [док
--debug=0|1 ; 1=выводить отладочные сообщения
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--version ; вывести версию и выйти
--comment ; любой текст (игнорируется)
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
@@ -194,7 +195,7 @@ dvtws, собираемый из тех же исходников (см. [док
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,padencap
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,dupsid,padencap
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
@@ -326,11 +327,12 @@ dvtws, собираемый из тех же исходников (см. [док
* `none`. Не применять никакие модификации.
* `rnd`. Рандомизировать поля `random` и `session id`. Выполняется на каждый запрос.
* `dupsid`. Копировать `session ID` из передаваемого TLS Client Hello. Имеет приоритет над `rnd`. Выполняется на каждый запрос.
* `rndsni`. Рандомизировать SNI. Если SNI >=7 символов, применяется случайный домен 2 уровня с известным TLD, иначе заполняется случайными символами без точки. Выполняется один раз при старте.
* `padencap`. Расширяется padding extension на размер передаваемого TLS Client Hello (включая многопакетный вариант с kyber). Если padding отсутствует, он добавляется в конец. Если присутствует - требуется, чтобы padding шел последним extension. Правятся все длины, чтобы создать видимость включения передаваемого TLS Client Hello в padding extension. Размер фейка не изменяется. Расчет идет на DPI, который не анализирует sequence numbers должным образом. Выполняется на каждый запрос.
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni`. Если фейк задан, используется `none`.
Это соответствует поведению программы более старых версий.
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni,dupsid`. Если фейк задан, используется `none`.
Это соответствует поведению программы более старых версий с добавлением функции `dupsid`.
### TCP СЕГМЕНТАЦИЯ
@@ -759,12 +761,21 @@ iptables могут не работать. При включенном offloadin
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. При включенном SFO работает
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
Offload включается через специальный target в iptables `FLOWOFFLOAD`. Не обязательно пропускать весь трафик через offload. Можно исключить из
offload соединения, которые должны попасть на tpws или nfqws. OpenWrt не предусматривает выборочного управления offload.
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в OpenWrt.
Offload включается через специальный target в iptables `FLOWOFFLOAD` или через flowtable в nftables.
Не обязательно пропускать весь трафик через offload.
tpws и так обходит offload "by design", а для отработки nfqws достаточно первых нескольких пакетов в tcp соединении или udp сеансе.
Пока сеанс не направлен на offload, он процессится обычным образом через полноценный netfilter.
Как только срабатывает правило offload по любому входящему или исходящему пакету, весь сеанс окончательно уходит из netfilter в offload.
Поэтому скрипты zapret берут правила для NFQUEUE, что они создали, и из них создают exemption правила, которые не дают раньше времени попасть сеансу в offload, а потом его "отпускают".
При этом входящим пакетам не дают начать offload, триггером выступают только исходящие пакеты.
Эта схема обеспечивает практически нулевой негативный эффект на скорость, одновременно покрывая нужды nfqws и упрощая правила таблиц.
OpenWrt не предусматривает выборочного управления offload, поэтому скрипты zapret поддерживают свою систему выборочного управления.
iptables target `FLOWOFFLOAD` - это проприетарное изобретение OpenWrt.
Управление offload в nftables реализовано в базовом ядре linux без патчей.
nftables - единственный способ включения offload на классическом Linux.
## tpws
@@ -776,6 +787,7 @@ tpws - это transparent proxy.
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--version ; вывести версию и выйти
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
@@ -893,13 +905,15 @@ tpws, как и nfqws, поддерживает множественную се
указанным сплит позициям. Другие ОС в этом вопросе ведут себя более предсказуемо. Спонтанного обьединения замечено не было.
Поэтому не стоит злоупотреблять сплитами и в особенности мелкими соседними пакетами.
Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8.
Как показывается практика, проблемы могут начаться , если количество сплитов более одного.
На каких-то системах наблюдался стабильный результат до 8 сплитов, на других проблемы уже начинались после 2 сплитов.
Один сплит работает стабильно, если не является частью массивной потоковой передачи.
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
Если вы его видите, это повод снизить количество сплит позиций.
Если это не вариант, для ядер Linux >=4.6 есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
И производится оно только , если происходит split, и в ожидании есть реальная необходимость.
Выполняется оно только , если происходит split, и в ожидании есть реальная необходимость.
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
Если вы пытаетесь сплитнуть массивную передачу с `--split-any-protocol`, когда информация поступает быстрее отсылки,
@@ -1115,6 +1129,78 @@ nft add rule inet ztest dnat_pre meta iifname $IFACE_LAN tcp dport { 80, 443 } d
nft delete table inet ztest
```
## ip2net
Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в `stdout`.
```
-4 ; лист - ipv4 (по умолчанию)
-6 ; лист - ipv6
--prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
--v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
--v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети
```
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
Выбирается подсеть, в которой присутствует указанный минимум адресов.
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.
Размер подсети выбирается следующим алгоритмом:
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
Результат будет :
1234:5678:aaa8::/45
```
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
Если изменить v6_threshold=4, то результат будет:
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
```
То есть ip не объединятся в подсеть, потому что их слишком мало.
Если изменить `prefix_length=56-64`, результат будет:
```
1234:5678:aaaa::/64
1234:5678:aaac::5
```
Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше.
## mdig
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
```
--threads=<threads_number> ; количество потоков. по умолчанию 1.
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
--verbose ; дебаг-лог на консоль
--stats=N ; выводить статистику каждые N доменов
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
```
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
```
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
```
## Способы получения списка заблокированных IP
@@ -1213,79 +1299,6 @@ ipfw таблицы в отличие от ipset могут содержать
Это особенно полезно на BSD системах с PF.
LISTS_RELOAD=- отключает перезагрузку листов.
## ip2net
Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в `stdout`.
```
-4 ; лист - ipv4 (по умолчанию)
-6 ; лист - ipv6
--prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
--v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
--v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети
```
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
Выбирается подсеть, в которой присутствует указанный минимум адресов.
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.
Размер подсети выбирается следующим алгоритмом:
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
Результат будет :
1234:5678:aaa8::/45
```
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
Если изменить v6_threshold=4, то результат будет:
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
```
То есть ip не объединятся в подсеть, потому что их слишком мало.
Если изменить `prefix_length=56-64`, результат будет:
```
1234:5678:aaaa::/64
1234:5678:aaac::5
```
Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше.
## mdig
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
```
--threads=<threads_number> ; количество потоков. по умолчанию 1.
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
--verbose ; дебаг-лог на консоль
--stats=N ; выводить статистику каждые N доменов
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
```
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
```
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
```
## Фильтрация по именам доменов
Альтернативой ipset является использование tpws или nfqws со списком доменов.

View File

@@ -1,6 +1,8 @@
127.0.0.0/8
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
169.254.0.0/16
::1
fc00::/7
fe80::/10

View File

@@ -354,7 +354,7 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
}
if (!append_to_list_file(dp->hostlist_auto->filename, hostname))
{
DLOG_PERROR("write to auto hostlist:");
DLOG_PERROR("write to auto hostlist");
return;
}
if (!file_mod_signature(dp->hostlist_auto->filename, &dp->hostlist_auto->mod_sig))
@@ -606,17 +606,17 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
// size does not change
// return : true - altered, false - not altered
static bool runtime_tls_mod(const struct desync_profile *dp, size_t encap_len, uint8_t *fake_mod)
static bool runtime_tls_mod(const struct desync_profile *dp, uint8_t *fake_mod, const uint8_t *payload, size_t payload_len)
{
bool b=false;
if (dp->fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
{
size_t sz_rec = pntoh16(dp->fake_tls+3) + encap_len;
size_t sz_handshake = pntoh24(dp->fake_tls+6) + encap_len;
size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + encap_len;
size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + encap_len;
size_t sz_rec = pntoh16(dp->fake_tls+3) + payload_len;
size_t sz_handshake = pntoh24(dp->fake_tls+6) + payload_len;
size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + payload_len;
size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + payload_len;
if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF))
DLOG("cannot apply tls mod. length overflow.\n");
DLOG("cannot apply padencap tls mod. length overflow.\n");
else
{
memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
@@ -634,6 +634,19 @@ static bool runtime_tls_mod(const struct desync_profile *dp, size_t encap_len, u
fill_random_bytes(fake_mod+44,fake_mod[43]); // session id
b=true;
}
if (dp->fake_tls_mod & FAKE_TLS_MOD_DUP_SID)
{
if (dp->fake_tls[43]!=payload[43])
DLOG("cannot apply dupsid tls mod. fake and orig session id length mismatch.\n");
else if (payload_len<(44+payload[43]))
DLOG("cannot apply dupsid tls mod. data payload is not valid.\n");
else
{
if (!b) memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
memcpy(fake_mod+44,payload+44,fake_mod[43]); // session id
b=true;
}
}
return b;
}
@@ -1174,7 +1187,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
fake_size = dp->fake_http_size;
break;
case TLS:
fake = runtime_tls_mod(dp,rlen_payload,fake_mod) ? fake_mod : dp->fake_tls;
fake = runtime_tls_mod(dp,fake_mod,rdata_payload,rlen_payload) ? fake_mod : dp->fake_tls;
fake_size = dp->fake_tls_size;
break;
default:

View File

@@ -9,6 +9,7 @@
#include <ctype.h>
#include <sys/stat.h>
#include <libgen.h>
#include <fcntl.h>
int unique_size_t(size_t *pu, int ct)
{
@@ -313,6 +314,17 @@ bool file_mod_signature(const char *filename, file_mod_sig *ms)
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf)
{
return port && (((!pf->from && !pf->to) || (port>=pf->from && port<=pf->to)) ^ pf->neg);

View File

@@ -77,6 +77,7 @@ typedef struct
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct
{

View File

@@ -109,6 +109,7 @@ static bool LoadHostList(struct hostlist_file *hfile)
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}

View File

@@ -130,6 +130,7 @@ static bool LoadIpset(struct ipset_file *hfile)
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}

View File

@@ -120,6 +120,29 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *dat
}
static bool test_list_files()
{
struct hostlist_file *hfile;
struct ipset_file *ifile;
LIST_FOREACH(hfile, &params.hostlists, next)
if (hfile->filename && !file_open_test(hfile->filename, O_RDONLY))
{
DLOG_PERROR("file_open_test");
DLOG_ERR("cannot access hostlist file '%s'\n",hfile->filename);
return false;
}
LIST_FOREACH(ifile, &params.ipsets, next)
if (ifile->filename && !file_open_test(ifile->filename, O_RDONLY))
{
DLOG_PERROR("file_open_test");
DLOG_ERR("cannot access ipset file '%s'\n",ifile->filename);
return false;
}
return true;
}
#ifdef __linux__
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
{
@@ -260,6 +283,8 @@ static int nfq_main(void)
if (params.droproot && !droproot(params.uid, params.gid))
return 1;
print_id();
if (params.droproot && !test_list_files())
return 1;
pre_desync();
@@ -357,6 +382,8 @@ static int dvt_main(void)
if (params.droproot && !droproot(params.uid, params.gid))
goto exiterr;
print_id();
if (params.droproot && !test_list_files())
goto exiterr;
pre_desync();
@@ -934,6 +961,8 @@ static bool parse_tlsmod_list(char *opt, uint8_t *mod)
*mod |= FAKE_TLS_MOD_RND_SNI;
else if (!strcmp(p,"padencap"))
*mod |= FAKE_TLS_MOD_PADENCAP;
else if (!strcmp(p,"dupsid"))
*mod |= FAKE_TLS_MOD_DUP_SID;
else if (strcmp(p,"none"))
return false;
@@ -979,10 +1008,10 @@ static void onetime_tls_mod(struct desync_profile *dp)
size_t extlen, slen;
if (dp->n && !(dp->fake_tls_mod & (FAKE_TLS_MOD_SET|FAKE_TLS_MOD_CUSTOM_FAKE)))
dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI; // old behavior compat
dp->fake_tls_mod |= FAKE_TLS_MOD_RND|FAKE_TLS_MOD_RND_SNI|FAKE_TLS_MOD_DUP_SID; // old behavior compat + dup_sid
if (!(dp->fake_tls_mod & ~FAKE_TLS_MOD_SAVE_MASK))
return; // nothing to do
if (!IsTLSClientHello(dp->fake_tls,dp->fake_tls_size,false))
if (!IsTLSClientHello(dp->fake_tls,dp->fake_tls_size,false) || (dp->fake_tls_size<(44+dp->fake_tls[43]))) // has session id ?
{
DLOG_ERR("profile %d tls mod set but tls fake structure invalid\n", dp->n);
exit_clean(1);
@@ -1201,6 +1230,7 @@ static void exithelp(void)
" @<config_file>|$<config_file>\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
#endif
" --debug=0|1|syslog|@<filename>\n"
" --version\t\t\t\t\t; print version and exit\n"
" --dry-run\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
" --comment=any_text\n"
#ifdef __linux__
@@ -1291,7 +1321,7 @@ static void exithelp(void)
" --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
" --dpi-desync-fake-http=<filename>|0xHEX\t; file containing fake http request\n"
" --dpi-desync-fake-tls=<filename>|0xHEX\t\t; file containing fake TLS ClientHello (for https)\n"
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,padencap\n"
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap\n"
" --dpi-desync-fake-unknown=<filename>|0xHEX\t; file containing unknown protocol fake payload\n"
" --dpi-desync-fake-syndata=<filename>|0xHEX\t; file containing SYN data payload\n"
" --dpi-desync-fake-quic=<filename>|0xHEX\t; file containing fake QUIC Initial\n"
@@ -1459,33 +1489,34 @@ int main(int argc, char **argv)
const struct option long_options[] = {
{"debug",optional_argument,0,0}, // optidx=0
{"dry-run",no_argument,0,0}, // optidx=1
{"comment",optional_argument,0,0}, // optidx=2
{"version",no_argument,0,0}, // optidx=2
{"comment",optional_argument,0,0}, // optidx=3
#ifdef __linux__
{"qnum",required_argument,0,0}, // optidx=3
{"qnum",required_argument,0,0}, // optidx=4
#elif defined(BSD)
{"port",required_argument,0,0}, // optidx=3
{"port",required_argument,0,0}, // optidx=4
#else
{"disabled_argument_1",no_argument,0,0},// optidx=3
{"disabled_argument_1",no_argument,0,0},// optidx=4
#endif
{"daemon",no_argument,0,0}, // optidx=4
{"pidfile",required_argument,0,0}, // optidx=5
{"daemon",no_argument,0,0}, // optidx=5
{"pidfile",required_argument,0,0}, // optidx=6
#ifndef __CYGWIN__
{"user",required_argument,0,0 }, // optidx=6
{"uid",required_argument,0,0 }, // optidx=7
{"user",required_argument,0,0 }, // optidx=7
{"uid",required_argument,0,0 }, // optidx=8
#else
{"disabled_argument_2",no_argument,0,0}, // optidx=6
{"disabled_argument_3",no_argument,0,0}, // optidx=7
{"disabled_argument_2",no_argument,0,0}, // optidx=7
{"disabled_argument_3",no_argument,0,0}, // optidx=8
#endif
{"wsize",required_argument,0,0}, // optidx=8
{"wssize",required_argument,0,0}, // optidx=9
{"wssize-cutoff",required_argument,0,0},// optidx=10
{"ctrack-timeouts",required_argument,0,0},// optidx=11
{"hostcase",no_argument,0,0}, // optidx=12
{"hostspell",required_argument,0,0}, // optidx=13
{"hostnospace",no_argument,0,0}, // optidx=14
{"domcase",no_argument,0,0 }, // optidx=15
{"methodeol",no_argument,0,0 }, // optidx=16
{"dpi-desync",required_argument,0,0}, // optidx=17
{"wsize",required_argument,0,0}, // optidx=9
{"wssize",required_argument,0,0}, // optidx=10
{"wssize-cutoff",required_argument,0,0},// optidx=11
{"ctrack-timeouts",required_argument,0,0},// optidx=12
{"hostcase",no_argument,0,0}, // optidx=13
{"hostspell",required_argument,0,0}, // optidx=14
{"hostnospace",no_argument,0,0}, // optidx=15
{"domcase",no_argument,0,0 }, // optidx=16
{"methodeol",no_argument,0,0 }, // optidx=17
{"dpi-desync",required_argument,0,0}, // optidx=18
#ifdef __linux__
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=18
#elif defined(SO_USER_COOKIE)
@@ -1493,69 +1524,69 @@ int main(int argc, char **argv)
#else
{"disabled_argument_4",no_argument,0,0}, // optidx=18
#endif
{"dpi-desync-ttl",required_argument,0,0}, // optidx=19
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=20
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=21
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=22
{"dpi-desync-fooling",required_argument,0,0}, // optidx=23
{"dpi-desync-repeats",required_argument,0,0}, // optidx=24
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=25
{"dpi-desync-split-pos",required_argument,0,0},// optidx=26
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=27
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=28
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=29
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=30
{"dpi-desync-fakedsplit-pattern",required_argument,0,0 },// optidx=31
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=32
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=33
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=34
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=35
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=36
{"dpi-desync-fake-http",required_argument,0,0},// optidx=37
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=38
{"dpi-desync-fake-tls-mod",required_argument,0,0},// optidx=39
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=40
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=41
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=42
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=43
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=44
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=45
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=46
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=47
{"dpi-desync-cutoff",required_argument,0,0},// optidx=48
{"dpi-desync-start",required_argument,0,0},// optidx=49
{"hostlist",required_argument,0,0}, // optidx=50
{"hostlist-domains",required_argument,0,0},// optidx=51
{"hostlist-exclude",required_argument,0,0}, // optidx=52
{"hostlist-exclude-domains",required_argument,0,0},// optidx=53
{"hostlist-auto",required_argument,0,0}, // optidx=54
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=55
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=56
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=57
{"hostlist-auto-debug",required_argument,0,0}, // optidx=58
{"new",no_argument,0,0}, // optidx=59
{"skip",no_argument,0,0}, // optidx=60
{"filter-l3",required_argument,0,0}, // optidx=61
{"filter-tcp",required_argument,0,0}, // optidx=62
{"filter-udp",required_argument,0,0}, // optidx=63
{"filter-l7",required_argument,0,0}, // optidx=64
{"ipset",required_argument,0,0}, // optidx=65
{"ipset-ip",required_argument,0,0}, // optidx=66
{"ipset-exclude",required_argument,0,0},// optidx=67
{"ipset-exclude-ip",required_argument,0,0}, // optidx=68
{"dpi-desync-ttl",required_argument,0,0}, // optidx=20
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=21
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=22
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=23
{"dpi-desync-fooling",required_argument,0,0}, // optidx=24
{"dpi-desync-repeats",required_argument,0,0}, // optidx=25
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=26
{"dpi-desync-split-pos",required_argument,0,0},// optidx=27
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=28
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=29
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=30
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=31
{"dpi-desync-fakedsplit-pattern",required_argument,0,0 },// optidx=32
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=33
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=34
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=35
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=36
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=37
{"dpi-desync-fake-http",required_argument,0,0},// optidx=38
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=39
{"dpi-desync-fake-tls-mod",required_argument,0,0},// optidx=40
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=41
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=42
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=43
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=44
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=45
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=46
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=47
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=48
{"dpi-desync-cutoff",required_argument,0,0},// optidx=49
{"dpi-desync-start",required_argument,0,0},// optidx=50
{"hostlist",required_argument,0,0}, // optidx=51
{"hostlist-domains",required_argument,0,0},// optidx=52
{"hostlist-exclude",required_argument,0,0}, // optidx=53
{"hostlist-exclude-domains",required_argument,0,0},// optidx=54
{"hostlist-auto",required_argument,0,0}, // optidx=55
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=56
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=57
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=58
{"hostlist-auto-debug",required_argument,0,0}, // optidx=59
{"new",no_argument,0,0}, // optidx=60
{"skip",no_argument,0,0}, // optidx=61
{"filter-l3",required_argument,0,0}, // optidx=62
{"filter-tcp",required_argument,0,0}, // optidx=63
{"filter-udp",required_argument,0,0}, // optidx=64
{"filter-l7",required_argument,0,0}, // optidx=65
{"ipset",required_argument,0,0}, // optidx=66
{"ipset-ip",required_argument,0,0}, // optidx=67
{"ipset-exclude",required_argument,0,0},// optidx=68
{"ipset-exclude-ip",required_argument,0,0}, // optidx=69
#ifdef __linux__
{"bind-fix4",no_argument,0,0}, // optidx=69
{"bind-fix6",no_argument,0,0}, // optidx=70
{"bind-fix4",no_argument,0,0}, // optidx=70
{"bind-fix6",no_argument,0,0}, // optidx=71
#elif defined(__CYGWIN__)
{"wf-iface",required_argument,0,0}, // optidx=69
{"wf-l3",required_argument,0,0}, // optidx=70
{"wf-tcp",required_argument,0,0}, // optidx=71
{"wf-udp",required_argument,0,0}, // optidx=72
{"wf-raw",required_argument,0,0}, // optidx=73
{"wf-save",required_argument,0,0}, // optidx=74
{"ssid-filter",required_argument,0,0}, // optidx=75
{"nlm-filter",required_argument,0,0}, // optidx=76
{"nlm-list",optional_argument,0,0}, // optidx=77
{"wf-iface",required_argument,0,0}, // optidx=70
{"wf-l3",required_argument,0,0}, // optidx=71
{"wf-tcp",required_argument,0,0}, // optidx=72
{"wf-udp",required_argument,0,0}, // optidx=73
{"wf-raw",required_argument,0,0}, // optidx=74
{"wf-save",required_argument,0,0}, // optidx=75
{"ssid-filter",required_argument,0,0}, // optidx=76
{"nlm-filter",required_argument,0,0}, // optidx=77
{"nlm-list",optional_argument,0,0}, // optidx=78
#endif
{NULL,0,NULL,0}
};
@@ -1608,9 +1639,12 @@ int main(int argc, char **argv)
case 1: /* dry-run */
bDry=true;
break;
case 2: /* comment */
case 2: /* version */
exit_clean(0);
break;
case 3: /* qnum or port */
case 3: /* comment */
break;
case 4: /* qnum or port */
#ifdef __linux__
params.qnum = atoi(optarg);
if (params.qnum < 0 || params.qnum>65535)
@@ -1630,15 +1664,15 @@ int main(int argc, char **argv)
}
#endif
break;
case 4: /* daemon */
case 5: /* daemon */
daemon = true;
break;
case 5: /* pidfile */
case 6: /* pidfile */
strncpy(pidfile, optarg, sizeof(pidfile));
pidfile[sizeof(pidfile) - 1] = '\0';
break;
#ifndef __CYGWIN__
case 6: /* user */
case 7: /* user */
{
struct passwd *pwd = getpwnam(optarg);
if (!pwd)
@@ -1651,7 +1685,7 @@ int main(int argc, char **argv)
params.droproot = true;
break;
}
case 7: /* uid */
case 8: /* uid */
params.gid = 0x7FFFFFFF; // default gid. drop gid=0
params.droproot = true;
if (sscanf(optarg, "%u:%u", &params.uid, &params.gid)<1)
@@ -1661,32 +1695,32 @@ int main(int argc, char **argv)
}
break;
#endif
case 8: /* wsize */
case 9: /* wsize */
if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale))
exit_clean(1);
break;
case 9: /* wssize */
case 10: /* wssize */
if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale))
exit_clean(1);
break;
case 10: /* wssize-cutoff */
case 11: /* wssize-cutoff */
if (!parse_cutoff(optarg, &dp->wssize_cutoff, &dp->wssize_cutoff_mode))
{
DLOG_ERR("invalid wssize-cutoff value\n");
exit_clean(1);
}
break;
case 11: /* ctrack-timeouts */
case 12: /* ctrack-timeouts */
if (sscanf(optarg, "%u:%u:%u:%u", &params.ctrack_t_syn, &params.ctrack_t_est, &params.ctrack_t_fin, &params.ctrack_t_udp)<3)
{
DLOG_ERR("invalid ctrack-timeouts value\n");
exit_clean(1);
}
break;
case 12: /* hostcase */
case 13: /* hostcase */
dp->hostcase = true;
break;
case 13: /* hostspell */
case 14: /* hostspell */
if (strlen(optarg) != 4)
{
DLOG_ERR("hostspell must be exactly 4 chars long\n");
@@ -1695,7 +1729,7 @@ int main(int argc, char **argv)
dp->hostcase = true;
memcpy(dp->hostspell, optarg, 4);
break;
case 14: /* hostnospace */
case 15: /* hostnospace */
if (dp->methodeol)
{
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
@@ -1703,10 +1737,10 @@ int main(int argc, char **argv)
}
dp->hostnospace = true;
break;
case 15: /* domcase */
case 16: /* domcase */
dp->domcase = true;
break;
case 16: /* methodeol */
case 17: /* methodeol */
if (dp->hostnospace)
{
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
@@ -1714,7 +1748,7 @@ int main(int argc, char **argv)
}
dp->methodeol = true;
break;
case 17: /* dpi-desync */
case 18: /* dpi-desync */
{
char *mode=optarg,*mode2,*mode3;
mode2 = mode ? strchr(mode,',') : NULL;
@@ -1760,7 +1794,7 @@ int main(int argc, char **argv)
}
break;
#ifndef __CYGWIN__
case 18: /* dpi-desync-fwmark/dpi-desync-sockarg */
case 19: /* dpi-desync-fwmark/dpi-desync-sockarg */
#if defined(__linux__) || defined(SO_USER_COOKIE)
params.desync_fwmark = 0;
if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark);
@@ -1775,27 +1809,27 @@ int main(int argc, char **argv)
#endif
break;
#endif
case 19: /* dpi-desync-ttl */
case 20: /* dpi-desync-ttl */
dp->desync_ttl = (uint8_t)atoi(optarg);
break;
case 20: /* dpi-desync-ttl6 */
case 21: /* dpi-desync-ttl6 */
dp->desync_ttl6 = (uint8_t)atoi(optarg);
break;
case 21: /* dpi-desync-autottl */
case 22: /* dpi-desync-autottl */
if (!parse_autottl(optarg, &dp->desync_autottl))
{
DLOG_ERR("dpi-desync-autottl value error\n");
exit_clean(1);
}
break;
case 22: /* dpi-desync-autottl6 */
case 23: /* dpi-desync-autottl6 */
if (!parse_autottl(optarg, &dp->desync_autottl6))
{
DLOG_ERR("dpi-desync-autottl6 value error\n");
exit_clean(1);
}
break;
case 23: /* dpi-desync-fooling */
case 24: /* dpi-desync-fooling */
{
char *e,*p = optarg;
while (p)
@@ -1830,17 +1864,17 @@ int main(int argc, char **argv)
}
}
break;
case 24: /* dpi-desync-repeats */
case 25: /* dpi-desync-repeats */
if (sscanf(optarg,"%u",&dp->desync_repeats)<1 || !dp->desync_repeats || dp->desync_repeats>20)
{
DLOG_ERR("dpi-desync-repeats must be within 1..20\n");
exit_clean(1);
}
break;
case 25: /* dpi-desync-skip-nosni */
case 26: /* dpi-desync-skip-nosni */
dp->desync_skip_nosni = !optarg || atoi(optarg);
break;
case 26: /* dpi-desync-split-pos */
case 27: /* dpi-desync-split-pos */
{
int ct;
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
@@ -1851,7 +1885,7 @@ int main(int argc, char **argv)
dp->split_count += ct;
}
break;
case 27: /* dpi-desync-split-http-req */
case 28: /* dpi-desync-split-http-req */
// obsolete arg
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
if (dp->split_count>=MAX_SPLITS)
@@ -1866,7 +1900,7 @@ int main(int argc, char **argv)
}
dp->split_count++;
break;
case 28: /* dpi-desync-split-tls */
case 29: /* dpi-desync-split-tls */
// obsolete arg
DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
if (dp->split_count>=MAX_SPLITS)
@@ -1881,7 +1915,7 @@ int main(int argc, char **argv)
}
dp->split_count++;
break;
case 29: /* dpi-desync-split-seqovl */
case 30: /* dpi-desync-split-seqovl */
if (!strcmp(optarg,"0"))
{
// allow zero = disable seqovl
@@ -1894,7 +1928,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 30: /* dpi-desync-split-seqovl-pattern */
case 31: /* dpi-desync-split-seqovl-pattern */
{
char buf[sizeof(dp->seqovl_pattern)];
size_t sz=sizeof(buf);
@@ -1902,7 +1936,7 @@ int main(int argc, char **argv)
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
}
break;
case 31: /* dpi-desync-fakedsplit-pattern */
case 32: /* dpi-desync-fakedsplit-pattern */
{
char buf[sizeof(dp->fsplit_pattern)];
size_t sz=sizeof(buf);
@@ -1910,7 +1944,7 @@ int main(int argc, char **argv)
fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz);
}
break;
case 32: /* dpi-desync-ipfrag-pos-tcp */
case 33: /* dpi-desync-ipfrag-pos-tcp */
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_tcp)<1 || dp->desync_ipfrag_pos_tcp<1 || dp->desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
{
DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
@@ -1922,7 +1956,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 33: /* dpi-desync-ipfrag-pos-udp */
case 34: /* dpi-desync-ipfrag-pos-udp */
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_udp)<1 || dp->desync_ipfrag_pos_udp<1 || dp->desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
{
DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
@@ -1934,71 +1968,71 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 34: /* dpi-desync-badseq-increments */
case 35: /* dpi-desync-badseq-increments */
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
{
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1);
}
break;
case 35: /* dpi-desync-badack-increment */
case 36: /* dpi-desync-badack-increment */
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_increment))
{
DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1);
}
break;
case 36: /* dpi-desync-any-protocol */
case 37: /* dpi-desync-any-protocol */
dp->desync_any_proto = !optarg || atoi(optarg);
break;
case 37: /* dpi-desync-fake-http */
case 38: /* dpi-desync-fake-http */
dp->fake_http_size = sizeof(dp->fake_http);
load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size);
break;
case 38: /* dpi-desync-fake-tls */
case 39: /* dpi-desync-fake-tls */
dp->fake_tls_size = sizeof(dp->fake_tls);
load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size);
dp->fake_tls_mod |= FAKE_TLS_MOD_CUSTOM_FAKE;
break;
case 39: /* dpi-desync-fake-tls-mod */
case 40: /* dpi-desync-fake-tls-mod */
if (!parse_tlsmod_list(optarg,&dp->fake_tls_mod))
{
DLOG_ERR("Invalid tls mod : %s\n",optarg);
exit_clean(1);
}
break;
case 40: /* dpi-desync-fake-unknown */
case 41: /* dpi-desync-fake-unknown */
dp->fake_unknown_size = sizeof(dp->fake_unknown);
load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size);
break;
case 41: /* dpi-desync-fake-syndata */
case 42: /* dpi-desync-fake-syndata */
dp->fake_syndata_size = sizeof(dp->fake_syndata);
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
break;
case 42: /* dpi-desync-fake-quic */
case 43: /* dpi-desync-fake-quic */
dp->fake_quic_size = sizeof(dp->fake_quic);
load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size);
break;
case 43: /* dpi-desync-fake-wireguard */
case 44: /* dpi-desync-fake-wireguard */
dp->fake_wg_size = sizeof(dp->fake_wg);
load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size);
break;
case 44: /* dpi-desync-fake-dht */
case 45: /* dpi-desync-fake-dht */
dp->fake_dht_size = sizeof(dp->fake_dht);
load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size);
break;
case 45: /* dpi-desync-fake-unknown-udp */
case 46: /* dpi-desync-fake-unknown-udp */
dp->fake_unknown_udp_size = sizeof(dp->fake_unknown_udp);
load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size);
break;
case 46: /* dpi-desync-udplen-increment */
case 47: /* dpi-desync-udplen-increment */
if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000)
{
DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
exit_clean(1);
}
break;
case 47: /* dpi-desync-udplen-pattern */
case 48: /* dpi-desync-udplen-pattern */
{
char buf[sizeof(dp->udplen_pattern)];
size_t sz=sizeof(buf);
@@ -2006,21 +2040,21 @@ int main(int argc, char **argv)
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
}
break;
case 48: /* desync-cutoff */
case 49: /* desync-cutoff */
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
{
DLOG_ERR("invalid desync-cutoff value\n");
exit_clean(1);
}
break;
case 49: /* desync-start */
case 50: /* desync-start */
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
{
DLOG_ERR("invalid desync-start value\n");
exit_clean(1);
}
break;
case 50: /* hostlist */
case 51: /* hostlist */
if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg))
{
@@ -2028,7 +2062,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 51: /* hostlist-domains */
case 52: /* hostlist-domains */
if (bSkip) break;
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
{
@@ -2041,7 +2075,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 52: /* hostlist-exclude */
case 53: /* hostlist-exclude */
if (bSkip) break;
if (!RegisterHostlist(dp, true, optarg))
{
@@ -2049,7 +2083,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 53: /* hostlist-exclude-domains */
case 54: /* hostlist-exclude-domains */
if (bSkip) break;
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
{
@@ -2062,7 +2096,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 54: /* hostlist-auto */
case 55: /* hostlist-auto */
if (bSkip) break;
if (dp->hostlist_auto)
{
@@ -2090,7 +2124,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 55: /* hostlist-auto-fail-threshold */
case 56: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
{
@@ -2098,7 +2132,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 56: /* hostlist-auto-fail-time */
case 57: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1)
{
@@ -2106,7 +2140,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 57: /* hostlist-auto-retrans-threshold */
case 58: /* hostlist-auto-retrans-threshold */
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
{
@@ -2114,7 +2148,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 58: /* hostlist-auto-debug */
case 59: /* hostlist-auto-debug */
{
FILE *F = fopen(optarg,"a+t");
if (!F)
@@ -2128,7 +2162,7 @@ int main(int argc, char **argv)
}
break;
case 59: /* new */
case 60: /* new */
if (bSkip)
{
dp_clear(dp);
@@ -2150,18 +2184,18 @@ int main(int argc, char **argv)
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
break;
case 60: /* skip */
case 61: /* skip */
bSkip = true;
break;
case 61: /* filter-l3 */
case 62: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{
DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1);
}
break;
case 62: /* filter-tcp */
case 63: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp))
{
DLOG_ERR("Invalid port filter : %s\n",optarg);
@@ -2171,7 +2205,7 @@ int main(int argc, char **argv)
if (!port_filters_deny_if_empty(&dp->pf_udp))
exit_clean(1);
break;
case 63: /* filter-udp */
case 64: /* filter-udp */
if (!parse_pf_list(optarg,&dp->pf_udp))
{
DLOG_ERR("Invalid port filter : %s\n",optarg);
@@ -2181,14 +2215,14 @@ int main(int argc, char **argv)
if (!port_filters_deny_if_empty(&dp->pf_tcp))
exit_clean(1);
break;
case 64: /* filter-l7 */
case 65: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7))
{
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1);
}
break;
case 65: /* ipset */
case 66: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg))
{
@@ -2196,7 +2230,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 66: /* ipset-ip */
case 67: /* ipset-ip */
if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{
@@ -2209,7 +2243,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 67: /* ipset-exclude */
case 68: /* ipset-exclude */
if (bSkip) break;
if (!RegisterIpset(dp, true, optarg))
{
@@ -2217,7 +2251,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 68: /* ipset-exclude-ip */
case 69: /* ipset-exclude-ip */
if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{
@@ -2233,28 +2267,28 @@ int main(int argc, char **argv)
#ifdef __linux__
case 69: /* bind-fix4 */
case 70: /* bind-fix4 */
params.bind_fix4 = true;
break;
case 70: /* bind-fix6 */
case 71: /* bind-fix6 */
params.bind_fix6 = true;
break;
#elif defined(__CYGWIN__)
case 69: /* wf-iface */
case 70: /* wf-iface */
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
{
DLOG_ERR("bad value for --wf-iface\n");
exit_clean(1);
}
break;
case 70: /* wf-l3 */
case 71: /* wf-l3 */
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
{
DLOG_ERR("bad value for --wf-l3\n");
exit_clean(1);
}
break;
case 71: /* wf-tcp */
case 72: /* wf-tcp */
hash_wf_tcp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) ||
!wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst)))
@@ -2263,7 +2297,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 72: /* wf-udp */
case 73: /* wf-udp */
hash_wf_udp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) ||
!wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst)))
@@ -2272,7 +2306,7 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case 73: /* wf-raw */
case 74: /* wf-raw */
hash_wf_raw=hash_jen(optarg,strlen(optarg));
if (optarg[0]=='@')
{
@@ -2286,11 +2320,11 @@ int main(int argc, char **argv)
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
}
break;
case 74: /* wf-save */
case 75: /* wf-save */
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
break;
case 75: /* ssid-filter */
case 76: /* ssid-filter */
hash_ssid_filter=hash_jen(optarg,strlen(optarg));
{
char *e,*p = optarg;
@@ -2308,7 +2342,7 @@ int main(int argc, char **argv)
}
}
break;
case 76: /* nlm-filter */
case 77: /* nlm-filter */
hash_nlm_filter=hash_jen(optarg,strlen(optarg));
{
char *e,*p = optarg;
@@ -2326,7 +2360,7 @@ int main(int argc, char **argv)
}
}
break;
case 77: /* nlm-list */
case 78: /* nlm-list */
if (!nlm_list(optarg && !strcmp(optarg,"all")))
{
DLOG_ERR("could not get list of NLM networks\n");

View File

@@ -42,8 +42,9 @@
#define FAKE_TLS_MOD_SET 0x01
#define FAKE_TLS_MOD_CUSTOM_FAKE 0x02
#define FAKE_TLS_MOD_RND 0x10
#define FAKE_TLS_MOD_RND_SNI 0x20
#define FAKE_TLS_MOD_PADENCAP 0x40
#define FAKE_TLS_MOD_DUP_SID 0x20
#define FAKE_TLS_MOD_RND_SNI 0x40
#define FAKE_TLS_MOD_PADENCAP 0x80
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };

View File

@@ -11,6 +11,7 @@
#include <sys/stat.h>
#include <libgen.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef __ANDROID__
#include "andr/ifaddrs.h"
@@ -327,6 +328,17 @@ bool file_mod_signature(const char *filename, file_mod_sig *ms)
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf)
{
return port && (((!pf->from && !pf->to) || (port >= pf->from && port <= pf->to)) ^ pf->neg);

View File

@@ -71,6 +71,7 @@ typedef struct
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct
{

View File

@@ -109,6 +109,7 @@ static bool LoadHostList(struct hostlist_file *hfile)
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}

View File

@@ -130,6 +130,7 @@ static bool LoadIpset(struct ipset_file *hfile)
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}

View File

@@ -116,6 +116,29 @@ static int8_t block_sigpipe(void)
return 0;
}
static bool test_list_files()
{
struct hostlist_file *hfile;
struct ipset_file *ifile;
printf("1\n");
LIST_FOREACH(hfile, &params.hostlists, next)
if (hfile->filename && !file_open_test(hfile->filename, O_RDONLY))
{
DLOG_PERROR("file_open_test");
DLOG_ERR("cannot access hostlist file '%s'\n",hfile->filename);
return false;
}
LIST_FOREACH(ifile, &params.ipsets, next)
if (ifile->filename && !file_open_test(ifile->filename, O_RDONLY))
{
DLOG_PERROR("file_open_test");
DLOG_ERR("cannot access ipset file '%s'\n",ifile->filename);
return false;
}
printf("2\n");
return true;
}
static bool is_interface_online(const char *ifname)
{
@@ -197,6 +220,7 @@ static void exithelp(void)
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
" --debug-level=0|1|2\t\t\t; specify debug level\n"
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
" --version\t\t\t\t; print version and exit\n"
" --comment=any_text\n"
"\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t; begin new strategy\n"
@@ -691,41 +715,42 @@ void parse_params(int argc, char *argv[])
{ "debug",optional_argument,0,0 },// optidx=45
{ "debug-level",required_argument,0,0 },// optidx=46
{ "dry-run",no_argument,0,0 },// optidx=47
{ "comment",optional_argument,0,0 },// optidx=48
{ "local-rcvbuf",required_argument,0,0 },// optidx=49
{ "local-sndbuf",required_argument,0,0 },// optidx=50
{ "remote-rcvbuf",required_argument,0,0 },// optidx=51
{ "remote-sndbuf",required_argument,0,0 },// optidx=52
{ "socks",no_argument,0,0 },// optidx=53
{ "no-resolve",no_argument,0,0 },// optidx=54
{ "resolver-threads",required_argument,0,0 },// optidx=55
{ "skip-nodelay",no_argument,0,0 },// optidx=56
{ "tamper-start",required_argument,0,0 },// optidx=57
{ "tamper-cutoff",required_argument,0,0 },// optidx=58
{ "connect-bind-addr",required_argument,0,0 },// optidx=59
{ "version",no_argument,0,0 },// optidx=48
{ "comment",optional_argument,0,0 },// optidx=49
{ "local-rcvbuf",required_argument,0,0 },// optidx=50
{ "local-sndbuf",required_argument,0,0 },// optidx=51
{ "remote-rcvbuf",required_argument,0,0 },// optidx=52
{ "remote-sndbuf",required_argument,0,0 },// optidx=53
{ "socks",no_argument,0,0 },// optidx=54
{ "no-resolve",no_argument,0,0 },// optidx=55
{ "resolver-threads",required_argument,0,0 },// optidx=56
{ "skip-nodelay",no_argument,0,0 },// optidx=57
{ "tamper-start",required_argument,0,0 },// optidx=58
{ "tamper-cutoff",required_argument,0,0 },// optidx=59
{ "connect-bind-addr",required_argument,0,0 },// optidx=60
{ "new",no_argument,0,0 }, // optidx=60
{ "skip",no_argument,0,0 }, // optidx=61
{ "filter-l3",required_argument,0,0 }, // optidx=62
{ "filter-tcp",required_argument,0,0 }, // optidx=63
{ "filter-l7",required_argument,0,0 }, // optidx=64
{ "ipset",required_argument,0,0 }, // optidx=65
{ "ipset-ip",required_argument,0,0 }, // optidx=66
{ "ipset-exclude",required_argument,0,0 }, // optidx=67
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=68
{ "new",no_argument,0,0 }, // optidx=61
{ "skip",no_argument,0,0 }, // optidx=62
{ "filter-l3",required_argument,0,0 }, // optidx=63
{ "filter-tcp",required_argument,0,0 }, // optidx=64
{ "filter-l7",required_argument,0,0 }, // optidx=65
{ "ipset",required_argument,0,0 }, // optidx=66
{ "ipset-ip",required_argument,0,0 }, // optidx=67
{ "ipset-exclude",required_argument,0,0 }, // optidx=68
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=69
#if defined(__FreeBSD__)
{ "enable-pf",no_argument,0,0 },// optidx=69
#elif defined(__APPLE__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=79
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
#elif defined(__linux__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
{ "mss",required_argument,0,0 }, // optidx=71
{ "fix-seg",optional_argument,0,0 }, // optidx=72
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=70
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
{ "mss",required_argument,0,0 }, // optidx=72
{ "fix-seg",optional_argument,0,0 }, // optidx=73
#ifdef SPLICE_PRESENT
{ "nosplice",no_argument,0,0 }, // optidx=73
{ "nosplice",no_argument,0,0 }, // optidx=74
#endif
#endif
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
@@ -1176,43 +1201,46 @@ void parse_params(int argc, char *argv[])
case 47: /* dry-run */
bDry = true;
break;
case 48: /* comment */
case 48: /* version */
exit_clean(0);
break;
case 49: /* local-rcvbuf */
case 49: /* comment */
break;
case 50: /* local-rcvbuf */
#ifdef __linux__
params.local_rcvbuf = atoi(optarg)/2;
#else
params.local_rcvbuf = atoi(optarg);
#endif
break;
case 50: /* local-sndbuf */
case 51: /* local-sndbuf */
#ifdef __linux__
params.local_sndbuf = atoi(optarg)/2;
#else
params.local_sndbuf = atoi(optarg);
#endif
break;
case 51: /* remote-rcvbuf */
case 52: /* remote-rcvbuf */
#ifdef __linux__
params.remote_rcvbuf = atoi(optarg)/2;
#else
params.remote_rcvbuf = atoi(optarg);
#endif
break;
case 52: /* remote-sndbuf */
case 53: /* remote-sndbuf */
#ifdef __linux__
params.remote_sndbuf = atoi(optarg)/2;
#else
params.remote_sndbuf = atoi(optarg);
#endif
break;
case 53: /* socks */
case 54: /* socks */
params.proxy_type = CONN_TYPE_SOCKS;
break;
case 54: /* no-resolve */
case 55: /* no-resolve */
params.no_resolve = true;
break;
case 55: /* resolver-threads */
case 56: /* resolver-threads */
params.resolver_threads = atoi(optarg);
if (params.resolver_threads<1 || params.resolver_threads>300)
{
@@ -1220,10 +1248,10 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 56: /* skip-nodelay */
case 57: /* skip-nodelay */
params.skip_nodelay = true;
break;
case 57: /* tamper-start */
case 58: /* tamper-start */
{
const char *p=optarg;
if (*p=='n')
@@ -1237,7 +1265,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper_lim = true;
break;
case 58: /* tamper-cutoff */
case 59: /* tamper-cutoff */
{
const char *p=optarg;
if (*p=='n')
@@ -1251,7 +1279,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper_lim = true;
break;
case 59: /* connect-bind-addr */
case 60: /* connect-bind-addr */
{
char *p = strchr(optarg,'%');
if (p) *p++=0;
@@ -1279,7 +1307,7 @@ void parse_params(int argc, char *argv[])
break;
case 60: /* new */
case 61: /* new */
if (bSkip)
{
dp_clear(dp);
@@ -1300,31 +1328,31 @@ void parse_params(int argc, char *argv[])
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
break;
case 61: /* skip */
case 62: /* skip */
bSkip = true;
break;
case 62: /* filter-l3 */
case 63: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{
DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1);
}
break;
case 63: /* filter-tcp */
case 64: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp))
{
DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1);
}
break;
case 64: /* filter-l7 */
case 65: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7))
{
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1);
}
break;
case 65: /* ipset */
case 66: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg))
{
@@ -1333,7 +1361,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 66: /* ipset-ip */
case 67: /* ipset-ip */
if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{
@@ -1347,7 +1375,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 67: /* ipset-exclude */
case 68: /* ipset-exclude */
if (bSkip) break;
if (!RegisterIpset(dp, true, optarg))
{
@@ -1356,7 +1384,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 68: /* ipset-exclude-ip */
case 69: /* ipset-exclude-ip */
if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{
@@ -1372,11 +1400,11 @@ void parse_params(int argc, char *argv[])
break;
#if defined(__FreeBSD__)
case 69: /* enable-pf */
case 70: /* enable-pf */
params.pf_enable = true;
break;
#elif defined(__linux__) || defined(__APPLE__)
case 69: /* local-tcp-user-timeout */
case 70: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
{
@@ -1384,7 +1412,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 70: /* remote-tcp-user-timeout */
case 71: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
{
@@ -1395,7 +1423,7 @@ void parse_params(int argc, char *argv[])
#endif
#if defined(__linux__)
case 71: /* mss */
case 72: /* mss */
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
dp->mss = atoi(optarg);
if (dp->mss<88 || dp->mss>32767)
@@ -1404,7 +1432,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 72: /* fix-seg */
case 73: /* fix-seg */
if (!params.fix_seg_avail)
{
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
@@ -1424,7 +1452,7 @@ void parse_params(int argc, char *argv[])
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break;
#ifdef SPLICE_PRESENT
case 73: /* nosplice */
case 74: /* nosplice */
params.nosplice = true;
break;
#endif
@@ -1918,10 +1946,12 @@ int main(int argc, char *argv[])
set_ulimit();
sec_harden();
if (params.droproot && !droproot(params.uid,params.gid))
goto exiterr;
print_id();
if (params.droproot && !test_list_files())
goto exiterr;
//splice() causes the process to receive the SIGPIPE-signal if one part (for
//example a socket) is closed during splice(). I would rather have splice()
//fail and return -1, so blocking SIGPIPE.