23 Commits
v69 ... v69.2

Author SHA1 Message Date
bol-van
9c8662b25e nfqws,tpws: fix crash 2024-11-23 14:14:12 +03:00
bol-van
fedb62df66 update docs 2024-11-23 13:28:34 +03:00
bol-van
44c19c1743 blockcheck: --methodeol test for nfqws 2024-11-23 13:20:02 +03:00
bol-van
56aa481226 nfqws: warn if cannot do hostnospace 2024-11-23 13:17:34 +03:00
bol-van
9184317549 nfqws: --methodeol 2024-11-23 13:14:02 +03:00
bol-van
a3048ae120 nfqws: --skip 2024-11-23 12:55:14 +03:00
bol-van
fc44d74f2b fix lto in nfqws makefile 2024-11-23 12:33:15 +03:00
bol-van
1779cfad30 tpws: --skip 2024-11-23 12:17:49 +03:00
bol-van
4856be4ef1 init.d: do not use pgrep for firmwares compatibility 2024-11-23 10:58:46 +03:00
bol-van
033043bdc0 tpws: remote duplicate if 2024-11-22 13:04:06 +03:00
bol-van
46284938ce tpws: fix socks-hostname hostlist checks 2024-11-22 12:42:33 +03:00
bol-van
09378553b9 keenetic script check disable ipv4 2024-11-21 20:35:27 +03:00
bol-van
6b85884cdf update keentic fix script 2024-11-21 20:30:23 +03:00
bol-van
1b14a8210c readme: more precise marker definition 2024-11-21 15:44:18 +03:00
bol-van
182fe850db makefiles: use lto 2024-11-21 15:25:19 +03:00
bol-van
62b081e9fb doc works 2024-11-21 10:47:11 +03:00
bol-van
e3e7449d74 doc works 2024-11-21 10:44:52 +03:00
bol-van
669f1978a3 doc works 2024-11-21 10:02:32 +03:00
bol-van
57c4b1a2b2 fix grep in default_route_interfaces6 2024-11-20 17:21:16 +03:00
bol-van
ac7385391e 10-keenetic-udp-fix: auto discover wan interfaces 2024-11-19 22:09:40 +03:00
bol-van
50a52d79ec default_route_interfaces helpers 2024-11-19 22:08:48 +03:00
bol-van
d77a1c8cd6 init.d: keenetic udp fix script 2024-11-19 19:54:21 +03:00
bol-van
395b9480c5 nfqws: fix wrong printf format 2024-11-19 19:27:36 +03:00
22 changed files with 465 additions and 298 deletions

View File

@@ -1173,7 +1173,7 @@ pktws_check_domain_http_bypass_()
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1' local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
[ "$sec" = 0 ] && { [ "$sec" = 0 ] && {
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase'; do for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase' '--methodeol'; do
pktws_curl_test_update $1 $3 $s pktws_curl_test_update $1 $3 $s
done done
} }

View File

@@ -125,3 +125,13 @@ resolve_lower_devices()
} }
} }
} }
default_route_interfaces6()
{
sed -nre 's/^00000000000000000000000000000000 00 [0-9a-f]{32} [0-9a-f]{2} [0-9a-f]{32} [0-9a-f]{8} [0-9a-f]{8} [0-9a-f]{8} [0-9a-f]{8} +(.*)$/\1/p' /proc/net/ipv6_route | grep -v '^lo$' | sort -u | xargs
}
default_route_interfaces4()
{
sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs
}

View File

@@ -389,3 +389,14 @@ blockcheck: added CURL_OPT
blockcheck: new strategies support blockcheck: new strategies support
blockcheck: test sequence rework blockcheck: test sequence rework
blockcheck: view all working strategies in summary blockcheck: view all working strategies in summary
v69.1:
init.d: keenetic udp fix custom
tpws: fixed incorrect hostlist checks
v69.2:
nfqws,tpws: --skip
nfqws: --methodeol
init.d: do not use pgrep in sysv for busybox compat

View File

@@ -146,6 +146,7 @@ nfqws takes the following parameters:
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host" --hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size --hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
--domcase ; mix domain case : Host: TeSt.cOm --domcase ; mix domain case : Host: TeSt.cOm
--methodeol ; add '\n' before method and remove space after Host:
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper --dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824) --dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
--dpi-desync-ttl=<int> ; set ttl for desync packet --dpi-desync-ttl=<int> ; set ttl for desync packet
@@ -185,7 +186,8 @@ nfqws takes the following parameters:
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60) --hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
--hostlist-auto-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3) --hostlist-auto-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3)
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives --hostlist-auto-debug=<logfile> ; debug auto hostlist positives
--new ; begin new strategy --new ; begin new strategy (new profile)
--skip ; do not use this profile
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. --filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported. --filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported.
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported. --filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
@@ -267,7 +269,7 @@ Positions are defined by markers.
Relative positions : Relative positions :
* **method** - HTTP method start ('GET', 'POST', 'HEAD', ...). Method is usually always at position 0 but also supported `--methodeol` fooling by **tpws**. If fooled position can become 1 or 2. * **method** - HTTP method start ('GET', 'POST', 'HEAD', ...). Method is usually always at position 0 but can shift because of `--methodeol` fooling. If fooled position can become 1 or 2.
* **host** - hostname start in a known protocol (http, TLS) * **host** - hostname start in a known protocol (http, TLS)
* **endhost** - the byte next to the last hostname's byte * **endhost** - the byte next to the last hostname's byte
* **sld** - second level domain start in the hostname * **sld** - second level domain start in the hostname
@@ -663,7 +665,8 @@ tpws is transparent proxy.
; its worth to make a reserve with 1.5 multiplier. by default maxfiles is (X*connections)*1.5+16 ; its worth to make a reserve with 1.5 multiplier. by default maxfiles is (X*connections)*1.5+16
--max-orphan-time=<sec> ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds --max-orphan-time=<sec> ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds
--new ; begin new strategy --new ; begin new strategy (new profile)
--skip ; do not use this profile
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. --filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. comma separated list supported. --filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. comma separated list supported.
--filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed. --filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.

View File

@@ -175,6 +175,7 @@ dvtws, собираемый из тех же исходников (см. [док
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60 --ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--domcase ; домен после Host: сделать таким : TeSt.cOm --domcase ; домен после Host: сделать таким : TeSt.cOm
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper --dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
@@ -217,6 +218,7 @@ dvtws, собираемый из тех же исходников (см. [док
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3) --hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. --hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль) --new ; начало новой стратегии (новый профиль)
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии --filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую. --filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую. --filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
@@ -323,11 +325,11 @@ dvtws, собираемый из тех же исходников (см. [док
Относительные позиции : Относительные позиции :
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но поддерживается и нахождение метода после дурение методом `--methodeol` от tpws. Тогда позиция может стать 1 или 2. * **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но может сместиться из-за `--methodeol`. Тогда позиция может стать 1 или 2.
* **host** - начало имени хоста в известном протоколе (http, TLS) * **host** - начало имени хоста в известном протоколе (http, TLS)
* **endhost** - конец имени хоста * **endhost** - байт, следующий за последним байтом имени хоста
* **sld** - начало домена 2 уровня в имени хоста * **sld** - начало домена 2 уровня в имени хоста
* **endsld** - конец домена 2 уровня в имени хоста * **endsld** - байт, следующий за последним байтом домена 2 уровня в имени хоста
* **midsld** - середина домена 2 уровня в имени хоста * **midsld** - середина домена 2 уровня в имени хоста
* **sniext** - начало поля данных SNI extension в TLS. Любой extension состоит из 2-байтовых полей type и length, за ними идет поле данных. * **sniext** - начало поля данных SNI extension в TLS. Любой extension состоит из 2-байтовых полей type и length, за ними идет поле данных.
@@ -381,7 +383,7 @@ Windows оставляет старые данные, поэтому disorder с
### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6 ### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6
Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к `ipv6` и заключается Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к ipv6 и заключается
в добавлении хедера `hop-by-hop options`, `destination options` или `fragment` во все пакеты, попадающие под десинхронизацию. в добавлении хедера `hop-by-hop options`, `destination options` или `fragment` во все пакеты, попадающие под десинхронизацию.
Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено
к пакетам максимального размера. Это имеет место при передаче больших сообщений. к пакетам максимального размера. Это имеет место при передаче больших сообщений.
@@ -398,7 +400,7 @@ extension хедерам в поисках транспортного хедер
В параметре dpi-desync можно указать до 3 режимов через запятую. В параметре dpi-desync можно указать до 3 режимов через запятую.
* 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata` `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](((#множественные-стратегии))). * 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata`, `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](#множественные-стратегии).
* 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`. * 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`.
* 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`). * 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`).
@@ -424,29 +426,10 @@ DPI может отстать от потока, если ClientHello его у
В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно
ролей клиента и сервера. ролей клиента и сервера.
!!! Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством
Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством
и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него. и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него.
Для реализации атаки в linux обязательно требуется отключить стандартное правило firewall, Для реализации атаки на проходящий трафик требуются nftables и схема [POSTNAT](#nftables-для-nfqws).
дропающее инвалидные пакеты в цепочке OUTPUT. Например : `-A OUTPUT -m state --state INVALID -j DROP`
В openwrt можно отключить drop INVALID в OUTPUT и FORWARD через опцию в /etc/config/firewall:
```
config zone
option name 'wan'
.........
option masq_allow_invalid '1'
```
К сожалению, отключить только в OUTPUT таким образом нельзя. Но можно сделать иначе. Вписать в `/etc/firewall.user`:
```
iptables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT
ip6tables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT
```
Лучше делать так, потому что отсутствие дропа INVALID в FORWARD может привести к нежелательным утечкам пакетов из LAN.
Если не принять эти меры, отсылка SYN,ACK сегмента вызовет ошибку и операция будет прервана.
Остальные режимы тоже не сработают. Если поймете, что вам synack не нужен, обязательно верните правило дропа INVALID.
### РЕЖИМ SYNDATA ### РЕЖИМ SYNDATA
@@ -480,7 +463,7 @@ conntrack - простенький, он не писался с учетом в
`--wssize` позволяет изменить с клиента размер tcp window для сервера, чтобы он послал следующие ответы разбитыми на части. `--wssize` позволяет изменить с клиента размер tcp window для сервера, чтобы он послал следующие ответы разбитыми на части.
Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения, Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения,
ответ на который должен быть разбит (например, TLS ClientHello). Именно поэтому и необходим conntrack, чтобы ответ на которое должен быть разбит (например, TLS ClientHello). Именно поэтому и необходим conntrack, чтобы
знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически. знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически.
В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет. В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет.
В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello. В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello.
@@ -521,7 +504,7 @@ nfqws поддерживает реассемблинг некоторых ви
На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую
криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124. криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124.
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
попасть любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом попасть в любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
принимает решение о блокировке. принимает решение о блокировке.
В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты
задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию
@@ -845,6 +828,7 @@ tpws - это transparent proxy.
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) --hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. --hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль) --new ; начало новой стратегии (новый профиль)
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии --filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую. --filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.

View File

@@ -0,0 +1,22 @@
# This script fixes keenetic issue with nfqws generated udp packets
# Keenetic uses proprietary ndmmark and does not masquerade without this mark
# If not masqueraded packets go to WAN with LAN IP and get dropped by ISP
# It's advised to set IFACE_WAN in config
zapret_custom_firewall()
{
# $1 - 1 - add, 0 - stop
local wan wanif rule
[ "$DISABLE_IPV4" = "1" ] || {
# use IFACE_WAN if defined. if not - search for interfaces with default route.
wanif=${IFACE_WAN:-$(sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs)}
for wan in $wanif; do
rule="-o $wan -p udp -m mark --mark $DESYNC_MARK/$DESYNC_MARK"
ipt_print_op $1 "$rule" "keenetic udp fix"
ipt_add_del $1 POSTROUTING -t nat $rule -j MASQUERADE
done
}
}

View File

@@ -167,9 +167,15 @@ run_daemon()
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile # use $PIDDIR/$DAEMONBASE$1.pid as pidfile
local DAEMONBASE="$(basename "$2")" local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid local PID= PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Starting daemon $1: $2 $3" echo "Starting daemon $1: $2 $3"
if [ -f "$PIDFILE" ] && pgrep -F "$PIDFILE" "$DAEMONBASE" >/dev/null; then
[ -f "$PIDFILE" ] && {
read PID <"$PIDFILE"
[ -d "/proc/$PID" ] || PID=
}
if [ -n "$PID" ]; then
echo already running echo already running
else else
"$2" $3 >/dev/null & "$2" $3 >/dev/null &
@@ -188,18 +194,14 @@ stop_daemon()
# $2 - daemon # $2 - daemon
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile # use $PIDDIR/$DAEMONBASE$1.pid as pidfile
local DAEMONBASE="$(basename "$2")" local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid local PID PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Stopping daemon $1: $2" echo "Stopping daemon $1: $2"
if exists start-stop-daemon ; then if [ -f "$PIDFILE" ]; then
start-stop-daemon -K -p "$PIDFILE" -x "$2" read PID <"$PIDFILE"
kill $PID
rm -f "$PIDFILE"
else else
if [ -f "$PIDFILE" ]; then echo no pidfile : $PIDFILE
read PID <"$PIDFILE"
kill $PID
rm -f "$PIDFILE"
else
echo no pidfile : $PIDFILE
fi
fi fi
} }
do_daemon() do_daemon()

View File

@@ -1,5 +1,5 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_WIN = -static CFLAGS_WIN = -static
LIBS = LIBS =

View File

@@ -1,5 +1,5 @@
CC ?= cc CC ?= cc
CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member -flto=auto
LIBS = -lz LIBS = -lz
SRC_FILES = *.c crypto/*.c SRC_FILES = *.c crypto/*.c

View File

@@ -1,7 +1,6 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_MAC = -mmacosx-version-min=10.8
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LIBS_BSD = -lz LIBS_BSD = -lz

View File

@@ -1082,7 +1082,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
ttl_fake = (ctrack_replay && ctrack_replay->autottl) ? ctrack_replay->autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); ttl_fake = (ctrack_replay && ctrack_replay->autottl) ? ctrack_replay->autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase) && HttpFindHost(&phost,dis->data_payload,dis->len_payload)) if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost,dis->data_payload,dis->len_payload))
{ {
if (dp->hostcase) if (dp->hostcase)
{ {
@@ -1098,23 +1098,40 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
verdict=VERDICT_MODIFY; verdict=VERDICT_MODIFY;
} }
uint8_t *pua; uint8_t *pua;
if (dp->hostnospace && if (dp->hostnospace)
(pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
(pua = (uint8_t*)memmem(pua + 1, dis->len_payload - (pua - dis->data_payload) - 1, "\r\n", 2)))
{ {
DLOG("removing space after Host: and adding it to User-Agent:\n"); if ((pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
if (pua > phost) (pua = (uint8_t*)memmem(pua + 1, dis->len_payload - (pua - dis->data_payload) - 1, "\r\n", 2)))
{ {
memmove(phost + 5, phost + 6, pua - phost - 6); DLOG("removing space after Host: and adding it to User-Agent:\n");
pua[-1]=' '; if (pua > phost)
{
memmove(phost + 5, phost + 6, pua - phost - 6);
pua[-1]=' ';
}
else
{
memmove(pua + 1, pua, phost - pua + 5);
*pua = ' ';
}
verdict=VERDICT_MODIFY;
} }
else else
{ DLOG("cannot do hostnospace because valid User-Agent: not found\n");
memmove(pua + 1, pua, phost - pua + 5);
*pua = ' ';
}
verdict=VERDICT_MODIFY;
} }
else if (dp->methodeol)
{
if (phost[5]==' ' || phost[5]=='\t')
{
DLOG("removing space after Host: and adding '\\n' before method\n");
memmove(dis->data_payload+1,dis->data_payload,phost-dis->data_payload+5);
dis->data_payload[0]='\n';
verdict=VERDICT_MODIFY;
}
else
DLOG("cannot do methodeol because there's no space or tab after Host:\n");
}
} }
if (dp->desync_mode==DESYNC_NONE) if (dp->desync_mode==DESYNC_NONE)
@@ -1395,7 +1412,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (i==0) if (i==0)
{ {
if (seqovl_pos>=from) if (seqovl_pos>=from)
DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2); DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2);
else else
{ {
seqovl = seqovl_pos; seqovl = seqovl_pos;
@@ -1440,7 +1457,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (seqovl_pos>=split_pos) if (seqovl_pos>=split_pos)
{ {
DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos); DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos);
seqovl = 0; seqovl = 0;
} }
else else

View File

@@ -1020,6 +1020,7 @@ static void exithelp(void)
#endif #endif
"\nMULTI-STRATEGY:\n" "\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t\t; begin new strategy\n" " --new\t\t\t\t\t\t; begin new strategy\n"
" --skip\t\t\t\t\t\t; do not use this strategy\n"
" --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n" " --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
" --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n" " --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n" " --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
@@ -1042,6 +1043,7 @@ static void exithelp(void)
" --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n" " --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n" " --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
" --domcase\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n" " --domcase\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n"
" --methodeol\t\t\t\t\t; add '\\n' before method and remove space from Host:\n"
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t; try to desync dpi state. modes :\n" " --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t; try to desync dpi state. modes :\n"
"\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n" "\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
"\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n" "\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n"
@@ -1139,7 +1141,7 @@ int main(int argc, char **argv)
#endif #endif
int result, v; int result, v;
int option_index = 0; int option_index = 0;
bool daemon = false; bool daemon = false, bSkip = false;
char pidfile[256]; char pidfile[256];
#ifdef __CYGWIN__ #ifdef __CYGWIN__
char windivert_filter[8192], wf_pf_tcp_src[256], wf_pf_tcp_dst[256], wf_pf_udp_src[256], wf_pf_udp_dst[256], wf_save_file[256]; char windivert_filter[8192], wf_pf_tcp_src[256], wf_pf_tcp_dst[256], wf_pf_udp_src[256], wf_pf_udp_dst[256], wf_save_file[256];
@@ -1227,70 +1229,72 @@ int main(int argc, char **argv)
{"hostspell",required_argument,0,0}, // optidx=11 {"hostspell",required_argument,0,0}, // optidx=11
{"hostnospace",no_argument,0,0}, // optidx=12 {"hostnospace",no_argument,0,0}, // optidx=12
{"domcase",no_argument,0,0 }, // optidx=13 {"domcase",no_argument,0,0 }, // optidx=13
{"dpi-desync",required_argument,0,0}, // optidx=14 {"methodeol",no_argument,0,0 }, // optidx=14
{"dpi-desync",required_argument,0,0}, // optidx=15
#ifdef __linux__ #ifdef __linux__
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=15 {"dpi-desync-fwmark",required_argument,0,0}, // optidx=16
#elif defined(SO_USER_COOKIE) #elif defined(SO_USER_COOKIE)
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15 {"dpi-desync-sockarg",required_argument,0,0}, // optidx=16
#else #else
{"disabled_argument_4",no_argument,0,0}, // optidx=15 {"disabled_argument_4",no_argument,0,0}, // optidx=16
#endif #endif
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16 {"dpi-desync-ttl",required_argument,0,0}, // optidx=17
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=17 {"dpi-desync-ttl6",required_argument,0,0}, // optidx=18
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=18 {"dpi-desync-autottl",optional_argument,0,0}, // optidx=19
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=19 {"dpi-desync-autottl6",optional_argument,0,0}, // optidx=20
{"dpi-desync-fooling",required_argument,0,0}, // optidx=20 {"dpi-desync-fooling",required_argument,0,0}, // optidx=21
{"dpi-desync-repeats",required_argument,0,0}, // optidx=21 {"dpi-desync-repeats",required_argument,0,0}, // optidx=22
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=22 {"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=23
{"dpi-desync-split-pos",required_argument,0,0},// optidx=23 {"dpi-desync-split-pos",required_argument,0,0},// optidx=24
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=24 {"dpi-desync-split-http-req",required_argument,0,0 },// optidx=25
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=25 {"dpi-desync-split-tls",required_argument,0,0 },// optidx=26
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=26 {"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=27
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=27 {"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=28
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=28 {"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=29
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=29 {"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=30
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=30 {"dpi-desync-badseq-increment",required_argument,0,0},// optidx=31
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=31 {"dpi-desync-badack-increment",required_argument,0,0},// optidx=32
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=32 {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=33
{"dpi-desync-fake-http",required_argument,0,0},// optidx=33 {"dpi-desync-fake-http",required_argument,0,0},// optidx=34
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=34 {"dpi-desync-fake-tls",required_argument,0,0},// optidx=35
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=35 {"dpi-desync-fake-unknown",required_argument,0,0},// optidx=36
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=36 {"dpi-desync-fake-syndata",required_argument,0,0},// optidx=37
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=37 {"dpi-desync-fake-quic",required_argument,0,0},// optidx=38
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=38 {"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=39
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=39 {"dpi-desync-fake-dht",required_argument,0,0},// optidx=40
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=40 {"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=41
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=41 {"dpi-desync-udplen-increment",required_argument,0,0},// optidx=42
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=42 {"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=43
{"dpi-desync-cutoff",required_argument,0,0},// optidx=43 {"dpi-desync-cutoff",required_argument,0,0},// optidx=44
{"dpi-desync-start",required_argument,0,0},// optidx=43 {"dpi-desync-start",required_argument,0,0},// optidx=45
{"hostlist",required_argument,0,0}, // optidx=44 {"hostlist",required_argument,0,0}, // optidx=46
{"hostlist-exclude",required_argument,0,0}, // optidx=45 {"hostlist-exclude",required_argument,0,0}, // optidx=47
{"hostlist-auto",required_argument,0,0}, // optidx=46 {"hostlist-auto",required_argument,0,0}, // optidx=48
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=48 {"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=49
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=49 {"hostlist-auto-fail-time",required_argument,0,0}, // optidx=50
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=50 {"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=51
{"hostlist-auto-debug",required_argument,0,0}, // optidx=51 {"hostlist-auto-debug",required_argument,0,0}, // optidx=52
{"new",no_argument,0,0}, // optidx=52 {"new",no_argument,0,0}, // optidx=53
{"filter-l3",required_argument,0,0}, // optidx=53 {"skip",no_argument,0,0}, // optidx=54
{"filter-tcp",required_argument,0,0}, // optidx=54 {"filter-l3",required_argument,0,0}, // optidx=55
{"filter-udp",required_argument,0,0}, // optidx=55 {"filter-tcp",required_argument,0,0}, // optidx=56
{"filter-l7",required_argument,0,0}, // optidx=56 {"filter-udp",required_argument,0,0}, // optidx=57
{"ipset",required_argument,0,0}, // optidx=57 {"filter-l7",required_argument,0,0}, // optidx=58
{"ipset-exclude",required_argument,0,0},// optidx=58 {"ipset",required_argument,0,0}, // optidx=59
{"ipset-exclude",required_argument,0,0},// optidx=60
#ifdef __linux__ #ifdef __linux__
{"bind-fix4",no_argument,0,0}, // optidx=59 {"bind-fix4",no_argument,0,0}, // optidx=61
{"bind-fix6",no_argument,0,0}, // optidx=60 {"bind-fix6",no_argument,0,0}, // optidx=62
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
{"wf-iface",required_argument,0,0}, // optidx=59 {"wf-iface",required_argument,0,0}, // optidx=61
{"wf-l3",required_argument,0,0}, // optidx=60 {"wf-l3",required_argument,0,0}, // optidx=62
{"wf-tcp",required_argument,0,0}, // optidx=61 {"wf-tcp",required_argument,0,0}, // optidx=63
{"wf-udp",required_argument,0,0}, // optidx=62 {"wf-udp",required_argument,0,0}, // optidx=64
{"wf-raw",required_argument,0,0}, // optidx=63 {"wf-raw",required_argument,0,0}, // optidx=65
{"wf-save",required_argument,0,0}, // optidx=64 {"wf-save",required_argument,0,0}, // optidx=66
{"ssid-filter",required_argument,0,0}, // optidx=65 {"ssid-filter",required_argument,0,0}, // optidx=67
{"nlm-filter",required_argument,0,0}, // optidx=66 {"nlm-filter",required_argument,0,0}, // optidx=68
{"nlm-list",optional_argument,0,0}, // optidx=67 {"nlm-list",optional_argument,0,0}, // optidx=69
#endif #endif
{NULL,0,NULL,0} {NULL,0,NULL,0}
}; };
@@ -1422,12 +1426,25 @@ int main(int argc, char **argv)
memcpy(dp->hostspell, optarg, 4); memcpy(dp->hostspell, optarg, 4);
break; break;
case 12: /* hostnospace */ case 12: /* hostnospace */
if (dp->methodeol)
{
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
exit_clean(1);
}
dp->hostnospace = true; dp->hostnospace = true;
break; break;
case 13: /* domcase */ case 13: /* domcase */
dp->domcase = true; dp->domcase = true;
break; break;
case 14: /* dpi-desync */ case 14: /* methodeol */
if (dp->hostnospace)
{
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
exit_clean(1);
}
dp->methodeol = true;
break;
case 15: /* dpi-desync */
{ {
char *mode=optarg,*mode2,*mode3; char *mode=optarg,*mode2,*mode3;
mode2 = mode ? strchr(mode,',') : NULL; mode2 = mode ? strchr(mode,',') : NULL;
@@ -1473,7 +1490,7 @@ int main(int argc, char **argv)
} }
break; break;
#ifndef __CYGWIN__ #ifndef __CYGWIN__
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */ case 16: /* dpi-desync-fwmark/dpi-desync-sockarg */
#if defined(__linux__) || defined(SO_USER_COOKIE) #if defined(__linux__) || defined(SO_USER_COOKIE)
params.desync_fwmark = 0; params.desync_fwmark = 0;
if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark); if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark);
@@ -1488,27 +1505,27 @@ int main(int argc, char **argv)
#endif #endif
break; break;
#endif #endif
case 16: /* dpi-desync-ttl */ case 17: /* dpi-desync-ttl */
dp->desync_ttl = (uint8_t)atoi(optarg); dp->desync_ttl = (uint8_t)atoi(optarg);
break; break;
case 17: /* dpi-desync-ttl6 */ case 18: /* dpi-desync-ttl6 */
dp->desync_ttl6 = (uint8_t)atoi(optarg); dp->desync_ttl6 = (uint8_t)atoi(optarg);
break; break;
case 18: /* dpi-desync-autottl */ case 19: /* dpi-desync-autottl */
if (!parse_autottl(optarg, &dp->desync_autottl)) if (!parse_autottl(optarg, &dp->desync_autottl))
{ {
DLOG_ERR("dpi-desync-autottl value error\n"); DLOG_ERR("dpi-desync-autottl value error\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 19: /* dpi-desync-autottl6 */ case 20: /* dpi-desync-autottl6 */
if (!parse_autottl(optarg, &dp->desync_autottl6)) if (!parse_autottl(optarg, &dp->desync_autottl6))
{ {
DLOG_ERR("dpi-desync-autottl6 value error\n"); DLOG_ERR("dpi-desync-autottl6 value error\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 20: /* dpi-desync-fooling */ case 21: /* dpi-desync-fooling */
{ {
char *e,*p = optarg; char *e,*p = optarg;
while (p) while (p)
@@ -1543,17 +1560,17 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 21: /* dpi-desync-repeats */ case 22: /* dpi-desync-repeats */
if (sscanf(optarg,"%u",&dp->desync_repeats)<1 || !dp->desync_repeats || dp->desync_repeats>20) 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"); DLOG_ERR("dpi-desync-repeats must be within 1..20\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 22: /* dpi-desync-skip-nosni */ case 23: /* dpi-desync-skip-nosni */
dp->desync_skip_nosni = !optarg || atoi(optarg); dp->desync_skip_nosni = !optarg || atoi(optarg);
break; break;
case 23: /* dpi-desync-split-pos */ case 24: /* dpi-desync-split-pos */
{ {
int ct; int ct;
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct)) if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
@@ -1564,7 +1581,7 @@ int main(int argc, char **argv)
dp->split_count += ct; dp->split_count += ct;
} }
break; break;
case 24: /* dpi-desync-split-http-req */ case 25: /* dpi-desync-split-http-req */
// obsolete arg // obsolete arg
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); 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) if (dp->split_count>=MAX_SPLITS)
@@ -1579,7 +1596,7 @@ int main(int argc, char **argv)
} }
dp->split_count++; dp->split_count++;
break; break;
case 25: /* dpi-desync-split-tls */ case 26: /* dpi-desync-split-tls */
// obsolete arg // obsolete arg
DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); 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) if (dp->split_count>=MAX_SPLITS)
@@ -1594,7 +1611,7 @@ int main(int argc, char **argv)
} }
dp->split_count++; dp->split_count++;
break; break;
case 26: /* dpi-desync-split-seqovl */ case 27: /* dpi-desync-split-seqovl */
if (!strcmp(optarg,"0")) if (!strcmp(optarg,"0"))
{ {
// allow zero = disable seqovl // allow zero = disable seqovl
@@ -1607,7 +1624,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 27: /* dpi-desync-split-seqovl-pattern */ case 28: /* dpi-desync-split-seqovl-pattern */
{ {
char buf[sizeof(dp->seqovl_pattern)]; char buf[sizeof(dp->seqovl_pattern)];
size_t sz=sizeof(buf); size_t sz=sizeof(buf);
@@ -1615,7 +1632,7 @@ int main(int argc, char **argv)
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz); fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
} }
break; break;
case 28: /* dpi-desync-ipfrag-pos-tcp */ case 29: /* 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) 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); DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
@@ -1627,7 +1644,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 29: /* dpi-desync-ipfrag-pos-udp */ case 30: /* 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) 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); DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
@@ -1639,63 +1656,63 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 30: /* dpi-desync-badseq-increments */ case 31: /* dpi-desync-badseq-increments */
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment)) if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
{ {
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n"); DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 31: /* dpi-desync-badack-increment */ case 32: /* dpi-desync-badack-increment */
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_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"); DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 32: /* dpi-desync-any-protocol */ case 33: /* dpi-desync-any-protocol */
dp->desync_any_proto = !optarg || atoi(optarg); dp->desync_any_proto = !optarg || atoi(optarg);
break; break;
case 33: /* dpi-desync-fake-http */ case 34: /* dpi-desync-fake-http */
dp->fake_http_size = sizeof(dp->fake_http); dp->fake_http_size = sizeof(dp->fake_http);
load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size); load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size);
break; break;
case 34: /* dpi-desync-fake-tls */ case 35: /* dpi-desync-fake-tls */
dp->fake_tls_size = sizeof(dp->fake_tls); dp->fake_tls_size = sizeof(dp->fake_tls);
load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size); load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size);
break; break;
case 35: /* dpi-desync-fake-unknown */ case 36: /* dpi-desync-fake-unknown */
dp->fake_unknown_size = sizeof(dp->fake_unknown); dp->fake_unknown_size = sizeof(dp->fake_unknown);
load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size); load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size);
break; break;
case 36: /* dpi-desync-fake-syndata */ case 37: /* dpi-desync-fake-syndata */
dp->fake_syndata_size = sizeof(dp->fake_syndata); dp->fake_syndata_size = sizeof(dp->fake_syndata);
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size); load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
break; break;
case 37: /* dpi-desync-fake-quic */ case 38: /* dpi-desync-fake-quic */
dp->fake_quic_size = sizeof(dp->fake_quic); dp->fake_quic_size = sizeof(dp->fake_quic);
load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size); load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size);
break; break;
case 38: /* dpi-desync-fake-wireguard */ case 39: /* dpi-desync-fake-wireguard */
dp->fake_wg_size = sizeof(dp->fake_wg); dp->fake_wg_size = sizeof(dp->fake_wg);
load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size); load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size);
break; break;
case 39: /* dpi-desync-fake-dht */ case 40: /* dpi-desync-fake-dht */
dp->fake_dht_size = sizeof(dp->fake_dht); dp->fake_dht_size = sizeof(dp->fake_dht);
load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size); load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size);
break; break;
case 40: /* dpi-desync-fake-unknown-udp */ case 41: /* dpi-desync-fake-unknown-udp */
dp->fake_unknown_udp_size = sizeof(dp->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); load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size);
break; break;
case 41: /* dpi-desync-udplen-increment */ case 42: /* dpi-desync-udplen-increment */
if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000) 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"); DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 42: /* dpi-desync-udplen-pattern */ case 43: /* dpi-desync-udplen-pattern */
{ {
char buf[sizeof(dp->udplen_pattern)]; char buf[sizeof(dp->udplen_pattern)];
size_t sz=sizeof(buf); size_t sz=sizeof(buf);
@@ -1703,35 +1720,35 @@ int main(int argc, char **argv)
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz); fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
} }
break; break;
case 43: /* desync-cutoff */ case 44: /* desync-cutoff */
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode)) if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
{ {
DLOG_ERR("invalid desync-cutoff value\n"); DLOG_ERR("invalid desync-cutoff value\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 44: /* desync-start */ case 45: /* desync-start */
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode)) if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
{ {
DLOG_ERR("invalid desync-start value\n"); DLOG_ERR("invalid desync-start value\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 45: /* hostlist */ case 46: /* hostlist */
if (!RegisterHostlist(dp, false, optarg)) if (!RegisterHostlist(dp, false, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 46: /* hostlist-exclude */ case 47: /* hostlist-exclude */
if (!RegisterHostlist(dp, true, optarg)) if (!RegisterHostlist(dp, true, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 47: /* hostlist-auto */ case 48: /* hostlist-auto */
if (dp->hostlist_auto) if (dp->hostlist_auto)
{ {
DLOG_ERR("only one auto hostlist per profile is supported\n"); DLOG_ERR("only one auto hostlist per profile is supported\n");
@@ -1758,7 +1775,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 48: /* hostlist-auto-fail-threshold */ case 49: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20) if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
{ {
@@ -1766,7 +1783,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 49: /* hostlist-auto-fail-time */ case 50: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1) if (dp->hostlist_auto_fail_time<1)
{ {
@@ -1774,7 +1791,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 50: /* hostlist-auto-retrans-threshold */ case 51: /* hostlist-auto-retrans-threshold */
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10) if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
{ {
@@ -1782,7 +1799,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 51: /* hostlist-auto-debug */ case 52: /* hostlist-auto-debug */
{ {
FILE *F = fopen(optarg,"a+t"); FILE *F = fopen(optarg,"a+t");
if (!F) if (!F)
@@ -1796,23 +1813,37 @@ int main(int argc, char **argv)
} }
break; break;
case 52: /* new */ case 53: /* new */
if (!(dpl = dp_list_add(&params.desync_profiles))) if (bSkip)
{ {
DLOG_ERR("desync_profile_add: out of memory\n"); dp_clear(dp);
exit_clean(1); dp_init(dp);
dp->n = desync_profile_count;
bSkip = false;
}
else
{
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
dp = &dpl->dp;
dp->n = ++desync_profile_count;
} }
dp = &dpl->dp;
dp->n = ++desync_profile_count;
break; break;
case 53: /* filter-l3 */ case 54: /* skip */
bSkip = true;
break;
case 55: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 54: /* filter-tcp */ case 56: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
@@ -1822,7 +1853,7 @@ int main(int argc, char **argv)
if (!port_filters_deny_if_empty(&dp->pf_udp)) if (!port_filters_deny_if_empty(&dp->pf_udp))
exit_clean(1); exit_clean(1);
break; break;
case 55: /* filter-udp */ case 57: /* filter-udp */
if (!parse_pf_list(optarg,&dp->pf_udp)) if (!parse_pf_list(optarg,&dp->pf_udp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
@@ -1832,21 +1863,21 @@ int main(int argc, char **argv)
if (!port_filters_deny_if_empty(&dp->pf_tcp)) if (!port_filters_deny_if_empty(&dp->pf_tcp))
exit_clean(1); exit_clean(1);
break; break;
case 56: /* filter-l7 */ case 58: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 57: /* ipset */ case 59: /* ipset */
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 58: /* ipset-exclude */ case 60: /* ipset-exclude */
if (!RegisterIpset(dp, true, optarg)) if (!RegisterIpset(dp, true, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1857,28 +1888,28 @@ int main(int argc, char **argv)
#ifdef __linux__ #ifdef __linux__
case 59: /* bind-fix4 */ case 61: /* bind-fix4 */
params.bind_fix4 = true; params.bind_fix4 = true;
break; break;
case 60: /* bind-fix6 */ case 62: /* bind-fix6 */
params.bind_fix6 = true; params.bind_fix6 = true;
break; break;
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
case 59: /* wf-iface */ case 61: /* wf-iface */
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx)) if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
{ {
DLOG_ERR("bad value for --wf-iface\n"); DLOG_ERR("bad value for --wf-iface\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 60: /* wf-l3 */ case 62: /* wf-l3 */
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6)) if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
{ {
DLOG_ERR("bad value for --wf-l3\n"); DLOG_ERR("bad value for --wf-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 61: /* wf-tcp */ case 63: /* wf-tcp */
hash_wf_tcp=hash_jen(optarg,strlen(optarg)); hash_wf_tcp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) || 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))) !wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst)))
@@ -1887,7 +1918,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 62: /* wf-udp */ case 64: /* wf-udp */
hash_wf_udp=hash_jen(optarg,strlen(optarg)); hash_wf_udp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) || 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))) !wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst)))
@@ -1896,7 +1927,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 63: /* wf-raw */ case 65: /* wf-raw */
hash_wf_raw=hash_jen(optarg,strlen(optarg)); hash_wf_raw=hash_jen(optarg,strlen(optarg));
if (optarg[0]=='@') if (optarg[0]=='@')
{ {
@@ -1910,11 +1941,11 @@ int main(int argc, char **argv)
windivert_filter[sizeof(windivert_filter) - 1] = '\0'; windivert_filter[sizeof(windivert_filter) - 1] = '\0';
} }
break; break;
case 64: /* wf-save */ case 66: /* wf-save */
strncpy(wf_save_file, optarg, sizeof(wf_save_file)); strncpy(wf_save_file, optarg, sizeof(wf_save_file));
wf_save_file[sizeof(wf_save_file) - 1] = '\0'; wf_save_file[sizeof(wf_save_file) - 1] = '\0';
break; break;
case 65: /* ssid-filter */ case 67: /* ssid-filter */
hash_ssid_filter=hash_jen(optarg,strlen(optarg)); hash_ssid_filter=hash_jen(optarg,strlen(optarg));
{ {
char *e,*p = optarg; char *e,*p = optarg;
@@ -1932,7 +1963,7 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 66: /* nlm-filter */ case 68: /* nlm-filter */
hash_nlm_filter=hash_jen(optarg,strlen(optarg)); hash_nlm_filter=hash_jen(optarg,strlen(optarg));
{ {
char *e,*p = optarg; char *e,*p = optarg;
@@ -1950,7 +1981,7 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 67: /* nlm-list */ case 69: /* nlm-list */
if (!nlm_list(optarg && !strcmp(optarg,"all"))) if (!nlm_list(optarg && !strcmp(optarg,"all")))
{ {
DLOG_ERR("could not get list of NLM networks\n"); DLOG_ERR("could not get list of NLM networks\n");
@@ -1961,6 +1992,12 @@ int main(int argc, char **argv)
#endif #endif
} }
} }
if (bSkip)
{
LIST_REMOVE(dpl,next);
dp_entry_destroy(dpl);
desync_profile_count--;
}
// do not need args from file anymore // do not need args from file anymore
#if !defined( __OpenBSD__) && !defined(__ANDROID__) #if !defined( __OpenBSD__) && !defined(__ANDROID__)

View File

@@ -170,45 +170,49 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
if (bcut) DLOG(" ..."); if (bcut) DLOG(" ...");
} }
void dp_init(struct desync_profile *dp)
{
LIST_INIT(&dp->hl_collection);
LIST_INIT(&dp->hl_collection_exclude);
LIST_INIT(&dp->ips_collection);
LIST_INIT(&dp->ips_collection_exclude);
LIST_INIT(&dp->pf_tcp);
LIST_INIT(&dp->pf_udp);
memcpy(dp->hostspell, "host", 4); // default hostspell
dp->desync_skip_nosni = true;
dp->desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
dp->desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
dp->desync_repeats = 1;
dp->fake_tls_size = sizeof(fake_tls_clienthello_default);
memcpy(dp->fake_tls,fake_tls_clienthello_default,dp->fake_tls_size);
randomize_default_tls_payload(dp->fake_tls);
dp->fake_http_size = strlen(fake_http_request_default);
memcpy(dp->fake_http,fake_http_request_default,dp->fake_http_size);
dp->fake_quic_size = 620; // must be 601+ for TSPU hack
dp->fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
dp->fake_wg_size = 64;
dp->fake_dht_size = 64;
dp->fake_unknown_size = 256;
dp->fake_syndata_size = 16;
dp->fake_unknown_udp_size = 64;
dp->wscale=-1; // default - dont change scale factor (client)
dp->desync_ttl6 = 0xFF; // unused
dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
dp->desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by default
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
dp->filter_ipv4 = dp->filter_ipv6 = true;
}
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head) struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{ {
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list)); struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL; if (!entry) return NULL;
LIST_INIT(&entry->dp.hl_collection); dp_init(&entry->dp);
LIST_INIT(&entry->dp.hl_collection_exclude);
LIST_INIT(&entry->dp.ips_collection);
LIST_INIT(&entry->dp.ips_collection_exclude);
LIST_INIT(&entry->dp.pf_tcp);
LIST_INIT(&entry->dp.pf_udp);
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
entry->dp.desync_skip_nosni = true;
entry->dp.desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
entry->dp.desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
entry->dp.desync_repeats = 1;
entry->dp.fake_tls_size = sizeof(fake_tls_clienthello_default);
memcpy(entry->dp.fake_tls,fake_tls_clienthello_default,entry->dp.fake_tls_size);
randomize_default_tls_payload(entry->dp.fake_tls);
entry->dp.fake_http_size = strlen(fake_http_request_default);
memcpy(entry->dp.fake_http,fake_http_request_default,entry->dp.fake_http_size);
entry->dp.fake_quic_size = 620; // must be 601+ for TSPU hack
entry->dp.fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
entry->dp.fake_wg_size = 64;
entry->dp.fake_dht_size = 64;
entry->dp.fake_unknown_size = 256;
entry->dp.fake_syndata_size = 16;
entry->dp.fake_unknown_udp_size = 64;
entry->dp.wscale=-1; // default - dont change scale factor (client)
entry->dp.desync_ttl6 = 0xFF; // unused
entry->dp.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
entry->dp.desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
entry->dp.wssize_cutoff_mode = entry->dp.desync_start_mode = entry->dp.desync_cutoff_mode = 'n'; // packet number by default
entry->dp.udplen_increment = UDPLEN_INCREMENT_DEFAULT;
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
entry->dp.hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
// add to the tail // add to the tail
struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles); struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles);
@@ -222,15 +226,24 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
return entry; return entry;
} }
static void dp_entry_destroy(struct desync_profile_list *entry) static void dp_clear_dynamic(struct desync_profile *dp)
{ {
hostlist_collection_destroy(&entry->dp.hl_collection); hostlist_collection_destroy(&dp->hl_collection);
hostlist_collection_destroy(&entry->dp.hl_collection_exclude); hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&entry->dp.ips_collection); ipset_collection_destroy(&dp->ips_collection);
ipset_collection_destroy(&entry->dp.ips_collection_exclude); ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&entry->dp.pf_tcp); port_filters_destroy(&dp->pf_tcp);
port_filters_destroy(&entry->dp.pf_udp); port_filters_destroy(&dp->pf_udp);
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters); HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
}
void dp_clear(struct desync_profile *dp)
{
dp_clear_dynamic(dp);
memset(dp,0,sizeof(*dp));
}
void dp_entry_destroy(struct desync_profile_list *entry)
{
dp_clear_dynamic(&entry->dp);
free(entry); free(entry);
} }
void dp_list_destroy(struct desync_profile_list_head *head) void dp_list_destroy(struct desync_profile_list_head *head)

View File

@@ -51,7 +51,7 @@ struct desync_profile
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int wssize_cutoff; unsigned int wssize_cutoff;
bool hostcase, hostnospace, domcase; bool hostcase, hostnospace, domcase, methodeol;
char hostspell[4]; char hostspell[4];
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
bool desync_retrans,desync_skip_nosni,desync_any_proto; bool desync_retrans,desync_skip_nosni,desync_any_proto;
@@ -99,8 +99,11 @@ struct desync_profile_list {
}; };
LIST_HEAD(desync_profile_list_head, desync_profile_list); LIST_HEAD(desync_profile_list_head, desync_profile_list);
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head); struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head); void dp_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(struct desync_profile_list_head *head); bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp);
struct params_s struct params_s
{ {

View File

@@ -1,5 +1,5 @@
CC ?= cc CC ?= cc
CFLAGS += -std=gnu99 -s -Os CFLAGS += -std=gnu99 -s -Os -flto=auto
LIBS = -lz -lpthread LIBS = -lz -lpthread
SRC_FILES = *.c SRC_FILES = *.c

View File

@@ -1,5 +1,5 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
LIBS = -lz -lpthread LIBS = -lz -lpthread
LIBS_ANDROID = -lz LIBS_ANDROID = -lz

View File

@@ -155,22 +155,26 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
if (bcut) VPRINT(" ..."); if (bcut) VPRINT(" ...");
} }
void dp_init(struct desync_profile *dp)
{
LIST_INIT(&dp->hl_collection);
LIST_INIT(&dp->hl_collection_exclude);
LIST_INIT(&dp->ips_collection);
LIST_INIT(&dp->ips_collection_exclude);
LIST_INIT(&dp->pf_tcp);
dp->filter_ipv4 = dp->filter_ipv6 = true;
memcpy(dp->hostspell, "host", 4); // default hostspell
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
}
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head) struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{ {
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list)); struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL; if (!entry) return NULL;
LIST_INIT(&entry->dp.hl_collection); dp_init(&entry->dp);
LIST_INIT(&entry->dp.hl_collection_exclude);
LIST_INIT(&entry->dp.ips_collection);
LIST_INIT(&entry->dp.ips_collection_exclude);
LIST_INIT(&entry->dp.pf_tcp);
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
// add to the tail // add to the tail
struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles); struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles);
@@ -184,14 +188,23 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
return entry; return entry;
} }
static void dp_entry_destroy(struct desync_profile_list *entry) static void dp_clear_dynamic(struct desync_profile *dp)
{ {
hostlist_collection_destroy(&entry->dp.hl_collection); hostlist_collection_destroy(&dp->hl_collection);
hostlist_collection_destroy(&entry->dp.hl_collection_exclude); hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&entry->dp.ips_collection); ipset_collection_destroy(&dp->ips_collection);
ipset_collection_destroy(&entry->dp.ips_collection_exclude); ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&entry->dp.pf_tcp); port_filters_destroy(&dp->pf_tcp);
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters); HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
}
void dp_clear(struct desync_profile *dp)
{
dp_clear_dynamic(dp);
memset(dp,0,sizeof(*dp));
}
void dp_entry_destroy(struct desync_profile_list *entry)
{
dp_clear_dynamic(&entry->dp);
free(entry); free(entry);
} }
void dp_list_destroy(struct desync_profile_list_head *head) void dp_list_destroy(struct desync_profile_list_head *head)

View File

@@ -83,7 +83,10 @@ struct desync_profile_list {
}; };
LIST_HEAD(desync_profile_list_head, desync_profile_list); LIST_HEAD(desync_profile_list_head, desync_profile_list);
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head); struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head); void dp_list_destroy(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp);
struct params_s struct params_s
{ {

View File

@@ -140,11 +140,6 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
if (bHaveHost) if (bHaveHost)
VPRINT("request hostname: %s\n", Host); VPRINT("request hostname: %s\n", Host);
if (ctrack->b_not_act)
{
VPRINT("Not acting on this request\n");
return;
}
bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN; bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN;
if (bDiscoveredL7) if (bDiscoveredL7)
@@ -169,17 +164,25 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
struct desync_profile *dp_prev = ctrack->dp; struct desync_profile *dp_prev = ctrack->dp;
apply_desync_profile(ctrack, dest); apply_desync_profile(ctrack, dest);
if (ctrack->dp!=dp_prev) if (ctrack->dp!=dp_prev)
{
VPRINT("desync profile changed by revealed l7 protocol or hostname !\n"); VPRINT("desync profile changed by revealed l7 protocol or hostname !\n");
ctrack->b_host_checked = ctrack->b_ah_check = false;
}
} }
if (bDiscoveredHostname && ctrack->dp->hostlist_auto) if (l7proto!=UNKNOWN && ctrack->dp->hostlist_auto)
{ {
bool bHostExcluded; if (bHaveHost && !ctrack->b_host_checked)
if (!HostlistCheck(ctrack->dp, Host, &bHostExcluded, false)) {
bool bHostExcluded;
ctrack->b_host_matches = HostlistCheck(ctrack->dp, Host, &bHostExcluded, false);
ctrack->b_host_checked = true;
if (!ctrack->b_host_matches)
ctrack->b_ah_check = !bHostExcluded;
}
if (!ctrack->b_host_matches)
{ {
ctrack->b_ah_check = !bHostExcluded;
VPRINT("Not acting on this request\n"); VPRINT("Not acting on this request\n");
ctrack->b_not_act = true;
return; return;
} }
} }

View File

@@ -14,8 +14,7 @@ typedef struct
// common state // common state
t_l7proto l7proto; t_l7proto l7proto;
bool bTamperInCutoff; bool bTamperInCutoff;
bool b_ah_check; bool b_host_checked,b_host_matches,b_ah_check;
bool b_not_act;
char *hostname; char *hostname;
struct desync_profile *dp; // desync profile cache struct desync_profile *dp; // desync profile cache
} t_ctrack; } t_ctrack;

View File

@@ -177,6 +177,7 @@ static void exithelp(void)
" --debug-level=0|1|2\t\t\t; specify debug level\n" " --debug-level=0|1|2\t\t\t; specify debug level\n"
"\nMULTI-STRATEGY:\n" "\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t; begin new strategy\n" " --new\t\t\t\t\t; begin new strategy\n"
" --skip\t\t\t\t\t; do not use this strategy\n"
" --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n" " --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
" --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n" " --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
" --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n" " --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n"
@@ -524,6 +525,7 @@ void parse_params(int argc, char *argv[])
{ {
int option_index = 0; int option_index = 0;
int v, i; int v, i;
bool bSkip=false;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.maxconn = DEFAULT_MAX_CONN; params.maxconn = DEFAULT_MAX_CONN;
@@ -630,24 +632,25 @@ void parse_params(int argc, char *argv[])
{ "connect-bind-addr",required_argument,0,0 },// optidx=55 { "connect-bind-addr",required_argument,0,0 },// optidx=55
{ "new",no_argument,0,0 }, // optidx=56 { "new",no_argument,0,0 }, // optidx=56
{ "filter-l3",required_argument,0,0 }, // optidx=57 { "skip",no_argument,0,0 }, // optidx=57
{ "filter-tcp",required_argument,0,0 }, // optidx=58 { "filter-l3",required_argument,0,0 }, // optidx=58
{ "filter-l7",required_argument,0,0 }, // optidx=59 { "filter-tcp",required_argument,0,0 }, // optidx=59
{ "ipset",required_argument,0,0 }, // optidx=60 { "filter-l7",required_argument,0,0 }, // optidx=60
{ "ipset-exclude",required_argument,0,0 }, // optidx=61 { "ipset",required_argument,0,0 }, // optidx=61
{ "ipset-exclude",required_argument,0,0 }, // optidx=62
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
{ "enable-pf",no_argument,0,0 },// optidx=62 { "enable-pf",no_argument,0,0 },// optidx=62
#elif defined(__APPLE__) #elif defined(__APPLE__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62 { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=63
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=64
#elif defined(__linux__) #elif defined(__linux__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62 { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=63
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=64
{ "mss",required_argument,0,0 }, // optidx=64 { "mss",required_argument,0,0 }, // optidx=65
{ "fix-seg",optional_argument,0,0 }, // optidx=65 { "fix-seg",optional_argument,0,0 }, // optidx=66
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
{ "nosplice",no_argument,0,0 }, // optidx=66 { "nosplice",no_argument,0,0 }, // optidx=67
#endif #endif
#endif #endif
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility { "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
@@ -1160,36 +1163,49 @@ void parse_params(int argc, char *argv[])
case 56: /* new */ case 56: /* new */
if (!(dpl = dp_list_add(&params.desync_profiles))) if (bSkip)
{ {
DLOG_ERR("desync_profile_add: out of memory\n"); dp_clear(dp);
exit_clean(1); dp_init(dp);
dp->n = desync_profile_count;
bSkip = false;
}
else
{
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
dp = &dpl->dp;
dp->n = ++desync_profile_count;
} }
dp = &dpl->dp;
dp->n = ++desync_profile_count;
break; break;
case 57: /* filter-l3 */ case 57: /* skip */
bSkip = true;
break;
case 58: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 58: /* filter-tcp */ case 59: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 59: /* filter-l7 */ case 60: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 60: /* ipset */ case 61: /* ipset */
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1197,7 +1213,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case 61: /* ipset-exclude */ case 62: /* ipset-exclude */
if (!RegisterIpset(dp, true, optarg)) if (!RegisterIpset(dp, true, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1207,11 +1223,11 @@ void parse_params(int argc, char *argv[])
break; break;
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
case 62: /* enable-pf */ case 63: /* enable-pf */
params.pf_enable = true; params.pf_enable = true;
break; break;
#elif defined(__linux__) || defined(__APPLE__) #elif defined(__linux__) || defined(__APPLE__)
case 62: /* local-tcp-user-timeout */ case 63: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg); params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400) if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
{ {
@@ -1219,7 +1235,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 63: /* remote-tcp-user-timeout */ case 64: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg); params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400) if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
{ {
@@ -1230,7 +1246,7 @@ void parse_params(int argc, char *argv[])
#endif #endif
#if defined(__linux__) #if defined(__linux__)
case 64: /* mss */ case 65: /* mss */
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing // this option does not work in any BSD and MacOS. OS may accept but it changes nothing
dp->mss = atoi(optarg); dp->mss = atoi(optarg);
if (dp->mss<88 || dp->mss>32767) if (dp->mss<88 || dp->mss>32767)
@@ -1239,7 +1255,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 65: /* fix-seg */ case 66: /* fix-seg */
if (!params.fix_seg_avail) if (!params.fix_seg_avail)
{ {
DLOG_ERR("--fix-seg is supported since kernel 4.6\n"); DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
@@ -1259,13 +1275,20 @@ void parse_params(int argc, char *argv[])
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT; params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break; break;
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
case 66: /* nosplice */ case 67: /* nosplice */
params.nosplice = true; params.nosplice = true;
break; break;
#endif #endif
#endif #endif
} }
} }
if (bSkip)
{
LIST_REMOVE(dpl,next);
dp_entry_destroy(dpl);
desync_profile_count--;
}
if (!params.bind_wait_only && !params.port) if (!params.bind_wait_only && !params.port)
{ {
DLOG_ERR("Need port number\n"); DLOG_ERR("Need port number\n");

View File

@@ -479,6 +479,33 @@ static int connect_remote(const struct sockaddr *remote_addr, int mss)
return remote_fd; return remote_fd;
} }
static bool connect_remote_conn(tproxy_conn_t *conn)
{
int mss=0;
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
if (conn->track.dp && conn->track.dp->mss)
{
mss = conn->track.dp->mss;
if (conn->track.dp->hostlist_auto)
{
if (conn->track.hostname)
{
bool bHostExcluded;
conn->track.b_host_matches = HostlistCheck(conn->track.dp, conn->track.hostname, &bHostExcluded, false);
conn->track.b_host_checked = true;
if (!conn->track.b_host_matches)
{
conn->track.b_ah_check = !bHostExcluded;
mss = 0;
}
}
}
}
return (conn->partner->fd = connect_remote((struct sockaddr *)&conn->dest, mss))>=0;
}
//Free resources occupied by this connection //Free resources occupied by this connection
static void free_conn(tproxy_conn_t *conn) static void free_conn(tproxy_conn_t *conn)
@@ -636,9 +663,7 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
conn->partner->client = conn->client; conn->partner->client = conn->client;
conn->partner->dest = conn->dest; conn->partner->dest = conn->dest;
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest); if (!connect_remote_conn(conn))
if ((conn->partner->fd = connect_remote((struct sockaddr *)&orig_dst, conn->track.dp ? conn->track.dp->mss : 0)) < 0)
{ {
DLOG_ERR("Failed to connect\n"); DLOG_ERR("Failed to connect\n");
free_conn(conn->partner); free_conn(conn->partner);
@@ -811,14 +836,6 @@ static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn
return false; return false;
} }
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
if ((remote_fd = connect_remote((struct sockaddr *)&conn->dest, conn->track.dp ? conn->track.dp->mss : 0)) < 0)
{
DLOG_ERR("socks failed to connect (1) errno=%d\n", errno);
socks_send_rep_errno(conn->socks_ver, conn->fd, errno);
return false;
}
if (!(conn->partner = new_conn(remote_fd, true))) if (!(conn->partner = new_conn(remote_fd, true)))
{ {
close(remote_fd); close(remote_fd);
@@ -830,6 +847,15 @@ static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn
conn->partner->efd = conn->efd; conn->partner->efd = conn->efd;
conn->partner->client = conn->client; conn->partner->client = conn->client;
conn->partner->dest = conn->dest; conn->partner->dest = conn->dest;
if (!connect_remote_conn(conn))
{
free_conn(conn->partner); conn->partner = NULL;
DLOG_ERR("socks failed to connect (1) errno=%d\n", errno);
socks_send_rep_errno(conn->socks_ver, conn->fd, errno);
return false;
}
if (!epoll_set(conn->partner, EPOLLOUT)) if (!epoll_set(conn->partner, EPOLLOUT))
{ {
DLOG_ERR("socks epoll_set error %d\n", errno); DLOG_ERR("socks epoll_set error %d\n", errno);
@@ -1652,7 +1678,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
} }
else else
{ {
DBGPRINT("conn fd=%d has no unsent\n", conn->fd); DBGPRINT("conn fd=%d has no unsent\n", conn->fd);
conn->bFlowIn = false; conn->bFlowIn = false;
epoll_update_flow(conn); epoll_update_flow(conn);