mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2026-01-27 12:40:36 +03:00
Compare commits
57 Commits
v1.0.0-rc3
...
v1.0.0-rc5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc345ed6d4 | ||
|
|
123c87a24d | ||
|
|
e28a288ea0 | ||
|
|
d1dab6928b | ||
|
|
fd980e5d98 | ||
|
|
9a3b139fb5 | ||
|
|
6568aa37f2 | ||
|
|
3a1deb054a | ||
|
|
ed5a669393 | ||
|
|
5fcb4a8012 | ||
|
|
8718fc5f6c | ||
|
|
062200d9ea | ||
|
|
25199288e8 | ||
|
|
1822983b34 | ||
|
|
ba0f87d195 | ||
|
|
e8bdd05839 | ||
|
|
f4e5cdb328 | ||
|
|
8b602a9f44 | ||
|
|
42e6d574a0 | ||
|
|
457a7a7f04 | ||
|
|
9b5c8a729d | ||
|
|
b452ed2d55 | ||
|
|
f9a51944dd | ||
|
|
7480cd31b8 | ||
|
|
b2ac2e0d03 | ||
|
|
5ee77d517b | ||
|
|
f5a6c5718f | ||
|
|
aefabe7e0a | ||
|
|
fd1ae1e574 | ||
|
|
7303abdaf2 | ||
|
|
cb138b902a | ||
|
|
3a5dbff8ac | ||
|
|
62551a9f82 | ||
|
|
ef120ca100 | ||
|
|
a4975dcdcd | ||
|
|
7ec29bd47b | ||
|
|
20ce07821b | ||
|
|
eb544c11ce | ||
|
|
3376860c0f | ||
|
|
438a3c17d8 | ||
|
|
046ecc4c97 | ||
|
|
bb8992578f | ||
|
|
cb46c89423 | ||
|
|
d87d3c9efb | ||
|
|
562f17e932 | ||
|
|
56b6126f52 | ||
|
|
235bf823db | ||
|
|
c9537bae95 | ||
|
|
0ee6d667e4 | ||
|
|
aa96769559 | ||
|
|
ae9592c71f | ||
|
|
93972f8404 | ||
|
|
7070ddfc74 | ||
|
|
0e9b3ff018 | ||
|
|
f344e525d2 | ||
|
|
f1ab2ac1a9 | ||
|
|
55d359d3e7 |
42
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
42
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Bug report
|
||||
description: Use this issue template when you are pretty sure here is a bug. Make sure the trouble you are experiencing haven't been already reported earlier and haven't been talked about in discussions.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Use this issue template when you are pretty sure here is a bug.
|
||||
Make sure the trouble you are experiencing haven't been already reported earlier and haven't been talked about in [discussions](https://github.com/Waujito/youtubeUnblock/discussions).
|
||||
|
||||
Note, that *bugs* are internal program errors: crashes, freezes and other types of undefined behavior. You may also report problems with routers infrastructure here, but **NOT** questions like *My router doesn't work help please*. Your questions and other stuff with custom routers setup should be discussed [here](https://github.com/Waujito/youtubeUnblock/discussions/172)
|
||||
|
||||
Discuss problems like *youtube doesn't unblock* [here](https://github.com/Waujito/youtubeUnblock/discussions/173)
|
||||
- type: textarea
|
||||
id: bug-report
|
||||
attributes:
|
||||
label: Bug description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: linux-distro
|
||||
attributes:
|
||||
label: Linux distribution
|
||||
description: Pass here your linux distro e.g. OpenWRT, Entware, Merlin, Padavan, Ubuntu, Debian
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: architecture
|
||||
attributes:
|
||||
label: Device architecture
|
||||
description: Pass here the architecture of your device. (On openwrt do `cat /etc/openwrt_release`, on other systems `lscpu` or `cat /proc/cpuinfo`)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: configs
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: Pass here the configuration of youtubeUnblock being used. You may pass output of `cat /etc/config/youtubeUnblock` on OpenWRT or raw flags of youtubeUnblock.
|
||||
validations:
|
||||
required: false
|
||||
10
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
1
.github/builder_containers/README.md
vendored
Normal file
1
.github/builder_containers/README.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
This directory contains dockerfiles for large docker containers. This allows not to rebuild binaries every build and not to utilize cache.
|
||||
6
.github/builder_containers/entware-aarch64-3.10.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-aarch64-3.10.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/aarch64-3.10.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
6
.github/builder_containers/entware-armv7-2.6.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-armv7-2.6.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git -b k2.6
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/armv7-2.6.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
6
.github/builder_containers/entware-armv7-3.2.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-armv7-3.2.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/armv7-3.2.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
6
.github/builder_containers/entware-mips-3.4.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-mips-3.4.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/mips-3.4.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
6
.github/builder_containers/entware-mipsel-3.4.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-mipsel-3.4.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/mipsel-3.4.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
6
.github/builder_containers/entware-x64-3.2.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-x64-3.2.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/x64-3.2.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
6
.github/builder_containers/entware-x86-2.6.Dockerfile
vendored
Normal file
6
.github/builder_containers/entware-x86-2.6.Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM waujito/entware_builder
|
||||
RUN git clone --depth 1 https://github.com/Entware/Entware.git -b k2.6
|
||||
WORKDIR /home/me/Entware
|
||||
RUN make package/symlinks
|
||||
RUN cp -v configs/x86-2.6.config .config
|
||||
RUN make -j$(nproc) toolchain/install
|
||||
1
.github/builder_containers/entware_docker
vendored
Submodule
1
.github/builder_containers/entware_docker
vendored
Submodule
Submodule .github/builder_containers/entware_docker added at 90eb6bc0a4
12
.github/builder_containers/kernel-3.0.101.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-3.0.101.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:14.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.0.101.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
12
.github/builder_containers/kernel-3.10.108.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-3.10.108.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.10.108.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
12
.github/builder_containers/kernel-4.19.322.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-4.19.322.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.322.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
12
.github/builder_containers/kernel-4.4.302.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-4.4.302.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.302.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
12
.github/builder_containers/kernel-5.15.167.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-5.15.167.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.167.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
12
.github/builder_containers/kernel-5.4.284.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-5.4.284.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.284.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
12
.github/builder_containers/kernel-6.6.52.Dockerfile
vendored
Normal file
12
.github/builder_containers/kernel-6.6.52.Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev wget
|
||||
|
||||
RUN wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.52.tar.xz -O kernel.tar.xz
|
||||
RUN tar -xf kernel.tar.xz
|
||||
RUN rm -f kernel.tar.xz
|
||||
RUN /bin/bash -c "mv linux-* linux"
|
||||
|
||||
WORKDIR /linux
|
||||
RUN make defconfig
|
||||
RUN make -j$(nproc)
|
||||
128
.github/workflows/build-ci.yml
vendored
128
.github/workflows/build-ci.yml
vendored
@@ -10,18 +10,18 @@ on:
|
||||
- 'LICENSE'
|
||||
- 'README.md'
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.gh.outputs.version }}
|
||||
release: ${{ steps.gh.outputs.release }}
|
||||
sha: ${{ steps.gh.outputs.sha }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: 'openwrt'
|
||||
|
||||
- name: GH
|
||||
id: gh
|
||||
@@ -30,7 +30,8 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "version=$(cat youtubeUnblock/Makefile | grep PKG_VERSION | sed 's/PKG_VERSION:=//')" >> $GITHUB_OUTPUT
|
||||
echo "version=$(cat Makefile | grep "PKG_VERSION :=" | sed 's/PKG_VERSION := //')" >> $GITHUB_OUTPUT
|
||||
echo "release=$(cat Makefile | grep "PKG_RELEASE :=" | sed 's/PKG_RELEASE := //')" >> $GITHUB_OUTPUT
|
||||
if [[ "${{ github.event_name }}" != "pull_request" ]]; then
|
||||
echo "sha=$(echo ${GITHUB_SHA::7})" >> $GITHUB_OUTPUT
|
||||
else
|
||||
@@ -72,6 +73,7 @@ jobs:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
@@ -85,7 +87,7 @@ jobs:
|
||||
make -j$(nproc) CC="ccache gcc -static-libgcc -static" || exit 1
|
||||
strip -s build/youtubeUnblock
|
||||
cp -va build/youtubeUnblock .
|
||||
tar -czvf youtubeUnblock-$VERSION-$SHA-$PLATFORM-static.tar.gz youtubeUnblock youtubeUnblock.service README.md
|
||||
tar -czvf youtubeUnblock-$VERSION-$RELEASE-$SHA-$PLATFORM-static.tar.gz youtubeUnblock youtubeUnblock.service README.md
|
||||
ccache --show-stats
|
||||
|
||||
- name: Upload artifacts
|
||||
@@ -114,6 +116,8 @@ jobs:
|
||||
tool: mips-unknown-linux-musl
|
||||
- arch: mipssf
|
||||
tool: mips-unknown-linux-muslsf
|
||||
- arch: armv7sf
|
||||
tool: armv7-unknown-linux-musleabi
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -126,7 +130,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p $HOME/tools
|
||||
gh api repos/$REPO/releases/latest --jq '.tag_name' |\
|
||||
xargs -I{} wget -qO- https://github.com/$REPO/releases/download/{}/$TOOL.tgz | tar -C $HOME/tools -xz || exit 1
|
||||
xargs -I{} wget -qO- https://github.com/$REPO/releases/download/{}/$TOOL.tar.xz | tar -C $HOME/tools -xJ || exit 1
|
||||
[ -d "$HOME/tools/$TOOL/bin" ] && echo "$HOME/tools/$TOOL/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Build
|
||||
@@ -135,6 +139,7 @@ jobs:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
TOOL: ${{ matrix.tool }}
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
run: |
|
||||
make -j$(nproc) \
|
||||
@@ -146,13 +151,13 @@ jobs:
|
||||
CROSS_COMPILE_PLATFORM=$TOOL || exit 1
|
||||
$TOOL-strip -s build/youtubeUnblock
|
||||
cp -va build/youtubeUnblock .
|
||||
tar -czvf youtubeUnblock-$VERSION-$SHA-$ARCH-static.tar.gz youtubeUnblock youtubeUnblock.service README.md
|
||||
tar -czvf youtubeUnblock-$VERSION-$RELEASE-$SHA-$ARCH-static.tar.gz youtubeUnblock youtubeUnblock.service README.md
|
||||
|
||||
- name: Upload artifacts
|
||||
if: steps.build.outcome == 'success'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: static-${{ matrix.arch }}
|
||||
name: youtubeUnblock-static-${{ matrix.arch }}
|
||||
path: ./**/youtubeUnblock*.tar.gz
|
||||
|
||||
build-openwrt:
|
||||
@@ -201,14 +206,26 @@ jobs:
|
||||
- name: Prepare build
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
run: |
|
||||
sed -i "s/PKG_REV:=.*$/PKG_REV:=$SHA/;s/PKG_VERSION:=.*$/PKG_VERSION:=$VERSION-$SHA/" youtubeUnblock/Makefile
|
||||
sed -i "s/PKG_REV:=.*$/PKG_REV:=$SHA/;s/PKG_VERSION:=.*$/PKG_VERSION:=$VERSION-$RELEASE-$SHA/" youtubeUnblock/Makefile
|
||||
|
||||
- name: Initilalize SDK
|
||||
id: init_sdk
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
working-directory: /builder
|
||||
run: |
|
||||
HOME=/builder ./setup.sh
|
||||
|
||||
- name: Build packages
|
||||
id: build
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
working-directory: /builder
|
||||
run: |
|
||||
@@ -218,7 +235,7 @@ jobs:
|
||||
./scripts/feeds install -a -p youtubeUnblock
|
||||
make defconfig
|
||||
make package/youtubeUnblock/compile V=s
|
||||
mv $(find ./bin -type f -name 'youtubeUnblock*.ipk') ./youtubeUnblock-$VERSION-$SHA-${{ matrix.arch }}-${{ matrix.branch }}.ipk
|
||||
mv $(find ./bin -type f -name 'youtubeUnblock*.ipk') ./youtubeUnblock-$VERSION-$RELEASE-$SHA-${{ matrix.arch }}-${{ matrix.branch }}.ipk
|
||||
|
||||
- name: Upload packages
|
||||
if: steps.build.outcome == 'success'
|
||||
@@ -243,14 +260,26 @@ jobs:
|
||||
- name: Prepare build
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
run: |
|
||||
sed -i "s/PKG_REV:=.*$/PKG_REV:=$SHA/;s/PKG_VERSION:=.*$/PKG_VERSION:=$VERSION-$SHA/" youtubeUnblock/Makefile
|
||||
sed -i "s/PKG_REV:=.*$/PKG_REV:=$SHA/;s/PKG_VERSION:=.*$/PKG_VERSION:=$VERSION-$RELEASE-$SHA/" youtubeUnblock/Makefile
|
||||
|
||||
- name: Initilalize SDK
|
||||
id: init_sdk
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
working-directory: /builder
|
||||
run: |
|
||||
HOME=/builder ./setup.sh
|
||||
|
||||
- name: Build packages
|
||||
id: build
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
working-directory: /builder
|
||||
run: |
|
||||
@@ -260,7 +289,7 @@ jobs:
|
||||
./scripts/feeds install -a -p youtubeUnblock
|
||||
make defconfig
|
||||
make package/luci-app-youtubeUnblock/compile V=s
|
||||
mv $(find ./bin -type f -name 'luci-app-youtubeUnblock*.ipk') ./luci-app-youtubeUnblock-$VERSION-$SHA.ipk
|
||||
mv $(find ./bin -type f -name 'luci-app-youtubeUnblock*.ipk') ./luci-app-youtubeUnblock-$VERSION-$RELEASE-$SHA.ipk
|
||||
|
||||
- name: Upload packages
|
||||
if: steps.build.outcome == 'success'
|
||||
@@ -281,90 +310,53 @@ jobs:
|
||||
- mips-3.4
|
||||
- mipsel-3.4
|
||||
- x64-3.2
|
||||
- x86-2.6
|
||||
- armv7-2.6
|
||||
container:
|
||||
image: waujito/entware_builder:${{ matrix.arch }}
|
||||
options: --user root
|
||||
steps:
|
||||
- name: Set up Entware docker container
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/Entware/docker.git
|
||||
docker build docker --pull --tag builder
|
||||
docker volume create entware-home
|
||||
|
||||
- name: Restore Entware from cache
|
||||
id: cache-restore
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/entware
|
||||
key: entware-${{ matrix.arch }}
|
||||
|
||||
- name: Load Entware from cache
|
||||
if: steps.cache-restore.outputs.cache-hit == 'true'
|
||||
run: |
|
||||
docker run --rm --mount source=entware-home,target=/backup_vol -v ~/entware:/backup ubuntu tar -xf /backup/entware.tar -C /backup_vol
|
||||
docker run --rm --mount source=entware-home,target=/home/me -w /home/me ubuntu bash -c 'cp -r ./backup_vol/* ./'
|
||||
docker run --rm --mount source=entware-home,target=/home/me -w /home/me ubuntu bash -c 'chown -R 1000:1000 ./* ./'
|
||||
|
||||
- name: Build Entware
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -w /home/me --name builder builder git clone --depth 1 https://github.com/Entware/Entware.git
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -w /home/me/Entware --name builder builder make package/symlinks
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -w /home/me/Entware --name builder builder cp -v configs/${{ matrix.arch }}.config .config
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -w /home/me/Entware --name builder builder make -j$(nproc) toolchain/install
|
||||
docker run --rm --mount source=entware-home,target=/backup_vol -v ~/entware:/backup ubuntu tar -cf /backup/entware.tar /backup_vol
|
||||
|
||||
- name: Save Entware to cache
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
id: cache-save
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/entware
|
||||
key: entware-${{ matrix.arch }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: 'entware'
|
||||
ref: 'openwrt'
|
||||
|
||||
- name: Prepare build
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
run: |
|
||||
sed -i "s/PKG_REV:=.*$/PKG_REV:=$SHA/;s/PKG_VERSION:=.*$/PKG_VERSION:=$VERSION-$SHA/" youtubeUnblock/Makefile
|
||||
sed -i "s/PKG_REV:=.*$/PKG_REV:=$SHA/;s/PKG_VERSION:=.*$/PKG_VERSION:=$VERSION-$RELEASE-$SHA/" youtubeUnblock/Makefile
|
||||
|
||||
- name: Build packages
|
||||
id: build
|
||||
run: |
|
||||
echo "src-link youtubeUnblock /youtubeUnblock" | docker run --rm -i --mount source=entware-home,target=/home/me -v $GITHUB_WORKSPACE:/youtubeUnblock -w /home/me/Entware --name builder builder tee -a feeds.conf
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -v $GITHUB_WORKSPACE:/youtubeUnblock -w /home/me/Entware --name builder builder ./scripts/feeds update youtubeUnblock
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -v $GITHUB_WORKSPACE:/youtubeUnblock -w /home/me/Entware --name builder builder ./scripts/feeds install -a -p youtubeUnblock
|
||||
echo "CONFIG_PACKAGE_youtubeUnblock=m" | docker run --rm -i --mount source=entware-home,target=/home/me -v $GITHUB_WORKSPACE:/youtubeUnblock -w /home/me/Entware --name builder builder tee -a .config
|
||||
docker run --rm -i --mount source=entware-home,target=/home/me -v $GITHUB_WORKSPACE:/youtubeUnblock -w /home/me/Entware --name builder builder make package/youtubeUnblock/compile V=s
|
||||
|
||||
- name: Extract packages
|
||||
if: steps.build.outcome == 'success'
|
||||
shell: bash
|
||||
working-directory: /home/me/Entware
|
||||
env:
|
||||
VERSION: ${{ needs.prepare.outputs.version }}
|
||||
RELEASE: ${{ needs.prepare.outputs.release }}
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
run: |
|
||||
mkdir output
|
||||
docker run --rm --user root -i --mount source=entware-home,target=/home/me -v $(pwd):/target -w /home/me/Entware --name builder builder find ./bin -type f -name 'youtubeUnblock*.ipk' -exec cp -v {} /target/output \;
|
||||
rm -rf youtubeUnblock || true
|
||||
mkdir youtubeUnblock
|
||||
bash -c "cp -r ./output/* youtubeUnblock"
|
||||
tar -czvf youtubeUnblock-$VERSION-$SHA-${{ matrix.arch }}-entware.tar.gz youtubeUnblock
|
||||
echo "src-link youtubeUnblock $GITHUB_WORKSPACE" >> feeds.conf
|
||||
cat feeds.conf
|
||||
./scripts/feeds update youtubeUnblock
|
||||
./scripts/feeds install -a -p youtubeUnblock
|
||||
echo "CONFIG_PACKAGE_youtubeUnblockEntware=m" | tee -a .config
|
||||
make package/youtubeUnblockEntware/compile V=s
|
||||
|
||||
mv $(find ./bin -type f -name 'youtubeUnblockEntware*.ipk') ./youtubeUnblock-$VERSION-$RELEASE-$SHA-entware-${{ matrix.arch }}.ipk
|
||||
|
||||
- name: Upload packages
|
||||
if: steps.build.outcome == 'success'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: youtubeUnblock-entware-${{ matrix.arch }}
|
||||
path: ./**/youtubeUnblock*-entware.tar.gz
|
||||
path: /home/me/Entware/youtubeUnblock*.ipk
|
||||
if-no-files-found: error
|
||||
|
||||
pre-release:
|
||||
if: github.event_name != 'pull_request' && github.ref_name == 'main'
|
||||
needs: [build-static, build-static-cross, build-openwrt, build-entware]
|
||||
needs: [build-static, build-static-cross, build-openwrt, build-entware, build-openwrt-luci]
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
119
.github/workflows/test.yml
vendored
119
.github/workflows/test.yml
vendored
@@ -1,25 +1,16 @@
|
||||
# Tests whether the youtubeUnblock builds properly
|
||||
|
||||
name: "youtubeUnblock build test"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '.editorconfig'
|
||||
- '.gitignore'
|
||||
- 'LICENSE'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- '.editorconfig'
|
||||
- '.gitignore'
|
||||
- 'LICENSE'
|
||||
- 'README.md'
|
||||
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
@@ -85,104 +76,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- kernel_version: "6.6.52"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.52.tar.xz"
|
||||
container_version: "24.04"
|
||||
|
||||
- kernel_version: "5.15.167"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.167.tar.xz"
|
||||
container_version: "24.04"
|
||||
|
||||
- kernel_version: "5.4.284"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.284.tar.xz"
|
||||
container_version: "24.04"
|
||||
|
||||
- kernel_version: "4.19.322"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.322.tar.xz"
|
||||
container_version: "24.04"
|
||||
|
||||
- kernel_version: "4.4.302"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.302.tar.xz"
|
||||
container_version: "24.04"
|
||||
|
||||
- kernel_version: "3.10.108"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.10.108.tar.xz"
|
||||
container_version: "16.04"
|
||||
|
||||
- kernel_version: "3.0.101"
|
||||
source: "https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.0.101.tar.xz"
|
||||
container_version: "14.04"
|
||||
kernel_version:
|
||||
- 6.6.52
|
||||
- 5.15.167
|
||||
- 5.4.284
|
||||
- 4.19.322
|
||||
- 4.4.302
|
||||
- 3.10.108
|
||||
- 3.0.101
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Restore builder from cache
|
||||
id: cache-restore
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/builder.tar
|
||||
key: builder-${{ matrix.kernel_version }}
|
||||
|
||||
- name: Load builder from cache
|
||||
if: steps.cache-restore.outputs.cache-hit == 'true'
|
||||
run: |
|
||||
docker import - builder < ~/builder.tar
|
||||
|
||||
- name: Prepare build env
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir ~/linux
|
||||
pwd
|
||||
ls /
|
||||
ls ~
|
||||
|
||||
- name: Obtain kernel
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd ~/linux
|
||||
wget ${{ matrix.source }} -O kernel.tar.xz -q
|
||||
tar -xf kernel.tar.xz
|
||||
rm -f kernel.tar.xz
|
||||
/bin/bash -c "mv linux-* linux"
|
||||
ls
|
||||
ls linux
|
||||
|
||||
- name: Install docker
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd ~/linux
|
||||
docker pull ubuntu:${{ matrix.container_version }}
|
||||
docker container create --name ubu_builder -w / ubuntu:${{ matrix.container_version }} tail -f /dev/null
|
||||
docker container start ubu_builder
|
||||
docker container exec ubu_builder bash -c "apt update && apt install -y build-essential flex bc bison libelf-dev elfutils libssl-dev"
|
||||
docker cp ./linux ubu_builder:/linux
|
||||
|
||||
- name: Build kernel
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd ~/linux
|
||||
docker container exec -w /linux ubu_builder bash -c 'make defconfig'
|
||||
docker container exec -w /linux ubu_builder bash -c 'make -j $(nproc)'
|
||||
|
||||
- name: Export container
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd ~/linux
|
||||
docker container kill ubu_builder
|
||||
docker container export ubu_builder > ubu_builder.tar
|
||||
docker container rm ubu_builder
|
||||
mv ./ubu_builder.tar ~/builder.tar
|
||||
docker import - builder < ~/builder.tar
|
||||
|
||||
- name: Save kernel image to cache
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
id: cache-save
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/builder.tar
|
||||
key: builder-${{ matrix.kernel_version }}
|
||||
|
||||
- name: Build kernel module
|
||||
id: build
|
||||
env:
|
||||
@@ -190,7 +95,7 @@ jobs:
|
||||
SHA: ${{ needs.prepare.outputs.sha }}
|
||||
shell: bash
|
||||
run: |
|
||||
docker run --rm -v ./:/youtubeUnblock -w /youtubeUnblock builder make kmake KERNEL_BUILDER_MAKEDIR:=/linux
|
||||
docker run --rm -v ./:/youtubeUnblock -w /youtubeUnblock waujito/kernel-bins:${{ matrix.kernel_version }} make kmake KERNEL_BUILDER_MAKEDIR:=/linux
|
||||
tar -czvf kmod-youtubeUnblock-$VERSION-$SHA-linux-${{ matrix.kernel_version }}.tar.gz kyoutubeUnblock.ko
|
||||
|
||||
- name: Upload artifacts
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule ".github/builder_containers/entware_docker"]
|
||||
path = .github/builder_containers/entware_docker
|
||||
url = https://github.com/Entware/docker.git
|
||||
2
Kbuild
2
Kbuild
@@ -1,3 +1,3 @@
|
||||
obj-m := kyoutubeUnblock.o
|
||||
kyoutubeUnblock-objs := kytunblock.o mangle.o quic.o utils.o kargs.o tls.o
|
||||
kyoutubeUnblock-objs := kytunblock.o mangle.o quic.o utils.o kargs.o tls.o getopt.o args.o
|
||||
ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement
|
||||
|
||||
7
Makefile
7
Makefile
@@ -1,6 +1,13 @@
|
||||
USPACE_TARGETS := default all install uninstall dev run_dev
|
||||
KMAKE_TARGETS := kmake kload kunload kreload xmod xtclean
|
||||
|
||||
PKG_VERSION := 1.0.0
|
||||
PKG_RELEASE := 5
|
||||
|
||||
PKG_FULLVERSION := $(PKG_VERSION)-$(PKG_RELEASE)
|
||||
|
||||
export PKG_VERSION PKG_RELEASE PKG_FULLVERSION
|
||||
|
||||
.PHONY: $(USPACE_TARGETS) $(KMAKE_TARGETS) clean
|
||||
$(USPACE_TARGETS):
|
||||
@$(MAKE) -f uspace.mk $@
|
||||
|
||||
30
Padavan.md
Normal file
30
Padavan.md
Normal file
@@ -0,0 +1,30 @@
|
||||
## Padavan
|
||||
На падаване есть раздел, доступный для записи (/etc/storage), и, докинув нужные модули, можно запустить youtubeUblock на уже установленной прошивке без USB. Установка самого youtubeUblock мало будет отличаться от классичкской установки. Наибольшая сложность заключается в получении модулей ядра специально для вашего роутера.
|
||||
|
||||
**Версия youtubeUblock должна быть не меньше v1.0.0-rc4.**
|
||||
|
||||
### Сборка прошивки с модулями
|
||||
|
||||
Необходимо собрать ядро с модулями nfqueue. Собирать можно у себя локально, а можно и в github actions (https://github.com/shvchk/padavan-builder-workflow)
|
||||
|
||||
Добавить строки ниже в `padavan-ng/trunk/configs/boards/TPLINK/TL_C5-V4/kernel-3.4.x.config` (вместо TPLINK/TL_C5-V4 нужно выбрать свою модель):
|
||||
|
||||
```sh
|
||||
CONFIG_NETFILTER_NETLINK=m
|
||||
CONFIG_NETFILTER_NETLINK_QUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_IP_NF_QUEUE=m
|
||||
CONFIG_IP6_NF_QUEUE=m
|
||||
```
|
||||
|
||||
Сборка
|
||||
```sh
|
||||
cd padavan-ng/trunk
|
||||
cp configs/templates/tplink/tl_c5-v4.config .config
|
||||
./build_firmware.sh
|
||||
```
|
||||
Если финальный размер превышает максимум, то можно отключить что-нибудь в .config, например FTP.
|
||||
|
||||
После сборки необходимо установить прошивку на роутер. Подробнее в гитлабе падавана: https://gitlab.com/hadzhioglu/padavan-ng. Как устанавливать: https://4pda.to/forum/index.php?showtopic=975687&st=12980#Spoil-115912586-5
|
||||
|
||||
Далее скачать youtubeUnblock, закинуть его на роутер, добавить правила фаервола и запустить. Можно скачивать static бинарник и запускать вручную, а можно загрузить entware на usb или в память, и поставить соответствующую версию youtubeUblock.
|
||||
120
README.md
120
README.md
@@ -9,6 +9,7 @@
|
||||
- [IPv6](#ipv6)
|
||||
- [Check it](#check-it)
|
||||
- [Flags](#flags)
|
||||
- [UDP](#udp)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [TV](#tv)
|
||||
- [Troubleshooting EPERMS (Operation not permitted)](#troubleshooting-eperms-operation-not-permitted)
|
||||
@@ -21,6 +22,7 @@
|
||||
- [Building on host system](#building-on-host-system)
|
||||
- [Building on any kernel](#building-on-any-kernel)
|
||||
- [Building with openwrt SDK](#building-with-openwrt-sdk)
|
||||
- [Padavan](#padavan)
|
||||
|
||||
|
||||
# youtubeUnblock
|
||||
@@ -87,28 +89,40 @@ Now we go to the configuration. For OpenWRT here is configuration via [UCI](http
|
||||
|
||||
For **LuCI** aka **GUI** aka **web-interface of router** you should install **luci-app-youtubeUnblock** package like you did it with the normal youtubeUnblock package. Note, that lists of official opkg feeds should be loaded (**Do it with Update lists option**).
|
||||
|
||||
If you got ` * pkg_hash_check_unresolved: cannot find dependency luci-lua-runtime for luci-app-youtubeUnblock` error, you are using old openwrt. Install [this dummy package](https://github.com/xiaorouji/openwrt-passwall/files/12605732/luci-lua-runtime_all_fake.zip). [Check this comment](https://github.com/Waujito/youtubeUnblock/issues/168#issuecomment-2449227547) for more details.
|
||||
|
||||
LuCI configuration lives in **Services->youtubeUnblock** section. It is self descriptive, with description for each flag. Note, that after you push `Save & Apply` button, the configuration is applied automatically and the service is restarted.
|
||||
|
||||
UCI configuration is available in /etc/config/youtubeUnblock file, in section `youtubeUnblock.youtubeUnblock`. The configuration is done with [flags](#flags). Note, that names of flags are not the same: you should replace `-` with `_`, you shouldn't use leading `--` for flag. Also you will enable toggle flags (without parameters) with `1`.
|
||||
UCI configuration is available in /etc/config/youtubeUnblock file, in section `youtubeUnblock.youtubeUnblock`. You may pass any args as a string to parameter `args`, but before it disable interactive flags (You can configurate with it but it is a way harder and I recommend to use it only with `luci-app-youtubeUnblock`):
|
||||
|
||||
For example, to enable trace logs you should do
|
||||
```sh
|
||||
uci set youtubeUnblock.youtubeUnblock.trace=1
|
||||
uci set youtubeUnblock.youtubeUnblock.conf_strat="args"
|
||||
uci set youtubeUnblock.youtubeUnblock.args="--queue-num=537 --threads=1"
|
||||
```
|
||||
|
||||
You can check the logs in CLI mode with `logread -l 200 | grep youtubeUnblock` command.
|
||||
To save the configs you should do `uci commit` and then `reload_config` to restart youtubeUnblock
|
||||
|
||||
For uci, to save the configs you should do `uci commit` and then `reload_config` to restart the youtubeUnblock
|
||||
|
||||
You can check the logs in CLI mode with `logread -l 200 | grep youtubeUnblock` command.
|
||||
|
||||
In CLI mode you will use youtubeUnblock as a normal init.d service:
|
||||
for example, you can enable it with `/etc/init.d/youtubeUnblock enable`.
|
||||
|
||||
### Entware
|
||||
|
||||
For Entware on Keenetic here is an [installation guide (russian)](https://help.keenetic.com/hc/ru/articles/360021214160-%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F-Entware-%D0%BD%D0%B0-USB-%D0%BD%D0%B0%D0%BA%D0%BE%D0%BF%D0%B8%D1%82%D0%B5%D0%BB%D1%8C). Note that if your Entware router is missing netfilter queue kernel modules, here is no way to deal with it since Entware does not offer kernel modules.
|
||||
For Entware on Keenetic here is an [installation guide (russian)](https://help.keenetic.com/hc/ru/articles/360021214160-%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F-Entware-%D0%BD%D0%B0-USB-%D0%BD%D0%B0%D0%BA%D0%BE%D0%BF%D0%B8%D1%82%D0%B5%D0%BB%D1%8C).
|
||||
|
||||
Install the binary with `opkg install youtubeUnblock-*.ipk`. After installation, the binary in /opt/bin and the init script in /opt/etc/init.d/S51youtubeUnblock will be available. To run the youtubeUnblock, simply run `/opt/etc/init.d/S51youtubeUnblock start`
|
||||
|
||||
### NFNETLINK_QUEUE kernel modules
|
||||
|
||||
Note, that you should feed the target kernel with nfnetlink_queue kernel module. The module may be disabled or even not present. Entware S51youtubeUnblock will try to insert kmods any way but if they are not provided by software, you should install them manually. AFAIK on keenetics here is a repository with modules compiled by customer. You can find them somewhere in the web interface of your device. On other routers you may want to do deeper research in that case and find your kmods. If you can't find anything, you may ask the customer for GPL codes of linux kernel (and may be even OpenWRT) and compile kmods manually.
|
||||
|
||||
You should insert the module with (this step may be omitted on Entware and OpenWRT):
|
||||
```sh
|
||||
modprobe nfnetlink_queue
|
||||
```
|
||||
|
||||
### PC configuration
|
||||
On local host make sure to change **FORWARD** to **OUTPUT** chain in the following Firewall rulesets.
|
||||
|
||||
@@ -121,7 +135,8 @@ Copy `youtubeUnblock.service` to `/usr/lib/systemd/system` (you should change th
|
||||
On nftables you should put next nftables rules:
|
||||
```sh
|
||||
nft add chain inet fw4 youtubeUnblock '{ type filter hook postrouting priority mangle - 1; policy accept; }'
|
||||
nft add rule inet fw4 youtubeUnblock 'meta l4proto { tcp, udp } th dport 443 ct original packets < 20 counter queue num 537 bypass'
|
||||
nft add rule inet fw4 youtubeUnblock 'tcp dport 443 ct original packets < 20 counter queue num 537 bypass'
|
||||
nft add rule inet fw4 youtubeUnblock 'meta l4proto udp ct original packets < 9 counter queue num 537 bypass'
|
||||
nft insert rule inet fw4 output 'mark and 0x8000 == 0x8000 counter accept'
|
||||
```
|
||||
|
||||
@@ -131,7 +146,7 @@ On iptables you should put next iptables rules:
|
||||
```sh
|
||||
iptables -t mangle -N YOUTUBEUNBLOCK
|
||||
iptables -t mangle -A YOUTUBEUNBLOCK -p tcp --dport 443 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
|
||||
iptables -t mangle -A YOUTUBEUNBLOCK -p udp --dport 443 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
|
||||
iptables -t mangle -A YOUTUBEUNBLOCK -p udp -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:8 -j NFQUEUE --queue-num 537 --queue-bypass
|
||||
iptables -t mangle -A POSTROUTING -j YOUTUBEUNBLOCK
|
||||
iptables -I OUTPUT -m mark --mark 32768/32768 -j ACCEPT
|
||||
```
|
||||
@@ -142,7 +157,7 @@ For IPv6 on iptables you need to duplicate rules above for ip6tables:
|
||||
```sh
|
||||
ip6tables -t mangle -N YOUTUBEUNBLOCK
|
||||
ip6tables -t mangle -A YOUTUBEUNBLOCK -p tcp --dport 443 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
|
||||
ip6tables -t mangle -A YOUTUBEUNBLOCK -p udp --dport 443 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
|
||||
ip6tables -t mangle -A YOUTUBEUNBLOCK -p udp -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:8 -j NFQUEUE --queue-num 537 --queue-bypass
|
||||
ip6tables -t mangle -A POSTROUTING -j YOUTUBEUNBLOCK
|
||||
ip6tables -I OUTPUT -m mark --mark 32768/32768 -j ACCEPT
|
||||
```
|
||||
@@ -172,13 +187,37 @@ curl -o/dev/null -k --connect-to ::google.com -k -L -H Host:\ mirror.gcr.io http
|
||||
Put flags to the **BINARY**, not an init script. If you are on OpenWRT you should put the flags inside the script: open `/etc/init.d/youtubeUnblock` with any text editor, like vi or nano and put your flags after `procd_set_param command /usr/bin/youtubeUnblock` line.
|
||||
|
||||
Available flags:
|
||||
|
||||
- `--sni-domains=<comma separated domain list>|all` List of domains you want to be handled by SNI. Use this string if you want to change default domain list. Defaults to `googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,googleapis.com,googleusercontent.com,gstatic.com,l.google.com`. You can pass **all** if you want for every *ClientHello* to be handled. You can exclude some domains with `--exclude-domains` flag.
|
||||
|
||||
- `--exclude-domains=<comma separated domain list>` List of domains to be excluded from targetting.
|
||||
#### General flags
|
||||
Flags that do not scoped to a specific section, used over all the youtubeUnblock
|
||||
|
||||
- `--queue-num=<number of netfilter queue>` The number of netfilter queue **youtubeUnblock** will be linked to. Defaults to **537**.
|
||||
|
||||
- `--silent` Disables verbose mode.
|
||||
|
||||
- `--trace` Maximum verbosity for debugging purposes.
|
||||
|
||||
- `--no-gso` Disables support for Google Chrome fat packets which uses GSO. This feature is well tested now, so this flag probably won't fix anything.
|
||||
|
||||
- `--no-ipv6` Disables support for ipv6. May be useful if you don't want for ipv6 socket to be opened.
|
||||
|
||||
- `--threads=<threads number>` Specifies the amount of threads you want to be running for your program. This defaults to **1** and shouldn't be edited for normal use. But if you really want multiple queue instances of youtubeUnblock, note that you should change --queue-num to --queue balance. For example, with 4 threads, use `--queue-balance 537:540` on iptables and `queue num 537-540` on nftables.
|
||||
|
||||
- `--connbytes-limit=<pkts>` **Kernel module only!** Specify how much packets of connection should be processed by kyoutubeUnblock. Pass 0 if you want for each packet to be processed. This flag may be useful for UDP traffic since unlimited youtubeUnblock may lead to traffic flood and unexpected bans. Defaults to 5. In most cases you don't want to change it.
|
||||
|
||||
- `--daemonize` Daemonizes the youtubeUnblock (forks and detaches it from the shell). Terminate the program with `killall youtubeUnblock`. If you want to track the logs of youtubeUnblock in logread or journalctl, use **--syslog** flag.
|
||||
|
||||
- `--syslog` Redirects logs to the system log. You can read it with `journalctl` or `logread`.
|
||||
|
||||
- `--noclose` Usable only with `--daemonize`. Will not redirect io streams to /dev/null.
|
||||
|
||||
- `--packet-mark=<mark>` Use this option if youtubeUnblock conflicts with other systems rely on packet mark. Note that you may want to change accept rule for iptables to follow the mark.
|
||||
|
||||
#### Section scoped flags
|
||||
|
||||
- `--fbegin` and `--fend` flags: youtubeUnblock supports multiple sets of strategies for specific filters. You may want to initiate a new set after the default one, like: `--sni-domains=googlevideo.com --faking-strategy=md5sum --fbegin --sni-domains=youtube.com --faking-strategy=tcp_check --fbegin --sni-domains=l.google.com --faking-strategy=pastseq`. Note, that the priority of these sets goes backwards: last is first, default (one that does not start with --fbegin) is last. If you start the new section, the default settings are implemented just like youtubeUnblock without any parameters. Note that the config above is just an example and won't work for you.
|
||||
|
||||
- `--tls={enabled|disabled}` Set it if you want not to process TLS traffic in current section. May be used if you want to set only UDP-based section. (Here section is a unit between `--fbegin` and `--fend` flags).
|
||||
|
||||
- `--fake-sni={0|1}` This flag enables fake-sni which forces **youtubeUnblock** to send at least three packets instead of one with TLS *ClientHello*: Fake *ClientHello*, 1st part of original *ClientHello*, 2nd part of original *ClientHello*. This flag may be related to some Operation not permitted error messages, so before open an issue refer to [Troubleshooting for EPERMS](#troubleshooting-eperms-operation-not-permitted). Defaults to **1**.
|
||||
|
||||
- `--fake-sni-seq-len=<length>` This flag specifies **youtubeUnblock** to build a complicated construction of fake client hello packets. length determines how much fakes will be sent. Defaults to **1**.
|
||||
@@ -187,7 +226,7 @@ Available flags:
|
||||
- `--fake-custom-payload=<payload>` Useful with `--fake-sni-type=custom`. You should specify the payload for fake message manually. Use hex format: `--fake-custom-payload=0001020304` mean that 5 bytes sequence: `0x00`, `0x01`, `0x02`, `0x03`, `0x04` used as fake.
|
||||
|
||||
- `--faking-strategy={randseq|ttl|tcp_check|pastseq|md5sum}` This flag determines the strategy of fake packets invalidation. Defaults to `randseq`
|
||||
- `randseq` specifies that random sequence/acknowledgemend random will be set. This option may be handled by provider which uses *conntrack* with drop on invalid *conntrack* state firewall rule enabled.
|
||||
- `randseq` specifies that random sequence/acknowledgment random will be set. This option may be handled by provider which uses *conntrack* with drop on invalid *conntrack* state firewall rule enabled.
|
||||
- `ttl` specifies that packet will be invalidated after `--faking-ttl=n` hops. `ttl` is better but may cause issues if unconfigured.
|
||||
- `pastseq` is like `randseq` but sequence number is not random but references the packet sent in the past (before current).
|
||||
- `tcp_check` will invalidate faking packet with invalid checksum. May be handled and dropped by some providers/TSPUs.
|
||||
@@ -207,8 +246,6 @@ Available flags:
|
||||
|
||||
- `--frag-sni-pos=<pos>` With this option **youtubeUnblock** will split the packet at the position pos. Defaults to 1.
|
||||
|
||||
- `--quic-drop` Drop all QUIC packets which goes to youtubeUnblock. Won't affect any other UDP packets. Suitable for some TVs. Note, that for this option to work you should also add proxy udp to youtubeUnblock in firewall. `connbytes` may also be used with udp.
|
||||
|
||||
- `--fk-winsize=<winsize>` Specifies window size for the fragmented TCP packet. Applicable if you want for response to be fragmented. May slowdown connection initialization.
|
||||
|
||||
- `--synfake={1|0}` If 1, syn payload will be sent before each request. The idea is taken from syndata from zapret project. Syn payload will normally be discarded by endpoint but may be handled by TSPU. This option sends normal fake in that payload. Please note, that the option works for all the sites, so --sni-domains won't change anything.
|
||||
@@ -219,19 +256,25 @@ Available flags:
|
||||
|
||||
- `--seg2delay=<delay>` This flag forces **youtubeUnblock** to wait a little bit before send the 2nd part of the split packet.
|
||||
|
||||
- `--silent` Disables verbose mode.
|
||||
- `--sni-domains=<comma separated domain list>|all` List of domains you want to be handled by SNI. Use this string if you want to change default domain list. Defaults to `googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,googleapis.com,googleusercontent.com,gstatic.com,l.google.com`. You can pass **all** if you want for every *ClientHello* to be handled. You can exclude some domains with `--exclude-domains` flag.
|
||||
|
||||
- `--trace` Maximum verbosity for debugging purposes.
|
||||
- `--exclude-domains=<comma separated domain list>` List of domains to be excluded from targeting.
|
||||
|
||||
- `--no-gso` Disables support for Google Chrome fat packets which uses GSO. This feature is well tested now, so this flag probably won't fix anything.
|
||||
- `--udp-mode={drop|fake}` This flag specifies udp handling strategy. If drop udp packets will be dropped (useful for quic when browser can fallback to tcp), if fake udp will be faked. Defaults to fake.
|
||||
|
||||
- `--no-ipv6` Disables support for ipv6. May be useful if you don't want for ipv6 socket to be opened.
|
||||
- `--udp-fake-seq-len=<amount of faking packets sent>` Specifies how much faking packets will be sent over the network. Defaults to 6.
|
||||
|
||||
- `--threads=<threads number>` Specifies the amount of threads you want to be running for your program. This defaults to **1** and shouldn't be edited for normal use. If you have performance issues, consult [performance chaptr](https://github.com/Waujito/youtubeUnblock?tab=readme-ov-file#performance)
|
||||
- `--udp-fake-len=<size of udp fake>` Size of udp fake payload (typically payload is zeroes). Defaults to 64.
|
||||
|
||||
- `--packet-mark=<mark>` Use this option if youtubeUnblock conflicts with other systems rely on packet mark. Note that you may want to change accept rule for iptables to follow the mark.
|
||||
- `--udp-dport-filter=<5,6,200-500>` Filter the UDP destination ports. Defaults to no ports. Specifie the ports you want to be handled by youtubeUnblock.
|
||||
|
||||
- `--fbegin` and `--fend` flags: youtubeUnblock supports multiple sets of strategies for specific filters. You may want to initiate a new set after the default one, like: `--sni-domains=googlevideo.com --faking-strategy=md5sum --fbegin --sni-domains=youtube.com --faking-strategy=tcp_check --fend --fbegin --sni-domains=l.google.com --faking-strategy=pastseq --fend`. Note, that the priority of these sets goes backwards: last is first, default (one that does not start with --fbegin) is last. If you start the new section, the default settings are implemented just like youtubeUnblock without any parameters. Note that the config above is just an example and won't work for you.
|
||||
- `--udp-filter-quic={disabled|all}` Enables QUIC filtering for UDP handler. If disabled, quic won't be processed, if all, all quic initial packets will be handled. Defaults to disabled.
|
||||
|
||||
- `--quic-drop` Drop all QUIC packets which goes to youtubeUnblock. Won't affect any other UDP packets. Just an alias for `--udp-filter-quic=all --udp-mode=drop`.
|
||||
|
||||
## UDP
|
||||
|
||||
UDP is another communication protocol. Well-known technologies that use it are DNS, QUIC, voice chats. UDP does not provide reliable connection and its header is much simpler than TCP thus fragmentation is limited. The support provided primarily by faking. For QUIC faking may not work well, so use `--quic-drop` if you want to drop all quic traffic. For other technologies I recommend to configure UDP support in the separate section from TCP, like `--fbegin --udp-dport-filter=50000-50099 --tls=disabled`. See more in flags related to udp and [issues tagged with udp label](https://github.com/Waujito/youtubeUnblock/issues?q=label%3Audp+).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -242,6 +285,8 @@ If you have troubles with some sites being proxied, you can play with flags valu
|
||||
|
||||
If you are on Chromium you may have to disable *kyber* (the feature that makes the TLS *ClientHello* very big). I've got the problem with it on router, so to escape possible errors, so it is better to disable it: in `chrome://flags` search for kyber and switch it to disabled state. Alternatively you may set `--sni-detection=brute` and probably adjust `--sni-domains` flag.
|
||||
|
||||
*Kyber* on firefox disables with `security.tls.enable_kyber` in `about:config`.
|
||||
|
||||
If your browser is using QUIC it may not work properly. Disable it in Chrome in `chrome://flags` and in Firefox `network.http.http{2,3}.enable(d)` in `about:config` option.
|
||||
|
||||
It seems like some TSPUs started to block wrongseq packets, so you should play around with faking strategies. I personally recommend to start with `md5sum` faking strategy.
|
||||
@@ -323,24 +368,20 @@ When compilation is done, the binary file will be in build directory. Copy it to
|
||||
|
||||
This section describes the kernel module version of youtubeUnblock. The kernel module operates as a normal module inside the kernel and integrates within the netfilter stack to statelessly mangle the packets sent over the Internet.
|
||||
|
||||
You can configure the module with its flags in insmod:
|
||||
```
|
||||
insmod kyoutubeUnblock.ko fake_sni=1 exclude_domains=.ru quic_drop=1
|
||||
```
|
||||
You can configure the module with its flags:
|
||||
|
||||
Note that the flags names are different from ones used for the regular youtubeUnblock(right like in UCI configuration for OpenWRT): replace `-` with `_` and no leading `--`. Also to configure togglers you should set them to `1` (`quic_drop=1`)
|
||||
|
||||
Also a good thig to mention is verbosity. The kernel module combines --trace and --silent option to the one parameter `verbosity`. This parameter accepts 3 arguments: `trace`, `debug` and `silent`. I highly don't recommend to enable `trace` mod on router because it may cause huge problems with performance and even freeze your device.
|
||||
|
||||
Also a drop in replacement is supported for all the parameters excluding packet mark. A drop in replacement does not require module restart if you want to change the parameters. You can specify and check the parameters within module's directory inside the sysfs: `/sys/module/kyoutubeUnblock/parameters/`. For example, to set quic_drop to true you may use next command:
|
||||
```sh
|
||||
echo 1 | sudo tee /sys/module/kyoutubeUnblock/parameters/quic_drop
|
||||
insmod kyoutubeUnblock.ko
|
||||
echo "--fake_sni=1 --exclude_domains=.ru --quic_drop" | sudo tee /sys/module/kyoutubeUnblock/parameters/parameters
|
||||
```
|
||||
and
|
||||
|
||||
You can also do
|
||||
|
||||
```sh
|
||||
cat /sys/module/kyoutubeUnblock/parameters/quic_drop
|
||||
cat /sys/module/kyoutubeUnblock/parameters/parameters
|
||||
```
|
||||
to check the parameter.
|
||||
|
||||
and check all the parameters configured.
|
||||
|
||||
### Building kernel module
|
||||
|
||||
@@ -381,4 +422,11 @@ make package/kyoutubeUnblock/compile V=s
|
||||
|
||||
When the commands finish, the module is ready. Find it with `find bin -name "kmod-youtubeUnblock*.ipk"`, copy to your host and install to the router via gui software interface. The module should start immediately. If not, do `modprobe kyoutubeUnblock`.
|
||||
|
||||
|
||||
## Padavan
|
||||
YoutubeUnblock may also run on Padavan. [Check the manual here\[rus\]](Padavan.md)
|
||||
|
||||
|
||||
>If you have any questions/suggestions/problems feel free to open an [issue](https://github.com/Waujito/youtubeUnblock/issues).
|
||||
|
||||
|
||||
|
||||
18
args.h
18
args.h
@@ -1,11 +1,23 @@
|
||||
#ifndef ARGS_H
|
||||
#define ARGS_H
|
||||
#include "types.h"
|
||||
#include "config.h"
|
||||
|
||||
void print_version();
|
||||
void print_version(void);
|
||||
void print_usage(const char *argv0);
|
||||
int parse_args(int argc, char *argv[]);
|
||||
int yparse_args(int argc, char *argv[]);
|
||||
size_t print_config(char *buffer, size_t buffer_size);
|
||||
|
||||
// Initializes configuration storage.
|
||||
int init_config(struct config_t *config);
|
||||
// Allocates and initializes configuration section.
|
||||
int init_section_config(struct section_config_t **section, struct section_config_t *prev);
|
||||
// Frees configuration section
|
||||
void free_config_section(struct section_config_t *config);
|
||||
// Frees sections under config
|
||||
void free_config(struct config_t config);
|
||||
|
||||
/* Prints starting messages */
|
||||
void print_welcome();
|
||||
void print_welcome(void);
|
||||
|
||||
#endif /* ARGS_H */
|
||||
|
||||
166
config.h
166
config.h
@@ -5,7 +5,7 @@
|
||||
#define USER_SPACE
|
||||
#endif
|
||||
|
||||
#include "raw_replacements.h"
|
||||
#include "types.h"
|
||||
|
||||
typedef int (*raw_send_t)(const unsigned char *data, unsigned int data_len);
|
||||
/**
|
||||
@@ -20,9 +20,28 @@ struct instance_config_t {
|
||||
};
|
||||
extern struct instance_config_t instance_config;
|
||||
|
||||
struct udp_dport_range {
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
};
|
||||
|
||||
struct domains_list {
|
||||
char *domain_name;
|
||||
uint16_t domain_len;
|
||||
|
||||
struct domains_list *next;
|
||||
};
|
||||
|
||||
struct section_config_t {
|
||||
const char *domains_str;
|
||||
unsigned int domains_strlen;
|
||||
int id;
|
||||
struct section_config_t *next;
|
||||
struct section_config_t *prev;
|
||||
|
||||
struct domains_list *sni_domains;
|
||||
struct domains_list *exclude_sni_domains;
|
||||
unsigned int all_domains;
|
||||
|
||||
int tls_enabled;
|
||||
|
||||
int fragmentation_strategy;
|
||||
int frag_sni_reverse;
|
||||
@@ -40,21 +59,15 @@ struct section_config_t {
|
||||
#define FAKE_PAYLOAD_DEFAULT 2
|
||||
int fake_sni_type;
|
||||
|
||||
int quic_drop;
|
||||
|
||||
/* In milliseconds */
|
||||
unsigned int seg2_delay;
|
||||
int synfake;
|
||||
unsigned int synfake_len;
|
||||
|
||||
const char *exclude_domains_str;
|
||||
unsigned int exclude_domains_strlen;
|
||||
unsigned int all_domains;
|
||||
|
||||
const char *fake_sni_pkt;
|
||||
unsigned int fake_sni_pkt_sz;
|
||||
|
||||
const char *fake_custom_pkt;
|
||||
char *fake_custom_pkt;
|
||||
unsigned int fake_custom_pkt_sz;
|
||||
|
||||
unsigned int fk_winsize;
|
||||
@@ -64,7 +77,14 @@ struct section_config_t {
|
||||
#define SNI_DETECTION_BRUTE 1
|
||||
int sni_detection;
|
||||
|
||||
int udp_mode;
|
||||
unsigned int udp_fake_seq_len;
|
||||
unsigned int udp_fake_len;
|
||||
int udp_faking_strategy;
|
||||
|
||||
struct udp_dport_range *udp_dport_range;
|
||||
int udp_dport_range_len;
|
||||
int udp_filter_quic;
|
||||
};
|
||||
|
||||
#define MAX_CONFIGLIST_LEN 64
|
||||
@@ -75,54 +95,28 @@ struct config_t {
|
||||
int use_gso;
|
||||
int use_ipv6;
|
||||
unsigned int mark;
|
||||
int daemonize;
|
||||
// Same as daemon() noclose
|
||||
int noclose;
|
||||
int syslog;
|
||||
|
||||
int connbytes_limit;
|
||||
|
||||
#define VERBOSE_INFO 0
|
||||
#define VERBOSE_DEBUG 1
|
||||
#define VERBOSE_TRACE 2
|
||||
int verbose;
|
||||
|
||||
struct section_config_t default_config;
|
||||
struct section_config_t custom_configs[MAX_CONFIGLIST_LEN];
|
||||
int custom_configs_len;
|
||||
struct section_config_t *first_section;
|
||||
struct section_config_t *last_section;
|
||||
};
|
||||
|
||||
extern struct config_t config;
|
||||
|
||||
#define ITER_CONFIG_SECTIONS(section) \
|
||||
for (struct section_config_t *section = &config.default_config + config.custom_configs_len; section >= &config.default_config; section--)
|
||||
#define ITER_CONFIG_SECTIONS(config, section) \
|
||||
for (struct section_config_t *section = (config)->last_section; section != NULL; section = section->prev)
|
||||
|
||||
#define CONFIG_SECTION_NUMBER(section) (int)((section) - &config.default_config)
|
||||
|
||||
#define default_section_config { \
|
||||
.frag_sni_reverse = 1, \
|
||||
.frag_sni_faked = 0, \
|
||||
.fragmentation_strategy = FRAGMENTATION_STRATEGY, \
|
||||
.faking_strategy = FAKING_STRATEGY, \
|
||||
.faking_ttl = FAKE_TTL, \
|
||||
.fake_sni = 1, \
|
||||
.fake_sni_seq_len = 1, \
|
||||
.fake_sni_type = FAKE_PAYLOAD_DEFAULT, \
|
||||
.frag_middle_sni = 1, \
|
||||
.frag_sni_pos = 1, \
|
||||
.fakeseq_offset = 10000, \
|
||||
.synfake = 0, \
|
||||
.synfake_len = 0, \
|
||||
.quic_drop = 0, \
|
||||
\
|
||||
.seg2_delay = 0, \
|
||||
\
|
||||
.domains_str = defaul_snistr, \
|
||||
.domains_strlen = sizeof(defaul_snistr), \
|
||||
\
|
||||
.exclude_domains_str = "", \
|
||||
.exclude_domains_strlen = 0, \
|
||||
\
|
||||
.fake_sni_pkt = fake_sni_old, \
|
||||
.fake_sni_pkt_sz = sizeof(fake_sni_old) - 1, \
|
||||
.fake_custom_pkt = custom_fake_buf, \
|
||||
.fake_custom_pkt_sz = 0, \
|
||||
.sni_detection = SNI_DETECTION_PARSE, \
|
||||
}
|
||||
#define CONFIG_SECTION_NUMBER(section) ((section)->id)
|
||||
|
||||
#define MAX_THREADS 16
|
||||
|
||||
@@ -162,8 +156,9 @@ for (struct section_config_t *section = &config.default_config + config.custom_c
|
||||
#define FAKE_STRAT_PAST_SEQ (1 << 2)
|
||||
#define FAKE_STRAT_TCP_CHECK (1 << 3)
|
||||
#define FAKE_STRAT_TCP_MD5SUM (1 << 4)
|
||||
#define FAKE_STRAT_UDP_CHECK (1 << 5)
|
||||
|
||||
#define FAKE_STRAT_COUNT 5
|
||||
#define FAKE_STRAT_COUNT 6
|
||||
|
||||
/**
|
||||
* This macros iterates through all faking strategies and executes code under it.
|
||||
@@ -185,7 +180,7 @@ if ((fake_bitmask) & strategy)
|
||||
|
||||
// The Maximum Transmission Unit size for rawsocket
|
||||
// Larger packets will be fragmented. Applicable for Chrome's kyber.
|
||||
#define AVAILABLE_MTU 1500
|
||||
#define AVAILABLE_MTU 1400
|
||||
|
||||
#define DEFAULT_QUEUE_NUM 537
|
||||
|
||||
@@ -193,6 +188,77 @@ if ((fake_bitmask) & strategy)
|
||||
|
||||
#define DEFAULT_SNISTR "googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,googleapis.com,googleusercontent.com,gstatic.com,l.google.com"
|
||||
|
||||
static const char defaul_snistr[] = DEFAULT_SNISTR;
|
||||
static const char default_snistr[] = DEFAULT_SNISTR;
|
||||
|
||||
enum {
|
||||
UDP_MODE_DROP,
|
||||
UDP_MODE_FAKE,
|
||||
};
|
||||
|
||||
enum {
|
||||
UDP_FILTER_QUIC_DISABLED,
|
||||
UDP_FILTER_QUIC_ALL,
|
||||
};
|
||||
|
||||
#define default_section_config { \
|
||||
.sni_domains = NULL, \
|
||||
.exclude_sni_domains = NULL, \
|
||||
.all_domains = 0, \
|
||||
.tls_enabled = 1, \
|
||||
.frag_sni_reverse = 1, \
|
||||
.frag_sni_faked = 0, \
|
||||
.fragmentation_strategy = FRAGMENTATION_STRATEGY, \
|
||||
.faking_strategy = FAKING_STRATEGY, \
|
||||
.faking_ttl = FAKE_TTL, \
|
||||
.fake_sni = 1, \
|
||||
.fake_sni_seq_len = 1, \
|
||||
.fake_sni_type = FAKE_PAYLOAD_DEFAULT, \
|
||||
.fake_custom_pkt = NULL, \
|
||||
.fake_custom_pkt_sz = 0, \
|
||||
.frag_middle_sni = 1, \
|
||||
.frag_sni_pos = 1, \
|
||||
.fakeseq_offset = 10000, \
|
||||
.synfake = 0, \
|
||||
.synfake_len = 0, \
|
||||
\
|
||||
.seg2_delay = 0, \
|
||||
\
|
||||
.sni_detection = SNI_DETECTION_PARSE, \
|
||||
\
|
||||
.udp_mode = UDP_MODE_FAKE, \
|
||||
.udp_fake_seq_len = 6, \
|
||||
.udp_fake_len = 64, \
|
||||
.udp_faking_strategy = FAKE_STRAT_UDP_CHECK, \
|
||||
.udp_dport_range = NULL, \
|
||||
.udp_dport_range_len = 0, \
|
||||
.udp_filter_quic = UDP_FILTER_QUIC_DISABLED, \
|
||||
\
|
||||
.prev = NULL, \
|
||||
.next = NULL, \
|
||||
.id = 0, \
|
||||
}
|
||||
|
||||
#define default_config_set { \
|
||||
.threads = THREADS_NUM, \
|
||||
.queue_start_num = DEFAULT_QUEUE_NUM, \
|
||||
.mark = DEFAULT_RAWSOCKET_MARK, \
|
||||
.use_ipv6 = 1, \
|
||||
.connbytes_limit = 8, \
|
||||
\
|
||||
.verbose = VERBOSE_DEBUG, \
|
||||
.use_gso = 1, \
|
||||
\
|
||||
.first_section = NULL, \
|
||||
.last_section = NULL, \
|
||||
\
|
||||
.daemonize = 0, \
|
||||
.noclose = 0, \
|
||||
.syslog = 0, \
|
||||
}
|
||||
|
||||
#define CONFIG_SET(config) \
|
||||
struct config_t config = default_config_set; \
|
||||
config->last_section = &(config.default_config) \
|
||||
|
||||
|
||||
#endif /* YTB_CONFIG_H */
|
||||
|
||||
204
getopt.c
Normal file
204
getopt.c
Normal file
@@ -0,0 +1,204 @@
|
||||
#include "types.h"
|
||||
#include "logging.h"
|
||||
#include "getopt.h"
|
||||
|
||||
char *optarg;
|
||||
int optind=1, opterr=1, optopt, __optpos, optreset=0;
|
||||
|
||||
#define optpos __optpos
|
||||
|
||||
static void __getopt_msg(const char *b, const char *c, size_t l)
|
||||
{
|
||||
lgerr("%s %.*s\n", b, (int)l, c);
|
||||
}
|
||||
|
||||
int getopt(int argc, char * const argv[], const char *optstring)
|
||||
{
|
||||
int i, c, d;
|
||||
int k, l;
|
||||
char *optchar;
|
||||
|
||||
if (!optind || optreset) {
|
||||
optreset = 0;
|
||||
__optpos = 0;
|
||||
optind = 1;
|
||||
}
|
||||
|
||||
if (optind >= argc || !argv[optind])
|
||||
return -1;
|
||||
|
||||
if (argv[optind][0] != '-') {
|
||||
if (optstring[0] == '-') {
|
||||
optarg = argv[optind++];
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!argv[optind][1])
|
||||
return -1;
|
||||
|
||||
if (argv[optind][1] == '-' && !argv[optind][2])
|
||||
return optind++, -1;
|
||||
|
||||
if (!optpos) optpos++;
|
||||
c = argv[optind][optpos], k = 1;
|
||||
optchar = argv[optind]+optpos;
|
||||
optopt = c;
|
||||
optpos += k;
|
||||
|
||||
if (!argv[optind][optpos]) {
|
||||
optind++;
|
||||
optpos = 0;
|
||||
}
|
||||
|
||||
if (optstring[0] == '-' || optstring[0] == '+')
|
||||
optstring++;
|
||||
|
||||
i = 0;
|
||||
d = 0;
|
||||
do {
|
||||
d = optstring[i], l = 1;
|
||||
if (l>0) i+=l; else i++;
|
||||
} while (l && d != c);
|
||||
|
||||
if (d != c) {
|
||||
if (optstring[0] != ':' && opterr)
|
||||
__getopt_msg("Unrecognized option: ", optchar, k);
|
||||
return '?';
|
||||
}
|
||||
if (optstring[i] == ':') {
|
||||
if (optstring[i+1] == ':') optarg = 0;
|
||||
else if (optind >= argc) {
|
||||
if (optstring[0] == ':') return ':';
|
||||
if (opterr) __getopt_msg("Option requires an argument: ",
|
||||
optchar, k);
|
||||
return '?';
|
||||
}
|
||||
if (optstring[i+1] != ':' || optpos) {
|
||||
optarg = argv[optind++] + optpos;
|
||||
optpos = 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static void permute(char *const *argv, int dest, int src)
|
||||
{
|
||||
char **av = (char **)argv;
|
||||
char *tmp = av[src];
|
||||
int i;
|
||||
for (i=src; i>dest; i--)
|
||||
av[i] = av[i-1];
|
||||
av[dest] = tmp;
|
||||
}
|
||||
|
||||
static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
|
||||
{
|
||||
optarg = 0;
|
||||
if (longopts && argv[optind][0] == '-' &&
|
||||
((longonly && argv[optind][1] && argv[optind][1] != '-') ||
|
||||
(argv[optind][1] == '-' && argv[optind][2])))
|
||||
{
|
||||
int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
|
||||
int i, cnt, match = -1;
|
||||
char *opt;
|
||||
for (cnt=i=0; longopts[i].name; i++) {
|
||||
const char *name = longopts[i].name;
|
||||
opt = argv[optind]+1;
|
||||
if (*opt == '-') opt++;
|
||||
for (; *name && *name == *opt; name++, opt++);
|
||||
if (*opt && *opt != '=') continue;
|
||||
match = i;
|
||||
if (!*name) {
|
||||
cnt = 1;
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
if (cnt==1) {
|
||||
i = match;
|
||||
optind++;
|
||||
optopt = longopts[i].val;
|
||||
if (*opt == '=') {
|
||||
if (!longopts[i].has_arg) {
|
||||
if (colon || !opterr)
|
||||
return '?';
|
||||
__getopt_msg(
|
||||
"Option does not take an argument: ",
|
||||
longopts[i].name,
|
||||
strlen(longopts[i].name));
|
||||
return '?';
|
||||
}
|
||||
optarg = opt+1;
|
||||
} else if (longopts[i].has_arg == required_argument) {
|
||||
if (!(optarg = argv[optind])) {
|
||||
if (colon) return ':';
|
||||
if (!opterr) return '?';
|
||||
__getopt_msg(
|
||||
"Option requires an argument: ",
|
||||
longopts[i].name,
|
||||
strlen(longopts[i].name));
|
||||
return '?';
|
||||
}
|
||||
optind++;
|
||||
}
|
||||
if (idx) *idx = i;
|
||||
if (longopts[i].flag) {
|
||||
*longopts[i].flag = longopts[i].val;
|
||||
return 0;
|
||||
}
|
||||
return longopts[i].val;
|
||||
}
|
||||
if (argv[optind][1] == '-') {
|
||||
if (!colon && opterr)
|
||||
__getopt_msg(cnt ?
|
||||
"Option is ambiguous: " :
|
||||
"Unrecognized option: ",
|
||||
argv[optind]+2,
|
||||
strlen(argv[optind]+2));
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
return getopt(argc, argv, optstring);
|
||||
}
|
||||
|
||||
static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
|
||||
{
|
||||
int ret, skipped, resumed;
|
||||
if (!optind || optreset) {
|
||||
optreset = 0;
|
||||
__optpos = 0;
|
||||
optind = 1;
|
||||
}
|
||||
if (optind >= argc || !argv[optind]) return -1;
|
||||
skipped = optind;
|
||||
if (optstring[0] != '+' && optstring[0] != '-') {
|
||||
int i;
|
||||
for (i=optind; ; i++) {
|
||||
if (i >= argc || !argv[i]) return -1;
|
||||
if (argv[i][0] == '-' && argv[i][1]) break;
|
||||
}
|
||||
optind = i;
|
||||
}
|
||||
resumed = optind;
|
||||
ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
|
||||
if (resumed > skipped) {
|
||||
int i, cnt = optind-resumed;
|
||||
for (i=0; i<cnt; i++)
|
||||
permute(argv, skipped, optind-1);
|
||||
optind = skipped + cnt;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
|
||||
{
|
||||
return __getopt_long(argc, argv, optstring, longopts, idx, 0);
|
||||
}
|
||||
|
||||
int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
|
||||
{
|
||||
return __getopt_long(argc, argv, optstring, longopts, idx, 1);
|
||||
}
|
||||
45
getopt.h
Normal file
45
getopt.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2005-2014 Rich Felker, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
#define _GETOPT_H
|
||||
|
||||
int getopt(int, char * const [], const char *);
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt, optreset;
|
||||
|
||||
struct option {
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
int getopt_long(int, char *const *, const char *, const struct option *, int *);
|
||||
int getopt_long_only(int, char *const *, const char *, const struct option *, int *);
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#endif
|
||||
2
kmake.mk
2
kmake.mk
@@ -13,7 +13,7 @@ KERNEL_BUILDER_MAKEDIR:=/lib/modules/$(shell uname -r)/build
|
||||
kmake: kmod
|
||||
|
||||
kmod:
|
||||
$(MAKE) -C $(KERNEL_BUILDER_MAKEDIR) M=$(PWD) modules
|
||||
$(MAKE) -C $(KERNEL_BUILDER_MAKEDIR) M=$(PWD) EXTRA_CFLAGS='-DPKG_VERSION=\"$(PKG_FULLVERSION)\"' modules
|
||||
|
||||
kload:
|
||||
insmod kyoutubeUnblock.ko
|
||||
|
||||
122
kytunblock.c
122
kytunblock.c
@@ -16,13 +16,20 @@
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_acct.h>
|
||||
|
||||
#include "mangle.h"
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "logging.h"
|
||||
#include "args.h"
|
||||
|
||||
#if defined(PKG_VERSION)
|
||||
MODULE_VERSION(PKG_VERSION);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.3.2");
|
||||
MODULE_AUTHOR("Vadim Vetrov <vetrovvd@gmail.com>");
|
||||
MODULE_DESCRIPTION("Linux kernel module for youtubeUnblock");
|
||||
|
||||
@@ -35,7 +42,7 @@ static int open_raw_socket(void) {
|
||||
ret = sock_create(AF_INET, SOCK_RAW, IPPROTO_RAW, &rawsocket);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_alert("Unable to create raw socket\n");
|
||||
lgerror(ret, "Unable to create raw socket\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -80,7 +87,7 @@ static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) {
|
||||
iov.iov_base = (__u8 *)pkt;
|
||||
iov.iov_len = pktlen;
|
||||
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_flags = MSG_DONTWAIT;
|
||||
msg.msg_name = &daddr;
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in);
|
||||
msg.msg_control = NULL;
|
||||
@@ -97,7 +104,7 @@ static int open_raw6_socket(void) {
|
||||
ret = sock_create(AF_INET6, SOCK_RAW, IPPROTO_RAW, &raw6socket);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_alert("Unable to create raw socket\n");
|
||||
lgerror(ret, "Unable to create raw socket\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -140,7 +147,7 @@ static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) {
|
||||
iov.iov_base = (__u8 *)pkt;
|
||||
iov.iov_len = pktlen;
|
||||
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_flags = MSG_DONTWAIT;
|
||||
msg.msg_name = &daddr;
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
||||
msg.msg_control = NULL;
|
||||
@@ -159,12 +166,12 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
||||
|
||||
NETBUF_ALLOC(buff1, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(buff1)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NETBUF_ALLOC(buff2, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(buff2)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
NETBUF_FREE(buff2);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -203,9 +210,9 @@ erret_lc:
|
||||
int ipvx = netproto_version(pkt, pktlen);
|
||||
|
||||
if (ipvx == IP4VERSION) {
|
||||
return send_raw_ipv4(pkt, pktlen);
|
||||
ret = send_raw_ipv4(pkt, pktlen);
|
||||
} else if (ipvx == IP6VERSION) {
|
||||
return send_raw_ipv6(pkt, pktlen);
|
||||
ret = send_raw_ipv6(pkt, pktlen);
|
||||
} else {
|
||||
printf("proto version %d is unsupported\n", ipvx);
|
||||
return -EINVAL;
|
||||
@@ -216,7 +223,7 @@ erret_lc:
|
||||
}
|
||||
|
||||
static int delay_packet_send(const unsigned char *data, unsigned int data_len, unsigned int delay_ms) {
|
||||
pr_info("delay_packet_send won't work on current youtubeUnblock version");
|
||||
lginfo("delay_packet_send won't work on current youtubeUnblock version");
|
||||
return send_raw_socket(data, data_len);
|
||||
}
|
||||
|
||||
@@ -225,6 +232,32 @@ struct instance_config_t instance_config = {
|
||||
.send_delayed_packet = delay_packet_send,
|
||||
};
|
||||
|
||||
static int connbytes_pkts(const struct sk_buff *skb) {
|
||||
const struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
u_int64_t pkts = 0;
|
||||
const struct nf_conn_counter *counters;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (!ct)
|
||||
return -1;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
|
||||
const struct nf_conn_acct *acct;
|
||||
acct = nf_conn_acct_find(ct);
|
||||
if (!acct)
|
||||
return -1;
|
||||
counters = acct->counter;
|
||||
#else
|
||||
counters = nf_conn_acct_find(ct);
|
||||
if (!counters)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
|
||||
|
||||
return pkts;
|
||||
}
|
||||
|
||||
/* If this is a Red Hat-based kernel (Red Hat, CentOS, Fedora, etc)... */
|
||||
#ifdef RHEL_RELEASE_CODE
|
||||
@@ -304,9 +337,12 @@ static NF_CALLBACK(ykb_nf_hook, skb) {
|
||||
if (skb->len > MAX_PACKET_SIZE)
|
||||
goto accept;
|
||||
|
||||
if (config.connbytes_limit != 0 && connbytes_pkts(skb) > config.connbytes_limit)
|
||||
goto accept;
|
||||
|
||||
ret = skb_linearize(skb);
|
||||
if (ret < 0) {
|
||||
lgerror("Cannot linearize", ret);
|
||||
lgerror(ret, "Cannot linearize");
|
||||
goto accept;
|
||||
}
|
||||
|
||||
@@ -343,45 +379,57 @@ static struct nf_hook_ops ykb6_nf_reg __read_mostly = {
|
||||
|
||||
static int __init ykb_init(void) {
|
||||
int ret = 0;
|
||||
ret = init_config(&config);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret = open_raw_socket();
|
||||
if (ret < 0) goto err;
|
||||
|
||||
|
||||
if (config.use_ipv6) {
|
||||
ret = open_raw6_socket();
|
||||
if (ret < 0) goto close_rawsocket;
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
|
||||
struct net *n;
|
||||
for_each_net(n) {
|
||||
ret = nf_register_net_hook(n, &ykb6_nf_reg);
|
||||
if (ret < 0)
|
||||
lgerror("bad rat",ret);
|
||||
}
|
||||
#else
|
||||
nf_register_hook(&ykb6_nf_reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
|
||||
struct net *n;
|
||||
|
||||
for_each_net(n) {
|
||||
ret = nf_register_net_hook(n, &ykb_nf_reg);
|
||||
if (ret < 0)
|
||||
lgerror("bad rat",ret);
|
||||
if (ret < 0) {
|
||||
lgerror(ret, "register net_hook");
|
||||
}
|
||||
}
|
||||
#else
|
||||
nf_register_hook(&ykb_nf_reg);
|
||||
ret = nf_register_hook(&ykb_nf_reg);
|
||||
if (ret < 0) {
|
||||
lgerror(ret, "register net_hook");
|
||||
}
|
||||
#endif
|
||||
|
||||
pr_info("youtubeUnblock kernel module started.\n");
|
||||
|
||||
if (config.use_ipv6) {
|
||||
ret = open_raw6_socket();
|
||||
if (ret < 0) {
|
||||
config.use_ipv6 = 0;
|
||||
lgwarning("ipv6 disabled!");
|
||||
goto ipv6_fallback;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
|
||||
struct net *n;
|
||||
for_each_net(n) {
|
||||
ret = nf_register_net_hook(n, &ykb6_nf_reg);
|
||||
if (ret < 0) {
|
||||
lgerror(ret, "register net6_hook");
|
||||
}
|
||||
}
|
||||
#else
|
||||
ret = nf_register_hook(&ykb6_nf_reg);
|
||||
if (ret < 0) {
|
||||
lgerror(ret, "register net6_hook");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ipv6_fallback:
|
||||
lginfo("youtubeUnblock kernel module started.\n");
|
||||
return 0;
|
||||
|
||||
close_rawsocket:
|
||||
close_raw_socket();
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -407,7 +455,9 @@ static void __exit ykb_destroy(void) {
|
||||
#endif
|
||||
|
||||
close_raw_socket();
|
||||
pr_info("youtubeUnblock kernel module destroyed.\n");
|
||||
|
||||
free_config(config);
|
||||
lginfo("youtubeUnblock kernel module destroyed.\n");
|
||||
}
|
||||
|
||||
module_init(ykb_init);
|
||||
|
||||
46
logging.h
46
logging.h
@@ -9,36 +9,62 @@
|
||||
#include <linux/module.h>
|
||||
#define printf pr_info
|
||||
#define perror pr_err
|
||||
#define lgerror(msg, ret, ...) __extension__ ({ \
|
||||
pr_err(msg ": %d\n", ##__VA_ARGS__, ret); \
|
||||
})
|
||||
|
||||
#define LOG_ERR KERN_ERR
|
||||
#define LOG_INFO KERN_INFO
|
||||
#define LOG_WARN KERN_WARNING
|
||||
|
||||
#define log_message(level, msg, ...) \
|
||||
(printk(level msg, ##__VA_ARGS__))
|
||||
|
||||
#define lgerror(ret, msg, ...) \
|
||||
(log_message(LOG_ERR, msg ": %d\n", ##__VA_ARGS__, ret))
|
||||
|
||||
#else
|
||||
#include <stdio.h> // IWYU pragma: export
|
||||
#include <errno.h>
|
||||
#define lgerror(msg, ret, ...) __extension__ ({ \
|
||||
#include <syslog.h>
|
||||
|
||||
#define log_message(level, msg, ...) \
|
||||
(config.syslog ? (void)(syslog((level), msg, ##__VA_ARGS__)) : (void)(printf(msg, ##__VA_ARGS__)))
|
||||
|
||||
#define lgerror(ret, msg, ...) __extension__ ({ \
|
||||
errno = -(ret); \
|
||||
printf(msg ": %s\n", ##__VA_ARGS__, strerror(errno)); \
|
||||
log_message(LOG_ERR, msg ": %s\n", ##__VA_ARGS__, strerror(errno)); \
|
||||
})
|
||||
#endif /* PROGRAM_SPACE */
|
||||
|
||||
#define lgerr(msg, ...) \
|
||||
(log_message(LOG_ERR, msg, ##__VA_ARGS__))
|
||||
|
||||
#define lgwarning(msg, ...) \
|
||||
(log_message(LOG_WARN, msg, ##__VA_ARGS__))
|
||||
|
||||
|
||||
#define lginfo(msg, ...) \
|
||||
(log_message(LOG_INFO, msg, ##__VA_ARGS__))
|
||||
|
||||
#define print_message(...) \
|
||||
(lginfo(__VA_ARGS__))
|
||||
|
||||
#define lgdebug(msg, ...) \
|
||||
(LOG_LEVEL >= VERBOSE_DEBUG ? printf(msg, ##__VA_ARGS__) : 0)
|
||||
(LOG_LEVEL >= VERBOSE_DEBUG ? log_message(LOG_INFO, msg, ##__VA_ARGS__) : (void)0)
|
||||
|
||||
#define lgdebugmsg(msg, ...) lgdebug(msg "\n", ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define lgtrace(msg, ...) \
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? printf(msg, ##__VA_ARGS__) : 0)
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, msg, ##__VA_ARGS__) : (void)0)
|
||||
|
||||
#define lgtracemsg(msg, ...) lgtrace(msg "\n", __VA_ARGS__)
|
||||
|
||||
#define lgtrace_start(msg, ...) \
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? printf("[TRACE] " msg " ( ", ##__VA_ARGS__) : 0)
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, "[TRACE] " msg " ( ", ##__VA_ARGS__) : (void)0)
|
||||
|
||||
#define lgtrace_addp(msg, ...) \
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? printf(msg", ", ##__VA_ARGS__) : 0)
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, msg", ", ##__VA_ARGS__) : (void)0)
|
||||
|
||||
#define lgtrace_end() \
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? printf(") \n") : 0)
|
||||
(LOG_LEVEL >= VERBOSE_TRACE ? log_message(LOG_INFO, ") \n") : (void)0)
|
||||
|
||||
#endif /* LOGGING_H */
|
||||
|
||||
185
mangle.c
185
mangle.c
@@ -62,7 +62,7 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
||||
lgtrace_addp("UDP");
|
||||
|
||||
|
||||
ITER_CONFIG_SECTIONS(section) {
|
||||
ITER_CONFIG_SECTIONS(&config, section) {
|
||||
lgtrace_addp("Section #%d", CONFIG_SECTION_NUMBER(section));
|
||||
|
||||
switch (transport_proto) {
|
||||
@@ -74,16 +74,32 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (verdict == PKT_CONTINUE)
|
||||
if (verdict == PKT_CONTINUE) {
|
||||
lgtrace_addp("continue_flow");
|
||||
continue;
|
||||
}
|
||||
|
||||
lgtrace_end();
|
||||
return verdict;
|
||||
goto ret_verdict;
|
||||
}
|
||||
|
||||
accept:
|
||||
verdict = PKT_ACCEPT;
|
||||
|
||||
ret_verdict:
|
||||
|
||||
switch (verdict) {
|
||||
case PKT_ACCEPT:
|
||||
lgtrace_addp("accept");
|
||||
break;
|
||||
case PKT_DROP:
|
||||
lgtrace_addp("drop");
|
||||
break;
|
||||
default:
|
||||
lgtrace_addp("unknow verdict: %d", verdict);
|
||||
}
|
||||
lgtrace_end();
|
||||
return PKT_ACCEPT;
|
||||
|
||||
return verdict;
|
||||
}
|
||||
|
||||
int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, uint32_t raw_payload_len) {
|
||||
@@ -112,7 +128,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
|
||||
NETBUF_ALLOC(payload, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(payload)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
goto accept;
|
||||
}
|
||||
|
||||
@@ -142,7 +158,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
|
||||
ret = instance_config.send_raw_packet(payload, iph_len + tcph_len + fake_len);
|
||||
if (ret < 0) {
|
||||
lgerror("send_syn_altered", ret);
|
||||
lgerror(ret, "send_syn_altered");
|
||||
|
||||
NETBUF_FREE(payload);
|
||||
goto accept;
|
||||
@@ -154,6 +170,9 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
|
||||
if (tcph->syn) goto continue_flow;
|
||||
|
||||
if (!section->tls_enabled)
|
||||
goto continue_flow;
|
||||
|
||||
struct tls_verdict vrd = analyze_tls_data(section, data, dlen);
|
||||
lgtrace_addp("TLS analyzed");
|
||||
|
||||
@@ -167,7 +186,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
uint32_t payload_len = raw_payload_len;
|
||||
NETBUF_ALLOC(payload, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(payload)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
goto accept;
|
||||
}
|
||||
|
||||
@@ -185,7 +204,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
&data, &dlen);
|
||||
|
||||
if (ret < 0) {
|
||||
lgerror("tcp_payload_split in targ_sni", ret);
|
||||
lgerror(ret, "tcp_payload_split in targ_sni");
|
||||
goto accept_lc;
|
||||
}
|
||||
|
||||
@@ -201,7 +220,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
&iph, &iph_len, &tcph, &tcph_len,
|
||||
&data, &dlen);
|
||||
if (ret < 0) {
|
||||
lgerror("seqovl_packet delta %d", ret, delta);
|
||||
lgerror(ret, "seqovl_packet delta %d", delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +260,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
|
||||
ret = send_tcp_frags(section, payload, payload_len, poses, cnt, 0);
|
||||
if (ret < 0) {
|
||||
lgerror("tcp4 send frags", ret);
|
||||
lgerror(ret, "tcp4 send frags");
|
||||
goto accept_lc;
|
||||
}
|
||||
|
||||
@@ -275,20 +294,20 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra
|
||||
|
||||
ret = send_ip4_frags(section, payload, payload_len, poses, cnt, 0);
|
||||
if (ret < 0) {
|
||||
lgerror("ip4 send frags", ret);
|
||||
lgerror(ret, "ip4 send frags");
|
||||
goto accept_lc;
|
||||
}
|
||||
|
||||
goto drop_lc;
|
||||
} else {
|
||||
printf("WARNING: IP fragmentation is supported only for IPv4\n");
|
||||
lginfo("WARNING: IP fragmentation is supported only for IPv4\n");
|
||||
goto default_send;
|
||||
}
|
||||
default:
|
||||
default_send:
|
||||
ret = instance_config.send_raw_packet(payload, payload_len);
|
||||
if (ret < 0) {
|
||||
lgerror("raw pack send", ret);
|
||||
lgerror(ret, "raw pack send");
|
||||
goto accept_lc;
|
||||
}
|
||||
|
||||
@@ -309,13 +328,10 @@ drop_lc:
|
||||
}
|
||||
|
||||
continue_flow:
|
||||
lgtrace_addp("continue_flow");
|
||||
return PKT_CONTINUE;
|
||||
accept:
|
||||
lgtrace_addp("accept");
|
||||
return PKT_ACCEPT;
|
||||
drop:
|
||||
lgtrace_addp("drop");
|
||||
return PKT_DROP;
|
||||
}
|
||||
|
||||
@@ -325,7 +341,6 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk
|
||||
const struct udphdr *udph;
|
||||
const uint8_t *data;
|
||||
uint32_t dlen;
|
||||
int ipver = netproto_version(pkt, pktlen);
|
||||
|
||||
int ret = udp_payload_split((uint8_t *)pkt, pktlen,
|
||||
(void **)&iph, &iph_len,
|
||||
@@ -338,84 +353,66 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk
|
||||
goto accept;
|
||||
}
|
||||
|
||||
if (dlen > 10 && config.verbose >= VERBOSE_TRACE) {
|
||||
printf("UDP payload start: [ ");
|
||||
if (dlen > 10 && config.verbose == VERBOSE_TRACE) {
|
||||
char logging_buf[128];
|
||||
char *bufpt = logging_buf;
|
||||
bufpt += sprintf(bufpt, "UDP payload start: [ ");
|
||||
for (int i = 0; i < 10; i++) {
|
||||
printf("%02x ", data[i]);
|
||||
bufpt += sprintf(bufpt, "%02x ", data[i]);
|
||||
}
|
||||
printf("], ");
|
||||
bufpt += sprintf(bufpt, "]");
|
||||
lgtrace_addp("%s", logging_buf);
|
||||
}
|
||||
|
||||
|
||||
if (section->quic_drop) {
|
||||
lgtrace_addp("QUIC probe");
|
||||
const struct quic_lhdr *qch;
|
||||
uint32_t qch_len;
|
||||
struct quic_cids qci;
|
||||
uint8_t *quic_raw_payload;
|
||||
uint32_t quic_raw_plen;
|
||||
ret = quic_parse_data((uint8_t *)data, dlen,
|
||||
(struct quic_lhdr **)&qch, &qch_len, &qci,
|
||||
&quic_raw_payload, &quic_raw_plen);
|
||||
|
||||
if (ret < 0) {
|
||||
lgtrace_addp("undefined type");
|
||||
goto accept_quic;
|
||||
}
|
||||
|
||||
lgtrace_addp("QUIC detected");
|
||||
uint8_t qtype = qch->type;
|
||||
if (!detect_udp_filtered(section, pkt, pktlen))
|
||||
goto continue_flow;
|
||||
|
||||
if (section->udp_mode == UDP_MODE_DROP)
|
||||
goto drop;
|
||||
|
||||
if (qch->version == QUIC_V1)
|
||||
qtype = quic_convtype_v1(qtype);
|
||||
else if (qch->version == QUIC_V2)
|
||||
qtype = quic_convtype_v2(qtype);
|
||||
|
||||
if (qtype != QUIC_INITIAL_TYPE) {
|
||||
lgtrace_addp("quic message type: %d", qtype);
|
||||
goto accept_quic;
|
||||
}
|
||||
|
||||
lgtrace_addp("quic initial message");
|
||||
}
|
||||
|
||||
/*
|
||||
if (1) {
|
||||
lgtrace_addp("Probe udp");
|
||||
if (ipver == IP4VERSION && ntohs(udph->dest) > 30) {
|
||||
lgtrace_addp("udp fool");
|
||||
const uint8_t *payload;
|
||||
uint32_t payload_len;
|
||||
|
||||
uint32_t poses[10];
|
||||
int cnt = 3;
|
||||
|
||||
poses[0] = 8;
|
||||
for (int i = 1; i < cnt; i++) {
|
||||
poses[i] = poses[i - 1] + 8;
|
||||
else if (section->udp_mode == UDP_MODE_FAKE) {
|
||||
for (int i = 0; i < section->udp_fake_seq_len; i++) {
|
||||
NETBUF_ALLOC(fake_udp, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(fake_udp)) {
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
uint32_t fsn_len = MAX_PACKET_SIZE;
|
||||
|
||||
ret = send_ip4_frags(pkt, pktlen, poses, cnt, 0);
|
||||
struct udp_fake_type fake_type = {
|
||||
.fake_len = section->udp_fake_len,
|
||||
.strategy = {
|
||||
.strategy = section->udp_faking_strategy,
|
||||
},
|
||||
};
|
||||
ret = gen_fake_udp(fake_type, iph, iph_len, udph, fake_udp, &fsn_len);
|
||||
if (ret < 0) {
|
||||
lgerror("ip4 send frags", ret);
|
||||
goto accept;
|
||||
lgerror(ret, "gen_fake_udp");
|
||||
goto erret_lc;
|
||||
}
|
||||
|
||||
goto drop;
|
||||
} else {
|
||||
printf("WARNING: IP fragmentation is supported only for IPv4\n");
|
||||
lgtrace_addp("post fake udp #%d", i + 1);
|
||||
|
||||
ret = instance_config.send_raw_packet(fake_udp, fsn_len);
|
||||
if (ret < 0) {
|
||||
lgerror(ret, "send fake udp");
|
||||
goto erret_lc;
|
||||
}
|
||||
|
||||
NETBUF_FREE(fake_udp);
|
||||
continue;
|
||||
erret_lc:
|
||||
NETBUF_FREE(fake_udp);
|
||||
goto accept;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
ret = instance_config.send_raw_packet(pkt, pktlen);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
continue_flow:
|
||||
lgtrace_addp("continue_flow");
|
||||
return PKT_CONTINUE;
|
||||
accept_quic:
|
||||
accept:
|
||||
return PKT_ACCEPT;
|
||||
drop:
|
||||
@@ -442,33 +439,35 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet
|
||||
} else {
|
||||
NETBUF_ALLOC(frag1, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(frag1)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
NETBUF_ALLOC(frag2, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(frag2)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
NETBUF_FREE(frag1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
NETBUF_ALLOC(fake_pad, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(fake_pad)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
NETBUF_FREE(frag1);
|
||||
NETBUF_FREE(frag2);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*/
|
||||
|
||||
uint32_t f1len = MAX_PACKET_SIZE;
|
||||
uint32_t f2len = MAX_PACKET_SIZE;
|
||||
uint32_t fake_pad_len = MAX_PACKET_SIZE;
|
||||
// uint32_t fake_pad_len = MAX_PACKET_SIZE;
|
||||
|
||||
int ret;
|
||||
|
||||
if (dvs > poses[0]) {
|
||||
lgerror("send_frags: Recursive dvs(%d) is more than poses0(%d)", -EINVAL, dvs, poses[0]);
|
||||
lgerror(-EINVAL, "send_frags: Recursive dvs(%d) is more than poses0(%d)", dvs, poses[0]);
|
||||
ret = -EINVAL;
|
||||
goto erret_lc;
|
||||
}
|
||||
@@ -480,7 +479,7 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet
|
||||
frag1, &f1len, frag2, &f2len);
|
||||
|
||||
if (ret < 0) {
|
||||
lgerror("send_frags: frag: with context packet with size %d, position: %d, recursive dvs: %d", ret, pktlen, poses[0], dvs);
|
||||
lgerror(ret, "send_frags: frag: with context packet with size %d, position: %d, recursive dvs: %d", pktlen, poses[0], dvs);
|
||||
goto erret_lc;
|
||||
}
|
||||
|
||||
@@ -539,12 +538,12 @@ send_frag2:
|
||||
out_lc:
|
||||
NETBUF_FREE(frag1);
|
||||
NETBUF_FREE(frag2);
|
||||
NETBUF_FREE(fake_pad);
|
||||
// NETBUF_FREE(fake_pad);
|
||||
goto out;
|
||||
erret_lc:
|
||||
NETBUF_FREE(frag1);
|
||||
NETBUF_FREE(frag2);
|
||||
NETBUF_FREE(fake_pad);
|
||||
// NETBUF_FREE(fake_pad);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -571,13 +570,13 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet
|
||||
} else {
|
||||
NETBUF_ALLOC(frag1, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(frag1)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
NETBUF_ALLOC(frag2, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(frag2)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
NETBUF_FREE(frag1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -588,7 +587,7 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet
|
||||
int ret;
|
||||
|
||||
if (dvs > poses[0]) {
|
||||
lgerror("send_frags: Recursive dvs(%d) is more than poses0(%d)", -EINVAL, dvs, poses[0]);
|
||||
lgerror(-EINVAL, "send_frags: Recursive dvs(%d) is more than poses0(%d)", dvs, poses[0]);
|
||||
ret = -EINVAL;
|
||||
goto erret_lc;
|
||||
}
|
||||
@@ -601,7 +600,7 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet
|
||||
lgtrace_addp("Packet split in %d bytes position of payload start, dvs: %d to two packets of %d and %d lengths", poses[0], dvs, f1len, f2len);
|
||||
|
||||
if (ret < 0) {
|
||||
lgerror("send_frags: tcp_frag: with context packet with size %d, position: %d, recursive dvs: %d", ret, pktlen, poses[0], dvs);
|
||||
lgerror(ret, "send_frags: tcp_frag: with context packet with size %d, position: %d, recursive dvs: %d", pktlen, poses[0], dvs);
|
||||
goto erret_lc;
|
||||
}
|
||||
|
||||
@@ -690,7 +689,7 @@ int post_fake_sni(struct fake_type f_type,
|
||||
for (int i = 0; i < fake_seq_type.sequence_len; i++) {
|
||||
NETBUF_ALLOC(fake_sni, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(fake_sni)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
uint32_t fsn_len = MAX_PACKET_SIZE;
|
||||
@@ -700,7 +699,7 @@ int post_fake_sni(struct fake_type f_type,
|
||||
fsiph, iph_len, fstcph, tcph_len,
|
||||
fake_sni, &fsn_len);
|
||||
if (ret < 0) {
|
||||
lgerror("gen_fake_sni", ret);
|
||||
lgerror(ret, "gen_fake_sni");
|
||||
goto erret_lc;
|
||||
}
|
||||
|
||||
@@ -712,7 +711,7 @@ int post_fake_sni(struct fake_type f_type,
|
||||
ret = instance_config.send_raw_packet(fake_sni, fsn_len);
|
||||
}
|
||||
if (ret < 0) {
|
||||
lgerror("send fake sni", ret);
|
||||
lgerror(ret, "send fake sni");
|
||||
goto erret_lc;
|
||||
}
|
||||
uint32_t iph_len;
|
||||
|
||||
184
quic.c
184
quic.c
@@ -43,7 +43,7 @@ int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len,
|
||||
uint32_t left_len = raw_payload_len - sizeof(struct quic_lhdr);
|
||||
uint8_t *cur_rawptr = raw_payload + sizeof(struct quic_lhdr);
|
||||
if (!nqch->fixed) {
|
||||
lgtrace_addp("quic fixed uset");
|
||||
lgtrace_addp("quic fixed unset");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
@@ -135,6 +135,186 @@ int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen,
|
||||
return 0;
|
||||
|
||||
invalid_packet:
|
||||
lgerror("QUIC invalid Initial packet", -EINVAL);
|
||||
lgerror(-EINVAL, "QUIC invalid Initial packet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen) {
|
||||
void *iph;
|
||||
uint32_t iph_len;
|
||||
struct udphdr *udph;
|
||||
uint8_t *data;
|
||||
uint32_t dlen;
|
||||
int ret;
|
||||
|
||||
ret = udp_payload_split(payload, *plen,
|
||||
&iph, &iph_len, &udph,
|
||||
&data, &dlen);
|
||||
|
||||
uint32_t ipxv = netproto_version(payload, *plen);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if (strategy.strategy == FAKE_STRAT_TTL) {
|
||||
lgtrace_addp("set fake ttl to %d", strategy.faking_ttl);
|
||||
|
||||
if (ipxv == IP4VERSION) {
|
||||
((struct iphdr *)iph)->ttl = strategy.faking_ttl;
|
||||
} else if (ipxv == IP6VERSION) {
|
||||
((struct ip6_hdr *)iph)->ip6_hops = strategy.faking_ttl;
|
||||
} else {
|
||||
lgerror(-EINVAL, "fail_packet: IP version is unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ipxv == IP4VERSION) {
|
||||
((struct iphdr *)iph)->frag_off = 0;
|
||||
}
|
||||
|
||||
|
||||
set_ip_checksum(iph, iph_len);
|
||||
|
||||
if (strategy.strategy == FAKE_STRAT_UDP_CHECK) {
|
||||
lgtrace_addp("break fake udp checksum");
|
||||
udph->check += 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gen_fake_udp(struct udp_fake_type type,
|
||||
const void *ipxh, uint32_t iph_len,
|
||||
const struct udphdr *udph,
|
||||
uint8_t *buf, uint32_t *buflen) {
|
||||
uint32_t data_len = type.fake_len;
|
||||
|
||||
if (!ipxh || !udph || !buf || !buflen)
|
||||
return -EINVAL;
|
||||
|
||||
int ipxv = netproto_version(ipxh, iph_len);
|
||||
|
||||
if (ipxv == IP4VERSION) {
|
||||
const struct iphdr *iph = ipxh;
|
||||
|
||||
memcpy(buf, iph, iph_len);
|
||||
struct iphdr *niph = (struct iphdr *)buf;
|
||||
|
||||
niph->protocol = IPPROTO_UDP;
|
||||
} else if (ipxv == IP6VERSION) {
|
||||
const struct ip6_hdr *iph = ipxh;
|
||||
|
||||
iph_len = sizeof(struct ip6_hdr);
|
||||
memcpy(buf, iph, iph_len);
|
||||
struct ip6_hdr *niph = (struct ip6_hdr *)buf;
|
||||
|
||||
niph->ip6_nxt = IPPROTO_UDP;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t dlen = iph_len + sizeof(struct udphdr) + data_len;
|
||||
|
||||
if (*buflen < dlen)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(buf + iph_len, udph, sizeof(struct udphdr));
|
||||
uint8_t *bfdptr = buf + iph_len + sizeof(struct udphdr);
|
||||
|
||||
memset(bfdptr, 0, data_len);
|
||||
|
||||
if (ipxv == IP4VERSION) {
|
||||
struct iphdr *niph = (struct iphdr *)buf;
|
||||
niph->tot_len = htons(dlen);
|
||||
niph->id = randint();
|
||||
} else if (ipxv == IP6VERSION) {
|
||||
struct ip6_hdr *niph = (struct ip6_hdr *)buf;
|
||||
niph->ip6_plen = htons(dlen - iph_len);
|
||||
}
|
||||
|
||||
struct udphdr *nudph = (struct udphdr *)(buf + iph_len);
|
||||
nudph->len = htons(sizeof(struct udphdr) + data_len);
|
||||
|
||||
|
||||
udp_fail_packet(type.strategy, buf, &dlen, *buflen);
|
||||
|
||||
*buflen = dlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int detect_udp_filtered(const struct section_config_t *section,
|
||||
const uint8_t *payload, uint32_t plen) {
|
||||
const void *iph;
|
||||
uint32_t iph_len;
|
||||
const struct udphdr *udph;
|
||||
const uint8_t *data;
|
||||
uint32_t dlen;
|
||||
int ret;
|
||||
|
||||
ret = udp_payload_split((uint8_t *)payload, plen,
|
||||
(void **)&iph, &iph_len,
|
||||
(struct udphdr **)&udph,
|
||||
(uint8_t **)&data, &dlen);
|
||||
int udp_dport = ntohs(udph->dest);
|
||||
lgtrace_addp("UDP dport: %d", udp_dport);
|
||||
|
||||
|
||||
if (ret < 0) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (section->udp_filter_quic) {
|
||||
const struct quic_lhdr *qch;
|
||||
uint32_t qch_len;
|
||||
struct quic_cids qci;
|
||||
uint8_t *quic_raw_payload;
|
||||
uint32_t quic_raw_plen;
|
||||
|
||||
lgtrace_addp("QUIC probe");
|
||||
|
||||
ret = quic_parse_data((uint8_t *)data, dlen,
|
||||
(struct quic_lhdr **)&qch, &qch_len, &qci,
|
||||
&quic_raw_payload, &quic_raw_plen);
|
||||
|
||||
if (ret < 0) {
|
||||
lgtrace_addp("QUIC undefined type");
|
||||
goto match_port;
|
||||
}
|
||||
|
||||
lgtrace_addp("QUIC detected");
|
||||
|
||||
uint8_t qtype = qch->type;
|
||||
if (qch->version == QUIC_V1)
|
||||
qtype = quic_convtype_v1(qtype);
|
||||
else if (qch->version == QUIC_V2)
|
||||
qtype = quic_convtype_v2(qtype);
|
||||
|
||||
if (qtype != QUIC_INITIAL_TYPE) {
|
||||
lgtrace_addp("QUIC message type: %d", qtype);
|
||||
goto match_port;
|
||||
}
|
||||
|
||||
lgtrace_addp("QUIC initial message");
|
||||
|
||||
goto approve;
|
||||
}
|
||||
|
||||
match_port:
|
||||
|
||||
for (int i = 0; i < section->udp_dport_range_len; i++) {
|
||||
struct udp_dport_range crange = section->udp_dport_range[i];
|
||||
if (udp_dport >= crange.start && udp_dport <= crange.end) {
|
||||
lgtrace_addp("matched to %d-%d", crange.start, crange.end);
|
||||
goto approve;
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
return 0;
|
||||
approve:
|
||||
return 1;
|
||||
}
|
||||
|
||||
13
quic.h
13
quic.h
@@ -1,6 +1,7 @@
|
||||
#ifndef QUIC_H
|
||||
#define QUIC_H
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -125,4 +126,16 @@ int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen,
|
||||
struct quici_hdr *qhdr,
|
||||
uint8_t **payload, uint32_t *plen);
|
||||
|
||||
// Like fail_packet for TCP
|
||||
int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen);
|
||||
|
||||
// Like gen_fake_sni for TCP
|
||||
int gen_fake_udp(struct udp_fake_type type,
|
||||
const void *ipxh, uint32_t iph_len,
|
||||
const struct udphdr *udph,
|
||||
uint8_t *buf, uint32_t *buflen);
|
||||
|
||||
int detect_udp_filtered(const struct section_config_t *section,
|
||||
const uint8_t *payload, uint32_t plen);
|
||||
|
||||
#endif /* QUIC_H */
|
||||
|
||||
258
tls.c
258
tls.c
@@ -9,6 +9,114 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static int bruteforce_analyze_sni_str(
|
||||
const struct section_config_t *section,
|
||||
const uint8_t *data, size_t dlen,
|
||||
struct tls_verdict *vrd
|
||||
) {
|
||||
if (section->all_domains) {
|
||||
vrd->target_sni = 1;
|
||||
vrd->sni_len = 0;
|
||||
vrd->sni_offset = dlen / 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) {
|
||||
const char *domain_startp = sne->domain_name;
|
||||
int domain_len = sne->domain_len;
|
||||
|
||||
if (sne->domain_len + dlen + 1 > MAX_PACKET_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NETBUF_ALLOC(buf, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(buf)) {
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NETBUF_ALLOC(nzbuf, MAX_PACKET_SIZE * sizeof(int));
|
||||
if (!NETBUF_CHECK(nzbuf)) {
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
NETBUF_FREE(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int *zbuf = (void *)nzbuf;
|
||||
|
||||
memcpy(buf, domain_startp, domain_len);
|
||||
memcpy(buf + domain_len, "#", 1);
|
||||
memcpy(buf + domain_len + 1, data, dlen);
|
||||
|
||||
z_function((char *)buf, zbuf, domain_len + 1 + dlen);
|
||||
|
||||
for (unsigned int k = 0; k < dlen; k++) {
|
||||
if (zbuf[k] == domain_len) {
|
||||
vrd->target_sni = 1;
|
||||
vrd->sni_len = domain_len;
|
||||
vrd->sni_offset = (k - domain_len - 1);
|
||||
vrd->sni_target_offset = vrd->sni_offset;
|
||||
vrd->sni_target_len = vrd->sni_len;
|
||||
NETBUF_FREE(buf);
|
||||
NETBUF_FREE(nzbuf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NETBUF_FREE(buf);
|
||||
NETBUF_FREE(nzbuf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int analyze_sni_str(
|
||||
const struct section_config_t *section,
|
||||
const char *sni_name, int sni_len, const uint8_t *data,
|
||||
struct tls_verdict *vrd
|
||||
) {
|
||||
if (section->all_domains) {
|
||||
vrd->target_sni = 1;
|
||||
goto check_domain;
|
||||
}
|
||||
|
||||
for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) {
|
||||
const char *sni_startp = sni_name + sni_len - sne->domain_len;
|
||||
const char *domain_startp = sne->domain_name;
|
||||
|
||||
if (sni_len >= sne->domain_len &&
|
||||
sni_len < 128 &&
|
||||
!strncmp(sni_startp,
|
||||
domain_startp,
|
||||
sne->domain_len)) {
|
||||
vrd->target_sni = 1;
|
||||
vrd->sni_target_offset = (const uint8_t *)sni_startp - data;
|
||||
vrd->sni_target_len = sne->domain_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_domain:
|
||||
if (vrd->target_sni == 1) {
|
||||
for (struct domains_list *sne = section->exclude_sni_domains; sne != NULL; sne = sne->next) {
|
||||
const char *sni_startp = sni_name + sni_len - sne->domain_len;
|
||||
const char *domain_startp = sne->domain_name;
|
||||
|
||||
if (sni_len >= sne->domain_len &&
|
||||
sni_len < 128 &&
|
||||
!strncmp(sni_startp,
|
||||
domain_startp,
|
||||
sne->domain_len)) {
|
||||
vrd->target_sni = 0;
|
||||
lgdebugmsg("Excluded SNI: %.*s",
|
||||
vrd->sni_len, data + vrd->sni_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define TLS_CONTENT_TYPE_HANDSHAKE 0x16
|
||||
#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01
|
||||
#define TLS_EXTENSION_SNI 0x0000
|
||||
@@ -30,6 +138,11 @@ struct tls_verdict analyze_tls_data(
|
||||
size_t i = 0;
|
||||
const uint8_t *data_end = data + dlen;
|
||||
|
||||
if (section->sni_detection == SNI_DETECTION_BRUTE) {
|
||||
bruteforce_analyze_sni_str(section, data, dlen, &vrd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (i + 4 < dlen) {
|
||||
const uint8_t *msgData = data + i;
|
||||
|
||||
@@ -44,10 +157,6 @@ struct tls_verdict analyze_tls_data(
|
||||
if (tls_content_type != TLS_CONTENT_TYPE_HANDSHAKE)
|
||||
goto nextMessage;
|
||||
|
||||
if (section->sni_detection == SNI_DETECTION_BRUTE) {
|
||||
goto brute;
|
||||
}
|
||||
|
||||
const uint8_t *handshakeProto = msgData + 5;
|
||||
|
||||
if (handshakeProto + 1 >= data_end) break;
|
||||
@@ -120,76 +229,14 @@ struct tls_verdict analyze_tls_data(
|
||||
|
||||
if (sni_ext_ptr + sni_len > sni_ext_end) break;
|
||||
|
||||
char *sni_name = (char *)sni_ext_ptr;
|
||||
const char *sni_name = (char *)sni_ext_ptr;
|
||||
|
||||
vrd.sni_offset = (uint8_t *)sni_name - data;
|
||||
vrd.sni_target_offset = vrd.sni_offset;
|
||||
vrd.sni_len = sni_len;
|
||||
vrd.sni_target_len = vrd.sni_len;
|
||||
|
||||
if (section->all_domains) {
|
||||
vrd.target_sni = 1;
|
||||
goto check_domain;
|
||||
}
|
||||
|
||||
unsigned int j = 0;
|
||||
for (unsigned int i = 0; i <= section->domains_strlen; i++) {
|
||||
if ( i > j &&
|
||||
(i == section->domains_strlen ||
|
||||
section->domains_str[i] == '\0' ||
|
||||
section->domains_str[i] == ',' ||
|
||||
section->domains_str[i] == '\n' )) {
|
||||
|
||||
unsigned int domain_len = (i - j);
|
||||
const char *sni_startp = sni_name + sni_len - domain_len;
|
||||
const char *domain_startp = section->domains_str + j;
|
||||
|
||||
if (sni_len >= domain_len &&
|
||||
sni_len < 128 &&
|
||||
!strncmp(sni_startp,
|
||||
domain_startp,
|
||||
domain_len)) {
|
||||
vrd.target_sni = 1;
|
||||
vrd.sni_target_offset = (const uint8_t *)sni_startp - data;
|
||||
vrd.sni_target_len = domain_len;
|
||||
goto check_domain;
|
||||
}
|
||||
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
check_domain:
|
||||
if (vrd.target_sni == 1 && section->exclude_domains_strlen != 0) {
|
||||
unsigned int j = 0;
|
||||
for (unsigned int i = 0; i <= section->exclude_domains_strlen; i++) {
|
||||
if ( i > j &&
|
||||
(i == section->exclude_domains_strlen ||
|
||||
section->exclude_domains_str[i] == '\0' ||
|
||||
section->exclude_domains_str[i] == ',' ||
|
||||
section->exclude_domains_str[i] == '\n' )) {
|
||||
|
||||
unsigned int domain_len = (i - j);
|
||||
const char *sni_startp = sni_name + sni_len - domain_len;
|
||||
const char *domain_startp = section->exclude_domains_str + j;
|
||||
|
||||
if (sni_len >= domain_len &&
|
||||
sni_len < 128 &&
|
||||
!strncmp(sni_startp,
|
||||
domain_startp,
|
||||
domain_len)) {
|
||||
|
||||
vrd.target_sni = 0;
|
||||
lgdebugmsg("Excluded SNI: %.*s",
|
||||
vrd.sni_len, data + vrd.sni_offset);
|
||||
goto out;
|
||||
}
|
||||
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
analyze_sni_str(section, sni_name, sni_len, data, &vrd);
|
||||
goto out;
|
||||
|
||||
nextExtension:
|
||||
@@ -201,73 +248,6 @@ nextMessage:
|
||||
|
||||
out:
|
||||
return vrd;
|
||||
|
||||
|
||||
brute:
|
||||
if (section->all_domains) {
|
||||
vrd.target_sni = 1;
|
||||
vrd.sni_len = 0;
|
||||
vrd.sni_offset = dlen / 2;
|
||||
goto out;
|
||||
}
|
||||
|
||||
unsigned int j = 0;
|
||||
for (unsigned int i = 0; i <= section->domains_strlen; i++) {
|
||||
if ( i > j &&
|
||||
(i == section->domains_strlen ||
|
||||
section->domains_str[i] == '\0' ||
|
||||
section->domains_str[i] == ',' ||
|
||||
section->domains_str[i] == '\n' )) {
|
||||
|
||||
unsigned int domain_len = (i - j);
|
||||
const char *domain_startp = section->domains_str + j;
|
||||
|
||||
if (domain_len + dlen + 1> MAX_PACKET_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NETBUF_ALLOC(buf, MAX_PACKET_SIZE);
|
||||
if (!NETBUF_CHECK(buf)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
NETBUF_ALLOC(nzbuf, MAX_PACKET_SIZE * sizeof(int));
|
||||
if (!NETBUF_CHECK(nzbuf)) {
|
||||
lgerror("Allocation error", -ENOMEM);
|
||||
NETBUF_FREE(buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int *zbuf = (void *)nzbuf;
|
||||
|
||||
memcpy(buf, domain_startp, domain_len);
|
||||
memcpy(buf + domain_len, "#", 1);
|
||||
memcpy(buf + domain_len + 1, data, dlen);
|
||||
|
||||
z_function((char *)buf, zbuf, domain_len + 1 + dlen);
|
||||
|
||||
for (unsigned int k = 0; k < dlen; k++) {
|
||||
if (zbuf[k] == domain_len) {
|
||||
vrd.target_sni = 1;
|
||||
vrd.sni_len = domain_len;
|
||||
vrd.sni_offset = (k - domain_len - 1);
|
||||
vrd.sni_target_offset = vrd.sni_offset;
|
||||
vrd.sni_target_len = vrd.sni_len;
|
||||
NETBUF_FREE(buf);
|
||||
NETBUF_FREE(nzbuf);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
j = i + 1;
|
||||
|
||||
NETBUF_FREE(buf);
|
||||
NETBUF_FREE(nzbuf);
|
||||
}
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
int gen_fake_sni(struct fake_type type,
|
||||
@@ -275,7 +255,6 @@ int gen_fake_sni(struct fake_type type,
|
||||
const struct tcphdr *tcph, uint32_t tcph_len,
|
||||
uint8_t *buf, uint32_t *buflen) {
|
||||
uint32_t data_len = type.fake_len;
|
||||
int ret;
|
||||
|
||||
if (type.type == FAKE_PAYLOAD_RANDOM && data_len == 0) {
|
||||
data_len = (uint32_t)randint() % 1200;
|
||||
@@ -322,15 +301,16 @@ int gen_fake_sni(struct fake_type type,
|
||||
get_random_bytes(bfdptr, data_len);
|
||||
#else /* KERNEL_SPACE */
|
||||
#if _NO_GETRANDOM
|
||||
ret = open("/dev/urandom", O_RDONLY);
|
||||
{
|
||||
int ret = open("/dev/urandom", O_RDONLY);
|
||||
if (ret < 0) {
|
||||
lgerror("Unable to open /dev/urandom", ret);
|
||||
lgerror(ret, "Unable to open /dev/urandom");
|
||||
return ret;
|
||||
}
|
||||
|
||||
read(ret, bfdptr, data_len);
|
||||
close(ret);
|
||||
|
||||
}
|
||||
#else /* _NO_GETRANDOM */
|
||||
getrandom(bfdptr, data_len, 0);
|
||||
#endif /* _NO_GETRANDOM */
|
||||
|
||||
11
types.h
11
types.h
@@ -34,6 +34,9 @@
|
||||
#include <linux/tcp.h> // IWYU pragma: export
|
||||
#include <linux/version.h>
|
||||
|
||||
#define free kfree
|
||||
#define malloc(size) kmalloc((size), GFP_KERNEL)
|
||||
|
||||
#define ip6_hdr ipv6hdr
|
||||
|
||||
/* from <netinet/ip.h> */
|
||||
@@ -67,6 +70,11 @@
|
||||
#include <netinet/udp.h> // IWYU pragma: export
|
||||
#endif
|
||||
|
||||
#define SFREE(item) do { \
|
||||
free((item)); \
|
||||
(item) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#ifndef KERNEL_SPACE
|
||||
|
||||
#define max(a,b)__extension__\
|
||||
@@ -85,6 +93,9 @@
|
||||
|
||||
#endif /* not a KERNEL_SPACE */
|
||||
|
||||
/* An alternative memory allocation strategy for userspace app */
|
||||
// #define ALLOC_MALLOC
|
||||
|
||||
/**
|
||||
* Use NETBUF_ALLOC and NETBUF_FREE as an abstraction of memory allocation.
|
||||
* Do not use it within expressions, consider these defines as separate statements.
|
||||
|
||||
@@ -10,13 +10,13 @@ CCLD:=$(CC)
|
||||
LD:=ld
|
||||
|
||||
ifeq ($(USE_SYS_LIBS), no)
|
||||
override CFLAGS += -Wall -Wpedantic -Wno-unused-variable -I$(DEPSDIR)/include -std=gnu11
|
||||
override CFLAGS += -I$(DEPSDIR)/include
|
||||
override LDFLAGS += -L$(DEPSDIR)/lib
|
||||
REQ = $(LIBNETFILTER_QUEUE) $(LIBMNL) $(LIBCRYPTO)
|
||||
else
|
||||
override CFLAGS += -Wall -Wpedantic -Wno-unused-variable -std=gnu11
|
||||
endif
|
||||
|
||||
override CFLAGS += -DPKG_VERSION=\"$(PKG_FULLVERSION)\" -Wall -Wpedantic -Wno-unused-variable -std=gnu99
|
||||
|
||||
LIBNFNETLINK_CFLAGS := -I$(DEPSDIR)/include
|
||||
LIBNFNETLINK_LIBS := -L$(DEPSDIR)/lib
|
||||
LIBMNL_CFLAGS := -I$(DEPSDIR)/include
|
||||
@@ -31,7 +31,7 @@ export CC CCLD LD CFLAGS LDFLAGS LIBNFNETLINK_CFLAGS LIBNFNETLINK_LIBS LIBMNL_CF
|
||||
|
||||
APP:=$(BUILD_DIR)/youtubeUnblock
|
||||
|
||||
SRCS := youtubeUnblock.c mangle.c args.c utils.c quic.c tls.c
|
||||
SRCS := youtubeUnblock.c mangle.c args.c utils.c quic.c tls.c getopt.c
|
||||
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
|
||||
|
||||
LIBNFNETLINK := $(DEPSDIR)/lib/libnfnetlink.la
|
||||
|
||||
32
utils.c
32
utils.c
@@ -81,20 +81,20 @@ int ip4_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||
struct iphdr **iph, uint32_t *iph_len,
|
||||
uint8_t **payload, uint32_t *plen) {
|
||||
if (pkt == NULL || buflen < sizeof(struct iphdr)) {
|
||||
lgerror("ip4_payload_split: pkt|buflen", -EINVAL);
|
||||
lgerror(-EINVAL, "ip4_payload_split: pkt|buflen");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct iphdr *hdr = (struct iphdr *)pkt;
|
||||
if (netproto_version(pkt, buflen) != IP4VERSION) {
|
||||
lgerror("ip4_payload_split: ipversion", -EINVAL);
|
||||
lgerror(-EINVAL, "ip4_payload_split: ipversion");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t hdr_len = hdr->ihl * 4;
|
||||
uint32_t pktlen = ntohs(hdr->tot_len);
|
||||
if (buflen < pktlen || hdr_len > pktlen) {
|
||||
lgerror("ip4_payload_split: buflen cmp pktlen", -EINVAL);
|
||||
lgerror(-EINVAL, "ip4_payload_split: buflen cmp pktlen");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -156,20 +156,20 @@ int ip6_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||
struct ip6_hdr **iph, uint32_t *iph_len,
|
||||
uint8_t **payload, uint32_t *plen) {
|
||||
if (pkt == NULL || buflen < sizeof(struct ip6_hdr)) {
|
||||
lgerror("ip6_payload_split: pkt|buflen", -EINVAL);
|
||||
lgerror(-EINVAL, "ip6_payload_split: pkt|buflen");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct ip6_hdr *hdr = (struct ip6_hdr *)pkt;
|
||||
if (netproto_version(pkt, buflen) != 6) {
|
||||
lgerror("ip6_payload_split: ip6version", -EINVAL);
|
||||
lgerror(-EINVAL, "ip6_payload_split: ip6version");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint32_t hdr_len = sizeof(struct ip6_hdr);
|
||||
uint32_t pktlen = ntohs(hdr->ip6_plen);
|
||||
if (buflen < pktlen) {
|
||||
lgerror("ip6_payload_split: buflen cmp pktlen: %d %d", -EINVAL, buflen, pktlen);
|
||||
lgerror(-EINVAL, "ip6_payload_split: buflen cmp pktlen: %d %d", buflen, pktlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ int tcp_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||
} else if (netvers == IP6VERSION) {
|
||||
return tcp6_payload_split(pkt, buflen, (struct ip6_hdr **)iph, iph_len, tcph, tcph_len, payload, plen);
|
||||
} else {
|
||||
lgerror("Internet Protocol version is unsupported", -EINVAL);
|
||||
lgerror(-EINVAL, "Internet Protocol version is unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -329,7 +329,7 @@ int udp_payload_split(uint8_t *pkt, uint32_t buflen,
|
||||
} else if (netvers == IP6VERSION) {
|
||||
return udp6_payload_split(pkt, buflen, (struct ip6_hdr **)iph, iph_len, udph, payload, plen);
|
||||
} else {
|
||||
lgerror("Internet Protocol version is unsupported", -EINVAL);
|
||||
lgerror(-EINVAL, "Internet Protocol version is unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -351,7 +351,7 @@ int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
||||
if ((ret = ip4_payload_split(
|
||||
(uint8_t *)pkt, buflen,
|
||||
&hdr, &hdr_len, (uint8_t **)&payload, &plen)) < 0) {
|
||||
lgerror("ipv4_frag: TCP Header extract error", ret);
|
||||
lgerror(ret, "ipv4_frag: TCP Header extract error");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
||||
}
|
||||
|
||||
if (payload_offset & ((1 << 3) - 1)) {
|
||||
lgerror("ipv4_frag: Payload offset MUST be a multiply of 8!", -EINVAL);
|
||||
lgerror(-EINVAL, "ipv4_frag: Payload offset MUST be a multiply of 8!");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -433,7 +433,7 @@ int tcp_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
||||
&hdr, &hdr_len,
|
||||
&tcph, &tcph_len,
|
||||
(uint8_t **)&payload, &plen)) < 0) {
|
||||
lgerror("tcp_frag: tcp_payload_split", ret);
|
||||
lgerror(ret, "tcp_frag: tcp_payload_split");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -448,7 +448,7 @@ int tcp_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset,
|
||||
ntohs(iphdr->frag_off) & IP_OFFMASK) {
|
||||
lgdebugmsg("tcp_frag: ip4: frag value: %d",
|
||||
ntohs(iphdr->frag_off));
|
||||
lgerror("tcp_frag: ip4: ip fragmentation is set", -EINVAL);
|
||||
lgerror(-EINVAL, "tcp_frag: ip4: ip fragmentation is set");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -514,7 +514,9 @@ void z_function(const char *str, int *zbuf, size_t len) {
|
||||
for (int i = 1; i < (int)len; i++) {
|
||||
zbuf[i] = 0;
|
||||
if (i < rh) {
|
||||
zbuf[i] = min(zbuf[i - lh], rh - i);
|
||||
zbuf[i] = zbuf[i - lh];
|
||||
if (rh - i < zbuf[i])
|
||||
zbuf[i] = rh - i;
|
||||
}
|
||||
|
||||
while (i + zbuf[i] < len && str[zbuf[i]] == str[i + zbuf[i]])
|
||||
@@ -590,7 +592,7 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, uint32_t *pl
|
||||
} else if (ipxv == IP6VERSION) {
|
||||
((struct ip6_hdr *)iph)->ip6_hops = strategy.faking_ttl;
|
||||
} else {
|
||||
lgerror("fail_packet: IP version is unsupported", -EINVAL);
|
||||
lgerror(-EINVAL, "fail_packet: IP version is unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (strategy.strategy == FAKE_STRAT_TCP_MD5SUM) {
|
||||
@@ -612,7 +614,7 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, uint32_t *pl
|
||||
} else if (ipxv == IP6VERSION) {
|
||||
((struct ip6_hdr *)iph)->ip6_plen = htons(ntohs(((struct ip6_hdr *)iph)->ip6_plen) + delta);
|
||||
} else {
|
||||
lgerror("fail_packet: IP version is unsupported", -EINVAL);
|
||||
lgerror(-EINVAL, "fail_packet: IP version is unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
optp_len += delta;
|
||||
|
||||
14
utils.h
14
utils.h
@@ -142,6 +142,20 @@ struct fake_type {
|
||||
struct failing_strategy strategy;
|
||||
};
|
||||
|
||||
struct udp_failing_strategy {
|
||||
unsigned int strategy;
|
||||
uint8_t faking_ttl;
|
||||
};
|
||||
|
||||
struct udp_fake_type {
|
||||
uint16_t fake_len;
|
||||
|
||||
// faking strategy of the fake packet.
|
||||
// Does not support bitmask, pass standalone strategy.
|
||||
// Pass 0 if you don't want any faking procedures.
|
||||
struct udp_failing_strategy strategy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Invalidates the raw packet. The function aims to invalid the packet
|
||||
* in such way as it will be accepted by DPI, but dropped by target server
|
||||
|
||||
164
youtubeUnblock.c
164
youtubeUnblock.c
@@ -45,12 +45,12 @@ static int open_socket(struct mnl_socket **_nl) {
|
||||
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
|
||||
if (nl == NULL) {
|
||||
perror("mnl_socket_open");
|
||||
lgerror(-errno, "mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
perror("mnl_socket_bind");
|
||||
lgerror(-errno, "mnl_socket_bind");
|
||||
mnl_socket_close(nl);
|
||||
return -1;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ static int close_socket(struct mnl_socket **_nl) {
|
||||
struct mnl_socket *nl = *_nl;
|
||||
if (nl == NULL) return 1;
|
||||
if (mnl_socket_close(nl) < 0) {
|
||||
perror("mnl_socket_close");
|
||||
lgerror(-errno, "mnl_socket_close");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -77,26 +77,26 @@ static int close_socket(struct mnl_socket **_nl) {
|
||||
static int open_raw_socket(void) {
|
||||
if (rawsocket != -2) {
|
||||
errno = EALREADY;
|
||||
perror("Raw socket is already opened");
|
||||
lgerror(-errno, "Raw socket is already opened");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rawsocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (rawsocket == -1) {
|
||||
perror("Unable to create raw socket");
|
||||
lgerror(-errno, "Unable to create raw socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mark = config.mark;
|
||||
if (setsockopt(rawsocket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
|
||||
{
|
||||
fprintf(stderr, "setsockopt(SO_MARK, %d) failed\n", mark);
|
||||
lgerror(-errno, "setsockopt(SO_MARK, %d) failed\n", mark);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mst = pthread_mutex_init(&rawsocket_lock, NULL);
|
||||
if (mst) {
|
||||
fprintf(stderr, "Mutex err: %d\n", mst);
|
||||
lgerror(-errno, "Mutex err: %d\n", mst);
|
||||
close(rawsocket);
|
||||
errno = mst;
|
||||
|
||||
@@ -110,12 +110,12 @@ static int open_raw_socket(void) {
|
||||
static int close_raw_socket(void) {
|
||||
if (rawsocket < 0) {
|
||||
errno = EALREADY;
|
||||
perror("Raw socket is not set");
|
||||
lgerror(-errno, "Raw socket is not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(rawsocket)) {
|
||||
perror("Unable to close raw socket");
|
||||
lgerror(-errno, "Unable to close raw socket");
|
||||
pthread_mutex_destroy(&rawsocket_lock);
|
||||
return -1;
|
||||
}
|
||||
@@ -129,28 +129,27 @@ static int close_raw_socket(void) {
|
||||
static int open_raw6_socket(void) {
|
||||
if (raw6socket != -2) {
|
||||
errno = EALREADY;
|
||||
perror("Raw socket is already opened");
|
||||
lgerror(-errno, "Raw socket is already opened");
|
||||
return -1;
|
||||
}
|
||||
|
||||
raw6socket = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
|
||||
if (rawsocket == -1) {
|
||||
perror("Unable to create raw socket");
|
||||
lgerror(-errno, "Unable to create raw socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mark = config.mark;
|
||||
if (setsockopt(raw6socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
|
||||
{
|
||||
fprintf(stderr, "setsockopt(SO_MARK, %d) failed\n", mark);
|
||||
lgerror(-errno, "setsockopt(SO_MARK, %d) failed\n", mark);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mst = pthread_mutex_init(&raw6socket_lock, NULL);
|
||||
if (mst) {
|
||||
fprintf(stderr, "Mutex err: %d\n", mst);
|
||||
lgerror(-errno, "Mutex err: %d\n", mst);
|
||||
close(raw6socket);
|
||||
errno = mst;
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -162,12 +161,12 @@ static int open_raw6_socket(void) {
|
||||
static int close_raw6_socket(void) {
|
||||
if (raw6socket < 0) {
|
||||
errno = EALREADY;
|
||||
perror("Raw socket is not set");
|
||||
lgerror(-errno, "Raw socket is not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(raw6socket)) {
|
||||
perror("Unable to close raw socket");
|
||||
lgerror(-errno, "Unable to close raw socket");
|
||||
pthread_mutex_destroy(&rawsocket_lock);
|
||||
return -1;
|
||||
}
|
||||
@@ -203,7 +202,7 @@ static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) {
|
||||
pthread_mutex_lock(&rawsocket_lock);
|
||||
|
||||
int sent = sendto(rawsocket,
|
||||
pkt, pktlen, 0,
|
||||
pkt, pktlen, MSG_DONTWAIT,
|
||||
(struct sockaddr *)&daddr, sizeof(daddr));
|
||||
|
||||
if (config.threads != 1)
|
||||
@@ -238,7 +237,7 @@ static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) {
|
||||
pthread_mutex_lock(&rawsocket_lock);
|
||||
|
||||
int sent = sendto(raw6socket,
|
||||
pkt, pktlen, 0,
|
||||
pkt, pktlen, MSG_DONTWAIT,
|
||||
(struct sockaddr *)&daddr, sizeof(daddr));
|
||||
|
||||
lgtrace_addp("rawsocket sent %d", sent);
|
||||
@@ -256,19 +255,29 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
||||
int ret;
|
||||
|
||||
if (pktlen > AVAILABLE_MTU) {
|
||||
if (config.verbose)
|
||||
printf("Split packet!\n");
|
||||
lgtrace("Split packet!\n");
|
||||
|
||||
NETBUF_ALLOC(buff1, MNL_SOCKET_BUFFER_SIZE);
|
||||
if (!NETBUF_CHECK(buff1)) {
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
NETBUF_ALLOC(buff2, MNL_SOCKET_BUFFER_SIZE);
|
||||
if (!NETBUF_CHECK(buff2)) {
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
NETBUF_FREE(buff1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
uint8_t buff1[MNL_SOCKET_BUFFER_SIZE];
|
||||
uint32_t buff1_size = MNL_SOCKET_BUFFER_SIZE;
|
||||
uint8_t buff2[MNL_SOCKET_BUFFER_SIZE];
|
||||
uint32_t buff2_size = MNL_SOCKET_BUFFER_SIZE;
|
||||
|
||||
if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128,
|
||||
buff1, &buff1_size, buff2, &buff2_size)) < 0) {
|
||||
|
||||
errno = -ret;
|
||||
return ret;
|
||||
goto free_buffs;
|
||||
}
|
||||
|
||||
int sent = 0;
|
||||
@@ -276,16 +285,23 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
||||
|
||||
if (status >= 0) sent += status;
|
||||
else {
|
||||
return status;
|
||||
ret = status;
|
||||
goto free_buffs;
|
||||
}
|
||||
|
||||
status = send_raw_socket(buff2, buff2_size);
|
||||
if (status >= 0) sent += status;
|
||||
else {
|
||||
return status;
|
||||
ret = status;
|
||||
goto free_buffs;
|
||||
}
|
||||
|
||||
return sent;
|
||||
ret = sent;
|
||||
|
||||
free_buffs:
|
||||
NETBUF_FREE(buff1)
|
||||
NETBUF_FREE(buff2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ipvx = netproto_version(pkt, pktlen);
|
||||
@@ -295,7 +311,7 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) {
|
||||
} else if (ipvx == IP6VERSION) {
|
||||
ret = send_raw_ipv6(pkt, pktlen);
|
||||
} else {
|
||||
printf("proto version %d is unsupported\n", ipvx);
|
||||
lginfo("proto version %d is unsupported\n", ipvx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -328,7 +344,7 @@ static int fallback_accept_packet(uint32_t id, struct queue_data qdata) {
|
||||
nfq_nlmsg_verdict_put(verdnlh, id, NF_ACCEPT);
|
||||
|
||||
if (mnl_socket_sendto(*qdata._nl, verdnlh, verdnlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_send");
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
@@ -353,7 +369,7 @@ void *delay_packet_send_fn(void *data) {
|
||||
int ret = send_raw_socket(pkt, pktlen);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
perror("send delayed raw packet");
|
||||
lgerror(-errno, "send delayed raw packet");
|
||||
}
|
||||
|
||||
free(pkt);
|
||||
@@ -385,13 +401,13 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
|
||||
struct packet_data packet = {0};
|
||||
|
||||
if (nfq_nlmsg_parse(nlh, attr) < 0) {
|
||||
perror("Attr parse");
|
||||
lgerror(-errno, "Attr parse");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (attr[NFQA_PACKET_HDR] == NULL) {
|
||||
errno = ENODATA;
|
||||
perror("Metaheader not set");
|
||||
lgerror(-errno, "Metaheader not set");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
@@ -404,7 +420,7 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
|
||||
packet.payload = mnl_attr_get_payload(attr[NFQA_PAYLOAD]);
|
||||
|
||||
if (attr[NFQA_CAP_LEN] != NULL && ntohl(mnl_attr_get_u32(attr[NFQA_CAP_LEN])) != packet.payload_len) {
|
||||
fprintf(stderr, "The packet was truncated! Skip!\n");
|
||||
lgerr("The packet was truncated! Skip!\n");
|
||||
return fallback_accept_packet(packet.id, *qdata);
|
||||
}
|
||||
|
||||
@@ -432,7 +448,7 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
|
||||
}
|
||||
|
||||
if (mnl_socket_sendto(*qdata->_nl, verdnlh, verdnlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_send");
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
@@ -445,20 +461,64 @@ int init_queue(int queue_num) {
|
||||
struct mnl_socket *nl;
|
||||
|
||||
if (open_socket(&nl)) {
|
||||
perror("Unable to open socket");
|
||||
lgerror(-errno, "Unable to open socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t portid = mnl_socket_get_portid(nl);
|
||||
|
||||
struct nlmsghdr *nlh;
|
||||
char buf[BUF_SIZE];
|
||||
NETBUF_ALLOC(bbuf, BUF_SIZE);
|
||||
if (!NETBUF_CHECK(bbuf)) {
|
||||
lgerror(-ENOMEM, "Allocation error");
|
||||
goto die_alloc;
|
||||
}
|
||||
char *buf = (char *)bbuf;
|
||||
|
||||
/* Support for kernels versions < 3.8 */
|
||||
// Obsolete and ignored in kernel version 3.8
|
||||
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0360ae412d09bc6f4864c801effcb20bfd84520e
|
||||
|
||||
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||
nfq_nlmsg_cfg_put_cmd(nlh, PF_INET, NFQNL_CFG_CMD_PF_UNBIND);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
goto die;
|
||||
}
|
||||
|
||||
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||
nfq_nlmsg_cfg_put_cmd(nlh, PF_INET, NFQNL_CFG_CMD_PF_BIND);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
goto die;
|
||||
}
|
||||
|
||||
if (config.use_ipv6) {
|
||||
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||
nfq_nlmsg_cfg_put_cmd(nlh, PF_INET6, NFQNL_CFG_CMD_PF_UNBIND);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
goto die;
|
||||
}
|
||||
|
||||
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||
nfq_nlmsg_cfg_put_cmd(nlh, PF_INET6, NFQNL_CFG_CMD_PF_BIND);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
goto die;
|
||||
}
|
||||
}
|
||||
/* End of support for kernel versions < 3.8 */
|
||||
|
||||
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||
nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_BIND);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_send");
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
goto die;
|
||||
}
|
||||
|
||||
@@ -471,7 +531,7 @@ int init_queue(int queue_num) {
|
||||
}
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||
perror("mnl_socket_send");
|
||||
lgerror(-errno, "mnl_socket_send");
|
||||
goto die;
|
||||
}
|
||||
|
||||
@@ -488,32 +548,35 @@ int init_queue(int queue_num) {
|
||||
.queue_num = queue_num
|
||||
};
|
||||
|
||||
printf("Queue %d started\n", qdata.queue_num);
|
||||
lginfo("Queue %d started\n", qdata.queue_num);
|
||||
|
||||
while (1) {
|
||||
ret = mnl_socket_recvfrom(nl, buf, BUF_SIZE);
|
||||
if (ret == -1) {
|
||||
perror("mnl_socket_recvfrom");
|
||||
lgerror(-errno, "mnl_socket_recvfrom");
|
||||
goto die;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, &qdata);
|
||||
if (ret < 0) {
|
||||
lgerror("mnl_cb_run", -EPERM);
|
||||
lgerror(-EPERM, "mnl_cb_run");
|
||||
if (errno == EPERM) {
|
||||
printf("Probably another instance of youtubeUnblock with the same queue number is running\n");
|
||||
lgerror(-errno, "Probably another instance of youtubeUnblock with the same queue number is running\n");
|
||||
} else {
|
||||
printf("Make sure the nfnetlink_queue kernel module is loaded\n");
|
||||
lgerror(-errno, "Make sure the nfnetlink_queue kernel module is loaded\n");
|
||||
}
|
||||
goto die;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NETBUF_FREE(bbuf)
|
||||
close_socket(&nl);
|
||||
return 0;
|
||||
|
||||
die:
|
||||
NETBUF_FREE(bbuf)
|
||||
die_alloc:
|
||||
close_socket(&nl);
|
||||
return -1;
|
||||
}
|
||||
@@ -537,7 +600,7 @@ void *init_queue_wrapper(void *qdconf) {
|
||||
|
||||
thres->status = init_queue(qconf->queue_num);
|
||||
|
||||
fprintf(stderr, "Thread %d exited with status %d\n", qconf->i, thres->status);
|
||||
lgerror(thres->status, "Thread %d exited with status %d\n", qconf->i, thres->status);
|
||||
|
||||
return thres;
|
||||
}
|
||||
@@ -549,9 +612,9 @@ struct instance_config_t instance_config = {
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ret;
|
||||
if ((ret = parse_args(argc, argv)) != 0) {
|
||||
if ((ret = yparse_args(argc, argv)) != 0) {
|
||||
if (ret < 0) {
|
||||
perror("Unable to parse args");
|
||||
lgerror(-errno, "Unable to parse args");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
@@ -560,19 +623,24 @@ int main(int argc, char *argv[]) {
|
||||
print_version();
|
||||
print_welcome();
|
||||
|
||||
|
||||
if (open_raw_socket() < 0) {
|
||||
perror("Unable to open raw socket");
|
||||
lgerror(-errno, "Unable to open raw socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (config.use_ipv6) {
|
||||
if (open_raw6_socket() < 0) {
|
||||
perror("Unable to open raw socket for ipv6");
|
||||
lgerror(-errno, "Unable to open raw socket for ipv6");
|
||||
close_raw_socket();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.daemonize) {
|
||||
daemon(0, config.noclose);
|
||||
}
|
||||
|
||||
struct queue_res *qres = &defqres;
|
||||
|
||||
if (config.threads == 1) {
|
||||
@@ -583,7 +651,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
qres = init_queue_wrapper(&tconf);
|
||||
} else {
|
||||
printf("%d threads wil be used\n", config.threads);
|
||||
lginfo("%d threads wil be used\n", config.threads);
|
||||
|
||||
struct queue_conf thread_confs[MAX_THREADS];
|
||||
pthread_t threads[MAX_THREADS];
|
||||
|
||||
Reference in New Issue
Block a user