Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-19 15:55:48 +00:00

22 Commits

Author SHA1 Message Date
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
27 changed files with 803 additions and 180 deletions

View File

@@ -493,7 +493,7 @@ jobs:
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
version: v4.2.4
version: v5.1.0
- name: Prepare binaries
shell: bash
@@ -508,7 +508,7 @@ jobs:
case $f in
*.tar.xz )
tar -C $dir -xvf $f && rm $f
if [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]] && [[ $dir != *-linux-risc ]]; then
if [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
run_upx $dir/*
fi
;;
@@ -552,8 +552,8 @@ jobs:
run: |
rm -rf ${{ env.repo_dir }}/.git*
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}.tar.gz
zip -9qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
(
cd ${{ env.repo_dir }}
rm -rf binaries/{android*,freebsd*,win*} \
@@ -561,7 +561,7 @@ jobs:
nfq2 ip2net mdig docs Makefile
pigz -11 lua/*.lua
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}-openwrt-embedded.tar.gz
- name: Upload release assets
uses: softprops/action-gh-release@v2

View File

@@ -152,7 +152,7 @@ v0.8.1
* zapret-antidpi: http_unixeol
* blockcheck2: http_unixeol test
0.8.2
v0.8.2
* nfqws2: do not start if NFQWS2_COMPAT_VER unexpected
* nfqws2: cache dns response IP addresses if --ipcache-hostname enabled
@@ -163,14 +163,14 @@ v0.8.1
* winws2: --wf-filter-loopback
* blockcheck2: NOTEST_MISC_HTTP[S], NOTEST_SYNDATA_HTTP[S]
0.8.3
v0.8.3
* nfqws2, zapret-lib: gzip compression and decompression
* nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now
* init.d: 99-lan-filter custom script
* mdig: --eagain, --eagain-delay
0.8.4
v0.8.4
* winws2: fix loopback large packets processing (up to 64K)
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
@@ -180,7 +180,7 @@ v0.8.1
* nfqws2: gracefully shutdown on SIGINT and SIGTERM
* nfqws2: harden wireguard detection. do not detect if reserved bytes 1..3 != 0
0.8.5
v0.8.5
* nfqws2: do not require / in the beginning of URI in http
* zapret-lib: rawsend_dissect_segmented support URG
@@ -190,13 +190,13 @@ v0.8.1
* zapret-lib: tcp_nop_del
* blockcheck2: tcp_nop_del in SYN packets with md5 in openbsd
0.8.6
v0.8.6
* winws2, blockcheck2: allow multiple instances in windows, linux, freebsd (not openbsd)
* nfqws2: fix critical bug - wrong ipv6 dissection
* zapret-auto: fix standard_failure_detector http redirect regression
0.9.0
v0.9.0
* nfqws2: removed hard check for host: presence in http_req
* nfqws2: file open test before destroying in-memory content of ipset/hostlist
@@ -215,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
@@ -240,3 +240,15 @@ v0.8.1
* 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.5
* builder_linux: simple scripts to build static linux bins for any supported architecture

View File

@@ -3,6 +3,20 @@ 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
linux static :
need any x86_64 classic linux distribution with curl, unzip, make, gcc, gcc-multilib
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
optionally review "common.inc" for Lua and LuaJIT versions
FreeBSD :
pkg install pkgconf

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,100 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
dl_deps()
{
if [ -d "$DEPS" ]; then
dir_is_not_empty "$DEPS" && {
echo "deps dir is not empty. if you want to redownload - delete it."
return
}
else
mkdir "$DEPS"
fi
pushd "$DEPS"
curl -Lo - https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
curl -Lo - https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
curl -Lo - https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
curl -Lo - https://zlib.net/zlib-1.3.1.tar.gz | tar -xz
curl -Lo - https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
curl -Lo - https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
popd
}
build_netlink()
{
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
[ -f "Makefile" ] && make clean
CFLAGS="$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="$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="$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="$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
}
}
dl_deps
check_toolchains
ask_target
for t in $TGT; do
buildenv $t
pushd "$DEPS"
bsd_files
build_netlink
build_zlib
build_lua
build_luajit_for_target $t
popd
buildenv_clear
done

View File

@@ -0,0 +1,107 @@
#!/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
pushd "$ZBASE"
curl -Lo /tmp/zapret2.zip "$ZURL"
unzip /tmp/zapret2.zip
rm /tmp/zapret2.zip
mv zapret2-${BRANCH} $ZDIR
popd
}
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
}
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_LUAVER}"
}
OPTIMIZE=-Oz \
CFLAGS="-static-libgcc -static -I$STAGING_DIR/include $CFLAGS" \
LDFLAGS="-L$DEPS_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,170 @@
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
TOOLCHAINS="$EXEDIR/toolchain"
DEPS="$EXEDIR/deps"
STAGE="$EXEDIR/staging"
MINSIZE="-Oz -flto=auto -ffunction-sections -fdata-sections"
LDMINSIZE="-Wl,--gc-sections -flto=auto"
CFLAGS=""
LDFLAGS="-lgcc_eh"
HOSTCC=cc
LUA_VER="5.5"
LUA_RELEASE="5.5.0"
LUAJIT_VER="2.1"
LUAJIT_RELEASE="2.1-20250826"
LUAJIT_LUAVER="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
}
bsd_files()
{
install -Dm644 -t $STAGING_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
}
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=
}
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
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
CC ?= cc
PKG_CONFIG ?= pkg-config
OPTIMIZE ?= -Oz
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables
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

View File

@@ -1,7 +1,7 @@
CC ?= cc
PKG_CONFIG ?= pkg-config
OPTIMIZE ?= -Os
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE)
CFLAGS_LINUX = -Wno-alloc-size-larger-than
CFLAGS_SYSTEMD = -DUSE_SYSTEMD

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

@@ -1901,7 +1901,7 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
lua_getfield(L,-1, "data");
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
if (!(p=(uint8_t*)lua_tolstring(L,-1,&l))) l=0;
if (!l || (l+2)>left || ((type==IPPROTO_AH) ? (l<6 || ((l+2) & 3)) : ((l+2) & 7))) goto err;
if (l<6 || (l+2)>left || (type==IPPROTO_AH ? (l>=1024 || ((l+2) & 3)) : (l>=2048 || ((l+2) & 7)))) goto err;
memcpy(data+2,p,l);
l+=2;
data[0] = next; // may be overwritten later
@@ -2539,7 +2539,7 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
}
else if (udp)
{
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
sz = lpayload+sizeof(struct udphdr);
if (sz>0xFFFF)
{
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
@@ -2813,7 +2813,7 @@ static int luacall_ntop(lua_State *L)
{
size_t l;
const char *p;
char s[40];
char s[INET6_ADDRSTRLEN];
int af=0;
lua_check_argc(L,"ntop",1);
@@ -2833,9 +2833,10 @@ static int luacall_ntop(lua_State *L)
lua_pushnil(L);
return 1;
}
if (!inet_ntop(af,p,s,sizeof(s)))
luaL_error(L, "inet_ntop error");
lua_pushstring(L,s);
if (inet_ntop(af,p,s,sizeof(s)))
lua_pushstring(L,s);
else
lua_pushnil(L);
LUA_STACK_GUARD_RETURN(L,1)
}
@@ -3139,7 +3140,7 @@ static int lua_get_ifaddrs(lua_State *L)
struct ifreq ifr;
const char *ifname;
#ifdef __CYGWIN__
char ifname_buf[16];
char ifname_buf[IFNAMSIZ];
#endif
memset(&ifr,0,sizeof(ifr));
@@ -3180,6 +3181,7 @@ static int lua_get_ifaddrs(lua_State *L)
#ifdef HAS_FILTER_SSID
lua_pushf_str(L, "ssid", wlan_ssid_search_ifname(ifname));
#endif
memset(ifr.ifr_name,0,sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
if (sock>=0 && !ioctl(sock, SIOCGIFMTU, &ifr))
lua_pushf_int(L, "mtu", ifr.ifr_mtu);
@@ -3468,7 +3470,7 @@ static int luacall_gunzip_inflate(lua_State *L)
size_t increment = bufchunk / 2;
if (increment < Z_INFL_BUF_INCREMENT) increment = Z_INFL_BUF_INCREMENT;
do
for(;;)
{
if ((bufsize - size) < BUFMIN)
{
@@ -3491,11 +3493,20 @@ static int luacall_gunzip_inflate(lua_State *L)
}
uzs->zs.avail_out = bufsize - size;
uzs->zs.next_out = buf + size;
r = inflate(&uzs->zs, Z_NO_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
size = bufsize - uzs->zs.avail_out;
} while (r == Z_OK && uzs->zs.avail_in);
r = inflate(&uzs->zs, Z_NO_FLUSH);
size = bufsize - uzs->zs.avail_out;
if (r==Z_STREAM_END) break;
if (r==Z_BUF_ERROR)
{
if (uzs->zs.avail_in)
goto zerr;
else
break; // OK
}
if (r!=Z_OK) goto zerr;
}
lua_pushlstring(L, (const char*)buf, size);
lua_pushboolean(L, r==Z_STREAM_END);
end:
@@ -3518,7 +3529,7 @@ static void z_free(voidpf opaque, voidpf address)
static int luacall_gzip_init(lua_State *L)
{
// gzip_init(windowBits, level, memlevel) return zstream
lua_check_argc_range(L,"gunzip_init",0,3);
lua_check_argc_range(L,"gzip_init",0,3);
LUA_STACK_GUARD_ENTER(L)
@@ -3569,7 +3580,7 @@ static int luacall_gzip_deflate(lua_State *L)
int argc=lua_gettop(L);
size_t l=0;
int r;
int r, flush;
size_t bufsize=0, size=0;
uint8_t *buf=NULL, *newbuf;
struct userdata_zs *uzs = lua_uzs(L, 1, false);
@@ -3582,7 +3593,8 @@ static int luacall_gzip_deflate(lua_State *L)
size_t increment = bufchunk / 2;
if (increment < Z_DEFL_BUF_INCREMENT) increment = Z_DEFL_BUF_INCREMENT;
do
flush = l ? Z_NO_FLUSH : Z_FINISH;
for(;;)
{
if ((bufsize - size) < BUFMIN)
{
@@ -3605,10 +3617,19 @@ static int luacall_gzip_deflate(lua_State *L)
}
uzs->zs.avail_out = bufsize - size;
uzs->zs.next_out = buf + size;
r = deflate(&uzs->zs, l ? Z_NO_FLUSH : Z_FINISH);
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
r = deflate(&uzs->zs, flush);
size = bufsize - uzs->zs.avail_out;
} while (r == Z_OK && (uzs->zs.avail_in || !uzs->zs.avail_out));
if (r==Z_STREAM_END) break;
if (r==Z_OK)
{
if (uzs->zs.avail_out && !uzs->zs.avail_in && flush != Z_FINISH)
break;
}
else
goto zerr;
}
lua_pushlstring(L, (const char*)buf, size);
lua_pushboolean(L, r==Z_STREAM_END);
@@ -3936,7 +3957,7 @@ static int luaL_doZfile(lua_State *L, const char *filename)
luaL_error(L, "could not open lua file '%s'", fname);
r = z_readfile(F, &buf, &size, 0);
fclose(F);
if (r != Z_OK)
if (r != Z_STREAM_END)
luaL_error(L, "could not unzip lua file '%s'", fname);
r = luaL_loadbuffer(L, buf, size, fname);
free(buf);

View File

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

View File

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

View File

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

View File

@@ -18,13 +18,24 @@ bool dropcaps(void);
#define arch_nr (offsetof(struct seccomp_data, arch))
#define syscall_arg(x) (offsetof(struct seccomp_data, args[x]))
#ifndef AUDIT_ARCH_RISCV64
#define AUDIT_ARCH_RISCV64 (EM_RISCV | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#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__)
@@ -80,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"