Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-14 06:13:09 +00:00

32 Commits

Author SHA1 Message Date
bol-van
847e689bfb AI fixes 2026-02-17 09:35:09 +03:00
bol-van
287527092a remove debug message 2026-02-17 09:15:53 +03:00
bol-van
a9514f39f5 update docs 2026-02-16 20:54:18 +03:00
bol-van
4b7ff505e4 nfqws2: old kernels compat 2026-02-16 20:51:39 +03:00
bol-van
2120264e0b AI and manual fixes 2026-02-16 19:45:58 +03:00
bol-van
178bced5f3 update docs 2026-02-16 14:55:31 +03:00
bol-van
ff78968807 nfqws2: ensure old toolchains do not break 2026-02-16 12:01:08 +03:00
bol-van
e4535d2646 nfqws2: loongarch64 compile fix 2026-02-16 11:51:43 +03:00
bol-van
7c60ad3a7a AI fixes 2026-02-16 10:47:50 +03:00
bol-van
a621edf898 AI fixes 2026-02-15 09:40:54 +03:00
bol-van
2809f8d7e4 update docs 2026-02-14 18:16:57 +03:00
bol-van
97819327cd nfqws2: remember absolute paths 2026-02-14 18:10:26 +03:00
bol-van
eb9a1e9f6b nfqws2: --chdir 2026-02-14 16:08:01 +03:00
bol-van
6f6850707a zapret-lib: tls_dissect abort 2 loops if data is corrupt 2026-02-14 15:30:59 +03:00
bol-van
f702865311 AI fixes 2026-02-14 13:19:48 +03:00
bol-van
6447081a01 winws2: optimize signal handling in windivert_recv 2026-02-14 11:36:00 +03:00
bol-van
e4e513ec66 github: stronger gz and zip compression 2026-02-13 17:38:22 +03:00
bol-van
47630450bd AI fixes 2026-02-13 16:49:42 +03:00
bol-van
e4129fec63 github: upx 5.1.0 2026-02-13 13:35:55 +03:00
bol-van
f71ba91e7c remove no-unwind from makefiles 2026-02-13 10:59:24 +03:00
bol-van
59e6603b83 dont use no-unwind to prevent crashes 2026-02-13 10:34:16 +03:00
bol-van
14a061859f change toolchain, riscv64 2026-02-13 09:11:51 +03:00
bol-van
9aaa419f68 nfqws2: fix fread inf loop 2026-02-12 11:54:12 +03:00
bol-van
d5231bc4fc nfqws2: allow any size iv_len in aes_gcm 2026-02-11 15:42:23 +03:00
bol-van
35cebfba73 winws2: use -msse only for luajit 2026-02-11 14:09:55 +03:00
bol-van
811d16054b update docs 2026-02-11 14:05:29 +03:00
bol-van
a9ee072a14 github: cygwin lto 2026-02-11 14:01:24 +03:00
bol-van
1dbf5ecfe6 optimize exe size 2026-02-11 13:18:14 +03:00
bol-van
b210db168f nfqws2: bsd compile fixes 2026-02-11 13:05:45 +03:00
bol-van
5306a043d0 AI fixes 2026-02-11 11:26:20 +03:00
bol-van
b375a94036 update docs 2026-02-11 11:22:53 +03:00
bol-van
8b2bff4187 AI fixes 2026-02-11 11:03:27 +03:00
30 changed files with 530 additions and 287 deletions

View File

@@ -26,32 +26,20 @@ jobs:
tool: aarch64-unknown-linux-musl
- arch: arm
tool: arm-unknown-linux-musleabi
# - arch: armhf
# tool: arm-unknown-linux-musleabihf
# - arch: armv7
# tool: armv7-unknown-linux-musleabi
# - arch: armv7hf
# tool: armv7-unknown-linux-musleabihf
# - arch: mips64el
# tool: mips64el-unknown-linux-musl
- arch: mips64
tool: mips64-unknown-linux-musl
# - arch: mipsel
# tool: mipsel-unknown-linux-musl
- arch: mipselsf
tool: mipsel-unknown-linux-muslsf
# - arch: mips
# tool: mips-unknown-linux-musl
- arch: mipssf
tool: mips-unknown-linux-muslsf
# - arch: ppc64
# tool: powerpc64-unknown-linux-musl
- arch: ppc
tool: powerpc-unknown-linux-musl
- arch: x86
tool: i586-unknown-linux-musl
- arch: x86_64
tool: x86_64-unknown-linux-musl
- arch: riscv64
tool: riscv64-unknown-linux-musl
- arch: lexra
tool: mips-linux
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
@@ -69,7 +57,7 @@ jobs:
env:
ARCH: ${{ matrix.arch }}
TOOL: ${{ matrix.tool }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'bol-van/musl-cross' }}
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
run: |
sudo dpkg --add-architecture i386
@@ -98,6 +86,8 @@ jobs:
LUAJIT_VER: 2.1
LUAJIT_RELEASE: 2.1-20250826
LUAJIT_LUAVER: 5.1
MINSIZE: -flto=auto -ffunction-sections -fdata-sections
LDMINSIZE: -Wl,--gc-sections -flto=auto
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export CC="$TARGET-gcc"
@@ -107,13 +97,19 @@ jobs:
export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=$RUNNER_TEMP
if [ "$ARCH" = lexra ]; then
OPTIMIZE=-Os
else
OPTIMIZE=-Oz
fi
MINSIZE="$OPTIMIZE $MINSIZE"
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == riscv64 ]] || [[ "$ARCH" == x86 ]] ; then
# use classic lua
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
(
cd lua-${LUA_RELEASE}
make CC=$CC CFLAGS="-Os -flto=auto $CFLAGS" linux -j$(nproc)
make CC=$CC AR="$AR rc" CFLAGS="$MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$(nproc)
make install INSTALL_TOP=$DEPS_DIR INSTALL_BIN=$DEPS_DIR/bin INSTALL_INC=$DEPS_DIR/include/lua${LUA_VER} INSTALL_LIB=$DEPS_DIR/lib
)
LJIT=0
@@ -131,7 +127,7 @@ jobs:
esac
(
cd luajit2-*
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -s -flto=auto $CFLAGS" -j$(nproc)
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
make install PREFIX= DESTDIR=$DEPS_DIR
)
LJIT=1
@@ -147,7 +143,8 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto $CFLAGS" \
CFLAGS="$MINSIZE $CFLAGS" \
LDFLAGS="$LDMINSIZE $LDFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -159,7 +156,7 @@ jobs:
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
(
cd zlib-*
CFLAGS="-Os -flto=auto $CFLAGS" \
CFLAGS="$MINSIZE $CFLAGS" \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -170,6 +167,7 @@ jobs:
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
# zapret2
OPTIMIZE=$OPTIMIZE \
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
make -C zapret2 LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc)
@@ -220,6 +218,8 @@ jobs:
LUAJIT_VER: 2.1
LUAJIT_RELEASE: 2.1-20250826
LUAJIT_LUAVER: 5.1
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
LDMINSIZE: -Wl,--gc-sections -flto=auto
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
@@ -242,7 +242,7 @@ jobs:
esac
(
cd luajit2-*
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -flto=auto $CFLAGS" -j$(nproc)
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
make install PREFIX= DESTDIR=$DEPS_DIR
)
LJIT=1
@@ -258,7 +258,8 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
CFLAGS="$MINSIZE -Wno-implicit-function-declaration $CFLAGS" \
LDFLAGS="$LDMINSIZE $LDFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -314,12 +315,14 @@ jobs:
TARGET: ${{ matrix.target }}
ARCH: ${{ matrix.arch }}
CC: ${{ matrix.target }}-freebsd11-clang
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
LDMINSIZE: -Wl,--gc-sections -flto=auto
run: |
wget -qO- https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
(
cd luajit2-*
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC CFLAGS="-Os -flto=auto $CFLAGS"
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
make install PREFIX= DESTDIR=$DEPS_DIR
)
@@ -390,7 +393,7 @@ jobs:
uses: cygwin/cygwin-install-action@v4
with:
platform: ${{ matrix.arch }}
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || null }}
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/2022/11/23/063457' }}
check-sig: 'false'
packages: >-
gcc-core
@@ -424,13 +427,15 @@ jobs:
- name: Build luajit
env:
LUAJIT_RELEASE: 2.1-20250826
MINSIZE: -Os -flto=auto -ffunction-sections -fdata-sections
LDMINSIZE: -Wl,--gc-sections -flto=auto
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
run: >-
export MAKEFLAGS=-j$(nproc) &&
wget -q https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz &&
tar -xzf v${LUAJIT_RELEASE}.tar.gz &&
rm -f v${LUAJIT_RELEASE}.tar.gz &&
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI CFLAGS="-Os -s" &&
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS="-DLUAJIT_DISABLE_FFI -ffat-lto-objects" TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" &&
make -C luajit2-${LUAJIT_RELEASE} install
- name: Build winws
@@ -488,7 +493,7 @@ jobs:
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
version: v4.2.4
version: v5.1.0
- name: Prepare binaries
shell: bash
@@ -532,6 +537,7 @@ jobs:
*-linux-mipselsf ) run_dir linux-mipsel ;;
*-linux-mipssf ) run_dir linux-mips ;;
*-linux-ppc ) run_dir linux-ppc ;;
*-linux-riscv64 ) run_dir linux-riscv64 ;;
*-linux-x86 ) run_dir linux-x86 ;;
*-linux-x86_64 ) run_dir linux-x86_64 ;;
*-linux-lexra ) run_dir linux-lexra ;;
@@ -546,8 +552,8 @@ jobs:
run: |
rm -rf ${{ env.repo_dir }}/.git*
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}.tar.gz
zip -9qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
(
cd ${{ env.repo_dir }}
rm -rf binaries/{android*,freebsd*,win*} \
@@ -555,7 +561,7 @@ jobs:
nfq2 ip2net mdig docs Makefile
pigz -11 lua/*.lua
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}-openwrt-embedded.tar.gz
- name: Upload release assets
uses: softprops/action-gh-release@v2

View File

@@ -152,7 +152,7 @@ v0.8.1
* zapret-antidpi: http_unixeol
* blockcheck2: http_unixeol test
0.8.2
v0.8.2
* nfqws2: do not start if NFQWS2_COMPAT_VER unexpected
* nfqws2: cache dns response IP addresses if --ipcache-hostname enabled
@@ -163,14 +163,14 @@ v0.8.1
* winws2: --wf-filter-loopback
* blockcheck2: NOTEST_MISC_HTTP[S], NOTEST_SYNDATA_HTTP[S]
0.8.3
v0.8.3
* nfqws2, zapret-lib: gzip compression and decompression
* nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now
* init.d: 99-lan-filter custom script
* mdig: --eagain, --eagain-delay
0.8.4
v0.8.4
* winws2: fix loopback large packets processing (up to 64K)
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
@@ -180,7 +180,7 @@ v0.8.1
* nfqws2: gracefully shutdown on SIGINT and SIGTERM
* nfqws2: harden wireguard detection. do not detect if reserved bytes 1..3 != 0
0.8.5
v0.8.5
* nfqws2: do not require / in the beginning of URI in http
* zapret-lib: rawsend_dissect_segmented support URG
@@ -190,13 +190,13 @@ v0.8.1
* zapret-lib: tcp_nop_del
* blockcheck2: tcp_nop_del in SYN packets with md5 in openbsd
0.8.6
v0.8.6
* winws2, blockcheck2: allow multiple instances in windows, linux, freebsd (not openbsd)
* nfqws2: fix critical bug - wrong ipv6 dissection
* zapret-auto: fix standard_failure_detector http redirect regression
0.9.0
v0.9.0
* nfqws2: removed hard check for host: presence in http_req
* nfqws2: file open test before destroying in-memory content of ipset/hostlist
@@ -215,25 +215,36 @@ v0.8.1
* winws2: use windivert bulk mode
* nfqws2: template free import
0.9.1
v0.9.1
* nfqws2: 'stat', 'clock_getfloattime' luacalls
* nfqws2: bcryptorandom normalize behavior when system entropy is low. prevent blocks
* nfqws2: --new[=name]
* winws2: fix not setting signal handlers
0.9.2
v0.9.2
nfqws2: bt and utp_bt protocol detectors
nfqws2: localtime,gmtime,timelocal,timegm luacalls
winws2: load wlanapi.dll dynamically only if needed
winws2: fixed lost windivert deinit on logical network disappear
* nfqws2: bt and utp_bt protocol detectors
* nfqws2: localtime,gmtime,timelocal,timegm luacalls
* winws2: load wlanapi.dll dynamically only if needed
* winws2: fixed lost windivert deinit on logical network disappear
0.9.3
v0.9.3
nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
zapret-auto: per_instance_condition orchestrator
zapret-auto: "instances" argument in condition orchestrator
zapret-auto: cond_tcp_has_ts, cond_lua iff functions
zapret-lib: replay_execution_plan and plan_clear max parameter
init.d: use bitmap:port ipset for standard dports
* nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
* zapret-auto: per_instance_condition orchestrator
* zapret-auto: "instances" argument in condition orchestrator
* zapret-auto: cond_tcp_has_ts, cond_lua iff functions
* zapret-lib: replay_execution_plan and plan_clear max parameter
* init.d: use bitmap:port ipset for standard dports
* github: reduce executables files size
* install_bin: added linux-riscv64 scan dir
* github actions: added linux-riscv64 arch
v0.9.4
* github actions: update upx to 5.1.0. use upx for linux-riscv5
* github actions: stronger zip and gz compression
* nfqws2: --chdir
* nfqws2: fixed wrong scale factor application to winsize
* nfqws2: very old kernels compat

View File

@@ -11,9 +11,9 @@ setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouc
4) install and compile luajit from here : https://github.com/openresty/luajit2
download latest releast, unpack, cd to it's directory
download latest release, unpack, cd to it's directory
make BUILDMODE=static CFLAGS="-Os"
make BUILDMODE=static CFLAGS="-Os -DLUAJIT_DISABLE_FFI -ffat-lto-objects -flto=auto -ffunction-sections -fdata-sections -fvisibility=hidden"
make install
5) cd to %ZAPRET_BASE%/nfq2
@@ -32,5 +32,5 @@ Choose version 2.2.2 for Windows 10 and 2.2.0 for Windows 7.
8) Copy cygwin1.dll, winws2.exe, windivert.dll and windivert64.sys to one folder.
9) Run winws2.exe from cmd.exe running as administrator.
winws will not run from cygwin shell with cygwin1.dll copy in it's folder.
winws will not run without cygwin1.dll outside of cygwin shell.
winws2 will not run from cygwin shell with cygwin1.dll copy in it's folder.
winws2 will not run without cygwin1.dll outside of cygwin shell.

View File

@@ -637,6 +637,7 @@ General parameters for all versions - nfqws2, dvtws2, winws2.
--comment=any_text ; any text. ignored
--intercept=0|1 ; allow interception. 0 - no, 1 - yes. If 0 lua-init scripts are executed then process exits. NFQUEUE is not initialized.
--daemon ; detach from the console (daemonize)
--chdir[=path] ; change current directory. if no path specified use the executable file directory - EXEDIR
--pidfile=<filename> ; write PID to a file
--ctrack-timeouts=S:E:F[:U] ; conntrack timeouts for tcp stages (SYN, ESTABLISHED, FIN) and for udp
--ctrack-disable=[0|1] ; 1 disables conntrack

View File

@@ -696,6 +696,7 @@ nfqws2 использует стандартный парсер getopt_long_only
--comment=any_text ; любой текст. игнорируется
--intercept=0|1 ; разрешить перехват. 0 - нет, 1 - да. при 0 выполняются lua-init скрипты и процесс завершается, перехват не включается, очередь NFQUEUE не инициализируется
--daemon ; отключиться от консоли (демонизироваться)
--chdir[=path] ; сменить текущую директорию. если нет path, выбирается путь исполняемого файла - EXEDIR
--pidfile=<filename> ; запись PID в файл
--ctrack-timeouts=S:E:F[:U] ; таймауты conntrack для стадий tcp SYN, ESTABLISHED, FIN и для udp
--ctrack-disable=[0|1] ; 1 отключает conntrack

View File

@@ -48,7 +48,7 @@ zapret2 является дальнейшим развитием проекта
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позиции и т.д.
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
и с большей гибкостью.

View File

@@ -157,7 +157,7 @@ fi
unset PKTWS
case $UNAME in
Linux)
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc linux-riscv64"
PKTWS=nfqws2
;;
FreeBSD)

View File

@@ -477,7 +477,7 @@ function per_instance_condition(ctx, desync)
if not instance then break end
if instance.arg.cond then
if type(_G[instance.arg.cond])~="function" then
error(name..": invalid 'iff' function '"..instance.arg.cond.."'")
error("per_instance_condition: invalid 'iff' function '"..instance.arg.cond.."'")
end
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
verdict = plan_instance_execute(desync, verdict, instance)

View File

@@ -434,7 +434,7 @@ function string2hex(s)
return ss
end
function has_nonprintable(s)
return s:match("[^ -\\r\\n\\t]")
return s:match("[^ -\r\n\t]")
end
function make_readable(v)
if type(v)=="string" then
@@ -805,9 +805,9 @@ function autottl(incoming_ttl, attl)
if incoming_ttl>223 then
orig=255
elseif incoming_ttl<128 and incoming_ttl>96 then
elseif incoming_ttl<=128 and incoming_ttl>96 then
orig=128
elseif incoming_ttl<64 and incoming_ttl>32 then
elseif incoming_ttl<=64 and incoming_ttl>32 then
orig=64
else
return nil
@@ -1161,16 +1161,15 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
local pos=1
local len
local payload=discopy.payload
while pos <= #payload do
len = #payload - pos + 1
if len > max_data then len = max_data end
if oob then
if urp>=pos and urp<(pos+len)then
discopy.tcp.th_flags = bitor(dis.tcp.th_flags, TH_URG)
discopy.tcp.th_flags = bitor(discopy.tcp.th_flags, TH_URG)
discopy.tcp.th_urp = urp-pos+1
else
discopy.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(TH_URG))
discopy.tcp.th_flags = bitand(discopy.tcp.th_flags, bitnot(TH_URG))
discopy.tcp.th_urp = 0
end
end
@@ -2125,7 +2124,7 @@ function is_tls_record(tls, offset, ctype, partialOK)
if not tls then return false end
if not offset then offset=1 end
if (#tls-offset+1)<6 or (ctype and ctype~=tls_record_type(tls, offset)) then return false end
if (#tls-offset+1)<5 or (ctype and ctype~=tls_record_type(tls, offset)) then return false end
local f2 = u16(tls, offset+1)
return f2>=TLS_VER_SSL30 and f2<=TLS_VER_TLS12 and (partialOK or tls_record_full(tls, offset))
@@ -2164,12 +2163,12 @@ function is_tls_handshake(tls, offset, htype, partialOK)
if not TLS_HANDSHAKE_TYPE_NAMES[typ] then return false end
if typ==TLS_HANDSHAKE_TYPE_CLIENT or typ==TLS_HANDSHAKE_TYPE_SERVER then
-- valid tls versions
if (#tls-offset+1)<6 then return false end
local f2 = u16(tls,offset+4)
if f2<TLS_VER_SSL30 or f2>TLS_VER_TLS12 then return false end
end
-- length fits to data buffer
return partialOK or tls_handshake_full(tls, offset)
end
function is_tls_hello(tls, offset, partialOK)
return is_tls_handshake(tls, offset, TLS_HANDSHAKE_TYPE_CLIENT, partialOK) or is_tls_handshake(tls, offset, TLS_HANDSHAKE_TYPE_SERVER, partialOK)
@@ -2448,6 +2447,11 @@ function tls_dissect(tls, offset, partialOK)
if typ==TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC then
encrypted = true
elseif typ==TLS_RECORD_TYPE_HANDSHAKE and not encrypted then
-- need 4 bytes for handshake type and 24-bit length
if (#tls-off+1)<9 then
if not partialOK then return end
break
end
local htyp = tls_handshake_type(tls, off + 5)
tdis.rec[#tdis.rec].htype = htyp
if not tdis.handshake then tdis.handshake = {} end
@@ -2463,7 +2467,7 @@ function tls_dissect(tls, offset, partialOK)
-- next record
if not is_tls_record(tls, off + 5 + len, nil, partialOK) or tls_record_type(tls, off + 5 + len) ~= typ then
if not partialOK then return end
break
goto endrec
end
off = off + 5 + len
len = tls_record_data_len(tls, off)
@@ -2473,14 +2477,15 @@ function tls_dissect(tls, offset, partialOK)
-- next record
off = off + 5 + len
end
::endrec::
if tdis.handshake then
for htyp, handshake in pairs(tdis.handshake) do
if (handshake.type == TLS_HANDSHAKE_TYPE_CLIENT or handshake.type == TLS_HANDSHAKE_TYPE_SERVER) then
tls_dissect_handshake(handshake, 1, partialOK)
tls_dissect_handshake(handshake, partialOK)
end
end
elseif is_tls_handshake(tls, offset, nil, partialOK) then
elseif not tdis.rec and is_tls_handshake(tls, offset, nil, partialOK) then
local htyp = tls_handshake_type(tls, offset)
tdis.handshake = { [htyp] = { type = htyp, name = TLS_HANDSHAKE_TYPE_NAMES[htyp], data = string.sub(tls, offset, #tls) } }
tls_dissect_handshake(tdis.handshake[htyp], partialOK)

View File

@@ -90,10 +90,9 @@ function test_hkdf()
local ikm = brandom(math.random(5,10))
for ninfo=1,nblob do
local info = brandom(math.random(5,10))
local okm_prev
for k,sha in pairs({"sha256","sha224"}) do
for k,okml in pairs({8, 16, 50}) do
local okm_prev
for k,okml in pairs({8, 16, 50}) do
local okm
print("* hkdf "..sha)
print("salt: "..string2hex(salt))
@@ -107,7 +106,6 @@ function test_hkdf()
print("duplicate okm !")
end
okms[okm] = true
test_assert(not okm_prev or okm_prev==string.sub(okm, 1, #okm_prev))
okm_prev = okm
end

View File

@@ -1,7 +1,9 @@
CC ?= cc
PKG_CONFIG ?= pkg-config
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
OPTIMIZE ?= -Oz
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
CFLAGS += -std=gnu99 -s $(OPTIMIZE) $(MINSIZE) -Wno-address-of-packed-member
LDFLAGS += -flto=auto -Wl,--gc-sections
LIBS = -lz -lm
SRC_FILES = *.c crypto/*.c

View File

@@ -1,12 +1,15 @@
CC ?= cc
PKG_CONFIG ?= pkg-config
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE)
CFLAGS_LINUX = -Wno-alloc-size-larger-than
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
CFLAGS_CYGWIN32 =
CFLAGS_UBSAN = -fsanitize=undefined,alignment -fno-sanitize-recover=undefined,alignment
LDFLAGS += -flto=auto -Wl,--gc-sections
LDFLAGS_ANDROID = -llog
LIBS =
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
@@ -27,6 +30,7 @@ ifeq ($(LUA_JIT),1)
LUAJIT_VER?=2.1
LUAJIT_LUA_VER?=5.1
LUA_PKG:=luajit
CFLAGS_CYGWIN32 = -msse2 -mfpmath=sse
$(info trying luajit $(LUAJIT_VER) lua $(LUAJIT_LUA_VER))
@@ -149,9 +153,9 @@ bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_BSD) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_BSD) $(LDFLAGS)
cygwin64:
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64) $(LDFLAGS)
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(RES_CYGWIN64) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(LDFLAGS)
cygwin32:
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS)
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) $(CFLAGS_CYGWIN32) -o winws2 $(SRC_FILES) $(RES_CYGWIN32) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(LDFLAGS)
cygwin: cygwin64
clean:

View File

@@ -140,8 +140,17 @@ static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
scale = tcp_find_scale_factor(dis->tcp);
mss = tcp_find_mss(dis->tcp);
direct->winsize_calc = direct->winsize = ntohs(dis->tcp->th_win);
if (t->pos.state == SYN)
{
// scale and mss only valid in syn packets
scale = tcp_find_scale_factor(dis->tcp);
if (scale != SCALE_NONE) direct->scale = scale;
direct->mss = tcp_find_mss(dis->tcp);
}
else if (direct->scale != SCALE_NONE)
// apply scale only outside of the SYN stage
direct->winsize_calc <<= direct->scale;
direct->seq_last = ntohl(dis->tcp->th_seq);
direct->pos = direct->seq_last + dis->len_payload;
@@ -154,10 +163,6 @@ static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *
if (!((direct->pos - direct->uppos) & 0x80000000))
direct->uppos = direct->pos;
}
direct->winsize_calc = direct->winsize = ntohs(dis->tcp->th_win);
if (scale != SCALE_NONE) direct->scale = scale;
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
if (mss && !direct->mss) direct->mss = mss;
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
direct->rseq_over_2G = true;
@@ -347,7 +352,7 @@ void ConntrackPoolDump(const t_conntrack *p)
{
t_conntrack_pool *t, *tmp;
time_t tnow;
char sa1[40], sa2[40];
char sa1[INET6_ADDRSTRLEN], sa2[INET6_ADDRSTRLEN];
if (!(tnow=boottime())) return;
HASH_ITER(hh, p->pool, t, tmp) {

View File

@@ -258,8 +258,6 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
size_t use_len; // byte count to process, up to 16 bytes
size_t i; // local loop iterator
if (iv_len!=12) return -1;
// since the context might be reused under the same key
// we zero the working buffers for this next new process
memset(ctx->y, 0x00, sizeof(ctx->y));
@@ -447,7 +445,7 @@ int gcm_crypt_and_tag(
prepare the gcm context with the keying material, we simply
invoke each of the three GCM sub-functions in turn...
*/
if (iv_len!=12 || tag_len>16) return -1;
if (tag_len>16) return -1;
int ret;
if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret;
@@ -483,26 +481,28 @@ int gcm_auth_decrypt(
uchar check_tag[16]; // the tag generated and returned by decryption
int diff; // an ORed flag to detect authentication errors
size_t i; // our local iterator
int ret;
if (iv_len!=12 || tag_len>16) return -1;
if (tag_len>16) return -1;
/*
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
(which is an identical XORing to reverse the previous one)
and also to re-generate the matching authentication tag
*/
gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len,
input, output, length, check_tag, tag_len);
if ((ret = gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len))) return ret;
// now we verify the authentication tag in 'constant time'
for (diff = 0, i = 0; i < tag_len; i++)
diff |= tag[i] ^ check_tag[i];
if (diff != 0) { // see whether any bits differed?
if (diff)
{
// see whether any bits differed?
memset(output, 0, length); // if so... wipe the output data
return(GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
}
return(0);
return 0;
}
/******************************************************************************

View File

@@ -60,9 +60,9 @@ int hkdf(SHAversion whichSha,
uint8_t okm[], size_t okm_len)
{
uint8_t prk[USHAMaxHashSize];
return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) ||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
info_len, okm, okm_len);
int ret;
if ((ret=hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk))) return ret;
return hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, info_len, okm, okm_len);
}
/*
@@ -146,6 +146,7 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
size_t hash_len, N;
unsigned char T[USHAMaxHashSize];
size_t Tlen, where, i;
int ret;
if (info == 0) {
info = (const unsigned char *)"";
@@ -164,12 +165,11 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
for (i = 1; i <= N; i++) {
HMACContext context;
unsigned char c = i;
int ret = hmacReset(&context, whichSha, prk, prk_len) ||
hmacInput(&context, T, Tlen) ||
hmacInput(&context, info, info_len) ||
hmacInput(&context, &c, 1) ||
hmacResult(&context, T);
if (ret != shaSuccess) return ret;
if ((ret=hmacReset(&context, whichSha, prk, prk_len))) return ret;
if ((ret=hmacInput(&context, T, Tlen))) return ret;
if ((ret=hmacInput(&context, info, info_len))) return ret;
if ((ret=hmacInput(&context, &c, 1))) return ret;
if ((ret=hmacResult(&context, T))) return ret;
memcpy(okm + where, T,
(i != N) ? hash_len : (okm_len - where));
where += hash_len;
@@ -321,9 +321,8 @@ int hkdfResult(HKDFContext *context,
if (!okm) return context->Corrupted = shaBadParam;
if (!prk) prk = prkbuf;
ret = hmacResult(&context->hmacContext, prk) ||
hkdfExpand(context->whichSha, prk, context->hashSize, info,
info_len, okm, okm_len);
if (!(ret = hmacResult(&context->hmacContext, prk)))
ret = hkdfExpand(context->whichSha, prk, context->hashSize, info, info_len, okm, okm_len);
context->Computed = 1;
return context->Corrupted = ret;
}

View File

@@ -49,9 +49,10 @@ int hmac(SHAversion whichSha,
uint8_t digest[USHAMaxHashSize])
{
HMACContext context;
return hmacReset(&context, whichSha, key, key_len) ||
hmacInput(&context, message_array, length) ||
hmacResult(&context, digest);
int ret;
if ((ret=hmacReset(&context, whichSha, key, key_len))) return ret;
if ((ret=hmacInput(&context, message_array, length))) return ret;
return hmacResult(&context, digest);
}
/*
@@ -101,10 +102,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
*/
if (key_len > blocksize) {
USHAContext tcontext;
int err = USHAReset(&tcontext, whichSha) ||
USHAInput(&tcontext, key, key_len) ||
USHAResult(&tcontext, tempkey);
if (err != shaSuccess) return err;
if ((ret=USHAReset(&tcontext, whichSha)) || (ret=USHAInput(&tcontext, key, key_len)) || (ret=USHAResult(&tcontext, tempkey)))
return ret;
key = tempkey;
key_len = hashsize;
@@ -134,9 +133,9 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
/* perform inner hash */
/* init context for 1st pass */
ret = USHAReset(&context->shaContext, whichSha) ||
if (!(ret = USHAReset(&context->shaContext, whichSha)))
/* and start with inner pad */
USHAInput(&context->shaContext, k_ipad, blocksize);
ret = USHAInput(&context->shaContext, k_ipad, blocksize);
return context->Corrupted = ret;
}
@@ -197,8 +196,7 @@ int hmacFinalBits(HMACContext *context,
if (context->Corrupted) return context->Corrupted;
if (context->Computed) return context->Corrupted = shaStateError;
/* then final bits of datagram */
return context->Corrupted =
USHAFinalBits(&context->shaContext, bits, bit_count);
return context->Corrupted = USHAFinalBits(&context->shaContext, bits, bit_count);
}
/*
@@ -229,21 +227,16 @@ int hmacResult(HMACContext *context, uint8_t *digest)
/* finish up 1st pass */
/* (Use digest here as a temporary buffer.) */
ret =
USHAResult(&context->shaContext, digest) ||
if (!(ret=USHAResult(&context->shaContext, digest)) &&
/* perform outer SHA */
/* init context for 2nd pass */
USHAReset(&context->shaContext, context->whichSha) ||
!(ret=USHAReset(&context->shaContext, context->whichSha)) &&
/* start with outer pad */
USHAInput(&context->shaContext, context->k_opad,
context->blockSize) ||
!(ret=USHAInput(&context->shaContext, context->k_opad, context->blockSize)) &&
/* then results of 1st hash */
USHAInput(&context->shaContext, digest, context->hashSize) ||
!(ret=USHAInput(&context->shaContext, digest, context->hashSize)))
/* finish up 2nd pass */
USHAResult(&context->shaContext, digest);
ret=USHAResult(&context->shaContext, digest);
context->Computed = 1;
return context->Corrupted = ret;

View File

@@ -285,7 +285,7 @@ void str_icmp_type_name(char *s, size_t s_len, bool v6, uint8_t type)
static void str_srcdst_ip(char *s, size_t s_len, const void *saddr,const void *daddr)
{
char s_ip[16],d_ip[16];
char s_ip[INET_ADDRSTRLEN],d_ip[INET_ADDRSTRLEN];
*s_ip=*d_ip=0;
inet_ntop(AF_INET, saddr, s_ip, sizeof(s_ip));
inet_ntop(AF_INET, daddr, d_ip, sizeof(d_ip));
@@ -306,7 +306,7 @@ void print_ip(const struct ip *ip)
}
void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *daddr)
{
char s_ip[40],d_ip[40];
char s_ip[INET6_ADDRSTRLEN],d_ip[INET6_ADDRSTRLEN];
*s_ip=*d_ip=0;
inet_ntop(AF_INET6, saddr, s_ip, sizeof(s_ip));
inet_ntop(AF_INET6, daddr, d_ip, sizeof(d_ip));
@@ -314,14 +314,14 @@ void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *daddr)
}
void str_ip6hdr(char *s, size_t s_len, const struct ip6_hdr *ip6hdr, uint8_t proto)
{
char ss[83],s_proto[16];
char ss[100],s_proto[16];
str_srcdst_ip6(ss,sizeof(ss),&ip6hdr->ip6_src,&ip6hdr->ip6_dst);
str_proto_name(s_proto,sizeof(s_proto),proto);
snprintf(s,s_len,"%s proto=%s ttl=%u",ss,s_proto,ip6hdr->ip6_hlim);
}
void print_ip6hdr(const struct ip6_hdr *ip6hdr, uint8_t proto)
{
char s[128];
char s[132];
str_ip6hdr(s,sizeof(s),ip6hdr,proto);
printf("%s",s);
}
@@ -504,7 +504,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
bool fr=false;
uint16_t fr_off=0;
if (len<sizeof(struct ip6_hdr)) return false;
if (len<sizeof(struct ip6_hdr)) return NULL;
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
last_proto = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
data = (uint8_t*)(ip6+1);
@@ -521,18 +521,18 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
case IPPROTO_MH: // mobility header
case IPPROTO_HIP: // Host Identity Protocol Version v2
case IPPROTO_SHIM6:
if (len < 2) return false; // error
if (len < 2) return NULL; // error
hdrlen = 8 + (data[1] << 3);
break;
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
hdrlen = 8;
if (len < hdrlen) return false; // error
if (len < hdrlen) return NULL; // error
fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK);
fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
break;
case IPPROTO_AH:
// special case. length in ah header is in 32-bit words minus 2
if (len < 2) return false; // error
if (len < 2) return NULL; // error
hdrlen = 8 + (data[1] << 2);
break;
default:
@@ -540,7 +540,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
// exthdr was not found
return NULL;
}
if (len < hdrlen) return false; // error
if (len < hdrlen) return NULL; // error
last_proto = *data;
len -= hdrlen; data += hdrlen;
}
@@ -1557,7 +1557,6 @@ void rawsend_cleanup(void)
{
if (w_filter)
{
CancelIoEx(w_filter,&ovl);
WinDivertClose(w_filter);
w_filter=NULL;
}
@@ -1585,71 +1584,71 @@ bool windivert_init(const char *filter)
return false;
}
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
static bool windivert_recv_exit(void)
{
UINT recv_len;
DWORD err;
DWORD rd;
char c;
sigset_t pending;
// make signals working
usleep(0);
if (bQuit)
{
errno=EINTR;
return false;
return true;
}
if (!logical_net_filter_match_rate_limited())
{
errno=ENODEV;
return false;
return true;
}
usleep(0);
return false;
}
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
{
UINT recv_len;
DWORD rd;
unsigned int wac;
*wa_count *= sizeof(WINDIVERT_ADDRESS);
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, wa_count, &ovl))
if (windivert_recv_exit()) return false;
wac = *wa_count * sizeof(WINDIVERT_ADDRESS);
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, &wac, &ovl))
{
*wa_count /= sizeof(WINDIVERT_ADDRESS);
*wa_count = wac/sizeof(WINDIVERT_ADDRESS);
*len = recv_len;
return true;
}
for(;;)
w_win32_error = GetLastError();
switch(w_win32_error)
{
w_win32_error = GetLastError();
switch(w_win32_error)
{
case ERROR_IO_PENDING:
// make signals working
while (WaitForSingleObject(ovl.hEvent,50)==WAIT_TIMEOUT)
{
if (bQuit)
{
errno=EINTR;
return false;
}
if (!logical_net_filter_match_rate_limited())
{
errno=ENODEV;
return false;
}
usleep(0);
}
if (!GetOverlappedResult(hFilter,&ovl,&rd,TRUE))
continue;
*wa_count /= sizeof(WINDIVERT_ADDRESS);
*len = rd;
return true;
case ERROR_INSUFFICIENT_BUFFER:
errno = ENOBUFS;
break;
case ERROR_NO_DATA:
errno = ESHUTDOWN;
break;
default:
errno = EIO;
}
break;
case ERROR_IO_PENDING:
// make signals working
while (WaitForSingleObject(ovl.hEvent,50)==WAIT_TIMEOUT)
{
if (windivert_recv_exit()) return false;
}
if (!GetOverlappedResult(hFilter,&ovl,&rd,FALSE))
{
errno=EIO;
goto cancel;
}
*wa_count = wac/sizeof(WINDIVERT_ADDRESS);
*len = rd;
return true;
case ERROR_INSUFFICIENT_BUFFER:
errno = ENOBUFS;
break;
case ERROR_NO_DATA:
errno = ESHUTDOWN;
break;
default:
errno = EIO;
}
cancel:
// make sure no pending operations
CancelIoEx(w_filter,&ovl);
GetOverlappedResult(hFilter, &ovl, &rd, TRUE);
return false;
}
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
@@ -1797,7 +1796,7 @@ static int rawsend_sendto_divert(sa_family_t family, int sock, const void *buf,
char s[64];
snprintf(s,sizeof(s),"rawsend_sendto_divert: sendto (%zu)",len);
DLOG_PERROR(s);
return false;
return -1;
}
return wr;
@@ -1881,8 +1880,9 @@ static int rawsend_socket(sa_family_t family)
}
if (family==AF_INET && setsockopt(*sock, IPPROTO_IP, IP_NODEFRAG, &yes, sizeof(yes)) == -1)
{
// since 2.6.36
DLOG_PERROR("rawsend: setsockopt(IP_NODEFRAG)");
goto exiterr;
//goto exiterr;
}
if (family==AF_INET && setsockopt(*sock, IPPROTO_IP, IP_FREEBIND, &yes, sizeof(yes)) == -1)
{

View File

@@ -289,11 +289,11 @@ static struct desync_profile *dp_find(
struct desync_profile_list *dpl;
if (params.debug)
{
char s[40];
char s[INET6_ADDRSTRLEN];
ntopa46(ip, ip6, s, sizeof(s));
if (ipr || ipr6)
{
char sr[40];
char sr[INET6_ADDRSTRLEN];
ntopa46(ipr, ipr6, sr, sizeof(sr));
DLOG("desync profile search for %s ip1=%s ip2=%s port=%u icmp=%u:%u l7proto=%s ssid='%s' hostname='%s'\n",
proto_name(l3proto), s, sr, port, icmp_type, icmp_code, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : "");
@@ -737,7 +737,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
}
if (params.debug)
{
char s[40];
char s[INET6_ADDRSTRLEN];
ntopa46(a4, a6, s, sizeof(s));
DLOG("ipcache hostname search for %s\n", s);
}
@@ -746,7 +746,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
{
if (params.debug)
{
char s[40];
char s[INET6_ADDRSTRLEN];
ntopa46(a4, a6, s, sizeof(s));
DLOG("got cached hostname for %s : %s (is_ip=%u)\n", s, ipc->hostname, ipc->hostname_is_ip);
}
@@ -1137,7 +1137,7 @@ static void setup_direction(
if (params.debug)
{
char ip[40];
char ip[INET6_ADDRSTRLEN];
ntopa46(*sdip4, *sdip6, ip, sizeof(ip));
DLOG("%s mode desync profile/ipcache search target ip=%s port=%u\n", params.server ? "server" : "client", ip, *sdport);
}
@@ -1574,8 +1574,9 @@ static uint8_t dpi_desync_tcp_packet_play(
if (!bReqFull && ReasmIsEmpty(&ps.ctrack->reasm_client) && !is_retransmission(&ps.ctrack->pos.client))
{
// do not reconstruct unexpected large payload (they are feeding garbage ?)
// also do not reconstruct if server window size is low
if (!reasm_client_start(ps.ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
goto pass_reasm_cancel;
goto rediscover;
}
if (!ReasmIsEmpty(&ps.ctrack->reasm_client))
@@ -1601,6 +1602,7 @@ static uint8_t dpi_desync_tcp_packet_play(
}
}
rediscover:
if (!dp_rediscovery(&ps))
goto pass_reasm_cancel;
@@ -1661,7 +1663,8 @@ static const uint8_t *dns_extract_name(const uint8_t *a, const uint8_t *b, const
if (p>=e) return NULL;
for (nl=0; *p ;)
{
if ((p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
// do not support mixed ptr+real
if ((*p & 0xC0) || (p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
if (nl) name[nl++] = '.';
memcpy(name + nl, p + 1, *p);
nl += *p;
@@ -1676,7 +1679,7 @@ static bool feed_dns_response(const uint8_t *a, size_t len)
// check of minimum header length and response flag
uint16_t k, off, dlen, qcount = a[4]<<8 | a[5], acount = a[6]<<8 | a[7];
char s_ip[40];
char s_ip[INET6_ADDRSTRLEN];
const uint8_t *b = a, *p;
const uint8_t *e = b + len;
size_t nl;

View File

@@ -173,7 +173,7 @@ bool packet_range_parse(const char *s, struct packet_range *range)
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr)
{
char s_ip[16];
char s_ip[INET_ADDRSTRLEN];
*s_ip=0;
inet_ntop(AF_INET, &cidr->addr, s_ip, sizeof(s_ip));
snprintf(s,s_len,cidr->preflen<32 ? "%s/%u" : "%s", s_ip, cidr->preflen);
@@ -186,14 +186,14 @@ void print_cidr4(const struct cidr4 *cidr)
}
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr)
{
char s_ip[40];
char s_ip[INET6_ADDRSTRLEN];
*s_ip=0;
inet_ntop(AF_INET6, &cidr->addr, s_ip, sizeof(s_ip));
snprintf(s,s_len,cidr->preflen<128 ? "%s/%u" : "%s", s_ip, cidr->preflen);
}
void print_cidr6(const struct cidr6 *cidr)
{
char s[44];
char s[INET_ADDRSTRLEN+4];
str_cidr6(s,sizeof(s),cidr);
printf("%s",s);
}

View File

@@ -15,6 +15,7 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
unsigned char in[ZCHUNK];
size_t bufsize;
void *newbuf;
size_t rd;
memset(&zs, 0, sizeof(zs));
@@ -26,20 +27,21 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
do
{
zs.avail_in = fread_safe(in, 1, sizeof(in), F);
if (ferror(F))
if (!fread_safe(in, 1, sizeof(in), F, &rd))
{
r = Z_ERRNO;
goto zerr;
}
if (!zs.avail_in)
if (!rd)
{
// file is not full
r = Z_DATA_ERROR;
goto zerr;
}
zs.avail_in = rd;
zs.next_in = in;
do
for(;;)
{
if ((bufsize - *size) < BUFMIN)
{
@@ -54,20 +56,41 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
}
zs.avail_out = bufsize - *size;
zs.next_out = (unsigned char*)(*buf + *size);
r = inflate(&zs, Z_NO_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
*size = bufsize - zs.avail_out;
} while (r == Z_OK && zs.avail_in);
if (r==Z_STREAM_END) break;
if (r==Z_BUF_ERROR)
{
if (zs.avail_in)
goto zerr;
else
{
r = Z_OK;
break;
}
}
if (r!=Z_OK) goto zerr;
}
} while (r == Z_OK);
if (*size < bufsize)
{
// free extra space
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
if (*size + extra_alloc)
{
// free extra space
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
}
else
{
free(*buf);
*buf = NULL;
}
}
inflateEnd(&zs);
return Z_OK;
return r;
zerr:
inflateEnd(&zs);
@@ -79,7 +102,7 @@ zerr:
bool is_gzip(FILE* F)
{
unsigned char magic[2];
bool b = !fseek(F, 0, SEEK_SET) && fread_safe(magic, 1, 2, F) == 2 && magic[0] == 0x1F && magic[1] == 0x8B;
bool b = !fseek(F, 0, SEEK_SET) && fread(magic, 1, 2, F) == 2 && magic[0] == 0x1F && magic[1] == 0x8B;
fseek(F, 0, SEEK_SET);
return b;
}

View File

@@ -9,9 +9,15 @@
#include <stdlib.h>
#include <ctype.h>
#include <libgen.h>
#include <limits.h>
#include <errno.h>
#include <sys/param.h>
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
#define UNIQ_SORT \
{ \
size_t i, j, u; \
@@ -120,8 +126,7 @@ bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_
}
}
*buffer_size = fread_safe(buffer, 1, *buffer_size, F);
if (ferror(F))
if (!fread_safe(buffer, 1, *buffer_size, F, buffer_size))
{
fclose(F);
return false;
@@ -241,7 +246,7 @@ void ntop46(const struct sockaddr *sa, char *str, size_t len)
}
void ntop46_port(const struct sockaddr *sa, char *str, size_t len)
{
char ip[40];
char ip[INET6_ADDRSTRLEN];
ntop46(sa, ip, sizeof(ip));
switch (sa->sa_family)
{
@@ -512,21 +517,31 @@ ssize_t read_intr(int fd, void *buf, size_t count)
return rd;
}
size_t fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F)
bool fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F, size_t *rd)
{
size_t result, total_read = 0;
size_t result, to_read, total_read = 0;
while (total_read < nmemb)
{
total_read += (result = fread((uint8_t*)ptr + (total_read * size), size, nmemb - total_read, F));
if (result < (nmemb - total_read))
to_read = nmemb - total_read;
errno = 0;
total_read += (result = fread((uint8_t*)ptr + (total_read * size), size, to_read, F));
if (result < to_read)
{
if (errno == EINTR)
clearerr(F);
else
break;
if (ferror(F))
{
if (errno == EINTR)
{
clearerr(F);
continue;
}
*rd = total_read;
return false;
}
break;
}
}
return total_read;
*rd = total_read;
return true;
}
char* fgets_safe(char *s, int size, FILE *stream)
{
@@ -534,6 +549,7 @@ char* fgets_safe(char *s, int size, FILE *stream)
while (true)
{
errno = 0;
if ((result = fgets(s, size, stream))) return result;
if (ferror(stream))
{
@@ -649,12 +665,64 @@ bool set_env_exedir(const char *argv0)
if ((s = strdup(argv0)))
{
if ((d = dirname(s)))
{
char d_abs[PATH_MAX];
if (realpath(d, d_abs))
d=d_abs;
bOK = !setenv("EXEDIR", d, 1);
}
free(s);
}
return bOK;
}
// works for existing and new files
bool realpath_any(const char *file, char *pabs)
{
bool b = true;
char *s1=NULL, *s2=NULL;
int res;
size_t l;
#ifdef __CYGWIN__
l = cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, file, NULL, 0);
char *rp_file = (char*)malloc(l);
if (cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, file, rp_file, l))
goto err;
#else
#define rp_file file
#endif
if (!realpath(rp_file,pabs))
{
char pa[PATH_MAX], *dir, *base;
if (!(s1 = strdup(rp_file))) goto err;
dir = dirname(s1);
if (!realpath(dir,pa))
goto err;
if (!(s2 = strdup(rp_file))) goto err;
base = basename(s2);
l = strlen(pa);
if (l && pa[l-1]=='/')
res=snprintf(pabs,PATH_MAX,"%s%s",pa, base);
else
res=snprintf(pabs,PATH_MAX,"%s/%s",pa,base);
b = res>0 && res<PATH_MAX;
}
ex:
#ifdef __CYGWIN__
free(rp_file);
#else
#undef rp_file
#endif
free(s1);
free(s2);
return b;
err:
b = false;
goto ex;
}
bool parse_int16(const char *p, int16_t *v)
{
if (*p == '+' || *p == '-' || *p >= '0' && *p <= '9')

View File

@@ -34,7 +34,7 @@ const char *strncasestr(const char *s,const char *find, size_t slen);
bool is_identifier(const char *p);
ssize_t read_intr(int fd, void *buf, size_t count);
size_t fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F);
bool fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F, size_t *rd);
char* fgets_safe(char *s, int size, FILE *stream);
bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_size);
@@ -106,6 +106,7 @@ void set_console_io_buffering(void);
void close_std(void);
void close_std_and_exit(int code);
bool set_env_exedir(const char *argv0);
bool realpath_any(const char *file, char *pabs);
bool parse_int16(const char *p, int16_t *v);

View File

@@ -60,7 +60,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
{
r = z_readfile(F,&zbuf,&zsize,0);
fclose(F);
if (r==Z_OK)
if (r==Z_STREAM_END)
{
DLOG_CONDUP("zlib compression detected. uncompressed size : %zu\n", zsize);
@@ -97,6 +97,12 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
return false;
}
}
if (ferror(F))
{
DLOG_PERROR("AppendHostList");
fclose(F);
return false;
}
fclose(F);
}
@@ -274,13 +280,15 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool no_ma
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{
struct hostlist_file *hfile;
char pabs[PATH_MAX];
if (filename)
{
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
if (!realpath(filename,pabs)) return NULL;
if (!(hfile=hostlist_files_search(hostlists, pabs)))
if (!(hfile=hostlist_files_add(hostlists, pabs)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_search(hl_collection, pabs))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
@@ -296,13 +304,11 @@ static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostl
}
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{
/*
if (filename && !file_mod_time(filename))
{
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL;
}
*/
return RegisterHostlist_(
&params.hostlists,
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,

View File

@@ -77,7 +77,7 @@ static bool AppendIpset(ipset *ips, const char *filename)
{
r = z_readfile(F,&zbuf,&zsize,0);
fclose(F);
if (r==Z_OK)
if (r==Z_STREAM_END)
{
DLOG_CONDUP("zlib compression detected. uncompressed size : %zu\n", zsize);
@@ -114,6 +114,12 @@ static bool AppendIpset(ipset *ips, const char *filename)
return false;
}
}
if (ferror(F))
{
DLOG_PERROR("AppendIpset");
fclose(F);
return false;
}
fclose(F);
}
@@ -176,7 +182,7 @@ bool LoadAllIpsets()
static bool SearchIpset(const ipset *ips, const struct in_addr *ipv4, const struct in6_addr *ipv6)
{
char s_ip[40];
char s_ip[INET6_ADDRSTRLEN];
bool bInSet=false;
if (!!ipv4 != !!ipv6)
@@ -272,12 +278,15 @@ bool IpsetCheck(
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{
struct ipset_file *hfile;
char pabs[PATH_MAX];
if (filename)
{
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
if (!realpath(filename,pabs)) return NULL;
if (!(hfile=ipset_files_search(ipsets, pabs)))
if (!(hfile=ipset_files_add(ipsets, pabs)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_search(ips_collection, pabs))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}

View File

@@ -686,8 +686,8 @@ static int luacall_aes_gcm(lua_State *L)
luaL_error(L, "aes_gcm: wrong key length %u. should be 16,24,32.", (unsigned)key_len);
size_t iv_len;
const uint8_t *iv = (uint8_t*)lua_reqlstring(L,3,&iv_len);
if (iv_len!=12)
luaL_error(L, "aes_gcm: wrong iv length %u. should be 12.", (unsigned)iv_len);
if (!iv_len)
luaL_error(L, "aes_gcm: zero iv length");
size_t input_len;
const uint8_t *input = (uint8_t*)lua_reqlstring(L,4,&input_len);
size_t add_len=0;
@@ -1901,7 +1901,7 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
lua_getfield(L,-1, "data");
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
if (!(p=(uint8_t*)lua_tolstring(L,-1,&l))) l=0;
if (!l || (l+2)>left || ((type==IPPROTO_AH) ? (l<6 || ((l+2) & 3)) : ((l+2) & 7))) goto err;
if (l<6 || (l+2)>left || (type==IPPROTO_AH ? (l>=1024 || ((l+2) & 3)) : (l>=2048 || ((l+2) & 7)))) goto err;
memcpy(data+2,p,l);
l+=2;
data[0] = next; // may be overwritten later
@@ -2539,7 +2539,7 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
}
else if (udp)
{
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
sz = lpayload+sizeof(struct udphdr);
if (sz>0xFFFF)
{
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
@@ -2569,12 +2569,13 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
DLOG_ERR("ipv4 frag : invalid ip_len\n");
goto err;
}
if (frag_start>l)
size_t frag_len = iplen-l3;
if ((frag_start+frag_len)>l)
{
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
DLOG_ERR("ipv4 frag : fragment end is outside of the packet\n");
goto err;
}
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
if (off) memmove(buf+l3,buf+frag_start,frag_len);
l = iplen; // shrink packet to iplen
}
else
@@ -2812,7 +2813,7 @@ static int luacall_ntop(lua_State *L)
{
size_t l;
const char *p;
char s[40];
char s[INET6_ADDRSTRLEN];
int af=0;
lua_check_argc(L,"ntop",1);
@@ -2832,9 +2833,10 @@ static int luacall_ntop(lua_State *L)
lua_pushnil(L);
return 1;
}
if (!inet_ntop(af,p,s,sizeof(s)))
luaL_error(L, "inet_ntop error");
lua_pushstring(L,s);
if (inet_ntop(af,p,s,sizeof(s)))
lua_pushstring(L,s);
else
lua_pushnil(L);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -3138,7 +3140,7 @@ static int lua_get_ifaddrs(lua_State *L)
struct ifreq ifr;
const char *ifname;
#ifdef __CYGWIN__
char ifname_buf[16];
char ifname_buf[IFNAMSIZ];
#endif
memset(&ifr,0,sizeof(ifr));
@@ -3179,6 +3181,7 @@ static int lua_get_ifaddrs(lua_State *L)
#ifdef HAS_FILTER_SSID
lua_pushf_str(L, "ssid", wlan_ssid_search_ifname(ifname));
#endif
memset(ifr.ifr_name,0,sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (sock>=0 && !ioctl(sock, SIOCGIFMTU, &ifr))
lua_pushf_int(L, "mtu", ifr.ifr_mtu);
@@ -3467,7 +3470,7 @@ static int luacall_gunzip_inflate(lua_State *L)
size_t increment = bufchunk / 2;
if (increment < Z_INFL_BUF_INCREMENT) increment = Z_INFL_BUF_INCREMENT;
do
for(;;)
{
if ((bufsize - size) < BUFMIN)
{
@@ -3490,11 +3493,20 @@ static int luacall_gunzip_inflate(lua_State *L)
}
uzs->zs.avail_out = bufsize - size;
uzs->zs.next_out = buf + size;
r = inflate(&uzs->zs, Z_NO_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
size = bufsize - uzs->zs.avail_out;
} while (r == Z_OK && uzs->zs.avail_in);
r = inflate(&uzs->zs, Z_NO_FLUSH);
size = bufsize - uzs->zs.avail_out;
if (r==Z_STREAM_END) break;
if (r==Z_BUF_ERROR)
{
if (uzs->zs.avail_in)
goto zerr;
else
break; // OK
}
if (r!=Z_OK) goto zerr;
}
lua_pushlstring(L, (const char*)buf, size);
lua_pushboolean(L, r==Z_STREAM_END);
end:
@@ -3517,7 +3529,7 @@ static void z_free(voidpf opaque, voidpf address)
static int luacall_gzip_init(lua_State *L)
{
// gzip_init(windowBits, level, memlevel) return zstream
lua_check_argc_range(L,"gunzip_init",0,3);
lua_check_argc_range(L,"gzip_init",0,3);
LUA_STACK_GUARD_ENTER(L)
@@ -3568,7 +3580,7 @@ static int luacall_gzip_deflate(lua_State *L)
int argc=lua_gettop(L);
size_t l=0;
int r;
int r, flush;
size_t bufsize=0, size=0;
uint8_t *buf=NULL, *newbuf;
struct userdata_zs *uzs = lua_uzs(L, 1, false);
@@ -3581,7 +3593,8 @@ static int luacall_gzip_deflate(lua_State *L)
size_t increment = bufchunk / 2;
if (increment < Z_DEFL_BUF_INCREMENT) increment = Z_DEFL_BUF_INCREMENT;
do
flush = l ? Z_NO_FLUSH : Z_FINISH;
for(;;)
{
if ((bufsize - size) < BUFMIN)
{
@@ -3604,10 +3617,19 @@ static int luacall_gzip_deflate(lua_State *L)
}
uzs->zs.avail_out = bufsize - size;
uzs->zs.next_out = buf + size;
r = deflate(&uzs->zs, l ? Z_NO_FLUSH : Z_FINISH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
r = deflate(&uzs->zs, flush);
size = bufsize - uzs->zs.avail_out;
} while (r == Z_OK && (uzs->zs.avail_in || !uzs->zs.avail_out));
if (r==Z_STREAM_END) break;
if (r==Z_OK)
{
if (uzs->zs.avail_out && !uzs->zs.avail_in && flush != Z_FINISH)
break;
}
else
goto zerr;
}
lua_pushlstring(L, (const char*)buf, size);
lua_pushboolean(L, r==Z_STREAM_END);
@@ -3935,7 +3957,7 @@ static int luaL_doZfile(lua_State *L, const char *filename)
luaL_error(L, "could not open lua file '%s'", fname);
r = z_readfile(F, &buf, &size, 0);
fclose(F);
if (r != Z_OK)
if (r != Z_STREAM_END)
luaL_error(L, "could not unzip lua file '%s'", fname);
r = luaL_loadbuffer(L, buf, size, fname);
free(buf);

View File

@@ -71,13 +71,13 @@ static void ReloadCheck()
if (!LoadAllHostLists())
{
DLOG_ERR("hostlists load failed. this is fatal.\n");
exit(1);
exit(200);
}
ResetAllIpsetModTime();
if (!LoadAllIpsets())
{
DLOG_ERR("ipset load failed. this is fatal.\n");
exit(1);
exit(200);
}
bReload = false;
}
@@ -183,7 +183,7 @@ static void fuzzPacketData(unsigned int count)
*packet = *packet ? (*packet & 1) ? 0x40 : 0x60 | (*packet & 0x0F) : (uint8_t)random();
}
modlen = random()%(sizeof(mod)+1);
verdict = processPacketData(&mark,random()%1 ? "ifin" : NULL,random()%1 ? "ifout" : NULL,packet,len,mod,&modlen);
verdict = processPacketData(&mark,(random() & 1) ? "ifin" : NULL,(random() & 1) ? "ifout" : NULL,packet,len,mod,&modlen);
free(packet);
}
}
@@ -317,22 +317,29 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *m
goto exiterr;
}
// linux 3.8 - bind calls are NOOP. linux 3.8- - secondary bind to AF_INET6 will fail
// old kernels seem to require both binds to ipv4 and ipv6. may not work without unbind
DLOG_CONDUP("unbinding existing nf_queue handler for AF_INET (if any)\n");
if (nfq_unbind_pf(*h, AF_INET) < 0) {
DLOG_PERROR("nfq_unbind_pf()");
DLOG_PERROR("nfq_unbind_pf(AF_INET)");
goto exiterr;
}
DLOG_CONDUP("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
if (nfq_bind_pf(*h, AF_INET) < 0) {
DLOG_PERROR("nfq_bind_pf()");
DLOG_PERROR("nfq_bind_pf(AF_INET)");
goto exiterr;
}
DLOG_CONDUP("unbinding existing nf_queue handler for AF_INET6 (if any)\n");
if (nfq_unbind_pf(*h, AF_INET6) < 0) {
DLOG_PERROR("nfq_unbind_pf(AF_INET6)");
}
DLOG_CONDUP("binding nfnetlink_queue as nf_queue handler for AF_INET6\n");
if (nfq_bind_pf(*h, AF_INET6) < 0) {
DLOG_PERROR("nfq_bind_pf()");
// do not fail - kernel may not support ipv6
DLOG_PERROR("nfq_bind_pf(AF_INET6)");
}
DLOG_CONDUP("binding this socket to queue '%u'\n", params.qnum);
@@ -355,7 +362,7 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *m
if (nfq_set_queue_flags(*qh, NFQA_CFG_F_FAIL_OPEN, NFQA_CFG_F_FAIL_OPEN))
{
DLOG_ERR("can't set queue flags. its OK on linux <3.6\n");
// dot not fail. not supported on old linuxes <3.6
// dot not fail. not supported in old linuxes <3.6
}
int yes = 1, fd = nfq_fd(*h);
@@ -1686,6 +1693,7 @@ static void exithelp(void)
" --port=<port>\t\t\t\t\t\t; divert port\n"
#endif
" --daemon\t\t\t\t\t\t; daemonize\n"
" --chdir[=path]\t\t\t\t\t\t; change current directory. if no path specified use EXEDIR\n"
" --pidfile=<filename>\t\t\t\t\t; write pid to file\n"
#ifndef __CYGWIN__
" --user=<username>\t\t\t\t\t; drop root privs\n"
@@ -1849,6 +1857,7 @@ enum opt_indices {
IDX_PORT,
#endif
IDX_DAEMON,
IDX_CHDIR,
IDX_PIDFILE,
#ifndef __CYGWIN__
IDX_USER,
@@ -1953,6 +1962,7 @@ static const struct option long_options[] = {
[IDX_PORT] = {"port", required_argument, 0, 0},
#endif
[IDX_DAEMON] = {"daemon", no_argument, 0, 0},
[IDX_CHDIR] = {"chdir", optional_argument, 0, 0},
[IDX_PIDFILE] = {"pidfile", required_argument, 0, 0},
#ifndef __CYGWIN__
[IDX_USER] = {"user", required_argument, 0, 0},
@@ -2170,8 +2180,11 @@ int main(int argc, char **argv)
{
if (*optarg == '@')
{
strncpy(params.debug_logfile, optarg + 1, sizeof(params.debug_logfile));
params.debug_logfile[sizeof(params.debug_logfile) - 1] = 0;
if (!realpath_any(optarg+1,params.debug_logfile))
{
DLOG_ERR("bad file '%s'\n",optarg+1);
exit_clean(1);
}
FILE *F = fopen(params.debug_logfile, "wt");
if (!F)
{
@@ -2258,8 +2271,28 @@ int main(int argc, char **argv)
case IDX_DAEMON:
params.daemon = true;
break;
case IDX_CHDIR:
{
const char *d = optarg ? optarg : getenv("EXEDIR");
if (!d)
{
DLOG_ERR("chdir: directory unknown\n");
exit_clean(1);
}
DLOG("changing dir to '%s'\n",d);
if (chdir(d))
{
DLOG_PERROR("chdir");
exit_clean(1);
}
}
break;
case IDX_PIDFILE:
snprintf(params.pidfile, sizeof(params.pidfile), "%s", optarg);
if (!realpath_any(optarg,params.pidfile))
{
DLOG_ERR("bad file '%s'\n",optarg);
exit_clean(1);
}
break;
#ifndef __CYGWIN__
case IDX_USER:
@@ -2363,8 +2396,11 @@ int main(int argc, char **argv)
params.writeable_dir_enable = true;
if (optarg)
{
strncpy(params.writeable_dir, optarg, sizeof(params.writeable_dir));
params.writeable_dir[sizeof(params.writeable_dir) - 1] = 0;
if (!realpath_any(optarg, params.writeable_dir))
{
DLOG_ERR("bad file '%s'\n",optarg);
exit_clean(1);
}
}
else
*params.writeable_dir = 0;
@@ -2375,10 +2411,22 @@ int main(int argc, char **argv)
break;
case IDX_LUA_INIT:
if (!strlist_add_tail(&params.lua_init_scripts, optarg))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
char pabs[PATH_MAX+1], *p=optarg;
if (*p=='@')
{
if (!realpath_any(p+1,pabs+1))
{
DLOG_ERR("bad file '%s'\n",p+1);
exit_clean(1);
}
*(p=pabs)='@';
}
if (!strlist_add_tail(&params.lua_init_scripts, p))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
}
break;
case IDX_LUA_GC:
@@ -2508,15 +2556,18 @@ int main(int argc, char **argv)
break;
case IDX_HOSTLIST_AUTO_DEBUG:
{
FILE *F = fopen(optarg, "a+t");
if (!realpath_any(optarg,params.hostlist_auto_debuglog))
{
DLOG_ERR("bad file '%s'\n",optarg);
exit_clean(1);
}
FILE *F = fopen(params.hostlist_auto_debuglog, "a+t");
if (!F)
{
DLOG_ERR("cannot create %s\n", optarg);
exit_clean(1);
}
fclose(F);
strncpy(params.hostlist_auto_debuglog, optarg, sizeof(params.hostlist_auto_debuglog));
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
}
break;

View File

@@ -1033,7 +1033,7 @@ static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a, cons
}
static void ipcache4Print(ip_cache4 *ipcache)
{
char s_ip[16];
char s_ip[INET_ADDRSTRLEN];
time_t now;
ip_cache4 *ipc, *tmp;
@@ -1091,7 +1091,7 @@ static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a, con
}
static void ipcache6Print(ip_cache6 *ipcache)
{
char s_ip[40];
char s_ip[INET6_ADDRSTRLEN];
time_t now;
ip_cache6 *ipc, *tmp;

View File

@@ -145,7 +145,6 @@ bool posmarker_parse(const char *s, struct proto_pos *m)
m->pos = 0;
}
return true;
}
bool posmarker_list_parse(const char *s, struct proto_pos *m, int *mct)
{
@@ -551,10 +550,14 @@ bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
l += (data[0]==0x02 ? 0 : pntoh16(data + l)) + 2;
if (data[0]==0x01) // client hello ?
l += pntoh16(data + l);
l+=2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
l += data[l] + 1;
if (data[0]==0x01) // client hello ?
l += data[l];
l++;
// ExtensionsLength
if (len < (l + 2)) return false;
*off = l;
@@ -1191,16 +1194,16 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
return false;
}
uint64_t payload_len,token_len;
size_t pn_offset;
uint64_t payload_len,token_len,pn_offset;
pn_offset = 1 + 4 + 1 + data[5];
if (pn_offset >= data_len) return false;
// SCID length
pn_offset += 1 + data[pn_offset];
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
if (pn_offset >= data_len || (pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
// token length
pn_offset += tvb_get_varint(data + pn_offset, &token_len);
pn_offset += token_len;
if (pn_offset >= data_len) return false;
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
if (pn_offset >= data_len || (pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
pn_offset += tvb_get_varint(data + pn_offset, &payload_len);
if (payload_len<20 || (pn_offset + payload_len)>data_len) return false;
@@ -1221,17 +1224,17 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
phton64(aesiv + sizeof(aesiv) - 8, pntoh64(aesiv + sizeof(aesiv) - 8) ^ pkn);
size_t cryptlen = payload_len - pkn_len - 16;
uint64_t cryptlen = payload_len - pkn_len - 16;
if (cryptlen > *clean_len) return false;
*clean_len = cryptlen;
*clean_len = (size_t)cryptlen;
const uint8_t *decrypt_begin = data + pn_offset + pkn_len;
uint8_t atag[16],header[2048];
size_t header_len = pn_offset + pkn_len;
uint64_t header_len = pn_offset + pkn_len;
if (header_len > sizeof(header)) return false; // not likely header will be so large
memcpy(header, data, header_len);
header[0] = packet0;
for(size_t i = 0; i < pkn_len; i++) header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
for(uint8_t i = 0; i < pkn_len; i++) header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
if (aes_gcm_crypt(AES_DECRYPT, clean, decrypt_begin, cryptlen, aeskey, sizeof(aeskey), aesiv, sizeof(aesiv), header, header_len, atag, sizeof(atag)))
return false;

View File

@@ -6,6 +6,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <grp.h>
#include <errno.h>
#include "params.h"
@@ -18,7 +19,6 @@
// __X32_SYSCALL_BIT defined in linux/unistd.h
#include <linux/unistd.h>
#include <syscall.h>
#include <errno.h>
/************ SECCOMP ************/
@@ -350,10 +350,19 @@ void daemonize(void)
DLOG_PERROR("setsid");
exit(21);
}
if (close(STDIN_FILENO)<0 || close(STDOUT_FILENO)<0 || close(STDERR_FILENO)<0)
if (close(STDIN_FILENO)<0 && errno!=EBADF)
{
// will work only if debug not to console
DLOG_PERROR("close");
DLOG_PERROR("close(stdin)");
exit(22);
}
if (close(STDOUT_FILENO)<0 && errno!=EBADF)
{
DLOG_PERROR("close(stdout)");
exit(22);
}
if (close(STDERR_FILENO)<0 && errno!=EBADF)
{
DLOG_PERROR("close(stderr)");
exit(22);
}
/* redirect fd's 0,1,2 to /dev/null */

View File

@@ -18,6 +18,25 @@ bool dropcaps(void);
#define arch_nr (offsetof(struct seccomp_data, arch))
#define syscall_arg(x) (offsetof(struct seccomp_data, args[x]))
#ifndef __AUDIT_ARCH_64BIT
#define __AUDIT_ARCH_64BIT 0x80000000
#endif
#ifndef __AUDIT_ARCH_LE
#define __AUDIT_ARCH_LE 0x40000000
#endif
#ifndef EM_RISCV
#define EM_RISCV 243
#endif
#ifndef AUDIT_ARCH_RISCV64
#define AUDIT_ARCH_RISCV64 (EM_RISCV | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#endif
#ifndef EM_LOONGARCH
#define EM_LOONGARCH 258
#endif
#ifndef AUDIT_ARCH_LOONGARCH64
#define AUDIT_ARCH_LOONGARCH64 (EM_LOONGARCH | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#endif
#if defined(__aarch64__)
# define ARCH_NR AUDIT_ARCH_AARCH64
@@ -72,6 +91,10 @@ bool dropcaps(void);
# define ARCH_NR AUDIT_ARCH_RISCV64
#elif defined(__loongarch__) && __loongarch_grlen == 64
# define ARCH_NR AUDIT_ARCH_LOONGARCH64
#else
# error "Platform does not support seccomp filter yet"