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

66 Commits

Author SHA1 Message Date
bol-van
8b6ea88a23 update docs 2026-02-24 10:19:01 +03:00
bol-van
59235827c4 nfqws2: fix broken wifi ssid update 2026-02-24 10:10:52 +03:00
bol-van
7073e1fd77 nfqws2: dns_extract_name OOB fixes 2026-02-23 22:47:14 +03:00
bol-van
340261da72 zapret-lib: harden apply_fooling checks 2026-02-23 19:33:58 +03:00
bol-van
937aa91e5d nfqws2: prevent OOB read in addpool 2026-02-23 18:45:25 +03:00
bol-van
dbf673e24a AI fixes 2026-02-23 18:10:37 +03:00
bol-van
61b0a70fa7 nfqws2: support mixed compressed+uncomressed DNS answers 2026-02-23 10:25:27 +03:00
bol-van
d985bb316f nfqws2: support uncompressed names in DNS answers 2026-02-23 09:32:45 +03:00
bol-van
59b3734643 nfqws2: add comment 2026-02-22 19:41:08 +03:00
bol-van
37f45a132f nfqws2: optimize 2026-02-22 18:49:44 +03:00
bol-van
4d753ecdc6 nfqws2: save some syscalls 2026-02-22 18:22:43 +03:00
bol-van
272f086639 nfqws2: optimize nfq buffers 2026-02-22 17:31:13 +03:00
bol-van
d9ae16e56f nfqws2: nfq_handle_packet verbose error logging 2026-02-22 17:03:52 +03:00
bol-van
46d4208c76 zapret-pcap: use reconstruct_dissect if under orchestrator 2026-02-22 12:48:20 +03:00
bol-van
2a4195070f AI fixes 2026-02-22 09:06:53 +03:00
bol-van
8e974e78e2 delete sip.bin dup 2026-02-21 19:44:00 +03:00
bol-van
7df42bc486 init.d: --payload= in custom examples 2026-02-21 10:35:14 +03:00
bol-van
7c12f60e1e AI fixes 2026-02-21 10:23:25 +03:00
bol-van
4c7a3d08d8 github: upx 4.2.4 for all except riscv64 2026-02-20 18:43:22 +03:00
bol-van
e146fc24c5 github: upx 4.2.4 for all except riscv64 2026-02-20 18:41:18 +03:00
bol-van
6165c13468 AI fix 2026-02-20 15:25:56 +03:00
bol-van
f7b3946ec2 update docs 2026-02-20 13:19:17 +03:00
bol-van
9f29f2c0ae update docs 2026-02-20 13:12:08 +03:00
bol-van
c13284b776 zapret-auto: per_instance_condition feed target desync to cond function, code=>cond_code 2026-02-20 07:18:31 +03:00
bol-van
6e85c9650d nfqws2: use tcp seq for reasm_offset 2026-02-19 17:38:46 +03:00
bol-van
7f3b5f659f update docs 2026-02-19 13:00:57 +03:00
bol-van
8e62b2e743 update docs 2026-02-19 12:57:50 +03:00
bol-van
94dfd5fded quic2_example_com.bin 2026-02-19 10:26:42 +03:00
bol-van
70d8e5ad15 AI fixes 2026-02-19 10:05:50 +03:00
bol-van
a80aed5ccc update builder-linux 2026-02-18 17:28:03 +03:00
bol-van
2b35dc8ecd update builder-linux 2026-02-18 16:31:01 +03:00
bol-van
75fadab371 update builder-linux 2026-02-18 16:16:58 +03:00
bol-van
e70f4a000a update builder-linux 2026-02-18 16:08:19 +03:00
bol-van
755c792797 github: luajit for ppc 2026-02-18 15:37:08 +03:00
bol-van
b17894eec1 nfqws2: goto lua desync if reasm is cancelled 2026-02-18 15:28:30 +03:00
bol-van
9e22ec883c update builder-linux 2026-02-18 12:42:11 +03:00
bol-van
f70fb89754 AI fixes, update builder-linux 2026-02-18 12:15:46 +03:00
bol-van
e30f99e106 update docs 2026-02-18 10:46:10 +03:00
bol-van
fce76e59aa build-linux update 2026-02-18 10:28:36 +03:00
bol-van
1b1c8ddb38 nfqws2, zapret-lib: always treat blobs, % and # as string 2026-02-17 19:22:17 +03:00
bol-van
5ced6811c8 winws: fix ensure_access for unix paths 2026-02-17 16:27:06 +03:00
bol-van
371612b000 install_bin: add mipsel64 2026-02-17 14:24:43 +03:00
bol-van
3c87be3cba update docs 2026-02-17 14:11:55 +03:00
bol-van
c642fb3845 builder-linux 2026-02-17 14:07:08 +03:00
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
48 changed files with 1396 additions and 428 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" == 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 -ffunction-sections -fdata-sections -fvisibility=hidden $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 -ffunction-sections -fdata-sections -fvisibility=hidden $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 -ffunction-sections -fdata-sections -fvisibility=hidden $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 -ffat-lto-objects" CFLAGS="-Os -s -flto=auto -ffunction-sections -fdata-sections -fvisibility=hidden" &&
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
@@ -485,17 +490,28 @@ jobs:
pattern: zapret2-*
- name: Install upx
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
version: v4.2.4
shell: bash
env:
VER_OLD: 4.2.4
VER_NEW: 5.1.0
run: |
# old upx works for old kernels like 2.6.26
# new upx crashes on ~<3.10 but required for riscv64
curl -Lo - https://github.com/upx/upx/releases/download/v$VER_OLD/upx-$VER_OLD-amd64_linux.tar.xz | tar -Jx upx-$VER_OLD-amd64_linux/upx
sudo cp upx-$VER_OLD-amd64_linux/upx /usr/local/bin/upx_old
curl -Lo - https://github.com/upx/upx/releases/download/v$VER_NEW/upx-$VER_NEW-amd64_linux.tar.xz | tar -Jx upx-$VER_NEW-amd64_linux/upx
sudo cp upx-$VER_NEW-amd64_linux/upx /usr/local/bin/upx_new
rm -r upx-$VER_OLD-amd64_linux/upx upx-$VER_NEW-amd64_linux/upx
- name: Prepare binaries
shell: bash
run: |
cd ${{ steps.bins.outputs.download-path }}
run_upx() {
upx --best --lzma $@ || true
run_upx_old() {
upx_old --best --lzma $@ || true
}
run_upx_new() {
upx_new --best --lzma $@ || true
}
run_dir() {
for f in $dir/* ; do
@@ -503,8 +519,10 @@ jobs:
case $f in
*.tar.xz )
tar -C $dir -xvf $f && rm $f
if [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
run_upx $dir/*
if [[ $dir = *-linux-riscv64 ]]; then
run_upx_new $dir/*
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
run_upx_old $dir/*
fi
;;
*.zip )
@@ -532,6 +550,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 +565,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 +574,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,21 +215,21 @@ 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
0.9.3
v0.9.3
* nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
* zapret-auto: per_instance_condition orchestrator
@@ -238,3 +238,24 @@ v0.8.1
* 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
v0.9.4.2
* builder_linux: simple scripts to build static linux bins for any supported architecture
* zapret-auto: incompatible change. cond_lua "code" parameter => "cond_code". to avoid collision with luaexec
v0.9.4.3
* nfqws2: fix broken wifi ssid update
* github: revert to upx 4.2.4 for all archs except riscv64
* zapret-lib: apply_fooling throws error if tcp_ts,tcp_seq,tcp_ack,ip_ttl,ip6_ttl,ip_autottl,ip6_autottl are empty or invalid

View File

@@ -1,9 +1,31 @@
debian,ubuntu :
* debian,ubuntu :
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev libluajit2-5.1-dev
make -C /opt/zapret2 systemd
FreeBSD :
* linux static :
need any x86_64 classic linux distribution
tested on debian/ubuntu/fedora 2020+
if your distro is very exotic, old or not glibc based you can debootstrap a modern debian/ubuntu system and chroot to it
NOTE: it's not possible to build luajit in chroot under standard openwrt kernel. build process requires 32-bit x86 support, kernel is compiled without it.
NOTE: toolchains are pre-compiled for x86_64 glibc. they can't run on arm or anything that is not x86_64.
optionally review "common.inc" for Lua and LuaJIT versions
debian/ubuntu: apt install curl xz-utils bzip2 unzip make gcc gcc-multilib libc6-dev libcap-dev pkg-config
fedora: dnf install curl xz bzip2 unzip make gcc glibc-devel glibc-devel.i686 libcap-devel pkg-config
copy directory "builder-linux" somethere with enough free disk space (up to 2G for all toolchains)
run "get_toolchains.sh"
select architectures you need or "ALL"
run "build_deps.sh", select "ALL"
run "build_zapret2.sh", select "ALL"
get static musl bins from "binaries" folder
"zapret2" is downloaded from github master branch. if you need specific version - download manually to "zapret2" dir
i586 and riscv64 targets are built with classic PUC Lua
* FreeBSD :
pkg install pkgconf
pkg search luajit-2
@@ -11,7 +33,7 @@ pkg search luajit-2
pkg install luajit-2.1.0.20250728
make -C /opt/zapret2
OpenBSD :
* OpenBSD :
pkg_add luajit gmake
gmake -C /opt/zapret2 bsd

View File

@@ -11,7 +11,7 @@ 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 -DLUAJIT_DISABLE_FFI -ffat-lto-objects -flto=auto -ffunction-sections -fdata-sections -fvisibility=hidden"
make install
@@ -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

@@ -0,0 +1,102 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
dl_deps()
{
[ -d "$DEPS" ] || mkdir -p "$DEPS"
(
cd "$DEPS"
exists_dir libnfnetlink-* ||
curl -Lo - https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj || exit 5
exists_dir libmnl-* ||
curl -Lo - https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj || exit 5
exists_dir libnetfilter_queue-* ||
curl -Lo - https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj || exit 5
exists_dir zlib-* ||
curl -Lo - https://zlib.net/fossils/zlib-1.3.1.tar.gz | tar -xz || exit 5
exists_dir luajit2-* ||
curl -Lo - https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz || exit 5
exists_dir lua-* ||
curl -Lo - https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz || exit 5
)
}
build_netlink()
{
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
[ -f "Makefile" ] && make clean
CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" \
LDFLAGS="$LDMINSIZE $LDFLAGS" \
./configure --prefix= --host=$TARGET CC=$CC LD=$LD --enable-static --disable-shared --disable-dependency-tracking
make install -j$nproc DESTDIR=$STAGING_DIR
)
sed -i "s|^prefix=.*|prefix=$STAGING_DIR|g" $STAGING_DIR/lib/pkgconfig/$i.pc
done
}
build_zlib()
{
(
cd zlib-*
[ -f "Makefile" ] && make clean
CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" \
LDFLAGS="$LDMINSIZE $LDFLAGS" \
./configure --prefix= --static
make install -j$nproc DESTDIR=$STAGING_DIR
)
}
build_lua()
{
(
cd lua-${LUA_RELEASE}
make clean
make CC="$CC" AR="$AR rc" CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$nproc
make install INSTALL_TOP="$STAGING_DIR" INSTALL_BIN="$STAGING_DIR/bin" INSTALL_INC="$STAGING_DIR/include/lua${LUA_VER}" INSTALL_LIB="$STAGING_DIR/lib"
)
}
build_luajit()
{
(
cd luajit2-*
make clean
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOST_CC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
make install PREFIX= DESTDIR="$STAGING_DIR"
)
}
build_luajit_for_target()
{
target_has_luajit $1 && {
case "$1" in
*64*)
HOST_CC="$HOSTCC"
;;
*)
HOST_CC="$HOSTCC -m32"
;;
esac
build_luajit
}
}
check_prog curl tar gzip bzip2 sed make cc pkg-config
check_h_files
dl_deps
check_toolchains
ask_target
for t in $TGT; do
buildenv $t
pushd "$DEPS"
install_h_files
build_netlink
build_zlib
build_lua
build_luajit_for_target $t
popd
buildenv_clear
done

View File

@@ -0,0 +1,62 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
ZDIR="zapret"
ZBASE="$EXEDIR"
BRANCH=master
ZURL=https://github.com/bol-van/zapret/archive/refs/heads/${BRANCH}.zip
ZBIN="$EXEDIR/binaries"
dl_zapret1()
{
if [ -d "$ZBASE/$ZDIR" ]; then
dir_is_not_empty "$ZBASE/$ZDIR" && {
echo "zapret dir is not empty. if you want to redownload - delete it."
return
}
rmdir "$ZBASE/$ZDIR"
fi
(
cd "$ZBASE"
curl -Lo /tmp/zapret.zip "$ZURL"
unzip /tmp/zapret.zip
rm /tmp/zapret.zip
mv zapret-${BRANCH} $ZDIR
)
}
check_prog curl unzip make
dl_zapret1
check_toolchains
ask_target
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
for t in $TGT; do
buildenv $t
translate_target $t || {
echo COULD NOT TRANSLATE TARGET $t TO BIN DIR
continue
}
pushd $ZBASE/$ZDIR
make clean
OPTIMIZE=$OPTIMIZE \
CFLAGS="-static-libgcc -static -I$STAGING_DIR/include $MINSIZE $CFLAGS" \
LDFLAGS="-L$STAGING_DIR/lib $LDMINSIZE $LDFLAGS" \
make
[ -d "$ZBIN/$ZBINTARGET" ] || mkdir "$ZBIN/$ZBINTARGET"
cp -f binaries/my/* "$ZBIN/$ZBINTARGET"
popd
buildenv_clear
done

View File

@@ -0,0 +1,73 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
ZDIR="zapret2"
ZBASE="$EXEDIR"
BRANCH=master
ZURL=https://github.com/bol-van/zapret2/archive/refs/heads/${BRANCH}.zip
ZBIN="$EXEDIR/binaries"
dl_zapret2()
{
if [ -d "$ZBASE/$ZDIR" ]; then
dir_is_not_empty "$ZBASE/$ZDIR" && {
echo "zapret2 dir is not empty. if you want to redownload - delete it."
return
}
rmdir "$ZBASE/$ZDIR"
fi
(
cd "$ZBASE"
curl -Lo /tmp/zapret2.zip "$ZURL"
unzip /tmp/zapret2.zip
rm /tmp/zapret2.zip
mv zapret2-${BRANCH} $ZDIR
)
}
check_prog curl unzip make
dl_zapret2
check_toolchains
ask_target
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
for t in $TGT; do
buildenv $t
translate_target $t || {
echo COULD NOT TRANSLATE TARGET $t TO BIN DIR
continue
}
pushd $ZBASE/$ZDIR
LUA_JIT=0
LCFLAGS="-I${STAGING_DIR}/include/lua${LUA_VER}"
LLIB="-L${STAGING_DIR}/lib -llua"
target_has_luajit $t && {
LUA_JIT=1
LCFLAGS="-I${STAGING_DIR}/include/luajit-${LUAJIT_VER}"
LLIB="-L${STAGING_DIR}/lib -lluajit-${LUAJIT_LUA_VER}"
}
make clean
LUA_JIT=$LUA_JIT LUA_VER=$LUA_VER LUAJIT_LUA_VER=$LUAJIT_LUA_VER \
OPTIMIZE=$OPTIMIZE \
MINSIZE=$MINSIZE \
CFLAGS="-static-libgcc -static -I$STAGING_DIR/include $CFLAGS" \
LDFLAGS="-L$STAGING_DIR/lib $LDFLAGS" \
make LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB"
[ -d "$ZBIN/$ZBINTARGET" ] || mkdir "$ZBIN/$ZBINTARGET"
cp -f binaries/my/* "$ZBIN/$ZBINTARGET"
popd
buildenv_clear
done

View File

@@ -0,0 +1,283 @@
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
TOOLCHAINS="$EXEDIR/toolchain"
DEPS="$EXEDIR/deps"
STAGE="$EXEDIR/staging"
OPTIMIZE=${OPTIMIZE:--Oz}
MINSIZE="${MINSIZE:--flto=auto -ffunction-sections -fdata-sections}"
LDMINSIZE="${LDMINSIZE:--Wl,--gc-sections -flto=auto}"
#CFLAGS=""
LDFLAGS="-lgcc_eh $LDFLAGS"
HOSTCC=${HOSTCC:-cc}
LUA_VER=${LUA_VER:-5.5}
LUA_RELEASE=${LUA_RELEASE:-5.5.0}
LUAJIT_VER=${LUAJIT_VER:-2.1}
LUAJIT_RELEASE=${LUAJIT_RELEASE:-2.1-20250826}
LUAJIT_LUA_VER=${LUAJIT_LUA_VER:-5.1}
nproc=$(nproc)
TARGETS="\
aarch64-unknown-linux-musl \
arm-unknown-linux-musleabi \
i586-unknown-linux-musl \
x86_64-unknown-linux-musl \
mips-unknown-linux-muslsf \
mips64-unknown-linux-musl \
mips64el-unknown-linux-musl \
mipsel-unknown-linux-muslsf \
powerpc-unknown-linux-musl \
riscv64-unknown-linux-musl \
"
target_has_luajit()
{
case "$1" in
aarch64-unknown-linux-musl| \
arm-unknown-linux-musleabi| \
x86_64-unknown-linux-musl| \
mips-unknown-linux-muslsf| \
mips64-unknown-linux-musl| \
mips64el-unknown-linux-musl| \
mipsel-unknown-linux-muslsf| \
powerpc-unknown-linux-musl) \
return 0
;;
esac
return 1
}
REQD_H_FILES="/usr/include/sys/capability.h /usr/include/bits/libc-header-start.h"
REQD_QUEUE_1="/usr/include/sys/queue.h"
REQD_QUEUE_2="/usr/include/x86_64-linux-gnu/sys/queue.h"
check_h_files()
{
[ ! -f "$REQD_QUEUE_1" -a ! -f "$REQD_QUEUE_2" ] && {
echo "could not find $REQD_QUEUE_1 or $REQD_QUEUE_2"
help_pkg
exit 10
}
check_file $REQD_H_FILES
}
install_h_files()
{
if [ -f "$REQD_QUEUE_1" ]; then
install -Dm644 -t $STAGING_DIR/include/sys $REQD_QUEUE_1
elif [ -f "$REQD_QUEUE_2" ]; then
install -Dm644 -t $STAGING_DIR/include/sys $REQD_QUEUE_2
fi
install -Dm644 -t $STAGING_DIR/include/sys $REQD_H_FILES
}
buildenv()
{
# $1 = arch
export TARGET=$1
export CC=$TARGET-gcc
export LD=$TARGET-ld
export AR=$TARGET-ar
export NM=$TARGET-nm
export STRIP=$TARGET-strip
export STAGING_DIR="$EXEDIR/staging/$TARGET"
[ -d "$STAGING_DIR" ] || {
mkdir -p "$STAGING_DIR"
mkdir -p "$STAGING_DIR/lib/pkgconfig"
mkdir -p "$STAGING_DIR/bin"
mkdir -p "$STAGING_DIR/include"
}
export PKG_CONFIG_PATH=$STAGING_DIR/lib/pkgconfig
OLDPATH="$PATH"
export PATH="$PATH:$TOOLCHAINS/$TARGET/bin"
}
buildenv_clear()
{
export PATH="$OLDPATH" TARGET= CC= LD= AR= NM= STRIP= STAGING_DIR= PKG_CONFIG_PATH=
OLDPATH=
}
which()
{
# on some systems 'which' command is considered deprecated and not installed by default
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
# $1 - executable name
local IFS=:
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
echo "$1"
return 0
}
for p in $PATH; do
[ -x "$p/$1" ] && {
echo "$p/$1"
return 0
}
done
return 1
}
exists()
{
which "$1" >/dev/null 2>/dev/null
}
exists_dir()
{
# use $1, ignore other args
[ -d "$1" ]
}
dir_is_not_empty()
{
# $1 - directory
local n
[ -d "$1" ] || return 1
n=$(ls -A "$1" | wc -c | xargs)
[ "$n" != 0 ]
}
find_str_in_list()
{
# $1 - string
# $2 - space separated values
local v
[ -n "$1" ] && {
for v in $2; do
[ "$v" = "$1" ] && return 0
done
}
return 1
}
ask_list()
{
# $1 - mode var
# $2 - space separated value list
# $3 - (optional) default value
local M_DEFAULT
eval M_DEFAULT="\$$1"
local M_DEFAULT_VAR="$M_DEFAULT"
local M="" m
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
n=1
for m in $2; do
echo $n : $m
n=$(($n+1))
done
printf "your choice (default : $M_DEFAULT) : "
read m
[ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null)
[ -z "$M" ] && M="$M_DEFAULT"
echo selected : $M
eval $1="\"$M\""
[ "$M" != "$M_DEFAULT_VAR" ]
}
ask_target()
{
# $1 = 1 = ask all, otherwise ask only present toolchains
# already set ?
[ -n "$TGT" ] && return
local d ALL_TARGETS
[ "$1" = 1 ] || {
if dir_is_not_empty "$TOOLCHAINS"; then
for d in "$TOOLCHAINS"/*; do
[ -d "$d" ] && {
d="$(basename "$d")"
ALL_TARGETS="$ALL_TARGETS $d"
}
done
fi
}
[ -n "$ALL_TARGETS" ] || ALL_TARGETS="$TARGETS"
echo "select target :"
ask_list TARGET "ALL $ALL_TARGETS" "ALL"
echo
echo selected TARGET : $TARGET
echo
if [ $TARGET = ALL ]; then
TGT="$ALL_TARGETS"
else
TGT="$TARGET"
fi
}
check_toolchains()
{
dir_is_not_empty "$TOOLCHAINS" || {
echo DOWNLOAD TOOLCHAINS FIRST
exit 1
}
}
help_pkg()
{
echo "debian/ubuntu: apt install curl xz-utils bzip2 unzip make gcc gcc-multilib libc6-dev libcap-dev pkg-config"
echo "fedora: dnf install curl xz bzip2 unzip make gcc glibc-devel glibc-devel.i686 libcap-devel pkg-config"
}
check_prog()
{
while [ -n "$1" ]; do
exists $1 || {
echo $1 is not available
help_pkg
exit 10
}
shift
done
}
check_file()
{
while [ -n "$1" ]; do
[ -f "$1" ] || {
echo $1 is not available
help_pkg
exit 10
}
shift
done
}
translate_target()
{
case $1 in
aarch64-unknown-linux-musl)
ZBINTARGET=linux-arm64
;;
arm-unknown-linux-musleabi)
ZBINTARGET=linux-arm
;;
x86_64-unknown-linux-musl)
ZBINTARGET=linux-x86_64
;;
i586-unknown-linux-musl)
ZBINTARGET=linux-x86
;;
mips-unknown-linux-muslsf)
ZBINTARGET=linux-mips
;;
mipsel-unknown-linux-muslsf)
ZBINTARGET=linux-mipsel
;;
mips64-unknown-linux-musl)
ZBINTARGET=linux-mips64
;;
mips64el-unknown-linux-musl)
ZBINTARGET=linux-mipsel64
;;
powerpc-unknown-linux-musl)
ZBINTARGET=linux-ppc
;;
riscv64-unknown-linux-musl)
ZBINTARGET=linux-riscv64
;;
*)
return 1
esac
return 0
}

View File

@@ -0,0 +1,22 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
BASEURL=https://github.com/bol-van/musl-cross/releases/download/latest
check_prog curl tar xz
[ -d "$TOOLCHAINS" ] || mkdir -p "$TOOLCHAINS"
ask_target 1
(
cd "$TOOLCHAINS"
for t in $TGT; do
[ -d "$t" ] && rm -r "$t"
curl -Lo - "${BASEURL}/${t}.tar.xz" | tar -Jx
done
)

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
@@ -3553,11 +3554,16 @@ Aggregates verdicts v1 and v2. VERDICT_MODIFY overrides VERDICT_PASS, while VERD
```
function plan_instance_execute(desync, verdict, instance)
function plan_instance_execute_preapplied(desync, verdict, instance)
```
Executes an [execution plan](#execution_plan) `instance`, taking into account the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters.
Returns the aggregation of the current verdict and the `instance` verdict.
The "preapplied" version does not apply execution plan, allowing the calling code to do so.
Sometimes, to decide whether to call an instance, you need a desync table configured for the called instance.
"preapplied" version allows to avoid double copying.
### plan_instance_pop
```
@@ -4472,7 +4478,7 @@ Returns `true` if the dissect is tcp and has tcp timestamp option.
function cond_lua(desync)
```
Executes a Lua code from the "code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code.
Executes a Lua code from the "cond_code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code.
# Auxiliary programs

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
@@ -3732,11 +3733,16 @@ function verdict_aggregate(v1, v2)
```
function plan_instance_execute(desync, verdict, instance)
function plan_instance_execute_preapplied(desync, verdict, instance)
```
Выполняет элемент [execution plan](#execution_plan) `instance` с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры).
Возвращает агрегацию verdict и вердикта `instance`.
Вариант "preapplied" не выполняет apply_execution_plan, позволяя это сделат вызывающему коду.
Иногда для принятия решения вызывать ли instance требуется таблица desync, настроенная на вызываемый инстанс.
Чтобы не делать apply дважды (там копирование desync.arg) и существует этот вариант.
### plan_instance_pop
```
@@ -4651,7 +4657,7 @@ function cond_tcp_ts(desync)
function cond_lua(desync)
```
Выполняет Lua код из аргумента "code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
Выполняет Lua код из аргумента "cond_code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
# Вспомогательные программы

Binary file not shown.

View File

@@ -1,13 +0,0 @@
REGISTER sip:192.168.1.1 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.2:42931;rport;branch=z9hG4bKPj3fd2e8713ffcd90c43f6ce69f6c98461
Max-Forwards: 50
From: <sip:703@192.168.1.1>;tag=ca565d7bd4e24a6d80c631d395ee117e
To: <sip:703@192.168.1.1>
Call-ID: dfec38302b8cea3d83c1452527c895c1
CSeq: 26139 REGISTER
User-Agent: MicroSIP/3.21.5
Contact: <sip:703@192.168.1.2:42931;ob>
Expires: 300
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Content-Length: 0

View File

@@ -2,8 +2,8 @@
WEBSERVER_DEFAULT_STRATEGY="
--server
--payload http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
--payload empty --lua-desync=synack_split"
--payload=http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
--payload=empty --lua-desync=synack_split"
# can override in config :
NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}"

View File

@@ -2,7 +2,7 @@
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload dht --lua-desync=dht_dn}"
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload=dht --lua-desync=dht_dn}"
# set it to "keepalive" to fool all packets, not just the first. or set number of packets to be fooled.
NFQWS_OPT_DHT_PKT_OUT=${NFQWS_OPT_DHT_PKT_OUT:-20}

View File

@@ -2,7 +2,7 @@
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload=discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
alloc_dnum DNUM_DISCORD_MEDIA

View File

@@ -1,7 +1,7 @@
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
# can override in config :
NFQWS2_MY1_OPT="${NFQWS2_MY1_OPT:---filter-udp=* --payload known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
NFQWS2_MY1_OPT="${NFQWS2_MY1_OPT:---filter-udp=* --payload=known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
NFQWS2_MY1_SUBNETS4="${NFQWS2_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
NFQWS2_MY1_SUBNETS6="${NFQWS2_MY1_SUBNETS6:-2a00:1450::/29}"
NFQWS2_MY1_PORTS_TCP=${NFQWS2_MY1_PORTS_TCP:-$NFQWS2_PORTS_TCP}

View File

@@ -2,7 +2,7 @@
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
alloc_dnum DNUM_QUIC4ALL
alloc_qnum QNUM_QUIC4ALL

View File

@@ -2,7 +2,7 @@
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload=stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
alloc_dnum DNUM_STUN4ALL
alloc_qnum QNUM_STUN4ALL

View File

@@ -3,7 +3,7 @@
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload=wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
alloc_dnum DNUM_WG4ALL
alloc_qnum QNUM_WG4ALL

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-mipsel64 linux-mipsel linux-mips linux-lexra linux-ppc linux-riscv64"
PKTWS=nfqws2
;;
FreeBSD)

View File

@@ -729,14 +729,15 @@ function hostfakesplit(ctx, desync)
local midhost
if desync.arg.midhost then
midhost = resolve_pos(data,desync.l7payload,desync.arg.midhost)
if not midhost then
if midhost then
DLOG("hosfakesplit: midhost marker resolved to "..midhost)
if midhost<=pos[1] or midhost>pos[2] then
DLOG("hostfakesplit: midhost is not inside the host range")
midhost = nil
end
else
DLOG("hostfakesplit: cannot resolve midhost marker '"..desync.arg.midhost.."'")
end
DLOG("hosfakesplit: midhost marker resolved to "..midhost)
if midhost<=pos[1] or midhost>pos[2] then
DLOG("hostfakesplit: midhost is not inside the host range")
midhost = nil
end
end
-- if present apply ipfrag only to real host parts. fakes and parts outside of the host must be visible to DPI.
if midhost then
@@ -942,7 +943,7 @@ function fakeddisorder(ctx, desync)
local opts_orig = {rawsend = rawsend_opts_base(desync), reconstruct = {}, ipfrag = {}, ipid = desync.arg, fooling = {tcp_ts_up = desync.arg.tcp_ts_up}}
local opts_fake = {rawsend = rawsend_opts(desync), reconstruct = reconstruct_opts(desync), ipfrag = {}, ipid = desync.arg, fooling = desync.arg}
fakepat = desync.arg.pattern and blob(desync,desync.arg.pattern) or "\x00"
local fakepat = desync.arg.pattern and blob(desync,desync.arg.pattern) or "\x00"
-- second fake
fake = pattern(fakepat,pos,#data-pos+1)

View File

@@ -411,19 +411,19 @@ function cond_tcp_has_ts(desync)
end
-- exec lua code in "code" arg and return it's result
function cond_lua(desync)
if not desync.arg.code then
error("cond_lua: no 'code' parameter")
if not desync.arg.cond_code then
error("cond_lua: no 'cond_code' parameter")
end
local fname = desync.func_instance.."_cond_code"
local fname = desync.func_instance.."_cond_cond_code"
if not _G[fname] then
local err
_G[fname], err = load(desync.arg.code, fname)
_G[fname], err = load(desync.arg.cond_code, fname)
if not _G[fname] then
error(err)
return
end
end
-- allow dynamic code to access desync
-- allow dynamic cond_code to access desync
_G.desync = desync
local res, v = pcall(_G[fname])
_G.desync = nil
@@ -479,8 +479,10 @@ function per_instance_condition(ctx, desync)
if type(_G[instance.arg.cond])~="function" then
error("per_instance_condition: invalid 'iff' function '"..instance.arg.cond.."'")
end
-- preapply exec plan to feed cond function correct args
apply_execution_plan(desync, instance)
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
verdict = plan_instance_execute(desync, verdict, instance)
verdict = plan_instance_execute_preapplied(desync, verdict, instance)
else
DLOG("per_instance_condition: condition not satisfied. skipping '"..instance.func_instance.."'")
end

View File

@@ -96,7 +96,7 @@ function detect_payload_str(ctx, desync)
error("detect_payload_str: missing 'pattern'")
end
local data = desync.reasm_data or desync.dis.payload
local b = string.find(data,desync.arg.pattern,1,true)
local b = data and string.find(data,desync.arg.pattern,1,true)
if b then
DLOG("detect_payload_str: detected '"..desync.arg.payload.."'")
if desync.arg.payload then desync.l7payload = desync.arg.payload end
@@ -153,7 +153,7 @@ function apply_arg_prefix(desync)
local c = string.sub(v,1,1)
if c=='#' then
local blb = blob(desync,string.sub(v,2))
desync.arg[a] = (type(blb)=='string' or type(blb)=='table') and #blb or 0
desync.arg[a] = tostring((type(blb)=='string' or type(blb)=='table') and #blb or 0)
elseif c=='%' then
desync.arg[a] = blob(desync,string.sub(v,2))
elseif c=='\\' then
@@ -192,8 +192,7 @@ function verdict_aggregate(v1, v2)
end
return bitor(v,vn)
end
function plan_instance_execute(desync, verdict, instance)
apply_execution_plan(desync, instance)
function plan_instance_execute_preapplied(desync, verdict, instance)
if cutoff_shim_check(desync) then
DLOG("plan_instance_execute: not calling '"..desync.func_instance.."' because of voluntary cutoff")
elseif not payload_match_filter(desync.l7payload, instance.payload_filter) then
@@ -206,6 +205,10 @@ function plan_instance_execute(desync, verdict, instance)
end
return verdict
end
function plan_instance_execute(desync, verdict, instance)
apply_execution_plan(desync, instance)
return plan_instance_execute_preapplied(desync,verdict,instance)
end
function plan_instance_pop(desync)
return (desync.plan and #desync.plan>0) and table.remove(desync.plan, 1) or nil
end
@@ -334,9 +337,8 @@ end
-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved
function barray(a, packer)
local sa={}
if a then
local s=""
local sa={}
for i=1,#a do
sa[i] = packer(a[i])
end
@@ -345,16 +347,16 @@ function barray(a, packer)
end
-- convert table a to packed string using 'packer' function. any indexes, any order
function btable(a, packer)
local sa={}
if a then
local s=""
local sa={}
local i=1
for k,v in pairs(a) do
sa[k] = packer(v)
sa[i] = packer(v)
i=i+1
end
return table.concat(sa)
end
end
-- sequence comparision functions. they work only within 2G interval
-- seq1>=seq2
function seq_ge(seq1, seq2)
@@ -434,7 +436,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
@@ -545,6 +547,7 @@ function blob(desync, name, def)
error("blob '"..name.."' unavailable")
end
end
blob = tostring(blob)
end
return blob
end
@@ -805,9 +808,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
@@ -872,7 +875,11 @@ function apply_fooling(desync, dis, fooling_options)
if type(desync.track.lua_state.autottl_cache)~="table" then desync.track.lua_state.autottl_cache={} end
if type(desync.track.lua_state.autottl_cache[desync.func_instance])~="table" then desync.track.lua_state.autottl_cache[desync.func_instance]={} end
if not desync.track.lua_state.autottl_cache[desync.func_instance].autottl_found then
desync.track.lua_state.autottl_cache[desync.func_instance].autottl = autottl(desync.track.incoming_ttl,parse_autottl(arg_autottl))
attl = parse_autottl(arg_autottl)
if not attl then
error("apply_fooling: invalid autottl value '"..arg_autottl.."'")
end
desync.track.lua_state.autottl_cache[desync.func_instance].autottl = autottl(desync.track.incoming_ttl,attl)
if desync.track.lua_state.autottl_cache[desync.func_instance].autottl then
desync.track.lua_state.autottl_cache[desync.func_instance].autottl_found = true
DLOG("apply_fooling: discovered autottl "..desync.track.lua_state.autottl_cache[desync.func_instance].autottl)
@@ -887,8 +894,11 @@ function apply_fooling(desync, dis, fooling_options)
DLOG("apply_fooling: cannot apply autottl because incoming ttl unknown")
end
end
if not ttl and tonumber(arg_ttl) then
if not ttl and arg_ttl then
ttl = tonumber(arg_ttl)
if not ttl or ttl<0 or ttl>255 then
error("apply_fooling: ip_ttl and ip6_ttl require valid value")
end
end
--io.stderr:write("TTL "..tostring(ttl).."\n")
return ttl
@@ -905,11 +915,19 @@ function apply_fooling(desync, dis, fooling_options)
-- use current packet if dissect not given
if not dis then dis = desync.dis end
if dis.tcp then
if tonumber(fooling_options.tcp_seq) then
dis.tcp.th_seq = u32add(dis.tcp.th_seq, fooling_options.tcp_seq)
if fooling_options.tcp_seq then
if tonumber(fooling_options.tcp_seq) then
dis.tcp.th_seq = u32add(dis.tcp.th_seq, fooling_options.tcp_seq)
else
error("apply_fooling: tcp_seq requires increment parameter. there's no default value.")
end
end
if tonumber(fooling_options.tcp_ack) then
dis.tcp.th_ack = u32add(dis.tcp.th_ack, fooling_options.tcp_ack)
if fooling_options.tcp_ack then
if tonumber(fooling_options.tcp_ack) then
dis.tcp.th_ack = u32add(dis.tcp.th_ack, fooling_options.tcp_ack)
else
error("apply_fooling: tcp_ack requires increment parameter. there's no default value.")
end
end
if fooling_options.tcp_flags_unset then
dis.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(parse_tcp_flags(fooling_options.tcp_flags_unset)))
@@ -924,12 +942,16 @@ function apply_fooling(desync, dis, fooling_options)
end
end
end
if tonumber(fooling_options.tcp_ts) then
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
dis.tcp.options[idx].data = bu32(u32add(u32(dis.tcp.options[idx].data),fooling_options.tcp_ts))..string.sub(dis.tcp.options[idx].data,5)
if fooling_options.tcp_ts then
if tonumber(fooling_options.tcp_ts) then
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
dis.tcp.options[idx].data = bu32(u32add(u32(dis.tcp.options[idx].data),fooling_options.tcp_ts))..string.sub(dis.tcp.options[idx].data,5)
else
DLOG("apply_fooling: timestamp tcp option not present or invalid")
end
else
DLOG("apply_fooling: timestamp tcp option not present or invalid")
error("apply_fooling: tcp_ts requires increment parameter. there's no default value.")
end
end
if fooling_options.tcp_md5 then
@@ -1161,16 +1183,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
@@ -1616,9 +1637,9 @@ function gzip_file(filename, data, expected_ratio, level, memlevel, compress_blo
if not gz then
error("gzip_file: stream init error")
end
local off=1, block_size
local off=1
repeat
block_size = #data-off+1
local block_size = #data-off+1
if block_size>compress_block_size then block_size=compress_block_size end
local comp, eof = gzip_deflate(gz, string.sub(data,off,off+block_size-1), block_size / expected_ratio)
if not comp then
@@ -2125,7 +2146,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 +2185,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 +2469,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 +2489,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 +2499,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

@@ -1,6 +1,6 @@
function pcap_write_header(file)
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0x4000 (16384), 0x65 - l3 packets without l2
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x65")
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0xFFFF (65535), 0x65 - l3 packets without l2
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x65")
end
function pcap_write_packet(file, raw)
local sec, nsec = clock_gettime();
@@ -34,6 +34,7 @@ function pcap(ctx, desync)
if not f then
error("pcap: could not write to '".._G[fn_cache_name].."'")
end
pcap_write(f, raw_packet(ctx))
local raw = ctx and raw_packet(ctx) or reconstruct_dissect(desync.dis)
pcap_write(f, raw)
f:close()
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,13 +1,15 @@
CC ?= cc
PKG_CONFIG ?= pkg-config
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto -Wl,--gc-sections
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

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
// 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;
@@ -167,9 +172,6 @@ static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
if (bReverse)
{
t->pos.server.pcounter++;
@@ -283,7 +285,7 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *d
}
return false;
ok:
ctr->track.ipproto = proto;
ctr->track.pos.ipproto = proto;
if (ctrack) *ctrack = &ctr->track;
if (bReverse) *bReverse = b_rev;
return true;
@@ -347,7 +349,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) {
@@ -365,8 +367,8 @@ void ConntrackPoolDump(const t_conntrack *p)
t->track.pos.client.seq0, t->track.pos.client.seq_last - t->track.pos.client.seq0, t->track.pos.client.pos - t->track.pos.client.seq0,
t->track.pos.server.seq0, t->track.pos.server.seq_last - t->track.pos.server.seq0, t->track.pos.server.pos - t->track.pos.server.seq0,
t->track.pos.client.mss, t->track.pos.server.mss,
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
t->track.pos.client.winsize, t->track.pos.client.scale,
t->track.pos.server.winsize, t->track.pos.server.scale);
else
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
t->track.pos.client.seq_last, t->track.pos.client.pos,

View File

@@ -53,7 +53,6 @@ typedef struct {
typedef struct
{
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
uint8_t ipproto;
struct timespec t_start;

View File

@@ -21,15 +21,15 @@ typedef struct
uint32_t ip6flow;
// tcp only state, not used in udp
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
uint32_t pos; // seq_last+payload, ack_last+payload
uint32_t uppos; // max seen position. useful to detect retransmissions
uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions
uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
uint32_t seq_last; // last seen seq and ack
uint32_t seq0; // starting seq and ack
uint16_t winsize; // last seen window size
uint16_t mss;
uint32_t winsize_calc; // calculated window size
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
uint8_t scale; // last seen window scale factor
bool rseq_over_2G;
} t_ctrack_position;
@@ -38,5 +38,6 @@ typedef struct
struct timespec t_last;
t_connstate state;
t_ctrack_position client, server;
uint8_t ipproto;
}
t_ctrack_positions;

View File

@@ -48,7 +48,7 @@ uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
{
return htonl(ntohl(netorder_value)+cpuorder_increment);
}
uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
uint16_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
{
return htons(ntohs(netorder_value)+cpuorder_increment);
}
@@ -229,7 +229,7 @@ uint16_t family_from_proto(uint8_t l3proto)
{
case IPPROTO_IP: return AF_INET;
case IPPROTO_IPV6: return AF_INET6;
default: return -1;
default: return AF_UNSPEC;
}
}
@@ -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);
}
@@ -335,7 +335,7 @@ void str_tcphdr(char *s, size_t s_len, const struct tcphdr *tcphdr)
if (tcphdr->th_flags & TH_PUSH) *f++='P';
if (tcphdr->th_flags & TH_URG) *f++='U';
*f=0;
snprintf(s,s_len,"sport=%u dport=%u flags=%s seq=%u ack_seq=%u",htons(tcphdr->th_sport),htons(tcphdr->th_dport),flags,htonl(tcphdr->th_seq),htonl(tcphdr->th_ack));
snprintf(s,s_len,"sport=%u dport=%u flags=%s seq=%u ack_seq=%u",ntohs(tcphdr->th_sport),ntohs(tcphdr->th_dport),flags,ntohl(tcphdr->th_seq),ntohl(tcphdr->th_ack));
}
void print_tcphdr(const struct tcphdr *tcphdr)
{
@@ -345,7 +345,7 @@ void print_tcphdr(const struct tcphdr *tcphdr)
}
void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr)
{
snprintf(s,s_len,"sport=%u dport=%u",htons(udphdr->uh_sport),htons(udphdr->uh_dport));
snprintf(s,s_len,"sport=%u dport=%u",ntohs(udphdr->uh_sport),ntohs(udphdr->uh_dport));
}
void print_udphdr(const struct udphdr *udphdr)
{
@@ -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;
}
@@ -557,11 +557,15 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
dis->data_pkt = data;
dis->len_pkt = len;
uint16_t iplen;
if (proto_check_ipv4(data, len) && (no_payload_check || proto_check_ipv4_payload(data, len)))
{
dis->ip = (const struct ip *) data;
dis->proto = dis->ip->ip_p;
p = data;
iplen = ntohs(((struct ip*)data)->ip_len);
if (iplen<len) dis->len_pkt = len = iplen;
proto_skip_ipv4(&data, &len, &dis->frag, &dis->frag_off);
dis->len_l3 = data-p;
}
@@ -569,6 +573,8 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
{
dis->ip6 = (const struct ip6_hdr *) data;
p = data;
iplen = ntohs(((struct ip6_hdr*)data)->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr);
if (iplen<len) dis->len_pkt = len = iplen;
proto_skip_ipv6(&data, &len, &dis->proto, &dis->frag, &dis->frag_off);
dis->len_l3 = data-p;
}
@@ -922,11 +928,29 @@ BOOL SetMandatoryLabelObject(HANDLE h, SE_OBJECT_TYPE ObjType, DWORD dwMandatory
bool ensure_file_access(const char *filename)
{
return SetMandatoryLabelFile(filename, SECURITY_MANDATORY_LOW_RID, 0);
bool b=false;
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, filename, NULL, 0);
WCHAR *wfilename = (WCHAR*)malloc(l);
if (wfilename)
{
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, filename, wfilename, l))
b = SetMandatoryLabelFileW(wfilename, SECURITY_MANDATORY_LOW_RID, 0);
free(wfilename);
}
return b;
}
bool ensure_dir_access(const char *dir)
{
return SetMandatoryLabelFile(dir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
bool b=false;
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, dir, NULL, 0);
WCHAR *wdir = (WCHAR*)malloc(l);
if (wdir)
{
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, dir, wdir, l))
b=SetMandatoryLabelFileW(wdir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
free(wdir);
}
return b;
}
bool prepare_low_appdata()
@@ -1557,7 +1581,6 @@ void rawsend_cleanup(void)
{
if (w_filter)
{
CancelIoEx(w_filter,&ovl);
WinDivertClose(w_filter);
w_filter=NULL;
}
@@ -1585,71 +1608,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 +1820,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 +1904,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)
{
@@ -2075,6 +2099,7 @@ static uint16_t wlan_get_family_id(struct mnl_socket* nl)
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
{
struct wlan_interface *wlan = (struct wlan_interface *)data;
size_t len;
switch(mnl_attr_get_type(attr))
{
case NL80211_ATTR_IFINDEX:
@@ -2086,12 +2111,10 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
wlan->ifindex = mnl_attr_get_u32(attr);
break;
case NL80211_ATTR_SSID:
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
{
DLOG_PERROR("mnl_attr_validate(ssid)");
return MNL_CB_ERROR;
}
snprintf(wlan->ssid,sizeof(wlan->ssid),"%s",mnl_attr_get_str(attr));
len = mnl_attr_get_payload_len(attr);
if (len>=sizeof(wlan->ssid)) len=sizeof(wlan->ssid)-1;
memcpy(wlan->ssid, mnl_attr_get_payload(attr), len);
wlan->ssid[len]=0;
break;
case NL80211_ATTR_IFNAME:
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
@@ -2137,8 +2160,8 @@ static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie)
{
if (len<(2+buf[1])) break;
if (buf[0]==ie) return buf;
buf+=buf[1]+2;
len-=buf[1]+2;
buf+=buf[1]+2;
}
return NULL;
}
@@ -2221,6 +2244,7 @@ static bool scan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wla
// wlan_info does not return ssid since kernel 5.19
// it's used to enumerate all wifi interfaces then call scan_info on each
if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false;
w->count=0;
for(int i=0;i<wc_all.count;i++)
if (!netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0, scan_prepare, (void*)&wc_all.wlan[i].ifindex, scan_info_cb, w))
return false;
@@ -2434,20 +2458,11 @@ bool make_writeable_dir()
if (mkdir(wrdir,0755) && errno!=EEXIST)
return false;
bool b = false;
bool b;
#ifdef __CYGWIN__
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, wrdir, NULL, 0);
WCHAR *wwrdir = (WCHAR*)malloc(l);
if (wwrdir)
{
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, wrdir, wwrdir, l))
b = SetMandatoryLabelFileW(wwrdir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
free(wwrdir);
}
b = ensure_dir_access(wrdir);
#else
if (ensure_dir_access(wrdir))
b = true;
else
if (!(b=ensure_dir_access(wrdir)))
{
// could not chown. may be still accessible ?
char testfile[PATH_MAX];

View File

@@ -94,7 +94,7 @@
// returns netorder value
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
uint16_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define SCALE_NONE ((uint8_t)-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 : "");
@@ -556,7 +556,7 @@ static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_
// server gave us too small tcp window
// client will not send all pieces of reasm
// if we drop packets and wait for next pieces we will see nothing but retransmissions
DLOG("reasm cancelled because server window size %u is smaller than expected reasm size %u\n", ctrack->pos.server.winsize_calc, sz);
DLOG("reasm cancelled because server window size %u is smaller than expected reasm size %zu\n", ctrack->pos.server.winsize_calc, sz);
return false;
}
return reasm_start(ctrack, &ctrack->reasm_client, proto, (proto == IPPROTO_TCP) ? ctrack->pos.client.seq_last : 0, sz, szMax, data_payload, len_payload);
@@ -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,20 +1574,21 @@ 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))
{
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos))
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos, false))
{
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ps.ctrack->delayed));
}
else
{
DLOG_ERR("rawpacket_queue failed !\n");
goto pass_reasm_cancel;
goto rediscover;
}
if (ReasmIsFull(&ps.ctrack->reasm_client))
{
@@ -1601,6 +1602,8 @@ static uint8_t dpi_desync_tcp_packet_play(
}
}
// UNSOLVED: if reasm is cancelled all packets except the last are passed as is without lua desync
rediscover:
if (!dp_rediscovery(&ps))
goto pass_reasm_cancel;
@@ -1645,8 +1648,12 @@ static const uint8_t *dns_extract_name(const uint8_t *a, const uint8_t *b, const
{
size_t nl, off;
const uint8_t *p;
bool bptr = (*a & 0xC0)==0xC0;
bool bptr;
uint8_t x,y;
if (!name_size) return NULL;
bptr = (*a & 0xC0)==0xC0;
if (bptr)
{
if (a+1>=e) return NULL;
@@ -1661,66 +1668,115 @@ 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;
if (nl) name[nl++] = '.';
memcpy(name + nl, p + 1, *p);
nl += *p;
p += *p + 1;
if (nl)
{
if (nl>=name_size) return NULL;
name[nl++] = '.';
}
// do not support mixed ptr+real
if ((*p & 0xC0) || (p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
for(y=*p++,x=0 ; x<y ; x++,p++) name[nl+x] = tolower(*p);
nl += y;
}
if (nl>=name_size) return NULL;
name[nl] = 0;
return bptr ? a+2 : p+1;
}
static bool dns_skip_name(const uint8_t **a, size_t *len)
{
// 11 higher bits indicate pointer
// lazy skip name. mixed compressed/uncompressed names are supported
for(;;)
{
if (*len<2) return false;
if ((**a & 0xC0)==0xC0)
{
// pointer is the end
(*a)+=2; (*len)-=2;
break;
}
if (!**a)
{
// zero length is the end
(*a)++; (*len)--;
break;
}
if (*len<(**a+1)) return false;
*len-=**a+1;
*a+=**a+1;
}
return true;
}
static bool feed_dns_response(const uint8_t *a, size_t len)
{
if (!params.cache_hostname) return true;
// 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];
uint16_t k, typ, off, dlen, qcount = a[4]<<8 | a[5], acount = a[6]<<8 | a[7];
char s_ip[INET6_ADDRSTRLEN];
const uint8_t *b = a, *p;
const uint8_t *e = b + len;
size_t nl;
char name[256] = "";
if (len<12 || !(a[2]&0x80)) return false;
a+=12; len-=12;
for(k=0;k<qcount;k++)
if (!qcount || len<12 || !(a[2]&0x80)) return false;
if (!acount)
{
DLOG("skipping DNS response without answer\n");
return false;
}
a+=12; len-=12;
for(k=0,*name = 0 ; k<qcount ; k++)
{
if (*name) return false; // we do not support multiple queries with names
// remember original query name
if (!(p = dns_extract_name(a, b, e, name, sizeof(name)))) return false;
len -= p-a;
if ((len<4) || p[2] || p[3]!=1) return false;
typ = pntoh16(p);
// must be A or AAAA query. others are not interesting
if ((len<4) || p[0] || p[1]!=1 && p[1]!=28 || p[2] || p[3]!=1) return false;
if (typ!=1 && typ!=28)
{
DLOG("skipping DNS query type %u for '%s'\n", typ, name);
return false;
}
else
{
DLOG("DNS query type %u for '%s'\n", typ, name);
}
// skip type, class
a=p+4; len-=4;
}
if (!*name) return false;
for(k=0;k<acount;k++)
{
// 11 higher bits indicate pointer
if (len<12 || (*a & 0xC0)!=0xC0) return false;
dlen = a[10]<<8 | a[11];
if (len<(dlen+12)) return false;
if (a[4]==0 && a[5]==1 && a[2]==0) // IN class and higher byte of type = 0
if (!dns_skip_name(&a,&len)) return false;
if (len<10) return false;
dlen = a[8]<<8 | a[9];
if (len<(dlen+10)) return false;
if (a[2]==0 && a[3]==1) // IN class
{
switch(a[3])
typ = pntoh16(a);
switch(typ)
{
case 1: // A
if (dlen!=4) break;
if (params.debug && inet_ntop(AF_INET, a+12, s_ip, sizeof(s_ip)))
DLOG("DNS response : %s\n", s_ip);
ipcache_put_hostname((struct in_addr *)(a+12), NULL, name, false);
if (params.debug && inet_ntop(AF_INET, a+10, s_ip, sizeof(s_ip)))
DLOG("DNS response type %u : %s\n", typ, s_ip);
ipcache_put_hostname((struct in_addr *)(a+10), NULL, name, false);
break;
case 28: // AAAA
if (dlen!=16) break;
if (params.debug && inet_ntop(AF_INET6, a+12, s_ip, sizeof(s_ip)))
DLOG("DNS response : %s\n", s_ip);
ipcache_put_hostname(NULL, (struct in6_addr *)(a+12), name, false);
if (params.debug && inet_ntop(AF_INET6, a+10, s_ip, sizeof(s_ip)))
DLOG("DNS response type %u : %s\n", typ, s_ip);
ipcache_put_hostname(NULL, (struct in6_addr *)(a+10), name, false);
break;
default:
DLOG("skipping DNS response type %u\n", typ);
}
}
len -= 12+dlen; a += 12+dlen;
len -= 10+dlen; a += 10+dlen;
}
return true;
}
@@ -1778,7 +1834,7 @@ static uint8_t dpi_desync_udp_packet_play(
else
{
DLOG("QUIC reasm is too long. cancelling.\n");
goto pass_reasm_cancel;
goto rediscover_cancel;
}
}
size_t hello_offset, hello_len, defrag_len = sizeof(defrag);
@@ -1802,18 +1858,18 @@ static uint8_t dpi_desync_udp_packet_play(
{
// preallocate max buffer to avoid reallocs that cause memory copy
if (!reasm_client_start(ps.ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
goto pass_reasm_cancel;
goto rediscover_cancel;
}
if (!ReasmIsEmpty(&ps.ctrack->reasm_client))
{
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos))
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos, false))
{
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ps.ctrack->delayed));
}
else
{
DLOG_ERR("rawpacket_queue failed !\n");
goto pass_reasm_cancel;
goto rediscover_cancel;
}
if (bReqFull)
{
@@ -1844,16 +1900,16 @@ static uint8_t dpi_desync_udp_packet_play(
{
// preallocate max buffer to avoid reallocs that cause memory copy
if (!reasm_client_start(ps.ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
goto pass_reasm_cancel;
goto rediscover_cancel;
}
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos))
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos, false))
{
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ps.ctrack->delayed));
}
else
{
DLOG_ERR("rawpacket_queue failed !\n");
goto pass_reasm_cancel;
goto rediscover_cancel;
}
return ct_new_postnat_fix(ps.ctrack, dis, mod_pkt, len_mod_pkt);
}
@@ -1878,18 +1934,16 @@ static uint8_t dpi_desync_udp_packet_play(
feed_dns_response(dis->data_payload, dis->len_payload);
} // len_payload
// UNSOLVED: if reasm is cancelled all packets except the last are passed as is without lua desync
rediscover_cancel:
reasm_client_cancel(ps.ctrack);
if (!dp_rediscovery(&ps))
goto pass;
ps.verdict = desync(ps.dp, fwmark, ifin, ifout, ps.bReverseFixed, ps.ctrack_replay, tpos, ps.l7payload, ps.l7proto, dis, ps.sdip4, ps.sdip6, ps.sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
pass:
return (!ps.bReverse && (ps.verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ps.ctrack, dis, mod_pkt, len_mod_pkt) : ps.verdict;
pass_reasm_cancel:
reasm_client_cancel(ps.ctrack);
goto pass;
return (!ps.bReverseFixed && (ps.verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ps.ctrack, dis, mod_pkt, len_mod_pkt) : ps.verdict;
}
// conntrack is supported only for RELATED icmp
@@ -2143,12 +2197,24 @@ static bool replay_queue(struct rawpacket_tailhead *q)
struct rawpacket *rp;
size_t offset;
unsigned int i, count;
bool b = true;
uint8_t mod[RECONSTRUCT_MAX_SIZE];
size_t modlen;
uint32_t seq0;
t_ctrack_position *pos;
bool b = true, bseq;
for (i = 0, offset = 0, count = rawpacket_queue_count(q); (rp = rawpacket_dequeue(q)); offset += rp->len_payload, rawpacket_free(rp), i++)
for (i = 0, offset = 0, count = rawpacket_queue_count(q); (rp = rawpacket_dequeue(q)); rawpacket_free(rp), i++)
{
// TCP: track reasm_offset using sequence numbers
if ((bseq = rp->tpos_present && rp->tpos.ipproto==IPPROTO_TCP))
{
pos = rp->server_side ? &rp->tpos.server : &rp->tpos.client;
if (i)
offset = pos->seq_last - seq0;
else
seq0 = pos->seq_last;
}
DLOG("REPLAYING delayed packet #%u offset %zu\n", i+1, offset);
modlen = sizeof(mod);
uint8_t verdict = dpi_desync_packet_play(i, count, offset, rp->fwmark_orig, rp->ifin, rp->ifout, rp->tpos_present ? &rp->tpos : NULL, rp->packet, rp->len, mod, &modlen);
@@ -2166,6 +2232,9 @@ static bool replay_queue(struct rawpacket_tailhead *q)
DLOG("DROPPING delayed packet #%u\n", i+1);
break;
}
if (!bseq)
offset += rp->len_payload;
}
return b;
}

View File

@@ -173,27 +173,27 @@ 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);
}
void print_cidr4(const struct cidr4 *cidr)
{
char s[19];
char s[INET_ADDRSTRLEN+4];
str_cidr4(s,sizeof(s),cidr);
printf("%s",s);
}
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[INET6_ADDRSTRLEN+4];
str_cidr6(s,sizeof(s),cidr);
printf("%s",s);
}

View File

@@ -40,7 +40,8 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
}
zs.avail_in = rd;
zs.next_in = in;
do
for(;;)
{
if ((bufsize - *size) < BUFMIN)
{
@@ -55,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);

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; \
@@ -240,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)
{
@@ -659,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

@@ -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

@@ -8,8 +8,10 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
{
char *p=*s;
for (; p<end && (*p==' ' || *p=='\t') ; p++);
*s = p;
// comment line ?
if ( *p != '#' && *p != ';' && *p != '/' && *p != '\r' && *p != '\n')
if (p<end && *p != '#' && *p != ';' && *p != '/' && *p != '\r' && *p != '\n')
{
// advance until eol lowering all chars
uint32_t flags = 0;
@@ -60,22 +62,25 @@ 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);
p = zbuf;
e = zbuf + zsize;
while(p<e)
if (zbuf)
{
if (!addpool(hostlist,&p,e,&ct))
p = zbuf;
e = zbuf + zsize;
while(p<e)
{
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
free(zbuf);
return false;
if (!addpool(hostlist,&p,e,&ct))
{
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
free(zbuf);
return false;
}
}
free(zbuf);
}
free(zbuf);
}
else
{
@@ -97,6 +102,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 +285,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 +309,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

@@ -11,36 +11,42 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
struct cidr4 c4;
struct cidr6 c6;
for (p=*s; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++);
// comment line
if (!(**s == '#' || **s == ';' || **s == '/' || **s == '\r' || **s == '\n' ))
for (p=*s; p<end && (*p==' ' || *p=='\t') ; p++);
if (p<end)
{
l = p-*s;
if (l>=sizeof(cidr)) l=sizeof(cidr)-1;
memcpy(cidr,*s,l);
cidr[l]=0;
// comment line
if (!(*p == '#' || *p == ';' || *p == '/' || *p == '\r' || *p == '\n' ))
{
*s=p;
// advance to the token's end
for (; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++);
if (parse_cidr4(cidr,&c4))
{
if (!ipset4AddCidr(&ips->ips4, &c4))
l = p-*s;
if (l>=sizeof(cidr)) l=sizeof(cidr)-1;
memcpy(cidr,*s,l);
cidr[l]=0;
if (parse_cidr4(cidr,&c4))
{
ipsetDestroy(ips);
return false;
if (!ipset4AddCidr(&ips->ips4, &c4))
{
ipsetDestroy(ips);
return false;
}
if (ct) (*ct)++;
}
if (ct) (*ct)++;
}
else if (parse_cidr6(cidr,&c6))
{
if (!ipset6AddCidr(&ips->ips6, &c6))
else if (parse_cidr6(cidr,&c6))
{
ipsetDestroy(ips);
return false;
if (!ipset6AddCidr(&ips->ips6, &c6))
{
ipsetDestroy(ips);
return false;
}
if (ct) (*ct)++;
}
if (ct) (*ct)++;
else
DLOG_ERR("bad ip or subnet : %s\n",cidr);
}
else
DLOG_ERR("bad ip or subnet : %s\n",cidr);
}
// skip remaining non-eol chars
@@ -77,22 +83,25 @@ 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);
p = zbuf;
e = zbuf + zsize;
while(p<e)
if (zbuf)
{
if (!addpool(ips,&p,e,&ct))
p = zbuf;
e = zbuf + zsize;
while(p<e)
{
DLOG_ERR("Not enough memory to store ipset : %s\n", filename);
free(zbuf);
return false;
if (!addpool(ips,&p,e,&ct))
{
DLOG_ERR("Not enough memory to store ipset : %s\n", filename);
free(zbuf);
return false;
}
}
free(zbuf);
}
free(zbuf);
}
else
{
@@ -104,7 +113,7 @@ static bool AppendIpset(ipset *ips, const char *filename)
{
DLOG_CONDUP("loading plain text list\n");
while (fgets(s, sizeof(s)-1, F))
while (fgets_safe(s, sizeof(s)-1, F))
{
p = s;
if (!addpool(ips,&p,p+strlen(p),&ct))
@@ -114,6 +123,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 +191,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 +287,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

@@ -1248,6 +1248,7 @@ void lua_push_blob(lua_State *L, int idx_desync, const char *blob)
lua_pop(L,1);
lua_getglobal(L, blob);
}
lua_tostring(L,-1);
}
void lua_pushf_blob(lua_State *L, int idx_desync, const char *field, const char *blob)
{
@@ -1657,7 +1658,7 @@ void lua_pushf_ctrack_pos(lua_State *L, const t_ctrack *ctrack, const t_ctrack_p
lua_pushf_lint(L,"pdcounter", pos->pdcounter);
lua_pushf_lint(L,"pbcounter", pos->pbcounter);
if (pos->ip6flow) lua_pushf_int(L,"ip6_flow", pos->ip6flow);
if (ctrack->ipproto == IPPROTO_TCP)
if (ctrack->pos.ipproto == IPPROTO_TCP)
{
lua_pushliteral(L, "tcp");
lua_createtable(L, 0, 11);
@@ -1779,7 +1780,10 @@ void lua_pushf_args(lua_State *L, const struct str2_list_head *args, int idx_des
lua_push_blob(L, idx_desync, val+1);
lua_Integer len = lua_rawlen(L, -1);
lua_pop(L,1);
lua_pushf_int(L, var, len);
lua_pushstring(L, var);
lua_pushinteger(L, len);
lua_tostring(L,-1); // force string type in arg
lua_rawset(L,-3);
}
else
lua_pushf_str(L, var, val);
@@ -1901,7 +1905,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 +2543,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");
@@ -2813,7 +2817,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);
@@ -2833,9 +2837,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)
}
@@ -3139,7 +3144,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));
@@ -3180,6 +3185,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);
@@ -3468,7 +3474,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)
{
@@ -3491,11 +3497,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:
@@ -3518,7 +3533,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)
@@ -3569,7 +3584,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);
@@ -3582,7 +3597,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)
{
@@ -3605,10 +3621,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);
@@ -3936,7 +3961,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

@@ -43,6 +43,7 @@
#endif
#ifdef __linux__
#include <sys/ioctl.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#define NF_DROP 0
#define NF_ACCEPT 1
@@ -71,13 +72,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 +184,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);
}
}
@@ -240,6 +241,13 @@ static int write_pidfile(FILE **Fpid)
#ifdef __linux__
struct nfq_cb_data
{
uint8_t *mod;
int sock;
};
// cookie must point to mod buffer with size RECONSTRUCT_MAX_SIZE
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
{
@@ -247,11 +255,10 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
size_t len;
struct nfqnl_msg_packet_hdr *ph;
uint8_t *data;
uint32_t ifidx_out, ifidx_in;
char ifout[IFNAMSIZ], ifin[IFNAMSIZ];
size_t modlen;
uint8_t *mod = (uint8_t*)cookie;
struct nfq_cb_data *cbdata = (struct nfq_cb_data*)cookie;
uint32_t mark;
struct ifreq ifr_in, ifr_out;
ph = nfq_get_msg_packet_hdr(nfa);
id = ph ? ntohl(ph->packet_id) : 0;
@@ -259,15 +266,21 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
mark = nfq_get_nfmark(nfa);
ilen = nfq_get_payload(nfa, &data);
ifidx_out = nfq_get_outdev(nfa);
*ifout = 0;
if (ifidx_out) if_indextoname(ifidx_out, ifout);
// if_indextoname creates socket, calls ioctl, closes socket
// code below prevents socket() and close() syscalls on every packet
// this saves CPU 5-10 times
ifidx_in = nfq_get_indev(nfa);
*ifin = 0;
if (ifidx_in) if_indextoname(ifidx_in, ifin);
*ifr_out.ifr_name = 0;
ifr_out.ifr_ifindex = nfq_get_outdev(nfa);
if (ifr_out.ifr_ifindex && ioctl(cbdata->sock, SIOCGIFNAME, &ifr_out)<0)
DLOG_PERROR("ioctl(SIOCGIFNAME)");
DLOG("\npacket: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifin, ifidx_in, ifout, ifidx_out);
*ifr_in.ifr_name = 0;
ifr_in.ifr_ifindex = nfq_get_indev(nfa);
if (ifr_in.ifr_ifindex && ioctl(cbdata->sock, SIOCGIFNAME, &ifr_in)<0)
DLOG_PERROR("ioctl(SIOCGIFNAME)");
DLOG("\npacket: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifr_in.ifr_name, ifr_in.ifr_ifindex, ifr_out.ifr_name, ifr_out.ifr_ifindex);
if (ilen >= 0)
{
@@ -277,12 +290,12 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
// to support increased sizes use separate mod buffer
// this is not a problem because only LUA code can trigger VERDICT_MODIFY (and postnat workaround too, once a connection if first packet is dropped)
// in case of VERIDCT_MODIFY packet is always reconstructed from dissect, so no difference where to save the data => no performance loss
uint8_t verdict = processPacketData(&mark, ifin, ifout, data, len, mod, &modlen);
uint8_t verdict = processPacketData(&mark, ifr_in.ifr_name, ifr_out.ifr_name, data, len, cbdata->mod, &modlen);
switch (verdict & VERDICT_MASK)
{
case VERDICT_MODIFY:
DLOG("packet: id=%d pass modified. len %zu => %zu\n", id, len, modlen);
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, (uint32_t)modlen, mod);
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, (uint32_t)modlen, cbdata->mod);
case VERDICT_DROP:
DLOG("packet: id=%d drop\n", id);
return nfq_set_verdict2(qh, id, NF_DROP, mark, 0, NULL);
@@ -306,7 +319,7 @@ static void nfq_deinit(struct nfq_handle **h, struct nfq_q_handle **qh)
*h = NULL;
}
}
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *mod_buffer)
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, struct nfq_cb_data *cbdata)
{
nfq_deinit(h, qh);
@@ -317,26 +330,33 @@ 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);
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, mod_buffer);
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, cbdata);
if (!*qh) {
DLOG_PERROR("nfq_create_queue()");
goto exiterr;
@@ -355,9 +375,11 @@ 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
}
nfnl_rcvbufsiz(nfq_nfnlh(*h), Q_RCVBUF);
int yes = 1, fd = nfq_fd(*h);
#if defined SOL_NETLINK && defined NETLINK_NO_ENOBUFS
@@ -380,6 +402,8 @@ static void notify_ready(void)
#endif
}
// extra space for netlink headers
#define NFQ_MAX_RECV_SIZE (RECONSTRUCT_MAX_SIZE+4096)
static int nfq_main(void)
{
struct nfq_handle *h = NULL;
@@ -388,6 +412,7 @@ static int nfq_main(void)
ssize_t rd;
FILE *Fpid = NULL;
uint8_t *buf=NULL, *mod=NULL;
struct nfq_cb_data cbdata = { .sock = -1 };
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -429,13 +454,19 @@ static int nfq_main(void)
goto exok;
}
if (!(buf = malloc(RECONSTRUCT_MAX_SIZE)) || !(mod = malloc(RECONSTRUCT_MAX_SIZE)))
if (!(buf = malloc(NFQ_MAX_RECV_SIZE)) || !(cbdata.mod = malloc(RECONSTRUCT_MAX_SIZE)))
{
DLOG_ERR("out of memory\n");
goto err;
}
if (!nfq_init(&h, &qh, mod))
if ((cbdata.sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
DLOG_PERROR("socket");
goto err;
}
if (!nfq_init(&h, &qh, &cbdata))
goto err;
#ifdef HAS_FILTER_SSID
@@ -459,7 +490,7 @@ static int nfq_main(void)
do
{
if (bQuit) goto quit;
while ((rd = recv(fd, buf, RECONSTRUCT_MAX_SIZE, 0)) >= 0)
while ((rd = recv(fd, buf, NFQ_MAX_RECV_SIZE, 0)) >= 0)
{
if (!rd)
{
@@ -474,7 +505,7 @@ static int nfq_main(void)
DLOG_ERR("cannot get wlan info\n");
#endif
int r = nfq_handle_packet(h, (char *)buf, (int)rd);
if (r) DLOG_ERR("nfq_handle_packet error %d\n", r);
if (r<0) DLOG_ERR("nfq_handle_packet result %d, errno %d : %s\n", r, errno, strerror(errno));
if (bQuit) goto quit;
}
if (errno==EINTR)
@@ -489,7 +520,8 @@ static int nfq_main(void)
exok:
res=0;
ex:
free(mod);
free(cbdata.mod);
if (cbdata.sock>=0) close(cbdata.sock);
free(buf);
nfq_deinit(&h, &qh);
lua_shutdown();
@@ -1686,6 +1718,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 +1882,7 @@ enum opt_indices {
IDX_PORT,
#endif
IDX_DAEMON,
IDX_CHDIR,
IDX_PIDFILE,
#ifndef __CYGWIN__
IDX_USER,
@@ -1953,6 +1987,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 +2205,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 +2296,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 +2421,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 +2436,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 +2581,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

@@ -26,7 +26,14 @@ void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
}
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos)
struct rawpacket *rawpacket_queue(
struct rawpacket_tailhead *q,
const struct sockaddr_storage* dst,
uint32_t fwmark_orig,uint32_t fwmark,
const char *ifin,const char *ifout,
const void *data,size_t len,size_t len_payload,
const t_ctrack_positions *tpos,
bool server_side)
{
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
if (!rp) return NULL;
@@ -61,6 +68,7 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
}
else
rp->tpos_present = false;
rp->server_side = server_side;
TAILQ_INSERT_TAIL(q, rp, next);

View File

@@ -18,6 +18,7 @@ struct rawpacket
uint8_t *packet;
t_ctrack_positions tpos;
bool tpos_present;
bool server_side; // true = reasm of packets from the server side
TAILQ_ENTRY(rawpacket) next;
};
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
@@ -26,6 +27,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos);
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos,bool server_side);
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
void rawpacket_free(struct rawpacket *rp);

View File

@@ -116,7 +116,7 @@ static char log_buf[4096];
static size_t log_buf_sz=0;
static void syslog_log_function(int priority, const char *line)
{
syslog(priority,"%s",log_buf);
syslog(priority,"%s",line);
}
static int DLOG_FILENAME(const char *filename, const char *format, ...)
@@ -405,7 +405,7 @@ static struct desync_profile_list *desync_profile_entry_alloc()
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{
struct desync_profile_list *entry = desync_profile_entry_alloc();
if (!entry) return false;
if (!entry) return NULL;
struct desync_profile_list *tail, *item;
LIST_TAIL(head, tail, item);

View File

@@ -23,7 +23,8 @@
#define RAW_SNDBUF (64*1024) // in bytes
#define Q_MAXLEN 1024 // in packets
#define Q_MAXLEN 4096 // in packets
#define Q_RCVBUF (1024*1024) // in bytes
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60

View File

@@ -493,7 +493,6 @@ void kavl_bit_destroy(struct kavl_bit_elem **hdr)
if (!e) break;
kavl_bit_destroy_elem(e);
}
free(*hdr);
}
struct kavl_bit_elem *kavl_bit_add(struct kavl_bit_elem **hdr, void *data, unsigned int bitlen, size_t struct_size)
{
@@ -1033,7 +1032,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 +1090,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)
{
@@ -249,7 +248,7 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7payload l7payload, cons
}
static const char *http_methods[] = { "GET ","POST ","HEAD ","OPTIONS ","PUT ","DELETE ","CONNECT ","TRACE ",NULL };
static const char *http_methods[] = { "GET ","POST ","HEAD ","OPTIONS ","PUT ","DELETE ","CONNECT ","TRACE ", "PATCH ", NULL };
static const char *HttpMethod(const uint8_t *data, size_t len)
{
const char **method;
@@ -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;
@@ -1334,14 +1337,12 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
{
// too small packets are not likely to be initials
// long header, fixed bit
if (len < 128 || (data[0] & 0xF0)!=0xC0) return false;
if (len < 128) return false;
uint32_t ver = QUICExtractVersion(data,len);
if (QUICDraftVersion(ver) < 11) return false;
// quic v1 : initial packets are 00b
// quic v2 : initial packets are 01b
if ((data[0] & 0x30) != (is_quic_v2(ver) ? 0x10 : 0x00)) return false;
if ((data[0] & 0xF0) != (is_quic_v2(ver) ? 0xD0 : 0xC0)) return false;
uint64_t offset=5, sz, sz2;
@@ -1444,7 +1445,7 @@ bool IsStunMessage(const uint8_t *data, size_t len)
(data[0]&0xC0)==0 && // 2 most significant bits must be zeroes
(data[3]&3)==0 && // length must be a multiple of 4
pntoh32(data+4)==0x2112A442 && // magic cookie
pntoh16(data+2)==(len-20);
pntoh16(data+2)<=(len-20);
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
@@ -1459,7 +1460,7 @@ bool IsMTProto(const uint8_t *data, size_t len)
return !memcmp(decrypt+56,"\xEF\xEF\xEF\xEF",4);
*/
// this way requires only one AES instead of 4
uint8_t decrypt[16] __attribute__((aligned)), iv[16];
uint8_t decrypt[16] __attribute__((aligned(16))), iv[16] __attribute__((aligned(16)));
aes_context ctx;
memcpy(iv, data+40, 16);

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"