mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-29 21:40:52 +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}
|
TPWS_GID=${TPWS_GID:-3003}
|
||||||
NFQWS=${NFQWS:-${ZAPRET_BASE}/nfq/nfqws}
|
NFQWS=${NFQWS:-${ZAPRET_BASE}/nfq/nfqws}
|
||||||
DVTWS=${DVTWS:-${ZAPRET_BASE}/nfq/dvtws}
|
DVTWS=${DVTWS:-${ZAPRET_BASE}/nfq/dvtws}
|
||||||
|
WINWS=${WINWS:-${ZAPRET_BASE}/nfq/winws}
|
||||||
TPWS=${TPWS:-${ZAPRET_BASE}/tpws/tpws}
|
TPWS=${TPWS:-${ZAPRET_BASE}/tpws/tpws}
|
||||||
MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
|
MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
|
||||||
DESYNC_MARK=0x10000000
|
DESYNC_MARK=0x10000000
|
||||||
@ -191,7 +192,9 @@ mdig_resolve()
|
|||||||
{
|
{
|
||||||
# $1 - ip version 4/6
|
# $1 - ip version 4/6
|
||||||
# $2 - hostname
|
# $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()
|
check_system()
|
||||||
@ -229,6 +232,12 @@ check_system()
|
|||||||
PKTWSD=dvtws
|
PKTWSD=dvtws
|
||||||
FWTYPE=mpf
|
FWTYPE=mpf
|
||||||
;;
|
;;
|
||||||
|
CYGWIN*)
|
||||||
|
UNAME=CYGWIN
|
||||||
|
PKTWS="$WINWS"
|
||||||
|
PKTWSD=winws
|
||||||
|
FWTYPE=windivert
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo $UNAME not supported
|
echo $UNAME not supported
|
||||||
exitp 5
|
exitp 5
|
||||||
@ -256,7 +265,7 @@ check_prerequisites()
|
|||||||
{
|
{
|
||||||
echo \* checking 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
|
local target
|
||||||
case $UNAME in
|
case $UNAME in
|
||||||
Darwin)
|
Darwin)
|
||||||
@ -323,6 +332,9 @@ check_prerequisites()
|
|||||||
[ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1
|
[ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1
|
||||||
pf_save
|
pf_save
|
||||||
;;
|
;;
|
||||||
|
CYGWIN)
|
||||||
|
SKIP_TPWS=1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
for prog in $progs; do
|
for prog in $progs; do
|
||||||
@ -446,6 +458,7 @@ curl_with_dig()
|
|||||||
return 6
|
return 6
|
||||||
}
|
}
|
||||||
shift ; shift ; shift
|
shift ; shift ; shift
|
||||||
|
|
||||||
ALL_PROXY="$ALL_PROXY" curl $connect_to "$@"
|
ALL_PROXY="$ALL_PROXY" curl $connect_to "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,6 +571,10 @@ pktws_ipt_prepare()
|
|||||||
opf)
|
opf)
|
||||||
opf_prepare_dvtws $1 $2
|
opf_prepare_dvtws $1 $2
|
||||||
;;
|
;;
|
||||||
|
windivert)
|
||||||
|
WF="--wf-l3=ipv${IPV} --wf-${1}=$2"
|
||||||
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
pktws_ipt_unprepare()
|
pktws_ipt_unprepare()
|
||||||
@ -578,6 +595,9 @@ pktws_ipt_unprepare()
|
|||||||
opf)
|
opf)
|
||||||
pf_restore
|
pf_restore
|
||||||
;;
|
;;
|
||||||
|
windivert)
|
||||||
|
unset WF
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,6 +656,9 @@ pktws_start()
|
|||||||
FreeBSD|OpenBSD)
|
FreeBSD|OpenBSD)
|
||||||
"$DVTWS" --port=$IPFW_DIVERT_PORT "$@" >/dev/null &
|
"$DVTWS" --port=$IPFW_DIVERT_PORT "$@" >/dev/null &
|
||||||
;;
|
;;
|
||||||
|
CYGWIN)
|
||||||
|
"$WINWS" $WF "$@" >/dev/null &
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
PID=$!
|
PID=$!
|
||||||
# give some time to initialize
|
# give some time to initialize
|
||||||
@ -711,7 +734,7 @@ pktws_curl_test()
|
|||||||
# $1 - test function
|
# $1 - test function
|
||||||
# $2 - domain
|
# $2 - domain
|
||||||
# $3,$4,$5, ... - nfqws/dvtws params
|
# $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 "$@"
|
ws_curl_test pktws_start "$@"
|
||||||
}
|
}
|
||||||
xxxws_curl_test_update()
|
xxxws_curl_test_update()
|
||||||
@ -726,7 +749,7 @@ xxxws_curl_test_update()
|
|||||||
shift
|
shift
|
||||||
$xxxf $testf $dom "$@"
|
$xxxf $testf $dom "$@"
|
||||||
code=$?
|
code=$?
|
||||||
[ $code = 0 ] && strategy="${strategy:-$@}"
|
[ $code = 0 ] && strategy="${WF:+$WF }${strategy:-$@}"
|
||||||
return $code
|
return $code
|
||||||
}
|
}
|
||||||
pktws_curl_test_update()
|
pktws_curl_test_update()
|
||||||
@ -1329,6 +1352,10 @@ pingtest()
|
|||||||
OpenBSD)
|
OpenBSD)
|
||||||
ping -c 1 -w 1 $1 >/dev/null
|
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
|
ping -c 1 -W 1 $1 >/dev/null
|
||||||
;;
|
;;
|
||||||
@ -1356,7 +1383,7 @@ lookup4()
|
|||||||
# $2 - DNS
|
# $2 - DNS
|
||||||
case "$LOOKUP" in
|
case "$LOOKUP" in
|
||||||
nslookup)
|
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)
|
||||||
host -t A $1 $2 | grep "has address" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
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
|
# $1 - domain
|
||||||
# $2 - public DNS
|
# $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"
|
lookup4 $1 $2 >"$DNSCHECK_DIG2"
|
||||||
# check whether system resolver returns anything other than public DNS
|
# check whether system resolver returns anything other than public DNS
|
||||||
grep -qvFf "$DNSCHECK_DIG2" "$DNSCHECK_DIG1"
|
grep -qvFf "$DNSCHECK_DIG2" "$DNSCHECK_DIG1"
|
||||||
@ -1475,7 +1504,7 @@ sigpipe()
|
|||||||
fsleep_setup
|
fsleep_setup
|
||||||
fix_sbin_path
|
fix_sbin_path
|
||||||
check_system
|
check_system
|
||||||
require_root
|
[ "$UNAME" = CYGWIN ] || require_root
|
||||||
check_prerequisites
|
check_prerequisites
|
||||||
trap sigint_cleanup INT
|
trap sigint_cleanup INT
|
||||||
check_dns
|
check_dns
|
||||||
@ -1485,6 +1514,7 @@ trap - INT
|
|||||||
|
|
||||||
PID=
|
PID=
|
||||||
NREPORT=
|
NREPORT=
|
||||||
|
unset WF
|
||||||
trap sigint INT
|
trap sigint INT
|
||||||
trap sigpipe PIPE
|
trap sigpipe PIPE
|
||||||
for dom in $DOMAINS; do
|
for dom in $DOMAINS; do
|
||||||
|
@ -283,3 +283,7 @@ nfqws: --dpi-desync-start option
|
|||||||
nfqws: packet delay for kyber TLS and QUIC
|
nfqws: packet delay for kyber TLS and QUIC
|
||||||
nfqws: --dpi-desync-retrans obsolete
|
nfqws: --dpi-desync-retrans obsolete
|
||||||
nfqws: --qnum is mandatory, no more default queue 0
|
nfqws: --qnum is mandatory, no more default queue 0
|
||||||
|
|
||||||
|
v58
|
||||||
|
|
||||||
|
winws
|
||||||
|
@ -91,7 +91,7 @@ zapret не может пробить блокировку по IP адресу
|
|||||||
Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов
|
Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов
|
||||||
с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI,
|
с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI,
|
||||||
которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
|
которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
|
||||||
blockheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
|
blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
|
||||||
В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
|
В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
|
||||||
Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
|
Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
|
||||||
--dpi-desync-fooling, чтобы не сломать сайты на более коротких дистанциях.
|
--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.
|
Mainly OpenWRT targeted but also supports traditional Linux, FreeBSD, OpenBSD, partially MacOS.
|
||||||
|
|
||||||
|
Most features are also supported in Windows.
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
In the simplest case you are dealing with passive DPI. Passive DPI can read passthrough traffic,
|
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)
|
### Windows (WSL)
|
||||||
|
|
||||||
Using WSL (Windows subsystem for Linux) it's possible to run tpws in socks mode under rather new builds of
|
see docs/windows.eng.md
|
||||||
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.
|
|
||||||
|
|
||||||
### Other devices
|
### Other devices
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
zapret v.57
|
zapret v.58
|
||||||
|
|
||||||
English
|
English
|
||||||
-------
|
-------
|
||||||
@ -16,10 +16,12 @@ For english version refer to docs/readme.eng.txt
|
|||||||
Поддерживаются традиционные Linux системы, FreeBSD, OpenBSD, частично MacOS.
|
Поддерживаются традиционные 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
|
Описано в docs/bsd.txt
|
||||||
|
|
||||||
|
|
||||||
Windows (WSL)
|
Windows
|
||||||
-------------
|
-------
|
||||||
|
|
||||||
tpws в режиме socks можно запускать и под более-менее современными билдами windows 10 и windows server
|
Описано в docs/windows.txt
|
||||||
с установленным 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).
|
|
||||||
|
|
||||||
|
|
||||||
Другие прошивки
|
Другие прошивки
|
||||||
|
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
|
# 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
|
# bash and zsh do not do this
|
||||||
if exists bash; then
|
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
|
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
|
else
|
||||||
# find does not use its own shell exec
|
# 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
|
# 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)
|
UNAME=$(uname)
|
||||||
if [ "$UNAME" = "Linux" ]; then
|
unset PKTWS
|
||||||
ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb ppc"
|
case $UNAME in
|
||||||
elif [ "$UNAME" = "Darwin" ]; then
|
Linux)
|
||||||
ARCHLIST="my mac64"
|
ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb ppc"
|
||||||
elif [ "$UNAME" = "FreeBSD" ]; then
|
PKTWS=nfqws
|
||||||
ARCHLIST="my freebsd-x64"
|
;;
|
||||||
else
|
Darwin)
|
||||||
ARCHLIST="my"
|
ARCHLIST="my mac64"
|
||||||
fi
|
;;
|
||||||
|
FreeBSD)
|
||||||
|
ARCHLIST="my freebsd-x64"
|
||||||
|
PKTWS=dvtws
|
||||||
|
;;
|
||||||
|
CYGWIN*)
|
||||||
|
UNAME=CYGWIN
|
||||||
|
ARCHLIST="win64"
|
||||||
|
PKTWS=winws
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ARCHLIST="my"
|
||||||
|
esac
|
||||||
|
|
||||||
if [ "$1" = "getarch" ]; then
|
if [ "$1" = "getarch" ]; then
|
||||||
for arch in $ARCHLIST
|
for arch in $ARCHLIST
|
||||||
@ -77,12 +89,8 @@ else
|
|||||||
echo installing binaries ...
|
echo installing binaries ...
|
||||||
ccp $arch/ip2net ip2net
|
ccp $arch/ip2net ip2net
|
||||||
ccp $arch/mdig mdig
|
ccp $arch/mdig mdig
|
||||||
if [ "$UNAME" = "Linux" ]; then
|
[ -n "$PKTWS" ] && ccp $arch/$PKTWS nfq
|
||||||
ccp $arch/nfqws nfq
|
[ "$UNAME" = CYGWIN ] || ccp $arch/tpws tpws
|
||||||
else
|
|
||||||
ccp $arch/dvtws nfq
|
|
||||||
fi
|
|
||||||
ccp $arch/tpws tpws
|
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
echo $arch is NOT OK
|
echo $arch is NOT OK
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
||||||
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
||||||
|
CFLAGS_WIN = -static
|
||||||
LIBS =
|
LIBS =
|
||||||
LIBS_WIN = -lws2_32
|
LIBS_WIN = -lws2_32
|
||||||
SRC_FILES = ip2net.c qsort.c
|
SRC_FILES = ip2net.c qsort.c
|
||||||
@ -21,7 +22,7 @@ mac: $(SRC_FILES)
|
|||||||
rm -f ip2netx ip2neta
|
rm -f ip2netx ip2neta
|
||||||
|
|
||||||
win: $(SRC_FILES)
|
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:
|
clean:
|
||||||
rm -f ip2net *.o
|
rm -f ip2net *.o
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
||||||
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
||||||
|
CFLAGS_WIN = -static
|
||||||
LIBS = -lpthread
|
LIBS = -lpthread
|
||||||
LIBS_WIN = -lws2_32
|
LIBS_WIN = -lws2_32
|
||||||
SRC_FILES = *.c
|
SRC_FILES = *.c
|
||||||
@ -21,7 +22,7 @@ mac: $(SRC_FILES)
|
|||||||
rm -f mdigx mdiga
|
rm -f mdigx mdiga
|
||||||
|
|
||||||
win: $(SRC_FILES)
|
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:
|
clean:
|
||||||
rm -f mdig *.o
|
rm -f mdig *.o
|
||||||
|
@ -2,9 +2,10 @@ CC ?= gcc
|
|||||||
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3
|
||||||
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch
|
||||||
CFLAGS_MAC = -mmacosx-version-min=10.8
|
CFLAGS_MAC = -mmacosx-version-min=10.8
|
||||||
|
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||||
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
|
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
|
||||||
LIBS_BSD = -lz
|
LIBS_BSD = -lz
|
||||||
LIBS_CYGWIN = -lz
|
LIBS_CYGWIN = -lz -Lwindivert -lwindivert
|
||||||
SRC_FILES = *.c crypto/*.c
|
SRC_FILES = *.c crypto/*.c
|
||||||
|
|
||||||
all: nfqws
|
all: nfqws
|
||||||
@ -23,7 +24,7 @@ mac: $(SRC_FILES)
|
|||||||
rm -f dvtwsx dvtwsa
|
rm -f dvtwsx dvtwsa
|
||||||
|
|
||||||
cygwin:
|
cygwin:
|
||||||
$(CC) -s $(CFLAGS) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN)
|
$(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN)
|
||||||
|
|
||||||
clean:
|
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
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "darkmagic.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -8,10 +7,13 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "darkmagic.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
|
||||||
|
|
||||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||||
{
|
{
|
||||||
return htonl(ntohl(netorder_value)+cpuorder_increment);
|
return htonl(ntohl(netorder_value)+cpuorder_increment);
|
||||||
@ -642,6 +644,8 @@ const char *proto_name(uint8_t proto)
|
|||||||
return "udp";
|
return "udp";
|
||||||
case IPPROTO_ICMP:
|
case IPPROTO_ICMP:
|
||||||
return "icmp";
|
return "icmp";
|
||||||
|
case IPPROTO_ICMPV6:
|
||||||
|
return "icmp6";
|
||||||
case IPPROTO_IGMP:
|
case IPPROTO_IGMP:
|
||||||
return "igmp";
|
return "igmp";
|
||||||
case IPPROTO_ESP:
|
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 int rawsend_sock4=-1, rawsend_sock6=-1;
|
||||||
static bool b_bind_fix4=false, b_bind_fix6=false;
|
static bool b_bind_fix4=false, b_bind_fix6=false;
|
||||||
@ -1264,6 +1393,8 @@ nofix:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // not CYGWIN
|
||||||
|
|
||||||
bool rawsend_rp(const struct rawpacket *rp)
|
bool rawsend_rp(const struct rawpacket *rp)
|
||||||
{
|
{
|
||||||
return rawsend((struct sockaddr*)&rp->dst,rp->fwmark,rp->ifout,rp->packet,rp->len);
|
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)
|
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||||
{
|
{
|
||||||
#ifdef __FreeBSD__
|
if (!(verdict & VERDICT_NOCSUM))
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
{
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
// always fix csum for windivert. original can be partial or bad
|
||||||
#else
|
#ifndef __CYGWIN__
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
#ifdef __FreeBSD__
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
#endif
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||||
tcp_fix_checksum(tcphdr,transport_len,ip,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)
|
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr)
|
||||||
{
|
{
|
||||||
#ifdef __FreeBSD__
|
if (!(verdict & VERDICT_NOCSUM))
|
||||||
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
{
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
// always fix csum for windivert. original can be partial or bad
|
||||||
#else
|
#ifndef __CYGWIN__
|
||||||
// if original packet was tampered earlier it needs checksum fixed
|
#ifdef __FreeBSD__
|
||||||
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
|
// FreeBSD tend to pass ipv6 frames with wrong checksum
|
||||||
#endif
|
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
|
||||||
udp_fix_checksum(udphdr,transport_len,ip,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
|
#pragma once
|
||||||
|
|
||||||
#include "checksum.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/ip6.h>
|
#include <netinet/ip6.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <netinet/udp.h>
|
#include <netinet/udp.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "checksum.h"
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#include "windivert/windivert.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "packet_queue.h"
|
#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);
|
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
|
||||||
bool tcp_has_fastopen(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
|
// 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(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len);
|
||||||
bool rawsend_rp(const struct rawpacket *rp);
|
bool rawsend_rp(const struct rawpacket *rp);
|
||||||
// return trues if all packets were send successfully
|
// return trues if all packets were send successfully
|
||||||
bool rawsend_queue(struct rawpacket_tailhead *q);
|
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
|
// cleans up socket autocreated by rawsend
|
||||||
void rawsend_cleanup(void);
|
void rawsend_cleanup(void);
|
||||||
|
|
||||||
|
#ifdef BSD
|
||||||
int socket_divert(sa_family_t family);
|
int socket_divert(sa_family_t family);
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *proto_name(uint8_t proto);
|
const char *proto_name(uint8_t proto);
|
||||||
uint16_t family_from_proto(uint8_t l3proto);
|
uint16_t family_from_proto(uint8_t l3proto);
|
||||||
|
@ -265,3 +265,35 @@ time_t file_mod_time(const char *filename)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
|
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);
|
int fprint_localtime(FILE *F);
|
||||||
|
|
||||||
time_t file_mod_time(const char *filename);
|
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");
|
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)
|
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))
|
if (!rawsend_preinit(params.bind_fix4,params.bind_fix6))
|
||||||
goto exiterr;
|
goto exiterr;
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
sec_harden();
|
sec_harden();
|
||||||
|
|
||||||
if (params.droproot && !droproot(params.uid, params.gid))
|
if (params.droproot && !droproot(params.uid, params.gid))
|
||||||
goto exiterr;
|
goto exiterr;
|
||||||
|
|
||||||
print_id();
|
print_id();
|
||||||
|
#endif
|
||||||
|
|
||||||
signal(SIGHUP, onhup);
|
pre_desync();
|
||||||
signal(SIGUSR1, onusr1);
|
|
||||||
signal(SIGUSR2, onusr2);
|
|
||||||
|
|
||||||
desync_init();
|
|
||||||
|
|
||||||
fd = nfq_fd(h);
|
fd = nfq_fd(h);
|
||||||
|
|
||||||
@ -311,10 +319,7 @@ static int dvt_main(void)
|
|||||||
goto exiterr;
|
goto exiterr;
|
||||||
print_id();
|
print_id();
|
||||||
|
|
||||||
signal(SIGHUP, onhup);
|
pre_desync();
|
||||||
signal(SIGUSR1, onusr1);
|
|
||||||
|
|
||||||
desync_init();
|
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
@ -385,7 +390,75 @@ exiterr:
|
|||||||
return res;
|
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
|
#endif
|
||||||
" --daemon\t\t\t\t\t; daemonize\n"
|
" --daemon\t\t\t\t\t; daemonize\n"
|
||||||
" --pidfile=<filename>\t\t\t\t; write pid to file\n"
|
" --pidfile=<filename>\t\t\t\t; write pid to file\n"
|
||||||
|
#ifndef __CYGWIN__
|
||||||
" --user=<username>\t\t\t\t; drop root privs\n"
|
" --user=<username>\t\t\t\t; drop root privs\n"
|
||||||
" --uid=uid[:gid]\t\t\t\t; drop root privs\n"
|
" --uid=uid[:gid]\t\t\t\t; drop root privs\n"
|
||||||
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
" --bind-fix4\t\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n"
|
" --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"
|
" --bind-fix6\t\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n"
|
||||||
#endif
|
#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"
|
" --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=<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"
|
" --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"
|
" --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"
|
" --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
||||||
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||||
@ -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-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-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-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"
|
" --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",
|
|
||||||
CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP,
|
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)
|
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||||
DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT,
|
DPI_DESYNC_FWMARK_DEFAULT,DPI_DESYNC_FWMARK_DEFAULT,
|
||||||
#endif
|
#endif
|
||||||
@ -488,8 +574,7 @@ static void exithelp(void)
|
|||||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT,
|
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_UDP_DEFAULT,
|
||||||
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT,
|
DPI_DESYNC_MAX_FAKE_LEN, IPFRAG_TCP_DEFAULT,
|
||||||
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
BADSEQ_INCREMENT_DEFAULT, BADSEQ_ACK_INCREMENT_DEFAULT,
|
||||||
UDPLEN_INCREMENT_DEFAULT,
|
UDPLEN_INCREMENT_DEFAULT
|
||||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT
|
|
||||||
);
|
);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -580,12 +665,151 @@ bool parse_autottl(const char *s, autottl *t)
|
|||||||
return true;
|
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 main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int result, v;
|
int result, v;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
bool daemon = false;
|
bool daemon = false;
|
||||||
char pidfile[256];
|
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));
|
srandom(time(NULL));
|
||||||
|
|
||||||
@ -629,12 +853,14 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
LIST_INIT(¶ms.hostlist_files);
|
LIST_INIT(¶ms.hostlist_files);
|
||||||
LIST_INIT(¶ms.hostlist_exclude_files);
|
LIST_INIT(¶ms.hostlist_exclude_files);
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
if (can_drop_root()) // are we root ?
|
if (can_drop_root()) // are we root ?
|
||||||
{
|
{
|
||||||
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
params.uid = params.gid = 0x7FFFFFFF; // default uid:gid
|
||||||
params.droproot = true;
|
params.droproot = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const struct option long_options[] = {
|
const struct option long_options[] = {
|
||||||
{"debug",optional_argument,0,0}, // optidx=0
|
{"debug",optional_argument,0,0}, // optidx=0
|
||||||
@ -647,8 +873,13 @@ int main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
{"daemon",no_argument,0,0}, // optidx=2
|
{"daemon",no_argument,0,0}, // optidx=2
|
||||||
{"pidfile",required_argument,0,0}, // optidx=3
|
{"pidfile",required_argument,0,0}, // optidx=3
|
||||||
|
#ifndef __CYGWIN__
|
||||||
{"user",required_argument,0,0 }, // optidx=4
|
{"user",required_argument,0,0 }, // optidx=4
|
||||||
{"uid",required_argument,0,0 }, // optidx=5
|
{"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
|
{"wsize",required_argument,0,0}, // optidx=6
|
||||||
{"wssize",required_argument,0,0}, // optidx=7
|
{"wssize",required_argument,0,0}, // optidx=7
|
||||||
{"wssize-cutoff",required_argument,0,0},// optidx=8
|
{"wssize-cutoff",required_argument,0,0},// optidx=8
|
||||||
@ -663,7 +894,7 @@ int main(int argc, char **argv)
|
|||||||
#elif defined(SO_USER_COOKIE)
|
#elif defined(SO_USER_COOKIE)
|
||||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15
|
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15
|
||||||
#else
|
#else
|
||||||
{"disabled_argument_2",no_argument,0,0}, // optidx=15
|
{"disabled_argument_4",no_argument,0,0}, // optidx=15
|
||||||
#endif
|
#endif
|
||||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16
|
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16
|
||||||
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=17
|
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=17
|
||||||
@ -701,6 +932,12 @@ int main(int argc, char **argv)
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
{"bind-fix4",no_argument,0,0}, // optidx=48
|
{"bind-fix4",no_argument,0,0}, // optidx=48
|
||||||
{"bind-fix6",no_argument,0,0}, // optidx=49
|
{"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
|
#endif
|
||||||
{NULL,0,NULL,0}
|
{NULL,0,NULL,0}
|
||||||
};
|
};
|
||||||
@ -713,6 +950,7 @@ int main(int argc, char **argv)
|
|||||||
case 0: /* debug */
|
case 0: /* debug */
|
||||||
params.debug = !optarg || atoi(optarg);
|
params.debug = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
#ifndef __CYGWIN__
|
||||||
case 1: /* qnum or port */
|
case 1: /* qnum or port */
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
params.qnum = atoi(optarg);
|
params.qnum = atoi(optarg);
|
||||||
@ -733,6 +971,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 2: /* daemon */
|
case 2: /* daemon */
|
||||||
daemon = true;
|
daemon = true;
|
||||||
break;
|
break;
|
||||||
@ -740,6 +979,7 @@ int main(int argc, char **argv)
|
|||||||
strncpy(pidfile, optarg, sizeof(pidfile));
|
strncpy(pidfile, optarg, sizeof(pidfile));
|
||||||
pidfile[sizeof(pidfile) - 1] = '\0';
|
pidfile[sizeof(pidfile) - 1] = '\0';
|
||||||
break;
|
break;
|
||||||
|
#ifndef __CYGWIN__
|
||||||
case 4: /* user */
|
case 4: /* user */
|
||||||
{
|
{
|
||||||
struct passwd *pwd = getpwnam(optarg);
|
struct passwd *pwd = getpwnam(optarg);
|
||||||
@ -762,6 +1002,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 6: /* wsize */
|
case 6: /* wsize */
|
||||||
if (!parse_ws_scale_factor(optarg,¶ms.wsize,¶ms.wscale))
|
if (!parse_ws_scale_factor(optarg,¶ms.wsize,¶ms.wscale))
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -847,6 +1088,7 @@ int main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifndef __CYGWIN__
|
||||||
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||||
params.desync_fwmark = 0;
|
params.desync_fwmark = 0;
|
||||||
@ -861,6 +1103,7 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 16: /* dpi-desync-ttl */
|
case 16: /* dpi-desync-ttl */
|
||||||
params.desync_ttl = (uint8_t)atoi(optarg);
|
params.desync_ttl = (uint8_t)atoi(optarg);
|
||||||
break;
|
break;
|
||||||
@ -1069,8 +1312,10 @@ int main(int argc, char **argv)
|
|||||||
fprintf(stderr, "gzipped auto hostlists are not supported\n");
|
fprintf(stderr, "gzipped auto hostlists are not supported\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
|
#ifndef __CYGWIN__
|
||||||
if (params.droproot && chown(optarg, params.uid, -1))
|
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);
|
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))
|
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||||
{
|
{
|
||||||
@ -1113,8 +1358,10 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
fclose(F);
|
fclose(F);
|
||||||
|
#ifndef __CYGWIN__
|
||||||
if (params.droproot && chown(optarg, params.uid, -1))
|
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);
|
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));
|
strncpy(params.hostlist_auto_debuglog, optarg, sizeof(params.hostlist_auto_debuglog));
|
||||||
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
|
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 */
|
case 49: /* bind-fix6 */
|
||||||
params.bind_fix6 = true;
|
params.bind_fix6 = true;
|
||||||
break;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1142,6 +1431,34 @@ int main(int argc, char **argv)
|
|||||||
fprintf(stderr, "Need divert port (--port)\n");
|
fprintf(stderr, "Need divert port (--port)\n");
|
||||||
exit_clean(1);
|
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
|
#endif
|
||||||
|
|
||||||
// not specified - use desync_ttl value instead
|
// not specified - use desync_ttl value instead
|
||||||
@ -1157,7 +1474,8 @@ int main(int argc, char **argv)
|
|||||||
fprintf(stderr, "Include hostlist load failed\n");
|
fprintf(stderr, "Include hostlist load failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
if (*params.hostlist_auto_filename) NonEmptyHostlist(¶ms.hostlist);
|
if (*params.hostlist_auto_filename)
|
||||||
|
NonEmptyHostlist(¶ms.hostlist);
|
||||||
if (!LoadExcludeHostLists())
|
if (!LoadExcludeHostLists())
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Exclude hostlist load failed\n");
|
fprintf(stderr, "Exclude hostlist load failed\n");
|
||||||
@ -1179,6 +1497,8 @@ int main(int argc, char **argv)
|
|||||||
result = nfq_main();
|
result = nfq_main();
|
||||||
#elif defined(BSD)
|
#elif defined(BSD)
|
||||||
result = dvt_main();
|
result = dvt_main();
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
result = win_main(windivert_filter);
|
||||||
#else
|
#else
|
||||||
#error unsupported OS
|
#error unsupported OS
|
||||||
#endif
|
#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];
|
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;
|
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;
|
int udplen_increment;
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
bool droproot;
|
bool droproot;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
#endif
|
||||||
|
|
||||||
strpool *hostlist, *hostlist_exclude;
|
strpool *hostlist, *hostlist_exclude;
|
||||||
struct str_list_head hostlist_files, hostlist_exclude_files;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
#else // __linux__
|
|
||||||
|
|
||||||
|
#endif // __linux__
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
|
||||||
|
#ifndef __linux__
|
||||||
bool sec_harden(void)
|
bool sec_harden(void)
|
||||||
{
|
{
|
||||||
// noop
|
// noop
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif // __linux__
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool can_drop_root(void)
|
bool can_drop_root(void)
|
||||||
{
|
{
|
||||||
@ -329,6 +330,7 @@ void print_id(void)
|
|||||||
{
|
{
|
||||||
int i,N;
|
int i,N;
|
||||||
gid_t g[128];
|
gid_t g[128];
|
||||||
|
|
||||||
printf("Running as UID=%u GID=",getuid());
|
printf("Running as UID=%u GID=",getuid());
|
||||||
N=getgroups(sizeof(g)/sizeof(*g),g);
|
N=getgroups(sizeof(g)/sizeof(*g),g);
|
||||||
if (N>0)
|
if (N>0)
|
||||||
@ -341,6 +343,9 @@ void print_id(void)
|
|||||||
printf("%u\n",getgid());
|
printf("%u\n",getgid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void daemonize(void)
|
void daemonize(void)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
|
@ -52,9 +52,12 @@ bool dropcaps(void);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
bool sec_harden(void);
|
bool sec_harden(void);
|
||||||
bool can_drop_root(void);
|
bool can_drop_root(void);
|
||||||
bool droproot(uid_t uid, gid_t gid);
|
bool droproot(uid_t uid, gid_t gid);
|
||||||
void print_id(void);
|
void print_id(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
void daemonize(void);
|
void daemonize(void);
|
||||||
bool writepid(const char *filename);
|
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;
|
struct stat st;
|
||||||
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
|
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);
|
int fprint_localtime(FILE *F);
|
||||||
|
|
||||||
time_t file_mod_time(const char *filename);
|
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 <time.h>
|
||||||
#include "tpws.h"
|
#include "tpws.h"
|
||||||
#include "pools.h"
|
#include "pools.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
#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;
|
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 params_s
|
||||||
{
|
{
|
||||||
struct bind_s binds[MAX_BINDS];
|
struct bind_s binds[MAX_BINDS];
|
||||||
|
@ -1530,37 +1530,3 @@ ex:
|
|||||||
if (resolve_pipe[1]) close(resolve_pipe[1]);
|
if (resolve_pipe[1]) close(resolve_pipe[1]);
|
||||||
return retval;
|
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 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