mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
Compare commits
361 Commits
v0.8.3
...
3c87be3cba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c87be3cba | ||
|
|
c642fb3845 | ||
|
|
847e689bfb | ||
|
|
287527092a | ||
|
|
a9514f39f5 | ||
|
|
4b7ff505e4 | ||
|
|
2120264e0b | ||
|
|
178bced5f3 | ||
|
|
ff78968807 | ||
|
|
e4535d2646 | ||
|
|
7c60ad3a7a | ||
|
|
a621edf898 | ||
|
|
2809f8d7e4 | ||
|
|
97819327cd | ||
|
|
eb9a1e9f6b | ||
|
|
6f6850707a | ||
|
|
f702865311 | ||
|
|
6447081a01 | ||
|
|
e4e513ec66 | ||
|
|
47630450bd | ||
|
|
e4129fec63 | ||
|
|
f71ba91e7c | ||
|
|
59e6603b83 | ||
|
|
14a061859f | ||
|
|
9aaa419f68 | ||
|
|
d5231bc4fc | ||
|
|
35cebfba73 | ||
|
|
811d16054b | ||
|
|
a9ee072a14 | ||
|
|
1dbf5ecfe6 | ||
|
|
b210db168f | ||
|
|
5306a043d0 | ||
|
|
b375a94036 | ||
|
|
8b2bff4187 | ||
|
|
827ab7cdcc | ||
|
|
bfa1d8c5dd | ||
|
|
52ea6270f4 | ||
|
|
0fb21856c6 | ||
|
|
48e4d3a6e7 | ||
|
|
6204c74993 | ||
|
|
d981391120 | ||
|
|
7db676e02c | ||
|
|
c91cae0903 | ||
|
|
c06712a0d5 | ||
|
|
2e2f118e10 | ||
|
|
6638140880 | ||
|
|
41bac1833e | ||
|
|
c3b1cc3eb9 | ||
|
|
6f52fb08f9 | ||
|
|
08549b570b | ||
|
|
13daef5167 | ||
|
|
1fd6063cd7 | ||
|
|
5e4f78228e | ||
|
|
2e255ca59f | ||
|
|
565a8abffc | ||
|
|
69f1576f7e | ||
|
|
0917cb21bb | ||
|
|
8f316ae1a2 | ||
|
|
caaf5e7a2e | ||
|
|
dbfbd6e6d3 | ||
|
|
397fe60b5f | ||
|
|
e096ed64bc | ||
|
|
0f2def9bd5 | ||
|
|
85721e4b82 | ||
|
|
0fd9314df9 | ||
|
|
a9e2bfe49c | ||
|
|
bd7a40f5a9 | ||
|
|
bcd50f5215 | ||
|
|
927cca3d44 | ||
|
|
162e8906a6 | ||
|
|
3f7180379b | ||
|
|
5d0af6b058 | ||
|
|
392e1cc1ef | ||
|
|
8a5643851d | ||
|
|
6299a46ab7 | ||
|
|
c5ecc0493d | ||
|
|
7bb8b1d7b3 | ||
|
|
401bd83f82 | ||
|
|
c117c30849 | ||
|
|
6828e7352c | ||
|
|
943e548f93 | ||
|
|
539c329da3 | ||
|
|
4c6902c17c | ||
|
|
9121d949f6 | ||
|
|
64c1f96f80 | ||
|
|
3334786fe3 | ||
|
|
20a0fa671d | ||
|
|
747de07c85 | ||
|
|
6384af6607 | ||
|
|
3046dd8013 | ||
|
|
c80ae95a09 | ||
|
|
d7e5fc1a7c | ||
|
|
97a6b9dd5b | ||
|
|
cfd2df41c4 | ||
|
|
f47f4a0cae | ||
|
|
823a2e2e5d | ||
|
|
0cdbedde74 | ||
|
|
36e243863b | ||
|
|
181395be87 | ||
|
|
fb71a41ea5 | ||
|
|
7f8f64a355 | ||
|
|
7e31dc9d89 | ||
|
|
4a9072a949 | ||
|
|
4b0e3af020 | ||
|
|
d442a38774 | ||
|
|
ede3515fa3 | ||
|
|
831cf02ad5 | ||
|
|
c436470b18 | ||
|
|
56b4ce0b2a | ||
|
|
18b33008af | ||
|
|
c72c48432e | ||
|
|
c5894b0708 | ||
|
|
79b018dd74 | ||
|
|
56cce72dac | ||
|
|
a8b4007386 | ||
|
|
2977c20044 | ||
|
|
d432e770a6 | ||
|
|
0574d609de | ||
|
|
043b85dfb4 | ||
|
|
22b7861603 | ||
|
|
8b24076c20 | ||
|
|
3abc22baf5 | ||
|
|
739c24cdf3 | ||
|
|
5c97563698 | ||
|
|
2ddfe55d9a | ||
|
|
a781f3d1ce | ||
|
|
080655c4c2 | ||
|
|
3434739144 | ||
|
|
740cbfbc34 | ||
|
|
37f0f4589f | ||
|
|
9d7fed4c67 | ||
|
|
2533a3debc | ||
|
|
6e90adad5b | ||
|
|
aa359128bb | ||
|
|
fed07a0249 | ||
|
|
055ae067f9 | ||
|
|
2490ef6951 | ||
|
|
a531da39fd | ||
|
|
b920964ab3 | ||
|
|
7d9f5a4b83 | ||
|
|
b157613b1a | ||
|
|
4081878b36 | ||
|
|
b1fbf5c81a | ||
|
|
04d940e619 | ||
|
|
bd9aec8374 | ||
|
|
e9bffca658 | ||
|
|
001942fe74 | ||
|
|
f5d1108cce | ||
|
|
27d387c76d | ||
|
|
d5306fb97a | ||
|
|
5f87b7670a | ||
|
|
2a2a3e4f73 | ||
|
|
1f99fb49af | ||
|
|
b99b59bbdb | ||
|
|
9128601820 | ||
|
|
584d3b5925 | ||
|
|
eff7e6488a | ||
|
|
27c49bcfe4 | ||
|
|
48fbd39ada | ||
|
|
6eb4970c9b | ||
|
|
ba5cff29f1 | ||
|
|
bd155daa91 | ||
|
|
5de6595ccd | ||
|
|
4253b7b408 | ||
|
|
389a331d83 | ||
|
|
540094baac | ||
|
|
a3c4724542 | ||
|
|
79f33ef75a | ||
|
|
d4c1126961 | ||
|
|
9e378f629d | ||
|
|
227c2e76e3 | ||
|
|
2f74d21923 | ||
|
|
4376aa0cdf | ||
|
|
331e0dcbab | ||
|
|
f1af8cbde9 | ||
|
|
b865591f2a | ||
|
|
384d219597 | ||
|
|
7880782a95 | ||
|
|
d914472542 | ||
|
|
6a32bc46e2 | ||
|
|
8cf0d68d58 | ||
|
|
04134d78ee | ||
|
|
47f6410946 | ||
|
|
a29e159895 | ||
|
|
e5fd657a8a | ||
|
|
faea98da74 | ||
|
|
c8722d1ed9 | ||
|
|
77e405e24d | ||
|
|
7c5dfad8e2 | ||
|
|
b25f16126b | ||
|
|
4970c01344 | ||
|
|
4e412ab2d6 | ||
|
|
a2374f0fcf | ||
|
|
65337446d4 | ||
|
|
be88140bb0 | ||
|
|
27fff3f5c3 | ||
|
|
8ba5739ef2 | ||
|
|
a788975268 | ||
|
|
e441711b05 | ||
|
|
314627d851 | ||
|
|
4560ef6d5b | ||
|
|
431e794356 | ||
|
|
f50bd701f7 | ||
|
|
15f29169d5 | ||
|
|
a106519f1e | ||
|
|
5b016f62e4 | ||
|
|
68c15864a4 | ||
|
|
752cafad7c | ||
|
|
12853b8052 | ||
|
|
1d869650b1 | ||
|
|
12a9bf8b19 | ||
|
|
4ade6f7e82 | ||
|
|
6adb789314 | ||
|
|
78b3baa03f | ||
|
|
90fa71d6d6 | ||
|
|
e33e1a9b89 | ||
|
|
e7f0e79f78 | ||
|
|
8b11d6c279 | ||
|
|
30044e8c61 | ||
|
|
1cffa0f5ec | ||
|
|
8bee9efcf0 | ||
|
|
848221b096 | ||
|
|
fb3bdd9b70 | ||
|
|
ca6d145312 | ||
|
|
01d78e8dc4 | ||
|
|
db050b9ba1 | ||
|
|
b65da8d8db | ||
|
|
1359986d29 | ||
|
|
36ee42bc8c | ||
|
|
a8373a8400 | ||
|
|
33b1e81041 | ||
|
|
577d9e6aba | ||
|
|
3caf1ce10a | ||
|
|
8e67260a23 | ||
|
|
378b1c727d | ||
|
|
14bd4832a4 | ||
|
|
6d8b405bf0 | ||
|
|
00b6d70efc | ||
|
|
ca14fbe9c8 | ||
|
|
c81968b94b | ||
|
|
a2d567c7a0 | ||
|
|
5026199f24 | ||
|
|
68435f64ea | ||
|
|
d84dfaf61d | ||
|
|
4c13c63d27 | ||
|
|
5dde1264ce | ||
|
|
cc989c52ed | ||
|
|
0446b1493b | ||
|
|
97cd8cebca | ||
|
|
2d02eeb578 | ||
|
|
fe318a42e8 | ||
|
|
73c10e3f15 | ||
|
|
17cf260fd0 | ||
|
|
fa15c635bb | ||
|
|
74690047b5 | ||
|
|
d24453da69 | ||
|
|
af200628cd | ||
|
|
76fe7bff82 | ||
|
|
1d1eedbb3b | ||
|
|
274b331825 | ||
|
|
69f900b3da | ||
|
|
da9faabf97 | ||
|
|
60934f5ab8 | ||
|
|
eb7043fc12 | ||
|
|
681c53c3b4 | ||
|
|
65f6923383 | ||
|
|
f0f59261bb | ||
|
|
06cf59d050 | ||
|
|
f0bff44219 | ||
|
|
da0016ed0e | ||
|
|
704c73f821 | ||
|
|
201dd40b46 | ||
|
|
aa13a1f5d2 | ||
|
|
2a3b6f2a8b | ||
|
|
801dec81c8 | ||
|
|
14359afb93 | ||
|
|
372c6748ca | ||
|
|
87d2fcd5a1 | ||
|
|
74ddd4f9d2 | ||
|
|
6b7507deb5 | ||
|
|
f8156a3d38 | ||
|
|
67a8ee47e3 | ||
|
|
93d81ca4b2 | ||
|
|
3d9a36600b | ||
|
|
c3adb3f045 | ||
|
|
f919533873 | ||
|
|
17bdfe16b1 | ||
|
|
bc0102fbdc | ||
|
|
10d72b3242 | ||
|
|
9dd14dfc7c | ||
|
|
10201f1abf | ||
|
|
236550918b | ||
|
|
72a269e88d | ||
|
|
d3199eebd3 | ||
|
|
ffcb14726d | ||
|
|
aa5a1f4183 | ||
|
|
ca186a6566 | ||
|
|
dced388652 | ||
|
|
1f7d10bf5b | ||
|
|
6b1b4adddb | ||
|
|
cfe7b76352 | ||
|
|
62fd0dc432 | ||
|
|
050a01bda2 | ||
|
|
4c5d84c19e | ||
|
|
d430b4775d | ||
|
|
807565968e | ||
|
|
e062b1795e | ||
|
|
3417e50438 | ||
|
|
70f5a88ec0 | ||
|
|
4b3fba3fb2 | ||
|
|
9cded5448a | ||
|
|
2302ac6949 | ||
|
|
0be76b902e | ||
|
|
fa89e011fb | ||
|
|
622a81001d | ||
|
|
4d793b73a4 | ||
|
|
a47b6a529b | ||
|
|
7c320c8d57 | ||
|
|
b18f0770c8 | ||
|
|
f7fc845014 | ||
|
|
2c1a885a07 | ||
|
|
9eb308d84c | ||
|
|
3e724c3810 | ||
|
|
c179d55d88 | ||
|
|
3f1af1441e | ||
|
|
4c1b2b65f3 | ||
|
|
918258413f | ||
|
|
e6206c5a5f | ||
|
|
f93c6de772 | ||
|
|
5a7e2b1ca2 | ||
|
|
ca8104c72a | ||
|
|
3aad1f9ed9 | ||
|
|
fd288d5e7d | ||
|
|
349fe3f7d7 | ||
|
|
4554b7c15b | ||
|
|
0b595ae3a8 | ||
|
|
3e69e1b8c1 | ||
|
|
02b895910b | ||
|
|
b2a53e9c64 | ||
|
|
a626cfce8a | ||
|
|
ebcbfc37ba | ||
|
|
33d3c94b68 | ||
|
|
d55dbb7717 | ||
|
|
cb82be9eab | ||
|
|
024d36acc4 | ||
|
|
08c6151a4c | ||
|
|
520317dc3c | ||
|
|
6bc0bf1b97 | ||
|
|
d18fec9053 | ||
|
|
e60e5a0578 | ||
|
|
84576a7039 | ||
|
|
7957a0a425 | ||
|
|
7ba4110416 | ||
|
|
4babaef6a8 | ||
|
|
872e37d160 | ||
|
|
a8219f4897 | ||
|
|
36267b7e9b | ||
|
|
99a7f06976 | ||
|
|
3617b8934f | ||
|
|
8e6387a6df | ||
|
|
3bc0e8e350 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,5 +1,7 @@
|
||||
* text=auto eol=lf
|
||||
*.cmd eol=crlf
|
||||
*.bat eol=crlf
|
||||
*.manifest eol=crlf
|
||||
*.rc eol=crlf
|
||||
init.d/windivert.filter.examples/** eol=crlf
|
||||
files/** binary
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
2
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
@@ -18,5 +18,7 @@ Discussions - место для обсуждения вопросов между
|
||||
Если вы игнорируете данное требование, вы не достигните своих целей , а только добавите желания удалить ваш issue или при настойчивости забанить.
|
||||
Идите в дискуссии, не захламляйте issues.
|
||||
|
||||
Так же будут немедленно удаляться любые issue, связанные с реакцией антивирусов. При агрессии или настойчивости - бан. (подсказка : вирусов нет, удаляйте если не верите)
|
||||
|
||||
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
|
||||
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.
|
||||
|
||||
70
.github/workflows/build.yml
vendored
70
.github/workflows/build.yml
vendored
@@ -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
|
||||
@@ -93,11 +81,13 @@ jobs:
|
||||
CFLAGS: ${{ matrix.env.CFLAGS != '' && matrix.env.CFLAGS || null }}
|
||||
LDFLAGS: ${{ matrix.env.LDFLAGS != '' && matrix.env.LDFLAGS || null }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
LUA_VER: 5.4
|
||||
LUA_RELEASE: 5.4.8
|
||||
LUA_VER: 5.5
|
||||
LUA_RELEASE: 5.5.0
|
||||
LUAJIT_VER: 2.1
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
LUAJIT_LUAVER: 5.1
|
||||
MINSIZE: -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
DEPS_DIR=$GITHUB_WORKSPACE/deps
|
||||
export CC="$TARGET-gcc"
|
||||
@@ -107,13 +97,19 @@ jobs:
|
||||
export STRIP=$TARGET-strip
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
if [ "$ARCH" = lexra ]; then
|
||||
OPTIMIZE=-Os
|
||||
else
|
||||
OPTIMIZE=-Oz
|
||||
fi
|
||||
MINSIZE="$OPTIMIZE $MINSIZE"
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == riscv64 ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
cd lua-${LUA_RELEASE}
|
||||
make CC=$CC CFLAGS="-Os -flto=auto $CFLAGS" linux -j$(nproc)
|
||||
make CC=$CC AR="$AR rc" CFLAGS="$MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$(nproc)
|
||||
make install INSTALL_TOP=$DEPS_DIR INSTALL_BIN=$DEPS_DIR/bin INSTALL_INC=$DEPS_DIR/include/lua${LUA_VER} INSTALL_LIB=$DEPS_DIR/lib
|
||||
)
|
||||
LJIT=0
|
||||
@@ -131,7 +127,7 @@ jobs:
|
||||
esac
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -s -flto=auto $CFLAGS" -j$(nproc)
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
LJIT=1
|
||||
@@ -147,7 +143,8 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto $CFLAGS" \
|
||||
CFLAGS="$MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -159,7 +156,7 @@ jobs:
|
||||
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
|
||||
(
|
||||
cd zlib-*
|
||||
CFLAGS="-Os -flto=auto $CFLAGS" \
|
||||
CFLAGS="$MINSIZE $CFLAGS" \
|
||||
./configure --prefix= --static
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -170,6 +167,7 @@ jobs:
|
||||
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
|
||||
|
||||
# zapret2
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
|
||||
make -C zapret2 LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc)
|
||||
@@ -220,6 +218,8 @@ jobs:
|
||||
LUAJIT_VER: 2.1
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
LUAJIT_LUAVER: 5.1
|
||||
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
DEPS_DIR=$GITHUB_WORKSPACE/deps
|
||||
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
|
||||
@@ -242,7 +242,7 @@ jobs:
|
||||
esac
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -flto=auto $CFLAGS" -j$(nproc)
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
LJIT=1
|
||||
@@ -258,7 +258,8 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
|
||||
CFLAGS="$MINSIZE -Wno-implicit-function-declaration $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -314,12 +315,14 @@ jobs:
|
||||
TARGET: ${{ matrix.target }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
CC: ${{ matrix.target }}-freebsd11-clang
|
||||
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
|
||||
wget -qO- https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC CFLAGS="-Os -flto=auto $CFLAGS"
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
|
||||
@@ -390,8 +393,8 @@ 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 }}
|
||||
check-sig: ${{ matrix.arch == 'x86_64' && 'false' || 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
|
||||
make
|
||||
@@ -424,13 +427,15 @@ jobs:
|
||||
- name: Build luajit
|
||||
env:
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
MINSIZE: -Os -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
|
||||
run: >-
|
||||
export MAKEFLAGS=-j$(nproc) &&
|
||||
wget -q https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz &&
|
||||
tar -xzf v${LUAJIT_RELEASE}.tar.gz &&
|
||||
rm -f v${LUAJIT_RELEASE}.tar.gz &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI CFLAGS="-Os -s" &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS="-DLUAJIT_DISABLE_FFI -ffat-lto-objects" TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} install
|
||||
|
||||
- name: Build winws
|
||||
@@ -488,7 +493,7 @@ jobs:
|
||||
uses: crazy-max/ghaction-upx@v3
|
||||
with:
|
||||
install-only: true
|
||||
version: v4.2.4
|
||||
version: v5.1.0
|
||||
|
||||
- name: Prepare binaries
|
||||
shell: bash
|
||||
@@ -532,6 +537,7 @@ jobs:
|
||||
*-linux-mipselsf ) run_dir linux-mipsel ;;
|
||||
*-linux-mipssf ) run_dir linux-mips ;;
|
||||
*-linux-ppc ) run_dir linux-ppc ;;
|
||||
*-linux-riscv64 ) run_dir linux-riscv64 ;;
|
||||
*-linux-x86 ) run_dir linux-x86 ;;
|
||||
*-linux-x86_64 ) run_dir linux-x86_64 ;;
|
||||
*-linux-lexra ) run_dir linux-lexra ;;
|
||||
@@ -546,8 +552,8 @@ jobs:
|
||||
run: |
|
||||
rm -rf ${{ env.repo_dir }}/.git*
|
||||
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
|
||||
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}.tar.gz
|
||||
zip -9qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
(
|
||||
cd ${{ env.repo_dir }}
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
@@ -555,7 +561,7 @@ jobs:
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
pigz -11 lua/*.lua
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}-openwrt-embedded.tar.gz
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
||||
2
binaries/readme.txt
Normal file
2
binaries/readme.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Бинари только в релизах. Собираем с исходников или качаем релиз с гитхаба ! Инфа по сборке в docs/compile.
|
||||
Binaries are only in releases. Build from source or download release from github ! See docs/compile.
|
||||
@@ -2,9 +2,11 @@
|
||||
Скопируйте эту директорию под другим именем в blockcheck2.d, отредактируйте list файлы, впишите туда свои стратегии.
|
||||
В диалоге blockcheck2.sh выберите тест с названием вашей директории.
|
||||
Можно комментировать строки символом '#' в начале строки.
|
||||
Параметры со спец символами типа "<" должны быть эскейпнуты по правилам shell.
|
||||
Альтернативный путь до файлов стратегий можно задать переменными LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
|
||||
This is simple strategy tester from a file.
|
||||
Copy this folder, write your strategies into list files and select your test in blockcheck2 dialog.
|
||||
Lines can be commented using the '#' symbol at the line start.
|
||||
Parameters with special symbols like "<" must be escaped.
|
||||
Strategy list files paths can be overriden in env variables : LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload=http_req --lua-desync=http_hostcase
|
||||
--payload=http_req --lua-desync=http_methodeol
|
||||
--payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_ts=-1000
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000
|
||||
--payload=tls_client_hello --lua-desync=fake:blob=0x00000000:tcp_md5:repeats=1 --lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,dupsid:repeats=1 --lua-desync=multisplit:pos=2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000
|
||||
--payload tls_client_hello --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop
|
||||
--payload tls_client_hello --lua-desync=luaexec:code="desync.pat=tls_mod(fake_default_tls,'rnd,rndsni,dupsid,padencap',desync.reasm_data)" --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=11
|
||||
--payload quic_initial --lua-desync=send:ipfrag --lua-desync=drop
|
||||
|
||||
39
blockcheck2.d/standard/17-oob.sh
Normal file
39
blockcheck2.d/standard/17-oob.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_oob()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local urp
|
||||
for urp in b 0 2 midsld; do
|
||||
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp
|
||||
done
|
||||
}
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_OOB_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_oob "$@"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_OOB_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_oob "$@"
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls12 "$1" "$2"
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_simple_split_tests()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain/uri
|
||||
# $3 - splits
|
||||
# $4 - PRE args for nfqws2
|
||||
local pos ok ok_any pre="$4"
|
||||
local splitf splitfs="multisplit $MULTIDISORDER"
|
||||
local pos ok ok_any pre="$4" func
|
||||
local splitf splitfs="multisplit multidisorder"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
func=$splitf
|
||||
[ "$func" = multidisorder ] && func=$MULTIDISORDER
|
||||
eval need_$splitf=0
|
||||
ok=0
|
||||
for pos in $3; do
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$splitf:pos=$pos && ok=1
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$func:pos=$pos && ok=1
|
||||
done
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] || eval need_$splitf=1
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
@@ -41,8 +45,6 @@ pktws_check_https_tls()
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_simple_split_tests "$1" "$2" "$splits_tls" "$3"
|
||||
}
|
||||
|
||||
@@ -50,6 +52,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -62,5 +67,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
@@ -34,6 +36,7 @@ pktws_seqovl_tests_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain/uri
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
local ok ok_any
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local pat rnd_mod padencap_mod split f f2
|
||||
@@ -42,46 +45,38 @@ pktws_seqovl_tests_tls()
|
||||
pat=${SEQOVL_PATTERN_HTTPS:+seqovl_pat}
|
||||
pat=${pat:-fake_default_tls}
|
||||
rnd_mod="--lua-init=$pat=tls_mod($pat,'rnd')"
|
||||
padencap_mod="--lua-desync=luaexec:code=desync.pat=tls_mod($pat,'rnd,dupsid,padencap',desync.reasm_data)"
|
||||
padencap_mod="--lua-desync=luaexec:code=desync.patmod=tls_mod($pat,'rnd,dupsid,padencap',desync.reasm_data)"
|
||||
|
||||
ok=0
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=#$pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#patmod:seqovl_pattern=patmod --lua-desync=drop && ok=1
|
||||
ok_any=$ok
|
||||
|
||||
ok=0
|
||||
for split in 10 10,sniext+1 10,sniext+4 10,midsld; do
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=1 && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=#$pat:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#pat:seqovl_pattern=pat && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#patmod:seqovl_pattern=patmod && ok=1
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2" "$3"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_seqovl_tests_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -90,5 +85,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ pktws_check_http()
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http ${split:+$PAYLOAD --lua-desync=$split}
|
||||
done
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ pktws_check_https_tls()
|
||||
|
||||
local PAYLOAD="--payload=tls_client_hello" ok=0 pre="$3" split
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=0x1603 ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
@@ -40,6 +38,8 @@ pktws_check_https_tls12()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -49,5 +49,7 @@ pktws_check_https_tls13()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ pktws_check_http()
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
@@ -40,7 +40,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
@@ -55,8 +55,8 @@ pktws_check_http()
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
[ $ok_any = 1 ]
|
||||
}
|
||||
|
||||
pktws_fake_https_vary_()
|
||||
@@ -76,7 +76,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -86,8 +86,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -102,8 +100,8 @@ pktws_check_https_tls()
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
@@ -125,14 +123,17 @@ pktws_check_https_tls()
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
[ $ok_any = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -145,5 +146,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ pktws_check_faked()
|
||||
local PAYLOAD="--payload=$3"
|
||||
local FAKED_PATTERN="$5"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fakedsplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -42,7 +42,7 @@ pktws_check_faked()
|
||||
for split in $splits; do
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
@@ -77,7 +77,6 @@ pktws_check_https_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
pktws_check_faked $1 "$2" tls_client_hello "$splits" "$FAKED_PATTERN_HTTPS" "$3"
|
||||
@@ -87,6 +86,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -99,5 +101,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
|
||||
pktws_hostfake_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5" disorder
|
||||
@@ -22,7 +21,7 @@ pktws_hostfake_vary()
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -37,8 +36,8 @@ pktws_check_hostfake()
|
||||
local ok ttls attls f fooling
|
||||
local PAYLOAD="--payload=$3"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
need_hostfakesplit=0
|
||||
ok=0
|
||||
@@ -58,7 +57,7 @@ pktws_check_hostfake()
|
||||
pktws_hostfake_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && eval need_hostfake=1
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_hostfakesplit=1
|
||||
[ $ok = 1 ]
|
||||
}
|
||||
|
||||
@@ -77,14 +76,15 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_hostfake $1 "$2" tls_client_hello "$3"
|
||||
}
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -97,5 +97,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ pktws_check_http()
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -82,7 +82,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -92,8 +92,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -106,8 +104,8 @@ pktws_check_https_tls()
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
@@ -148,6 +146,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -156,5 +157,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ pktws_check_http()
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_fakedsplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -69,11 +69,11 @@ pktws_fake_https_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
}
|
||||
@@ -83,7 +83,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -93,8 +93,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -107,8 +105,8 @@ pktws_check_https_tls()
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + fakedsplit if fakedsplit works
|
||||
[ "$need_fakedsplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -149,6 +147,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -157,5 +158,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ pktws_hostfake_vary()
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5"
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5"
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5"
|
||||
}
|
||||
|
||||
pktws_check_hostfake()
|
||||
@@ -33,8 +33,8 @@ pktws_check_hostfake()
|
||||
|
||||
[ "$need_hostfakesplit" = 0 ] && return 0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
@@ -69,7 +69,7 @@ pktws_check_http()
|
||||
local FAKE="$FAKE_HTTP"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=bfake
|
||||
fake=fake_http
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
@@ -83,13 +83,11 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
local FAKE="$FAKE_HTTPS"
|
||||
|
||||
if [ -n "$FAKE_HTTPS" ]; then
|
||||
fake=bfake
|
||||
fake=fake_tls
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
@@ -101,6 +99,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -109,5 +110,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -15,3 +15,7 @@ MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||
|
||||
# can use MULTIDISORER=multidisorder_legacy
|
||||
MULTIDISORDER=${MULTIDISORDER:-multidisorder}
|
||||
|
||||
TCP_MD5=tcp_md5
|
||||
# OpenBSD can occupy 24 bytes in tcp options in SYN packet leaving no space for the md5 header
|
||||
[ "$UNAME" = OpenBSD ] && TCP_MD5=$TCP_MD5:tcp_nop_del
|
||||
|
||||
127
blockcheck2.sh
127
blockcheck2.sh
@@ -26,7 +26,6 @@ CURL=${CURL:-curl}
|
||||
|
||||
TEST_DEFAULT=${TEST_DEFAULT:-standard}
|
||||
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
|
||||
QNUM=${QNUM:-59781}
|
||||
SOCKS_PORT=${SOCKS_PORT:-1993}
|
||||
WS_UID=${WS_UID:-1}
|
||||
WS_GID=${WS_GID:-3003}
|
||||
@@ -35,8 +34,6 @@ DVTWS2=${DVTWS2:-${ZAPRET_BASE}/nfq2/dvtws2}
|
||||
WINWS2=${WINWS2:-${ZAPRET_BASE}/nfq2/winws2}
|
||||
MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
|
||||
DESYNC_MARK=0x10000000
|
||||
IPFW_RULE_NUM=${IPFW_RULE_NUM:-1}
|
||||
IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780}
|
||||
CURL_MAX_TIME=${CURL_MAX_TIME:-2}
|
||||
CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
|
||||
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
|
||||
@@ -45,12 +42,20 @@ HTTP_PORT=${HTTP_PORT:-80}
|
||||
HTTPS_PORT=${HTTPS_PORT:-443}
|
||||
QUIC_PORT=${QUIC_PORT:-443}
|
||||
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
|
||||
PARALLEL_OUT=/tmp/zapret_parallel
|
||||
SIM_SUCCESS_RATE=${SIM_SUCCESS_RATE:-10}
|
||||
|
||||
HDRTEMP=/tmp/zapret-hdr
|
||||
IPFW_RULE_MAX=${IPFW_RULE_MAX:-999}
|
||||
IPFW_RULE_NUM=${IPFW_RULE_NUM:-$(($$ % $IPFW_RULE_MAX + 1))}
|
||||
IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-$(($$ % 64536 + 1000))}
|
||||
QNUM=${QNUM:-$(($$ % 64536 + 1000))}
|
||||
|
||||
NFT_TABLE=blockcheck
|
||||
IPSET_FILE=/tmp/blockcheck_ipset_$$.txt
|
||||
PARALLEL_OUT=/tmp/zapret_parallel_$$
|
||||
HDRTEMP=/tmp/zapret-hdr-$$
|
||||
NFT_TABLE=blockcheck$$
|
||||
IPT_OUT_CHAIN=blockcheck_output_$$
|
||||
IPT_IN_CHAIN=blockcheck_input_$$
|
||||
IPT_COMMENT="-m comment --comment blockcheck_$$"
|
||||
|
||||
DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1}
|
||||
DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ej.ru rutracker.org www.torproject.org bbc.com}
|
||||
@@ -59,7 +64,6 @@ DNSCHECK_DIG1=/tmp/dig1.txt
|
||||
DNSCHECK_DIG2=/tmp/dig2.txt
|
||||
DNSCHECK_DIGS=/tmp/digs.txt
|
||||
|
||||
IPSET_FILE=/tmp/blockcheck_ipset.txt
|
||||
|
||||
unset PF_STATUS
|
||||
PF_RULES_SAVE=/tmp/pf-zapret-save.conf
|
||||
@@ -240,7 +244,7 @@ mdig_vars()
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname
|
||||
|
||||
hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g')
|
||||
hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g' | tr 'A-Z' 'a-z')
|
||||
cachevar=DNSCACHE_${hostvar}_$1
|
||||
countvar=${cachevar}_COUNT
|
||||
eval count=\$${countvar}
|
||||
@@ -297,7 +301,7 @@ mdig_resolve_all()
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=0
|
||||
while [ "$n" -le $count ]; do
|
||||
while [ "$n" -lt $count ]; do
|
||||
eval ip__=\$${cachevar}_$n
|
||||
if [ -n "$ips__" ]; then
|
||||
ips__="$ips__ $ip__"
|
||||
@@ -408,8 +412,14 @@ zp_already_running()
|
||||
CYGWIN)
|
||||
win_process_exists $PKTWSD || win_process_exists winws || win_process_exists goodbyedpi
|
||||
;;
|
||||
*)
|
||||
FreeBSD|OpenBSD)
|
||||
process_exists $PKTWSD || process_exists tpws || process_exists dvtws
|
||||
;;
|
||||
Linux)
|
||||
process_exists $PKTWSD || process_exists tpws || process_exists nfqws
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
esac
|
||||
}
|
||||
check_already()
|
||||
@@ -633,11 +643,11 @@ curl_with_dig()
|
||||
# $2 - domain name
|
||||
# $3 - port
|
||||
# $4+ - curl params
|
||||
local dom=$2 port=$3
|
||||
local dom="$2" port=$3
|
||||
local sdom suri ip
|
||||
|
||||
split_by_separator "$dom" / sdom suri
|
||||
mdig_resolve $1 ip $sdom
|
||||
mdig_resolve $1 ip "$sdom"
|
||||
shift ; shift ; shift
|
||||
if [ -n "$ip" ]; then
|
||||
curl_with_subst_ip "$sdom" "$port" "$ip" "$@"
|
||||
@@ -652,12 +662,12 @@ curl_probe()
|
||||
# $3 - port
|
||||
# $4 - subst ip
|
||||
# $5+ - curl params
|
||||
local ipv=$1 dom=$2 port=$3 subst=$4
|
||||
local ipv=$1 dom="$2" port=$3 subst=$4
|
||||
shift; shift; shift; shift
|
||||
if [ -n "$subst" ]; then
|
||||
curl_with_subst_ip $dom $port $subst "$@"
|
||||
curl_with_subst_ip "$dom" $port $subst "$@"
|
||||
else
|
||||
curl_with_dig $ipv $dom $port "$@"
|
||||
curl_with_dig $ipv "$dom" $port "$@"
|
||||
fi
|
||||
}
|
||||
curl_test_http()
|
||||
@@ -668,7 +678,7 @@ curl_test_http()
|
||||
# $4 - "detail" - detail info
|
||||
|
||||
local code loc hdrt="${HDRTEMP}_${!:-$$}.txt" dom="$(tolower "$2")"
|
||||
curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
|
||||
curl_probe $1 "$2" $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
|
||||
code=$?
|
||||
rm -f "$hdrt"
|
||||
return $code
|
||||
@@ -680,6 +690,7 @@ curl_test_http()
|
||||
code=$(hdrfile_http_code "$hdrt")
|
||||
[ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && {
|
||||
loc=$(hdrfile_location "$hdrt")
|
||||
split_by_separator "$dom" / dom
|
||||
tolower "$loc" | grep -qE "^https?://.*$dom(/|$)" ||
|
||||
tolower "$loc" | grep -vqE '^https?://' || {
|
||||
echo suspicious redirection $code to : $loc
|
||||
@@ -703,7 +714,7 @@ curl_test_https_tls12()
|
||||
# $3 - subst ip
|
||||
|
||||
# do not use tls 1.3 to make sure server certificate is not encrypted
|
||||
curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
|
||||
curl_probe $1 "$2" $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
curl_test_https_tls13()
|
||||
{
|
||||
@@ -712,7 +723,7 @@ curl_test_https_tls13()
|
||||
# $3 - subst ip
|
||||
|
||||
# force TLS1.3 mode
|
||||
curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
|
||||
curl_probe $1 "$2" $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
|
||||
curl_test_http3()
|
||||
@@ -721,7 +732,7 @@ curl_test_http3()
|
||||
# $2 - domain name
|
||||
|
||||
# force QUIC only mode without tcp
|
||||
curl_with_dig $1 $2 $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
|
||||
curl_with_dig $1 "$2" $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
|
||||
ipt_aux_scheme()
|
||||
@@ -731,24 +742,24 @@ ipt_aux_scheme()
|
||||
# $3 - port
|
||||
|
||||
# to avoid possible INVALID state drop
|
||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT
|
||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn $IPT_COMMENT -j ACCEPT
|
||||
|
||||
local icmp_filter="-p icmp -m icmp --icmp-type"
|
||||
[ "$IPV" = 6 ] && icmp_filter="-p icmpv6 -m icmp6 --icmpv6-type"
|
||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK $IPT_COMMENT -j DROP
|
||||
|
||||
# for strategies with incoming packets involved (autottl)
|
||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT
|
||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID $IPT_COMMENT -j ACCEPT
|
||||
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
|
||||
# the only way to reliable disable ipv6 defrag. works only in 4.16+ kernels
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag -j CT --notrack
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag $IPT_COMMENT -j CT --notrack
|
||||
elif [ "$IPV" = 4 ]; then
|
||||
# enable fragments
|
||||
IPT_ADD_DEL $1 OUTPUT -f -j ACCEPT
|
||||
IPT_ADD_DEL $1 OUTPUT -f $IPT_COMMENT -j ACCEPT
|
||||
fi
|
||||
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
|
||||
# raw table may not be present
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK $IPT_COMMENT -j CT --notrack
|
||||
}
|
||||
ipt_scheme()
|
||||
{
|
||||
@@ -758,18 +769,18 @@ ipt_scheme()
|
||||
|
||||
local ip
|
||||
|
||||
$IPTABLES -t mangle -N blockcheck_output 2>/dev/null
|
||||
$IPTABLES -t mangle -F blockcheck_output
|
||||
IPT OUTPUT -t mangle -j blockcheck_output
|
||||
$IPTABLES -t mangle -N $IPT_OUT_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -F $IPT_OUT_CHAIN
|
||||
IPT OUTPUT -t mangle -j $IPT_OUT_CHAIN
|
||||
|
||||
# prevent loop
|
||||
$IPTABLES -t mangle -A blockcheck_output -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_output ! -p $1 -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN ! -p $1 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -p $1 ! --dport $2 -j RETURN
|
||||
|
||||
for ip in $3; do
|
||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -d $ip -j NFQUEUE --queue-num $QNUM
|
||||
done
|
||||
|
||||
ipt_aux_scheme 1 $1 $2
|
||||
@@ -845,9 +856,9 @@ pktws_ipt_unprepare()
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
ipt_aux_scheme 0 $1 $2
|
||||
IPT_DEL OUTPUT -t mangle -j blockcheck_output
|
||||
$IPTABLES -t mangle -F blockcheck_output 2>/dev/null
|
||||
$IPTABLES -t mangle -X blockcheck_output 2>/dev/null
|
||||
IPT_DEL OUTPUT -t mangle -j $IPT_OUT_CHAIN
|
||||
$IPTABLES -t mangle -F $IPT_OUT_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -X $IPT_OUT_CHAIN 2>/dev/null
|
||||
;;
|
||||
nftables)
|
||||
nft delete table inet $NFT_TABLE 2>/dev/null
|
||||
@@ -875,17 +886,17 @@ pktws_ipt_prepare_tcp()
|
||||
|
||||
pktws_ipt_prepare tcp $1 "$2"
|
||||
|
||||
# for autottl mode
|
||||
# for autottl mode and tcp_mss detection
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
$IPTABLES -N blockcheck_input -t mangle 2>/dev/null
|
||||
$IPTABLES -F blockcheck_input -t mangle 2>/dev/null
|
||||
IPT INPUT -t mangle -j blockcheck_input
|
||||
$IPTABLES -t mangle -A blockcheck_input ! -p tcp -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_input -p tcp ! --sport $1 -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_input -p tcp ! --tcp-flags SYN,ACK SYN,ACK -j RETURN
|
||||
$IPTABLES -N $IPT_IN_CHAIN -t mangle 2>/dev/null
|
||||
$IPTABLES -F $IPT_IN_CHAIN -t mangle 2>/dev/null
|
||||
IPT INPUT -t mangle -j $IPT_IN_CHAIN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN ! -p tcp -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN -p tcp ! --sport $1 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN -p tcp ! --tcp-flags SYN,ACK SYN,ACK -j RETURN
|
||||
for ip in $2; do
|
||||
$IPTABLES -A blockcheck_input -t mangle -s $ip -j NFQUEUE --queue-num $QNUM
|
||||
$IPTABLES -A $IPT_IN_CHAIN -t mangle -s $ip -j NFQUEUE --queue-num $QNUM
|
||||
done
|
||||
;;
|
||||
nftables)
|
||||
@@ -909,9 +920,9 @@ pktws_ipt_unprepare_tcp()
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
IPT_DEL INPUT -t mangle -j blockcheck_input
|
||||
$IPTABLES -t mangle -F blockcheck_input 2>/dev/null
|
||||
$IPTABLES -t mangle -X blockcheck_input 2>/dev/null
|
||||
IPT_DEL INPUT -t mangle -j $IPT_IN_CHAIN
|
||||
$IPTABLES -t mangle -F $IPT_IN_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -X $IPT_IN_CHAIN 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -939,7 +950,9 @@ pktws_start()
|
||||
"$DVTWS2" --port=$IPFW_DIVERT_PORT --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
;;
|
||||
CYGWIN)
|
||||
"$WINWS2" $WF --ipset="$IPSET_FILE" --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
# allow multiple PKTWS instances with the same wf filter but different ipset
|
||||
# some methods require empty acks
|
||||
"$WINWS2" --wf-dup-check=0 --wf-tcp-empty=1 $WF --ipset="$IPSET_FILE" --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
;;
|
||||
esac
|
||||
PID=$!
|
||||
@@ -990,7 +1003,7 @@ curl_test()
|
||||
if [ "$PARALLEL" = 1 ]; then
|
||||
rm -f "${PARALLEL_OUT}"*
|
||||
for n in $(seq -s ' ' 1 $REPEATS); do
|
||||
$1 "$IPV" $2 $3 "$4" >"${PARALLEL_OUT}_$n" &
|
||||
$1 "$IPV" "$2" $3 "$4" >"${PARALLEL_OUT}_$n" &
|
||||
pids="${pids:+$pids }$!"
|
||||
done
|
||||
n=1
|
||||
@@ -1009,7 +1022,7 @@ curl_test()
|
||||
while [ $n -lt $REPEATS ]; do
|
||||
n=$(($n+1))
|
||||
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
|
||||
if $1 "$IPV" $2 $3 "$4" ; then
|
||||
if $1 "$IPV" "$2" $3 "$4" ; then
|
||||
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
|
||||
else
|
||||
code=$?
|
||||
@@ -1034,7 +1047,7 @@ ws_curl_test()
|
||||
# $2 - test function
|
||||
# $3 - domain
|
||||
# $4,$5,$6, ... - ws params
|
||||
local code ws_start=$1 testf=$2 dom=$3
|
||||
local code ws_start=$1 testf=$2 dom="$3"
|
||||
|
||||
[ "$SIMULATE" = 1 ] && {
|
||||
n=$(random 0 99)
|
||||
@@ -1050,7 +1063,7 @@ ws_curl_test()
|
||||
shift
|
||||
shift
|
||||
$ws_start "$@"
|
||||
curl_test $testf $dom
|
||||
curl_test $testf "$dom"
|
||||
code=$?
|
||||
ws_kill
|
||||
return $code
|
||||
@@ -1060,11 +1073,11 @@ pktws_curl_test()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3,$4,$5, ... - nfqws/dvtws params
|
||||
local testf=$1 dom=$2 strategy code
|
||||
local testf=$1 dom="$2" strategy code
|
||||
|
||||
shift; shift;
|
||||
echo - $testf ipv$IPV $dom : $PKTWSD ${WF:+$WF }${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }$@${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
ws_curl_test pktws_start $testf $dom ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
ws_curl_test pktws_start $testf "$dom" ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
|
||||
code=$?
|
||||
[ "$code" = 0 ] && {
|
||||
@@ -1086,11 +1099,11 @@ xxxws_curl_test_update()
|
||||
# $2 - test function
|
||||
# $3 - domain
|
||||
# $4,$5,$6, ... - nfqws2/dvtws2 params
|
||||
local code xxxf=$1 testf=$2 dom=$3
|
||||
local code xxxf=$1 testf=$2 dom="$3"
|
||||
shift
|
||||
shift
|
||||
shift
|
||||
$xxxf $testf $dom "$@"
|
||||
$xxxf $testf "$dom" "$@"
|
||||
code=$?
|
||||
[ $code = 0 ] && strategy="${strategy:-$@}"
|
||||
return $code
|
||||
@@ -1314,7 +1327,6 @@ check_domain_http_tcp()
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_tcp $2
|
||||
ws_kill
|
||||
|
||||
check_domain_prolog $1 $2 $4 || return
|
||||
@@ -1342,7 +1354,6 @@ check_domain_http_udp()
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_udp $2
|
||||
ws_kill
|
||||
|
||||
check_domain_prolog $1 $2 $3 || return
|
||||
|
||||
@@ -95,7 +95,7 @@ end_with_newline()
|
||||
}
|
||||
trim()
|
||||
{
|
||||
awk '{gsub(/^ +| +$/,"")}1'
|
||||
awk '{gsub(/^[ \t]+|[ \t]+$/,"")}1'
|
||||
}
|
||||
split_by_separator()
|
||||
{
|
||||
@@ -119,7 +119,7 @@ dir_is_not_empty()
|
||||
# $1 - directory
|
||||
local n
|
||||
[ -d "$1" ] || return 1
|
||||
n=$(ls "$1" | wc -c | xargs)
|
||||
n=$(ls -A "$1" | wc -c | xargs)
|
||||
[ "$n" != 0 ]
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ setup_md5()
|
||||
{
|
||||
[ -n "$MD5" ] && return
|
||||
MD5=md5sum
|
||||
exists $MD5 || MD5=md5
|
||||
exists $MD5 || MD5="md5 -q"
|
||||
}
|
||||
|
||||
md5f()
|
||||
@@ -366,7 +366,7 @@ random()
|
||||
local r rs
|
||||
setup_random
|
||||
if [ -c /dev/urandom ]; then
|
||||
read rs </dev/urandom
|
||||
rs=$(dd if=/dev/urandom count=1 bs=16 2>/dev/null | hexdump -e '1 "%02x"')
|
||||
else
|
||||
rs="$RANDOM$RANDOM$(date)"
|
||||
fi
|
||||
@@ -394,9 +394,9 @@ shell_name()
|
||||
process_exists()
|
||||
{
|
||||
if exists pgrep; then
|
||||
pgrep ^$1$ >/dev/null
|
||||
pgrep "^$1$" >/dev/null
|
||||
elif exists pidof; then
|
||||
pidof $1 >/dev/null
|
||||
pidof "$1" >/dev/null
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
@@ -426,14 +426,6 @@ alloc_num()
|
||||
eval $1="$v"
|
||||
}
|
||||
|
||||
std_ports()
|
||||
{
|
||||
NFQWS2_PORTS_TCP_IPT=$(replace_char - : $NFQWS2_PORTS_TCP)
|
||||
NFQWS2_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_TCP_KEEPALIVE)
|
||||
NFQWS2_PORTS_UDP_IPT=$(replace_char - : $NFQWS2_PORTS_UDP)
|
||||
NFQWS2_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_UDP_KEEPALIVE)
|
||||
}
|
||||
|
||||
has_bad_ws_options()
|
||||
{
|
||||
# $1 - nfqws2 opts
|
||||
|
||||
@@ -36,8 +36,8 @@ ask_list()
|
||||
# $3 - (optional) default value
|
||||
local M_DEFAULT
|
||||
eval M_DEFAULT="\$$1"
|
||||
local M_ALL=$M_DEFAULT
|
||||
local M="" m M_OLD
|
||||
local M_DEFAULT_VAR="$M_DEFAULT"
|
||||
local M="" m
|
||||
|
||||
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
|
||||
|
||||
@@ -53,5 +53,5 @@ ask_list()
|
||||
echo selected : $M
|
||||
eval $1="\"$M\""
|
||||
|
||||
[ "$M" != "$M_DEFAULT" ]
|
||||
[ "$M" != "$M_DEFAULT_VAR" ]
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ check_system()
|
||||
|
||||
get_free_space_mb()
|
||||
{
|
||||
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
|
||||
df -m "$1" | awk '/[0-9]%/{print $(NF-2)}'
|
||||
}
|
||||
get_ram_kb()
|
||||
{
|
||||
@@ -522,11 +522,6 @@ install_openwrt_firewall()
|
||||
{
|
||||
echo \* installing firewall script $1
|
||||
|
||||
[ -n "MODE" ] || {
|
||||
echo should specify MODE in $ZAPRET_CONFIG
|
||||
exitp 7
|
||||
}
|
||||
|
||||
echo "linking : $FW_SCRIPT_SRC => $OPENWRT_FW_INCLUDE"
|
||||
ln -fs "$FW_SCRIPT_SRC" "$OPENWRT_FW_INCLUDE"
|
||||
|
||||
@@ -784,7 +779,9 @@ select_fwtype()
|
||||
echo WARNING ! if you need large lists it may be necessary to fall back to iptables+ipset firewall
|
||||
}
|
||||
echo select firewall type :
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE"
|
||||
# always write config var to prevent auto discovery every time
|
||||
write_config_var FWTYPE
|
||||
}
|
||||
|
||||
dry_run_nfqws_()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
std_ports
|
||||
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
|
||||
IPSET_EXCLUDE="-m set ! --match-set nozapret"
|
||||
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
|
||||
IPSET_PORTS_NAME=zport
|
||||
|
||||
ipt()
|
||||
{
|
||||
@@ -41,7 +41,7 @@ ipt6_add_del()
|
||||
}
|
||||
ipt6a_add_del()
|
||||
{
|
||||
on_off_function ipt6 ipt6a_del "$@"
|
||||
on_off_function ipt6a ipt6_del "$@"
|
||||
}
|
||||
|
||||
is_ipt_flow_offload_avail()
|
||||
@@ -227,6 +227,16 @@ fw_reverse_nfqws_rule()
|
||||
fw_reverse_nfqws_rule6 $1 "$3" $4
|
||||
}
|
||||
|
||||
ipt_port_ipset()
|
||||
{
|
||||
# $1 - ipset name
|
||||
# $2 - ports
|
||||
ipset -q flush $1 || {
|
||||
ipset create $1 bitmap:port range 0-65535 || return
|
||||
}
|
||||
echo "$2" | tr ',' '\n' | sed -nEe "s/^.+$/add $1 &/p" | ipset -! restore
|
||||
}
|
||||
|
||||
ipt_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
@@ -237,26 +247,31 @@ ipt_do_nfqws_in_out()
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - tcp,udp
|
||||
# $3 - ports
|
||||
# $4 - PKT_OUT. special value : 'keepalive'
|
||||
# $5 - PKT_IN
|
||||
local f4 f6 first_packets_only
|
||||
# $4 - PKT. special value : 'keepalive'
|
||||
# $5 - 1 - out, 0 - in
|
||||
# $6 - ipset base name
|
||||
local f f4 f6 first_packets_only ipset
|
||||
[ -n "$3" ] || return
|
||||
ipset="${6}_$2"
|
||||
[ "$4" = keepalive ] && ipset="${ipset}_k"
|
||||
[ "$1" = 1 ] && ipt_port_ipset $ipset "$3"
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $4)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f4="-p $2 -m set --match-set $ipset"
|
||||
if [ "$5" = 1 ]; then
|
||||
f4="$f4 dst"
|
||||
f=fw_nfqws_post
|
||||
else
|
||||
f4="$f4 src"
|
||||
f=fw_reverse_nfqws_rule
|
||||
fi
|
||||
f4="$f4 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ -n "$5" -a "$5" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $5)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_reverse_nfqws_rule $1 "$f4" "$f6" $QNUM
|
||||
$f $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ "$1" = 1 ] || ipset -q destroy $ipset
|
||||
}
|
||||
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
@@ -264,10 +279,12 @@ zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && {
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_IPT" "$NFQWS2_TCP_PKT_OUT" "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_IPT" "$NFQWS2_UDP_PKT_OUT" "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_OUT" 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_IN" 0 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE" keepalive 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_OUT" 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_IN" 0 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE" keepalive 1 $IPSET_PORTS_NAME
|
||||
}
|
||||
}
|
||||
zapret_do_firewall_standard_rules_ipt()
|
||||
|
||||
@@ -3,7 +3,6 @@ nft_connbytes="ct original packets"
|
||||
|
||||
# required for : nft -f -
|
||||
create_dev_stdin
|
||||
std_ports
|
||||
|
||||
nft_create_table()
|
||||
{
|
||||
@@ -77,8 +76,7 @@ nft_rule_exists()
|
||||
nft_add_rule ruletest "$2"
|
||||
rule=$(nft list chain inet $ZAPRET_NFT_TABLE ruletest | sed -n '3s/\t//gp')
|
||||
nft_flush_chain ruletest
|
||||
local yes=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | sed -n "s/^[\t]*$rule\$/1/p")
|
||||
[ -n "$yes" ]
|
||||
nft list chain inet $ZAPRET_NFT_TABLE $1 | trim | grep -qxF "$rule"
|
||||
}
|
||||
|
||||
nft_del_all_chains_from_table()
|
||||
|
||||
@@ -41,7 +41,9 @@ AUTOHOSTLIST_DEBUGLOG=0
|
||||
|
||||
# number of parallel threads for domain list resolves
|
||||
MDIG_THREADS=30
|
||||
# EAI_AGAIN retries
|
||||
MDIG_EAGAIN=10
|
||||
# delay between EAI_AGAIN retries (ms)
|
||||
MDIG_EAGAIN_DELAY=500
|
||||
|
||||
# ipset/*.sh can compress large lists
|
||||
|
||||
@@ -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,9 +163,92 @@ 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
|
||||
|
||||
v0.8.4
|
||||
|
||||
* winws2: fix loopback large packets processing (up to 64K)
|
||||
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
|
||||
* nfqws2: move ctx from lightuserdata to userdata. prevents crashes on specific ARM cpus
|
||||
* nfqws2: alternative representation of payload filter in execution_plan item
|
||||
* nfqws2: --payload-disable
|
||||
* nfqws2: gracefully shutdown on SIGINT and SIGTERM
|
||||
* nfqws2: harden wireguard detection. do not detect if reserved bytes 1..3 != 0
|
||||
|
||||
v0.8.5
|
||||
|
||||
* nfqws2: do not require / in the beginning of URI in http
|
||||
* zapret-lib: rawsend_dissect_segmented support URG
|
||||
* zapret-antidpi: oob
|
||||
* blockcheck2: 17-oob.sh
|
||||
* nfqws2: set desync.tcp_mss to minimum of both ends or default if at least one is unknown
|
||||
* zapret-lib: tcp_nop_del
|
||||
* blockcheck2: tcp_nop_del in SYN packets with md5 in openbsd
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
* github actions: lua 5.5
|
||||
* nfqws2: enable dead reasm protection in wsize=0 case
|
||||
* nfqws2: --intercept
|
||||
* winws2: changed icon to multi-res png up to 256px
|
||||
* nfqws2: support icmp and ipp
|
||||
* nfqws2: VERDICT_PRESERVE_NEXT
|
||||
* nfqws2: keepsum reconstruct option
|
||||
* nfqws2: more helpers
|
||||
* zapret-obfs: ippxor, udp2icmp, synhide
|
||||
* nfqws2: LUA_COMPAT_VER=5
|
||||
* winws2: --wf-raw-filter
|
||||
* nfqws2: conntrack_feed
|
||||
* winws2: use windivert bulk mode
|
||||
* nfqws2: template free import
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
v0.9.3
|
||||
|
||||
* nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
|
||||
* zapret-auto: per_instance_condition orchestrator
|
||||
* zapret-auto: "instances" argument in condition orchestrator
|
||||
* zapret-auto: cond_tcp_has_ts, cond_lua iff functions
|
||||
* zapret-lib: replay_execution_plan and plan_clear max parameter
|
||||
* init.d: use bitmap:port ipset for standard dports
|
||||
* 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
|
||||
|
||||
@@ -3,8 +3,23 @@ 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
|
||||
pkg search luajit-2
|
||||
# see what's the version available
|
||||
pkg install luajit-2.1.0.20250728
|
||||
@@ -12,5 +27,5 @@ make -C /opt/zapret2
|
||||
|
||||
OpenBSD :
|
||||
|
||||
pkg_add luajit gmake bsd
|
||||
gmake -C /opt/zapret2
|
||||
pkg_add luajit gmake
|
||||
gmake -C /opt/zapret2 bsd
|
||||
|
||||
@@ -11,9 +11,9 @@ setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouc
|
||||
|
||||
4) install and compile luajit from here : https://github.com/openresty/luajit2
|
||||
|
||||
download latest releast, unpack, cd to it's directory
|
||||
download latest release, unpack, cd to it's directory
|
||||
|
||||
make BUILDMODE=static CFLAGS="-Os"
|
||||
make BUILDMODE=static CFLAGS="-Os -DLUAJIT_DISABLE_FFI -ffat-lto-objects -flto=auto -ffunction-sections -fdata-sections -fvisibility=hidden"
|
||||
make install
|
||||
|
||||
5) cd to %ZAPRET_BASE%/nfq2
|
||||
@@ -32,5 +32,5 @@ Choose version 2.2.2 for Windows 10 and 2.2.0 for Windows 7.
|
||||
8) Copy cygwin1.dll, winws2.exe, windivert.dll and windivert64.sys to one folder.
|
||||
|
||||
9) Run winws2.exe from cmd.exe running as administrator.
|
||||
winws will not run from cygwin shell with cygwin1.dll copy in it's folder.
|
||||
winws will not run without cygwin1.dll outside of cygwin shell.
|
||||
winws2 will not run from cygwin shell with cygwin1.dll copy in it's folder.
|
||||
winws2 will not run without cygwin1.dll outside of cygwin shell.
|
||||
|
||||
100
docs/compile/builder-linux/build_deps.sh
Executable file
100
docs/compile/builder-linux/build_deps.sh
Executable 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
|
||||
107
docs/compile/builder-linux/build_zapret2.sh
Executable file
107
docs/compile/builder-linux/build_zapret2.sh
Executable 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
|
||||
|
||||
170
docs/compile/builder-linux/common.inc
Normal file
170
docs/compile/builder-linux/common.inc
Normal 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
|
||||
}
|
||||
}
|
||||
19
docs/compile/builder-linux/get_toolchains.sh
Executable file
19
docs/compile/builder-linux/get_toolchains.sh
Executable 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
|
||||
@@ -26,7 +26,7 @@ define Package/nfqws2
|
||||
CATEGORY:=Network
|
||||
TITLE:=nfqws2
|
||||
SUBMENU:=Zapret
|
||||
DEPENDS:=+libnetfilter-queue +lmnl +libcap +zlib +$(LUA_DEP)
|
||||
DEPENDS:=+libnetfilter-queue +libmnl +libcap +zlib +$(LUA_DEP)
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
|
||||
5519
docs/manual.en.md
Normal file
5519
docs/manual.en.md
Normal file
File diff suppressed because it is too large
Load Diff
1044
docs/manual.md
1044
docs/manual.md
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
## English
|
||||
|
||||
[Manual](manual.en.md)
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
|
||||
@@ -11,11 +15,15 @@ VPN. Может использоваться для частичной проз
|
||||
[Полный мануал](manual.md)
|
||||
|
||||
|
||||
## Поддержать разработчика
|
||||
## Поддержать разработчика. Donations
|
||||
|
||||
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
|
||||
|
||||
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` (предпочительно сеть ERC-20)
|
||||
If you find this project useful and wish to donate here are crypto wallets :
|
||||
|
||||
USDT ERC `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
||||
|
||||
USDT TRC `TEzAAtn4VhndqEaAyuCM78xh5W2gCjwWEo`
|
||||
|
||||
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
|
||||
|
||||
@@ -40,7 +48,7 @@ zapret2 является дальнейшим развитием проекта
|
||||
|
||||
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позиции и т.д.
|
||||
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
и с большей гибкостью.
|
||||
|
||||
@@ -53,8 +61,7 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое, руководствуясь [талмудом](manual.md) как справочником.
|
||||
|
||||
### Механика обработки трафика
|
||||
|
||||
@@ -414,3 +421,80 @@ nfqws2 \
|
||||
|
||||
Научитесь пользоваться `--debug` логом. Без него будет очень сложно понять *nfqws2* на начальном этапе и приспособиться к новой схеме.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой Lua код. Их надо читать.
|
||||
|
||||
### Не только лишь автономный обман DPI
|
||||
|
||||
Рабочий тестовый пример icmp обфускатора udp от винды к серверу на vps.
|
||||
Для теста используем wireguard. Ничего в конфигах менять не надо - wireguard будет думать, что он работает по udp, но на самом деле он преобразуется в пинги icmp, которые могут проходить NAT. Размер пакетов не изменяется, потому проблемы MTU нет.
|
||||
|
||||
Будем загонять исходящие с клиента в icmp type 8 (echo request) code 199 , исходящие с сервера в icmp type 0 (echo reply) code 199.
|
||||
Код у обоих концов делаем одинаковый, иначе NAT не соотнесет. Без NAT можно коды делать разными для клиента и сервера.
|
||||
Особый icmp code нужен для фильтрации от обычных пингов.
|
||||
|
||||
По стандарту код должен быть 0, но на практике с большой вероятностью работают любые коды.
|
||||
Разные имплементации NAT теоретически могут фильтровать ненулевой код, соотносить или не соотносить код вместе с identifier. Linux NAT соотносит.
|
||||
При любых проблемах убираем wireguard, ставим netcat с обоих концов и пробуем общаться, посматривая в wireshark.
|
||||
Всегда можно откатиться на нулевой код, но тогда у сервера без фильтра по IP клиента будет плохая защита от обычных пингов - все они будут преобразовываться в udp и направляться в wireguard,
|
||||
который будет их игнорировать, поскольку передается мусор. Сервер перестанет пингаться.
|
||||
|
||||
Другой способ избежать проблемы и уйти от стандартных пингов - использовать другие типы icmp. Работающие пары, пробрасываемые Linux NAT :
|
||||
|
||||
- `ctype=8:stype=0` - echo request - echo reply (используется по умолчанию)
|
||||
- `ctype=13:stype=14` - timestamp - timestamp reply
|
||||
- `ctype=15:stype=16` - information request - information reply
|
||||
- `ctype=17:stype=18` - address mask request - address mask reply
|
||||
|
||||
На провайдерских NAT или на аппаратном ускорении роутера может быть другой расклад по работающим парам.
|
||||
Нужно пробовать и смотреть что выходит в сеть после NAT и что приходит на сервер.
|
||||
Например, Linux NAT вообще не пробрасывает type 42 - extended echo request. Но аппаратная железка может пробросить и провайдер тоже.
|
||||
|
||||
Кто знает, может быть DPI настроен сечь icmp тоннели на стандартных пингах, а на других типах icmp нет ?
|
||||
|
||||
|
||||
wireguard server - `1.2.3.4:5555`
|
||||
|
||||
```
|
||||
table ip ztest {
|
||||
chain post {
|
||||
type filter hook output priority mangle; policy accept;
|
||||
meta mark & 0x40000000 == 0x00000000 udp sport 5555 queue flags bypass to 200
|
||||
}
|
||||
|
||||
chain pre {
|
||||
type filter hook input priority mangle; policy accept;
|
||||
meta mark & 0x40000000 == 0x00000000 icmp type echo-request icmp code 199 queue flags bypass to 200
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
nfqws2 --qnum 200 --server
|
||||
--lua-init=@/opt/zapret2/lua/zapret-lib.lua
|
||||
--lua-init=@/opt/zapret2/lua/zapret-obfs.lua
|
||||
--in-range=a
|
||||
--lua-desync=udp2icmp:ccode=199:scode=199
|
||||
```
|
||||
|
||||
Клиент на винде :
|
||||
|
||||
```
|
||||
winws2
|
||||
--wf-icmp-in=0:199 --wf-udp-out=5555
|
||||
--wf-raw-filter="ip.SrcAddr=1.2.3.4 or ip.DstAddr=1.2.3.4"
|
||||
--lua-init=@lua/zapret-lib.lua
|
||||
--lua-init=@lua/zapret-obfs.lua
|
||||
--in-range=a
|
||||
--lua-desync=udp2icmp:ccode=199:scode=199
|
||||
```
|
||||
|
||||
Все лишнее отсекается в ядре в windivert - проц зазря не грузит.
|
||||
--wf-raw-filter сочетается со всем остальным собранным конструктором по AND. Отсекает по IP адресу сервера.
|
||||
--wf-icmp-in отсекает входящие icmp типа 0 с кодом 199.
|
||||
|
||||
И включаем wireguard.
|
||||
В шарке сплошняком пинги и реплаи с кодом 199
|
||||
|
||||
Если IP клиента постоянен, можно дополнительно на стороне сервера сделать фильтр по IP клиента.
|
||||
|
||||
Дополнительно можно сделать dataxor=blob на обоих концах, чтобы поксорить пейлоад.
|
||||
blob растягивается на размер пакета как pattern. Можно использовать от 1 hex byte до специально нагенеренного рандома. На обоих концах должен быть одинаковый
|
||||
|
||||
13
files/fake/sip.bin
Normal file
13
files/fake/sip.bin
Normal file
@@ -0,0 +1,13 @@
|
||||
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
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
||||
|
||||
# can override in config :
|
||||
NFQWS_MY1_OPT="${NFQWS_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}"
|
||||
NFQWS_MY1_SUBNETS4="${NFQWS_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}"
|
||||
NFQWS_MY1_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}"
|
||||
NFQWS_MY1_PORTS_TCP=${NFQWS_MY1_PORTS_TCP:-$NFQWS_PORTS_TCP}
|
||||
NFQWS_MY1_PORTS_UDP=${NFQWS_MY1_PORTS_UDP:-$NFQWS_PORTS_UDP}
|
||||
NFQWS_MY1_TCP_PKT_OUT=${NFQWS_MY1_TCP_PKT_OUT:-$NFQWS_TCP_PKT_OUT}
|
||||
NFQWS_MY1_UDP_PKT_OUT=${NFQWS_MY1_UDP_PKT_OUT:-$NFQWS_UDP_PKT_OUT}
|
||||
NFQWS_MY1_TCP_PKT_IN=${NFQWS_MY1_TCP_PKT_IN:-$NFQWS_TCP_PKT_IN}
|
||||
NFQWS_MY1_UDP_PKT_IN=${NFQWS_MY1_UDP_PKT_IN:-$NFQWS_UDP_PKT_IN}
|
||||
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}
|
||||
NFQWS2_MY1_PORTS_UDP=${NFQWS2_MY1_PORTS_UDP:-$NFQWS2_PORTS_UDP}
|
||||
NFQWS2_MY1_TCP_PKT_OUT=${NFQWS2_MY1_TCP_PKT_OUT:-$NFQWS2_TCP_PKT_OUT}
|
||||
NFQWS2_MY1_UDP_PKT_OUT=${NFQWS2_MY1_UDP_PKT_OUT:-$NFQWS2_UDP_PKT_OUT}
|
||||
NFQWS2_MY1_TCP_PKT_IN=${NFQWS2_MY1_TCP_PKT_IN:-$NFQWS2_TCP_PKT_IN}
|
||||
NFQWS2_MY1_UDP_PKT_IN=${NFQWS2_MY1_UDP_PKT_IN:-$NFQWS2_UDP_PKT_IN}
|
||||
|
||||
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
|
||||
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
|
||||
NFQWS2_MY1_IPSET_SIZE=${NFQWS2_MY1_IPSET_SIZE:-4096}
|
||||
NFQWS2_MY1_IPSET_OPT="${NFQWS2_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS2_MY1_IPSET_SIZE}"
|
||||
|
||||
alloc_dnum DNUM_NFQWS_MY1
|
||||
alloc_qnum QNUM_NFQWS_MY1
|
||||
NFQWS_MY1_NAME4=my1nfqws4
|
||||
NFQWS_MY1_NAME6=my1nfqws6
|
||||
alloc_dnum DNUM_NFQWS2_MY1
|
||||
alloc_qnum QNUM_NFQWS2_MY1
|
||||
NFQWS2_MY1_NAME4=my1nfqws4
|
||||
NFQWS2_MY1_NAME6=my1nfqws6
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
|
||||
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
||||
local opt="--qnum=$QNUM_NFQWS2_MY1 $NFQWS2_MY1_OPT"
|
||||
do_nfqws $1 $DNUM_NFQWS2_MY1 "$opt"
|
||||
}
|
||||
|
||||
zapret_custom_firewall()
|
||||
@@ -32,103 +32,103 @@ zapret_custom_firewall()
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f4 f6 subnet
|
||||
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
|
||||
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
|
||||
local NFQWS2_MY1_PORTS_TCP=$(replace_char - : $NFQWS2_MY1_PORTS_TCP)
|
||||
local NFQWS2_MY1_PORTS_UDP=$(replace_char - : $NFQWS2_MY1_PORTS_UDP)
|
||||
|
||||
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME4
|
||||
for subnet in $NFQWS_MY1_SUBNETS4; do
|
||||
echo add $NFQWS_MY1_NAME4 $subnet
|
||||
ipset create $NFQWS2_MY1_NAME4 $NFQWS2_MY1_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $NFQWS2_MY1_NAME4
|
||||
for subnet in $NFQWS2_MY1_SUBNETS4; do
|
||||
echo add $NFQWS2_MY1_NAME4 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME6
|
||||
for subnet in $NFQWS_MY1_SUBNETS6; do
|
||||
echo add $NFQWS_MY1_NAME6 $subnet
|
||||
ipset create $NFQWS2_MY1_NAME6 $NFQWS2_MY1_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $NFQWS2_MY1_NAME6
|
||||
for subnet in $NFQWS2_MY1_SUBNETS6; do
|
||||
echo add $NFQWS2_MY1_NAME6 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_OUT" -a "$NFQWS2_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="-p tcp -m multiport --dports $NFQWS2_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS2_MY1_TCP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_IN" -a "$NFQWS2_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="-p tcp -m multiport --sports $NFQWS2_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS2_MY1_TCP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_OUT" -a "$NFQWS2_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="-p udp -m multiport --dports $NFQWS2_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS2_MY1_UDP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_IN" -a "$NFQWS2_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="-p udp -m multiport --sports $NFQWS2_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS2_MY1_UDP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
|
||||
[ "$1" = 1 ] || {
|
||||
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
|
||||
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
|
||||
ipset destroy $NFQWS2_MY1_NAME4 2>/dev/null
|
||||
ipset destroy $NFQWS2_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
local f4 f6 subnets
|
||||
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
|
||||
local first_packets_only="$nft_connbytes 1-$NFQWS2_MY1_PKT_OUT"
|
||||
|
||||
[ "$DISABLE_IPV4" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS4
|
||||
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME4
|
||||
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
|
||||
make_comma_list subnets $NFQWS2_MY1_SUBNETS4
|
||||
nft_create_set $NFQWS2_MY1_NAME4 "type ipv4_addr; size $NFQWS2_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS2_MY1_NAME4
|
||||
nft_add_set_element $NFQWS2_MY1_NAME4 "$subnets"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS6
|
||||
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME6
|
||||
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
|
||||
make_comma_list subnets $NFQWS2_MY1_SUBNETS6
|
||||
nft_create_set $NFQWS2_MY1_NAME6 "type ipv6_addr; size $NFQWS2_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS2_MY1_NAME6
|
||||
nft_add_set_element $NFQWS2_MY1_NAME6 "$subnets"
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_OUT" -a "$NFQWS2_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="tcp dport {$NFQWS2_MY1_PORTS_TCP} $(nft_first_packets $NFQWS2_MY1_TCP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_IN" -a "$NFQWS2_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="tcp sport {$NFQWS2_MY1_PORTS_TCP} $(nft_first_packets $NFQWS2_MY1_TCP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_OUT" -a "$NFQWS2_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="udp dport {$NFQWS2_MY1_PORTS_UDP} $(nft_first_packets $NFQWS2_MY1_UDP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_IN" -a "$NFQWS2_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="udp sport {$NFQWS2_MY1_PORTS_UDP} $(nft_first_packets $NFQWS2_MY1_UDP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,6 @@ zapret_custom_firewall_nft_flush()
|
||||
# this function is called after all nft fw rules are deleted
|
||||
# however sets are not deleted. it's desired to clear sets here.
|
||||
|
||||
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
|
||||
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
|
||||
nft_del_set $NFQWS2_MY1_NAME4 2>/dev/null
|
||||
nft_del_set $NFQWS2_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
udp.PayloadLength=148 and udp.Payload[0]=0x01 or
|
||||
udp.PayloadLength=92 and udp.Payload[0]=0x02 or
|
||||
udp.PayloadLength=64 and udp.Payload[0]=0x03
|
||||
udp.PayloadLength=148 and udp.Payload32[0]=0x01000000 or
|
||||
udp.PayloadLength=92 and udp.Payload32[0]=0x02000000 or
|
||||
udp.PayloadLength=64 and udp.Payload32[0]=0x03000000
|
||||
|
||||
@@ -157,7 +157,7 @@ fi
|
||||
unset PKTWS
|
||||
case $UNAME in
|
||||
Linux)
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc linux-riscv64"
|
||||
PKTWS=nfqws2
|
||||
;;
|
||||
FreeBSD)
|
||||
|
||||
@@ -288,7 +288,7 @@ ask_config_tmpdir()
|
||||
echo /tmp in openwrt is tmpfs. on low RAM systems there may be not enough RAM to store downloaded files
|
||||
echo default tmpfs has size of 50% RAM
|
||||
echo "RAM : $(get_ram_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb "$EXEDIR/tmp") Mb"
|
||||
echo select temp file location
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
|
||||
|
||||
@@ -38,6 +38,7 @@ standard fooling :
|
||||
* tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
* tcp_flags_unset=<list> - unset tcp flags in comma separated list
|
||||
* tcp_ts_up - move timestamp tcp option to the top if present (workaround for badack without badseq fooling)
|
||||
* tcp_nop_del - delete NOP tcp options to free space in tcp header
|
||||
|
||||
* fool=fool_function - custom fooling function : fool_func(dis, fooling_options)
|
||||
|
||||
@@ -53,7 +54,7 @@ standard rawsend :
|
||||
|
||||
standard payload :
|
||||
|
||||
* payload - comma separarated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||
* payload - comma separated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||
|
||||
standard ip_id :
|
||||
|
||||
@@ -64,8 +65,10 @@ standard ipfrag :
|
||||
|
||||
* ipfrag[=frag_function] - ipfrag function name. "ipfrag2" by default if empty
|
||||
* ipfrag_disorder - send fragments from last to first
|
||||
* ipfrag2 : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
* ipfrag2 : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
* ipfrag2 : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
* ipfrag2 : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
* ipfrag2 : ipfrag_pos_icmp - icmp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
* ipfrag2 : ipfrag_pos - frag position for other L4. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
* ipfrag2 : ipfrag_next - next protocol field in ipv6 fragment extenstion header of the second fragment. same as first by default.
|
||||
|
||||
]]
|
||||
@@ -113,7 +116,8 @@ end
|
||||
-- standard args : direction
|
||||
function http_domcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -139,7 +143,8 @@ end
|
||||
-- arg : spell=<str> . spelling of the "Host" header. must be exactly 4 chars long
|
||||
function http_hostcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -149,12 +154,17 @@ function http_hostcase(ctx, desync)
|
||||
error("http_hostcase: invalid host spelling '"..spell.."'")
|
||||
else
|
||||
local hdis = http_dissect_req(desync.dis.payload)
|
||||
if hdis.headers.host then
|
||||
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
|
||||
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers.host.pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers.host.pos_header_end+1)
|
||||
return VERDICT_MODIFY
|
||||
if hdis then
|
||||
local idx_host = array_field_search(hdis.headers, "header_low", "host")
|
||||
if idx_host then
|
||||
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
|
||||
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers[idx_host].pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers[idx_host].pos_header_end+1)
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
DLOG("http_hostcase: 'Host:' header not found")
|
||||
end
|
||||
else
|
||||
DLOG("http_hostcase: 'Host:' header not found")
|
||||
DLOG("http_hostcase: http dissect error")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -162,25 +172,32 @@ end
|
||||
|
||||
-- nfqws1 : "--methodeol"
|
||||
-- standard args : direction
|
||||
-- NOTE : if using with other http tampering methodeol should be the last !
|
||||
function http_methodeol(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if desync.l7payload=="http_req" and direction_check(desync) then
|
||||
local hdis = http_dissect_req(desync.dis.payload)
|
||||
local ua = hdis.headers["user-agent"]
|
||||
if ua then
|
||||
if (ua.pos_end - ua.pos_value_start) < 2 then
|
||||
DLOG("http_methodeol: 'User-Agent:' header is too short")
|
||||
if hdis then
|
||||
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
|
||||
if idx_ua then
|
||||
local ua = hdis.headers[idx_ua]
|
||||
if (ua.pos_end - ua.pos_value_start) < 2 then
|
||||
DLOG("http_methodeol: 'User-Agent:' header is too short")
|
||||
else
|
||||
DLOG("http_methodeol: applied")
|
||||
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
DLOG("http_methodeol: applied")
|
||||
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
|
||||
return VERDICT_MODIFY
|
||||
DLOG("http_methodeol: 'User-Agent:' header not found")
|
||||
end
|
||||
else
|
||||
DLOG("http_methodeol: 'User-Agent:' header not found")
|
||||
DLOG("http_methodeol: http dissect error")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -190,17 +207,19 @@ end
|
||||
-- standard args : direction
|
||||
function http_unixeol(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if desync.l7payload=="http_req" and direction_check(desync) then
|
||||
local hdis = http_dissect_req(desync.dis.payload)
|
||||
if hdis then
|
||||
if hdis.headers["user-agent"] then
|
||||
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
|
||||
if idx_ua then
|
||||
local http = http_reconstruct_req(hdis, true)
|
||||
if #http < #desync.dis.payload then
|
||||
hdis.headers["user-agent"].value = hdis.headers["user-agent"].value .. string.rep(" ", #desync.dis.payload - #http)
|
||||
hdis.headers[idx_ua].value = hdis.headers[idx_ua].value .. string.rep(" ", #desync.dis.payload - #http)
|
||||
end
|
||||
local http = http_reconstruct_req(hdis, true)
|
||||
if #http==#desync.dis.payload then
|
||||
@@ -211,7 +230,7 @@ function http_unixeol(ctx, desync)
|
||||
DLOG("http_unixeol: reconstruct differs in size from original: "..#http.."!="..#desync.dis.payload)
|
||||
end
|
||||
else
|
||||
DLOG("http_unixeol: user-agent header absent")
|
||||
DLOG("http_unixeol: 'User-Agent:' header absent")
|
||||
end
|
||||
else
|
||||
DLOG("http_unixeol: could not dissect http")
|
||||
@@ -258,7 +277,8 @@ function synack_split(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -275,7 +295,8 @@ function synack(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -293,7 +314,8 @@ function wsize(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -304,7 +326,8 @@ end
|
||||
-- arg : forced_cutoff=<list> - comma separated list of payloads that trigger forced wssize cutoff. by default - any non-empty payload
|
||||
function wssize(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
local verdict = VERDICT_PASS
|
||||
@@ -333,7 +356,8 @@ end
|
||||
-- arg: sni_last - add name to the end
|
||||
function tls_client_hello_clone(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -375,7 +399,8 @@ function syndata(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -384,7 +409,8 @@ end
|
||||
-- arg : rstack - send RST,ACK instead of RST
|
||||
function rst(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -411,8 +437,8 @@ end
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap . sni=%var is supported
|
||||
function fake(ctx, desync)
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if direction_check(desync) and payload_check(desync) then
|
||||
-- by default process only outgoing known payloads. works only for tcp and udp
|
||||
if (desync.dis.tcp or desync.dis.udp) and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
if not desync.arg.blob then
|
||||
error("fake: 'blob' arg required")
|
||||
@@ -444,7 +470,8 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multisplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -499,11 +526,10 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- internal function for code deduplication. do not call directly
|
||||
|
||||
function pos_normalize(pos, low, hi)
|
||||
return (pos>=low and pos<hi) and (pos-low+1) or nil
|
||||
end
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function pos_array_normalize(pos, low, hi)
|
||||
-- remove positions outside of hi,low range. normalize others to low
|
||||
local i=1
|
||||
@@ -558,7 +584,8 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multidisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -609,7 +636,8 @@ end
|
||||
-- arg : optional - use zero pattern if seqovl_pattern blob is absent
|
||||
function multidisorder_legacy(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -666,7 +694,8 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function hostfakesplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -783,7 +812,8 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakedsplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -887,7 +917,8 @@ end
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakeddisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -998,7 +1029,8 @@ end
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
function tcpseg(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -1043,6 +1075,106 @@ function tcpseg(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : not available
|
||||
-- tpws : close analog is "--split-pos=.. --oob" but works not the same way
|
||||
-- standard args : fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : char - oob char
|
||||
-- arg : byte - oob byte
|
||||
-- arg : urp - urgent pointer position marker, 'b' or 'e'. default - 0
|
||||
function oob(ctx, desync)
|
||||
if not desync.track then return end
|
||||
if not desync.dis.tcp then
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
local key = desync.func_instance.."_syn"
|
||||
if not desync.track.lua_state[key] then
|
||||
if bitand(desync.dis.tcp.th_flags, TH_SYN+TH_ACK)~=TH_SYN then
|
||||
DLOG("oob: must be applied since the very beginning of the tcp connection - SYN packet")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
desync.track.lua_state[key] = true
|
||||
end
|
||||
if desync.outgoing then
|
||||
-- direct pos - outgoing
|
||||
local pos = pos_get(desync, 's', false)
|
||||
if pos<=1 then
|
||||
local dseq = u32add(desync.dis.tcp.th_seq, -1)
|
||||
DLOG("oob: decreasing outgoing seq : "..desync.dis.tcp.th_seq.." => "..dseq)
|
||||
desync.dis.tcp.th_seq = dseq
|
||||
end
|
||||
if pos==0 then
|
||||
return VERDICT_MODIFY
|
||||
elseif pos==1 then
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
if #data==0 then
|
||||
-- empty ACK
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
local oob = desync.arg.char or (desync.arg.byte and bu8(desync.arg.byte) or nil) or "\x00"
|
||||
if #oob~=1 then
|
||||
error("oob: OOB must be exactly one byte")
|
||||
end
|
||||
local dis_oob = deepcopy(desync.dis)
|
||||
local urp
|
||||
if not desync.arg.urp or desync.arg.urp=='b' then
|
||||
urp = 1
|
||||
dis_oob.tcp.th_urp = 0
|
||||
elseif desync.arg.urp=='e' then
|
||||
urp = #data+1
|
||||
dis_oob.tcp.th_urp = urp
|
||||
else
|
||||
urp = resolve_pos(data, desync.l7payload, desync.arg.urp)
|
||||
if not urp then
|
||||
DLOG("oob: cannot resolve urp marker '"..desync.arg.urp.."'")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
DLOG("oob: resolved urp marker to "..urp-1)
|
||||
dis_oob.tcp.th_urp = urp
|
||||
end
|
||||
DLOG("oob: th_urp "..dis_oob.tcp.th_urp)
|
||||
-- one byte OOB payload
|
||||
dis_oob.payload = string.sub(data, 1, urp-1) .. oob .. string.sub(data, urp)
|
||||
dis_oob.tcp.th_flags = bitor(dis_oob.tcp.th_flags, TH_URG)
|
||||
DLOG("oob: sending OOB")
|
||||
if not rawsend_dissect_segmented(desync, dis_oob) then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
if not desync.replay then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
return VERDICT_DROP
|
||||
else
|
||||
-- drop replay and cutoff
|
||||
if desync.replay then
|
||||
DLOG("oob: dropping replay piece")
|
||||
if desync.replay_piece_last then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_DROP
|
||||
end
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
else
|
||||
-- reverse pos - outgoing
|
||||
local pos = pos_get(desync, 's', true)
|
||||
if pos>1 then
|
||||
DLOG("oob: unexpected outgoing position "..pos)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
local dack = u32add(desync.dis.tcp.th_ack, 1)
|
||||
DLOG("oob: increasing incoming ack : "..desync.dis.tcp.th_ack.." => "..dack)
|
||||
desync.dis.tcp.th_ack = dack
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=udplen"
|
||||
-- standard args : direction, payload
|
||||
-- arg : min=N . do not act on payloads smaller than N bytes
|
||||
@@ -1052,7 +1184,8 @@ end
|
||||
-- arg : pattern_offset=N . offset in the pattern. 0 by default
|
||||
function udplen(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -1088,7 +1221,8 @@ end
|
||||
-- arg : dn=N - message starts from "dN". 3 by default
|
||||
function dht_dn(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
|
||||
@@ -58,6 +58,7 @@ function automate_host_record(desync)
|
||||
end
|
||||
-- per-connection storage
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track then return nil end
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
end
|
||||
@@ -106,10 +107,10 @@ end
|
||||
-- hostname is original hostname
|
||||
function is_dpi_redirect(hostname, location)
|
||||
local ds = dissect_url(location)
|
||||
if ds.domain then
|
||||
if ds and ds.domain then
|
||||
local sld1 = dissect_nld(hostname,2)
|
||||
local sld2 = dissect_nld(ds.domain,2)
|
||||
return sld2 and sld1~=sld2
|
||||
return sld2 and sld1~=sld2 and true or false
|
||||
end
|
||||
return false
|
||||
end
|
||||
@@ -180,13 +181,16 @@ function standard_failure_detector(desync, crec)
|
||||
end
|
||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
local hdis = http_dissect_reply(desync.dis.payload)
|
||||
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. NOT a DPI redirect.")
|
||||
if hdis and (hdis.code==302 or hdis.code==307) then
|
||||
local idx_loc = array_field_search(hdis.headers, "header_low", "location")
|
||||
if idx_loc then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers[idx_loc].value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers[idx_loc].value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers[idx_loc].value.."'. NOT a DPI redirect.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -399,8 +403,36 @@ function cond_payload_str(desync)
|
||||
if not desync.arg.pattern then
|
||||
error("cond_payload_str: missing 'pattern'")
|
||||
end
|
||||
return string.find(desync.dis.payload,desync.arg.pattern,1,true)
|
||||
return desync.dis.payload and string.find(desync.dis.payload,desync.arg.pattern,1,true)
|
||||
end
|
||||
-- true if dissect is tcp and timestamp tcp option is present
|
||||
function cond_tcp_has_ts(desync)
|
||||
return desync.dis.tcp and find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS)
|
||||
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")
|
||||
end
|
||||
local fname = desync.func_instance.."_cond_code"
|
||||
if not _G[fname] then
|
||||
local err
|
||||
_G[fname], err = load(desync.arg.code, fname)
|
||||
if not _G[fname] then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- allow dynamic code to access desync
|
||||
_G.desync = desync
|
||||
local res, v = pcall(_G[fname])
|
||||
_G.desync = nil
|
||||
if not res then
|
||||
error(v);
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- check iff function available. error if not
|
||||
function require_iff(desync, name)
|
||||
if not desync.arg.iff then
|
||||
@@ -414,18 +446,55 @@ end
|
||||
-- for example, this can be used by custom protocol detectors
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- arg: instances - how many instances execute conditionally. all if not defined
|
||||
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
function condition(ctx, desync)
|
||||
require_iff(desync, "condition")
|
||||
orchestrate(ctx, desync)
|
||||
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
|
||||
DLOG("condition: true")
|
||||
return replay_execution_plan(desync)
|
||||
else
|
||||
DLOG("condition: false")
|
||||
plan_clear(desync)
|
||||
plan_clear(desync, tonumber(desync.arg.instances))
|
||||
if #desync.plan>0 then
|
||||
DLOG("condition: executing remaining "..#desync.plan.." instance(s)")
|
||||
end
|
||||
end
|
||||
return replay_execution_plan(desync)
|
||||
end
|
||||
-- execute further desync instances.
|
||||
-- each instance may have "cond" and "cond_neg" args.
|
||||
-- "cond" - condition function. "neg" - invert condition function result
|
||||
-- arg: instances - how many instances execute conditionally. all if not defined
|
||||
function per_instance_condition(ctx, desync)
|
||||
orchestrate(ctx, desync)
|
||||
|
||||
local verdict = VERDICT_PASS
|
||||
local n = 0
|
||||
local max = tonumber(desync.arg.instances)
|
||||
while not max or n<max do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
if instance.arg.cond then
|
||||
if type(_G[instance.arg.cond])~="function" then
|
||||
error("per_instance_condition: invalid 'iff' function '"..instance.arg.cond.."'")
|
||||
end
|
||||
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
else
|
||||
DLOG("per_instance_condition: condition not satisfied. skipping '"..instance.func_instance.."'")
|
||||
end
|
||||
else
|
||||
DLOG("per_instance_condition: no 'cond' arg in '"..instance.func_instance.."'. skipping")
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if #desync.plan>0 then
|
||||
DLOG("per_instance_condition: executing remaining "..#desync.plan.." instance(s) unconditionally")
|
||||
end
|
||||
return verdict_aggregate(verdict, replay_execution_plan(desync))
|
||||
end
|
||||
|
||||
-- clear execution plan if user provided 'iff' functions returns true
|
||||
-- can be used with other orchestrators to stop execution conditionally
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
@@ -454,13 +523,17 @@ end
|
||||
function repeater(ctx, desync)
|
||||
local repeats = tonumber(desync.arg.repeats)
|
||||
if not repeats then
|
||||
error("repeat: missing 'repeats'")
|
||||
error("repeater: missing 'repeats'")
|
||||
end
|
||||
local iff = desync.arg.iff or "cond_true"
|
||||
if type(_G[iff])~="function" then
|
||||
error(name..": invalid 'iff' function '"..iff.."'")
|
||||
error("repeater: invalid 'iff' function '"..iff.."'")
|
||||
end
|
||||
orchestrate(ctx, desync)
|
||||
if #desync.plan==0 then
|
||||
DLOG("repeater: execution plan is empty - nothing to repeat")
|
||||
return
|
||||
end
|
||||
local neg = desync.arg.neg
|
||||
local stop = desync.arg.stop
|
||||
local clear = desync.arg.clear
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
NFQWS2_COMPAT_VER_REQUIRED=4
|
||||
NFQWS2_COMPAT_VER_REQUIRED=5
|
||||
|
||||
if NFQWS2_COMPAT_VER~=NFQWS2_COMPAT_VER_REQUIRED then
|
||||
error("Incompatible NFQWS2_COMPAT_VER. Use pktws and lua scripts from the same release !")
|
||||
@@ -18,14 +18,22 @@ function luaexec(ctx, desync)
|
||||
if not desync.arg.code then
|
||||
error("luaexec: no 'code' parameter")
|
||||
end
|
||||
local fname = desync.func_instance.."_luaexec_code"
|
||||
local fname = desync.func_instance.."_code"
|
||||
if not _G[fname] then
|
||||
_G[fname] = load(desync.arg.code, fname)
|
||||
local err
|
||||
_G[fname], err = load(desync.arg.code, fname)
|
||||
if not _G[fname] then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- allow dynamic code to access desync
|
||||
_G.desync = desync
|
||||
_G[fname]()
|
||||
local res, err = pcall(_G[fname])
|
||||
_G.desync = nil
|
||||
if not res then
|
||||
error(err);
|
||||
end
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
@@ -169,9 +177,12 @@ function apply_execution_plan(desync, instance)
|
||||
end
|
||||
-- produce resulting verdict from 2 verdicts
|
||||
function verdict_aggregate(v1, v2)
|
||||
local v
|
||||
v1 = v1 or VERDICT_PASS
|
||||
v2 = v2 or VERDICT_PASS
|
||||
local vn = bitor(bitand(v1,VERDICT_PRESERVE_NEXT),bitand(v2,VERDICT_PRESERVE_NEXT))
|
||||
local v
|
||||
v1 = bitand(v1, VERDICT_MASK)
|
||||
v2 = bitand(v2, VERDICT_MASK)
|
||||
if v1==VERDICT_DROP or v2==VERDICT_DROP then
|
||||
v=VERDICT_DROP
|
||||
elseif v1==VERDICT_MODIFY or v2==VERDICT_MODIFY then
|
||||
@@ -179,7 +190,7 @@ function verdict_aggregate(v1, v2)
|
||||
else
|
||||
v=VERDICT_PASS
|
||||
end
|
||||
return v
|
||||
return bitor(v,vn)
|
||||
end
|
||||
function plan_instance_execute(desync, verdict, instance)
|
||||
apply_execution_plan(desync, instance)
|
||||
@@ -198,8 +209,13 @@ end
|
||||
function plan_instance_pop(desync)
|
||||
return (desync.plan and #desync.plan>0) and table.remove(desync.plan, 1) or nil
|
||||
end
|
||||
function plan_clear(desync)
|
||||
while table.remove(desync.plan) do end
|
||||
function plan_clear(desync, max)
|
||||
if max then
|
||||
local n=0
|
||||
while n<max and table.remove(desync.plan,1) do n=n+1 end
|
||||
else
|
||||
while table.remove(desync.plan) do end
|
||||
end
|
||||
end
|
||||
-- this approach allows nested orchestrators
|
||||
function orchestrate(ctx, desync)
|
||||
@@ -222,12 +238,17 @@ function desync_copy(desync)
|
||||
return dcopy
|
||||
end
|
||||
-- redo what whould be done without orchestration
|
||||
function replay_execution_plan(desync)
|
||||
function replay_execution_plan(desync, max)
|
||||
local verdict = VERDICT_PASS
|
||||
while true do
|
||||
local n=0
|
||||
while not max or n<max do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
n = n + 1
|
||||
end
|
||||
if max and n>=max then
|
||||
DLOG("replay_execution_plan: reached max instances limit "..max)
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
@@ -242,9 +263,9 @@ end
|
||||
|
||||
-- if seq is over 2G s and p position comparision can be wrong
|
||||
function pos_counter_overflow(desync, mode, reverse)
|
||||
if not desync.track or not desync.track.tcp or (mode~='s' and mode~='p') then return false end
|
||||
if not desync.track or (mode~='s' and mode~='p') then return false end
|
||||
local track_pos = reverse and desync.track.pos.reverse or desync.track.pos.direct
|
||||
return track_pos.tcp.rseq_over_2G
|
||||
return track_pos.tcp and track_pos.tcp.rseq_over_2G
|
||||
end
|
||||
-- these functions duplicate range check logic from C code
|
||||
-- mode must be n,d,b,s,x,a
|
||||
@@ -310,24 +331,27 @@ function pos_str(desync, pos)
|
||||
return pos.mode..pos_get(desync, pos.mode)
|
||||
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=""
|
||||
for i=1,#a do
|
||||
s = s .. packer(a[i])
|
||||
sa[i] = packer(a[i])
|
||||
end
|
||||
return s
|
||||
return table.concat(sa)
|
||||
end
|
||||
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=""
|
||||
for k,v in pairs(a) do
|
||||
s = s .. packer(v)
|
||||
sa[k] = packer(v)
|
||||
end
|
||||
return s
|
||||
return table.concat(sa)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -410,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
|
||||
@@ -569,7 +593,6 @@ function array_search(a, v)
|
||||
return k
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
-- linear search array a for a[index].f==v. return index
|
||||
function array_field_search(a, f, v)
|
||||
@@ -578,7 +601,6 @@ function array_field_search(a, f, v)
|
||||
return k
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- find pos of the next eol and pos of the next non-eol character after eol
|
||||
@@ -625,12 +647,47 @@ function parse_tcp_flags(s)
|
||||
end
|
||||
end
|
||||
return f
|
||||
end
|
||||
end
|
||||
|
||||
-- get ip protocol from l3 headers
|
||||
function ip_proto_l3(dis)
|
||||
if dis.ip then
|
||||
return dis.ip.ip_p
|
||||
elseif dis.ip6 then
|
||||
return #dis.ip6.exthdr==0 and dis.ip6.ip6_nxt or dis.ip6.exthdr[#dis.ip6.exthdr].next
|
||||
end
|
||||
end
|
||||
-- get ip protocol from l4 headers
|
||||
function ip_proto_l4(dis)
|
||||
if dis.tcp then
|
||||
return IPPROTO_TCP
|
||||
elseif dis.udp then
|
||||
return IPPROTO_UDP
|
||||
elseif dis.ip then
|
||||
return dis.icmp and IPPROTO_ICMP or nil
|
||||
elseif dis.ip6 then
|
||||
return dis.icmp and IPPROTO_ICMPV6 or nil
|
||||
end
|
||||
end
|
||||
function ip_proto(dis)
|
||||
return ip_proto_l4(dis) or ip_proto_l3(dis)
|
||||
end
|
||||
-- discover ip protocol and fix "next" fields
|
||||
function fix_ip_proto(dis, proto)
|
||||
local pr = proto or ip_proto(dis)
|
||||
if pr then
|
||||
if dis.ip then
|
||||
dis.ip.ip_p = pr
|
||||
elseif dis.ip6 then
|
||||
fix_ip6_next(dis.ip6, pr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- find first tcp options of specified kind in dissect.tcp.options
|
||||
function find_tcp_option(options, kind)
|
||||
if options then
|
||||
for i, opt in pairs(options) do
|
||||
for i, opt in ipairs(options) do
|
||||
if opt.kind==kind then return i end
|
||||
end
|
||||
end
|
||||
@@ -640,7 +697,7 @@ end
|
||||
-- find first ipv6 extension header of specified protocol in dissect.ip6.exthdr
|
||||
function find_ip6_exthdr(exthdr, proto)
|
||||
if exthdr then
|
||||
for i, hdr in pairs(exthdr) do
|
||||
for i, hdr in ipairs(exthdr) do
|
||||
if hdr.type==proto then return i end
|
||||
end
|
||||
end
|
||||
@@ -712,6 +769,14 @@ function dis_reverse(dis)
|
||||
end
|
||||
end
|
||||
|
||||
function dis_reconstruct_l3(dis, options)
|
||||
if dis.ip then
|
||||
return csum_ip4_fix(reconstruct_iphdr(dis.ip))
|
||||
elseif dis.ip6 then
|
||||
return reconstruct_ip6hdr(dis.ip6, options)
|
||||
end
|
||||
end
|
||||
|
||||
-- parse autottl : delta,min-max
|
||||
function parse_autottl(s)
|
||||
if s then
|
||||
@@ -740,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
|
||||
@@ -790,6 +855,7 @@ end
|
||||
-- tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
-- tcp_flags_unset=<list> - unset tcp flags in comma separated list
|
||||
-- tcp_ts_up - move timestamp tcp option to the top if it's present. this allows linux not to accept badack segments without badseq. this is very strange discovery but it works.
|
||||
-- tcp_nop_del - delete NOP tcp options to free space in tcp header
|
||||
|
||||
-- fool - custom fooling function : fool_func(dis, fooling_options)
|
||||
function apply_fooling(desync, dis, fooling_options)
|
||||
@@ -851,6 +917,13 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if fooling_options.tcp_flags_set then
|
||||
dis.tcp.th_flags = bitor(dis.tcp.th_flags, parse_tcp_flags(fooling_options.tcp_flags_set))
|
||||
end
|
||||
if fooling_options.tcp_nop_del then
|
||||
for i=#dis.tcp.options,1,-1 do
|
||||
if dis.tcp.options[i].kind==TCP_KIND_NOOP then
|
||||
table.remove(dis.tcp.options,i)
|
||||
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
|
||||
@@ -874,11 +947,11 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
local bin
|
||||
if fooling_options.ip6_hopbyhop then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
|
||||
end
|
||||
if fooling_options.ip6_hopbyhop2 then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop2,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
|
||||
end
|
||||
-- for possible unfragmentable part
|
||||
if fooling_options.ip6_destopt then
|
||||
@@ -968,7 +1041,7 @@ function l3_extra_len(dis, ip6_exthdr_last_idx)
|
||||
end
|
||||
elseif dis.ip6 and dis.ip6.exthdr then
|
||||
local ct
|
||||
if ip6_exthdr_last_idx and ip6_exthdr_last_idx<=#dis.ip6.exthdr then
|
||||
if ip6_exthdr_last_idx and ip6_exthdr_last_idx>=0 and ip6_exthdr_last_idx<=#dis.ip6.exthdr then
|
||||
ct = ip6_exthdr_last_idx
|
||||
else
|
||||
ct = #dis.ip6.exthdr
|
||||
@@ -995,6 +1068,8 @@ function l4_base_len(dis)
|
||||
return TCP_BASE_LEN
|
||||
elseif dis.udp then
|
||||
return UDP_BASE_LEN
|
||||
elseif dis.icmp then
|
||||
return ICMP_BASE_LEN
|
||||
else
|
||||
return 0
|
||||
end
|
||||
@@ -1034,7 +1109,7 @@ end
|
||||
|
||||
-- option : ipfrag.ipfrag_disorder - send fragments from last to first
|
||||
function rawsend_dissect_ipfrag(dis, options)
|
||||
if options and options.ipfrag and options.ipfrag.ipfrag then
|
||||
if options and options.ipfrag and options.ipfrag.ipfrag and not dis.frag then
|
||||
local frag_func = options.ipfrag.ipfrag=="" and "ipfrag2" or options.ipfrag.ipfrag
|
||||
if type(_G[frag_func]) ~= "function" then
|
||||
error("rawsend_dissect_ipfrag: ipfrag function '"..tostring(frag_func).."' does not exist")
|
||||
@@ -1054,7 +1129,7 @@ function rawsend_dissect_ipfrag(dis, options)
|
||||
if not rawsend_dissect(fragments[i], options.rawsend, reconstruct_frag) then return false end
|
||||
end
|
||||
else
|
||||
for i, d in pairs(fragments) do
|
||||
for i, d in ipairs(fragments) do
|
||||
DLOG("sending ip fragment "..i)
|
||||
-- C function
|
||||
if not rawsend_dissect(d, options.rawsend, reconstruct_frag) then return false end
|
||||
@@ -1070,21 +1145,34 @@ end
|
||||
|
||||
-- send dissect with tcp segmentation based on mss value. appply specified rawsend options.
|
||||
function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
dis = dis or desync.dis
|
||||
local discopy = deepcopy(dis)
|
||||
options = options or desync_opts(desync)
|
||||
apply_fooling(desync, discopy, options and options.fooling)
|
||||
|
||||
if dis.tcp then
|
||||
mss = mss or desync.tcp_mss
|
||||
local extra_len = l3l4_extra_len(discopy)
|
||||
if extra_len >= mss then return false end
|
||||
local max_data = mss - extra_len
|
||||
local urp = dis.tcp.th_urp
|
||||
local oob = bitand(dis.tcp.th_flags, TH_URG)~=0
|
||||
if #discopy.payload > max_data then
|
||||
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(discopy.tcp.th_flags, TH_URG)
|
||||
discopy.tcp.th_urp = urp-pos+1
|
||||
else
|
||||
discopy.tcp.th_flags = bitand(discopy.tcp.th_flags, bitnot(TH_URG))
|
||||
discopy.tcp.th_urp = 0
|
||||
end
|
||||
end
|
||||
discopy.payload = string.sub(payload,pos,pos+len-1)
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
if not rawsend_dissect_ipfrag(discopy, options) then
|
||||
@@ -1104,20 +1192,20 @@ end
|
||||
|
||||
-- send specified payload based on existing L3/L4 headers in the dissect. add seq to tcp.th_seq.
|
||||
function rawsend_payload_segmented(desync, payload, seq, options)
|
||||
options = options or desync_opts(desync)
|
||||
local dis = deepcopy(desync.dis)
|
||||
-- save some cpu and ram
|
||||
local dis = (payload or seq and seq~=0) and deepcopy(desync.dis) or desync.dis
|
||||
if payload then dis.payload = payload end
|
||||
if dis.tcp and seq then
|
||||
dis.tcp.th_seq = dis.tcp.th_seq + seq
|
||||
end
|
||||
return rawsend_dissect_segmented(desync, dis, desync.tcp_mss, options)
|
||||
return rawsend_dissect_segmented(desync, dis, nil, options)
|
||||
end
|
||||
|
||||
|
||||
-- check if desync.outgoing comply with arg.dir or def if it's not present or "out" of they are not present both. dir can be "in","out","any"
|
||||
function direction_check(desync, def)
|
||||
local dir = desync.arg.dir or def or "out"
|
||||
return desync.outgoing and desync.arg.dir~="in" or not desync.outgoing and dir~="out"
|
||||
return desync.outgoing and dir~="in" or not desync.outgoing and dir~="out"
|
||||
end
|
||||
-- if dir "in" or "out" cutoff current desync function from opposite direction
|
||||
function direction_cutoff_opposite(ctx, desync, def)
|
||||
@@ -1160,9 +1248,9 @@ function replay_drop_set(desync, v)
|
||||
if v == nil then v=true end
|
||||
local rdk = replay_drop_key(desync)
|
||||
if v then
|
||||
if desync.replay then desync.track.lua_state[replay_drop_key] = true end
|
||||
if desync.replay then desync.track.lua_state[rdk] = true end
|
||||
else
|
||||
desync.track.lua_state[replay_drop_key] = nil
|
||||
desync.track.lua_state[rdk] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1170,7 +1258,7 @@ end
|
||||
-- return true if the caller should return VERDICT_DROP
|
||||
function replay_drop(desync)
|
||||
if desync.track then
|
||||
local drop = desync.replay and desync.track.lua_state[replay_drop_key]
|
||||
local drop = desync.replay and desync.track.lua_state[replay_drop_key(desync)]
|
||||
if not desync.replay or desync.replay_piece_last then
|
||||
-- replay stopped or last piece of reasm
|
||||
replay_drop_set(desync, false)
|
||||
@@ -1227,6 +1315,31 @@ function host_or_ip(desync)
|
||||
return host_ip(desync)
|
||||
end
|
||||
|
||||
-- rate limited update of global ifaddrs
|
||||
function update_ifaddrs()
|
||||
if ifaddrs then
|
||||
local now = os.time()
|
||||
if not ifaddrs_last then ifaddrs_last = now end
|
||||
if ifaddrs_last~=now then
|
||||
ifaddrs = get_ifaddrs()
|
||||
ifaddrs_last = now
|
||||
end
|
||||
else
|
||||
ifaddrs = get_ifaddrs()
|
||||
end
|
||||
end
|
||||
-- search ifaddrs for ip and return interface name or nil if not found
|
||||
-- do not call get_ifaddrs too often to avoid overhead
|
||||
function ip2ifname(ip)
|
||||
update_ifaddrs()
|
||||
if not ifaddrs then return nil end
|
||||
for ifname,ifinfo in pairs(ifaddrs) do
|
||||
if array_field_search(ifinfo.addr, "addr", ip) then
|
||||
return ifname
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function is_absolute_path(path)
|
||||
if string.sub(path,1,1)=='/' then return true end
|
||||
local un = uname()
|
||||
@@ -1272,8 +1385,10 @@ end
|
||||
|
||||
-- standard fragmentation to 2 ip fragments
|
||||
-- function returns 2 dissects with fragments
|
||||
-- option : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
-- option : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
-- option : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
-- option : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
-- option : ipfrag_pos_icmp - icmp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
-- option : ipfrag_pos - icmp frag position for other L4. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
-- option : ipfrag_next - next protocol field in ipv6 fragment extenstion header of the second fragment. same as first by default.
|
||||
function ipfrag2(dis, ipfrag_options)
|
||||
local function frag_idx(exthdr)
|
||||
@@ -1307,6 +1422,8 @@ function ipfrag2(dis, ipfrag_options)
|
||||
pos = ipfrag_options.ipfrag_pos_tcp or 32
|
||||
elseif dis.udp then
|
||||
pos = ipfrag_options.ipfrag_pos_udp or 8
|
||||
elseif dis.icmp then
|
||||
pos = ipfrag_options.ipfrag_pos_icmp or 8
|
||||
else
|
||||
pos = ipfrag_options.ipfrag_pos or 32
|
||||
end
|
||||
@@ -1323,12 +1440,8 @@ function ipfrag2(dis, ipfrag_options)
|
||||
if (pos+l3)>0xFFFF then
|
||||
error("ipfrag2: too high frag offset")
|
||||
end
|
||||
local plen = l3 + l4_len(dis) + #dis.payload
|
||||
if (pos+l3)>=plen then
|
||||
DLOG("ipfrag2: ip frag pos exceeds packet length. ipfrag cancelled.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local plen = l3 + l4_len(dis) + #dis.payload
|
||||
if dis.ip then
|
||||
-- ipv4 frag is done by both lua and C part
|
||||
-- lua code must correctly set ip_len, IP_MF and ip_off and provide full unfragmented payload
|
||||
@@ -1336,6 +1449,11 @@ function ipfrag2(dis, ipfrag_options)
|
||||
-- ip_off must be set to fragment offset and IP_MF bit must be set if it's not the last fragment
|
||||
-- C code constructs unfragmented packet then moves everything after ip header according to ip_off and ip_len
|
||||
|
||||
if (pos+l3)>=plen then
|
||||
DLOG("ipfrag2: ip frag pos "..pos.." exceeds packet length. ipfrag cancelled.")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- ip_id must not be zero or fragment will be dropped
|
||||
local ip_id = dis.ip.ip_id==0 and math.random(1,0xFFFF) or dis.ip.ip_id
|
||||
dis1 = deepcopy(dis)
|
||||
@@ -1356,7 +1474,15 @@ function ipfrag2(dis, ipfrag_options)
|
||||
-- C code constructs unfragmented packet then moves fragmentable part as needed
|
||||
|
||||
local idxfrag = frag_idx(dis.ip6.exthdr)
|
||||
local l3extra = l3_extra_len(dis, idxfrag-1) + 8 -- all ext headers before frag + 8 bytes for frag header
|
||||
local l3extra = l3_extra_len(dis, idxfrag-1) -- all ext headers before frag
|
||||
|
||||
l3 = l3_base_len(dis) + l3extra
|
||||
if (pos+l3)>=plen then
|
||||
DLOG("ipfrag2: ip frag pos "..pos.." exceeds packet length. ipfrag cancelled.")
|
||||
return nil
|
||||
end
|
||||
|
||||
l3extra = l3extra + 8 -- + 8 bytes for frag header
|
||||
local ident = math.random(1,0xFFFFFFFF)
|
||||
|
||||
dis1 = deepcopy(dis)
|
||||
@@ -1372,7 +1498,6 @@ function ipfrag2(dis, ipfrag_options)
|
||||
end
|
||||
dis2.ip6.ip6_plen = plen - IP6_BASE_LEN + 8 - pos -- packet len without frag + 8 byte frag header - ipv6 base header
|
||||
end
|
||||
|
||||
return {dis1,dis2}
|
||||
end
|
||||
|
||||
@@ -1428,7 +1553,7 @@ end
|
||||
|
||||
-- checks if filename is gzip compressed
|
||||
function is_gzip_file(filename)
|
||||
local f, err = io.open(filename, "r")
|
||||
local f, err = io.open(filename, "rb")
|
||||
if not f then
|
||||
error("is_gzip_file: "..err)
|
||||
end
|
||||
@@ -1439,7 +1564,7 @@ end
|
||||
-- ungzip file to raw string
|
||||
-- expected_ratio = uncompressed_size/compressed_size (default 4)
|
||||
function gunzip_file(filename, expected_ratio, read_block_size)
|
||||
local f, err = io.open(filename, "r")
|
||||
local f, err = io.open(filename, "rb")
|
||||
if not f then
|
||||
error("gunzip_file: "..err)
|
||||
end
|
||||
@@ -1447,7 +1572,7 @@ function gunzip_file(filename, expected_ratio, read_block_size)
|
||||
if not expected_ratio then expected_ratio=4 end
|
||||
|
||||
local decompressed=""
|
||||
gz = gunzip_init()
|
||||
local gz = gunzip_init()
|
||||
if not gz then
|
||||
error("gunzip_file: stream init error")
|
||||
end
|
||||
@@ -1479,14 +1604,14 @@ end
|
||||
-- level : 1..9 (default 9)
|
||||
-- memlevel : 1..8 (default 8)
|
||||
function gzip_file(filename, data, expected_ratio, level, memlevel, compress_block_size)
|
||||
local f, err = io.open(filename, "w")
|
||||
local f, err = io.open(filename, "wb")
|
||||
if not f then
|
||||
error("gzip_file: "..err)
|
||||
end
|
||||
if not write_block_size then compress_block_size=16384 end
|
||||
if not compress_block_size then compress_block_size=16384 end
|
||||
if not expected_ratio then expected_ratio=2 end
|
||||
|
||||
gz = gzip_init(nil, level, memlevel)
|
||||
local gz = gzip_init(nil, level, memlevel)
|
||||
if not gz then
|
||||
error("gzip_file: stream init error")
|
||||
end
|
||||
@@ -1508,7 +1633,7 @@ function gzip_file(filename, data, expected_ratio, level, memlevel, compress_blo
|
||||
end
|
||||
-- reads the whole file
|
||||
function readfile(filename)
|
||||
local f, err = io.open(filename, "r")
|
||||
local f, err = io.open(filename, "rb")
|
||||
if not f then
|
||||
error("readfile: "..err)
|
||||
end
|
||||
@@ -1526,12 +1651,15 @@ function z_readfile(filename, expected_ratio)
|
||||
end
|
||||
-- write data to filename
|
||||
function writefile(filename, data)
|
||||
local f, err = io.open(filename, "w")
|
||||
local f, err = io.open(filename, "wb")
|
||||
if not f then
|
||||
error("writefile: "..err)
|
||||
end
|
||||
local s,err = f:write(data)
|
||||
f:close()
|
||||
if not s then
|
||||
error("writefile: "..err)
|
||||
end
|
||||
end
|
||||
|
||||
-- DISSECTORS
|
||||
@@ -1547,7 +1675,7 @@ function http_dissect_header(header)
|
||||
end
|
||||
-- make table with structured http header representation
|
||||
function http_dissect_headers(http, pos)
|
||||
local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue,pos_headers_next
|
||||
local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue,pos_headers_end
|
||||
headers={}
|
||||
while pos do
|
||||
eol,pnext = find_next_line(http,pos)
|
||||
@@ -1558,7 +1686,7 @@ function http_dissect_headers(http, pos)
|
||||
end
|
||||
header,value,pos_endheader,pos_startvalue = http_dissect_header(header)
|
||||
if header then
|
||||
headers[string.lower(header)] = { header = header, value = value, pos_start = pos, pos_end = eol, pos_header_end = pos+pos_endheader-1, pos_value_start = pos+pos_startvalue-1 }
|
||||
headers[#headers+1] = { header_low = string.lower(header), header = header, value = value, pos_start = pos, pos_end = eol, pos_header_end = pos+pos_endheader-1, pos_value_start = pos+pos_startvalue-1 }
|
||||
end
|
||||
pos=pnext
|
||||
end
|
||||
@@ -1606,14 +1734,20 @@ function http_dissect_reply(http)
|
||||
s = string.sub(http,1,8)
|
||||
if s~="HTTP/1.1" and s~="HTTP/1.0" then return nil end
|
||||
pos = string.find(http,"[ \t\r\n]",10)
|
||||
if not pos then return nil end
|
||||
code = tonumber(string.sub(http,10,pos-1))
|
||||
if not code then return nil end
|
||||
pos = find_next_line(http,pos)
|
||||
return { code = code, headers = http_dissect_headers(http,pos) }
|
||||
s,pos = find_next_line(http,pos)
|
||||
local hdis = { code = code }
|
||||
hdis.headers, hdis.pos_headers_end = http_dissect_headers(http,pos)
|
||||
if hdis.pos_headers_end then
|
||||
hdis.body = string.sub(http, hdis.pos_headers_end)
|
||||
end
|
||||
return hdis
|
||||
end
|
||||
function http_reconstruct_headers(headers, unixeol)
|
||||
local eol = unixeol and "\n" or "\r\n"
|
||||
return headers and btable(headers, function(a) return a.header..": "..a.value..eol end) or ""
|
||||
return headers and barray(headers, function(a) return a.header..": "..a.value..eol end) or ""
|
||||
end
|
||||
function http_reconstruct_req(hdis, unixeol)
|
||||
local eol = unixeol and "\n" or "\r\n"
|
||||
@@ -1990,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))
|
||||
|
||||
@@ -2029,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)
|
||||
@@ -2313,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
|
||||
@@ -2328,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)
|
||||
@@ -2338,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)
|
||||
|
||||
482
lua/zapret-obfs.lua
Normal file
482
lua/zapret-obfs.lua
Normal file
@@ -0,0 +1,482 @@
|
||||
-- test case : --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
|
||||
-- encrypt standard wireguard messages - initiation, response, cookie - and change udp packet size
|
||||
-- do not encrypt data messages and keepalives
|
||||
-- wgobfs adds maximum of 30+padmax bytes to udp size
|
||||
-- reduce MTU of wireguard interface to avoid ip fragmentation !
|
||||
-- without knowing the secret encrypted packets should be crypto strong white noise with no signature
|
||||
-- arg : secret - shared secret. any string. must be the same on both peers
|
||||
-- arg : padmin - min random garbage bytes. 0 by default
|
||||
-- arg : padmax - max random garbage bytes. 16 by default
|
||||
-- NOTE : this function does not depend on zapret-lib.lua and should not be run under orchestrator (uses direct instance_cutoff)
|
||||
function wgobfs(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
|
||||
local padmin = desync.arg.padmin and tonumber(desync.arg.padmin) or 0
|
||||
local padmax = desync.arg.padmax and tonumber(desync.arg.padmax) or 16
|
||||
local function genkey()
|
||||
-- cache key in a global var bound to instance name
|
||||
local key_cache_name = desync.func_instance.."_key"
|
||||
local key = _G[key_cache_name]
|
||||
if not key then
|
||||
key = hkdf("sha256", "wgobfs_salt", desync.arg.secret, nil, 16)
|
||||
_G[key_cache_name] = key
|
||||
end
|
||||
return key
|
||||
end
|
||||
local function maybe_encrypted_payload(payload)
|
||||
for k,plsize in pairs({2+12+16+148, 2+12+16+92, 2+12+16+64}) do
|
||||
if #payload>=(plsize+padmin) and #payload<=(plsize+padmax) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local function wg_payload_from_size(payload)
|
||||
if #payload==148 then return "wireguard_initiation"
|
||||
elseif #payload==92 then return "wireguard_response"
|
||||
elseif #payload==64 then return "wireguard_cookie"
|
||||
else return nil
|
||||
end
|
||||
end
|
||||
|
||||
if not desync.arg.secret or #desync.arg.secret==0 then
|
||||
error("wgobfs: secret required")
|
||||
end
|
||||
if padmin>padmax then
|
||||
error("wgobfs: padmin>padmax")
|
||||
end
|
||||
if (desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie") and #desync.dis.payload<65506 then
|
||||
DLOG("wgobfs: encrypting '"..desync.l7payload.."'. size "..#desync.dis.payload)
|
||||
local key = genkey()
|
||||
-- in aes-gcm every message require it's own crypto secure random iv
|
||||
-- encrypting more than one message with the same iv is considered catastrophic failure
|
||||
-- iv must be sent with encrypted message
|
||||
local iv = bcryptorandom(12)
|
||||
local encrypted, atag = aes_gcm(true, key, iv, bu16(#desync.dis.payload)..desync.dis.payload..brandom(math.random(padmin,padmax)), nil)
|
||||
desync.dis.payload = iv..atag..encrypted
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
|
||||
if desync.l7payload=="unknown" and maybe_encrypted_payload(desync.dis.payload) then
|
||||
local key = genkey()
|
||||
local iv = string.sub(desync.dis.payload,1,12)
|
||||
local atag = string.sub(desync.dis.payload,13,28)
|
||||
local decrypted, atag2 = aes_gcm(false, key, iv, string.sub(desync.dis.payload,29))
|
||||
if atag==atag2 then
|
||||
local plen = u16(decrypted)
|
||||
if plen>(#decrypted-2) then
|
||||
DLOG("wgobfs: bad decrypted payload data")
|
||||
else
|
||||
desync.dis.payload = string.sub(decrypted, 3, 3+plen-1)
|
||||
if b_debug then DLOG("wgobfs: decrypted '"..(wg_payload_from_size(desync.dis.payload) or "unknown").."' message. size "..plen) end
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
DLOG("wgobfs: decrypt auth tag mismatch")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- test case :
|
||||
-- endpoint1:
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{5001}" queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport "{5001}" queue num 200 bypass
|
||||
-- iperf -i 1 -c endpoint2
|
||||
-- endpoint2:
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD --server
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp sport "{5001}" queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport "{5001}" queue num 200 bypass
|
||||
-- iperf -s
|
||||
-- xor ip protocol number and optionally xor tcp,udp,icmp payload with supplied blob pattern
|
||||
-- arg : ippxor - value to xor ip protocol number
|
||||
-- arg : dataxor - blob to xor tcp, udp or icmp payload
|
||||
-- arg : rebuild - always reconstruct desync.dis if after ippxor packet becomes tcp,udp or icmp
|
||||
function ippxor(ctx, desync)
|
||||
local dataxor
|
||||
local function need_dxor(dis)
|
||||
return dataxor and dis.payload and #dis.payload>0 and (dis.tcp or dis.udp or dis.icmp)
|
||||
end
|
||||
local function dxor(dis)
|
||||
dis.payload = bxor(dis.payload, pattern(dataxor,1,#dis.payload))
|
||||
end
|
||||
|
||||
if not desync.arg.ippxor then
|
||||
error("ippxor: ippxor value required")
|
||||
end
|
||||
local ippxor = tonumber(desync.arg.ippxor)
|
||||
if ippxor<0 or ippxor>0xFF then
|
||||
error("ippxor: invalid ippxor value. should be 0..255")
|
||||
end
|
||||
if desync.arg.dataxor then
|
||||
dataxor = blob(desync,desync.arg.dataxor)
|
||||
if #dataxor==0 then
|
||||
error("ippxor: empty dataxor value")
|
||||
end
|
||||
end
|
||||
|
||||
local bdxor = need_dxor(desync.dis)
|
||||
if bdxor then
|
||||
DLOG("ippxor: dataxor size="..#desync.dis.payload)
|
||||
dxor(desync.dis)
|
||||
end
|
||||
|
||||
local l3_from = ip_proto_l3(desync.dis)
|
||||
local l3_to = bitxor(l3_from, ippxor)
|
||||
DLOG("ippxor: "..l3_from.." => "..l3_to)
|
||||
fix_ip_proto(desync.dis, l3_to)
|
||||
|
||||
if (not bdxor and dataxor or desync.arg.rebuild) and
|
||||
(l3_to==IPPROTO_TCP and not desync.dis.tcp or
|
||||
l3_to==IPPROTO_UDP and not desync.dis.udp or
|
||||
l3_to==IPPROTO_ICMP and not (desync.dis.ip and desync.dis.icmp) or
|
||||
l3_to==IPPROTO_ICMPV6 and not (desync.dis.ip6 and desync.dis.icmp))
|
||||
then
|
||||
DLOG("ippxor: packet rebuild")
|
||||
local raw_ip = reconstruct_dissect(desync.dis, {ip6_preserve_next=true})
|
||||
local dis = dissect(raw_ip)
|
||||
if not dis.ip and not dis.ip6 then
|
||||
DLOG_ERR("ippxor: could not rebuild packet")
|
||||
return
|
||||
end
|
||||
desync.dis = dis
|
||||
end
|
||||
|
||||
if not bdxor and need_dxor(desync.dis) then
|
||||
DLOG("ippxor: dataxor size="..#desync.dis.payload)
|
||||
dxor(desync.dis)
|
||||
end
|
||||
|
||||
return VERDICT_MODIFY + VERDICT_PRESERVE_NEXT
|
||||
end
|
||||
|
||||
-- test case:
|
||||
-- endpoint1:
|
||||
-- --in-range=a --lua-desync=udp2icmp
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport 12345 queue num 200 bypass
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto "{icmp,icmpv6}" queue num 200 bypass
|
||||
-- endpoint2:
|
||||
-- --in-range=a --lua-desync=udp2icmp --server
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport 12345 queue num 200 bypass
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto "{icmp,icmpv6}" queue num 200 bypass
|
||||
-- packs udp datagram to icmp message without changing packet size
|
||||
-- function keeps icmp identifier as (sport xor dport) to help traverse NAT (it won't help if NAT changes id)
|
||||
-- one end must be in server mode, another - in client mode
|
||||
-- arg : ctype - client icmp type
|
||||
-- arg : ccode - client icmp code
|
||||
-- arg : stype - server icmp type
|
||||
-- arg : scode - server icmp code
|
||||
-- arg : dataxor - blob to xor udp payload
|
||||
-- arg : server=[0|1] - override server mode. by default use "--server" nfqws2 parameter
|
||||
function udp2icmp(ctx, desync)
|
||||
local dataxor
|
||||
local bserver = desync.arg.server and (desync.arg.server~="0") or b_server
|
||||
|
||||
local function one_byte_arg(name)
|
||||
if desync.arg[name] then
|
||||
local v = tonumber(desync.arg[name])
|
||||
if v<0 or v>0xFF then
|
||||
error("udp2icmp: invalid type or code value. should be 0..255")
|
||||
end
|
||||
return v
|
||||
end
|
||||
end
|
||||
local function ictype(send)
|
||||
local ctype = one_byte_arg("ctype")
|
||||
local stype = one_byte_arg("stype")
|
||||
if logical_xor(ctype,stype) then
|
||||
error("udp2icmp: ctype and stype must be both set or not set")
|
||||
end
|
||||
if not ctype then
|
||||
ctype = desync.dis.ip6 and ICMP6_ECHO_REQUEST or ICMP_ECHO
|
||||
stype = desync.dis.ip6 and ICMP6_ECHO_REPLY or ICMP_ECHOREPLY
|
||||
end
|
||||
return logical_xor(send,bserver) and ctype or stype
|
||||
end
|
||||
local function iccode(send)
|
||||
local ccode = one_byte_arg("ccode")
|
||||
local scode = one_byte_arg("scode")
|
||||
if logical_xor(ccode,scode) then
|
||||
error("udp2icmp: ccode and scode must be both set or not set")
|
||||
end
|
||||
if not ccode then
|
||||
ccode = 0
|
||||
scode = 0
|
||||
end
|
||||
return logical_xor(send,bserver) and ccode or scode
|
||||
end
|
||||
local function plxor()
|
||||
if dataxor then
|
||||
DLOG("udp2icmp: dataxor")
|
||||
desync.dis.payload = bxor(desync.dis.payload, pattern(dataxor,1,#desync.dis.payload))
|
||||
end
|
||||
end
|
||||
|
||||
if desync.arg.dataxor then
|
||||
dataxor = blob(desync,desync.arg.dataxor)
|
||||
if #dataxor==0 then
|
||||
error("udp2icmp: empty dataxor value")
|
||||
end
|
||||
end
|
||||
|
||||
if desync.dis.udp then
|
||||
plxor()
|
||||
if b_debug then -- save some cpu
|
||||
DLOG("udp2icmp: udp => icmp sport="..desync.dis.udp.uh_sport.." dport="..desync.dis.udp.uh_dport.." size="..#desync.dis.payload)
|
||||
end
|
||||
desync.dis.icmp = {
|
||||
icmp_type = ictype(true),
|
||||
icmp_code = iccode(true),
|
||||
icmp_data = u32(
|
||||
bu16(bitxor(desync.dis.udp.uh_sport,desync.dis.udp.uh_dport))..
|
||||
(bserver and bu16(desync.dis.udp.uh_sport) or bu16(desync.dis.udp.uh_dport)))
|
||||
}
|
||||
desync.dis.udp = nil
|
||||
fix_ip_proto(desync.dis)
|
||||
return VERDICT_MODIFY
|
||||
elseif desync.dis.icmp and desync.dis.icmp.icmp_type==ictype(false) and desync.dis.icmp.icmp_code==iccode(false) then
|
||||
local pl = bitand(desync.dis.icmp.icmp_data,0xFFFF)
|
||||
local pm = bitxor(bitrshift(desync.dis.icmp.icmp_data,16),pl)
|
||||
desync.dis.udp = {
|
||||
uh_sport = bserver and pm or pl,
|
||||
uh_dport = bserver and pl or pm,
|
||||
uh_ulen = UDP_BASE_LEN + #desync.dis.payload
|
||||
}
|
||||
desync.dis.icmp = nil
|
||||
fix_ip_proto(desync.dis)
|
||||
if b_debug then -- save some cpu
|
||||
DLOG("udp2icmp: icmp => udp sport="..desync.dis.udp.uh_sport.." dport="..desync.dis.udp.uh_dport.." size="..#desync.dis.payload)
|
||||
end
|
||||
plxor()
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
test case :
|
||||
both:
|
||||
nft create table inet ztest
|
||||
nft add chain inet ztest post "{type filter hook output priority mangle;}"
|
||||
nft add chain inet ztest pre "{type filter hook input priority mangle;}"
|
||||
nft add chain inet ztest predefrag "{type filter hook output priority -401;}"
|
||||
nft add rule inet ztest predefrag "mark & 0x40000000 != 0x00000000 notrack"
|
||||
client:
|
||||
--in-range="<d1" --out-range="<d1" --lua-desync=synhide:synack:ghost=2
|
||||
nft add rule inet ztest post "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == syn queue flags bypass to 200"
|
||||
nft add rule inet ztest pre meta "mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (rst | ack) tcp urgptr != 0 queue flags bypass to 200"
|
||||
nft add rule inet ztest pre meta "mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (rst | ack) tcp option 172 exists queue flags bypass to 200"
|
||||
nft add rule inet ztest pre meta "mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (rst | ack) @th,100,4 != 0 queue flags bypass to 200"
|
||||
server:
|
||||
--in-range=a --lua-desync=synhide:synack
|
||||
nft add rule inet ztest post "meta mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (syn | ack) queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack tcp urgptr != 0 queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack tcp option 172 exists queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack @th,100,4 != 0 queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack ct state new queue flags bypass to 200"
|
||||
|
||||
hides tcp handshake from DPI optionally using ghost SYN packet with low ttl to punch NAT hole
|
||||
NOTE: linux conntrack treats packets without SYN in SYN_SENT state as INVALID ! NAT does not work !
|
||||
NOTE: the only found workaround - put NFQUEUE handler to that packet. It should only return pass verdict.
|
||||
NOTE: BSD and CGNAT should work
|
||||
NOTE: won't likely pass home routers even with hardware offload enabled - SYN state is managed in netfilter before offload. but can work from router itself.
|
||||
|
||||
arg : ghost - ghost syn ttl for ipv4. must be hop_to_last_nat+1. syn is not ghosted if not supplied
|
||||
arg : ghost6 - ghost syn hl for ipv6. must be hop_to_last_nat+1. syn is not ghosted if not supplied
|
||||
arg : synack - also fake synack. NOTE: will likely not work with magic=tsecr on *nix clients because they expect valid echoed tsecr in SYN,ACK
|
||||
arg : magic=[x2|urp|opt|tsecr] - where to put magic value to recognize modified packets
|
||||
arg : x2=bit - th_x2 bit used for magic=x2 - 1,2,4,8
|
||||
arg : kind - kind of tcp option for magic=opt
|
||||
arg : opt=hex - tcp option value
|
||||
arg : xorseq=hex - 4 hex bytes to xor seq
|
||||
--]]
|
||||
function synhide(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
|
||||
local fl = bitand(desync.dis.tcp.th_flags, TH_SYN+TH_ACK+TH_FIN+TH_RST+TH_URG)
|
||||
local tsidx = find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS)
|
||||
local magic
|
||||
if desync.arg.magic then
|
||||
if desync.arg.magic~="tsecr" and desync.arg.magic~="x2" and desync.arg.magic~="urp" and desync.arg.magic~="opt" then
|
||||
error("synhide: invalid magic mode '"..desync.arg.magic.."'")
|
||||
end
|
||||
magic = desync.arg.magic
|
||||
if magic=="tsecr" and not tsidx then
|
||||
DLOG("synhide: cannot use tsecr magic because timestamp option is absent")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
else
|
||||
magic = "x2"
|
||||
end
|
||||
DLOG("synhide: magic="..magic)
|
||||
|
||||
local x2
|
||||
if desync.arg.x2 then
|
||||
x2 = tonumber(desync.arg.x2)
|
||||
if x2<1 or x2>0x0F then
|
||||
error("synhide: invalid x2 value")
|
||||
end
|
||||
else
|
||||
-- some firewalls allow only AECN bit (1). if reserved bits are !=0 => administratively prohibited
|
||||
x2 = 1
|
||||
end
|
||||
|
||||
local kind
|
||||
if desync.arg.kind then
|
||||
kind = tonumber(desync.arg.kind)
|
||||
-- do not allow noop and end
|
||||
if kind<2 or kind>0xFF then
|
||||
error("synhide: invalid kind value")
|
||||
end
|
||||
else
|
||||
kind = 172 -- accurate ecn
|
||||
end
|
||||
|
||||
local opt
|
||||
if desync.arg.opt then
|
||||
opt = parse_hex(desync.arg.opt)
|
||||
if not opt then
|
||||
error("synhide: invalid opt value")
|
||||
end
|
||||
else
|
||||
opt=""
|
||||
end
|
||||
|
||||
|
||||
local xorseq
|
||||
if desync.arg.xorseq then
|
||||
xorseq = parse_hex(desync.arg.xorseq)
|
||||
if not xorseq or #xorseq~=4 then
|
||||
error("synhide: invalid xorseq value")
|
||||
end
|
||||
xorseq = u32(xorseq)
|
||||
end
|
||||
|
||||
local function make_magic(client)
|
||||
local m
|
||||
-- use client seq0
|
||||
m = client and desync.dis.tcp.th_seq or desync.dis.tcp.th_ack-1
|
||||
m = bitxor(bitrshift(m,16),bitand(m,0xFFFF))
|
||||
if m==0 then
|
||||
-- 0 is not acceptable
|
||||
m = client and desync.dis.tcp.th_dport or desync.dis.tcp.th_sport
|
||||
end
|
||||
return m
|
||||
end
|
||||
local function xorhdr()
|
||||
if xorseq then
|
||||
desync.dis.tcp.th_ack = bitxor(desync.dis.tcp.th_ack, xorseq)
|
||||
desync.dis.tcp.th_seq = bitxor(desync.dis.tcp.th_seq, xorseq)
|
||||
end
|
||||
end
|
||||
local function ver_magic(client)
|
||||
local r = false
|
||||
xorhdr()
|
||||
if magic=="tsecr" then
|
||||
r = make_magic(client)==u16(string.sub(desync.dis.tcp.options[tsidx].data,7))
|
||||
elseif magic=="x2" then
|
||||
r = bitand(desync.dis.tcp.th_x2, x2)~=0
|
||||
elseif magic=="urp" then
|
||||
r = desync.dis.tcp.th_urp == make_magic(client)
|
||||
elseif magic=="opt" then
|
||||
local idx = find_tcp_option(desync.dis.tcp.options, kind)
|
||||
r = idx and desync.dis.tcp.options[idx].data == opt
|
||||
end
|
||||
xorhdr()
|
||||
return r
|
||||
end
|
||||
local function set_magic(client)
|
||||
if magic=="tsecr" then
|
||||
desync.dis.tcp.options[tsidx].data = string.sub(desync.dis.tcp.options[tsidx].data,1,6) .. bu16(make_magic(client))
|
||||
elseif magic=="x2" then
|
||||
desync.dis.tcp.th_x2 = bitor(desync.dis.tcp.th_x2, x2)
|
||||
elseif magic=="urp" then
|
||||
desync.dis.tcp.th_urp = make_magic(client)
|
||||
elseif magic=="opt" then
|
||||
table.insert(desync.dis.tcp.options, {kind=kind, data=opt})
|
||||
end
|
||||
xorhdr()
|
||||
end
|
||||
local function clear_magic()
|
||||
xorhdr()
|
||||
if magic=="tsecr" then
|
||||
desync.dis.tcp.options[tsidx].data = string.sub(desync.dis.tcp.options[tsidx].data,1,6) .. "\x00\x00"
|
||||
elseif magic=="x2" then
|
||||
desync.dis.tcp.th_x2 = bitand(desync.dis.tcp.th_x2,bitnot(x2))
|
||||
elseif magic=="urp" then
|
||||
desync.dis.tcp.th_urp = 0
|
||||
elseif magic=="opt" then
|
||||
local idx = find_tcp_option(desync.dis.tcp.options, kind)
|
||||
if idx then
|
||||
table.remove(desync.dis.tcp.options, idx)
|
||||
end
|
||||
end
|
||||
desync.track = conntrack_feed(desync.dis)
|
||||
end
|
||||
|
||||
if fl==TH_SYN then
|
||||
-- client sent
|
||||
local ttl = tonumber(desync.dis.ip and desync.arg.ghost or desync.arg.ghost6)
|
||||
if ttl then
|
||||
DLOG("synhide: punch NAT hole with ttl="..ttl)
|
||||
local dis = deepcopy(desync.dis)
|
||||
if dis.ip then
|
||||
dis.ip.ip_ttl = ttl
|
||||
elseif dis.ip6 then
|
||||
dis.ip6.ip6_hlim = ttl
|
||||
end
|
||||
if not rawsend_dissect(dis, rawsend_opts_base(desync)) then
|
||||
instance_cutoff_shim(ctx, desync) -- failed
|
||||
return
|
||||
end
|
||||
end
|
||||
DLOG("synhide: client sends SYN. remove SYN")
|
||||
set_magic(true)
|
||||
-- remove SYN, set ACK
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_SYN)), TH_ACK)
|
||||
if not desync.arg.synack then
|
||||
DLOG("synhide: mission complete")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_MODIFY
|
||||
elseif fl==(TH_SYN+TH_ACK) then
|
||||
-- server sent
|
||||
if desync.arg.synack then
|
||||
DLOG("synhide: server sends SYN+ACK. remove SYN, set RST")
|
||||
set_magic(false)
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_SYN)), TH_RST)
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
DLOG("synhide: server sends SYN+ACK. do not remove SYN because 'synack' arg is not set.")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return -- do nothing
|
||||
end
|
||||
elseif fl==TH_ACK and ver_magic(true) then
|
||||
DLOG("synhide: server received magic. restore SYN")
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_ACK)), TH_SYN)
|
||||
clear_magic()
|
||||
if not desync.arg.synack then
|
||||
DLOG("synhide: mission complete")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_MODIFY
|
||||
elseif fl==(TH_ACK+TH_RST) and ver_magic(false) then
|
||||
DLOG("synhide: client received magic. restore SYN, remove RST")
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_RST)), TH_SYN)
|
||||
clear_magic()
|
||||
DLOG("synhide: mission complete")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
|
||||
DLOG("synhide: sequence failed")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
@@ -30,7 +30,7 @@ function pcap(ctx, desync)
|
||||
os.remove(_G[fn_cache_name])
|
||||
end
|
||||
end
|
||||
local f = io.open(_G[fn_cache_name], "a")
|
||||
local f = io.open(_G[fn_cache_name], "ab")
|
||||
if not f then
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
|
||||
@@ -13,15 +13,19 @@ end
|
||||
|
||||
|
||||
function test_all(...)
|
||||
test_run({test_crypto, test_bin, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve, test_rawsend},...)
|
||||
test_run({
|
||||
test_crypto, test_bin, test_time, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
|
||||
test_get_source_ip, test_ifaddrs, test_rawsend},...)
|
||||
end
|
||||
|
||||
|
||||
function test_crypto(...)
|
||||
test_run({test_random, test_aes, test_aes_gcm, test_aes_ctr, test_hkdf, test_hash},...)
|
||||
test_run({test_random, test_bop, test_aes, test_aes_gcm, test_aes_ctr, test_hkdf, test_hash},...)
|
||||
end
|
||||
|
||||
function test_random()
|
||||
print("* random")
|
||||
|
||||
local rnds={}
|
||||
for i=1,20 do
|
||||
local rnd = bcryptorandom(math.random(10,20))
|
||||
@@ -31,7 +35,35 @@ function test_random()
|
||||
end
|
||||
end
|
||||
|
||||
function test_bop()
|
||||
print("* bop")
|
||||
|
||||
for n,test in ipairs(
|
||||
{
|
||||
{ fb = bxor, fbit = bitxor, nb = "bxor", nbit="bitxor" },
|
||||
{ fb = bor, fbit = bitor, nb = "bor", nbit="bitor" },
|
||||
{ fb = band, fbit = bitand, nb = "band", nbit="bitand" }
|
||||
}) do
|
||||
for k=1,5 do
|
||||
local r = {}
|
||||
for i=1,6 do r[i] = math.random(0,0xFFFFFFFFFFFF) end
|
||||
local v1 = bu48(r[1])..bu48(r[2])..bu48(r[3])
|
||||
local v2 = bu48(r[4])..bu48(r[5])..bu48(r[6])
|
||||
print("x1 : "..string2hex(v1))
|
||||
print("x2 : "..string2hex(v2))
|
||||
local v3 = test.fb(v1,v2)
|
||||
local v4 = bu48(test.fbit(r[1],r[4]))..bu48(test.fbit(r[2],r[5]))..bu48(test.fbit(r[3],r[6]))
|
||||
print(test.nb.." : "..string2hex(v3))
|
||||
print(test.nbit.." : "..string2hex(v4))
|
||||
print("result : "..(v3==v4 and "OK" or "FAIL"))
|
||||
test_assert(v3==v4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function test_hash()
|
||||
print("* hash")
|
||||
|
||||
local hashes={}
|
||||
for i=1,5 do
|
||||
local rnd = brandom(math.random(5,64))
|
||||
@@ -48,6 +80,8 @@ function test_hash()
|
||||
end
|
||||
|
||||
function test_hkdf()
|
||||
print("* hkdf")
|
||||
|
||||
local nblob = 2
|
||||
local okms = {}
|
||||
for nsalt=1,nblob do
|
||||
@@ -56,10 +90,9 @@ function test_hkdf()
|
||||
local ikm = brandom(math.random(5,10))
|
||||
for ninfo=1,nblob do
|
||||
local info = brandom(math.random(5,10))
|
||||
local okm_prev
|
||||
for k,sha in pairs({"sha256","sha224"}) do
|
||||
for k,okml in pairs({8, 16, 50}) do
|
||||
local okm_prev
|
||||
for k,okml in pairs({8, 16, 50}) do
|
||||
local okm
|
||||
print("* hkdf "..sha)
|
||||
print("salt: "..string2hex(salt))
|
||||
@@ -73,7 +106,6 @@ function test_hkdf()
|
||||
print("duplicate okm !")
|
||||
end
|
||||
okms[okm] = true
|
||||
|
||||
test_assert(not okm_prev or okm_prev==string.sub(okm, 1, #okm_prev))
|
||||
okm_prev = okm
|
||||
end
|
||||
@@ -84,6 +116,8 @@ function test_hkdf()
|
||||
end
|
||||
|
||||
function test_aes()
|
||||
print("* aes")
|
||||
|
||||
local clear_text="test "..brandom_az09(11)
|
||||
local iv, key, encrypted, decrypted
|
||||
|
||||
@@ -93,7 +127,7 @@ function test_aes()
|
||||
print()
|
||||
print("* aes test key_size "..tostring(key_size))
|
||||
|
||||
print("clear text: "..clear_text);
|
||||
print("clear text: "..clear_text)
|
||||
|
||||
print("* encrypting")
|
||||
encrypted = aes(true, key, clear_text)
|
||||
@@ -121,6 +155,8 @@ function test_aes()
|
||||
end
|
||||
|
||||
function test_aes_gcm()
|
||||
print("* aes_gcm")
|
||||
|
||||
local authenticated_data = "authenticated message "..brandom_az09(math.random(10,50))
|
||||
local clear_text="test message "..brandom_az09(math.random(10,50))
|
||||
local iv, key, encrypted, atag, decrypted, atag2
|
||||
@@ -132,8 +168,8 @@ function test_aes_gcm()
|
||||
print()
|
||||
print("* aes_gcm test key_size "..tostring(key_size))
|
||||
|
||||
print("clear text: "..clear_text);
|
||||
print("authenticated data: "..authenticated_data);
|
||||
print("clear text: "..clear_text)
|
||||
print("authenticated data: "..authenticated_data)
|
||||
|
||||
print("* encrypting")
|
||||
encrypted, atag = aes_gcm(true, key, iv, clear_text, authenticated_data)
|
||||
@@ -188,6 +224,8 @@ function test_aes_gcm()
|
||||
end
|
||||
|
||||
function test_aes_ctr()
|
||||
print("* aes_ctr")
|
||||
|
||||
local clear_text="test message "..brandom_az09(math.random(10,50))
|
||||
local iv, key, encrypted, decrypted
|
||||
|
||||
@@ -198,7 +236,7 @@ function test_aes_ctr()
|
||||
print()
|
||||
print("* aes_ctr test key_size "..tostring(key_size))
|
||||
|
||||
print("clear text: "..clear_text);
|
||||
print("clear text: "..clear_text)
|
||||
|
||||
print("* encrypting")
|
||||
encrypted = aes_ctr(key, iv, clear_text)
|
||||
@@ -251,6 +289,8 @@ function test_aes_ctr()
|
||||
end
|
||||
|
||||
function test_ub()
|
||||
print("* ub")
|
||||
|
||||
for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}, {u48,bu48,0xFFFFFFFFFFFF,48}}) do
|
||||
local v = math.random(0,f[3])
|
||||
local pos = math.random(1,20)
|
||||
@@ -262,6 +302,8 @@ function test_ub()
|
||||
end
|
||||
|
||||
function test_bit()
|
||||
print("* bit")
|
||||
|
||||
local v, v2, v3, v4, b1, b2, pow
|
||||
|
||||
for i=1,100 do
|
||||
@@ -305,6 +347,8 @@ function test_bit()
|
||||
end
|
||||
|
||||
function test_swap()
|
||||
print("* swap")
|
||||
|
||||
local v1, v2, v3
|
||||
|
||||
v1 = math.random(0,0xFFFF)
|
||||
@@ -338,7 +382,10 @@ function test_swap()
|
||||
end
|
||||
|
||||
function test_ux()
|
||||
print("* ux")
|
||||
|
||||
local v1, v2, v3, usum, sum
|
||||
|
||||
for k,test in pairs({
|
||||
{ add=u8add, fname="u8add", max = 0xFF },
|
||||
{ add=u16add, fname="u16add", max = 0xFFFF },
|
||||
@@ -366,7 +413,45 @@ function test_bin(...)
|
||||
test_run({test_ub, test_bit, test_swap, test_ux},...)
|
||||
end
|
||||
|
||||
function test_time(...)
|
||||
print("* time")
|
||||
|
||||
local unixtime=os.time()
|
||||
local tm = localtime(unixtime);
|
||||
local t
|
||||
print()
|
||||
print("now: "..tm.str.." "..tm.zone.." = "..unixtime)
|
||||
local tm = gmtime(unixtime);
|
||||
print("gmt: "..tm.str.." "..tm.zone.." = "..unixtime)
|
||||
print()
|
||||
for i=1,20 do
|
||||
unixtime = math.random(0,0x7FFFFFFF);
|
||||
tm = localtime(unixtime);
|
||||
t = timelocal(tm)
|
||||
print("timelocal: "..tm.str.." "..tm.zone.." = "..t)
|
||||
print( t==unixtime and "LOCALTIME OK" or "LOCALTIME FAILED" )
|
||||
test_assert(t==unixtime)
|
||||
|
||||
unixtime = math.random(0,0x7FFFFFFF);
|
||||
tm = gmtime(unixtime);
|
||||
t = timegm(tm)
|
||||
print("timegm: "..tm.str.." "..tm.zone.." = "..t)
|
||||
print( t==unixtime and "GMTIME OK" or "GMTIME FAILED" )
|
||||
test_assert(t==unixtime)
|
||||
end
|
||||
unixtime = math.random(0x80000000,0xFFFFFFFF);
|
||||
tm = gmtime(unixtime)
|
||||
t = timegm(tm)
|
||||
print( t==unixtime and "TIME 0x80000000..0xFFFFFFFF OK" or "TIME 0x80000000..0xFFFFFFFF FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
|
||||
unixtime = math.random(0x100000000,0x200000000);
|
||||
tm = gmtime(unixtime)
|
||||
t = timegm(tm)
|
||||
print( t==unixtime and "TIME 64 OK" or "TIME 64 FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
|
||||
end
|
||||
|
||||
function test_gzip()
|
||||
print("* gzip")
|
||||
|
||||
local s=""
|
||||
for i=1,math.random(2000,3000) do
|
||||
local rnd=brandom(math.random(1,50))
|
||||
@@ -397,9 +482,11 @@ function test_gzip()
|
||||
end
|
||||
|
||||
function test_ipstr()
|
||||
print("* ipstr")
|
||||
|
||||
local s_ip, ip, s_ip2
|
||||
|
||||
s_ip = string.format("%u.%u.%u.%u", math.random(0,255), math.random(0,255), math.random(0,255), math.random(0,255));
|
||||
s_ip = string.format("%u.%u.%u.%u", math.random(0,255), math.random(0,255), math.random(0,255), math.random(0,255))
|
||||
ip = pton(s_ip)
|
||||
s_ip2 = ntop(ip)
|
||||
print("IP: "..s_ip)
|
||||
@@ -407,7 +494,7 @@ function test_ipstr()
|
||||
print("IP2: "..s_ip2)
|
||||
test_assert(s_ip==s_ip2)
|
||||
|
||||
s_ip = string.format("%x:%x:%x:%x:%x:%x:%x:%x", math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF));
|
||||
s_ip = string.format("%x:%x:%x:%x:%x:%x:%x:%x", math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF))
|
||||
ip = pton(s_ip)
|
||||
s_ip2 = ntop(ip)
|
||||
print("IP: "..s_ip)
|
||||
@@ -418,6 +505,8 @@ end
|
||||
|
||||
|
||||
function test_dissect()
|
||||
print("* dissect")
|
||||
|
||||
local dis, raw1, raw2
|
||||
|
||||
for i=1,20 do
|
||||
@@ -455,13 +544,56 @@ function test_dissect()
|
||||
}
|
||||
raw1 = reconstruct_dissect(ip_tcp)
|
||||
print("IP+TCP : "..string2hex(raw1))
|
||||
dis1 = dissect(raw1);
|
||||
dis1 = dissect(raw1)
|
||||
raw2 = reconstruct_dissect(dis1)
|
||||
dis2 = dissect(raw2);
|
||||
dis2 = dissect(raw2)
|
||||
print("IP+TCP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("IP standalone")
|
||||
raw1 = reconstruct_iphdr(ip_tcp.ip)
|
||||
print("IP1: "..string2hex(raw1))
|
||||
dis1 = dissect_iphdr(raw1)
|
||||
raw2 = reconstruct_iphdr(dis1)
|
||||
print("IP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("TCP standalone")
|
||||
raw1 = reconstruct_tcphdr(ip_tcp.tcp)
|
||||
print("TCP1: "..string2hex(raw1))
|
||||
dis1 = dissect_tcphdr(raw1)
|
||||
raw2 = reconstruct_tcphdr(dis1)
|
||||
print("TCP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
local ip_icmp = {
|
||||
ip = {
|
||||
ip_tos = math.random(0,255),
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
ip_ttl = math.random(0,255),
|
||||
ip_p = IPPROTO_ICMP,
|
||||
ip_src = brandom(4),
|
||||
ip_dst = brandom(4),
|
||||
options = brandom(math.random(0,40))
|
||||
},
|
||||
icmp = {
|
||||
icmp_type = ICMP_DEST_UNREACH, icmp_code=ICMP_UNREACH_PORT,
|
||||
icmp_data = math.random(1,0xFFFFFFFF)
|
||||
}
|
||||
}
|
||||
print("ICMP standalone")
|
||||
raw1 = reconstruct_icmphdr(ip_icmp.icmp)
|
||||
print("ICMP1: "..string2hex(raw1))
|
||||
dis1 = dissect_icmphdr(raw1)
|
||||
raw2 = reconstruct_icmphdr(dis1)
|
||||
print("ICMP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
local ip6_udp = {
|
||||
ip6 = {
|
||||
ip6_flow = 0x60000000 + math.random(0,0xFFFFFFF),
|
||||
@@ -482,18 +614,56 @@ function test_dissect()
|
||||
|
||||
raw1 = reconstruct_dissect(ip6_udp)
|
||||
print("IP6+UDP : "..string2hex(raw1))
|
||||
dis1 = dissect(raw1);
|
||||
dis1 = dissect(raw1)
|
||||
raw2 = reconstruct_dissect(dis1)
|
||||
dis2 = dissect(raw2);
|
||||
dis2 = dissect(raw2)
|
||||
print("IP6+UDP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
raw1 = string.sub(reconstruct_dissect(ip6_udp),1,-4-#ip6_udp.payload)
|
||||
dis1 = dissect(raw1, false)
|
||||
dis2 = dissect(raw1, true)
|
||||
local ok = not dis1.ip6 and dis2.ip6
|
||||
print("IP6 partial : "..(ok and "OK" or "FAIL"))
|
||||
test_assert(ok)
|
||||
|
||||
print("IP6+IPP")
|
||||
dis1 = {ip6 = ip6_udp.ip6, payload=brandom(math.random(1,1))}
|
||||
raw1 = reconstruct_dissect(dis1,{ip6_last_proto=IPPROTO_IPIP})
|
||||
dis2 = dissect(raw1)
|
||||
raw2 = reconstruct_dissect(dis2,{ip6_preserve_next=true})
|
||||
print("IP6+IPP1: "..string2hex(raw1))
|
||||
print("IP6+IPP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("UDP standalone")
|
||||
raw1 = reconstruct_udphdr(ip6_udp.udp)
|
||||
print("UDP1: "..string2hex(raw1))
|
||||
dis1 = dissect_udphdr(raw1)
|
||||
raw2 = reconstruct_udphdr(dis1)
|
||||
print("UDP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("IP6 standalone")
|
||||
ip6_udp.ip6.ip6_plen = nil
|
||||
raw1 = reconstruct_ip6hdr(ip6_udp.ip6,{ip6_last_proto=IPPROTO_UDP})
|
||||
print("IP1: "..string2hex(raw1))
|
||||
dis1 = dissect_ip6hdr(raw1)
|
||||
raw2 = reconstruct_ip6hdr(dis1,{ip6_last_proto=IPPROTO_UDP})
|
||||
print("IP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
end
|
||||
end
|
||||
|
||||
function test_csum()
|
||||
print("* csum")
|
||||
|
||||
local payload = brandom(math.random(10,20))
|
||||
local ip4b, ip6b, raw, tcpb, udpb, dis1, dis2
|
||||
local ip4b, ip6b, raw, tcpb, udpb, icmpb, dis1, dis2
|
||||
local ip = {
|
||||
ip_tos = math.random(0,255),
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
@@ -559,6 +729,8 @@ function test_csum()
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, tcp=tcp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
ip.ip_len = IP_BASE_LEN + #ip.options + #tcpb + #payload
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
tcpb = csum_tcp_fix(ip4b,tcpb,payload)
|
||||
dis2 = dissect(ip4b..tcpb..payload)
|
||||
print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP4 CSUM OK" or "TCP+IP4 CSUM FAILED" )
|
||||
@@ -594,18 +766,17 @@ function test_csum()
|
||||
print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP6 CSUM OK" or "TCP+IP6 CSUM FAILED" )
|
||||
test_assert(dis1.tcp.th_sum==dis2.tcp.th_sum)
|
||||
|
||||
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP})
|
||||
|
||||
local udp = {
|
||||
uh_sport = math.random(0,0xFFFF),
|
||||
uh_dport = math.random(0,0xFFFF),
|
||||
uh_ulen = UDP_BASE_LEN + #payload
|
||||
}
|
||||
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP})
|
||||
|
||||
udpb = reconstruct_udphdr(udp)
|
||||
raw = bu16(udp.uh_sport) ..
|
||||
bu16(udp.uh_dport) ..
|
||||
@@ -616,6 +787,8 @@ function test_csum()
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, udp=udp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
ip.ip_len = IP_BASE_LEN + #ip.options + #udpb + #payload
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
udpb = csum_udp_fix(ip4b,udpb,payload)
|
||||
dis2 = dissect(ip4b..udpb..payload)
|
||||
print( dis1.udp.uh_sum==dis2.udp.uh_sum and "UDP+IP4 CSUM OK" or "UDP+IP4 CSUM FAILED" )
|
||||
@@ -627,9 +800,42 @@ function test_csum()
|
||||
dis2 = dissect(ip6b..udpb..payload)
|
||||
print( dis1.udp.uh_sum==dis2.udp.uh_sum and "UDP+IP6 CSUM OK" or "UDP+IP6 CSUM FAILED" )
|
||||
test_assert(dis1.udp.uh_sum==dis2.udp.uh_sum)
|
||||
|
||||
local icmp = {
|
||||
icmp_type = math.random(0,0xFF), icmp_code=math.random(0,0xFF),
|
||||
icmp_data = math.random(0,0xFFFFFFFF)
|
||||
}
|
||||
ip.ip_p = IPPROTO_ICMP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,icmp=icmp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_ICMPV6})
|
||||
|
||||
icmpb = reconstruct_icmphdr(icmp)
|
||||
raw = bu8(icmp.icmp_type) ..
|
||||
bu8(icmp.icmp_code) ..
|
||||
bu16(0) ..
|
||||
bu32(icmp.icmp_data)
|
||||
print( raw==icmpb and "ICMP RECONSTRUCT OK" or "ICMP RECONSTRUCT FAILED" )
|
||||
test_assert(raw==icmpb)
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, icmp=icmp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
icmpb = csum_icmp_fix(ip4b,icmpb,payload)
|
||||
dis2 = dissect(ip4b..icmpb..payload)
|
||||
print( dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum and "ICMP+IP4 CSUM OK" or "ICMP+IP4 CSUM FAILED" )
|
||||
test_assert(dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum)
|
||||
|
||||
raw = reconstruct_dissect({ip6=ip6, icmp=icmp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
icmpb = csum_icmp_fix(ip6b,icmpb,payload)
|
||||
dis2 = dissect(ip6b..icmpb..payload)
|
||||
print( dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum and "ICMP+IP6 CSUM OK" or "ICMP+IP6 CSUM FAILED" )
|
||||
test_assert(dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum)
|
||||
end
|
||||
|
||||
function test_resolve()
|
||||
print("* resolve")
|
||||
|
||||
local pos
|
||||
|
||||
local tdis = tls_dissect(fake_default_tls)
|
||||
@@ -678,7 +884,33 @@ function test_resolve()
|
||||
print("resolve_pos http non-existent : "..m.." : "..tostring(pos))
|
||||
end
|
||||
|
||||
function test_get_source_ip(opts)
|
||||
print("* get_source_ip")
|
||||
|
||||
for k,d in ipairs({
|
||||
'127.0.0.1','192.168.1.1','10.1.1.1','1.1.1.1','255.255.255.255',
|
||||
'::1','fc81::4','2a06::1','2001:470::1','2002:0101:0101::1','::1.1.1.1'})
|
||||
do
|
||||
local src = get_source_ip(pton(d))
|
||||
print((src and ntop(src) or "?").." => "..d)
|
||||
end
|
||||
end
|
||||
function test_ifaddrs(opts)
|
||||
print("* ifaddrs")
|
||||
|
||||
local ifa = get_ifaddrs()
|
||||
test_assert(ifa)
|
||||
for ifname,ifinfo in pairs(ifa) do
|
||||
print(ifname.." index="..tostring(ifinfo.index).." mtu="..tostring(ifinfo.mtu))
|
||||
for i,addr in ipairs(ifinfo.addr) do
|
||||
print(" "..ntop(addr.addr)..(addr.netmask and " mask "..tostring(ntop(addr.netmask)) or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function test_rawsend(opts)
|
||||
print("* rawsend")
|
||||
|
||||
local ifout = (opts and opts.ifout) and opts.ifout
|
||||
local function rawsend_fail_warning()
|
||||
if not opts or not opts.ifout or #opts.ifout==0 then
|
||||
@@ -688,13 +920,13 @@ function test_rawsend(opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
local function rawsend_dissect_print(dis, options)
|
||||
local function rawsend_dissect_print(dis, options, reconstruct)
|
||||
if options then
|
||||
options.ifout = ifout
|
||||
else
|
||||
options = { ifout = ifout }
|
||||
end
|
||||
local b = rawsend_dissect(dis, options)
|
||||
local b = rawsend_dissect(dis, options, reconstruct)
|
||||
if not b then
|
||||
print("rawsend_dissect failed")
|
||||
rawsend_fail_warning()
|
||||
@@ -719,15 +951,30 @@ function test_rawsend(opts)
|
||||
local payload = brandom(math.random(100,1200))
|
||||
local b
|
||||
|
||||
local target
|
||||
for ifname,ifinfo in pairs(get_ifaddrs()) do
|
||||
for k,v in pairs(ifinfo.addr) do
|
||||
if #v.addr==4 and string.sub(v.addr,1,2)=="\xC0\xA8" then
|
||||
target = string.sub(v.addr,1,3)..bu8(u8add(u8(v.addr,4),1))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
target = target or pton("192.168.254.32")
|
||||
print("ipv4 target is "..ntop(target))
|
||||
ip = {
|
||||
ip_tos = 0,
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
ip_ttl = 1,
|
||||
ip_p = IPPROTO_UDP,
|
||||
ip_src = pton("192.168.1.1"),
|
||||
ip_dst = pton("192.168.1.2")
|
||||
ip_src = get_source_ip(target),
|
||||
ip_dst = target
|
||||
}
|
||||
if not ip.ip_src then
|
||||
print("dest "..ntop(target).." unreachable")
|
||||
test_assert(false)
|
||||
end
|
||||
udp = {
|
||||
uh_sport = math.random(0,0xFFFF),
|
||||
uh_dport = math.random(0,0xFFFF)
|
||||
@@ -750,18 +997,42 @@ function test_rawsend(opts)
|
||||
print("send ipv4 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend_print(raw, {repeats=5}))
|
||||
|
||||
local target
|
||||
for ifname,ifinfo in pairs(get_ifaddrs()) do
|
||||
for k,v in pairs(ifinfo.addr) do
|
||||
if #v.addr==16 and (string.sub(v.addr,1,1)=="\xFC" or string.sub(v.addr,1,1)=="\xFD") then
|
||||
target = string.sub(v.addr,1,1)..bu8(u8add(u8(v.addr,2),1))..string.sub(v.addr,3)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
target = target or pton("fdce:3124:164a:5318::2")
|
||||
print("ipv6 target is "..ntop(target))
|
||||
ip6 = {
|
||||
ip6_flow = 0x60000000,
|
||||
ip6_hlim = 1,
|
||||
ip6_src = pton("fdce:3124:164a:5318::1"),
|
||||
ip6_dst = pton("fdce:3124:164a:5318::2")
|
||||
ip6_src = get_source_ip(target),
|
||||
ip6_dst = target
|
||||
}
|
||||
if not ip6.ip6_src then
|
||||
print("dest "..ntop(target).." unreachable")
|
||||
test_assert(false)
|
||||
end
|
||||
dis = {ip6 = ip6, udp = udp, payload = payload}
|
||||
print("send ipv6 udp")
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ip2 = deepcopy(ip6)
|
||||
ip2.ip6_plen = UDP_BASE_LEN + #payload
|
||||
raw_ip = reconstruct_ip6hdr(ip2, {ip6_last_proto = IPPROTO_UDP})
|
||||
raw_udp = reconstruct_udphdr({uh_sport = udp.uh_sport, uh_dport = udp.uh_dport, uh_ulen = UDP_BASE_LEN + #payload})
|
||||
raw_udp = csum_udp_fix(raw_ip,raw_udp,payload)
|
||||
raw = raw_ip .. raw_udp .. payload
|
||||
print("send ipv6 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend_print(raw, {repeats=7}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k)
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
@@ -771,27 +1042,67 @@ function test_rawsend(opts)
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop ext header")
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
|
||||
table.insert(ip6.exthdr, { type = IPPROTO_DSTOPTS, data = "\x00\x00\x00\x00\x00\x00" })
|
||||
table.insert(ip6.exthdr, { type = IPPROTO_DSTOPTS, data = "\x00\x00\x00\x00\x00\x00" })
|
||||
ip6.ip6_flow = 0x60001234;
|
||||
insert_ip6_exthdr(ip6, nil, IPPROTO_DSTOPTS, "\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(ip6, nil, IPPROTO_DSTOPTS, "\x00\x00\x00\x00\x00\x00")
|
||||
ip6.ip6_flow = 0x60001234
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop, destopt ext headers in unfragmentable part and another destopt ext header in fragmentable part")
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x50EA}))
|
||||
end
|
||||
|
||||
fix_ip6_next(ip6) -- required to forge next proto in the second fragment
|
||||
ip6.ip6_flow = 0x6000AE38;
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80, ipfrag_next = IPPROTO_TCP})
|
||||
for k,d in pairs(ddis) do
|
||||
fix_ip_proto(dis) -- ip6_preserve_next requires next fields in ip6.exthdr
|
||||
ip6.ip6_flow = 0x6000AE38
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 72, ipfrag_next = IPPROTO_TCP})
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop, destopt ext headers in unfragmentable part and another destopt ext header in fragmentable part. forge next proto in fragment header of the second fragment to TCP")
|
||||
-- reconstruct dissect using next proto fields in the dissect. do not auto fix next proto chain.
|
||||
-- by default reconstruct fixes next proto chain
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x409A, repeats=2}, {ip6_preserve_next = true}))
|
||||
end
|
||||
|
||||
local icmp = {
|
||||
icmp_type = ICMP_ECHO, icmp_code=0,
|
||||
icmp_data = u32(bu16(math.random(1,0xFFFF))..bu16(1))
|
||||
}
|
||||
ip.ip_p = IPPROTO_ICMP
|
||||
payload=brandom_az09(math.random(10,1100))
|
||||
dis = {ip = ip, icmp = icmp, payload = payload}
|
||||
print("send ipv4 icmp")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0xD133, repeats=3}))
|
||||
|
||||
ip6.exthdr={{ type = IPPROTO_HOPOPTS, data = "\x00\x00\x00\x00\x00\x00" }}
|
||||
ip6.ip6_flow=0x60009E3B
|
||||
icmp.icmp_type = ICMP6_ECHO_REQUEST
|
||||
dis = {ip6 = ip6, icmp = icmp, payload = payload}
|
||||
print("send ipv6 icmp")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}))
|
||||
|
||||
local ip2 = {
|
||||
ip_tos = 0,
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
ip_ttl = 64,
|
||||
ip_p = IPPROTO_UDP,
|
||||
ip_src = pton("10.1.1.1"),
|
||||
ip_dst = pton("10.1.1.2"),
|
||||
}
|
||||
|
||||
dis = {ip = ip2, udp = udp, payload = payload}
|
||||
raw_udp = reconstruct_dissect(dis)
|
||||
|
||||
ip6.ip6_flow=0x6000583F
|
||||
dis = {ip6 = ip6, payload = raw_udp}
|
||||
print("send ipv6 ipip")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}, {ip6_last_proto=IPPROTO_IPIP}))
|
||||
|
||||
dis = {ip = ip, payload = raw_udp}
|
||||
dis.ip.ip_p = IPPROTO_IPIP
|
||||
print("send ipv4 ipip")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}, {ip6_last_proto=IPPROTO_IPIP}))
|
||||
end
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
-- test case : --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
|
||||
-- encrypt standard wireguard messages - initiation, response, cookie - and change udp packet size
|
||||
-- do not encrypt data messages and keepalives
|
||||
-- wgobfs adds maximum of 30+padmax bytes to udp size
|
||||
-- reduce MTU of wireguard interface to avoid ip fragmentation !
|
||||
-- without knowing the secret encrypted packets should be crypto strong white noise with no signature
|
||||
-- arg : secret - shared secret. any string. must be the same on both peers
|
||||
-- arg : padmin - min random garbage bytes. 0 by default
|
||||
-- arg : padmax - max random garbage bytes. 16 by default
|
||||
function wgobfs(ctx, desync)
|
||||
local padmin = desync.arg.padmin and tonumber(desync.arg.padmin) or 0
|
||||
local padmax = desync.arg.padmax and tonumber(desync.arg.padmax) or 16
|
||||
local function genkey()
|
||||
-- cache key in a global var bound to instance name
|
||||
local key_cache_name = desync.func_instance.."_key"
|
||||
key = _G[key_cache_name]
|
||||
if not key then
|
||||
key = hkdf("sha256", "wgobfs_salt", desync.arg.secret, nil, 16)
|
||||
_G[key_cache_name] = key
|
||||
end
|
||||
return key
|
||||
end
|
||||
local function maybe_encrypted_payload(payload)
|
||||
for k,plsize in pairs({2+12+16+148, 2+12+16+92, 2+12+16+64}) do
|
||||
if #payload>=(plsize+padmin) and #payload<=(plsize+padmax) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local function wg_payload_from_size(payload)
|
||||
if #payload==148 then return "wireguard_initiation"
|
||||
elseif #payload==92 then return "wireguard_response"
|
||||
elseif #payload==64 then return "wireguard_cookie"
|
||||
else return nil
|
||||
end
|
||||
end
|
||||
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff(ctx)
|
||||
return
|
||||
end
|
||||
if not desync.arg.secret or #desync.arg.secret==0 then
|
||||
error("wgobfs requires secret")
|
||||
end
|
||||
if padmin>padmax then
|
||||
error("wgobfs: padmin>padmax")
|
||||
end
|
||||
if desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie" and #desync.dis.payload<65506 then
|
||||
DLOG("wgobfs: encrypting '"..desync.l7payload.."'. size "..#desync.dis.payload)
|
||||
local key = genkey()
|
||||
-- in aes-gcm every message require it's own crypto secure random iv
|
||||
-- encrypting more than one message with the same iv is considered catastrophic failure
|
||||
-- iv must be sent with encrypted message
|
||||
local iv = bcryptorandom(12)
|
||||
local encrypted, atag = aes_gcm(true, key, iv, bu16(#desync.dis.payload)..desync.dis.payload..brandom(math.random(padmin,padmax)), nil)
|
||||
desync.dis.payload = iv..atag..encrypted
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
|
||||
if desync.l7payload=="unknown" and maybe_encrypted_payload(desync.dis.payload) then
|
||||
local key = genkey()
|
||||
local iv = string.sub(desync.dis.payload,1,12)
|
||||
local atag = string.sub(desync.dis.payload,13,28)
|
||||
local decrypted, atag2 = aes_gcm(false, key, iv, string.sub(desync.dis.payload,29))
|
||||
if atag==atag2 then
|
||||
local plen = u16(decrypted)
|
||||
if plen>(#decrypted-2) then
|
||||
DLOG("wgobfs: bad decrypted payload data")
|
||||
else
|
||||
desync.dis.payload = string.sub(decrypted, 3, 3+plen-1)
|
||||
if b_debug then DLOG("wgobfs: decrypted '"..(wg_payload_from_size(desync.dis.payload) or "unknown").."' message. size "..plen) end
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
DLOG("wgobfs: decrypt auth tag mismatch")
|
||||
end
|
||||
end
|
||||
end
|
||||
14
mdig/mdig.c
14
mdig/mdig.c
@@ -80,15 +80,15 @@ static bool dom_valid(char *dom)
|
||||
{
|
||||
if (!dom || *dom=='.') return false;
|
||||
for (; *dom; dom++)
|
||||
if (*dom < 0x20 || (*dom & 0x80) || !(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
|
||||
return false;
|
||||
if (!(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void invalid_domain_beautify(char *dom)
|
||||
{
|
||||
for (int i = 0; *dom && i < 64; i++, dom++)
|
||||
if (*dom < 0x20 || *dom<0) *dom = '?';
|
||||
if (*dom < 0x20 || (*dom & 0x80)) *dom = '?';
|
||||
if (*dom) *dom = 0;
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ static void *t_resolver(void *arg)
|
||||
{
|
||||
if ((family == AF_INET && (glob.family & FAMILY4)) || (family == AF_INET6 && (glob.family & FAMILY6)))
|
||||
{
|
||||
unsigned int mask;
|
||||
unsigned int mask=0;
|
||||
bool mask_needed = false;
|
||||
if (s_mask)
|
||||
{
|
||||
@@ -436,7 +436,7 @@ int dns_parse_query()
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
l = fread(a,1,sizeof(a),stdin);
|
||||
if (!l || !feof(stdin))
|
||||
if (!l || ferror(stdin))
|
||||
{
|
||||
fprintf(stderr, "could not read DNS reply blob from stdin\n");
|
||||
return 10;
|
||||
@@ -455,8 +455,8 @@ static void exithelp(void)
|
||||
printf(
|
||||
" --family=<4|6|46>\t\t; ipv4, ipv6, ipv4+ipv6\n"
|
||||
" --threads=<threads_number>\n"
|
||||
" --eagain=<eagain_retries>\t; how many times to retry if EAGAIN received. default %u\n"
|
||||
" --eagain-delay=<ms>\t\t; time in msec to wait between EAGAIN attempts. default %u\n"
|
||||
" --eagain=<eagain_retries>\t; how many times to retry if EAI_AGAIN received. default %u\n"
|
||||
" --eagain-delay=<ms>\t\t; time in msec to wait between EAI_AGAIN attempts. default %u\n"
|
||||
" --verbose\t\t\t; print query progress to stderr\n"
|
||||
" --stats=N\t\t\t; print resolve stats to stderr every N domains\n"
|
||||
" --log-resolved=<file>\t\t; log successfully resolved domains to a file\n"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
|
||||
PKG_CONFIG ?= pkg-config
|
||||
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
|
||||
|
||||
@@ -14,7 +17,7 @@ LUA_PKG:=luajit
|
||||
|
||||
.else
|
||||
|
||||
LUA_VER ?= 5.4
|
||||
LUA_VER ?= 5.5
|
||||
LUA_VER_UNDOTTED!= echo $(LUA_VER) | sed 's/\.//g'
|
||||
|
||||
OSNAME!=uname
|
||||
@@ -26,8 +29,8 @@ OSNAME!=uname
|
||||
|
||||
.endif
|
||||
|
||||
LUA_LIB!= pkg-config --libs $(LUA_PKG)
|
||||
LUA_CFLAGS!= pkg-config --cflags $(LUA_PKG)
|
||||
LUA_LIB!= $(PKG_CONFIG) --libs $(LUA_PKG)
|
||||
LUA_CFLAGS!= $(PKG_CONFIG) --cflags $(LUA_PKG)
|
||||
|
||||
.if "${LUA_JIT}" == "1"
|
||||
LUA_CFLAGS+=-DLUAJIT
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
CC ?= cc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE)
|
||||
CFLAGS_LINUX = -Wno-alloc-size-larger-than
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||
CFLAGS_CYGWIN32 =
|
||||
CFLAGS_UBSAN = -fsanitize=undefined,alignment -fno-sanitize-recover=undefined,alignment
|
||||
LDFLAGS += -flto=auto -Wl,--gc-sections
|
||||
LDFLAGS_ANDROID = -llog
|
||||
LIBS =
|
||||
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
|
||||
LIBS_SYSTEMD = -lsystemd
|
||||
LIBS_BSD = -lz -lm
|
||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
|
||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lole32 -loleaut32 -liphlpapi -lntdll
|
||||
LIBS_CYGWIN32 = -lwindivert32
|
||||
LIBS_CYGWIN64 = -lwindivert64
|
||||
RES_CYGWIN32 = windows/res/32/winmanifest.o windows/res/32/winicon.o
|
||||
RES_CYGWIN64 = windows/res/64/winmanifest.o windows/res/64/winicon.o
|
||||
RES_CYGWIN32 = windows/res/winws_res32.o
|
||||
RES_CYGWIN64 = windows/res/winws_res64.o
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
|
||||
|
||||
LUA_JIT?=1
|
||||
|
||||
@@ -24,18 +30,19 @@ ifeq ($(LUA_JIT),1)
|
||||
LUAJIT_VER?=2.1
|
||||
LUAJIT_LUA_VER?=5.1
|
||||
LUA_PKG:=luajit
|
||||
CFLAGS_CYGWIN32 = -msse2 -mfpmath=sse
|
||||
|
||||
$(info trying luajit $(LUAJIT_VER) lua $(LUAJIT_LUA_VER))
|
||||
|
||||
LUA_LIB_NAME=
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null)
|
||||
LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG) 2>/dev/null)
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := -I/usr/local/include/luajit-$(LUAJIT_VER) -I/usr/include/luajit-$(LUAJIT_VER)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(LUA_LIB),)
|
||||
LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB := $(shell $(PKG_CONFIG) --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB_DIR :=
|
||||
|
||||
ifeq ($(LUA_LIB),)
|
||||
@@ -72,7 +79,7 @@ ifeq ($(LUA_LIB),)
|
||||
|
||||
# no success with luajit
|
||||
|
||||
LUA_VER?=5.4
|
||||
LUA_VER?=5.5
|
||||
LUA_VER_UNDOTTED:=$(shell echo $(LUA_VER) | sed 's/\.//g')
|
||||
|
||||
LUA_CFL :=
|
||||
@@ -87,13 +94,13 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null)
|
||||
LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG) 2>/dev/null)
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := -I/usr/local/include/lua$(LUA_VER) -I/usr/local/include/lua-$(LUA_VER) -I/usr/include/lua$(LUA_VER) -I/usr/include/lua-$(LUA_VER)
|
||||
LUA_CFLAGS := -I/usr/local/include/lua$(LUA_VER) -I/usr/local/include/lua-$(LUA_VER) -I/usr/include/lua$(LUA_VER) -I/usr/include/lua-$(LUA_VER) -I/usr/local/include/lua -I/usr/local/include
|
||||
endif
|
||||
endif
|
||||
ifeq ($(LUA_LIB),)
|
||||
LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB := $(shell $(PKG_CONFIG) --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB_DIR :=
|
||||
ifeq ($(LUA_LIB),)
|
||||
ifneq ($(wildcard /usr/local/lib/liblua-$(LUA_VER).*),)
|
||||
@@ -131,21 +138,24 @@ LUA_CFL += $(LUA_CFLAGS)
|
||||
all: nfqws2
|
||||
|
||||
nfqws2: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
|
||||
ubsan: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS_UBSAN) $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
|
||||
systemd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
|
||||
android: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
|
||||
android: $(SRC_FILES_ANDROID)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES_ANDROID) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
|
||||
|
||||
bsd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_BSD) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_BSD) $(LDFLAGS)
|
||||
|
||||
cygwin64:
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(RES_CYGWIN64) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(LDFLAGS)
|
||||
cygwin32:
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) $(CFLAGS_CYGWIN32) -o winws2 $(SRC_FILES) $(RES_CYGWIN32) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(LDFLAGS)
|
||||
cygwin: cygwin64
|
||||
|
||||
clean:
|
||||
|
||||
216
nfq2/andr/getifaddrs.c
Normal file
216
nfq2/andr/getifaddrs.c
Normal file
@@ -0,0 +1,216 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <syscall.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include "netlink.h"
|
||||
|
||||
#define IFADDRS_HASH_SIZE 64
|
||||
|
||||
/* getifaddrs() reports hardware addresses with PF_PACKET that implies
|
||||
* struct sockaddr_ll. But e.g. Infiniband socket address length is
|
||||
* longer than sockaddr_ll.ssl_addr[8] can hold. Use this hack struct
|
||||
* to extend ssl_addr - callers should be able to still use it. */
|
||||
struct sockaddr_ll_hack {
|
||||
unsigned short sll_family, sll_protocol;
|
||||
int sll_ifindex;
|
||||
unsigned short sll_hatype;
|
||||
unsigned char sll_pkttype, sll_halen;
|
||||
unsigned char sll_addr[24];
|
||||
};
|
||||
|
||||
union sockany {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_ll_hack ll;
|
||||
struct sockaddr_in v4;
|
||||
struct sockaddr_in6 v6;
|
||||
};
|
||||
|
||||
struct ifaddrs_storage {
|
||||
struct ifaddrs ifa;
|
||||
struct ifaddrs_storage *hash_next;
|
||||
union sockany addr, netmask, ifu;
|
||||
unsigned int index;
|
||||
char name[IFNAMSIZ+1];
|
||||
};
|
||||
|
||||
struct ifaddrs_ctx {
|
||||
struct ifaddrs *first;
|
||||
struct ifaddrs *last;
|
||||
struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE];
|
||||
};
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifp)
|
||||
{
|
||||
struct ifaddrs *n;
|
||||
while (ifp) {
|
||||
n = ifp->ifa_next;
|
||||
free(ifp);
|
||||
ifp = n;
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_addr(struct sockaddr **r, int af, union sockany *sa, void *addr, size_t addrlen, int ifindex)
|
||||
{
|
||||
uint8_t *dst;
|
||||
int len;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
dst = (uint8_t*) &sa->v4.sin_addr;
|
||||
len = 4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
dst = (uint8_t*) &sa->v6.sin6_addr;
|
||||
len = 16;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MC_LINKLOCAL(addr))
|
||||
sa->v6.sin6_scope_id = ifindex;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (addrlen < len) return;
|
||||
sa->sa.sa_family = af;
|
||||
memcpy(dst, addr, len);
|
||||
*r = &sa->sa;
|
||||
}
|
||||
|
||||
static void gen_netmask(struct sockaddr **r, int af, union sockany *sa, int prefixlen)
|
||||
{
|
||||
uint8_t addr[16] = {0};
|
||||
int i;
|
||||
|
||||
if (prefixlen > 8*sizeof(addr)) prefixlen = 8*sizeof(addr);
|
||||
i = prefixlen / 8;
|
||||
memset(addr, 0xff, i);
|
||||
if (i < sizeof(addr)) addr[i++] = 0xff << (8 - (prefixlen % 8));
|
||||
copy_addr(r, af, sa, addr, sizeof(addr), 0);
|
||||
}
|
||||
|
||||
static void copy_lladdr(struct sockaddr **r, union sockany *sa, void *addr, size_t addrlen, int ifindex, unsigned short hatype)
|
||||
{
|
||||
if (addrlen > sizeof(sa->ll.sll_addr)) return;
|
||||
sa->ll.sll_family = AF_PACKET;
|
||||
sa->ll.sll_ifindex = ifindex;
|
||||
sa->ll.sll_hatype = hatype;
|
||||
sa->ll.sll_halen = addrlen;
|
||||
memcpy(sa->ll.sll_addr, addr, addrlen);
|
||||
*r = &sa->sa;
|
||||
}
|
||||
|
||||
static int netlink_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
|
||||
{
|
||||
struct ifaddrs_ctx *ctx = pctx;
|
||||
struct ifaddrs_storage *ifs, *ifs0;
|
||||
struct ifinfomsg *ifi = NLMSG_DATA(h);
|
||||
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
||||
struct rtattr *rta;
|
||||
int stats_len = 0;
|
||||
|
||||
if (h->nlmsg_type == RTM_NEWLINK) {
|
||||
for (rta = NLMSG_RTA(h, sizeof(*ifi)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
|
||||
if (rta->rta_type != IFLA_STATS) continue;
|
||||
stats_len = RTA_DATALEN(rta);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (ifs0 = ctx->hash[ifa->ifa_index % IFADDRS_HASH_SIZE]; ifs0; ifs0 = ifs0->hash_next)
|
||||
if (ifs0->index == ifa->ifa_index)
|
||||
break;
|
||||
if (!ifs0) return 0;
|
||||
}
|
||||
|
||||
ifs = calloc(1, sizeof(struct ifaddrs_storage) + stats_len);
|
||||
if (ifs == 0) return -1;
|
||||
|
||||
if (h->nlmsg_type == RTM_NEWLINK) {
|
||||
ifs->index = ifi->ifi_index;
|
||||
ifs->ifa.ifa_flags = ifi->ifi_flags;
|
||||
|
||||
for (rta = NLMSG_RTA(h, sizeof(*ifi)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
|
||||
switch (rta->rta_type) {
|
||||
case IFLA_IFNAME:
|
||||
if (RTA_DATALEN(rta) < sizeof(ifs->name)) {
|
||||
memcpy(ifs->name, RTA_DATA(rta), RTA_DATALEN(rta));
|
||||
ifs->ifa.ifa_name = ifs->name;
|
||||
}
|
||||
break;
|
||||
case IFLA_ADDRESS:
|
||||
copy_lladdr(&ifs->ifa.ifa_addr, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifi->ifi_index, ifi->ifi_type);
|
||||
break;
|
||||
case IFLA_BROADCAST:
|
||||
copy_lladdr(&ifs->ifa.ifa_broadaddr, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifi->ifi_index, ifi->ifi_type);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
ifs->ifa.ifa_data = (void*)(ifs+1);
|
||||
memcpy(ifs->ifa.ifa_data, RTA_DATA(rta), RTA_DATALEN(rta));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ifs->ifa.ifa_name) {
|
||||
unsigned int bucket = ifs->index % IFADDRS_HASH_SIZE;
|
||||
ifs->hash_next = ctx->hash[bucket];
|
||||
ctx->hash[bucket] = ifs;
|
||||
}
|
||||
} else {
|
||||
ifs->ifa.ifa_name = ifs0->ifa.ifa_name;
|
||||
ifs->ifa.ifa_flags = ifs0->ifa.ifa_flags;
|
||||
for (rta = NLMSG_RTA(h, sizeof(*ifa)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
|
||||
switch (rta->rta_type) {
|
||||
case IFA_ADDRESS:
|
||||
/* If ifa_addr is already set we, received an IFA_LOCAL before
|
||||
* so treat this as destination address */
|
||||
if (ifs->ifa.ifa_addr)
|
||||
copy_addr(&ifs->ifa.ifa_dstaddr, ifa->ifa_family, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
else
|
||||
copy_addr(&ifs->ifa.ifa_addr, ifa->ifa_family, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
break;
|
||||
case IFA_BROADCAST:
|
||||
copy_addr(&ifs->ifa.ifa_broadaddr, ifa->ifa_family, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
break;
|
||||
case IFA_LOCAL:
|
||||
/* If ifa_addr is set and we get IFA_LOCAL, assume we have
|
||||
* a point-to-point network. Move address to correct field. */
|
||||
if (ifs->ifa.ifa_addr) {
|
||||
ifs->ifu = ifs->addr;
|
||||
ifs->ifa.ifa_dstaddr = &ifs->ifu.sa;
|
||||
memset(&ifs->addr, 0, sizeof(ifs->addr));
|
||||
}
|
||||
copy_addr(&ifs->ifa.ifa_addr, ifa->ifa_family, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
if (RTA_DATALEN(rta) < sizeof(ifs->name)) {
|
||||
memcpy(ifs->name, RTA_DATA(rta), RTA_DATALEN(rta));
|
||||
ifs->ifa.ifa_name = ifs->name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ifs->ifa.ifa_addr)
|
||||
gen_netmask(&ifs->ifa.ifa_netmask, ifa->ifa_family, &ifs->netmask, ifa->ifa_prefixlen);
|
||||
}
|
||||
|
||||
if (ifs->ifa.ifa_name) {
|
||||
if (!ctx->first) ctx->first = &ifs->ifa;
|
||||
if (ctx->last) ctx->last->ifa_next = &ifs->ifa;
|
||||
ctx->last = &ifs->ifa;
|
||||
} else {
|
||||
free(ifs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
struct ifaddrs_ctx _ctx, *ctx = &_ctx;
|
||||
int r;
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
r = __rtnetlink_enumerate(AF_UNSPEC, AF_UNSPEC, netlink_msg_to_ifaddr, ctx);
|
||||
if (r == 0) *ifap = ctx->first;
|
||||
else freeifaddrs(ctx->first);
|
||||
return r;
|
||||
}
|
||||
8
nfq2/andr/ifaddrs.h
Normal file
8
nfq2/andr/ifaddrs.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#if __ANDROID_API__ < 24
|
||||
void freeifaddrs(struct ifaddrs *);
|
||||
int getifaddrs(struct ifaddrs **);
|
||||
#endif
|
||||
54
nfq2/andr/netlink.c
Normal file
54
nfq2/andr/netlink.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "netlink.h"
|
||||
|
||||
static int __netlink_enumerate(int fd, unsigned int seq, int type, int af,
|
||||
int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx)
|
||||
{
|
||||
struct nlmsghdr *h;
|
||||
union {
|
||||
uint8_t buf[8192];
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct rtgenmsg g;
|
||||
} req;
|
||||
struct nlmsghdr reply;
|
||||
} u;
|
||||
int r, ret;
|
||||
|
||||
memset(&u.req, 0, sizeof(u.req));
|
||||
u.req.nlh.nlmsg_len = sizeof(u.req);
|
||||
u.req.nlh.nlmsg_type = type;
|
||||
u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
||||
u.req.nlh.nlmsg_seq = seq;
|
||||
u.req.g.rtgen_family = af;
|
||||
r = send(fd, &u.req, sizeof(u.req), 0);
|
||||
if (r < 0) return r;
|
||||
|
||||
while (1) {
|
||||
r = recv(fd, u.buf, sizeof(u.buf), 0);
|
||||
if (r <= 0) return -1;
|
||||
for (h = &u.reply; NLMSG_OK(h, (void*)&u.buf[r]); h = NLMSG_NEXT(h)) {
|
||||
if (h->nlmsg_type == NLMSG_DONE) return 0;
|
||||
if (h->nlmsg_type == NLMSG_ERROR) return -1;
|
||||
ret = cb(ctx, h);
|
||||
if (ret) return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __rtnetlink_enumerate(int link_af, int addr_af, int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx)
|
||||
{
|
||||
int fd, r;
|
||||
|
||||
fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||
if (fd < 0) return -1;
|
||||
r = __netlink_enumerate(fd, 1, RTM_GETLINK, link_af, cb, ctx);
|
||||
if (!r) r = __netlink_enumerate(fd, 2, RTM_GETADDR, addr_af, cb, ctx);
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
||||
94
nfq2/andr/netlink.h
Normal file
94
nfq2/andr/netlink.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/* linux/netlink.h */
|
||||
|
||||
#define NETLINK_ROUTE 0
|
||||
|
||||
struct nlmsghdr {
|
||||
uint32_t nlmsg_len;
|
||||
uint16_t nlmsg_type;
|
||||
uint16_t nlmsg_flags;
|
||||
uint32_t nlmsg_seq;
|
||||
uint32_t nlmsg_pid;
|
||||
};
|
||||
|
||||
#define NLM_F_REQUEST 1
|
||||
#define NLM_F_MULTI 2
|
||||
#define NLM_F_ACK 4
|
||||
|
||||
#define NLM_F_ROOT 0x100
|
||||
#define NLM_F_MATCH 0x200
|
||||
#define NLM_F_ATOMIC 0x400
|
||||
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||
|
||||
#define NLMSG_NOOP 0x1
|
||||
#define NLMSG_ERROR 0x2
|
||||
#define NLMSG_DONE 0x3
|
||||
#define NLMSG_OVERRUN 0x4
|
||||
|
||||
/* linux/rtnetlink.h */
|
||||
|
||||
#define RTM_NEWLINK 16
|
||||
#define RTM_GETLINK 18
|
||||
#define RTM_NEWADDR 20
|
||||
#define RTM_GETADDR 22
|
||||
|
||||
struct rtattr {
|
||||
unsigned short rta_len;
|
||||
unsigned short rta_type;
|
||||
};
|
||||
|
||||
struct rtgenmsg {
|
||||
unsigned char rtgen_family;
|
||||
};
|
||||
|
||||
struct ifinfomsg {
|
||||
unsigned char ifi_family;
|
||||
unsigned char __ifi_pad;
|
||||
unsigned short ifi_type;
|
||||
int ifi_index;
|
||||
unsigned ifi_flags;
|
||||
unsigned ifi_change;
|
||||
};
|
||||
|
||||
/* linux/if_link.h */
|
||||
|
||||
#define IFLA_ADDRESS 1
|
||||
#define IFLA_BROADCAST 2
|
||||
#define IFLA_IFNAME 3
|
||||
#define IFLA_STATS 7
|
||||
|
||||
/* linux/if_addr.h */
|
||||
|
||||
struct ifaddrmsg {
|
||||
uint8_t ifa_family;
|
||||
uint8_t ifa_prefixlen;
|
||||
uint8_t ifa_flags;
|
||||
uint8_t ifa_scope;
|
||||
uint32_t ifa_index;
|
||||
};
|
||||
|
||||
#define IFA_ADDRESS 1
|
||||
#define IFA_LOCAL 2
|
||||
#define IFA_LABEL 3
|
||||
#define IFA_BROADCAST 4
|
||||
|
||||
/* musl */
|
||||
|
||||
#define NETLINK_ALIGN(len) (((len)+3) & ~3)
|
||||
#define NLMSG_DATA(nlh) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)))
|
||||
#define NLMSG_DATALEN(nlh) ((nlh)->nlmsg_len-sizeof(struct nlmsghdr))
|
||||
#define NLMSG_DATAEND(nlh) ((char*)(nlh)+(nlh)->nlmsg_len)
|
||||
#define NLMSG_NEXT(nlh) (struct nlmsghdr*)((char*)(nlh)+NETLINK_ALIGN((nlh)->nlmsg_len))
|
||||
#define NLMSG_OK(nlh,end) ((char*)(end)-(char*)(nlh) >= sizeof(struct nlmsghdr))
|
||||
|
||||
#define RTA_DATA(rta) ((void*)((char*)(rta)+sizeof(struct rtattr)))
|
||||
#define RTA_DATALEN(rta) ((rta)->rta_len-sizeof(struct rtattr))
|
||||
#define RTA_DATAEND(rta) ((char*)(rta)+(rta)->rta_len)
|
||||
#define RTA_NEXT(rta) (struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len))
|
||||
#define RTA_OK(rta,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr))
|
||||
|
||||
#define NLMSG_RTA(nlh,len) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)+NETLINK_ALIGN(len)))
|
||||
#define NLMSG_RTAOK(rta,nlh) RTA_OK(rta,NLMSG_DATAEND(nlh))
|
||||
|
||||
int __rtnetlink_enumerate(int link_af, int addr_af, int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx);
|
||||
@@ -95,10 +95,7 @@ static uint16_t do_csum(const uint8_t *buff, size_t len)
|
||||
return u16;
|
||||
}
|
||||
|
||||
uint16_t csum_partial(const void *buff, size_t len)
|
||||
{
|
||||
return do_csum(buff, len);
|
||||
}
|
||||
#define csum_partial(buff, len) do_csum((const uint8_t*)buff,len)
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
@@ -107,7 +104,7 @@ uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t p
|
||||
|
||||
uint16_t ip4_compute_csum(const void *buff, size_t len)
|
||||
{
|
||||
return ~from64to16(do_csum(buff, len));
|
||||
return ~csum_partial(buff, len);
|
||||
}
|
||||
void ip4_fix_checksum(struct ip *ip)
|
||||
{
|
||||
@@ -158,3 +155,21 @@ void udp_fix_checksum(struct udphdr *udp, size_t len, const struct ip *ip, const
|
||||
else if (ip6hdr)
|
||||
udp6_fix_checksum(udp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
|
||||
}
|
||||
|
||||
void icmp4_fix_checksum(struct icmp46 *icmp, size_t len)
|
||||
{
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = ~csum_partial(icmp, len);
|
||||
}
|
||||
void icmp6_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = csum_ipv6_magic(&ip6hdr->ip6_src, &ip6hdr->ip6_dst, len, IPPROTO_ICMPV6, csum_partial(icmp, len));
|
||||
}
|
||||
void icmp_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip6hdr)
|
||||
icmp6_fix_checksum(icmp, len, ip6hdr);
|
||||
else
|
||||
icmp4_fix_checksum(icmp, len);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,20 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
uint16_t csum_partial(const void *buff, size_t len);
|
||||
// icmp 4 and 6 are basically compatible although checksums are calculated differently
|
||||
// do not use version specific structs
|
||||
struct icmp46
|
||||
{
|
||||
uint8_t icmp_type, icmp_code;
|
||||
uint16_t icmp_cksum;
|
||||
union
|
||||
{
|
||||
uint32_t data32;
|
||||
uint16_t data16[2];
|
||||
uint8_t data8[4];
|
||||
} data;
|
||||
};
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum);
|
||||
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum);
|
||||
|
||||
@@ -25,3 +38,7 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
|
||||
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr);
|
||||
void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr);
|
||||
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr);
|
||||
|
||||
void icmp4_fix_checksum(struct icmp46 *icmp, size_t len);
|
||||
void icmp6_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr);
|
||||
void icmp_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "conntrack.h"
|
||||
#include "darkmagic.h"
|
||||
#include <arpa/inet.h>
|
||||
@@ -66,11 +67,11 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
|
||||
p->timeout_fin = timeout_fin;
|
||||
p->timeout_udp = timeout_udp;
|
||||
p->t_purge_interval = purge_interval;
|
||||
time(&p->t_last_purge);
|
||||
p->t_last_purge = boottime();
|
||||
p->pool = NULL;
|
||||
}
|
||||
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
|
||||
bool ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
memset(c, 0, sizeof(*c));
|
||||
if (dis->ip)
|
||||
@@ -86,8 +87,9 @@ void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
|
||||
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
|
||||
}
|
||||
else
|
||||
c->l3proto = -1;
|
||||
return false;
|
||||
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
return c->l4proto!=IPPROTO_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +104,7 @@ static void ConntrackInitTrack(t_ctrack *t)
|
||||
{
|
||||
memset(t, 0, sizeof(*t));
|
||||
t->l7proto = L7_UNKNOWN;
|
||||
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
|
||||
t->pos.client.scale = t->pos.server.scale = 0;
|
||||
rawpacket_queue_init(&t->delayed);
|
||||
lua_newtable(params.L);
|
||||
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
@@ -138,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 = ntohs(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;
|
||||
@@ -152,11 +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 = ntohs(dis->tcp->th_win);
|
||||
direct->winsize_calc = direct->winsize;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
|
||||
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
|
||||
direct->rseq_over_2G = true;
|
||||
@@ -215,7 +221,7 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect
|
||||
ConntrackApplyPos(t, bReverse, dis);
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
|
||||
clock_gettime(CLOCK_BOOT_OR_UPTIME, &t->pos.t_last);
|
||||
// make sure t_start gets exactly the same value as first t_last
|
||||
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
|
||||
}
|
||||
@@ -225,7 +231,7 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct di
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if (!ConntrackExtractConn(&conn, false, dis)) return false;
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
if (bReverse) *bReverse = false;
|
||||
@@ -256,7 +262,7 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *d
|
||||
bool b_rev;
|
||||
uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if (!ConntrackExtractConn(&conn, false, dis)) return false;
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
|
||||
@@ -296,7 +302,7 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *d
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *t;
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if (!ConntrackExtractConn(&conn, false, dis)) return false;
|
||||
if (!(t = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
connswap(&conn, &connswp);
|
||||
@@ -314,14 +320,14 @@ bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis)
|
||||
void ConntrackPoolPurge(t_conntrack *p)
|
||||
{
|
||||
time_t tidle;
|
||||
struct timespec tnow;
|
||||
time_t tnow;
|
||||
t_conntrack_pool *t, *tmp;
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
|
||||
if (!(tnow=boottime())) return;
|
||||
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
|
||||
{
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
|
||||
tidle = tnow - t->track.pos.t_last.tv_sec;
|
||||
if (t->track.b_cutoff ||
|
||||
(t->conn.l4proto == IPPROTO_TCP && (
|
||||
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
|
||||
@@ -333,7 +339,7 @@ void ConntrackPoolPurge(t_conntrack *p)
|
||||
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
|
||||
}
|
||||
}
|
||||
p->t_last_purge = tnow.tv_sec;
|
||||
p->t_last_purge = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,18 +351,18 @@ static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsiz
|
||||
void ConntrackPoolDump(const t_conntrack *p)
|
||||
{
|
||||
t_conntrack_pool *t, *tmp;
|
||||
struct timespec tnow;
|
||||
char sa1[40], sa2[40];
|
||||
time_t tnow;
|
||||
char sa1[INET6_ADDRSTRLEN], sa2[INET6_ADDRSTRLEN];
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
if (!(tnow=boottime())) return;
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
|
||||
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%llu ",
|
||||
proto_name(t->conn.l4proto),
|
||||
sa1, t->conn.sport, sa2, t->conn.dport,
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
|
||||
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow.tv_sec - t->track.pos.t_last.tv_sec),
|
||||
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow - t->track.pos.t_last.tv_sec),
|
||||
(unsigned long long)t->track.pos.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
|
||||
(unsigned long long)t->track.pos.server.pdcounter, (unsigned long long)t->track.pos.server.pcounter, (unsigned long long)t->track.pos.server.pbcounter);
|
||||
if (t->conn.l4proto == IPPROTO_TCP)
|
||||
@@ -371,7 +377,7 @@ void ConntrackPoolDump(const t_conntrack *p)
|
||||
t->track.pos.client.seq_last, t->track.pos.client.pos,
|
||||
t->track.pos.server.seq_last, t->track.pos.server.pos);
|
||||
printf(" req_retrans=%u cutoff=%u lua_in_cutoff=%u lua_out_cutoff=%u hostname=%s l7proto=%s\n",
|
||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname ? t->track.hostname : "", l7proto_str(t->track.l7proto));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -418,7 +424,7 @@ bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t le
|
||||
if ((reasm->size_present - neg_overlap + szcopy) > reasm->size)
|
||||
return false; // buffer overflow
|
||||
// in case of seq overlap new data replaces old - unix behavior
|
||||
memcpy(reasm->packet + reasm->size_present - neg_overlap, payload + szignore, szcopy);
|
||||
memcpy(reasm->packet + reasm->size_present - neg_overlap, (const uint8_t*)payload + szignore, szcopy);
|
||||
if (szcopy>neg_overlap)
|
||||
{
|
||||
reasm->size_present += szcopy - neg_overlap;
|
||||
|
||||
@@ -105,7 +105,7 @@ bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctr
|
||||
// do not create, do not update. only find existing
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
|
||||
bool ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
|
||||
void ConntrackPoolDump(const t_conntrack *p);
|
||||
void ConntrackPoolPurge(t_conntrack *p);
|
||||
void ConntrackClearHostname(t_ctrack *track);
|
||||
|
||||
@@ -391,7 +391,9 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uint64_t orig_add_len = ctx->add_len * 8;
|
||||
size_t i;
|
||||
|
||||
if (tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len);
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
if (tag_len) memcpy(tag, ctx->base_ectr, tag_len);
|
||||
|
||||
if (orig_len || orig_add_len) {
|
||||
memset(work_buf, 0x00, 16);
|
||||
@@ -443,10 +445,12 @@ int gcm_crypt_and_tag(
|
||||
prepare the gcm context with the keying material, we simply
|
||||
invoke each of the three GCM sub-functions in turn...
|
||||
*/
|
||||
gcm_start(ctx, mode, iv, iv_len, add, add_len);
|
||||
gcm_update(ctx, length, input, output);
|
||||
gcm_finish(ctx, tag, tag_len);
|
||||
return(0);
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
int ret;
|
||||
if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret;
|
||||
if ((ret=gcm_update(ctx, length, input, output))) return ret;
|
||||
return gcm_finish(ctx, tag, tag_len);
|
||||
}
|
||||
|
||||
|
||||
@@ -477,23 +481,28 @@ int gcm_auth_decrypt(
|
||||
uchar check_tag[16]; // the tag generated and returned by decryption
|
||||
int diff; // an ORed flag to detect authentication errors
|
||||
size_t i; // our local iterator
|
||||
int ret;
|
||||
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
/*
|
||||
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
|
||||
(which is an identical XORing to reverse the previous one)
|
||||
and also to re-generate the matching authentication tag
|
||||
*/
|
||||
gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len,
|
||||
input, output, length, check_tag, tag_len);
|
||||
if ((ret = gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len))) return ret;
|
||||
|
||||
// now we verify the authentication tag in 'constant time'
|
||||
for (diff = 0, i = 0; i < tag_len; i++)
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
|
||||
if (diff != 0) { // see whether any bits differed?
|
||||
if (diff)
|
||||
{
|
||||
// see whether any bits differed?
|
||||
memset(output, 0, length); // if so... wipe the output data
|
||||
return(GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -60,9 +60,9 @@ int hkdf(SHAversion whichSha,
|
||||
uint8_t okm[], size_t okm_len)
|
||||
{
|
||||
uint8_t prk[USHAMaxHashSize];
|
||||
return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) ||
|
||||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
|
||||
info_len, okm, okm_len);
|
||||
int ret;
|
||||
if ((ret=hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk))) return ret;
|
||||
return hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, info_len, okm, okm_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,9 +103,6 @@ int hkdfExtract(SHAversion whichSha,
|
||||
salt_len = USHAHashSize(whichSha);
|
||||
memset(nullSalt, '\0', salt_len);
|
||||
}
|
||||
else if (salt_len < 0) {
|
||||
return shaBadParam;
|
||||
}
|
||||
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
|
||||
}
|
||||
|
||||
@@ -149,16 +146,13 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
|
||||
size_t hash_len, N;
|
||||
unsigned char T[USHAMaxHashSize];
|
||||
size_t Tlen, where, i;
|
||||
int ret;
|
||||
|
||||
if (info == 0) {
|
||||
info = (const unsigned char *)"";
|
||||
info_len = 0;
|
||||
}
|
||||
else if (info_len < 0) {
|
||||
return shaBadParam;
|
||||
}
|
||||
if (okm_len <= 0) return shaBadParam;
|
||||
if (!okm) return shaBadParam;
|
||||
if (!okm || !okm_len) return shaBadParam;
|
||||
|
||||
hash_len = USHAHashSize(whichSha);
|
||||
if (prk_len < hash_len) return shaBadParam;
|
||||
@@ -171,12 +165,11 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
|
||||
for (i = 1; i <= N; i++) {
|
||||
HMACContext context;
|
||||
unsigned char c = i;
|
||||
int ret = hmacReset(&context, whichSha, prk, prk_len) ||
|
||||
hmacInput(&context, T, Tlen) ||
|
||||
hmacInput(&context, info, info_len) ||
|
||||
hmacInput(&context, &c, 1) ||
|
||||
hmacResult(&context, T);
|
||||
if (ret != shaSuccess) return ret;
|
||||
if ((ret=hmacReset(&context, whichSha, prk, prk_len))) return ret;
|
||||
if ((ret=hmacInput(&context, T, Tlen))) return ret;
|
||||
if ((ret=hmacInput(&context, info, info_len))) return ret;
|
||||
if ((ret=hmacInput(&context, &c, 1))) return ret;
|
||||
if ((ret=hmacResult(&context, T))) return ret;
|
||||
memcpy(okm + where, T,
|
||||
(i != N) ? hash_len : (okm_len - where));
|
||||
where += hash_len;
|
||||
@@ -328,9 +321,8 @@ int hkdfResult(HKDFContext *context,
|
||||
if (!okm) return context->Corrupted = shaBadParam;
|
||||
if (!prk) prk = prkbuf;
|
||||
|
||||
ret = hmacResult(&context->hmacContext, prk) ||
|
||||
hkdfExpand(context->whichSha, prk, context->hashSize, info,
|
||||
info_len, okm, okm_len);
|
||||
if (!(ret = hmacResult(&context->hmacContext, prk)))
|
||||
ret = hkdfExpand(context->whichSha, prk, context->hashSize, info, info_len, okm, okm_len);
|
||||
context->Computed = 1;
|
||||
return context->Corrupted = ret;
|
||||
}
|
||||
|
||||
@@ -49,9 +49,10 @@ int hmac(SHAversion whichSha,
|
||||
uint8_t digest[USHAMaxHashSize])
|
||||
{
|
||||
HMACContext context;
|
||||
return hmacReset(&context, whichSha, key, key_len) ||
|
||||
hmacInput(&context, message_array, length) ||
|
||||
hmacResult(&context, digest);
|
||||
int ret;
|
||||
if ((ret=hmacReset(&context, whichSha, key, key_len))) return ret;
|
||||
if ((ret=hmacInput(&context, message_array, length))) return ret;
|
||||
return hmacResult(&context, digest);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,10 +102,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
*/
|
||||
if (key_len > blocksize) {
|
||||
USHAContext tcontext;
|
||||
int err = USHAReset(&tcontext, whichSha) ||
|
||||
USHAInput(&tcontext, key, key_len) ||
|
||||
USHAResult(&tcontext, tempkey);
|
||||
if (err != shaSuccess) return err;
|
||||
if ((ret=USHAReset(&tcontext, whichSha)) || (ret=USHAInput(&tcontext, key, key_len)) || (ret=USHAResult(&tcontext, tempkey)))
|
||||
return ret;
|
||||
|
||||
key = tempkey;
|
||||
key_len = hashsize;
|
||||
@@ -134,9 +133,9 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
|
||||
/* perform inner hash */
|
||||
/* init context for 1st pass */
|
||||
ret = USHAReset(&context->shaContext, whichSha) ||
|
||||
if (!(ret = USHAReset(&context->shaContext, whichSha)))
|
||||
/* and start with inner pad */
|
||||
USHAInput(&context->shaContext, k_ipad, blocksize);
|
||||
ret = USHAInput(&context->shaContext, k_ipad, blocksize);
|
||||
return context->Corrupted = ret;
|
||||
}
|
||||
|
||||
@@ -197,8 +196,7 @@ int hmacFinalBits(HMACContext *context,
|
||||
if (context->Corrupted) return context->Corrupted;
|
||||
if (context->Computed) return context->Corrupted = shaStateError;
|
||||
/* then final bits of datagram */
|
||||
return context->Corrupted =
|
||||
USHAFinalBits(&context->shaContext, bits, bit_count);
|
||||
return context->Corrupted = USHAFinalBits(&context->shaContext, bits, bit_count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -229,21 +227,16 @@ int hmacResult(HMACContext *context, uint8_t *digest)
|
||||
|
||||
/* finish up 1st pass */
|
||||
/* (Use digest here as a temporary buffer.) */
|
||||
ret =
|
||||
USHAResult(&context->shaContext, digest) ||
|
||||
|
||||
if (!(ret=USHAResult(&context->shaContext, digest)) &&
|
||||
/* perform outer SHA */
|
||||
/* init context for 2nd pass */
|
||||
USHAReset(&context->shaContext, context->whichSha) ||
|
||||
|
||||
!(ret=USHAReset(&context->shaContext, context->whichSha)) &&
|
||||
/* start with outer pad */
|
||||
USHAInput(&context->shaContext, context->k_opad,
|
||||
context->blockSize) ||
|
||||
|
||||
!(ret=USHAInput(&context->shaContext, context->k_opad, context->blockSize)) &&
|
||||
/* then results of 1st hash */
|
||||
USHAInput(&context->shaContext, digest, context->hashSize) ||
|
||||
!(ret=USHAInput(&context->shaContext, digest, context->hashSize)))
|
||||
/* finish up 2nd pass */
|
||||
USHAResult(&context->shaContext, digest);
|
||||
ret=USHAResult(&context->shaContext, digest);
|
||||
|
||||
context->Computed = 1;
|
||||
return context->Corrupted = ret;
|
||||
|
||||
@@ -64,12 +64,12 @@
|
||||
* Add "length" to the length.
|
||||
* Set Corrupted when overflow has occurred.
|
||||
*/
|
||||
static uint32_t addTemp;
|
||||
#define SHA224_256AddLength(context, length) \
|
||||
(addTemp = (context)->Length_Low, (context)->Corrupted = \
|
||||
(((context)->Length_Low += (length)) < addTemp) && \
|
||||
(++(context)->Length_High == 0) ? shaInputTooLong : \
|
||||
(context)->Corrupted )
|
||||
static int SHA224_256AddLength(SHA256Context *context, uint32_t length)
|
||||
{
|
||||
uint32_t addTemp = context->Length_Low;
|
||||
if (((context->Length_Low += length) < addTemp) && (++(context)->Length_High == 0)) context->Corrupted = shaInputTooLong;
|
||||
return context->Corrupted;
|
||||
}
|
||||
|
||||
/* Local Function Prototypes */
|
||||
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
|
||||
|
||||
788
nfq2/darkmagic.c
788
nfq2/darkmagic.c
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,11 @@
|
||||
#ifdef __CYGWIN__
|
||||
#define INITGUID
|
||||
#include "windivert/windivert.h"
|
||||
#include "netinet/icmp6.h"
|
||||
#include "netinet/ip_icmp.h"
|
||||
#else
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#endif
|
||||
|
||||
#ifndef IPPROTO_DIVERT
|
||||
@@ -58,6 +63,34 @@
|
||||
#ifndef IPPROTO_SHIM6
|
||||
#define IPPROTO_SHIM6 140
|
||||
#endif
|
||||
#ifndef IPPROTO_SCTP
|
||||
#define IPPROTO_SCTP 132
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_DEST_UNREACH
|
||||
#define ICMP_DEST_UNREACH 3
|
||||
#endif
|
||||
#ifndef ICMP_TIME_EXCEEDED
|
||||
#define ICMP_TIME_EXCEEDED 11
|
||||
#endif
|
||||
#ifndef ICMP_PARAMETERPROB
|
||||
#define ICMP_PARAMETERPROB 12
|
||||
#endif
|
||||
#ifndef ICMP_TIMESTAMP
|
||||
#define ICMP_TIMESTAMP 13
|
||||
#endif
|
||||
#ifndef ICMP_TIMESTAMPREPLY
|
||||
#define ICMP_TIMESTAMPREPLY 14
|
||||
#endif
|
||||
#ifndef ICMP_INFO_REQUEST
|
||||
#define ICMP_INFO_REQUEST 15
|
||||
#endif
|
||||
#ifndef ICMP_INFO_REPLY
|
||||
#define ICMP_INFO_REPLY 16
|
||||
#endif
|
||||
#ifndef MLD_LISTENER_REDUCTION
|
||||
#define MLD_LISTENER_REDUCTION 132
|
||||
#endif
|
||||
|
||||
// returns netorder value
|
||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
|
||||
@@ -69,8 +102,10 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
||||
#define VERDICT_MODIFY 1
|
||||
#define VERDICT_DROP 2
|
||||
#define VERDICT_MASK 3
|
||||
#define VERDICT_NOCSUM 4
|
||||
#define VERDICT_MASK_VALID 7
|
||||
#define VERDICT_PRESERVE_NEXT 4
|
||||
#define VERDICT_MASK_VALID_LUA (VERDICT_MASK|VERDICT_PRESERVE_NEXT)
|
||||
#define VERDICT_NOCSUM 8
|
||||
#define VERDICT_MASK_VALID 15
|
||||
|
||||
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
|
||||
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
|
||||
@@ -85,6 +120,7 @@ uint16_t tcp_find_mss(const struct tcphdr *tcp);
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr);
|
||||
bool tcp_syn_segment(const struct tcphdr *tcphdr);
|
||||
|
||||
|
||||
bool make_writeable_dir();
|
||||
bool ensure_file_access(const char *filename);
|
||||
#ifdef __CYGWIN__
|
||||
@@ -94,12 +130,12 @@ bool ensure_dir_access(const char *filename);
|
||||
bool prepare_low_appdata();
|
||||
bool win_sandbox(void);
|
||||
bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_list_head *nlm_filter);
|
||||
bool win_dark_deinit(void);
|
||||
void win_dark_deinit(void);
|
||||
bool logical_net_filter_present(void);
|
||||
bool logical_net_filter_match(void);
|
||||
bool nlm_list(bool bAll);
|
||||
bool windivert_init(const char *filter);
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa);
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count);
|
||||
bool windivert_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa);
|
||||
#else
|
||||
#define ensure_dir_access(dir) ensure_file_access(dir)
|
||||
@@ -121,27 +157,37 @@ int socket_divert(sa_family_t family);
|
||||
#endif
|
||||
|
||||
const char *proto_name(uint8_t proto);
|
||||
void str_proto_name(char *s, size_t s_len, uint8_t proto);
|
||||
const char *icmp_type_name(bool v6, uint8_t type);
|
||||
void str_icmp_type_name(char *s, size_t s_len, bool v6, uint8_t type);
|
||||
uint16_t family_from_proto(uint8_t l3proto);
|
||||
void print_ip(const struct ip *ip);
|
||||
void print_ip6hdr(const struct ip6_hdr *ip6hdr, uint8_t proto);
|
||||
void print_tcphdr(const struct tcphdr *tcphdr);
|
||||
void print_udphdr(const struct udphdr *udphdr);
|
||||
void print_icmphdr(const struct icmp46 *icmp, bool v6);
|
||||
void str_ip(char *s, size_t s_len, const struct ip *ip);
|
||||
void str_ip6hdr(char *s, size_t s_len, const struct ip6_hdr *ip6hdr, uint8_t proto);
|
||||
void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *daddr);
|
||||
void str_tcphdr(char *s, size_t s_len, const struct tcphdr *tcphdr);
|
||||
void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr);
|
||||
void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp);
|
||||
|
||||
bool proto_check_ipv4(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len);
|
||||
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off);
|
||||
bool proto_check_ipv6(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, const uint8_t **last_header_type);
|
||||
bool proto_set_last_ip6_proto(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
||||
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off);
|
||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
||||
bool proto_check_tcp(const uint8_t *data, size_t len);
|
||||
void proto_skip_tcp(const uint8_t **data, size_t *len);
|
||||
bool proto_check_udp(const uint8_t *data, size_t len);
|
||||
bool proto_check_udp_payload(const uint8_t *data, size_t len);
|
||||
void proto_skip_udp(const uint8_t **data, size_t *len);
|
||||
bool proto_check_icmp(const uint8_t *data, size_t len);
|
||||
void proto_skip_icmp(const uint8_t **data, size_t *len);
|
||||
|
||||
struct dissect
|
||||
{
|
||||
const uint8_t *data_pkt;
|
||||
@@ -152,19 +198,26 @@ struct dissect
|
||||
uint8_t proto;
|
||||
const struct tcphdr *tcp;
|
||||
const struct udphdr *udp;
|
||||
const struct icmp46 *icmp;
|
||||
size_t len_l4;
|
||||
size_t transport_len;
|
||||
const uint8_t *data_payload;
|
||||
size_t len_payload;
|
||||
bool frag;
|
||||
uint16_t frag_off;
|
||||
};
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check);
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
||||
void reverse_tcp(struct tcphdr *tcp);
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
|
||||
|
||||
bool get_source_ip4(const struct in_addr *target, struct in_addr *source);
|
||||
bool get_source_ip6(const struct in6_addr *target, struct in6_addr *source);
|
||||
|
||||
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, const struct ip *ip, const struct ip6_hdr *ip6hdr);
|
||||
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, const struct ip *ip, const struct ip6_hdr *ip6hdr);
|
||||
void verdict_icmp_csum_fix(uint8_t verdict, struct icmp46 *icmphdr, size_t transport_len, const struct ip6_hdr *ip6hdr);
|
||||
|
||||
void dbgprint_socket_buffers(int fd);
|
||||
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);
|
||||
|
||||
1440
nfq2/desync.c
1440
nfq2/desync.c
File diff suppressed because it is too large
Load Diff
237
nfq2/filter.c
Normal file
237
nfq2/filter.c
Normal file
@@ -0,0 +1,237 @@
|
||||
#include "filter.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
bool pf_match(uint16_t port, const port_filter *pf)
|
||||
{
|
||||
return port && (((!pf->from && !pf->to) || (port>=pf->from && port<=pf->to)) ^ pf->neg);
|
||||
}
|
||||
bool pf_parse(const char *s, port_filter *pf)
|
||||
{
|
||||
unsigned int v1,v2;
|
||||
char c;
|
||||
|
||||
if (!s) return false;
|
||||
if (*s=='*' && s[1]==0)
|
||||
{
|
||||
pf->from=1; pf->to=0xFFFF;
|
||||
pf->neg=false;
|
||||
return true;
|
||||
}
|
||||
if (*s=='~')
|
||||
{
|
||||
pf->neg=true;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
pf->neg=false;
|
||||
if (sscanf(s,"%u-%u%c",&v1,&v2,&c)==2)
|
||||
{
|
||||
if (v1>65535 || v2>65535 || v1>v2) return false;
|
||||
pf->from=(uint16_t)v1;
|
||||
pf->to=(uint16_t)v2;
|
||||
}
|
||||
else if (sscanf(s,"%u%c",&v1,&c)==1)
|
||||
{
|
||||
if (v1>65535) return false;
|
||||
pf->to=pf->from=(uint16_t)v1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
// deny all case
|
||||
if (!pf->from && !pf->to) pf->neg=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fltmode_parse(const char *s, uint8_t *mode)
|
||||
{
|
||||
if (*s=='*' && !s[1])
|
||||
{
|
||||
*mode = FLTMODE_ANY;
|
||||
return true;
|
||||
}
|
||||
else if (*s=='-' && !s[1])
|
||||
{
|
||||
*mode = FLTMODE_SKIP;
|
||||
return true;
|
||||
}
|
||||
*mode = FLTMODE_SKIP;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool icf_match(uint8_t type, uint8_t code, const icmp_filter *icf)
|
||||
{
|
||||
return icf->mode==FLTMODE_ANY || icf->mode==FLTMODE_FILTER && icf->type==type && (!icf->code_valid || icf->code==code);
|
||||
}
|
||||
bool icf_parse(const char *s, icmp_filter *icf)
|
||||
{
|
||||
unsigned int u1,u2;
|
||||
char c1,c2;
|
||||
|
||||
icf->type = icf->code = 0;
|
||||
icf->code_valid = false;
|
||||
if (fltmode_parse(s, &icf->mode)) return true;
|
||||
switch(sscanf(s,"%u%c%u%c",&u1,&c1,&u2,&c2))
|
||||
{
|
||||
case 1:
|
||||
if (u1>0xFF) return false;
|
||||
icf->type = (uint8_t)u1;
|
||||
icf->mode = FLTMODE_FILTER;
|
||||
break;
|
||||
case 3:
|
||||
if (c1!=':' || (u1>0xFF) || (u2>0xFF)) return false;
|
||||
icf->type = (uint8_t)u1;
|
||||
icf->code = (uint8_t)u2;
|
||||
icf->code_valid = true;
|
||||
icf->mode = FLTMODE_FILTER;
|
||||
break;
|
||||
default:
|
||||
icf->mode = FLTMODE_SKIP;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ipp_match(uint8_t proto, const ipp_filter *ipp)
|
||||
{
|
||||
return ipp->mode==FLTMODE_ANY || ipp->mode==FLTMODE_FILTER && ipp->proto==proto;
|
||||
}
|
||||
bool ipp_parse(const char *s, ipp_filter *ipp)
|
||||
{
|
||||
unsigned int u1;
|
||||
char c;
|
||||
|
||||
ipp->proto = 0xFF;
|
||||
if (fltmode_parse(s, &ipp->mode)) return true;
|
||||
if (sscanf(s,"%u%c",&u1,&c)!=1 || u1>0xFF) return false;
|
||||
ipp->proto = (uint8_t)u1;
|
||||
ipp->mode = FLTMODE_FILTER;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool packet_pos_parse(const char *s, struct packet_pos *pos)
|
||||
{
|
||||
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
|
||||
pos->mode=*s;
|
||||
if (pos->mode=='x' || pos->mode=='a')
|
||||
{
|
||||
pos->pos=0;
|
||||
return true;
|
||||
}
|
||||
return sscanf(s+1,"%u",&pos->pos)==1;
|
||||
}
|
||||
bool packet_range_parse(const char *s, struct packet_range *range)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
range->upper_cutoff = false;
|
||||
if (*s=='-' || *s=='<')
|
||||
{
|
||||
range->from = PACKET_POS_ALWAYS;
|
||||
range->upper_cutoff = *s=='<';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!packet_pos_parse(s,&range->from)) return false;
|
||||
if (range->from.mode=='x')
|
||||
{
|
||||
range->to = range->from;
|
||||
return true;
|
||||
}
|
||||
if (!(p = strchr(s,'-')))
|
||||
p = strchr(s,'<');
|
||||
if (p)
|
||||
{
|
||||
s = p;
|
||||
range->upper_cutoff = *s=='<';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (range->from.mode=='a')
|
||||
{
|
||||
range->to = range->from;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
if (*s)
|
||||
{
|
||||
return packet_pos_parse(s,&range->to);
|
||||
}
|
||||
else
|
||||
{
|
||||
range->to = PACKET_POS_ALWAYS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr)
|
||||
{
|
||||
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];
|
||||
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[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[INET_ADDRSTRLEN+4];
|
||||
str_cidr6(s,sizeof(s),cidr);
|
||||
printf("%s",s);
|
||||
}
|
||||
bool parse_cidr4(char *s, struct cidr4 *cidr)
|
||||
{
|
||||
char *p,d;
|
||||
bool b;
|
||||
unsigned int plen;
|
||||
|
||||
if ((p = strchr(s, '/')))
|
||||
{
|
||||
if (sscanf(p + 1, "%u", &plen)!=1 || plen>32)
|
||||
return false;
|
||||
cidr->preflen = (uint8_t)plen;
|
||||
d=*p; *p=0; // backup char
|
||||
}
|
||||
else
|
||||
cidr->preflen = 32;
|
||||
b = (inet_pton(AF_INET, s, &cidr->addr)==1);
|
||||
if (p) *p=d; // restore char
|
||||
return b;
|
||||
}
|
||||
bool parse_cidr6(char *s, struct cidr6 *cidr)
|
||||
{
|
||||
char *p,d;
|
||||
bool b;
|
||||
unsigned int plen;
|
||||
|
||||
if ((p = strchr(s, '/')))
|
||||
{
|
||||
if (sscanf(p + 1, "%u", &plen)!=1 || plen>128)
|
||||
return false;
|
||||
cidr->preflen = (uint8_t)plen;
|
||||
d=*p; *p=0; // backup char
|
||||
}
|
||||
else
|
||||
cidr->preflen = 128;
|
||||
b = (inet_pton(AF_INET6, s, &cidr->addr)==1);
|
||||
if (p) *p=d; // restore char
|
||||
return b;
|
||||
}
|
||||
64
nfq2/filter.h
Normal file
64
nfq2/filter.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t from,to;
|
||||
bool neg;
|
||||
} port_filter;
|
||||
bool pf_match(uint16_t port, const port_filter *pf);
|
||||
bool pf_parse(const char *s, port_filter *pf);
|
||||
|
||||
#define FLTMODE_SKIP 0
|
||||
#define FLTMODE_ANY 1
|
||||
#define FLTMODE_FILTER 2
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mode, type, code;
|
||||
bool code_valid;
|
||||
} icmp_filter;
|
||||
bool icf_match(uint8_t type, uint8_t code, const icmp_filter *icf);
|
||||
bool icf_parse(const char *s, icmp_filter *icf);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mode, proto;
|
||||
} ipp_filter;
|
||||
bool ipp_match(uint8_t proto, const ipp_filter *ipp);
|
||||
bool ipp_parse(const char *s, ipp_filter *ipp);
|
||||
|
||||
struct packet_pos
|
||||
{
|
||||
char mode; // n - packets, d - data packets, s - relative sequence
|
||||
unsigned int pos;
|
||||
};
|
||||
struct packet_range
|
||||
{
|
||||
struct packet_pos from, to;
|
||||
bool upper_cutoff; // true - do not include upper limit, false - include upper limit
|
||||
};
|
||||
#define PACKET_POS_NEVER (struct packet_pos){'x',0}
|
||||
#define PACKET_POS_ALWAYS (struct packet_pos){'a',0}
|
||||
#define PACKET_RANGE_NEVER (struct packet_range){PACKET_POS_NEVER,PACKET_POS_NEVER}
|
||||
#define PACKET_RANGE_ALWAYS (struct packet_range){PACKET_POS_ALWAYS,PACKET_POS_ALWAYS}
|
||||
bool packet_range_parse(const char *s, struct packet_range *range);
|
||||
|
||||
struct cidr4
|
||||
{
|
||||
struct in_addr addr;
|
||||
uint8_t preflen;
|
||||
};
|
||||
struct cidr6
|
||||
{
|
||||
struct in6_addr addr;
|
||||
uint8_t preflen;
|
||||
};
|
||||
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr);
|
||||
void print_cidr4(const struct cidr4 *cidr);
|
||||
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr);
|
||||
void print_cidr6(const struct cidr6 *cidr);
|
||||
bool parse_cidr4(char *s, struct cidr4 *cidr);
|
||||
bool parse_cidr6(char *s, struct cidr6 *cidr);
|
||||
47
nfq2/gzip.c
47
nfq2/gzip.c
@@ -2,6 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "helpers.h"
|
||||
|
||||
#define ZCHUNK 16384
|
||||
#define BUFMIN 128
|
||||
@@ -14,6 +15,7 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
unsigned char in[ZCHUNK];
|
||||
size_t bufsize;
|
||||
void *newbuf;
|
||||
size_t rd;
|
||||
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
@@ -25,15 +27,21 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
|
||||
do
|
||||
{
|
||||
zs.avail_in = fread(in, 1, sizeof(in), F);
|
||||
if (ferror(F))
|
||||
if (!fread_safe(in, 1, sizeof(in), F, &rd))
|
||||
{
|
||||
r = Z_ERRNO;
|
||||
goto zerr;
|
||||
}
|
||||
if (!zs.avail_in) break;
|
||||
if (!rd)
|
||||
{
|
||||
// file is not full
|
||||
r = Z_DATA_ERROR;
|
||||
goto zerr;
|
||||
}
|
||||
zs.avail_in = rd;
|
||||
zs.next_in = in;
|
||||
do
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if ((bufsize - *size) < BUFMIN)
|
||||
{
|
||||
@@ -48,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);
|
||||
|
||||
722
nfq2/helpers.c
722
nfq2/helpers.c
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define UNARY_PLUS(v) (v>0 ? "+" : "")
|
||||
|
||||
@@ -28,12 +29,15 @@ void qsort_ssize_t(ssize_t *array, int ct);
|
||||
int str_index(const char **strs, int count, const char *str);
|
||||
void rtrim(char *s);
|
||||
void replace_char(char *s, char from, char to);
|
||||
char *strncasestr(const char *s,const char *find, size_t slen);
|
||||
const char *strncasestr(const char *s,const char *find, size_t slen);
|
||||
// [a-zA-z][a-zA-Z0-9]*
|
||||
bool is_identifier(const char *p);
|
||||
|
||||
ssize_t read_intr(int fd, void *buf, size_t count);
|
||||
bool fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F, size_t *rd);
|
||||
char* fgets_safe(char *s, int size, FILE *stream);
|
||||
|
||||
bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_size);
|
||||
bool load_file_nonempty(const char *filename, off_t offset, void *buffer, size_t *buffer_size);
|
||||
bool save_file(const char *filename, const void *buffer, size_t buffer_size);
|
||||
bool append_to_list_file(const char *filename, const char *s);
|
||||
|
||||
@@ -45,8 +49,6 @@ void print_sockaddr(const struct sockaddr *sa);
|
||||
void ntopa46(const struct in_addr *ip, const struct in6_addr *ip6,char *str, size_t len);
|
||||
void ntop46(const struct sockaddr *sa, char *str, size_t len);
|
||||
void ntop46_port(const struct sockaddr *sa, char *str, size_t len);
|
||||
bool pton4_port(const char *s, struct sockaddr_in *sa);
|
||||
bool pton6_port(const char *s, struct sockaddr_in6 *sa);
|
||||
|
||||
uint16_t saport(const struct sockaddr *sa);
|
||||
bool sa_has_addr(const struct sockaddr *sa);
|
||||
@@ -66,9 +68,9 @@ void phton48(uint8_t *p, uint64_t v);
|
||||
uint64_t pntoh64(const uint8_t *p);
|
||||
void phton64(uint8_t *p, uint64_t v);
|
||||
|
||||
uint16_t swap16(uint16_t u);
|
||||
uint32_t swap24(uint32_t u);
|
||||
uint64_t swap48(uint64_t u);
|
||||
uint16_t bswap16(uint16_t u);
|
||||
uint32_t bswap24(uint32_t u);
|
||||
uint64_t bswap48(uint64_t u);
|
||||
|
||||
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
|
||||
char hex_digit(uint8_t v);
|
||||
@@ -87,55 +89,39 @@ time_t file_mod_time(const char *filename);
|
||||
bool file_size(const char *filename, off_t *size);
|
||||
bool file_open_test(const char *filename, int flags);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t from,to;
|
||||
bool neg;
|
||||
} port_filter;
|
||||
bool pf_in_range(uint16_t port, const port_filter *pf);
|
||||
bool pf_parse(const char *s, port_filter *pf);
|
||||
bool pf_is_empty(const port_filter *pf);
|
||||
|
||||
struct packet_pos
|
||||
{
|
||||
char mode; // n - packets, d - data packets, s - relative sequence
|
||||
unsigned int pos;
|
||||
};
|
||||
struct packet_range
|
||||
{
|
||||
struct packet_pos from, to;
|
||||
bool upper_cutoff; // true - do not include upper limit, false - include upper limit
|
||||
};
|
||||
#define PACKET_POS_NEVER (struct packet_pos){'x',0}
|
||||
#define PACKET_POS_ALWAYS (struct packet_pos){'a',0}
|
||||
#define PACKET_RANGE_NEVER (struct packet_range){PACKET_POS_NEVER,PACKET_POS_NEVER}
|
||||
#define PACKET_RANGE_ALWAYS (struct packet_range){PACKET_POS_ALWAYS,PACKET_POS_ALWAYS}
|
||||
bool packet_range_parse(const char *s, struct packet_range *range);
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version <= 1200000
|
||||
int getentropy(void *buf, size_t len);
|
||||
#endif
|
||||
|
||||
void fill_random_bytes(uint8_t *p,size_t sz);
|
||||
void fill_random_az(uint8_t *p,size_t sz);
|
||||
void fill_random_az09(uint8_t *p,size_t sz);
|
||||
bool fill_crypto_random_bytes(uint8_t *p,size_t sz);
|
||||
|
||||
void bxor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz);
|
||||
void band(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz);
|
||||
void bor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz);
|
||||
|
||||
void set_console_io_buffering(void);
|
||||
void close_std(void);
|
||||
void close_std_and_exit(int code);
|
||||
bool set_env_exedir(const char *argv0);
|
||||
|
||||
|
||||
struct cidr4
|
||||
{
|
||||
struct in_addr addr;
|
||||
uint8_t preflen;
|
||||
};
|
||||
struct cidr6
|
||||
{
|
||||
struct in6_addr addr;
|
||||
uint8_t preflen;
|
||||
};
|
||||
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr);
|
||||
void print_cidr4(const struct cidr4 *cidr);
|
||||
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr);
|
||||
void print_cidr6(const struct cidr6 *cidr);
|
||||
bool parse_cidr4(char *s, struct cidr4 *cidr);
|
||||
bool parse_cidr6(char *s, struct cidr6 *cidr);
|
||||
bool realpath_any(const char *file, char *pabs);
|
||||
|
||||
bool parse_int16(const char *p, int16_t *v);
|
||||
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_BOOTTIME
|
||||
#elif defined(CLOCK_UPTIME)
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME
|
||||
#else
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
time_t boottime(void);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
uint32_t mask_from_bitcount(uint32_t zct);
|
||||
void mask_from_bitcount6_prepare(void);
|
||||
const struct in6_addr *mask_from_bitcount6(uint32_t zct);
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
|
||||
p = ++(*s);
|
||||
flags |= HOSTLIST_POOL_FLAG_STRICT_MATCH;
|
||||
}
|
||||
for (; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
|
||||
for (; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++) *p=tolower((unsigned char)*p);
|
||||
if (!HostlistPoolAddStrLen(hostlist, *s, p-*s, flags))
|
||||
{
|
||||
HostlistPoolDestroy(hostlist);
|
||||
@@ -42,7 +42,7 @@ bool AppendHostlistItem(hostlist_pool **hostlist, char *s)
|
||||
|
||||
bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
char *p, *e, s[4096], *zbuf;
|
||||
size_t zsize;
|
||||
int ct = 0;
|
||||
FILE *F;
|
||||
@@ -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);
|
||||
|
||||
@@ -79,7 +79,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG_ERR("zlib decompression failed : result %d\n",r);
|
||||
DLOG_ERR("zlib decompression failed : result %d\n", r);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
{
|
||||
DLOG_CONDUP("loading plain text list\n");
|
||||
|
||||
while (fgets(s, sizeof(s), F))
|
||||
while (fgets_safe(s, sizeof(s), F))
|
||||
{
|
||||
p = s;
|
||||
if (!addpool(hostlist,&p,p+strlen(p),&ct))
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -113,10 +119,18 @@ static bool LoadHostList(struct hostlist_file *hfile)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_PERROR("file_mod_signature");
|
||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
goto unchanged;
|
||||
}
|
||||
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
|
||||
// check if it's readable. do not destroy in-memory copy if not
|
||||
if (!file_open_test(hfile->filename, O_RDONLY))
|
||||
{
|
||||
DLOG_PERROR("file_open_test");
|
||||
goto unchanged;
|
||||
}
|
||||
// don't want to keep backup copy in memory - it will require *2 RAM. Problem on low-ram devices. It's better to fail hostlist read than have OOM.
|
||||
// if a file can be opened there're few chances it can't be read. fs corruption, disk error, deleted or made inaccessible between 2 syscals ?
|
||||
// it's all hypotetically possible but very unlikely. but OOM is much more real problem on an embedded device if list is large enough
|
||||
HostlistPoolDestroy(&hfile->hostlist);
|
||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||
{
|
||||
@@ -126,6 +140,9 @@ static bool LoadHostList(struct hostlist_file *hfile)
|
||||
hfile->mod_sig=fsig;
|
||||
}
|
||||
return true;
|
||||
unchanged:
|
||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
static bool LoadHostLists(struct hostlist_files_head *list)
|
||||
{
|
||||
@@ -263,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;
|
||||
}
|
||||
@@ -285,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_(
|
||||
¶ms.hostlists,
|
||||
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
||||
|
||||
62
nfq2/ipset.c
62
nfq2/ipset.c
@@ -4,7 +4,6 @@
|
||||
#include "helpers.h"
|
||||
|
||||
|
||||
// inplace tolower() and add to pool
|
||||
static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
{
|
||||
char *p, cidr[128];
|
||||
@@ -60,7 +59,7 @@ bool AppendIpsetItem(ipset *ips, char *ip)
|
||||
|
||||
static bool AppendIpset(ipset *ips, const char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
char *p, *e, s[4096], *zbuf;
|
||||
size_t zsize;
|
||||
int ct = 0;
|
||||
FILE *F;
|
||||
@@ -78,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);
|
||||
|
||||
@@ -115,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);
|
||||
}
|
||||
|
||||
@@ -131,10 +136,18 @@ static bool LoadIpset(struct ipset_file *hfile)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_PERROR("file_mod_signature");
|
||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
goto unchanged;
|
||||
}
|
||||
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
|
||||
// check if it's readable. do not destroy in-memory copy if not
|
||||
if (!file_open_test(hfile->filename, O_RDONLY))
|
||||
{
|
||||
DLOG_PERROR("file_open_test");
|
||||
goto unchanged;
|
||||
}
|
||||
// don't want to keep backup copy in memory - it will require *2 RAM. Problem on low-ram devices. It's better to fail ipset read than have OOM.
|
||||
// if a file can be opened there're few chances it can't be read. fs corruption, disk error, deleted or made inaccessible between 2 syscals ?
|
||||
// it's all hypotetically possible but very unlikely. but OOM is much more real problem on an embedded device if list is large enough
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
if (!AppendIpset(&hfile->ipset, hfile->filename))
|
||||
{
|
||||
@@ -144,6 +157,9 @@ static bool LoadIpset(struct ipset_file *hfile)
|
||||
hfile->mod_sig=fsig;
|
||||
}
|
||||
return true;
|
||||
unchanged:
|
||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
static bool LoadIpsets(struct ipset_files_head *list)
|
||||
{
|
||||
@@ -166,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)
|
||||
@@ -205,7 +221,11 @@ bool IpsetsReloadCheckForProfile(const struct desync_profile *dp)
|
||||
return IpsetsReloadCheck(&dp->ips_collection) && IpsetsReloadCheck(&dp->ips_collection_exclude);
|
||||
}
|
||||
|
||||
static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ipset_collection_head *ips_exclude, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||
static bool IpsetCheck_(
|
||||
const struct ipset_collection_head *ips, const struct ipset_collection_head *ips_exclude,
|
||||
const struct in_addr *ipv4, const struct in6_addr *ipv6,
|
||||
const struct in_addr *ipv4r, const struct in6_addr *ipv6r
|
||||
)
|
||||
{
|
||||
struct ipset_item *item;
|
||||
|
||||
@@ -217,6 +237,12 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||
return false;
|
||||
if (ipv4r || ipv6r)
|
||||
{
|
||||
DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4r, ipv6r))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// old behavior compat: all include lists are empty means check passes
|
||||
if (!ipset_collection_is_empty(ips))
|
||||
@@ -226,29 +252,41 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||
return true;
|
||||
if (ipv4r || ipv6r)
|
||||
{
|
||||
DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4r, ipv6r))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||
bool IpsetCheck(
|
||||
const struct desync_profile *dp,
|
||||
const struct in_addr *ipv4, const struct in6_addr *ipv6,
|
||||
const struct in_addr *ipv4r, const struct in6_addr *ipv6r)
|
||||
{
|
||||
if (PROFILE_IPSETS_ABSENT(dp)) return true;
|
||||
DLOG("* ipset check for profile %u (%s)\n",dp->n,PROFILE_NAME(dp));
|
||||
return IpsetCheck_(&dp->ips_collection,&dp->ips_collection_exclude,ipv4,ipv6);
|
||||
return IpsetCheck_(&dp->ips_collection,&dp->ips_collection_exclude,ipv4,ipv6,ipv4r,ipv6r);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
#include "pools.h"
|
||||
|
||||
bool LoadAllIpsets();
|
||||
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
|
||||
bool IpsetCheck(
|
||||
const struct desync_profile *dp,
|
||||
const struct in_addr *ipv4, const struct in6_addr *ipv6,
|
||||
const struct in_addr *ipv4r, const struct in6_addr *ipv6r);
|
||||
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||
void IpsetsDebug();
|
||||
bool AppendIpsetItem(ipset *ips, char *ip);
|
||||
|
||||
52
nfq2/kavl.h
52
nfq2/kavl.h
@@ -92,6 +92,19 @@ int main(void) {
|
||||
} \
|
||||
if (cnt_) *cnt_ = cnt; \
|
||||
return (__type*)p; \
|
||||
} \
|
||||
__scope __type *kavl_interval_##suf(const __type *root, const __type *x, __type **lower, __type **upper) { \
|
||||
const __type *p = root, *l = 0, *u = 0; \
|
||||
while (p != 0) { \
|
||||
int cmp; \
|
||||
cmp = __cmp(x, p); \
|
||||
if (cmp < 0) u = p, p = p->__head.p[0]; \
|
||||
else if (cmp > 0) l = p, p = p->__head.p[1]; \
|
||||
else { l = u = p; break; } \
|
||||
} \
|
||||
if (lower) *lower = (__type*)l; \
|
||||
if (upper) *upper = (__type*)u; \
|
||||
return (__type*)p; \
|
||||
}
|
||||
|
||||
#define __KAVL_ROTATE(suf, __type, __head) \
|
||||
@@ -271,43 +284,42 @@ int main(void) {
|
||||
|
||||
#define __KAVL_ITR(suf, __scope, __type, __head, __cmp) \
|
||||
struct kavl_itr_##suf { \
|
||||
const __type *stack[KAVL_MAX_DEPTH], **top, *right; /* _right_ points to the right child of *top */ \
|
||||
const __type *stack[KAVL_MAX_DEPTH], **top; \
|
||||
}; \
|
||||
__scope void kavl_itr_first_##suf(const __type *root, struct kavl_itr_##suf *itr) { \
|
||||
const __type *p; \
|
||||
for (itr->top = itr->stack - 1, p = root; p; p = p->__head.p[0]) \
|
||||
*++itr->top = p; \
|
||||
itr->right = (*itr->top)->__head.p[1]; \
|
||||
} \
|
||||
__scope int kavl_itr_find_##suf(const __type *root, const __type *x, struct kavl_itr_##suf *itr) { \
|
||||
const __type *p = root; \
|
||||
itr->top = itr->stack - 1; \
|
||||
while (p != 0) { \
|
||||
int cmp; \
|
||||
*++itr->top = p; \
|
||||
cmp = __cmp(x, p); \
|
||||
if (cmp < 0) *++itr->top = p, p = p->__head.p[0]; \
|
||||
if (cmp < 0) p = p->__head.p[0]; \
|
||||
else if (cmp > 0) p = p->__head.p[1]; \
|
||||
else break; \
|
||||
} \
|
||||
if (p) { \
|
||||
*++itr->top = p; \
|
||||
itr->right = p->__head.p[1]; \
|
||||
return 1; \
|
||||
} else if (itr->top >= itr->stack) { \
|
||||
itr->right = (*itr->top)->__head.p[1]; \
|
||||
return 0; \
|
||||
} else return 0; \
|
||||
return p? 1 : 0; \
|
||||
} \
|
||||
__scope int kavl_itr_next_##suf(struct kavl_itr_##suf *itr) { \
|
||||
for (;;) { \
|
||||
const __type *p; \
|
||||
for (p = itr->right, --itr->top; p; p = p->__head.p[0]) \
|
||||
__scope int kavl_itr_next_bidir_##suf(struct kavl_itr_##suf *itr, int dir) { \
|
||||
const __type *p; \
|
||||
if (itr->top < itr->stack) return 0; \
|
||||
dir = !!dir; \
|
||||
p = (*itr->top)->__head.p[dir]; \
|
||||
if (p) { /* go down */ \
|
||||
for (; p; p = p->__head.p[!dir]) \
|
||||
*++itr->top = p; \
|
||||
if (itr->top < itr->stack) return 0; \
|
||||
itr->right = (*itr->top)->__head.p[1]; \
|
||||
return 1; \
|
||||
} else { /* go up */ \
|
||||
do { \
|
||||
p = *itr->top--; \
|
||||
} while (itr->top >= itr->stack && p == (*itr->top)->__head.p[dir]); \
|
||||
return itr->top < itr->stack? 0 : 1; \
|
||||
} \
|
||||
}
|
||||
} \
|
||||
|
||||
/**
|
||||
* Insert a node to the tree
|
||||
@@ -332,6 +344,7 @@ int main(void) {
|
||||
* @return node equal to _x_ if present, or NULL if absent
|
||||
*/
|
||||
#define kavl_find(suf, root, x, cnt) kavl_find_##suf(root, x, cnt)
|
||||
#define kavl_interval(suf, root, x, lower, upper) kavl_interval_##suf(root, x, lower, upper)
|
||||
|
||||
/**
|
||||
* Delete a node from the tree
|
||||
@@ -376,7 +389,8 @@ int main(void) {
|
||||
*
|
||||
* @return 1 if there is a next object; 0 otherwise
|
||||
*/
|
||||
#define kavl_itr_next(suf, itr) kavl_itr_next_##suf(itr)
|
||||
#define kavl_itr_next(suf, itr) kavl_itr_next_bidir_##suf(itr, 1)
|
||||
#define kavl_itr_prev(suf, itr) kavl_itr_next_bidir_##suf(itr, 0)
|
||||
|
||||
/**
|
||||
* Return the pointer at the iterator
|
||||
|
||||
1738
nfq2/lua.c
1738
nfq2/lua.c
File diff suppressed because it is too large
Load Diff
25
nfq2/lua.h
25
nfq2/lua.h
@@ -38,12 +38,12 @@
|
||||
#define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L);
|
||||
#define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure");
|
||||
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
|
||||
|
||||
#define LUA_STACK_GUARD_UNWIND(L) lua_settop(L,_lsg);
|
||||
|
||||
void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size);
|
||||
|
||||
|
||||
bool lua_test_init_script_files(void);
|
||||
void lua_req_quit(void);
|
||||
bool lua_init(void);
|
||||
void lua_shutdown(void);
|
||||
void lua_dlog_error(void);
|
||||
@@ -54,6 +54,9 @@ int lua_absindex(lua_State *L, int idx);
|
||||
#define lua_rawlen lua_objlen
|
||||
#endif
|
||||
|
||||
const char *lua_reqlstring(lua_State *L,int idx,size_t *len);
|
||||
const char *lua_reqstring(lua_State *L,int idx);
|
||||
|
||||
// push - create object and push to the stack
|
||||
// pushf - create object and set it as a named field of a table already present on the stack
|
||||
// pushi - create object and set it as a index field of a table already present on the stack
|
||||
@@ -82,13 +85,23 @@ void lua_pushi_table(lua_State *L, lua_Integer idx);
|
||||
void lua_push_blob(lua_State *L, int idx_desync, const char *blob);
|
||||
void lua_pushf_blob(lua_State *L, int idx_desync, const char *field, const char *blob);
|
||||
|
||||
void lua_push_ipaddr(lua_State *L, const struct sockaddr *sa);
|
||||
void lua_pushf_ipaddr(lua_State *L, const char *field, const struct sockaddr *sa);
|
||||
void lua_pushi_ipaddr(lua_State *L, lua_Integer idx, const struct sockaddr *sa);
|
||||
void lua_pushi_str(lua_State *L, lua_Integer idx, const char *str);
|
||||
void lua_pushf_tcphdr_options(lua_State *L, const struct tcphdr *tcp, size_t len);
|
||||
void lua_push_tcphdr(lua_State *L, const struct tcphdr *tcp, size_t len);
|
||||
void lua_pushf_tcphdr(lua_State *L, const struct tcphdr *tcp, size_t len);
|
||||
void lua_push_udphdr(lua_State *L, const struct udphdr *udp, size_t len);
|
||||
void lua_pushf_udphdr(lua_State *L, const struct udphdr *udp, size_t len);
|
||||
void lua_pushf_icmphdr(lua_State *L, const struct icmp46 *icmp, size_t len);
|
||||
void lua_push_iphdr(lua_State *L, const struct ip *ip, size_t len);
|
||||
void lua_pushf_iphdr(lua_State *L, const struct ip *ip, size_t len);
|
||||
void lua_push_ip6hdr(lua_State *L, const struct ip6_hdr *ip6, size_t len);
|
||||
void lua_pushf_ip6hdr(lua_State *L, const struct ip6_hdr *ip6, size_t len);
|
||||
void lua_push_dissect(lua_State *L, const struct dissect *dis);
|
||||
void lua_pushf_dissect(lua_State *L, const struct dissect *dis);
|
||||
void lua_push_ctrack(lua_State *L, const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming);
|
||||
void lua_pushf_ctrack(lua_State *L, const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming);
|
||||
void lua_pushf_args(lua_State *L, const struct str2_list_head *args, int idx_desync, bool subst_prefix);
|
||||
void lua_pushf_pos(lua_State *L, const char *name, const struct packet_pos *pos);
|
||||
@@ -99,17 +112,17 @@ bool lua_reconstruct_ip6hdr(lua_State *L, int idx, struct ip6_hdr *ip6, size_t *
|
||||
bool lua_reconstruct_iphdr(lua_State *L, int idx, struct ip *ip, size_t *len);
|
||||
bool lua_reconstruct_tcphdr(lua_State *L, int idx, struct tcphdr *tcp, size_t *len);
|
||||
bool lua_reconstruct_udphdr(lua_State *L, int idx, struct udphdr *udp);
|
||||
bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
|
||||
bool lua_reconstruct_icmphdr(lua_State *L, int idx, struct icmp46 *icmp);
|
||||
bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, bool keepsum, bool badsum, uint8_t last_proto, bool ip6_preserve_next);
|
||||
|
||||
#define MAGIC_CTX 0xE73DC935
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
unsigned int func_n;
|
||||
const char *func, *instance;
|
||||
const struct desync_profile *dp;
|
||||
const struct dissect *dis;
|
||||
t_ctrack *ctrack;
|
||||
bool incoming,cancel;
|
||||
bool incoming, cancel;
|
||||
bool valid;
|
||||
} t_lua_desync_context;
|
||||
|
||||
bool lua_instance_cutoff_check(lua_State *L, const t_lua_desync_context *ctx, bool bIn);
|
||||
|
||||
984
nfq2/nfqws.c
984
nfq2/nfqws.c
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#define HAS_FILTER_SSID 1
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
extern bool bQuit;
|
||||
#endif
|
||||
extern volatile sig_atomic_t bQuit;
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
// when something changes that can break LUA compatibility this version should be increased
|
||||
#define LUA_COMPAT_VER 4
|
||||
#define LUA_COMPAT_VER 5
|
||||
|
||||
@@ -337,6 +337,8 @@ void dp_init_dynamic(struct desync_profile *dp)
|
||||
LIST_INIT(&dp->ips_collection_exclude);
|
||||
LIST_INIT(&dp->pf_tcp);
|
||||
LIST_INIT(&dp->pf_udp);
|
||||
LIST_INIT(&dp->icf);
|
||||
LIST_INIT(&dp->ipf);
|
||||
LIST_INIT(&dp->lua_desync);
|
||||
#ifdef HAS_FILTER_SSID
|
||||
LIST_INIT(&dp->filter_ssid);
|
||||
@@ -354,12 +356,10 @@ void dp_init(struct desync_profile *dp)
|
||||
dp->hostlist_auto_incoming_maxseq = HOSTLIST_AUTO_INCOMING_MAXSEQ;
|
||||
dp->hostlist_auto_udp_out = HOSTLIST_AUTO_UDP_OUT;
|
||||
dp->hostlist_auto_udp_in = HOSTLIST_AUTO_UDP_IN;
|
||||
dp->filter_ipv4 = dp->filter_ipv6 = true;
|
||||
}
|
||||
static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
{
|
||||
free(dp->name);
|
||||
free(dp->name_tpl);
|
||||
free(dp->cookie);
|
||||
|
||||
hostlist_collection_destroy(&dp->hl_collection);
|
||||
@@ -368,6 +368,8 @@ static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
ipset_collection_destroy(&dp->ips_collection_exclude);
|
||||
port_filters_destroy(&dp->pf_tcp);
|
||||
port_filters_destroy(&dp->pf_udp);
|
||||
icmp_filters_destroy(&dp->icf);
|
||||
ipp_filters_destroy(&dp->ipf);
|
||||
funclist_destroy(&dp->lua_desync);
|
||||
#ifdef HAS_FILTER_SSID
|
||||
strlist_destroy(&dp->filter_ssid);
|
||||
@@ -411,18 +413,48 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
|
||||
return entry;
|
||||
}
|
||||
bool dp_list_copy(struct desync_profile *to, const struct desync_profile *from)
|
||||
#define DP_COPY_SIMPLE(v) if (from->b_##v) {to->v=from->v; to->b_##v=true;}
|
||||
bool dp_copy(struct desync_profile *to, const struct desync_profile *from)
|
||||
{
|
||||
// clear everything in target
|
||||
dp_clear(to);
|
||||
// first copy all simple type values
|
||||
*to = *from;
|
||||
// prepare empty dynamic structures
|
||||
dp_init_dynamic(to);
|
||||
DP_COPY_SIMPLE(hostlist_auto_fail_threshold)
|
||||
DP_COPY_SIMPLE(hostlist_auto_fail_time)
|
||||
DP_COPY_SIMPLE(hostlist_auto_retrans_threshold)
|
||||
DP_COPY_SIMPLE(hostlist_auto_retrans_maxseq)
|
||||
DP_COPY_SIMPLE(hostlist_auto_incoming_maxseq)
|
||||
DP_COPY_SIMPLE(hostlist_auto_retrans_reset)
|
||||
DP_COPY_SIMPLE(hostlist_auto_udp_out)
|
||||
DP_COPY_SIMPLE(hostlist_auto_udp_in)
|
||||
DP_COPY_SIMPLE(filter_l7)
|
||||
if (from->b_filter_l3)
|
||||
{
|
||||
if (to->b_filter_l3)
|
||||
{
|
||||
to->filter_ipv4 |= from->filter_ipv4;
|
||||
to->filter_ipv6 |= from->filter_ipv6;
|
||||
}
|
||||
else
|
||||
{
|
||||
to->filter_ipv4 = from->filter_ipv4;
|
||||
to->filter_ipv6 = from->filter_ipv6;
|
||||
to->b_filter_l3 = true;
|
||||
}
|
||||
}
|
||||
|
||||
// copy dynamic structures
|
||||
if (from->name && !(to->name = strdup(from->name))) return false;
|
||||
if (from->name_tpl && !(to->name_tpl = strdup(from->name_tpl))) return false;
|
||||
if (from->cookie && !(to->cookie = strdup(from->cookie))) return false;
|
||||
if (from->cookie)
|
||||
{
|
||||
free(to->cookie);
|
||||
if (!(to->cookie = strdup(from->cookie))) return false;
|
||||
}
|
||||
if (from->hostlist_auto && from->hostlist_auto!=to->hostlist_auto)
|
||||
{
|
||||
if (to->hostlist_auto)
|
||||
{
|
||||
DLOG_ERR("autohostlist replacement is not supported\n");
|
||||
return false;
|
||||
}
|
||||
to->hostlist_auto = from->hostlist_auto;
|
||||
}
|
||||
if (
|
||||
#ifdef HAS_FILTER_SSID
|
||||
!strlist_copy(&to->filter_ssid, &from->filter_ssid) ||
|
||||
@@ -431,8 +463,13 @@ bool dp_list_copy(struct desync_profile *to, const struct desync_profile *from)
|
||||
!ipset_collection_copy(&to->ips_collection, &from->ips_collection) ||
|
||||
!ipset_collection_copy(&to->ips_collection_exclude, &from->ips_collection_exclude) ||
|
||||
!hostlist_collection_copy(&to->hl_collection, &from->hl_collection) ||
|
||||
!hostlist_collection_copy(&to->hl_collection_exclude, &from->hl_collection_exclude))
|
||||
!hostlist_collection_copy(&to->hl_collection_exclude, &from->hl_collection_exclude) ||
|
||||
!port_filters_copy(&to->pf_tcp, &from->pf_tcp) ||
|
||||
!port_filters_copy(&to->pf_udp, &from->pf_udp) ||
|
||||
!icmp_filters_copy(&to->icf, &from->icf) ||
|
||||
!ipp_filters_copy(&to->ipf, &from->ipf))
|
||||
{
|
||||
DLOG_ERR("dynamic structure copy failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -475,11 +512,35 @@ void cleanup_windivert_portfilters(struct params_s *params)
|
||||
{
|
||||
char **wdbufs[] =
|
||||
{¶ms->wf_pf_tcp_src_in, ¶ms->wf_pf_tcp_dst_in, ¶ms->wf_pf_udp_src_in, ¶ms->wf_pf_udp_dst_in,
|
||||
¶ms->wf_pf_tcp_src_out, ¶ms->wf_pf_tcp_dst_out, ¶ms->wf_pf_udp_src_out, ¶ms->wf_pf_udp_dst_out};
|
||||
¶ms->wf_pf_tcp_src_out, ¶ms->wf_pf_tcp_dst_out, ¶ms->wf_pf_udp_src_out, ¶ms->wf_pf_udp_dst_out,
|
||||
¶ms->wf_icf_in, ¶ms->wf_icf_out,
|
||||
¶ms->wf_ipf_in, ¶ms->wf_ipf_out,
|
||||
¶ms->wf_raw_filter};
|
||||
for (int i=0 ; i<(sizeof(wdbufs)/sizeof(*wdbufs)) ; i++)
|
||||
{
|
||||
free(*wdbufs[i]); *wdbufs[i] = NULL;
|
||||
free(*wdbufs[i]);
|
||||
*wdbufs[i] = NULL;
|
||||
}
|
||||
strlist_destroy(¶ms->wf_raw_part);
|
||||
}
|
||||
bool alloc_windivert_portfilters(struct params_s *params)
|
||||
{
|
||||
char **wdbufs[] =
|
||||
{¶ms->wf_pf_tcp_src_in, ¶ms->wf_pf_tcp_dst_in, ¶ms->wf_pf_udp_src_in, ¶ms->wf_pf_udp_dst_in,
|
||||
¶ms->wf_pf_tcp_src_out, ¶ms->wf_pf_tcp_dst_out, ¶ms->wf_pf_udp_src_out, ¶ms->wf_pf_udp_dst_out,
|
||||
¶ms->wf_icf_in, ¶ms->wf_icf_out,
|
||||
¶ms->wf_ipf_in, ¶ms->wf_ipf_out};
|
||||
for (int i=0 ; i<(sizeof(wdbufs)/sizeof(*wdbufs)) ; i++)
|
||||
{
|
||||
if (!(*wdbufs[i] = malloc(WINDIVERT_PORTFILTER_MAX))) goto err;
|
||||
**wdbufs[i] = 0;
|
||||
}
|
||||
if (!(params->wf_raw_filter = malloc(WINDIVERT_MAX))) goto err;
|
||||
*params->wf_raw_filter = 0;
|
||||
return true;
|
||||
err:
|
||||
cleanup_windivert_portfilters(params);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
void cleanup_params(struct params_s *params)
|
||||
@@ -498,6 +559,7 @@ void cleanup_params(struct params_s *params)
|
||||
ipcacheDestroy(¶ms->ipcache);
|
||||
blob_collection_destroy(¶ms->blobs);
|
||||
strlist_destroy(¶ms->lua_init_scripts);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
strlist_destroy(¶ms->ssid_filter);
|
||||
strlist_destroy(¶ms->nlm_filter);
|
||||
@@ -513,6 +575,7 @@ void init_params(struct params_s *params)
|
||||
{
|
||||
memset(params, 0, sizeof(*params));
|
||||
|
||||
params->intercept = true;
|
||||
#ifdef __linux__
|
||||
params->qnum = -1;
|
||||
#elif defined(BSD)
|
||||
@@ -531,6 +594,8 @@ void init_params(struct params_s *params)
|
||||
LIST_INIT(¶ms->blobs);
|
||||
LIST_INIT(¶ms->lua_init_scripts);
|
||||
|
||||
params->reasm_payload_disable = params->payload_disable = 1ULL<<L7P_NONE;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
LIST_INIT(¶ms->ssid_filter);
|
||||
LIST_INIT(¶ms->nlm_filter);
|
||||
@@ -543,5 +608,4 @@ void init_params(struct params_s *params)
|
||||
params->droproot = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include <wordexp.h>
|
||||
#endif
|
||||
|
||||
#define TLS_PARTIALS_ENABLE true
|
||||
|
||||
#define RAW_SNDBUF (64*1024) // in bytes
|
||||
|
||||
#define Q_MAXLEN 1024 // in packets
|
||||
@@ -45,7 +43,7 @@
|
||||
// this MSS is used for ipv6 in windows and linux
|
||||
#define DEFAULT_MSS 1220
|
||||
|
||||
#define RECONSTRUCT_MAX_SIZE 16384
|
||||
#define RECONSTRUCT_MAX_SIZE 65536
|
||||
|
||||
#define LUA_GC_INTERVAL 60
|
||||
|
||||
@@ -59,12 +57,12 @@ struct desync_profile
|
||||
{
|
||||
unsigned int n; // number of the profile
|
||||
char *name; // optional malloced name string
|
||||
unsigned int n_tpl; // number of imported template
|
||||
char *name_tpl; // imported template name
|
||||
char *cookie; // optional malloced string
|
||||
|
||||
bool filter_ipv4,filter_ipv6;
|
||||
struct port_filters_head pf_tcp,pf_udp;
|
||||
struct icmp_filters_head icf;
|
||||
struct ipp_filters_head ipf;
|
||||
uint64_t filter_l7; // L7_PROTO_* bits
|
||||
|
||||
#ifdef HAS_FILTER_SSID
|
||||
@@ -87,8 +85,16 @@ struct desync_profile
|
||||
bool hostlist_auto_retrans_reset;
|
||||
|
||||
hostfail_pool *hostlist_auto_fail_counters;
|
||||
time_t hostlist_auto_last_purge;
|
||||
|
||||
struct func_list_head lua_desync;
|
||||
|
||||
// was option set ?
|
||||
bool b_hostlist_auto_fail_threshold, b_hostlist_auto_fail_time,b_hostlist_auto_retrans_threshold;
|
||||
bool b_hostlist_auto_retrans_maxseq, b_hostlist_auto_incoming_maxseq, b_hostlist_auto_retrans_reset;
|
||||
bool b_hostlist_auto_udp_out, b_hostlist_auto_udp_in;
|
||||
bool b_filter_l3, b_filter_l7;
|
||||
|
||||
};
|
||||
#define PROFILE_NAME(dp) ((dp)->name ? (dp)->name : "noname")
|
||||
|
||||
@@ -103,7 +109,7 @@ struct desync_profile_list {
|
||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||
void dp_list_move(struct desync_profile_list_head *target, struct desync_profile_list *dpl);
|
||||
bool dp_list_copy(struct desync_profile *to, const struct desync_profile *from);
|
||||
bool dp_copy(struct desync_profile *to, const struct desync_profile *from);
|
||||
struct desync_profile_list *dp_list_search_name(struct desync_profile_list_head *head, const char *name);
|
||||
void dp_entry_destroy(struct desync_profile_list *entry);
|
||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||
@@ -126,7 +132,8 @@ struct params_s
|
||||
char debug_logfile[PATH_MAX];
|
||||
bool debug;
|
||||
|
||||
bool daemon;
|
||||
bool daemon, intercept;
|
||||
unsigned int fuzz;
|
||||
|
||||
#ifdef __linux__
|
||||
int qnum;
|
||||
@@ -145,6 +152,8 @@ struct params_s
|
||||
char *windivert_filter;
|
||||
char *wf_pf_tcp_src_in, *wf_pf_tcp_dst_in, *wf_pf_udp_src_in, *wf_pf_udp_dst_in;
|
||||
char *wf_pf_tcp_src_out, *wf_pf_tcp_dst_out, *wf_pf_udp_src_out, *wf_pf_udp_dst_out;
|
||||
char *wf_icf_in, *wf_icf_out, *wf_ipf_in, *wf_ipf_out;
|
||||
char *wf_raw_filter;
|
||||
#else
|
||||
bool droproot;
|
||||
char *user;
|
||||
@@ -176,12 +185,14 @@ struct params_s
|
||||
unsigned int ipcache_lifetime;
|
||||
ip_cache ipcache;
|
||||
uint64_t reasm_payload_disable;
|
||||
uint64_t payload_disable;
|
||||
|
||||
struct str_list_head lua_init_scripts;
|
||||
bool writeable_dir_enable;
|
||||
char writeable_dir[PATH_MAX];
|
||||
|
||||
int lua_gc;
|
||||
int ref_desync_ctx; // desync ctx userdata registry ref
|
||||
lua_State *L;
|
||||
};
|
||||
|
||||
@@ -193,6 +204,7 @@ void init_params(struct params_s *params);
|
||||
void cleanup_args(struct params_s *params);
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
bool alloc_windivert_portfilters(struct params_s *params);
|
||||
void cleanup_windivert_portfilters(struct params_s *params);
|
||||
#endif
|
||||
void cleanup_params(struct params_s *params);
|
||||
|
||||
227
nfq2/pools.c
227
nfq2/pools.c
@@ -68,7 +68,7 @@ hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s)
|
||||
}
|
||||
bool HostlistPoolCheckStr(hostlist_pool *p, const char *s)
|
||||
{
|
||||
return !!HostlistPoolGetStr(p,s);
|
||||
return HostlistPoolGetStr(p,s);
|
||||
}
|
||||
|
||||
void HostlistPoolDestroy(hostlist_pool **pp)
|
||||
@@ -86,7 +86,7 @@ hostfail_pool * HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time)
|
||||
{
|
||||
size_t slen = strlen(s);
|
||||
ADD_STR_POOL(hostfail_pool, pp, s, slen)
|
||||
elem->expire = time(NULL) + fail_time;
|
||||
elem->expire = boottime() + fail_time;
|
||||
elem->counter = 0;
|
||||
return elem;
|
||||
}
|
||||
@@ -105,28 +105,27 @@ void HostFailPoolDel(hostfail_pool **p, hostfail_pool *elem)
|
||||
void HostFailPoolPurge(hostfail_pool **pp)
|
||||
{
|
||||
hostfail_pool *elem, *tmp;
|
||||
time_t now = time(NULL);
|
||||
time_t now = boottime();
|
||||
HASH_ITER(hh, *pp, elem, tmp)
|
||||
{
|
||||
if (now >= elem->expire)
|
||||
HostFailPoolDel(pp, elem);
|
||||
}
|
||||
}
|
||||
static time_t host_fail_purge_prev=0;
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp)
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp, time_t *purge_prev)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
time_t now = boottime();
|
||||
// do not purge too often to save resources
|
||||
if (host_fail_purge_prev != now)
|
||||
if (*purge_prev != now)
|
||||
{
|
||||
HostFailPoolPurge(pp);
|
||||
host_fail_purge_prev = now;
|
||||
*purge_prev = now;
|
||||
}
|
||||
}
|
||||
void HostFailPoolDump(hostfail_pool *p)
|
||||
{
|
||||
hostfail_pool *elem, *tmp;
|
||||
time_t now = time(NULL);
|
||||
time_t now = boottime();
|
||||
HASH_ITER(hh, p, elem, tmp)
|
||||
printf("host=%s counter=%d time_left=%lld\n",elem->str,elem->counter,(long long int)elem->expire-now);
|
||||
}
|
||||
@@ -525,10 +524,15 @@ struct kavl_bit_elem *kavl_bit_get(const struct kavl_bit_elem *hdr, const void *
|
||||
|
||||
static bool ipset_kavl_add(struct kavl_bit_elem **ipset, const void *a, uint8_t preflen)
|
||||
{
|
||||
uint8_t bytelen = (preflen+7)>>3;
|
||||
uint8_t *abuf = malloc(bytelen);
|
||||
if (!abuf) return false;
|
||||
memcpy(abuf,a,bytelen);
|
||||
uint8_t *abuf, bytelen = (preflen+7)>>3;
|
||||
if (bytelen)
|
||||
{
|
||||
abuf = malloc(bytelen);
|
||||
if (!abuf) return false;
|
||||
memcpy(abuf,a,bytelen);
|
||||
}
|
||||
else
|
||||
abuf = NULL;
|
||||
if (!kavl_bit_add(ipset,abuf,preflen,0))
|
||||
{
|
||||
free(abuf);
|
||||
@@ -540,7 +544,7 @@ static bool ipset_kavl_add(struct kavl_bit_elem **ipset, const void *a, uint8_t
|
||||
|
||||
bool ipset4Check(const struct kavl_bit_elem *ipset, const struct in_addr *a, uint8_t preflen)
|
||||
{
|
||||
return !!kavl_bit_get(ipset,a,preflen);
|
||||
return kavl_bit_get(ipset,a,preflen);
|
||||
}
|
||||
bool ipset4Add(struct kavl_bit_elem **ipset, const struct in_addr *a, uint8_t preflen)
|
||||
{
|
||||
@@ -568,7 +572,7 @@ void ipset4Print(struct kavl_bit_elem *ipset)
|
||||
|
||||
bool ipset6Check(const struct kavl_bit_elem *ipset, const struct in6_addr *a, uint8_t preflen)
|
||||
{
|
||||
return !!kavl_bit_get(ipset,a,preflen);
|
||||
return kavl_bit_get(ipset,a,preflen);
|
||||
}
|
||||
bool ipset6Add(struct kavl_bit_elem **ipset, const struct in6_addr *a, uint8_t preflen)
|
||||
{
|
||||
@@ -724,16 +728,35 @@ bool ipset_collection_is_empty(const struct ipset_collection_head *head)
|
||||
}
|
||||
|
||||
|
||||
bool port_filter_add(struct port_filters_head *head, const port_filter *pf)
|
||||
static struct port_filter_item *port_filter_entry_alloc(const port_filter *pf)
|
||||
{
|
||||
struct port_filter_item *entry = malloc(sizeof(struct port_filter_item));
|
||||
if (entry)
|
||||
{
|
||||
entry->pf = *pf;
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
if (entry) entry->pf = *pf;
|
||||
return entry;
|
||||
}
|
||||
bool port_filter_add(struct port_filters_head *head, const port_filter *pf)
|
||||
{
|
||||
struct port_filter_item *entry = port_filter_entry_alloc(pf);
|
||||
if (entry) LIST_INSERT_HEAD(head, entry, next);
|
||||
return entry;
|
||||
}
|
||||
static struct port_filter_item *port_filter_entry_copy(const struct port_filter_item *pfi)
|
||||
{
|
||||
return port_filter_entry_alloc(&pfi->pf);
|
||||
}
|
||||
bool port_filters_copy(struct port_filters_head *to, const struct port_filters_head *from)
|
||||
{
|
||||
struct port_filter_item *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = port_filter_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void port_filters_destroy(struct port_filters_head *head)
|
||||
{
|
||||
struct port_filter_item *entry;
|
||||
@@ -743,14 +766,14 @@ void port_filters_destroy(struct port_filters_head *head)
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port)
|
||||
bool port_filters_match(const struct port_filters_head *head, uint16_t port)
|
||||
{
|
||||
const struct port_filter_item *item;
|
||||
|
||||
if (LIST_EMPTY(head)) return true;
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (pf_in_range(port, &item->pf))
|
||||
if (pf_match(port, &item->pf))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -763,6 +786,121 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
|
||||
}
|
||||
|
||||
|
||||
static struct icmp_filter_item *icmp_filter_entry_alloc(const icmp_filter *icf)
|
||||
{
|
||||
struct icmp_filter_item *entry = malloc(sizeof(struct icmp_filter_item));
|
||||
if (entry) entry->icf = *icf;
|
||||
return entry;
|
||||
}
|
||||
bool icmp_filter_add(struct icmp_filters_head *head, const icmp_filter *icf)
|
||||
{
|
||||
struct icmp_filter_item *entry = icmp_filter_entry_alloc(icf);
|
||||
if (entry) LIST_INSERT_HEAD(head, entry, next);
|
||||
return entry;
|
||||
}
|
||||
static struct icmp_filter_item *icmp_filter_entry_copy(const struct icmp_filter_item *ifi)
|
||||
{
|
||||
return icmp_filter_entry_alloc(&ifi->icf);
|
||||
}
|
||||
bool icmp_filters_copy(struct icmp_filters_head *to, const struct icmp_filters_head *from)
|
||||
{
|
||||
struct icmp_filter_item *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = icmp_filter_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void icmp_filters_destroy(struct icmp_filters_head *head)
|
||||
{
|
||||
struct icmp_filter_item *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
bool icmp_filters_match(const struct icmp_filters_head *head, uint8_t type, uint8_t code)
|
||||
{
|
||||
const struct icmp_filter_item *item;
|
||||
|
||||
if (LIST_EMPTY(head)) return true;
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (icf_match(type, code, &item->icf))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool icmp_filters_deny_if_empty(struct icmp_filters_head *head)
|
||||
{
|
||||
icmp_filter icf;
|
||||
if (!LIST_EMPTY(head)) return true;
|
||||
return icf_parse("-",&icf) && icmp_filter_add(head,&icf);
|
||||
}
|
||||
|
||||
|
||||
static struct ipp_filter_item *ipp_filter_entry_alloc(const ipp_filter *ipp)
|
||||
{
|
||||
struct ipp_filter_item *entry = malloc(sizeof(struct ipp_filter_item));
|
||||
if (entry) entry->ipp = *ipp;
|
||||
return entry;
|
||||
}
|
||||
bool ipp_filter_add(struct ipp_filters_head *head, const ipp_filter *ipp)
|
||||
{
|
||||
struct ipp_filter_item *entry = ipp_filter_entry_alloc(ipp);
|
||||
if (entry) LIST_INSERT_HEAD(head, entry, next);
|
||||
return entry;
|
||||
}
|
||||
static struct ipp_filter_item *ipp_filter_entry_copy(const struct ipp_filter_item *ifi)
|
||||
{
|
||||
return ipp_filter_entry_alloc(&ifi->ipp);
|
||||
}
|
||||
bool ipp_filters_copy(struct ipp_filters_head *to, const struct ipp_filters_head *from)
|
||||
{
|
||||
struct ipp_filter_item *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = ipp_filter_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void ipp_filters_destroy(struct ipp_filters_head *head)
|
||||
{
|
||||
struct ipp_filter_item *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
bool ipp_filters_match(const struct ipp_filters_head *head, uint8_t proto)
|
||||
{
|
||||
const struct ipp_filter_item *item;
|
||||
|
||||
if (LIST_EMPTY(head)) return true;
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (ipp_match(proto, &item->ipp))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ipp_filters_deny_if_empty(struct ipp_filters_head *head)
|
||||
{
|
||||
ipp_filter ipp;
|
||||
if (!LIST_EMPTY(head)) return true;
|
||||
return ipp_parse("-",&ipp) && ipp_filter_add(head,&ipp);
|
||||
}
|
||||
|
||||
|
||||
struct blob_item *blob_collection_add(struct blob_collection_head *head)
|
||||
{
|
||||
@@ -779,12 +917,15 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
|
||||
{
|
||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
||||
if (!entry) return NULL;
|
||||
if (!(entry->data = malloc(size+size_reserve)))
|
||||
if (size+size_reserve)
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
if (!(entry->data = malloc(size+size_reserve)))
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
if (data) memcpy(entry->data,data,size);
|
||||
}
|
||||
if (data) memcpy(entry->data,data,size);
|
||||
entry->size = size;
|
||||
entry->size_buf = size+size_reserve;
|
||||
|
||||
@@ -833,7 +974,7 @@ struct blob_item *blob_collection_search_name(struct blob_collection_head *head,
|
||||
|
||||
static void ipcache_item_touch(ip_cache_item *item)
|
||||
{
|
||||
time(&item->last);
|
||||
item->last = boottime();
|
||||
}
|
||||
static void ipcache_item_init(ip_cache_item *item)
|
||||
{
|
||||
@@ -892,11 +1033,11 @@ 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;
|
||||
|
||||
time(&now);
|
||||
now = boottime();
|
||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
||||
{
|
||||
*s_ip=0;
|
||||
@@ -950,11 +1091,11 @@ 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;
|
||||
|
||||
time(&now);
|
||||
now = boottime();
|
||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
||||
{
|
||||
*s_ip=0;
|
||||
@@ -974,6 +1115,22 @@ void ipcachePrint(ip_cache *ipcache)
|
||||
ipcache6Print(ipcache->ipcache6);
|
||||
}
|
||||
|
||||
ip_cache_item *ipcacheFind(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
|
||||
{
|
||||
ip_cache4 *ipcache4;
|
||||
ip_cache6 *ipcache6;
|
||||
if (a4)
|
||||
{
|
||||
if ((ipcache4 = ipcache4Find(ipcache->ipcache4,a4,iface)))
|
||||
return &ipcache4->data;
|
||||
}
|
||||
else if (a6)
|
||||
{
|
||||
if ((ipcache6 = ipcache6Find(ipcache->ipcache6,a6,iface)))
|
||||
return &ipcache6->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
|
||||
{
|
||||
ip_cache4 *ipcache4;
|
||||
@@ -1000,7 +1157,7 @@ ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const s
|
||||
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
|
||||
{
|
||||
ip_cache4 *elem, *tmp;
|
||||
time_t now = time(NULL);
|
||||
time_t now = boottime();
|
||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
||||
{
|
||||
if (now >= (elem->data.last + lifetime))
|
||||
@@ -1014,7 +1171,7 @@ static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
|
||||
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
|
||||
{
|
||||
ip_cache6 *elem, *tmp;
|
||||
time_t now = time(NULL);
|
||||
time_t now = boottime();
|
||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
||||
{
|
||||
if (now >= (elem->data.last + lifetime))
|
||||
@@ -1036,7 +1193,7 @@ static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
|
||||
static time_t ipcache_purge_prev=0;
|
||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
time_t now = boottime();
|
||||
// do not purge too often to save resources
|
||||
if (ipcache_purge_prev != now)
|
||||
{
|
||||
|
||||
35
nfq2/pools.h
35
nfq2/pools.h
@@ -4,9 +4,9 @@
|
||||
#include <ctype.h>
|
||||
#include <sys/queue.h>
|
||||
#include <net/if.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "helpers.h"
|
||||
#include "filter.h"
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
@@ -75,9 +75,9 @@ void funclist_destroy(struct func_list_head *head);
|
||||
|
||||
|
||||
typedef struct hostfail_pool {
|
||||
char *str; /* key */
|
||||
int counter; /* value */
|
||||
time_t expire; /* when to expire record (unixtime) */
|
||||
char *str;
|
||||
int counter;
|
||||
time_t expire; // when to expire record (unixtime)
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
} hostfail_pool;
|
||||
|
||||
@@ -86,7 +86,7 @@ hostfail_pool *HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time);
|
||||
hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s);
|
||||
void HostFailPoolDel(hostfail_pool **pp, hostfail_pool *elem);
|
||||
void HostFailPoolPurge(hostfail_pool **pp);
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp);
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp, time_t *purge_prev);
|
||||
void HostFailPoolDump(hostfail_pool *p);
|
||||
|
||||
|
||||
@@ -185,10 +185,32 @@ struct port_filter_item {
|
||||
};
|
||||
LIST_HEAD(port_filters_head, port_filter_item);
|
||||
bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
|
||||
bool port_filters_copy(struct port_filters_head *to, const struct port_filters_head *from);
|
||||
void port_filters_destroy(struct port_filters_head *head);
|
||||
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
|
||||
bool port_filters_match(const struct port_filters_head *head, uint16_t port);
|
||||
bool port_filters_deny_if_empty(struct port_filters_head *head);
|
||||
|
||||
struct icmp_filter_item {
|
||||
icmp_filter icf;
|
||||
LIST_ENTRY(icmp_filter_item) next;
|
||||
};
|
||||
LIST_HEAD(icmp_filters_head, icmp_filter_item);
|
||||
bool icmp_filter_add(struct icmp_filters_head *head, const icmp_filter *icf);
|
||||
bool icmp_filters_copy(struct icmp_filters_head *to, const struct icmp_filters_head *from);
|
||||
void icmp_filters_destroy(struct icmp_filters_head *head);
|
||||
bool icmp_filters_match(const struct icmp_filters_head *head, uint8_t type, uint8_t code);
|
||||
bool icmp_filters_deny_if_empty(struct icmp_filters_head *head);
|
||||
|
||||
struct ipp_filter_item {
|
||||
ipp_filter ipp;
|
||||
LIST_ENTRY(ipp_filter_item) next;
|
||||
};
|
||||
LIST_HEAD(ipp_filters_head, ipp_filter_item);
|
||||
bool ipp_filter_add(struct ipp_filters_head *head, const ipp_filter *ipp);
|
||||
bool ipp_filters_copy(struct ipp_filters_head *to, const struct ipp_filters_head *from);
|
||||
void ipp_filters_destroy(struct ipp_filters_head *head);
|
||||
bool ipp_filters_match(const struct ipp_filters_head *head, uint8_t proto);
|
||||
bool ipp_filters_deny_if_empty(struct ipp_filters_head *head);
|
||||
|
||||
struct blob_item {
|
||||
uint8_t *data; // main data blob
|
||||
@@ -243,6 +265,7 @@ typedef struct ip_cache
|
||||
} ip_cache;
|
||||
|
||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
|
||||
ip_cache_item *ipcacheFind(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
|
||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
|
||||
void ipcacheDestroy(ip_cache *ipcache);
|
||||
void ipcachePrint(ip_cache *ipcache);
|
||||
|
||||
167
nfq2/protocol.c
167
nfq2/protocol.c
@@ -17,12 +17,15 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
|
||||
{
|
||||
int i;
|
||||
const uint8_t *p1,*p2;
|
||||
|
||||
if (level<1) return false;
|
||||
for (i=1,p2=dom+dlen;i<level;i++)
|
||||
{
|
||||
for (p2--; p2>dom && *p2!='.'; p2--);
|
||||
if (p2<=dom) return false;
|
||||
}
|
||||
for (p1=p2-1 ; p1>dom && *p1!='.'; p1--);
|
||||
if (p1<dom) return false;
|
||||
if (*p1=='.') p1++;
|
||||
if (p) *p = p1;
|
||||
if (len) *len = p2-p1;
|
||||
@@ -30,7 +33,7 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
|
||||
}
|
||||
|
||||
static const char *l7proto_name[] = {
|
||||
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"
|
||||
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto","bt","utp_bt"
|
||||
};
|
||||
const char *l7proto_str(t_l7proto l7)
|
||||
{
|
||||
@@ -44,11 +47,12 @@ t_l7proto l7proto_from_name(const char *name)
|
||||
}
|
||||
bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
|
||||
{
|
||||
return filter_l7==L7_ALL || (filter_l7 & (1<<l7proto)) || (filter_l7 & (1<<L7_KNOWN)) && l7proto>L7_KNOWN && l7proto<L7_LAST;
|
||||
return filter_l7==L7_ALL || (filter_l7 & (1ULL<<l7proto)) || (filter_l7 & (1ULL<<L7_KNOWN)) && l7proto>L7_KNOWN && l7proto<L7_LAST;
|
||||
}
|
||||
|
||||
static const char *l7payload_name[] = {
|
||||
"all","unknown","empty","known",
|
||||
"ipv4","ipv6","icmp",
|
||||
"http_req","http_reply",
|
||||
"tls_client_hello","tls_server_hello",
|
||||
"dtls_client_hello","dtls_server_hello",
|
||||
@@ -57,7 +61,9 @@ static const char *l7payload_name[] = {
|
||||
"dht","discord_ip_discovery","stun",
|
||||
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
|
||||
"dns_query", "dns_response",
|
||||
"mtproto_initial"};
|
||||
"mtproto_initial",
|
||||
"bt_handshake", "utp_bt_handshake"
|
||||
};
|
||||
t_l7payload l7payload_from_name(const char *name)
|
||||
{
|
||||
int idx = str_index(l7payload_name,sizeof(l7payload_name)/sizeof(*l7payload_name),name);
|
||||
@@ -70,11 +76,11 @@ const char *l7payload_str(t_l7payload l7)
|
||||
}
|
||||
bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p)
|
||||
{
|
||||
return filter_l7p==L7P_ALL || (filter_l7p & (1<<l7payload)) || (filter_l7p & (1<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
|
||||
return filter_l7p==L7P_ALL || (filter_l7p & (1ULL<<l7payload)) || (filter_l7p & (1ULL<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
|
||||
}
|
||||
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
{
|
||||
char *p;
|
||||
char *p, *e;
|
||||
const char *pstr;
|
||||
size_t lstr;
|
||||
t_l7payload pl;
|
||||
@@ -86,17 +92,17 @@ bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
memcpy(buf,"all",4);
|
||||
return true;
|
||||
}
|
||||
for(pl=0, p=buf, *buf=0 ; pl<L7P_LAST ; pl++)
|
||||
for(pl=0, p=buf, e=p+size, *buf=0 ; pl<L7P_LAST ; pl++)
|
||||
{
|
||||
if (l7p & (1<<pl))
|
||||
if (l7p & (1ULL<<pl))
|
||||
{
|
||||
pstr = l7payload_str(pl);
|
||||
lstr = strlen(pstr);
|
||||
if (size < ((p!=buf) + lstr + 1)) return false;
|
||||
if ((p + (p!=buf) + lstr + 1) > e) return false;
|
||||
if (p!=buf) *p++=','; // not first
|
||||
memcpy(p,pstr,lstr);
|
||||
p[lstr]=0;
|
||||
p+=lstr;
|
||||
p += lstr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -139,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)
|
||||
{
|
||||
@@ -243,24 +248,38 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7payload l7payload, cons
|
||||
}
|
||||
|
||||
|
||||
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS ","PUT /","DELETE /","CONNECT ","TRACE /",NULL };
|
||||
const char *HttpMethod(const uint8_t *data, size_t len)
|
||||
static const char *http_methods[] = { "GET ","POST ","HEAD ","OPTIONS ","PUT ","DELETE ","CONNECT ","TRACE ",NULL };
|
||||
static const char *HttpMethod(const uint8_t *data, size_t len)
|
||||
{
|
||||
const char **method;
|
||||
size_t method_len;
|
||||
for (method = http_methods; *method; method++)
|
||||
|
||||
if (len>=4)
|
||||
{
|
||||
method_len = strlen(*method);
|
||||
if (method_len <= len && !memcmp(data, *method, method_len))
|
||||
return *method;
|
||||
for (method = http_methods; *method; method++)
|
||||
{
|
||||
method_len = strlen(*method);
|
||||
if (method_len <= len && !memcmp(data, *method, method_len))
|
||||
return *method;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
bool IsHttp(const uint8_t *data, size_t len)
|
||||
{
|
||||
return !!HttpMethod(data,len);
|
||||
if (!HttpMethod(data,len)) return false;
|
||||
// GET /uri HTTP/1.1
|
||||
// skip method
|
||||
for(; len && *data!=' ' && *data!='\t' && *data!='\r' && *data!='\n'; data++, len--);
|
||||
if (!len || *data!=' ' && *data!='\t') return false;
|
||||
for(; len && (*data==' '|| *data=='\t'); data++, len--);
|
||||
// skip URI
|
||||
for(; len && *data!=' ' && *data!='\t' && *data!='\r' && *data!='\n'; data++, len--);
|
||||
if (!len || *data!=' ' && *data!='\t') return false;
|
||||
for(; len && (*data==' '|| *data=='\t'); data++, len--);
|
||||
if (len<10 || *data=='\r' || *data=='\n') return false;
|
||||
return !memcmp(data,"HTTP/1.",7);
|
||||
}
|
||||
|
||||
static bool IsHostAt(const uint8_t *p)
|
||||
{
|
||||
return \
|
||||
@@ -301,7 +320,7 @@ bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
|
||||
*pHost = FindHostIn(buf, bs);
|
||||
if (*pHost) (*pHost)++;
|
||||
}
|
||||
return !!*pHost;
|
||||
return *pHost;
|
||||
}
|
||||
|
||||
bool IsHttpReply(const uint8_t *data, size_t len)
|
||||
@@ -349,7 +368,7 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
|
||||
char loc[256],*redirect_host, *p;
|
||||
int code;
|
||||
|
||||
if (!host || !*host) return false;
|
||||
if (!host || !*host || !IsHttpReply(data, len)) return false;
|
||||
|
||||
code = HttpReplyCode(data,len);
|
||||
|
||||
@@ -394,10 +413,11 @@ ssize_t HttpPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
|
||||
case PM_HTTP_METHOD:
|
||||
// recognize some tpws pre-applied hacks
|
||||
method=data;
|
||||
if (sz<10) break;
|
||||
if (sz<12) break;
|
||||
if (*method=='\n' || *method=='\r') method++;
|
||||
if (*method=='\n' || *method=='\r') method++;
|
||||
for (p=method,i=0;i<7;i++) if (*p>='A' && *p<='Z') p++;
|
||||
// max length is PROPPATCH
|
||||
for (p=method,i=0; i<9 && *p>='A' && *p<='Z'; i++,p++);
|
||||
if (i<3 || *p!=' ') break;
|
||||
return CheckPos(sz,method-data+pos);
|
||||
case PM_HOST:
|
||||
@@ -428,6 +448,7 @@ const char *TLSVersionStr(uint16_t tlsver)
|
||||
{
|
||||
switch(tlsver)
|
||||
{
|
||||
case 0x0300: return "SSL 3.0";
|
||||
case 0x0301: return "TLS 1.0";
|
||||
case 0x0302: return "TLS 1.1";
|
||||
case 0x0303: return "TLS 1.2";
|
||||
@@ -529,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;
|
||||
@@ -675,7 +700,7 @@ ssize_t TLSPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
|
||||
case PM_HOST_MIDSLD:
|
||||
case PM_HOST_ENDSLD:
|
||||
case PM_SNI_EXT:
|
||||
if (TLSFindExt(data,sz,0,&ext,&elen,TLS_PARTIALS_ENABLE))
|
||||
if (TLSFindExt(data,sz,0,&ext,&elen,true))
|
||||
{
|
||||
if (posmarker==PM_SNI_EXT)
|
||||
{
|
||||
@@ -961,7 +986,7 @@ static uint8_t tvb_get_varint(const uint8_t *tvb, uint64_t *value)
|
||||
return 8;
|
||||
}
|
||||
// impossible case
|
||||
if (*value) *value = 0;
|
||||
if (value) *value = 0;
|
||||
return 0;
|
||||
}
|
||||
static uint8_t tvb_get_size(uint8_t tvb)
|
||||
@@ -985,28 +1010,26 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_quic_v2(uint32_t version)
|
||||
{
|
||||
return (version == 0x709A50C4) || (version == 0x6b3343cf);
|
||||
}
|
||||
/* Returns the QUIC draft version or 0 if not applicable. */
|
||||
uint8_t QUICDraftVersion(uint32_t version)
|
||||
{
|
||||
/* IETF Draft versions */
|
||||
if ((version >> 8) == 0xff0000) {
|
||||
if ((version >> 8) == 0xff0000)
|
||||
return (uint8_t)version;
|
||||
}
|
||||
/* Facebook mvfst, based on draft -22. */
|
||||
if (version == 0xfaceb001) {
|
||||
if (version == 0xfaceb001)
|
||||
return 22;
|
||||
}
|
||||
/* Facebook mvfst, based on draft -27. */
|
||||
if (version == 0xfaceb002 || version == 0xfaceb00e) {
|
||||
if (version == 0xfaceb002 || version == 0xfaceb00e)
|
||||
return 27;
|
||||
}
|
||||
/* GQUIC Q050, T050 and T051: they are not really based on any drafts,
|
||||
* but we must return a sensible value */
|
||||
if (version == 0x51303530 ||
|
||||
version == 0x54303530 ||
|
||||
version == 0x54303531) {
|
||||
if (version == 0x51303530 || version == 0x54303530 || version == 0x54303531)
|
||||
return 27;
|
||||
}
|
||||
/* https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-15
|
||||
"Versions that follow the pattern 0x?a?a?a?a are reserved for use in
|
||||
forcing version negotiation to be exercised"
|
||||
@@ -1014,19 +1037,17 @@ uint8_t QUICDraftVersion(uint32_t version)
|
||||
used to select a proper salt (which depends on the version itself), but
|
||||
we don't have a real version here! Let's hope that we need to handle
|
||||
only latest drafts... */
|
||||
if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
|
||||
if ((version & 0x0F0F0F0F) == 0x0a0a0a0a)
|
||||
return 29;
|
||||
}
|
||||
/* QUIC (final?) constants for v1 are defined in draft-33, but draft-34 is the
|
||||
final draft version */
|
||||
if (version == 0x00000001) {
|
||||
if (version == 0x00000001)
|
||||
return 34;
|
||||
}
|
||||
/* QUIC Version 2 */
|
||||
/* TODO: for the time being use 100 as a number for V2 and let see how v2 drafts evolve */
|
||||
if (version == 0x709A50C4) {
|
||||
if (is_quic_v2(version))
|
||||
return 100;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1034,10 +1055,6 @@ static bool is_quic_draft_max(uint32_t draft_version, uint8_t max_version)
|
||||
{
|
||||
return draft_version && draft_version <= max_version;
|
||||
}
|
||||
static bool is_quic_v2(uint32_t version)
|
||||
{
|
||||
return version == 0x6b3343cf;
|
||||
}
|
||||
|
||||
static bool quic_hkdf_expand_label(const uint8_t *secret, uint8_t secret_len, const char *label, uint8_t *out, size_t out_len)
|
||||
{
|
||||
@@ -1143,12 +1160,12 @@ static bool quic_derive_initial_secret(const quic_cid_t *cid, uint8_t *client_in
|
||||
}
|
||||
bool QUICIsLongHeader(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=9 && !!(*data & 0x80);
|
||||
return len>=9 && (*data & 0x80);
|
||||
}
|
||||
uint32_t QUICExtractVersion(const uint8_t *data, size_t len)
|
||||
{
|
||||
// long header, fixed bit, type=initial
|
||||
return QUICIsLongHeader(data, len) ? ntohl(*(uint32_t*)(data + 1)) : 0;
|
||||
return QUICIsLongHeader(data, len) ? pntoh32(data + 1) : 0;
|
||||
}
|
||||
bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid)
|
||||
{
|
||||
@@ -1177,15 +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 + 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;
|
||||
|
||||
@@ -1206,13 +1224,13 @@ 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[256];
|
||||
size_t header_len = pn_offset + pkn_len;
|
||||
uint8_t atag[16],header[2048];
|
||||
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;
|
||||
@@ -1328,7 +1346,7 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
// quic v2 : initial packets are 01b
|
||||
if ((data[0] & 0x30) != (is_quic_v2(ver) ? 0x10 : 0x00)) return false;
|
||||
|
||||
uint64_t offset=5, sz;
|
||||
uint64_t offset=5, sz, sz2;
|
||||
|
||||
// DCID
|
||||
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||
@@ -1339,14 +1357,16 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
offset += 1 + data[offset];
|
||||
|
||||
// token length
|
||||
if (offset>=len || (offset + tvb_get_size(data[offset])) > len) return false;
|
||||
offset += tvb_get_varint(data + offset, &sz);
|
||||
offset += sz;
|
||||
if (offset >= len) return false;
|
||||
|
||||
// payload length
|
||||
if ((offset + tvb_get_size(data[offset])) > len) return false;
|
||||
sz2 = tvb_get_size(data[offset]);
|
||||
if ((offset + sz2) > len) return false;
|
||||
tvb_get_varint(data + offset, &sz);
|
||||
offset += sz;
|
||||
offset += sz2 + sz;
|
||||
if (offset > len) return false;
|
||||
|
||||
return true;
|
||||
@@ -1386,24 +1406,24 @@ bool IsDNSResponse(const uint8_t *data, size_t len)
|
||||
}
|
||||
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len==148 && data[0]==1;
|
||||
return len==148 && pntoh32(data)==0x01000000;
|
||||
}
|
||||
bool IsWireguardHandshakeResponse(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len==92 && data[0]==2;
|
||||
return len==92 && pntoh32(data)==0x02000000;
|
||||
}
|
||||
bool IsWireguardHandshakeCookie(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len==64 && data[0]==3;
|
||||
return len==64 && pntoh32(data)==0x03000000;
|
||||
}
|
||||
bool IsWireguardData(const uint8_t *data, size_t len)
|
||||
{
|
||||
// 16 bytes wg header + min 20 bytes for ipv4 encrypted header + 16 byte auth tag
|
||||
return len>=52 && data[0]==4;
|
||||
return len>=52 && pntoh32(data)==0x04000000;
|
||||
}
|
||||
bool IsWireguardKeepalive(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len==32 && data[0]==4;
|
||||
return len==32 && pntoh32(data)==0x04000000;
|
||||
}
|
||||
bool IsDht(const uint8_t *data, size_t len)
|
||||
{
|
||||
@@ -1426,8 +1446,8 @@ bool IsStunMessage(const uint8_t *data, size_t len)
|
||||
return len>=20 && // header size
|
||||
(data[0]&0xC0)==0 && // 2 most significant bits must be zeroes
|
||||
(data[3]&3)==0 && // length must be a multiple of 4
|
||||
ntohl(*(uint32_t*)(&data[4]))==0x2112A442 && // magic cookie
|
||||
ntohs(*(uint16_t*)(&data[2]))==len-20;
|
||||
pntoh32(data+4)==0x2112A442 && // magic cookie
|
||||
pntoh16(data+2)==(len-20);
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
@@ -1437,12 +1457,12 @@ bool IsMTProto(const uint8_t *data, size_t len)
|
||||
if (len>=64)
|
||||
{
|
||||
/*
|
||||
uint8_t decrypt[64];
|
||||
uint8_t decrypt[64] __attribute__((aligned));
|
||||
aes_ctr_crypt(data+8, 32, data+40, data, 64, decrypt);
|
||||
return !memcmp(decrypt+56,"\xEF\xEF\xEF\xEF",4);
|
||||
*/
|
||||
// this way requires only one AES instead of 4
|
||||
uint8_t decrypt[16], iv[16];
|
||||
uint8_t decrypt[16] __attribute__((aligned)), iv[16];
|
||||
aes_context ctx;
|
||||
|
||||
memcpy(iv, data+40, 16);
|
||||
@@ -1474,3 +1494,14 @@ bool IsDTLSServerHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return IsDTLS(data,len) && data[0]==0x16 && data[13]==2;
|
||||
}
|
||||
|
||||
bool IsBTHandshake(const uint8_t *data, size_t len)
|
||||
{
|
||||
// len, pstrlen, reserved, sha1, peer id
|
||||
return len>=(1+19+8+20+20) && !memcmp(data,"\x13" "BitTorrent protocol",20);
|
||||
}
|
||||
bool IsUTP_BTHandshake(const uint8_t *data, size_t len)
|
||||
{
|
||||
// len, pstrlen, reserved, sha1, peer id
|
||||
return len>=(20+1+19+8+20+20) && data[0]==0x01 && !memcmp(data+20,"\x13" "BitTorrent protocol",20);;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ typedef enum {
|
||||
L7_XMPP,
|
||||
L7_DNS,
|
||||
L7_MTPROTO,
|
||||
L7_LAST, L7_INVALID=L7_LAST
|
||||
L7_BT,
|
||||
L7_UTP_BT,
|
||||
L7_LAST, L7_INVALID=L7_LAST, L7_NONE=L7_LAST
|
||||
} t_l7proto;
|
||||
const char *l7proto_str(t_l7proto l7);
|
||||
t_l7proto l7proto_from_name(const char *name);
|
||||
@@ -31,6 +33,9 @@ typedef enum {
|
||||
L7P_UNKNOWN,
|
||||
L7P_EMPTY,
|
||||
L7P_KNOWN,
|
||||
L7P_IPV4,
|
||||
L7P_IPV6,
|
||||
L7P_ICMP,
|
||||
L7P_HTTP_REQ,
|
||||
L7P_HTTP_REPLY,
|
||||
L7P_TLS_CLIENT_HELLO,
|
||||
@@ -53,7 +58,9 @@ typedef enum {
|
||||
L7P_DNS_QUERY,
|
||||
L7P_DNS_RESPONSE,
|
||||
L7P_MTPROTO_INITIAL,
|
||||
L7P_LAST, L7P_INVALID=L7P_LAST
|
||||
L7P_BT_HANDSHAKE,
|
||||
L7P_UTP_BT_HANDSHAKE,
|
||||
L7P_LAST, L7P_INVALID=L7P_LAST, L7P_NONE=L7P_LAST
|
||||
} t_l7payload;
|
||||
t_l7payload l7payload_from_name(const char *name);
|
||||
const char *l7payload_str(t_l7payload l7);
|
||||
@@ -90,16 +97,12 @@ ssize_t TLSPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz);
|
||||
ssize_t ResolvePos(const uint8_t *data, size_t sz, t_l7payload l7payload, const struct proto_pos *sp);
|
||||
void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7payload l7payload, const struct proto_pos *marker, int marker_count, ssize_t *pos, int *pos_count);
|
||||
|
||||
extern const char *http_methods[9];
|
||||
const char *HttpMethod(const uint8_t *data, size_t len);
|
||||
bool IsHttp(const uint8_t *data, size_t len);
|
||||
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs);
|
||||
bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs);
|
||||
// header must be passed like this : "\nHost:"
|
||||
bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char *buf, size_t len_buf);
|
||||
bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host);
|
||||
bool IsHttpReply(const uint8_t *data, size_t len);
|
||||
const char *HttpFind2ndLevelDomain(const char *host);
|
||||
// must be pre-checked by IsHttpReply
|
||||
int HttpReplyCode(const uint8_t *data, size_t len);
|
||||
// must be pre-checked by IsHttpReply
|
||||
@@ -161,7 +164,8 @@ bool IsMTProto(const uint8_t *data, size_t len);
|
||||
bool IsDTLS(const uint8_t *data, size_t len);
|
||||
bool IsDTLSClientHello(const uint8_t *data, size_t len);
|
||||
bool IsDTLSServerHello(const uint8_t *data, size_t len);
|
||||
|
||||
bool IsBTHandshake(const uint8_t *data, size_t len);
|
||||
bool IsUTP_BTHandshake(const uint8_t *data, size_t len);
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
typedef struct quic_cid {
|
||||
|
||||
36
nfq2/random.c
Normal file
36
nfq2/random.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "random.h"
|
||||
|
||||
#ifdef NEED_GETRANDOM
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef SYS_getrandom
|
||||
|
||||
#if defined(__aarch64__)
|
||||
#define SYS_getrandom 278
|
||||
|
||||
#elif defined(__arm__)
|
||||
/* ARM EABI */
|
||||
#define SYS_getrandom 384
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
#define SYS_getrandom 318
|
||||
|
||||
#elif defined(__i386__)
|
||||
#define SYS_getrandom 355
|
||||
|
||||
#elif defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32
|
||||
#define SYS_getrandom 4353
|
||||
|
||||
#else
|
||||
#error "Unsupported architecture: SYS_getrandom not defined"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
ssize_t getrandom(void *ptr, size_t len, unsigned int flags)
|
||||
{
|
||||
return syscall(SYS_getrandom, ptr, len, flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
31
nfq2/random.h
Normal file
31
nfq2/random.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
// shim for old NDK and old gcc linux compilers
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#if defined(__ANDROID__) && __ANDROID_API__ < 28 || !defined(SYS_getrandom)
|
||||
|
||||
#define NEED_GETRANDOM
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* getrandom flags */
|
||||
#define GRND_NONBLOCK 1
|
||||
#define GRND_RANDOM 2
|
||||
|
||||
ssize_t getrandom(void *ptr, size_t len, unsigned int flags);
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/random.h>
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(__CYGWIN__)
|
||||
|
||||
#include <sys/random.h>
|
||||
|
||||
#endif
|
||||
69
nfq2/sec.c
69
nfq2/sec.c
@@ -6,6 +6,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "params.h"
|
||||
|
||||
@@ -18,7 +19,6 @@
|
||||
// __X32_SYSCALL_BIT defined in linux/unistd.h
|
||||
#include <linux/unistd.h>
|
||||
#include <syscall.h>
|
||||
#include <errno.h>
|
||||
|
||||
/************ SECCOMP ************/
|
||||
|
||||
@@ -210,10 +210,10 @@ int getmaxcap(void)
|
||||
}
|
||||
bool dropcaps(void)
|
||||
{
|
||||
uint64_t caps = (1<<CAP_NET_ADMIN)|(1<<CAP_NET_RAW);
|
||||
uint64_t caps = (1ULL<<CAP_NET_ADMIN)|(1ULL<<CAP_NET_RAW);
|
||||
int maxcap = getmaxcap();
|
||||
|
||||
if (setpcap(caps|(1<<CAP_SETPCAP)))
|
||||
if (setpcap(caps|(1ULL<<CAP_SETPCAP)))
|
||||
{
|
||||
for (int cap = 0; cap <= maxcap; cap++)
|
||||
{
|
||||
@@ -249,7 +249,7 @@ bool can_drop_root(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// has some caps
|
||||
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID));
|
||||
return checkpcap((1ULL<<CAP_SETUID)|(1ULL<<CAP_SETGID));
|
||||
#else
|
||||
// effective root
|
||||
return !geteuid();
|
||||
@@ -327,37 +327,66 @@ void daemonize(void)
|
||||
int pid;
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
if (!getcwd(cwd, sizeof(cwd))) *cwd=0;
|
||||
if (!getcwd(cwd, sizeof(cwd)))
|
||||
{
|
||||
DLOG_PERROR("getcwd");
|
||||
*cwd=0;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
DLOG_PERROR("fork");
|
||||
exit(2);
|
||||
exit(20);
|
||||
}
|
||||
else if (pid != 0)
|
||||
exit(0);
|
||||
|
||||
if (*cwd)
|
||||
{
|
||||
int res = chdir(cwd);
|
||||
}
|
||||
if (*cwd && chdir(cwd)<0)
|
||||
DLOG_PERROR("chdir");
|
||||
|
||||
if (setsid() == -1)
|
||||
exit(2);
|
||||
if (chdir("/") == -1)
|
||||
exit(2);
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
{
|
||||
DLOG_PERROR("setsid");
|
||||
exit(21);
|
||||
}
|
||||
if (close(STDIN_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
DLOG_PERROR("close(stdin)");
|
||||
exit(22);
|
||||
}
|
||||
if (close(STDOUT_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
DLOG_PERROR("close(stdout)");
|
||||
exit(22);
|
||||
}
|
||||
if (close(STDERR_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
DLOG_PERROR("close(stderr)");
|
||||
exit(22);
|
||||
}
|
||||
/* redirect fd's 0,1,2 to /dev/null */
|
||||
open("/dev/null", O_RDWR);
|
||||
int fd;
|
||||
/* stdin */
|
||||
fd = dup(0);
|
||||
if (open("/dev/null", O_RDWR)<0)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("open(stdin)");
|
||||
exit(23);
|
||||
}
|
||||
/* stdout */
|
||||
fd = dup(0);
|
||||
if (dup(0)<0)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("dup(stdout)");
|
||||
exit(24);
|
||||
}
|
||||
/* stderror */
|
||||
if (dup(0)<0)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("dup(stderr)");
|
||||
exit(25);
|
||||
}
|
||||
}
|
||||
|
||||
bool writepid(const char *filename)
|
||||
|
||||
23
nfq2/sec.h
23
nfq2/sec.h
@@ -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"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
|
||||
Copyright (c) 2003-2025, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,12 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit */
|
||||
|
||||
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
|
||||
/* This codepath is provided for backward compatibility, but I plan to remove it. */
|
||||
#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead"
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
||||
#if defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
||||
/* The user doesn't have <stdint.h>, and must figure out their own way
|
||||
to provide definitions for uint8_t and uint32_t. */
|
||||
#else
|
||||
#include <stdint.h> /* uint8_t, uint32_t */
|
||||
#endif
|
||||
@@ -51,6 +48,8 @@ typedef unsigned char uint8_t;
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#endif
|
||||
#elif defined(__MCST__) /* Elbrus C Compiler */
|
||||
#define DECLTYPE(x) (__typeof(x))
|
||||
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||
#define NO_DECLTYPE
|
||||
#else /* GNU, Sun and other compilers */
|
||||
@@ -157,7 +156,7 @@ do {
|
||||
if (head) { \
|
||||
unsigned _hf_bkt; \
|
||||
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \
|
||||
} \
|
||||
} \
|
||||
@@ -194,7 +193,7 @@ do {
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) ((bv[(idx)/8U] & (1U << ((idx)%8U))) != 0)
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
|
||||
@@ -206,7 +205,7 @@ do {
|
||||
#define HASH_BLOOM_MAKE(tbl,oomed)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) 1
|
||||
#define HASH_BLOOM_BYTELEN 0U
|
||||
#endif
|
||||
|
||||
@@ -450,7 +449,7 @@ do {
|
||||
|
||||
#define HASH_DELETE_HH(hh,head,delptrhh) \
|
||||
do { \
|
||||
struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
||||
const struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
||||
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
@@ -593,7 +592,9 @@ do {
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
||||
* (archive link: https://archive.is/Ivcan )
|
||||
*/
|
||||
#define HASH_SAX(key,keylen,hashv) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
|
||||
347
nfq2/windows/netinet/icmp6.h
Normal file
347
nfq2/windows/netinet/icmp6.h
Normal file
@@ -0,0 +1,347 @@
|
||||
/* Copyright (C) 1991-2025 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _NETINET_ICMP6_H
|
||||
#define _NETINET_ICMP6_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define ICMP6_FILTER 1
|
||||
|
||||
#define ICMP6_FILTER_BLOCK 1
|
||||
#define ICMP6_FILTER_PASS 2
|
||||
#define ICMP6_FILTER_BLOCKOTHERS 3
|
||||
#define ICMP6_FILTER_PASSONLY 4
|
||||
|
||||
struct icmp6_filter
|
||||
{
|
||||
uint32_t icmp6_filt[8];
|
||||
};
|
||||
|
||||
struct icmp6_hdr
|
||||
{
|
||||
uint8_t icmp6_type; /* type field */
|
||||
uint8_t icmp6_code; /* code field */
|
||||
uint16_t icmp6_cksum; /* checksum field */
|
||||
union
|
||||
{
|
||||
uint32_t icmp6_un_data32[1]; /* type-specific field */
|
||||
uint16_t icmp6_un_data16[2]; /* type-specific field */
|
||||
uint8_t icmp6_un_data8[4]; /* type-specific field */
|
||||
} icmp6_dataun;
|
||||
};
|
||||
|
||||
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
|
||||
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
|
||||
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
|
||||
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
|
||||
#define icmp6_mtu icmp6_data32[0] /* packet too big */
|
||||
#define icmp6_id icmp6_data16[0] /* echo request/reply */
|
||||
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
|
||||
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
|
||||
|
||||
#define ICMP6_DST_UNREACH 1
|
||||
#define ICMP6_PACKET_TOO_BIG 2
|
||||
#define ICMP6_TIME_EXCEEDED 3
|
||||
#define ICMP6_PARAM_PROB 4
|
||||
|
||||
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
|
||||
|
||||
#define ICMP6_ECHO_REQUEST 128
|
||||
#define ICMP6_ECHO_REPLY 129
|
||||
#define MLD_LISTENER_QUERY 130
|
||||
#define MLD_LISTENER_REPORT 131
|
||||
#define MLD_LISTENER_REDUCTION 132
|
||||
#define ICMPV6_EXT_ECHO_REQUEST 160
|
||||
#define ICMPV6_EXT_ECHO_REPLY 161
|
||||
|
||||
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
|
||||
#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */
|
||||
/* administratively prohibited */
|
||||
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
|
||||
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
|
||||
#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */
|
||||
|
||||
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */
|
||||
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
|
||||
|
||||
#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
|
||||
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
|
||||
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */
|
||||
|
||||
#define ICMP6_FILTER_WILLPASS(type, filterp) \
|
||||
((((filterp)->icmp6_filt[(type) >> 5]) & (1U << ((type) & 31))) == 0)
|
||||
|
||||
#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
|
||||
((((filterp)->icmp6_filt[(type) >> 5]) & (1U << ((type) & 31))) != 0)
|
||||
|
||||
#define ICMP6_FILTER_SETPASS(type, filterp) \
|
||||
((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1U << ((type) & 31))))
|
||||
|
||||
#define ICMP6_FILTER_SETBLOCK(type, filterp) \
|
||||
((((filterp)->icmp6_filt[(type) >> 5]) |= (1U << ((type) & 31))))
|
||||
|
||||
#define ICMP6_FILTER_SETPASSALL(filterp) \
|
||||
memset (filterp, 0, sizeof (struct icmp6_filter));
|
||||
|
||||
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
|
||||
memset (filterp, 0xFF, sizeof (struct icmp6_filter));
|
||||
|
||||
#define ND_ROUTER_SOLICIT 133
|
||||
#define ND_ROUTER_ADVERT 134
|
||||
#define ND_NEIGHBOR_SOLICIT 135
|
||||
#define ND_NEIGHBOR_ADVERT 136
|
||||
#define ND_REDIRECT 137
|
||||
|
||||
struct nd_router_solicit /* router solicitation */
|
||||
{
|
||||
struct icmp6_hdr nd_rs_hdr;
|
||||
/* could be followed by options */
|
||||
};
|
||||
|
||||
#define nd_rs_type nd_rs_hdr.icmp6_type
|
||||
#define nd_rs_code nd_rs_hdr.icmp6_code
|
||||
#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
|
||||
#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
|
||||
|
||||
struct nd_router_advert /* router advertisement */
|
||||
{
|
||||
struct icmp6_hdr nd_ra_hdr;
|
||||
uint32_t nd_ra_reachable; /* reachable time */
|
||||
uint32_t nd_ra_retransmit; /* retransmit timer */
|
||||
/* could be followed by options */
|
||||
};
|
||||
|
||||
#define nd_ra_type nd_ra_hdr.icmp6_type
|
||||
#define nd_ra_code nd_ra_hdr.icmp6_code
|
||||
#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
|
||||
#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
|
||||
#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
|
||||
#define ND_RA_FLAG_MANAGED 0x80
|
||||
#define ND_RA_FLAG_OTHER 0x40
|
||||
#define ND_RA_FLAG_HOME_AGENT 0x20
|
||||
#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
|
||||
|
||||
struct nd_neighbor_solicit /* neighbor solicitation */
|
||||
{
|
||||
struct icmp6_hdr nd_ns_hdr;
|
||||
struct in6_addr nd_ns_target; /* target address */
|
||||
/* could be followed by options */
|
||||
};
|
||||
|
||||
#define nd_ns_type nd_ns_hdr.icmp6_type
|
||||
#define nd_ns_code nd_ns_hdr.icmp6_code
|
||||
#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
|
||||
#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
|
||||
|
||||
struct nd_neighbor_advert /* neighbor advertisement */
|
||||
{
|
||||
struct icmp6_hdr nd_na_hdr;
|
||||
struct in6_addr nd_na_target; /* target address */
|
||||
/* could be followed by options */
|
||||
};
|
||||
|
||||
#define nd_na_type nd_na_hdr.icmp6_type
|
||||
#define nd_na_code nd_na_hdr.icmp6_code
|
||||
#define nd_na_cksum nd_na_hdr.icmp6_cksum
|
||||
#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ND_NA_FLAG_ROUTER 0x80000000
|
||||
#define ND_NA_FLAG_SOLICITED 0x40000000
|
||||
#define ND_NA_FLAG_OVERRIDE 0x20000000
|
||||
#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
|
||||
#define ND_NA_FLAG_ROUTER 0x00000080
|
||||
#define ND_NA_FLAG_SOLICITED 0x00000040
|
||||
#define ND_NA_FLAG_OVERRIDE 0x00000020
|
||||
#endif
|
||||
|
||||
struct nd_redirect /* redirect */
|
||||
{
|
||||
struct icmp6_hdr nd_rd_hdr;
|
||||
struct in6_addr nd_rd_target; /* target address */
|
||||
struct in6_addr nd_rd_dst; /* destination address */
|
||||
/* could be followed by options */
|
||||
};
|
||||
|
||||
#define nd_rd_type nd_rd_hdr.icmp6_type
|
||||
#define nd_rd_code nd_rd_hdr.icmp6_code
|
||||
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
|
||||
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
|
||||
|
||||
struct nd_opt_hdr /* Neighbor discovery option header */
|
||||
{
|
||||
uint8_t nd_opt_type;
|
||||
uint8_t nd_opt_len; /* in units of 8 octets */
|
||||
/* followed by option specific data */
|
||||
};
|
||||
|
||||
#define ND_OPT_SOURCE_LINKADDR 1
|
||||
#define ND_OPT_TARGET_LINKADDR 2
|
||||
#define ND_OPT_PREFIX_INFORMATION 3
|
||||
#define ND_OPT_REDIRECTED_HEADER 4
|
||||
#define ND_OPT_MTU 5
|
||||
#define ND_OPT_RTR_ADV_INTERVAL 7
|
||||
#define ND_OPT_HOME_AGENT_INFO 8
|
||||
|
||||
struct nd_opt_prefix_info /* prefix information */
|
||||
{
|
||||
uint8_t nd_opt_pi_type;
|
||||
uint8_t nd_opt_pi_len;
|
||||
uint8_t nd_opt_pi_prefix_len;
|
||||
uint8_t nd_opt_pi_flags_reserved;
|
||||
uint32_t nd_opt_pi_valid_time;
|
||||
uint32_t nd_opt_pi_preferred_time;
|
||||
uint32_t nd_opt_pi_reserved2;
|
||||
struct in6_addr nd_opt_pi_prefix;
|
||||
};
|
||||
|
||||
#define ND_OPT_PI_FLAG_ONLINK 0x80
|
||||
#define ND_OPT_PI_FLAG_AUTO 0x40
|
||||
#define ND_OPT_PI_FLAG_RADDR 0x20
|
||||
|
||||
struct nd_opt_rd_hdr /* redirected header */
|
||||
{
|
||||
uint8_t nd_opt_rh_type;
|
||||
uint8_t nd_opt_rh_len;
|
||||
uint16_t nd_opt_rh_reserved1;
|
||||
uint32_t nd_opt_rh_reserved2;
|
||||
/* followed by IP header and data */
|
||||
};
|
||||
|
||||
struct nd_opt_mtu /* MTU option */
|
||||
{
|
||||
uint8_t nd_opt_mtu_type;
|
||||
uint8_t nd_opt_mtu_len;
|
||||
uint16_t nd_opt_mtu_reserved;
|
||||
uint32_t nd_opt_mtu_mtu;
|
||||
};
|
||||
|
||||
struct mld_hdr
|
||||
{
|
||||
struct icmp6_hdr mld_icmp6_hdr;
|
||||
struct in6_addr mld_addr; /* multicast address */
|
||||
};
|
||||
|
||||
#define mld_type mld_icmp6_hdr.icmp6_type
|
||||
#define mld_code mld_icmp6_hdr.icmp6_code
|
||||
#define mld_cksum mld_icmp6_hdr.icmp6_cksum
|
||||
#define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0]
|
||||
#define mld_reserved mld_icmp6_hdr.icmp6_data16[1]
|
||||
|
||||
#define ICMP6_ROUTER_RENUMBERING 138
|
||||
|
||||
struct icmp6_router_renum /* router renumbering header */
|
||||
{
|
||||
struct icmp6_hdr rr_hdr;
|
||||
uint8_t rr_segnum;
|
||||
uint8_t rr_flags;
|
||||
uint16_t rr_maxdelay;
|
||||
uint32_t rr_reserved;
|
||||
};
|
||||
|
||||
#define rr_type rr_hdr.icmp6_type
|
||||
#define rr_code rr_hdr.icmp6_code
|
||||
#define rr_cksum rr_hdr.icmp6_cksum
|
||||
#define rr_seqnum rr_hdr.icmp6_data32[0]
|
||||
|
||||
/* Router renumbering flags */
|
||||
#define ICMP6_RR_FLAGS_TEST 0x80
|
||||
#define ICMP6_RR_FLAGS_REQRESULT 0x40
|
||||
#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20
|
||||
#define ICMP6_RR_FLAGS_SPECSITE 0x10
|
||||
#define ICMP6_RR_FLAGS_PREVDONE 0x08
|
||||
|
||||
struct rr_pco_match /* match prefix part */
|
||||
{
|
||||
uint8_t rpm_code;
|
||||
uint8_t rpm_len;
|
||||
uint8_t rpm_ordinal;
|
||||
uint8_t rpm_matchlen;
|
||||
uint8_t rpm_minlen;
|
||||
uint8_t rpm_maxlen;
|
||||
uint16_t rpm_reserved;
|
||||
struct in6_addr rpm_prefix;
|
||||
};
|
||||
|
||||
/* PCO code values */
|
||||
#define RPM_PCO_ADD 1
|
||||
#define RPM_PCO_CHANGE 2
|
||||
#define RPM_PCO_SETGLOBAL 3
|
||||
|
||||
struct rr_pco_use /* use prefix part */
|
||||
{
|
||||
uint8_t rpu_uselen;
|
||||
uint8_t rpu_keeplen;
|
||||
uint8_t rpu_ramask;
|
||||
uint8_t rpu_raflags;
|
||||
uint32_t rpu_vltime;
|
||||
uint32_t rpu_pltime;
|
||||
uint32_t rpu_flags;
|
||||
struct in6_addr rpu_prefix;
|
||||
};
|
||||
|
||||
#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x20
|
||||
#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
|
||||
# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80
|
||||
# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40
|
||||
#endif
|
||||
|
||||
struct rr_result /* router renumbering result message */
|
||||
{
|
||||
uint16_t rrr_flags;
|
||||
uint8_t rrr_ordinal;
|
||||
uint8_t rrr_matchedlen;
|
||||
uint32_t rrr_ifid;
|
||||
struct in6_addr rrr_prefix;
|
||||
};
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define ICMP6_RR_RESULT_FLAGS_OOB 0x0002
|
||||
# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define ICMP6_RR_RESULT_FLAGS_OOB 0x0200
|
||||
# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100
|
||||
#endif
|
||||
|
||||
/* Mobile IPv6 extension: Advertisement Interval. */
|
||||
struct nd_opt_adv_interval
|
||||
{
|
||||
uint8_t nd_opt_adv_interval_type;
|
||||
uint8_t nd_opt_adv_interval_len;
|
||||
uint16_t nd_opt_adv_interval_reserved;
|
||||
uint32_t nd_opt_adv_interval_ival;
|
||||
};
|
||||
|
||||
/* Mobile IPv6 extension: Home Agent Info. */
|
||||
struct nd_opt_home_agent_info
|
||||
{
|
||||
uint8_t nd_opt_home_agent_info_type;
|
||||
uint8_t nd_opt_home_agent_info_len;
|
||||
uint16_t nd_opt_home_agent_info_reserved;
|
||||
uint16_t nd_opt_home_agent_info_preference;
|
||||
uint16_t nd_opt_home_agent_info_lifetime;
|
||||
};
|
||||
|
||||
#endif /* netinet/icmpv6.h */
|
||||
298
nfq2/windows/netinet/ip_icmp.h
Normal file
298
nfq2/windows/netinet/ip_icmp.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/* Copyright (C) 1991-2025 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef __NETINET_IP_ICMP_H
|
||||
#define __NETINET_IP_ICMP_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct icmphdr
|
||||
{
|
||||
uint8_t type; /* message type */
|
||||
uint8_t code; /* type sub-code */
|
||||
uint16_t checksum;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo; /* echo datagram */
|
||||
uint32_t gateway; /* gateway address */
|
||||
struct
|
||||
{
|
||||
uint16_t __glibc_reserved;
|
||||
uint16_t mtu;
|
||||
} frag; /* path mtu discovery */
|
||||
} un;
|
||||
};
|
||||
|
||||
#define ICMP_ECHOREPLY 0 /* Echo Reply */
|
||||
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
|
||||
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
|
||||
#define ICMP_REDIRECT 5 /* Redirect (change route) */
|
||||
#define ICMP_ECHO 8 /* Echo Request */
|
||||
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
|
||||
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
|
||||
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
|
||||
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
|
||||
#define ICMP_INFO_REQUEST 15 /* Information Request */
|
||||
#define ICMP_INFO_REPLY 16 /* Information Reply */
|
||||
#define ICMP_ADDRESS 17 /* Address Mask Request */
|
||||
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
|
||||
#define NR_ICMP_TYPES 18
|
||||
|
||||
|
||||
/* Codes for UNREACH. */
|
||||
#define ICMP_NET_UNREACH 0 /* Network Unreachable */
|
||||
#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
|
||||
#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
|
||||
#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
|
||||
#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
|
||||
#define ICMP_SR_FAILED 5 /* Source Route failed */
|
||||
#define ICMP_NET_UNKNOWN 6
|
||||
#define ICMP_HOST_UNKNOWN 7
|
||||
#define ICMP_HOST_ISOLATED 8
|
||||
#define ICMP_NET_ANO 9
|
||||
#define ICMP_HOST_ANO 10
|
||||
#define ICMP_NET_UNR_TOS 11
|
||||
#define ICMP_HOST_UNR_TOS 12
|
||||
#define ICMP_PKT_FILTERED 13 /* Packet filtered */
|
||||
#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
|
||||
#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
|
||||
#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */
|
||||
|
||||
/* Codes for REDIRECT. */
|
||||
#define ICMP_REDIR_NET 0 /* Redirect Net */
|
||||
#define ICMP_REDIR_HOST 1 /* Redirect Host */
|
||||
#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
|
||||
#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
|
||||
|
||||
/* Codes for TIME_EXCEEDED. */
|
||||
#define ICMP_EXC_TTL 0 /* TTL count exceeded */
|
||||
#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
|
||||
|
||||
/* Codes for ICMP_EXT_ECHO (PROBE) */
|
||||
#define ICMP_EXT_ECHO 42
|
||||
#define ICMP_EXT_ECHOREPLY 43
|
||||
#define ICMP_EXT_CODE_MAL_QUERY 1 /* Malformed Query */
|
||||
#define ICMP_EXT_CODE_NO_IF 2 /* No such Interface */
|
||||
#define ICMP_EXT_CODE_NO_TABLE_ENT 3 /* No table entry */
|
||||
#define ICMP_EXT_CODE_MULT_IFS 4 /* Multiple Interfaces Satisfy Query */
|
||||
|
||||
/* Constants for EXT_ECHO (PROBE) */
|
||||
#define ICMP_EXT_ECHOREPLY_ACTIVE (1 << 2)/* active bit in reply */
|
||||
#define ICMP_EXT_ECHOREPLY_IPV4 (1 << 1)/* ipv4 bit in reply */
|
||||
#define ICMP_EXT_ECHOREPLY_IPV6 1 /* ipv6 bit in reply */
|
||||
#define ICMP_EXT_ECHO_CTYPE_NAME 1
|
||||
#define ICMP_EXT_ECHO_CTYPE_INDEX 2
|
||||
#define ICMP_EXT_ECHO_CTYPE_ADDR 3
|
||||
#define ICMP_AFI_IP 1 /* Address Family Identifier for IPV4 */
|
||||
#define ICMP_AFI_IP6 2 /* Address Family Identifier for IPV6 */
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
/*
|
||||
* Internal of an ICMP Router Advertisement
|
||||
*/
|
||||
struct icmp_ra_addr
|
||||
{
|
||||
uint32_t ira_addr;
|
||||
uint32_t ira_preference;
|
||||
};
|
||||
|
||||
struct icmp
|
||||
{
|
||||
uint8_t icmp_type; /* type of message, see below */
|
||||
uint8_t icmp_code; /* type sub code */
|
||||
uint16_t icmp_cksum; /* ones complement checksum of struct */
|
||||
union
|
||||
{
|
||||
unsigned char ih_pptr; /* ICMP_PARAMPROB */
|
||||
struct in_addr ih_gwaddr; /* gateway address */
|
||||
struct ih_idseq /* echo datagram */
|
||||
{
|
||||
uint16_t icd_id;
|
||||
uint16_t icd_seq;
|
||||
} ih_idseq;
|
||||
uint32_t ih_void;
|
||||
|
||||
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
|
||||
struct ih_pmtu
|
||||
{
|
||||
uint16_t ipm_void;
|
||||
uint16_t ipm_nextmtu;
|
||||
} ih_pmtu;
|
||||
|
||||
struct ih_rtradv
|
||||
{
|
||||
uint8_t irt_num_addrs;
|
||||
uint8_t irt_wpa;
|
||||
uint16_t irt_lifetime;
|
||||
} ih_rtradv;
|
||||
} icmp_hun;
|
||||
#define icmp_pptr icmp_hun.ih_pptr
|
||||
#define icmp_gwaddr icmp_hun.ih_gwaddr
|
||||
#define icmp_id icmp_hun.ih_idseq.icd_id
|
||||
#define icmp_seq icmp_hun.ih_idseq.icd_seq
|
||||
#define icmp_void icmp_hun.ih_void
|
||||
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
|
||||
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
|
||||
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
|
||||
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
|
||||
#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t its_otime;
|
||||
uint32_t its_rtime;
|
||||
uint32_t its_ttime;
|
||||
} id_ts;
|
||||
struct
|
||||
{
|
||||
struct ip idi_ip;
|
||||
/* options and then 64 bits of data */
|
||||
} id_ip;
|
||||
struct icmp_ra_addr id_radv;
|
||||
uint32_t id_mask;
|
||||
uint8_t id_data[1];
|
||||
} icmp_dun;
|
||||
#define icmp_otime icmp_dun.id_ts.its_otime
|
||||
#define icmp_rtime icmp_dun.id_ts.its_rtime
|
||||
#define icmp_ttime icmp_dun.id_ts.its_ttime
|
||||
#define icmp_ip icmp_dun.id_ip.idi_ip
|
||||
#define icmp_radv icmp_dun.id_radv
|
||||
#define icmp_mask icmp_dun.id_mask
|
||||
#define icmp_data icmp_dun.id_data
|
||||
};
|
||||
|
||||
/*
|
||||
* Lower bounds on packet lengths for various types.
|
||||
* For the error advice packets must first insure that the
|
||||
* packet is large enough to contain the returned ip header.
|
||||
* Only then can we do the check to see if 64 bits of packet
|
||||
* data have been returned, since we need to check the returned
|
||||
* ip header length.
|
||||
*/
|
||||
#define ICMP_MINLEN 8 /* abs minimum */
|
||||
#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
|
||||
#define ICMP_MASKLEN 12 /* address mask */
|
||||
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
|
||||
#ifndef _IP_VHL
|
||||
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
|
||||
/* N.B.: must separately check that ip_hl >= 5 */
|
||||
#else
|
||||
#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8)
|
||||
/* N.B.: must separately check that header length >= 5 */
|
||||
#endif
|
||||
|
||||
/* Definition of type and code fields. */
|
||||
/* defined above: ICMP_ECHOREPLY, ICMP_REDIRECT, ICMP_ECHO */
|
||||
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
|
||||
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
|
||||
#define ICMP_ROUTERADVERT 9 /* router advertisement */
|
||||
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
|
||||
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
|
||||
#define ICMP_PARAMPROB 12 /* ip header bad */
|
||||
#define ICMP_TSTAMP 13 /* timestamp request */
|
||||
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
|
||||
#define ICMP_IREQ 15 /* information request */
|
||||
#define ICMP_IREQREPLY 16 /* information reply */
|
||||
#define ICMP_MASKREQ 17 /* address mask request */
|
||||
#define ICMP_MASKREPLY 18 /* address mask reply */
|
||||
|
||||
#define ICMP_MAXTYPE 18
|
||||
|
||||
/* UNREACH codes */
|
||||
#define ICMP_UNREACH_NET 0 /* bad net */
|
||||
#define ICMP_UNREACH_HOST 1 /* bad host */
|
||||
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
|
||||
#define ICMP_UNREACH_PORT 3 /* bad port */
|
||||
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
|
||||
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
|
||||
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
|
||||
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
|
||||
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
|
||||
#define ICMP_UNREACH_NET_PROHIB 9 /* net denied */
|
||||
#define ICMP_UNREACH_HOST_PROHIB 10 /* host denied */
|
||||
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
|
||||
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
|
||||
#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */
|
||||
#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */
|
||||
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */
|
||||
|
||||
/* REDIRECT codes */
|
||||
#define ICMP_REDIRECT_NET 0 /* for network */
|
||||
#define ICMP_REDIRECT_HOST 1 /* for host */
|
||||
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
|
||||
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
|
||||
|
||||
/* TIMEXCEED codes */
|
||||
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
|
||||
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
|
||||
|
||||
/* PARAMPROB code */
|
||||
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
|
||||
|
||||
#define ICMP_INFOTYPE(type) \
|
||||
((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO \
|
||||
|| (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT \
|
||||
|| (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY \
|
||||
|| (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY \
|
||||
|| (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
|
||||
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* netinet/ip_icmp.h */
|
||||
40
nfq2/windows/nthacks.h
Normal file
40
nfq2/windows/nthacks.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <winternl.h>
|
||||
|
||||
#define DIRECTORY_QUERY (0x0001)
|
||||
#define DIRECTORY_TRAVERSE (0x0002)
|
||||
#define DIRECTORY_CREATE_OBJECT (0x0004)
|
||||
#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008)
|
||||
#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF)
|
||||
|
||||
typedef struct _PROCESS_SESSION_INFORMATION {
|
||||
ULONG SessionId;
|
||||
} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
|
||||
|
||||
typedef struct _OBJECT_DIRECTORY_INFORMATION {
|
||||
UNICODE_STRING Name;
|
||||
UNICODE_STRING TypeName;
|
||||
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
NTSTATUS NTAPI NtOpenDirectoryObject(
|
||||
_Out_ PHANDLE DirectoryHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ POBJECT_ATTRIBUTES ObjectAttributes
|
||||
);
|
||||
NTSTATUS NTAPI NtQueryDirectoryObject(
|
||||
_In_ HANDLE DirectoryHandle,
|
||||
_Out_opt_ PVOID Buffer,
|
||||
_In_ ULONG Length,
|
||||
_In_ BOOLEAN ReturnSingleEntry,
|
||||
_In_ BOOLEAN RestartScan,
|
||||
_Inout_ PULONG Context,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
nfq2/windows/res/howto.txt
Normal file
4
nfq2/windows/res/howto.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# in 64 bit cygwin
|
||||
windres winws.rc -O coff -o winws_res64.o
|
||||
# in 32 bit cygwin
|
||||
windres winws.rc -O coff -o winws_res32.o
|
||||
BIN
nfq2/windows/res/winws.ico
Normal file
BIN
nfq2/windows/res/winws.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user