mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-30 05:50:53 +03:00
Compare commits
5 Commits
f48617e1a3
...
45913cc2cd
Author | SHA1 | Date | |
---|---|---|---|
|
45913cc2cd | ||
|
92c6ccf38f | ||
|
1a9a676c94 | ||
|
3098727f4c | ||
|
147af10b61 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
binaries/win64/WinDivert.dll
Normal file
BIN
binaries/win64/WinDivert.dll
Normal file
Binary file not shown.
BIN
binaries/win64/WinDivert64.sys
Normal file
BIN
binaries/win64/WinDivert64.sys
Normal file
Binary file not shown.
BIN
binaries/win64/ip2net.exe
Normal file
BIN
binaries/win64/ip2net.exe
Normal file
Binary file not shown.
BIN
binaries/win64/mdig.exe
Normal file
BIN
binaries/win64/mdig.exe
Normal file
Binary file not shown.
9
binaries/win64/readme.txt
Normal file
9
binaries/win64/readme.txt
Normal file
@ -0,0 +1,9 @@
|
||||
Standalone version in zapret-winws folder !!
|
||||
From this folder winws can be started only from cygwin shell.
|
||||
|
||||
Cygwin refuses to start winws if a copy of cygwin1.dll is present !
|
||||
|
||||
How to get win7 and winws compatible version of cygwin :
|
||||
|
||||
curl -O https://www.cygwin.com/setup-x86_64.exe
|
||||
setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215
|
BIN
binaries/win64/winws.exe
Normal file
BIN
binaries/win64/winws.exe
Normal file
Binary file not shown.
BIN
binaries/win64/zapret-winws/WinDivert.dll
Normal file
BIN
binaries/win64/zapret-winws/WinDivert.dll
Normal file
Binary file not shown.
BIN
binaries/win64/zapret-winws/WinDivert64.sys
Normal file
BIN
binaries/win64/zapret-winws/WinDivert64.sys
Normal file
Binary file not shown.
BIN
binaries/win64/zapret-winws/cygwin1.dll
Normal file
BIN
binaries/win64/zapret-winws/cygwin1.dll
Normal file
Binary file not shown.
2
binaries/win64/zapret-winws/task_create.cmd
Normal file
2
binaries/win64/zapret-winws/task_create.cmd
Normal file
@ -0,0 +1,2 @@
|
||||
set WINWS1=--wf-l3=ipv4,ipv6 --wf-tcp=80,443 --dpi-desync=fake,split --dpi-desync-ttl=7 --dpi-desync-fooling=md5sig
|
||||
schtasks /Create /F /TN winws1 /NP /RU "" /SC onstart /TR "\"%~dp0winws.exe\" %WINWS1%"
|
2
binaries/win64/zapret-winws/task_remove.cmd
Normal file
2
binaries/win64/zapret-winws/task_remove.cmd
Normal file
@ -0,0 +1,2 @@
|
||||
schtasks /End /TN winws1
|
||||
schtasks /Delete /TN winws1 /F
|
1
binaries/win64/zapret-winws/task_start.cmd
Normal file
1
binaries/win64/zapret-winws/task_start.cmd
Normal file
@ -0,0 +1 @@
|
||||
schtasks /Run /TN winws1
|
1
binaries/win64/zapret-winws/task_stop.cmd
Normal file
1
binaries/win64/zapret-winws/task_stop.cmd
Normal file
@ -0,0 +1 @@
|
||||
schtasks /End /TN winws1
|
BIN
binaries/win64/zapret-winws/winws.exe
Normal file
BIN
binaries/win64/zapret-winws/winws.exe
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -17,6 +17,7 @@ TPWS_UID=${TPWS_UID:-1}
|
||||
TPWS_GID=${TPWS_GID:-3003}
|
||||
NFQWS=${NFQWS:-${ZAPRET_BASE}/nfq/nfqws}
|
||||
DVTWS=${DVTWS:-${ZAPRET_BASE}/nfq/dvtws}
|
||||
WINWS=${WINWS:-${ZAPRET_BASE}/nfq/winws}
|
||||
TPWS=${TPWS:-${ZAPRET_BASE}/tpws/tpws}
|
||||
MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
|
||||
DESYNC_MARK=0x10000000
|
||||
@ -191,7 +192,9 @@ mdig_resolve()
|
||||
{
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname
|
||||
echo "$2" | "$MDIG" --family=$1 | head -n 1
|
||||
|
||||
# windows version of mdig outputs 0D0A line ending. remove 0D.
|
||||
echo "$2" | "$MDIG" --family=$1 | head -n 1 | tr -d '\r'
|
||||
}
|
||||
|
||||
check_system()
|
||||
@ -229,6 +232,12 @@ check_system()
|
||||
PKTWSD=dvtws
|
||||
FWTYPE=mpf
|
||||
;;
|
||||
CYGWIN*)
|
||||
UNAME=CYGWIN
|
||||
PKTWS="$WINWS"
|
||||
PKTWSD=winws
|
||||
FWTYPE=windivert
|
||||
;;
|
||||
*)
|
||||
echo $UNAME not supported
|
||||
exitp 5
|
||||
@ -256,7 +265,7 @@ check_prerequisites()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
[ "$UNAME" = Darwin -o -x "$PKTWS" ] && [ -x "$TPWS" ] && [ -x "$MDIG" ] || {
|
||||
[ "$UNAME" = Darwin -o -x "$PKTWS" ] && [ "$UNAME" = CYGWIN -o -x "$TPWS" ] && [ -x "$MDIG" ] || {
|
||||
local target
|
||||
case $UNAME in
|
||||
Darwin)
|
||||
@ -323,6 +332,9 @@ check_prerequisites()
|
||||
[ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1
|
||||
pf_save
|
||||
;;
|
||||
CYGWIN)
|
||||
SKIP_TPWS=1
|
||||
;;
|
||||
esac
|
||||
|
||||
for prog in $progs; do
|
||||
@ -446,6 +458,7 @@ curl_with_dig()
|
||||
return 6
|
||||
}
|
||||
shift ; shift ; shift
|
||||
|
||||
ALL_PROXY="$ALL_PROXY" curl $connect_to "$@"
|
||||
}
|
||||
|
||||
@ -558,6 +571,10 @@ pktws_ipt_prepare()
|
||||
opf)
|
||||
opf_prepare_dvtws $1 $2
|
||||
;;
|
||||
windivert)
|
||||
WF="--wf-l3=ipv${IPV} --wf-${1}=$2"
|
||||
;;
|
||||
|
||||
esac
|
||||
}
|
||||
pktws_ipt_unprepare()
|
||||
@ -578,6 +595,9 @@ pktws_ipt_unprepare()
|
||||
opf)
|
||||
pf_restore
|
||||
;;
|
||||
windivert)
|
||||
unset WF
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
@ -636,6 +656,9 @@ pktws_start()
|
||||
FreeBSD|OpenBSD)
|
||||
"$DVTWS" --port=$IPFW_DIVERT_PORT "$@" >/dev/null &
|
||||
;;
|
||||
CYGWIN)
|
||||
"$WINWS" $WF "$@" >/dev/null &
|
||||
;;
|
||||
esac
|
||||
PID=$!
|
||||
# give some time to initialize
|
||||
@ -711,7 +734,7 @@ pktws_curl_test()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3,$4,$5, ... - nfqws/dvtws params
|
||||
echo - checking $PKTWSD $3 $4 $5 $6 $7 $8 $9
|
||||
echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9
|
||||
ws_curl_test pktws_start "$@"
|
||||
}
|
||||
xxxws_curl_test_update()
|
||||
@ -726,7 +749,7 @@ xxxws_curl_test_update()
|
||||
shift
|
||||
$xxxf $testf $dom "$@"
|
||||
code=$?
|
||||
[ $code = 0 ] && strategy="${strategy:-$@}"
|
||||
[ $code = 0 ] && strategy="${WF:+$WF }${strategy:-$@}"
|
||||
return $code
|
||||
}
|
||||
pktws_curl_test_update()
|
||||
@ -1329,6 +1352,10 @@ pingtest()
|
||||
OpenBSD)
|
||||
ping -c 1 -w 1 $1 >/dev/null
|
||||
;;
|
||||
CYGWIN)
|
||||
# cygwin does not have own PING by default. use windows PING.
|
||||
ping -n 1 -w 1000 $1 >/dev/null
|
||||
;;
|
||||
*)
|
||||
ping -c 1 -W 1 $1 >/dev/null
|
||||
;;
|
||||
@ -1356,7 +1383,7 @@ lookup4()
|
||||
# $2 - DNS
|
||||
case "$LOOKUP" in
|
||||
nslookup)
|
||||
nslookup $1 $2 | sed -n '/Name:/,$p' | grep ^Address | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||
nslookup $1 $2 2>/dev/null | sed -n '/Name:/,$p' | sed -nre 's/^.*(([0-9]{1,3}\.){3}[0-9]{1,3}).*$/\1/p'
|
||||
;;
|
||||
host)
|
||||
host -t A $1 $2 | grep "has address" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||
@ -1367,7 +1394,9 @@ check_dns_spoof()
|
||||
{
|
||||
# $1 - domain
|
||||
# $2 - public DNS
|
||||
echo $1 | "$MDIG" --family=4 >"$DNSCHECK_DIG1"
|
||||
|
||||
# windows version of mdig outputs 0D0A line ending. remove 0D.
|
||||
echo $1 | "$MDIG" --family=4 | tr -d '\r' >"$DNSCHECK_DIG1"
|
||||
lookup4 $1 $2 >"$DNSCHECK_DIG2"
|
||||
# check whether system resolver returns anything other than public DNS
|
||||
grep -qvFf "$DNSCHECK_DIG2" "$DNSCHECK_DIG1"
|
||||
@ -1475,7 +1504,7 @@ sigpipe()
|
||||
fsleep_setup
|
||||
fix_sbin_path
|
||||
check_system
|
||||
require_root
|
||||
[ "$UNAME" = CYGWIN ] || require_root
|
||||
check_prerequisites
|
||||
trap sigint_cleanup INT
|
||||
check_dns
|
||||
@ -1485,6 +1514,7 @@ trap - INT
|
||||
|
||||
PID=
|
||||
NREPORT=
|
||||
unset WF
|
||||
trap sigint INT
|
||||
trap sigpipe PIPE
|
||||
for dom in $DOMAINS; do
|
||||
|
@ -283,3 +283,7 @@ nfqws: --dpi-desync-start option
|
||||
nfqws: packet delay for kyber TLS and QUIC
|
||||
nfqws: --dpi-desync-retrans obsolete
|
||||
nfqws: --qnum is mandatory, no more default queue 0
|
||||
|
||||
v58
|
||||
|
||||
winws
|
||||
|
@ -91,7 +91,7 @@ zapret не может пробить блокировку по IP адресу
|
||||
Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов
|
||||
с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI,
|
||||
которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
|
||||
blockheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
|
||||
blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
|
||||
В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
|
||||
Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
|
||||
--dpi-desync-fooling, чтобы не сломать сайты на более коротких дистанциях.
|
||||
|
95
docs/quick_start_windows.txt
Normal file
95
docs/quick_start_windows.txt
Normal file
@ -0,0 +1,95 @@
|
||||
Специально для тех, кто хочет побыстрее начать, но не хочет слишком углубляться в простыню readme.txt.
|
||||
|
||||
Как обычно, компьютерная грамотность ложится полностью на вас.
|
||||
Вы должны уметь работать с консолью windows и иметь минимальные навыки обращения с командными файлами bat,cmd.
|
||||
Если грамотность отсутствует и возникает куча "как" на базовых вещах - проходите мимо или ищите помощь в другом месте.
|
||||
|
||||
Обход DPI является хакерской методикой. Под этим словом понимается метод, которому сопротивляется окружающая среда,
|
||||
которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах,
|
||||
требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем,
|
||||
и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации.
|
||||
Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать.
|
||||
Могут и сломаться отдельные незаблокированные ресурсы.
|
||||
Поэтому очень желательно иметь знания в области сетей, чтобы иметь возможность проанализировать техническую ситуацию.
|
||||
Не будет лишним иметь обходные каналы проксирования трафика на случай, если обход DPI не помогает.
|
||||
|
||||
Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы.
|
||||
|
||||
1) Если у вас windows 7, обновляйте систему. Годами не обновляемая 7-ка может не запускать драйвер windivert.
|
||||
Поддержка 32-битных x86 windows возможна, но в готовом виде отсутствует.
|
||||
Поддержка arm64 систем возможна при определенных условиях, но в готовом виде отсутствует.
|
||||
Читайте docs/windows.txt
|
||||
|
||||
Имейте в виду, что антивирусы могут плохо реагировать на windivert. Если это имеет место , используйте исключения.
|
||||
|
||||
2) Скачайте zip архив проекта с github, распакуйте его куда-нибудь.
|
||||
|
||||
3) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret.
|
||||
|
||||
4) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит
|
||||
|
||||
5) Выполните установку cygwin. Желательно устанавливать windows 7 совместимую версию, под которой и был собран проект.
|
||||
Скачайте https://www.cygwin.com/setup-x86_64.exe
|
||||
Выполните его с параметрами : setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215
|
||||
Установите cygwin, выбрав в списке пакетов curl.
|
||||
|
||||
cygwin нужен только для поиска стратегии обхода блокировки. После этого он не нужен.
|
||||
|
||||
6) Запустите cygwin.bat из директории установки cygwin от имени администратора.
|
||||
В нем нужно пройти в директорию с zapret. Буква диска windows X: отображается как /cygdrive/x.
|
||||
Используейте команды как в *nix
|
||||
|
||||
7) Однократно выполните ./install_bin.sh
|
||||
|
||||
8) Запустите blockcheck.sh. blockcheck.sh в начале проверяет DNS. Если выводятся сообщения о подмене адресов, то
|
||||
первым делом нужно решить эту проблему, иначе ничего не будет работать.
|
||||
Решение проблемы DNS выходит за рамки проекта. Обычно она решается либо заменой DNS серверов
|
||||
от провайдера на публичные (1.1.1.1, 8.8.8.8), либо в случае перехвата провайдером обращений
|
||||
к сторонним серверам - через специальные средства шифрования DNS запросов, такие как dnscrypt, DoT, DoH.
|
||||
В современных броузерах чаще всего DoH включен по умолчанию, но curl будет использовать обычный DNS.
|
||||
|
||||
9) blockcheck позволяет выявить рабочую стратегию обхода блокировок.
|
||||
Запомните найденные стратегии.
|
||||
|
||||
Следует понимать, что blockcheck проверяет доступность только конкретного домена, который вы вводите в начале.
|
||||
Вероятно, все остальные домены блокированы подобным образом, но не факт.
|
||||
В большинстве случаев можно обьединить несколько стратегий в одну универсальную, но для этого необходимо понимать
|
||||
"что там за буковки". Если вы в сетях слабо разбираетесь, это не для вас. В противном случае читайте readme.txt.
|
||||
zapret не может пробить блокировку по IP адресу
|
||||
Для проверки нескольких доменов вводите их через пробел.
|
||||
|
||||
Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов
|
||||
с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI,
|
||||
которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
|
||||
blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
|
||||
В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
|
||||
Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
|
||||
--dpi-desync-fooling, чтобы не сломать сайты на более коротких дистанциях.
|
||||
md5sig наиболее совместим, но работатет только на linux серверах.
|
||||
badseq может работать только на https и не работать на http.
|
||||
Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL
|
||||
с каждым из этих ограничителей.
|
||||
|
||||
При использовании autottl следует протестировать как можно больше разных доменов. Эта техника
|
||||
может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах
|
||||
она стабильна, на третьих полный хаос, и проще отказаться.
|
||||
|
||||
10) Протестируйте найденные стратегии на winws. winws следует брать из binaries/win64/zapret-winws.
|
||||
|
||||
11) Обеспечьте удобную загрузку обхода блокировок.
|
||||
В binaries/win64/zapret-winws есть командные файлы task_*, предназначенные для управления задачами планировщика.
|
||||
Там следует поменять содержимое переменной WINWS1 на свою стратегию.
|
||||
Если вы не можете обьединить несколько стратегий для разных протоколов в одну, дублируйте код в каждом из cmd
|
||||
для поддержки нескольких задач : winws1,winws2,winws3.
|
||||
После создания задач запустите их. Проверьте, что обход встает после перезагрузки windows.
|
||||
|
||||
12) Если ломаются отдельные незаблокированные ресурсы, используйте хост-листы.
|
||||
Где они будут находиться - решайте сами. Пути прописываются не в формате windows, а формате cygwin.
|
||||
Например, /cygdrive/c/Users/vasya/zapret.
|
||||
Если в путях присутствуют национальные символы, кодировку нужно использовать OEM. Для русского языка это 866.
|
||||
Пути с пробелами нужно брать в кавычки.
|
||||
Параметры управления хост-листами точно такие же, как в *nix.
|
||||
|
||||
Это минимальная инструкция, чтобы соориентироваться с чего начать. Однако, это - не панацея.
|
||||
В некоторых случаях вы не обойдетесь без знаний и основного "толмуда".
|
||||
Подробности и полное техническое описание расписаны в readme.txt
|
@ -9,6 +9,8 @@ blocked by Roskomnadzor), but most others are common.
|
||||
|
||||
Mainly OpenWRT targeted but also supports traditional Linux, FreeBSD, OpenBSD, partially MacOS.
|
||||
|
||||
Most features are also supported in Windows.
|
||||
|
||||
## How it works
|
||||
|
||||
In the simplest case you are dealing with passive DPI. Passive DPI can read passthrough traffic,
|
||||
@ -1158,29 +1160,7 @@ see docs/bsd.eng.md
|
||||
|
||||
### Windows (WSL)
|
||||
|
||||
Using WSL (Windows subsystem for Linux) it's possible to run tpws in socks mode under rather new builds of
|
||||
windows 10 and windows server.
|
||||
Its not required to install any linux distributions as suggested in most articles.
|
||||
tpws is static binary. It doesn't need a distribution.
|
||||
|
||||
Install WSL : `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all`
|
||||
|
||||
Copy binaries/x86_64/tpws_wsl.tgz to the target system.
|
||||
Run : `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz`
|
||||
|
||||
Run tpws : `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <fooling_options>`
|
||||
|
||||
Configure socks as 127.0.0.1:1080 in a browser or another program.
|
||||
|
||||
Cleanup : `wsl --unregister tpws`
|
||||
|
||||
Tested in windows 10 build 19041 (20.04).
|
||||
|
||||
`--oob` , `--mss` and `--disorder` do not work.
|
||||
RST detection in autohostlist scheme may not work.
|
||||
WSL may glitch with pipes. `--nosplice` may be required.
|
||||
|
||||
NOTICE. There is native windows solution GoodByeDPI. It works on packet level like nfqws.
|
||||
see docs/windows.eng.md
|
||||
|
||||
### Other devices
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
zapret v.57
|
||||
zapret v.58
|
||||
|
||||
English
|
||||
-------
|
||||
@ -16,10 +16,12 @@ For english version refer to docs/readme.eng.txt
|
||||
Поддерживаются традиционные Linux системы, FreeBSD, OpenBSD, частично MacOS.
|
||||
В некоторых случаях возможна самостоятельная прикрутка решения к различным прошивкам.
|
||||
|
||||
Большая часть функционала работает на windows.
|
||||
|
||||
Как побыстрее начать
|
||||
--------------------
|
||||
|
||||
Читайте docs/quick_start.txt
|
||||
Читайте docs/quick_start.txt для linux и openwrt, docs/quick_start_windows.txt для windows.
|
||||
|
||||
|
||||
Как это работает
|
||||
@ -1559,29 +1561,10 @@ FreeBSD, OpenBSD, MacOS
|
||||
Описано в docs/bsd.txt
|
||||
|
||||
|
||||
Windows (WSL)
|
||||
-------------
|
||||
Windows
|
||||
-------
|
||||
|
||||
tpws в режиме socks можно запускать и под более-менее современными билдами windows 10 и windows server
|
||||
с установленным WSL. Совсем не обязательно устанавливать дистрибутив убунту, как вам напишут почти в каждой
|
||||
статье про WSL, которую вы найдете в сети. tpws - статический бинарик, ему дистрибутив не нужен.
|
||||
|
||||
Установить WSL : dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all
|
||||
Скопировать на целевую систему binaries/x86_64/tpws_wsl.tgz.
|
||||
Выполнить : wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz
|
||||
Запустить : wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <параметры_дурения>
|
||||
Прописать socks 127.0.0.1:1080 в броузер или другую программу.
|
||||
|
||||
Удаление : wsl --unregister tpws
|
||||
|
||||
Проверено на windows 10 build 19041 (20.04).
|
||||
|
||||
Не работают функции --oob и --mss из-за ограничений реализации WSL.
|
||||
--disorder не работает из-за особенностей tcp/ip стека windows.
|
||||
Может не срабатывать детект RST в autohostlist.
|
||||
WSL может глючить с pipes, ломая тем самым splice и приводя к зацикливанию процесса. Может потребоваться --nosplice.
|
||||
|
||||
ЗАМЕЧАНИЕ. Под Windows существует нативное решение GoodByeDPI, выполняющее дурение на пакетном уровне (по типу nfqws).
|
||||
Описано в docs/windows.txt
|
||||
|
||||
|
||||
Другие прошивки
|
||||
|
95
docs/windows.eng.md
Normal file
95
docs/windows.eng.md
Normal file
@ -0,0 +1,95 @@
|
||||
### tpws
|
||||
|
||||
Using `WSL` (Windows subsystem for Linux) it's possible to run `tpws` in socks mode under rather new builds of
|
||||
windows 10 and windows server.
|
||||
Its not required to install any linux distributions as suggested in most articles.
|
||||
tpws is static binary. It doesn't need a distribution.
|
||||
|
||||
Install `WSL` : `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all`
|
||||
|
||||
Copy `binaries/x86_64/tpws_wsl.tgz` to the target system.
|
||||
Run : `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz`
|
||||
|
||||
Run tpws : `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <fooling_options>`
|
||||
|
||||
Configure socks as `127.0.0.1:1080` in a browser or another program.
|
||||
|
||||
Cleanup : `wsl --unregister tpws`
|
||||
|
||||
Tested in windows 10 build 19041 (20.04).
|
||||
|
||||
`--oob` , `--mss` and `--disorder` do not work.
|
||||
RST detection in autohostlist scheme may not work.
|
||||
WSL may glitch with splice. `--nosplice` may be required.
|
||||
|
||||
|
||||
### winws
|
||||
|
||||
`winws` is `nfqws` version for windows. It's based on `windivert`. Most functions are working.
|
||||
Large ip filters (ipsets) are not possible. Forwarded traffic and connection sharing are not supported.
|
||||
Administrator rights are required.
|
||||
|
||||
Working with packet filter consists of two parts
|
||||
|
||||
1. In-kernel packet selection and passing selected packets to a packet filter in user mode.
|
||||
In *nix it's done by `iptables`, `nftables`, `pf`, `ipfw`.
|
||||
2. User mode packet filter processes packets and does DPI bypass magic.
|
||||
|
||||
Windows does not have part 1. No `iptables` exist. That's why 3rd party packet redirector is used.
|
||||
It's called `windivert`. It works starting from `windows 7`. Kernel driver is signed but it may require to disable secure boot
|
||||
or update windows 7.
|
||||
|
||||
Task of `iptables` is done inside `winws` through `windivert` filters. `Windivert` has it's own [filter language](https://reqrypt.org/windivert-doc.html#filter_language).
|
||||
`winws` can automate filter construction using simple ip version and port filter. Raw filters are also supported.
|
||||
|
||||
```
|
||||
--wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
||||
--wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed.
|
||||
--wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed.
|
||||
--wf-raw=<filter>|@<filename> ; raw windivert filter string or filename
|
||||
--wf-save=<filename> ; save windivert filter string to a file and exit
|
||||
```
|
||||
|
||||
`--wf-l3`, `--wf-tcp`, `--wf-udp` can take multiple comma separated arguments.
|
||||
|
||||
Multiple `winws` processes are allowed. However, it's discouraged to intersect their filters.
|
||||
|
||||
Paths are passed in `cygwin` format. Windows drives are mapped to `/cygdrive/x`. For example : `/cygdrive/c/Users/vasya/zapret`.
|
||||
|
||||
`Cygwin` shell does not run binaries if their directory has it's own copy of `cygwin1.dll`.
|
||||
That's why exists separate standalone version in `binaries/win64/zapret-tpws`.
|
||||
`Cygwin` is required for `blockcheck.sh` support but `winws` itself can be run standalone without cygwin.
|
||||
|
||||
How to get `windows 7` and `winws` compatible `cygwin` :
|
||||
```
|
||||
curl -O https://www.cygwin.com/setup-x86_64.exe
|
||||
setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215
|
||||
```
|
||||
You must choose to install `curl`. To compile from sources install `gcc-core`,`make`,`zlib-devel`.
|
||||
|
||||
`winws` requires `cygwin1.dll`, `windivert.dll`, `windivert64.sys`. You can take them from `binaries/win64/zapret-winws`.
|
||||
|
||||
It's possible to build x86 32-bit version but this version is not shipped. You have to build it yourself.
|
||||
32-bit `windivert` can be downloaded from it's developer github. Required version is 2.2.2.
|
||||
There's no `arm64` signed `windivert` driver. You can compile it yourself but it will run only with disabled driver signature checks.
|
||||
|
||||
|
||||
### blockcheck
|
||||
|
||||
`blockcheck.sh` is written in posix shell and uses some standard posix utilites.
|
||||
Windows does not have them. To execute `blockcheck.sh` use `cygwin` command prompt run as administrator.
|
||||
It's not possible to use `WSL`. It's not the same as `cygwin`.
|
||||
First run once `install_bin.sh` then `blockcheck.sh`.
|
||||
|
||||
`Cygwin` is required only for `blockcheck.sh`. Standalone `winws` can be run without it.
|
||||
|
||||
|
||||
### auto start
|
||||
|
||||
To start `winws` with windows use windows task scheduler. There are `task_*.cmd` batch files in `binaries/win64/zapret-winws`.
|
||||
They create, remove, start and stop scheduled task `winws1`. They must be run as administrator.
|
||||
|
||||
Edit `task_create.cmd` and write your `winws` parameters to `%WINWS1%` variable. If you need multiple `winws` instances
|
||||
clone the code in all cmd files to support multiple tasks `winws1,winws2,winws3,...`.
|
||||
|
||||
Tasks can also be controlled from GUI `taskschd.msc`.
|
117
docs/windows.txt
Normal file
117
docs/windows.txt
Normal file
@ -0,0 +1,117 @@
|
||||
tpws
|
||||
----
|
||||
|
||||
Запуск tpws возможен только в Linux варианте под WSL.
|
||||
Нативного варианта под Windows нет, поскольку он использует epoll, которого под windows не существует.
|
||||
|
||||
tpws в режиме socks можно запускать под более-менее современными билдами windows 10 и windows server
|
||||
с установленным WSL. Совсем не обязательно устанавливать дистрибутив убунту, как вам напишут почти в каждой
|
||||
статье про WSL, которую вы найдете в сети. tpws - статический бинарик, ему дистрибутив не нужен.
|
||||
|
||||
Установить WSL : dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all
|
||||
Скопировать на целевую систему binaries/x86_64/tpws_wsl.tgz.
|
||||
Выполнить : wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz
|
||||
Запустить : wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <параметры_дурения>
|
||||
Прописать socks 127.0.0.1:1080 в броузер или другую программу.
|
||||
|
||||
Удаление : wsl --unregister tpws
|
||||
|
||||
Проверено на windows 10 build 19041 (20.04).
|
||||
|
||||
Не работают функции --oob и --mss из-за ограничений реализации WSL.
|
||||
--disorder не работает из-за особенностей tcp/ip стека windows.
|
||||
Может не срабатывать детект RST в autohostlist.
|
||||
WSL может глючить со splice, приводя к зацикливанию процесса. Может потребоваться --nosplice.
|
||||
|
||||
|
||||
winws
|
||||
-----
|
||||
|
||||
Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert.
|
||||
Все функции работоспособны, однако функционал ipset отсутствует. Фильтры по большому количеству IP адресов невозможны.
|
||||
Работа с проходящим трафиком, например в случае "расшаривания" соединения, не проверялась и не гарантируется.
|
||||
Для работы с windivert требуются права администратора.
|
||||
Специфические для unix параметры, такие как --uid, --user и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws.
|
||||
|
||||
Работа с пакетным фильтром основана на двух действиях.
|
||||
Первое - выделение перенаправляемого трафика в режиме ядра и передача его пакетному фильтру в user mode.
|
||||
Второе - собственно обработка перенаправленных пакетов в пакетном фильтре.
|
||||
|
||||
В windows отсутствуют встроенные средства для перенаправления трафика, такие как iptables, nftables, pf или ipfw.
|
||||
Поэтому используется сторонний драйвер ядра windivert. Он работает, начиная с windows 7. На системах с включенным
|
||||
secure boot могут быть проблемы из-за подписи драйвера. В этом случае отключите secureboot или включите режим testsigning.
|
||||
На windows 7 требуются обновления. На старых необновленных системах может быть ошибка проверки подписи драйвера.
|
||||
Требования к патчам точно такие же, как и у GoodbyDPI.
|
||||
|
||||
Задача iptables в winws решается внутренними средствами через фильтры windivert.
|
||||
У windivert существует собственный язык фильтров, похожий на язык фильтров wireshark.
|
||||
Документация по фильтрам windivert : https://reqrypt.org/windivert-doc.html#filter_language
|
||||
Чтобы не писать сложные фильтры вручную, предусмотрены различные упрощенные варианты автоматического построения фильтров.
|
||||
|
||||
--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6.
|
||||
--wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание
|
||||
--wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание
|
||||
--wf-raw=<filter>|@<filename> ; задать напрямую фильтр windivert из параметра или из файла. имени файла предшествует символ @.
|
||||
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную
|
||||
|
||||
Параметры --wf-l3, --wf-tcp, --wf-udp могут брать несколько значений через запятую.
|
||||
|
||||
Конструктор фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций
|
||||
autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307.
|
||||
Всегда добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
|
||||
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона,
|
||||
сохраненного через --wf-save. Нужно править файл и подсовывать его в параметре --wf-raw. Максимальный размер фильтра - 8 Kb.
|
||||
|
||||
Можно запускать несколько процессов winws с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.
|
||||
|
||||
В параметрах, берущих пути к файлам, они прописываются не в формате windows, а формате cygwin.
|
||||
Например, /cygdrive/c/Users/vasya/zapret.
|
||||
Если в путях присутствуют национальные символы, то при вызове winws из cmd или bat кодировку нужно использовать OEM.
|
||||
Для русского языка это 866. Пути с пробелами нужно брать в кавычки.
|
||||
|
||||
Существует неочевидный момент, каcаемый запуска winws из cygwin шелла. Если в директории, где находится nfqws, находится
|
||||
копия cygwin1.dll, winws не запустится. Поэтому в binaries/win64 существует директория zapret-winws, содержащая полный
|
||||
комплект для запуска без cygwin. Его вы и берете для повседневного использования.
|
||||
Если нужен запуск под cygwin, то следует запускать из binaries/win64. Это нужно для работы blockcheck.
|
||||
Из cygwin шелла можно посылать winws сигналы через kill точно так же, как в *nix.
|
||||
|
||||
Как получить совместимый с windows 7 и winws cygwin :
|
||||
curl -O https://www.cygwin.com/setup-x86_64.exe
|
||||
setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215
|
||||
Следует выбрать установку curl.
|
||||
|
||||
Для сборки из исходников требуется gcc-core,make,zlib-devel.
|
||||
winws требует cygwin1.dll, windivert.dll, windivert64.sys. Их можно взять из binaries/win64/zapret-winws.
|
||||
Версию для 32-битных x86 windows собрать можно, но такие системы уже уходят в прошлое, поэтому если надо - собирайте сами.
|
||||
32-битный windivert можно взять с сайта разработчика. Требуется версия 2.2.2.
|
||||
Для arm64 систем нет подписанного драйвера windivert. Можно самому собрать windivert, но работать он будет только
|
||||
с отключенной подписью драйверов.
|
||||
|
||||
|
||||
blockcheck
|
||||
----------
|
||||
|
||||
blockcheck.sh написан на posix shell и требует некоторых стандартных утилит posix. В windows, естественно, этого нет.
|
||||
Потому просто так запустить blockcheck.sh невозможно.
|
||||
Для этого требуется скачать и установить cygwin так , как описано в предыдущем разделе.
|
||||
Следует запустить от имени администратора cygwin shell через cygwin.bat.
|
||||
В нем нужно пройти в директорию с zapret. Буква диска windows X: отображается как /cygdrive/x.
|
||||
Далее все как в *nix : 1 раз ./install_bin.sh , затем ./blockcheck.sh.
|
||||
WSL использовать нельзя, это не то же самое.
|
||||
|
||||
cygwin для обычной работы winws не нужен. Разве что вы хотите посылать winws SIGHUP для перечитки листов без перезапуска.
|
||||
|
||||
|
||||
автозапуск winws
|
||||
----------------
|
||||
|
||||
Для запуска winws вместе с windows воспользуйтесь планировщиком задач windows.
|
||||
Удобнее всего создавать задачи и управлять ими через консольную программу schtasks.
|
||||
В директории binaries/win64/winws подготовлены файлы task_*.cmd .
|
||||
В них реализовано создание, удаление, старт и стоп одной копии процесса winws с параметрами из переменной %WINWS1%.
|
||||
Исправьте параметры на нужную вам стратегию. Если для разных фильтров применяется разная стратегия, размножьте код
|
||||
для задач winws1,winws2,winws3,...
|
||||
|
||||
Все батники требуется запускать от имени администратора.
|
||||
|
||||
Управлять задачами можно так же из графической программы управления планировщиком taskschd.msc
|
@ -18,9 +18,9 @@ check_dir()
|
||||
# ash and dash try to execute invalid executables as a script. they interpret binary garbage with possible negative consequences
|
||||
# bash and zsh do not do this
|
||||
if exists bash; then
|
||||
out=$(echo 0.0.0.0 | bash -c "$exe" 2>/dev/null)
|
||||
out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null)
|
||||
elif exists zsh; then
|
||||
out=$(echo 0.0.0.0 | zsh -c "$exe" 2>/dev/null)
|
||||
out=$(echo 0.0.0.0 | zsh -c "\"$exe\"" 2>/dev/null)
|
||||
else
|
||||
# find does not use its own shell exec
|
||||
# it uses execvp(). in musl libc it does not call shell, in glibc it DOES call /bin/sh
|
||||
@ -49,15 +49,27 @@ ccp()
|
||||
}
|
||||
|
||||
UNAME=$(uname)
|
||||
if [ "$UNAME" = "Linux" ]; then
|
||||
ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb ppc"
|
||||
elif [ "$UNAME" = "Darwin" ]; then
|
||||
ARCHLIST="my mac64"
|
||||
elif [ "$UNAME" = "FreeBSD" ]; then
|
||||
ARCHLIST="my freebsd-x64"
|
||||
else
|
||||
ARCHLIST="my"
|
||||
fi
|
||||
unset PKTWS
|
||||
case $UNAME in
|
||||
Linux)
|
||||
ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb ppc"
|
||||
PKTWS=nfqws
|
||||
;;
|
||||
Darwin)
|
||||
ARCHLIST="my mac64"
|
||||
;;
|
||||
FreeBSD)
|
||||
ARCHLIST="my freebsd-x64"
|
||||
PKTWS=dvtws
|
||||
;;
|
||||
CYGWIN*)
|
||||
UNAME=CYGWIN
|
||||
ARCHLIST="win64"
|
||||
PKTWS=winws
|
||||
;;
|
||||
*)
|
||||
ARCHLIST="my"
|
||||
esac
|
||||
|
||||
if [ "$1" = "getarch" ]; then
|
||||
for arch in $ARCHLIST
|
||||
@ -77,12 +89,8 @@ else
|
||||
echo installing binaries ...
|
||||
ccp $arch/ip2net ip2net
|
||||
ccp $arch/mdig mdig
|
||||
if [ "$UNAME" = "Linux" ]; then
|
||||
ccp $arch/nfqws nfq
|
||||
else
|
||||
ccp $arch/dvtws nfq
|
||||
fi
|
||||
ccp $arch/tpws tpws
|
||||
[ -n "$PKTWS" ] && ccp $arch/$PKTWS nfq
|
||||
[ "$UNAME" = CYGWIN ] || ccp $arch/tpws tpws
|
||||
exit 0
|
||||
else
|
||||
echo $arch is NOT OK
|
||||
|
@ -1,6 +1,7 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
||||
CFLAGS_WIN = -static
|
||||
LIBS =
|
||||
LIBS_WIN = -lws2_32
|
||||
SRC_FILES = ip2net.c qsort.c
|
||||
@ -21,7 +22,7 @@ mac: $(SRC_FILES)
|
||||
rm -f ip2netx ip2neta
|
||||
|
||||
win: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN)
|
||||
$(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN)
|
||||
|
||||
clean:
|
||||
rm -f ip2net *.o
|
||||
|
@ -1,6 +1,7 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
||||
CFLAGS_WIN = -static
|
||||
LIBS = -lpthread
|
||||
LIBS_WIN = -lws2_32
|
||||
SRC_FILES = *.c
|
||||
@ -21,7 +22,7 @@ mac: $(SRC_FILES)
|
||||
rm -f mdigx mdiga
|
||||
|
||||
win: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS) -o mdig -static $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN)
|
||||
$(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN)
|
||||
|
||||
clean:
|
||||
rm -f mdig *.o
|
||||
|
@ -2,9 +2,10 @@ CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
||||
CFLAGS_MAC = -mmacosx-version-min=10.8
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
|
||||
LIBS_BSD = -lz
|
||||
LIBS_CYGWIN = -lz
|
||||
LIBS_CYGWIN = -lz -Lwindivert -lwindivert
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
all: nfqws
|
||||
@ -23,7 +24,7 @@ mac: $(SRC_FILES)
|
||||
rm -f dvtwsx dvtwsa
|
||||
|
||||
cygwin:
|
||||
$(CC) -s $(CFLAGS) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN)
|
||||
$(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN)
|
||||
|
||||
clean:
|
||||
rm -f nfqws dvtws *.o
|
||||
rm -f nfqws dvtws winws.exe *.o
|
||||
|
177
nfq/darkmagic.c
177
nfq/darkmagic.c
@ -1,6 +1,5 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "darkmagic.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -8,10 +7,13 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/param.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "darkmagic.h"
|
||||
#include "helpers.h"
|
||||
#include "params.h"
|
||||
|
||||
|
||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||
{
|
||||
return htonl(ntohl(netorder_value)+cpuorder_increment);
|
||||
@ -642,6 +644,8 @@ const char *proto_name(uint8_t proto)
|
||||
return "udp";
|
||||
case IPPROTO_ICMP:
|
||||
return "icmp";
|
||||
case IPPROTO_ICMPV6:
|
||||
return "icmp6";
|
||||
case IPPROTO_IGMP:
|
||||
return "igmp";
|
||||
case IPPROTO_ESP:
|
||||
@ -950,8 +954,133 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
|
||||
}
|
||||
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
||||
static HANDLE w_filter = NULL, w_event = NULL;
|
||||
|
||||
static HANDLE windivert_init_filter(const char *filter, UINT64 flags)
|
||||
{
|
||||
LPTSTR errormessage = NULL;
|
||||
DWORD errorcode = 0;
|
||||
HANDLE h;
|
||||
|
||||
h = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, 0, flags);
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return h;
|
||||
}
|
||||
errorcode = GetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorcode, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPTSTR)&errormessage, 0, NULL);
|
||||
fprintf(stderr, "windivert: error opening filter: %s", errormessage);
|
||||
LocalFree(errormessage);
|
||||
if (errorcode == 577)
|
||||
fprintf(stderr,"windivert: try to disable secure boot and install OS patches\n");
|
||||
return NULL;
|
||||
}
|
||||
void rawsend_cleanup(void)
|
||||
{
|
||||
if (w_filter)
|
||||
{
|
||||
WinDivertClose(w_filter);
|
||||
w_filter=NULL;
|
||||
}
|
||||
if (w_event)
|
||||
{
|
||||
CloseHandle(w_event);
|
||||
w_event=NULL;
|
||||
}
|
||||
}
|
||||
bool windivert_init(const char *filter)
|
||||
{
|
||||
rawsend_cleanup();
|
||||
w_filter = windivert_init_filter(filter, 0);
|
||||
if (w_filter)
|
||||
{
|
||||
w_event = CreateEventW(NULL,FALSE,FALSE,NULL);
|
||||
if (!w_event)
|
||||
{
|
||||
rawsend_cleanup();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa)
|
||||
{
|
||||
UINT recv_len;
|
||||
DWORD err;
|
||||
OVERLAPPED ovl = { .hEvent = w_event };
|
||||
DWORD rd;
|
||||
char c;
|
||||
|
||||
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, NULL, &ovl))
|
||||
{
|
||||
*len = recv_len;
|
||||
return true;
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
err = GetLastError();
|
||||
switch(err)
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
// make signals working
|
||||
while(WaitForSingleObject(w_event,50)==WAIT_TIMEOUT) usleep(0);
|
||||
if (!GetOverlappedResult(hFilter,&ovl,&rd,TRUE))
|
||||
continue;
|
||||
*len = rd;
|
||||
return true;
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
errno = ENOBUFS;
|
||||
break;
|
||||
case ERROR_NO_DATA:
|
||||
errno = ESHUTDOWN;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa)
|
||||
{
|
||||
return windivert_recv_filter(w_filter,packet,len,wa);
|
||||
}
|
||||
|
||||
static bool windivert_send_filter(HANDLE hFilter, const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa)
|
||||
{
|
||||
return WinDivertSend(hFilter,packet,(UINT)len,NULL,wa);
|
||||
}
|
||||
bool windivert_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa)
|
||||
{
|
||||
return windivert_send_filter(w_filter,packet,len,wa);
|
||||
}
|
||||
|
||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len)
|
||||
{
|
||||
WINDIVERT_ADDRESS wa;
|
||||
|
||||
memset(&wa,0,sizeof(wa));
|
||||
// pseudo interface id IfIdx.SubIfIdx
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
wa.Outbound=1;
|
||||
wa.IPChecksum=1;
|
||||
wa.TCPChecksum=1;
|
||||
wa.UDPChecksum=1;
|
||||
wa.IPv6 = (dst->sa_family==AF_INET6);
|
||||
|
||||
return windivert_send(data,len,&wa);
|
||||
}
|
||||
|
||||
#else // *nix
|
||||
|
||||
static int rawsend_sock4=-1, rawsend_sock6=-1;
|
||||
static bool b_bind_fix4=false, b_bind_fix6=false;
|
||||
@ -1264,6 +1393,8 @@ nofix:
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // not CYGWIN
|
||||
|
||||
bool rawsend_rp(const struct rawpacket *rp)
|
||||
{
|
||||
return rawsend((struct sockaddr*)&rp->dst,rp->fwmark,rp->ifout,rp->packet,rp->len);
|
||||
@ -1311,23 +1442,35 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
|
||||
|
||||
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
|
||||
if (!(verdict & VERDICT_NOCSUM))
|
||||
{
|
||||
// always fix csum for windivert. original can be partial or bad
|
||||
#ifndef __CYGWIN__
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
#endif
|
||||
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
|
||||
}
|
||||
}
|
||||
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
|
||||
if (!(verdict & VERDICT_NOCSUM))
|
||||
{
|
||||
// always fix csum for windivert. original can be partial or bad
|
||||
#ifndef __CYGWIN__
|
||||
#ifdef __FreeBSD__
|
||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||
#else
|
||||
// if original packet was tampered earlier it needs checksum fixed
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
||||
#endif
|
||||
#endif
|
||||
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "checksum.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "checksum.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include "windivert/windivert.h"
|
||||
#endif
|
||||
|
||||
#include "packet_queue.h"
|
||||
|
||||
@ -142,17 +148,26 @@ uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
|
||||
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
|
||||
bool tcp_has_fastopen(const struct tcphdr *tcp);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
bool windivert_init(const char *filter);
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa);
|
||||
bool windivert_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa);
|
||||
#else
|
||||
// should pre-do it if dropping privileges. otherwise its not necessary
|
||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
||||
#endif
|
||||
|
||||
// auto creates internal socket and uses it for subsequent calls
|
||||
bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len);
|
||||
bool rawsend_rp(const struct rawpacket *rp);
|
||||
// return trues if all packets were send successfully
|
||||
bool rawsend_queue(struct rawpacket_tailhead *q);
|
||||
// should pre-do it if dropping privileges. otherwise its not necessary
|
||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
||||
// cleans up socket autocreated by rawsend
|
||||
void rawsend_cleanup(void);
|
||||
|
||||
#ifdef BSD
|
||||
int socket_divert(sa_family_t family);
|
||||
#endif
|
||||
|
||||
const char *proto_name(uint8_t proto);
|
||||
uint16_t family_from_proto(uint8_t l3proto);
|
||||
|
@ -265,3 +265,35 @@ time_t file_mod_time(const char *filename)
|
||||
struct stat st;
|
||||
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
bool pf_parse(const char *s, port_filter *pf)
|
||||
{
|
||||
unsigned int v1,v2;
|
||||
|
||||
if (!s) return false;
|
||||
if (*s=='~')
|
||||
{
|
||||
pf->neg=true;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
pf->neg=false;
|
||||
if (sscanf(s,"%u-%u",&v1,&v2)==2)
|
||||
{
|
||||
if (!v1 || v1>65535 || v2>65535 || v1>v2) return false;
|
||||
pf->from=(uint16_t)v1;
|
||||
pf->to=(uint16_t)v2;
|
||||
}
|
||||
else if (sscanf(s,"%u",&v1)==1)
|
||||
{
|
||||
if (!v1 || v1>65535) return false;
|
||||
pf->to=pf->from=(uint16_t)v1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -47,3 +47,11 @@ void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize
|
||||
int fprint_localtime(FILE *F);
|
||||
|
||||
time_t file_mod_time(const char *filename);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t from,to;
|
||||
bool neg;
|
||||
} port_filter;
|
||||
bool pf_in_range(uint16_t port, const port_filter *pf);
|
||||
bool pf_parse(const char *s, port_filter *pf);
|
||||
|
368
nfq/nfqws.c
368
nfq/nfqws.c
@ -78,6 +78,15 @@ static void onusr2(int sig)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void pre_desync(void)
|
||||
{
|
||||
signal(SIGHUP, onhup);
|
||||
signal(SIGUSR1, onusr1);
|
||||
signal(SIGUSR2, onusr2);
|
||||
|
||||
desync_init();
|
||||
}
|
||||
|
||||
|
||||
static uint8_t processPacketData(uint32_t *mark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt)
|
||||
{
|
||||
@ -189,17 +198,16 @@ static int nfq_main(void)
|
||||
if (!rawsend_preinit(params.bind_fix4,params.bind_fix6))
|
||||
goto exiterr;
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
sec_harden();
|
||||
|
||||
if (params.droproot && !droproot(params.uid, params.gid))
|
||||
goto exiterr;
|
||||
|
||||
print_id();
|
||||
#endif
|
||||
|
||||
signal(SIGHUP, onhup);
|
||||
signal(SIGUSR1, onusr1);
|
||||
signal(SIGUSR2, onusr2);
|
||||
|
||||
desync_init();
|
||||
pre_desync();
|
||||
|
||||
fd = nfq_fd(h);
|
||||
|
||||
@ -311,10 +319,7 @@ static int dvt_main(void)
|
||||
goto exiterr;
|
||||
print_id();
|
||||
|
||||
signal(SIGHUP, onhup);
|
||||
signal(SIGUSR1, onusr1);
|
||||
|
||||
desync_init();
|
||||
pre_desync();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
@ -385,7 +390,75 @@ exiterr:
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined (__CYGWIN__)
|
||||
|
||||
static int win_main(const char *windivert_filter)
|
||||
{
|
||||
size_t len;
|
||||
unsigned int id;
|
||||
uint8_t verdict;
|
||||
bool bOutbound;
|
||||
uint8_t packet[16384];
|
||||
uint32_t mark;
|
||||
WINDIVERT_ADDRESS wa;
|
||||
char ifout[22];
|
||||
|
||||
if (!windivert_init(windivert_filter))
|
||||
return 1;
|
||||
|
||||
printf("windivert initialized. capture is started.\n");
|
||||
|
||||
pre_desync();
|
||||
|
||||
for (id=0;;id++)
|
||||
{
|
||||
len = sizeof(packet);
|
||||
if (!windivert_recv(packet, &len, &wa))
|
||||
{
|
||||
if (errno==ENOBUFS)
|
||||
{
|
||||
DLOG("windivert: ignoring too large packet\n")
|
||||
continue; // too large packet
|
||||
}
|
||||
fprintf(stderr, "windivert: recv failed. errno %d\n", errno);
|
||||
break;
|
||||
}
|
||||
*ifout=0;
|
||||
snprintf(ifout,sizeof(ifout),"%u.%u",wa.Network.IfIdx, wa.Network.SubIfIdx);
|
||||
DLOG("packet: id=%u len=%zu outbound=%u IPv6=%u IPChecksum=%u TCPChecksum=%u UDPChecksum=%u IfIdx=%s\n", id, len, wa.Outbound, wa.IPv6, wa.IPChecksum, wa.TCPChecksum, wa.UDPChecksum, ifout)
|
||||
if (wa.Impostor)
|
||||
{
|
||||
DLOG("windivert: skipping impostor packet\n")
|
||||
continue;
|
||||
}
|
||||
if (wa.Loopback)
|
||||
{
|
||||
DLOG("windivert: skipping loopback packet\n")
|
||||
continue;
|
||||
}
|
||||
mark=0;
|
||||
// pseudo interface id IfIdx.SubIfIdx
|
||||
verdict = processPacketData(&mark, ifout, packet, &len);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_PASS:
|
||||
case VERDICT_MODIFY:
|
||||
if ((verdict & VERDICT_MASK)==VERDICT_PASS)
|
||||
DLOG("packet: id=%u reinject unmodified\n", id)
|
||||
else
|
||||
DLOG("packet: id=%u reinject modified len=%zu\n", id, len)
|
||||
if (!windivert_send(packet, len, &wa))
|
||||
fprintf(stderr,"windivert: reinject of packet id=%u failed\n", id);
|
||||
break;
|
||||
default:
|
||||
DLOG("packet: id=%u drop\n", id);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // multiple OS divert handlers
|
||||
|
||||
|
||||
|
||||
@ -427,16 +500,35 @@ static void exithelp(void)
|
||||
#endif
|
||||
" --daemon\t\t\t\t\t; daemonize\n"
|
||||
" --pidfile=<filename>\t\t\t\t; write pid to file\n"
|
||||
#ifndef __CYGWIN__
|
||||
" --user=<username>\t\t\t\t; drop root privs\n"
|
||||
" --uid=uid[:gid]\t\t\t\t; drop root privs\n"
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
" --bind-fix4\t\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n"
|
||||
" --bind-fix6\t\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n"
|
||||
#endif
|
||||
" --ctrack-timeouts=S:E:F[:U]\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n"
|
||||
#ifdef __CYGWIN__
|
||||
"\nWINDIVERT FILTER:\n"
|
||||
" --wf-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --wf-tcp=[~]port1[-port2]\t\t\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
||||
" --wf-udp=[~]port1[-port2]\t\t\t; UDP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
||||
" --wf-raw=<filter>|@<filename>\t\t\t; raw windivert filter string or filename\n"
|
||||
" --wf-save=<filename>\t\t\t\t; save windivert filter string to a file and exit\n"
|
||||
#endif
|
||||
"\nHOSTLIST FILTER:\n"
|
||||
" --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-exclude=<filename>\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-auto=<filename>\t\t\t; detect DPI blocks and build hostlist automatically\n"
|
||||
" --hostlist-auto-fail-threshold=<int>\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
|
||||
" --hostlist-auto-fail-time=<int>\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
" --hostlist-auto-retrans-threshold=<int>\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
||||
" --hostlist-auto-debug=<logfile>\t\t; debug auto hostlist positives\n"
|
||||
"\nTAMPER:\n"
|
||||
" --wsize=<window_size>[:<scale_factor>]\t\t; set window size. 0 = do not modify. OBSOLETE !\n"
|
||||
" --wssize=<window_size>[:<scale_factor>]\t; set window size for server. 0 = do not modify. default scale_factor = 0.\n"
|
||||
" --wssize-cutoff=[n|d|s]N\t\t\t; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
||||
" --ctrack-timeouts=S:E:F[:U]\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n"
|
||||
" --hostcase\t\t\t\t\t; change Host: => 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"
|
||||
@ -471,15 +563,9 @@ static void exithelp(void)
|
||||
" --dpi-desync-udplen-increment=<int>\t\t; increase or decrease udp packet length by N bytes (default %u). negative values decrease length.\n"
|
||||
" --dpi-desync-udplen-pattern=<filename>|0xHEX\t; udp tail fill pattern\n"
|
||||
" --dpi-desync-start=[n|d|s]N\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
||||
" --dpi-desync-cutoff=[n|d|s]N\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
||||
" --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-exclude=<filename>\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-auto=<filename>\t\t\t; detect DPI blocks and build hostlist automatically\n"
|
||||
" --hostlist-auto-fail-threshold=<int>\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
|
||||
" --hostlist-auto-fail-time=<int>\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
" --hostlist-auto-retrans-threshold=<int>\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
||||
" --hostlist-auto-debug=<logfile>\t\t; debug auto hostlist positives\n",
|
||||
" --dpi-desync-cutoff=[n|d|s]N\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n",
|
||||
CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP,
|
||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT,
|
||||
#endif
|
||||
@ -488,8 +574,7 @@ static void exithelp(void)
|
||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT,
|
||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT,
|
||||
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
||||
UDPLEN_INCREMENT_DEFAULT,
|
||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT
|
||||
UDPLEN_INCREMENT_DEFAULT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
@ -580,12 +665,151 @@ bool parse_autottl(const char *s, autottl *t)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *buf, size_t len)
|
||||
{
|
||||
char *e,*p,c,s1[64];
|
||||
port_filter pf;
|
||||
int n;
|
||||
|
||||
if (len<3) return false;
|
||||
|
||||
for (n=0,p=opt,*buf='(',buf[1]=0 ; p ; n++)
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
if (!pf_parse(p,&pf)) return false;
|
||||
|
||||
if (pf.from==pf.to)
|
||||
snprintf(s1, sizeof(s1), "(%s.%s %s %u)", l4, portname, pf.neg ? "!=" : "==", pf.from);
|
||||
else
|
||||
snprintf(s1, sizeof(s1), "(%s.%s %s %u %s %s.%s %s %u)", l4, portname, pf.neg ? "<" : ">=", pf.from, pf.neg ? "or" : "and" , l4, portname, pf.neg ? ">" : "<=", pf.to);
|
||||
if (n) strncat(buf," or ",len-strlen(buf)-1);
|
||||
strncat(buf, s1, len-strlen(buf)-1);
|
||||
|
||||
if (e)
|
||||
{
|
||||
*e++=c;
|
||||
}
|
||||
p = e;
|
||||
}
|
||||
strncat(buf, ")", len-strlen(buf)-1);
|
||||
return true;
|
||||
}
|
||||
static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6)
|
||||
{
|
||||
char *e,*p,c;
|
||||
|
||||
for (p=opt,*ipv4=*ipv6=false ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (!strcmp(p,"ipv4"))
|
||||
*ipv4 = true;
|
||||
else if (!strcmp(p,"ipv6"))
|
||||
*ipv6 = true;
|
||||
else return false;
|
||||
|
||||
if (e)
|
||||
{
|
||||
*e++=c;
|
||||
}
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DIVERT_NO_LOCALNETSv4_DST "(" \
|
||||
"(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and " \
|
||||
"(ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and " \
|
||||
"(ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and " \
|
||||
"(ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and " \
|
||||
"(ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255))"
|
||||
#define DIVERT_NO_LOCALNETSv4_SRC "(" \
|
||||
"(ip.SrcAddr < 127.0.0.1 or ip.SrcAddr > 127.255.255.255) and " \
|
||||
"(ip.SrcAddr < 10.0.0.0 or ip.SrcAddr > 10.255.255.255) and " \
|
||||
"(ip.SrcAddr < 192.168.0.0 or ip.SrcAddr > 192.168.255.255) and " \
|
||||
"(ip.SrcAddr < 172.16.0.0 or ip.SrcAddr > 172.31.255.255) and " \
|
||||
"(ip.SrcAddr < 169.254.0.0 or ip.SrcAddr > 169.254.255.255))"
|
||||
|
||||
#define DIVERT_NO_LOCALNETSv6_DST "(" \
|
||||
"(ipv6.DstAddr > ::1) and " \
|
||||
"(ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and " \
|
||||
"(ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and " \
|
||||
"(ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and " \
|
||||
"(ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))"
|
||||
#define DIVERT_NO_LOCALNETSv6_SRC "(" \
|
||||
"(ipv6.SrcAddr > ::1) and " \
|
||||
"(ipv6.SrcAddr < 2001::0 or ipv6.SrcAddr >= 2001:1::0) and " \
|
||||
"(ipv6.SrcAddr < fc00::0 or ipv6.SrcAddr >= fe00::0) and " \
|
||||
"(ipv6.SrcAddr < fe80::0 or ipv6.SrcAddr >= fec0::0) and " \
|
||||
"(ipv6.SrcAddr < ff00::0 or ipv6.SrcAddr >= ffff::0))"
|
||||
|
||||
#define DIVERT_NO_LOCALNETS_SRC "(" DIVERT_NO_LOCALNETSv4_SRC " or " DIVERT_NO_LOCALNETSv6_SRC ")"
|
||||
#define DIVERT_NO_LOCALNETS_DST "(" DIVERT_NO_LOCALNETSv4_DST " or " DIVERT_NO_LOCALNETSv6_DST ")"
|
||||
|
||||
#define DIVERT_TCP_INBOUNDS "tcp.Ack and tcp.Syn or tcp.Rst or tcp.Fin"
|
||||
|
||||
// HTTP/1.? 30(2|7)
|
||||
#define DIVERT_HTTP_REDIRECT "tcp.PayloadLength>=12 and tcp.Payload32[0]==0x48545450 and tcp.Payload16[2]==0x2F31 and tcp.Payload[6]==0x2E and tcp.Payload16[4]==0x2033 and tcp.Payload[10]==0x30 and (tcp.Payload[11]==0x32 or tcp.Payload[11]==0x37)"
|
||||
|
||||
#define DIVERT_PROLOG "!impostor and !loopback"
|
||||
|
||||
static bool wf_make_filter(
|
||||
char *wf, size_t len,
|
||||
bool ipv4, bool ipv6,
|
||||
const char *pf_tcp_src, const char *pf_tcp_dst,
|
||||
const char *pf_udp_src, const char *pf_udp_dst)
|
||||
{
|
||||
char pf_src_buf[512],pf_dst_buf[512];
|
||||
const char *pf_dst;
|
||||
const char *f_tcpin = *pf_tcp_src ? *params.hostlist_auto_filename ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : "";
|
||||
|
||||
if (!*pf_tcp_src && !*pf_udp_src) return false;
|
||||
if (*pf_tcp_src && *pf_udp_src)
|
||||
{
|
||||
snprintf(pf_dst_buf,sizeof(pf_dst_buf),"(%s or %s)",pf_tcp_dst,pf_udp_dst);
|
||||
pf_dst = pf_dst_buf;
|
||||
}
|
||||
else
|
||||
pf_dst = *pf_tcp_dst ? pf_tcp_dst : pf_udp_dst;
|
||||
snprintf(wf,len,
|
||||
DIVERT_PROLOG " and%s\n ((outbound and %s%s)\n or\n (inbound and tcp%s%s%s%s%s%s%s))",
|
||||
ipv4 ? ipv6 ? "" : " ip and" : " ipv6 and",
|
||||
pf_dst,
|
||||
ipv4 ? ipv6 ? " and " DIVERT_NO_LOCALNETS_DST : " and " DIVERT_NO_LOCALNETSv4_DST : " and " DIVERT_NO_LOCALNETSv6_DST,
|
||||
*pf_tcp_src ? "" : " and false",
|
||||
*f_tcpin ? " and " : "",
|
||||
*f_tcpin ? f_tcpin : "",
|
||||
*pf_tcp_src ? " and " : "",
|
||||
*pf_tcp_src ? pf_tcp_src : "",
|
||||
*pf_tcp_src ? " and " : "",
|
||||
*pf_tcp_src ? ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC : ""
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result, v;
|
||||
int option_index = 0;
|
||||
bool daemon = false;
|
||||
char pidfile[256];
|
||||
#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];
|
||||
bool wf_ipv4=true, wf_ipv6=true;
|
||||
*windivert_filter = *wf_pf_tcp_src = *wf_pf_tcp_dst = *wf_pf_udp_src = *wf_pf_udp_dst = *wf_save_file = 0;
|
||||
#endif
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
@ -629,12 +853,14 @@ int main(int argc, char **argv)
|
||||
|
||||
LIST_INIT(¶ms.hostlist_files);
|
||||
LIST_INIT(¶ms.hostlist_exclude_files);
|
||||
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
if (can_drop_root()) // are we root ?
|
||||
{
|
||||
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
||||
params.droproot = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct option long_options[] = {
|
||||
{"debug",optional_argument,0,0}, // optidx=0
|
||||
@ -647,8 +873,13 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
{"daemon",no_argument,0,0}, // optidx=2
|
||||
{"pidfile",required_argument,0,0}, // optidx=3
|
||||
#ifndef __CYGWIN__
|
||||
{"user",required_argument,0,0 }, // optidx=4
|
||||
{"uid",required_argument,0,0 }, // optidx=5
|
||||
#else
|
||||
{"disabled_argument_2",no_argument,0,0}, // optidx=4
|
||||
{"disabled_argument_3",no_argument,0,0}, // optidx=5
|
||||
#endif
|
||||
{"wsize",required_argument,0,0}, // optidx=6
|
||||
{"wssize",required_argument,0,0}, // optidx=7
|
||||
{"wssize-cutoff",required_argument,0,0},// optidx=8
|
||||
@ -663,7 +894,7 @@ int main(int argc, char **argv)
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15
|
||||
#else
|
||||
{"disabled_argument_2",no_argument,0,0}, // optidx=15
|
||||
{"disabled_argument_4",no_argument,0,0}, // optidx=15
|
||||
#endif
|
||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16
|
||||
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=17
|
||||
@ -701,6 +932,12 @@ int main(int argc, char **argv)
|
||||
#ifdef __linux__
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=48
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=49
|
||||
#elif defined(__CYGWIN__)
|
||||
{"wf-l3",required_argument,0,0}, // optidx=48
|
||||
{"wf-tcp",required_argument,0,0}, // optidx=49
|
||||
{"wf-udp",required_argument,0,0}, // optidx=50
|
||||
{"wf-raw",required_argument,0,0}, // optidx=51
|
||||
{"wf-save",required_argument,0,0}, // optidx=52
|
||||
#endif
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
@ -713,6 +950,7 @@ int main(int argc, char **argv)
|
||||
case 0: /* debug */
|
||||
params.debug = !optarg || atoi(optarg);
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case 1: /* qnum or port */
|
||||
#ifdef __linux__
|
||||
params.qnum = atoi(optarg);
|
||||
@ -733,6 +971,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case 2: /* daemon */
|
||||
daemon = true;
|
||||
break;
|
||||
@ -740,6 +979,7 @@ int main(int argc, char **argv)
|
||||
strncpy(pidfile, optarg, sizeof(pidfile));
|
||||
pidfile[sizeof(pidfile) - 1] = '\0';
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case 4: /* user */
|
||||
{
|
||||
struct passwd *pwd = getpwnam(optarg);
|
||||
@ -762,6 +1002,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 6: /* wsize */
|
||||
if (!parse_ws_scale_factor(optarg,¶ms.wsize,¶ms.wscale))
|
||||
exit_clean(1);
|
||||
@ -847,6 +1088,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
params.desync_fwmark = 0;
|
||||
@ -861,6 +1103,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case 16: /* dpi-desync-ttl */
|
||||
params.desync_ttl = (uint8_t)atoi(optarg);
|
||||
break;
|
||||
@ -1069,8 +1312,10 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "gzipped auto hostlists are not supported\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
#ifndef __CYGWIN__
|
||||
if (params.droproot && chown(optarg, params.uid, -1))
|
||||
fprintf(stderr, "could not chown %s. auto hostlist file may not be writable after privilege drop\n", optarg);
|
||||
#endif
|
||||
}
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
@ -1113,8 +1358,10 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
fclose(F);
|
||||
#ifndef __CYGWIN__
|
||||
if (params.droproot && chown(optarg, params.uid, -1))
|
||||
fprintf(stderr, "could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", optarg);
|
||||
#endif
|
||||
strncpy(params.hostlist_auto_debuglog, optarg, sizeof(params.hostlist_auto_debuglog));
|
||||
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
|
||||
}
|
||||
@ -1126,6 +1373,48 @@ int main(int argc, char **argv)
|
||||
case 49: /* bind-fix6 */
|
||||
params.bind_fix6 = true;
|
||||
break;
|
||||
#elif defined(__CYGWIN__)
|
||||
case 48: /* wf-l3 */
|
||||
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
|
||||
{
|
||||
fprintf(stderr, "bad value for --wf-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 49: /* wf-tcp */
|
||||
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)))
|
||||
{
|
||||
fprintf(stderr, "bad value for --wf-tcp\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 50: /* wf-udp */
|
||||
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)))
|
||||
{
|
||||
fprintf(stderr, "bad value for --wf-udp\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 51: /* wf-raw */
|
||||
if (optarg[0]=='@')
|
||||
{
|
||||
size_t sz = sizeof(windivert_filter)-1;
|
||||
load_file_or_exit(optarg+1,windivert_filter,&sz);
|
||||
windivert_filter[sz] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(windivert_filter, optarg, sizeof(windivert_filter));
|
||||
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
case 52: /* wf-save */
|
||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||
break;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1142,6 +1431,34 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Need divert port (--port)\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
#elif defined(__CYGWIN__)
|
||||
if (!*windivert_filter)
|
||||
{
|
||||
if (!*wf_pf_tcp_src && !*wf_pf_udp_src)
|
||||
{
|
||||
fprintf(stderr, "windivert filter : must specify port filter\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!wf_make_filter(windivert_filter, sizeof(windivert_filter), wf_ipv4, wf_ipv6, wf_pf_tcp_src, wf_pf_tcp_dst, wf_pf_udp_src, wf_pf_udp_dst))
|
||||
{
|
||||
fprintf(stderr, "windivert filter : could not make filter\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
DLOG("windivert filter size: %zu\nwindivert filter:\n%s\n",strlen(windivert_filter),windivert_filter)
|
||||
if (*wf_save_file)
|
||||
{
|
||||
if (save_file(wf_save_file,windivert_filter,strlen(windivert_filter)))
|
||||
{
|
||||
printf("windivert filter: raw filter saved to %s\n", wf_save_file);
|
||||
exit_clean(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "windivert filter: could not save raw filter to %s\n", wf_save_file);
|
||||
exit_clean(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// not specified - use desync_ttl value instead
|
||||
@ -1157,7 +1474,8 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Include hostlist load failed\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (*params.hostlist_auto_filename) NonEmptyHostlist(¶ms.hostlist);
|
||||
if (*params.hostlist_auto_filename)
|
||||
NonEmptyHostlist(¶ms.hostlist);
|
||||
if (!LoadExcludeHostLists())
|
||||
{
|
||||
fprintf(stderr, "Exclude hostlist load failed\n");
|
||||
@ -1179,6 +1497,8 @@ int main(int argc, char **argv)
|
||||
result = nfq_main();
|
||||
#elif defined(BSD)
|
||||
result = dvt_main();
|
||||
#elif defined(__CYGWIN__)
|
||||
result = win_main(windivert_filter);
|
||||
#else
|
||||
#error unsupported OS
|
||||
#endif
|
||||
|
@ -61,9 +61,12 @@ struct params_s
|
||||
uint8_t fake_unknown_udp[1472],udplen_pattern[1472],fake_quic[1472],fake_wg[1472],fake_dht[1472];
|
||||
size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size;
|
||||
int udplen_increment;
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
bool droproot;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
#endif
|
||||
|
||||
strpool *hostlist, *hostlist_exclude;
|
||||
struct str_list_head hostlist_files, hostlist_exclude_files;
|
||||
|
15
nfq/sec.c
15
nfq/sec.c
@ -270,17 +270,18 @@ bool dropcaps(void)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else // __linux__
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
|
||||
#ifndef __linux__
|
||||
bool sec_harden(void)
|
||||
{
|
||||
// noop
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
bool can_drop_root(void)
|
||||
{
|
||||
@ -329,6 +330,7 @@ void print_id(void)
|
||||
{
|
||||
int i,N;
|
||||
gid_t g[128];
|
||||
|
||||
printf("Running as UID=%u GID=",getuid());
|
||||
N=getgroups(sizeof(g)/sizeof(*g),g);
|
||||
if (N>0)
|
||||
@ -341,6 +343,9 @@ void print_id(void)
|
||||
printf("%u\n",getgid());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void daemonize(void)
|
||||
{
|
||||
int pid;
|
||||
|
@ -52,9 +52,12 @@ bool dropcaps(void);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
bool sec_harden(void);
|
||||
bool can_drop_root(void);
|
||||
bool droproot(uid_t uid, gid_t gid);
|
||||
void print_id(void);
|
||||
#endif
|
||||
|
||||
void daemonize(void);
|
||||
bool writepid(const char *filename);
|
||||
|
BIN
nfq/windivert/libwindivert.a
Normal file
BIN
nfq/windivert/libwindivert.a
Normal file
Binary file not shown.
635
nfq/windivert/windivert.h
Normal file
635
nfq/windivert/windivert.h
Normal file
@ -0,0 +1,635 @@
|
||||
// WinDivert 2.2.2. MODDED
|
||||
|
||||
/*
|
||||
* windivert.h
|
||||
* (C) 2019, all rights reserved,
|
||||
*
|
||||
* This file is part of WinDivert.
|
||||
*
|
||||
* WinDivert is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* WinDivert is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __WINDIVERT_H
|
||||
#define __WINDIVERT_H
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
#include <windows.h>
|
||||
#endif /* WINDIVERT_KERNEL */
|
||||
|
||||
#ifndef WINDIVERTEXPORT
|
||||
#define WINDIVERTEXPORT extern __declspec(dllimport)
|
||||
#endif /* WINDIVERTEXPORT */
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define __in
|
||||
#define __in_opt
|
||||
#define __out
|
||||
#define __out_opt
|
||||
#define __inout
|
||||
#define __inout_opt
|
||||
#include <stdint.h>
|
||||
#define INT8 int8_t
|
||||
#define UINT8 uint8_t
|
||||
#define INT16 int16_t
|
||||
#define UINT16 uint16_t
|
||||
#define INT32 int32_t
|
||||
#define UINT32 uint32_t
|
||||
#define INT64 int64_t
|
||||
#define UINT64 uint64_t
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* WINDIVERT API */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* WinDivert layers.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */
|
||||
WINDIVERT_LAYER_NETWORK_FORWARD = 1,/* Network layer (forwarded packets) */
|
||||
WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
|
||||
WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */
|
||||
WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */
|
||||
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
|
||||
|
||||
/*
|
||||
* WinDivert NETWORK and NETWORK_FORWARD layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT32 IfIdx; /* Packet's interface index. */
|
||||
UINT32 SubIfIdx; /* Packet's sub-interface index. */
|
||||
} WINDIVERT_DATA_NETWORK, *PWINDIVERT_DATA_NETWORK;
|
||||
|
||||
/*
|
||||
* WinDivert FLOW layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT64 EndpointId; /* Endpoint ID. */
|
||||
UINT64 ParentEndpointId; /* Parent endpoint ID. */
|
||||
UINT32 ProcessId; /* Process ID. */
|
||||
UINT32 LocalAddr[4]; /* Local address. */
|
||||
UINT32 RemoteAddr[4]; /* Remote address. */
|
||||
UINT16 LocalPort; /* Local port. */
|
||||
UINT16 RemotePort; /* Remote port. */
|
||||
UINT8 Protocol; /* Protocol. */
|
||||
} WINDIVERT_DATA_FLOW, *PWINDIVERT_DATA_FLOW;
|
||||
|
||||
/*
|
||||
* WinDivert SOCKET layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT64 EndpointId; /* Endpoint ID. */
|
||||
UINT64 ParentEndpointId; /* Parent Endpoint ID. */
|
||||
UINT32 ProcessId; /* Process ID. */
|
||||
UINT32 LocalAddr[4]; /* Local address. */
|
||||
UINT32 RemoteAddr[4]; /* Remote address. */
|
||||
UINT16 LocalPort; /* Local port. */
|
||||
UINT16 RemotePort; /* Remote port. */
|
||||
UINT8 Protocol; /* Protocol. */
|
||||
} WINDIVERT_DATA_SOCKET, *PWINDIVERT_DATA_SOCKET;
|
||||
|
||||
/*
|
||||
* WinDivert REFLECTION layer data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Handle open time. */
|
||||
UINT32 ProcessId; /* Handle process ID. */
|
||||
WINDIVERT_LAYER Layer; /* Handle layer. */
|
||||
UINT64 Flags; /* Handle flags. */
|
||||
INT16 Priority; /* Handle priority. */
|
||||
} WINDIVERT_DATA_REFLECT, *PWINDIVERT_DATA_REFLECT;
|
||||
|
||||
/*
|
||||
* WinDivert address.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4201)
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
INT64 Timestamp; /* Packet's timestamp. */
|
||||
UINT32 Layer:8; /* Packet's layer. */
|
||||
UINT32 Event:8; /* Packet event. */
|
||||
UINT32 Sniffed:1; /* Packet was sniffed? */
|
||||
UINT32 Outbound:1; /* Packet is outound? */
|
||||
UINT32 Loopback:1; /* Packet is loopback? */
|
||||
UINT32 Impostor:1; /* Packet is impostor? */
|
||||
UINT32 IPv6:1; /* Packet is IPv6? */
|
||||
UINT32 IPChecksum:1; /* Packet has valid IPv4 checksum? */
|
||||
|
||||
// MODDED : UDPChecksum and TCPChecksum in original version are exchanged
|
||||
UINT32 UDPChecksum:1; /* Packet has valid UDP checksum? */
|
||||
UINT32 TCPChecksum:1; /* Packet has valid TCP checksum? */
|
||||
|
||||
UINT32 Reserved1:8;
|
||||
UINT32 Reserved2;
|
||||
union
|
||||
{
|
||||
WINDIVERT_DATA_NETWORK Network; /* Network layer data. */
|
||||
WINDIVERT_DATA_FLOW Flow; /* Flow layer data. */
|
||||
WINDIVERT_DATA_SOCKET Socket; /* Socket layer data. */
|
||||
WINDIVERT_DATA_REFLECT Reflect; /* Reflect layer data. */
|
||||
UINT8 Reserved3[64];
|
||||
};
|
||||
} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* WinDivert events.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_EVENT_NETWORK_PACKET = 0, /* Network packet. */
|
||||
WINDIVERT_EVENT_FLOW_ESTABLISHED = 1,
|
||||
/* Flow established. */
|
||||
WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */
|
||||
WINDIVERT_EVENT_SOCKET_BIND = 3, /* Socket bind. */
|
||||
WINDIVERT_EVENT_SOCKET_CONNECT = 4, /* Socket connect. */
|
||||
WINDIVERT_EVENT_SOCKET_LISTEN = 5, /* Socket listen. */
|
||||
WINDIVERT_EVENT_SOCKET_ACCEPT = 6, /* Socket accept. */
|
||||
WINDIVERT_EVENT_SOCKET_CLOSE = 7, /* Socket close. */
|
||||
WINDIVERT_EVENT_REFLECT_OPEN = 8, /* WinDivert handle opened. */
|
||||
WINDIVERT_EVENT_REFLECT_CLOSE = 9, /* WinDivert handle closed. */
|
||||
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
|
||||
|
||||
/*
|
||||
* WinDivert flags.
|
||||
*/
|
||||
#define WINDIVERT_FLAG_SNIFF 0x0001
|
||||
#define WINDIVERT_FLAG_DROP 0x0002
|
||||
#define WINDIVERT_FLAG_RECV_ONLY 0x0004
|
||||
#define WINDIVERT_FLAG_READ_ONLY WINDIVERT_FLAG_RECV_ONLY
|
||||
#define WINDIVERT_FLAG_SEND_ONLY 0x0008
|
||||
#define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY
|
||||
#define WINDIVERT_FLAG_NO_INSTALL 0x0010
|
||||
#define WINDIVERT_FLAG_FRAGMENTS 0x0020
|
||||
|
||||
/*
|
||||
* WinDivert parameters.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_PARAM_QUEUE_LENGTH = 0, /* Packet queue length. */
|
||||
WINDIVERT_PARAM_QUEUE_TIME = 1, /* Packet queue time. */
|
||||
WINDIVERT_PARAM_QUEUE_SIZE = 2, /* Packet queue size. */
|
||||
WINDIVERT_PARAM_VERSION_MAJOR = 3, /* Driver version (major). */
|
||||
WINDIVERT_PARAM_VERSION_MINOR = 4, /* Driver version (minor). */
|
||||
} WINDIVERT_PARAM, *PWINDIVERT_PARAM;
|
||||
#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_VERSION_MINOR
|
||||
|
||||
/*
|
||||
* WinDivert shutdown parameter.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
WINDIVERT_SHUTDOWN_RECV = 0x1, /* Shutdown recv. */
|
||||
WINDIVERT_SHUTDOWN_SEND = 0x2, /* Shutdown send. */
|
||||
WINDIVERT_SHUTDOWN_BOTH = 0x3, /* Shutdown recv and send. */
|
||||
} WINDIVERT_SHUTDOWN, *PWINDIVERT_SHUTDOWN;
|
||||
#define WINDIVERT_SHUTDOWN_MAX WINDIVERT_SHUTDOWN_BOTH
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
* Open a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT HANDLE WinDivertOpen(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__in INT16 priority,
|
||||
__in UINT64 flags);
|
||||
|
||||
/*
|
||||
* Receive (read) a packet from a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertRecv(
|
||||
__in HANDLE handle,
|
||||
__out_opt VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT *pRecvLen,
|
||||
__out_opt WINDIVERT_ADDRESS *pAddr);
|
||||
|
||||
/*
|
||||
* Receive (read) a packet from a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertRecvEx(
|
||||
__in HANDLE handle,
|
||||
__out_opt VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT *pRecvLen,
|
||||
__in UINT64 flags,
|
||||
__out WINDIVERT_ADDRESS *pAddr,
|
||||
__inout_opt UINT *pAddrLen,
|
||||
__inout_opt LPOVERLAPPED lpOverlapped);
|
||||
|
||||
/*
|
||||
* Send (write/inject) a packet to a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertSend(
|
||||
__in HANDLE handle,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT *pSendLen,
|
||||
__in const WINDIVERT_ADDRESS *pAddr);
|
||||
|
||||
/*
|
||||
* Send (write/inject) a packet to a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertSendEx(
|
||||
__in HANDLE handle,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt UINT *pSendLen,
|
||||
__in UINT64 flags,
|
||||
__in const WINDIVERT_ADDRESS *pAddr,
|
||||
__in UINT addrLen,
|
||||
__inout_opt LPOVERLAPPED lpOverlapped);
|
||||
|
||||
/*
|
||||
* Shutdown a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertShutdown(
|
||||
__in HANDLE handle,
|
||||
__in WINDIVERT_SHUTDOWN how);
|
||||
|
||||
/*
|
||||
* Close a WinDivert handle.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertClose(
|
||||
__in HANDLE handle);
|
||||
|
||||
/*
|
||||
* Set a WinDivert handle parameter.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertSetParam(
|
||||
__in HANDLE handle,
|
||||
__in WINDIVERT_PARAM param,
|
||||
__in UINT64 value);
|
||||
|
||||
/*
|
||||
* Get a WinDivert handle parameter.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertGetParam(
|
||||
__in HANDLE handle,
|
||||
__in WINDIVERT_PARAM param,
|
||||
__out UINT64 *pValue);
|
||||
|
||||
#endif /* WINDIVERT_KERNEL */
|
||||
|
||||
/*
|
||||
* WinDivert constants.
|
||||
*/
|
||||
#define WINDIVERT_PRIORITY_HIGHEST 30000
|
||||
#define WINDIVERT_PRIORITY_LOWEST (-WINDIVERT_PRIORITY_HIGHEST)
|
||||
#define WINDIVERT_PARAM_QUEUE_LENGTH_DEFAULT 4096
|
||||
#define WINDIVERT_PARAM_QUEUE_LENGTH_MIN 32
|
||||
#define WINDIVERT_PARAM_QUEUE_LENGTH_MAX 16384
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 2000 /* 2s */
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_MIN 100 /* 100ms */
|
||||
#define WINDIVERT_PARAM_QUEUE_TIME_MAX 16000 /* 16s */
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */
|
||||
#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */
|
||||
#define WINDIVERT_BATCH_MAX 0xFF /* 255 */
|
||||
#define WINDIVERT_MTU_MAX (40 + 0xFFFF)
|
||||
|
||||
/****************************************************************************/
|
||||
/* WINDIVERT HELPER API */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4214)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UINT8 HdrLength:4;
|
||||
UINT8 Version:4;
|
||||
UINT8 TOS;
|
||||
UINT16 Length;
|
||||
UINT16 Id;
|
||||
UINT16 FragOff0;
|
||||
UINT8 TTL;
|
||||
UINT8 Protocol;
|
||||
UINT16 Checksum;
|
||||
UINT32 SrcAddr;
|
||||
UINT32 DstAddr;
|
||||
} WINDIVERT_IPHDR, *PWINDIVERT_IPHDR;
|
||||
|
||||
#define WINDIVERT_IPHDR_GET_FRAGOFF(hdr) \
|
||||
(((hdr)->FragOff0) & 0xFF1F)
|
||||
#define WINDIVERT_IPHDR_GET_MF(hdr) \
|
||||
((((hdr)->FragOff0) & 0x0020) != 0)
|
||||
#define WINDIVERT_IPHDR_GET_DF(hdr) \
|
||||
((((hdr)->FragOff0) & 0x0040) != 0)
|
||||
#define WINDIVERT_IPHDR_GET_RESERVED(hdr) \
|
||||
((((hdr)->FragOff0) & 0x0080) != 0)
|
||||
|
||||
#define WINDIVERT_IPHDR_SET_FRAGOFF(hdr, val) \
|
||||
do \
|
||||
{ \
|
||||
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0x00E0) | \
|
||||
((val) & 0xFF1F); \
|
||||
} \
|
||||
while (FALSE)
|
||||
#define WINDIVERT_IPHDR_SET_MF(hdr, val) \
|
||||
do \
|
||||
{ \
|
||||
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFDF) | \
|
||||
(((val) & 0x0001) << 5); \
|
||||
} \
|
||||
while (FALSE)
|
||||
#define WINDIVERT_IPHDR_SET_DF(hdr, val) \
|
||||
do \
|
||||
{ \
|
||||
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFBF) | \
|
||||
(((val) & 0x0001) << 6); \
|
||||
} \
|
||||
while (FALSE)
|
||||
#define WINDIVERT_IPHDR_SET_RESERVED(hdr, val) \
|
||||
do \
|
||||
{ \
|
||||
(hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFF7F) | \
|
||||
(((val) & 0x0001) << 7); \
|
||||
} \
|
||||
while (FALSE)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 TrafficClass0:4;
|
||||
UINT8 Version:4;
|
||||
UINT8 FlowLabel0:4;
|
||||
UINT8 TrafficClass1:4;
|
||||
UINT16 FlowLabel1;
|
||||
UINT16 Length;
|
||||
UINT8 NextHdr;
|
||||
UINT8 HopLimit;
|
||||
UINT32 SrcAddr[4];
|
||||
UINT32 DstAddr[4];
|
||||
} WINDIVERT_IPV6HDR, *PWINDIVERT_IPV6HDR;
|
||||
|
||||
#define WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(hdr) \
|
||||
((((hdr)->TrafficClass0) << 4) | ((hdr)->TrafficClass1))
|
||||
#define WINDIVERT_IPV6HDR_GET_FLOWLABEL(hdr) \
|
||||
((((UINT32)(hdr)->FlowLabel0) << 16) | ((UINT32)(hdr)->FlowLabel1))
|
||||
|
||||
#define WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(hdr, val) \
|
||||
do \
|
||||
{ \
|
||||
(hdr)->TrafficClass0 = ((UINT8)(val) >> 4); \
|
||||
(hdr)->TrafficClass1 = (UINT8)(val); \
|
||||
} \
|
||||
while (FALSE)
|
||||
#define WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val) \
|
||||
do \
|
||||
{ \
|
||||
(hdr)->FlowLabel0 = (UINT8)((val) >> 16); \
|
||||
(hdr)->FlowLabel1 = (UINT16)(val); \
|
||||
} \
|
||||
while (FALSE)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 Type;
|
||||
UINT8 Code;
|
||||
UINT16 Checksum;
|
||||
UINT32 Body;
|
||||
} WINDIVERT_ICMPHDR, *PWINDIVERT_ICMPHDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 Type;
|
||||
UINT8 Code;
|
||||
UINT16 Checksum;
|
||||
UINT32 Body;
|
||||
} WINDIVERT_ICMPV6HDR, *PWINDIVERT_ICMPV6HDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 SrcPort;
|
||||
UINT16 DstPort;
|
||||
UINT32 SeqNum;
|
||||
UINT32 AckNum;
|
||||
UINT16 Reserved1:4;
|
||||
UINT16 HdrLength:4;
|
||||
UINT16 Fin:1;
|
||||
UINT16 Syn:1;
|
||||
UINT16 Rst:1;
|
||||
UINT16 Psh:1;
|
||||
UINT16 Ack:1;
|
||||
UINT16 Urg:1;
|
||||
UINT16 Reserved2:2;
|
||||
UINT16 Window;
|
||||
UINT16 Checksum;
|
||||
UINT16 UrgPtr;
|
||||
} WINDIVERT_TCPHDR, *PWINDIVERT_TCPHDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 SrcPort;
|
||||
UINT16 DstPort;
|
||||
UINT16 Length;
|
||||
UINT16 Checksum;
|
||||
} WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flags for WinDivertHelperCalcChecksums()
|
||||
*/
|
||||
#define WINDIVERT_HELPER_NO_IP_CHECKSUM 1
|
||||
#define WINDIVERT_HELPER_NO_ICMP_CHECKSUM 2
|
||||
#define WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM 4
|
||||
#define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8
|
||||
#define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
* Hash a packet.
|
||||
*/
|
||||
WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in UINT64 seed
|
||||
#ifdef __cplusplus
|
||||
= 0
|
||||
#endif
|
||||
);
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
|
||||
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
|
||||
__out_opt UINT8 *pProtocol,
|
||||
__out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
|
||||
__out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
|
||||
__out_opt PWINDIVERT_TCPHDR *ppTcpHdr,
|
||||
__out_opt PWINDIVERT_UDPHDR *ppUdpHdr,
|
||||
__out_opt PVOID *ppData,
|
||||
__out_opt UINT *pDataLen,
|
||||
__out_opt PVOID *ppNext,
|
||||
__out_opt UINT *pNextLen);
|
||||
|
||||
/*
|
||||
* Parse an IPv4 address.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperParseIPv4Address(
|
||||
__in const char *addrStr,
|
||||
__out_opt UINT32 *pAddr);
|
||||
|
||||
/*
|
||||
* Parse an IPv6 address.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address(
|
||||
__in const char *addrStr,
|
||||
__out_opt UINT32 *pAddr);
|
||||
|
||||
/*
|
||||
* Format an IPv4 address.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv4Address(
|
||||
__in UINT32 addr,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
/*
|
||||
* Format an IPv6 address.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
|
||||
__in const UINT32 *pAddr,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperCalcChecksums(
|
||||
__inout VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt WINDIVERT_ADDRESS *pAddr,
|
||||
__in UINT64 flags);
|
||||
|
||||
/*
|
||||
* Decrement the TTL/HopLimit.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperDecrementTTL(
|
||||
__inout VOID *pPacket,
|
||||
__in UINT packetLen);
|
||||
|
||||
/*
|
||||
* Compile the given filter string.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperCompileFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__out_opt char *object,
|
||||
__in UINT objLen,
|
||||
__out_opt const char **errorStr,
|
||||
__out_opt UINT *errorPos);
|
||||
|
||||
/*
|
||||
* Evaluate the given filter string.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter(
|
||||
__in const char *filter,
|
||||
__in const VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__in const WINDIVERT_ADDRESS *pAddr);
|
||||
|
||||
/*
|
||||
* Format the given filter string.
|
||||
*/
|
||||
WINDIVERTEXPORT BOOL WinDivertHelperFormatFilter(
|
||||
__in const char *filter,
|
||||
__in WINDIVERT_LAYER layer,
|
||||
__out char *buffer,
|
||||
__in UINT bufLen);
|
||||
|
||||
/*
|
||||
* Byte ordering.
|
||||
*/
|
||||
WINDIVERTEXPORT UINT16 WinDivertHelperNtohs(
|
||||
__in UINT16 x);
|
||||
WINDIVERTEXPORT UINT16 WinDivertHelperHtons(
|
||||
__in UINT16 x);
|
||||
WINDIVERTEXPORT UINT32 WinDivertHelperNtohl(
|
||||
__in UINT32 x);
|
||||
WINDIVERTEXPORT UINT32 WinDivertHelperHtonl(
|
||||
__in UINT32 x);
|
||||
WINDIVERTEXPORT UINT64 WinDivertHelperNtohll(
|
||||
__in UINT64 x);
|
||||
WINDIVERTEXPORT UINT64 WinDivertHelperHtonll(
|
||||
__in UINT64 x);
|
||||
WINDIVERTEXPORT void WinDivertHelperNtohIPv6Address(
|
||||
__in const UINT *inAddr,
|
||||
__out UINT *outAddr);
|
||||
WINDIVERTEXPORT void WinDivertHelperHtonIPv6Address(
|
||||
__in const UINT *inAddr,
|
||||
__out UINT *outAddr);
|
||||
|
||||
/*
|
||||
* Old names to be removed in the next version.
|
||||
*/
|
||||
WINDIVERTEXPORT void WinDivertHelperNtohIpv6Address(
|
||||
__in const UINT *inAddr,
|
||||
__out UINT *outAddr);
|
||||
WINDIVERTEXPORT void WinDivertHelperHtonIpv6Address(
|
||||
__in const UINT *inAddr,
|
||||
__out UINT *outAddr);
|
||||
|
||||
#endif /* WINDIVERT_KERNEL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __WINDIVERT_H */
|
@ -229,3 +229,35 @@ time_t file_mod_time(const char *filename)
|
||||
struct stat st;
|
||||
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
bool pf_parse(const char *s, port_filter *pf)
|
||||
{
|
||||
unsigned int v1,v2;
|
||||
|
||||
if (!s) return false;
|
||||
if (*s=='~')
|
||||
{
|
||||
pf->neg=true;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
pf->neg=false;
|
||||
if (sscanf(s,"%u-%u",&v1,&v2)==2)
|
||||
{
|
||||
if (!v1 || v1>65535 || v2>65535 || v1>v2) return false;
|
||||
pf->from=(uint16_t)v1;
|
||||
pf->to=(uint16_t)v2;
|
||||
}
|
||||
else if (sscanf(s,"%u",&v1)==1)
|
||||
{
|
||||
if (!v1 || v1>65535) return false;
|
||||
pf->to=pf->from=(uint16_t)v1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -47,3 +47,11 @@ static inline void phton16(uint8_t *p, uint16_t v) {
|
||||
int fprint_localtime(FILE *F);
|
||||
|
||||
time_t file_mod_time(const char *filename);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t from,to;
|
||||
bool neg;
|
||||
} port_filter;
|
||||
bool pf_in_range(uint16_t port, const port_filter *pf);
|
||||
bool pf_parse(const char *s, port_filter *pf);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <time.h>
|
||||
#include "tpws.h"
|
||||
#include "pools.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
||||
@ -25,12 +26,6 @@ struct bind_s
|
||||
int bind_wait_ifup,bind_wait_ip,bind_wait_ip_ll;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t from,to;
|
||||
bool neg;
|
||||
} port_filter;
|
||||
|
||||
struct params_s
|
||||
{
|
||||
struct bind_s binds[MAX_BINDS];
|
||||
|
@ -1530,37 +1530,3 @@ ex:
|
||||
if (resolve_pipe[1]) close(resolve_pipe[1]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
bool pf_parse(const char *s, port_filter *pf)
|
||||
{
|
||||
unsigned int v1,v2;
|
||||
|
||||
if (!s) return false;
|
||||
if (*s=='~')
|
||||
{
|
||||
pf->neg=true;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
pf->neg=false;
|
||||
if (sscanf(s,"%u-%u",&v1,&v2)==2)
|
||||
{
|
||||
if (!v1 || v1>65535 || v2>65535 || v1>v2) return false;
|
||||
pf->from=(uint16_t)v1;
|
||||
pf->to=(uint16_t)v2;
|
||||
}
|
||||
else if (sscanf(s,"%u",&v1)==1)
|
||||
{
|
||||
if (!v1 || v1>65535) return false;
|
||||
pf->to=pf->from=(uint16_t)v1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,3 @@ TAILQ_HEAD(tailhead, tproxy_conn);
|
||||
|
||||
|
||||
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);
|
||||
|
||||
bool pf_in_range(uint16_t port, const port_filter *pf);
|
||||
bool pf_parse(const char *s, port_filter *pf);
|
||||
|
Loading…
Reference in New Issue
Block a user