Archived
Public Access
Simplify to kernel-install-only; default to BBR + CAKE + ECN
Strip the project down to installing the BBRv3 kernel and nothing else, and ship a single standard kernel (x86_64 + arm64, latest stable). - install.sh: 1413 -> ~490 lines. Menu reduced to install latest / install specific / status / uninstall. Removed all qdisc/TCP-tuning/speedtest/ smart-bandwidth/"madness"/clear-config features, the security (Dirty-Frag) mitigations, the profile (standard/max) selection, and the self-installing `b` quick command. Map dep command->package (sysctl->procps, awk->gawk) and abort clearly when a hard dependency is missing. - Default network stack: on install write /etc/sysctl.d/99-bbrv3.conf with net.core.default_qdisc=cake, net.ipv4.tcp_congestion_control=bbr, net.ipv4.tcp_ecn=1 (CAKE has no compile-time default-qdisc option, so it is set via sysctl); uninstall removes the drop-in. - prepare-kernel-config.sh: build sch_cake in (=y) so cake works at boot; drop the now-dead build-configs/ output. - build.yml: matrix is just x86_64 + arm64 standard; tags are <arch>-<version>; removed the max profile/steps and the update-config-baseline auto-commit job; releases carry only the kernel .deb assets. - Remove cve_2026_31431_detector.py and the two max-profile helper scripts. - README rewritten to the 4-action, kernel-only scope. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+13
-111
@@ -1,15 +1,10 @@
|
|||||||
name: 构建带有BBRv3的内核
|
name: 构建带有BBRv3的内核
|
||||||
|
|
||||||
# Gitea Actions reads workflows from .github/workflows/ (and .gitea/workflows/).
|
# Gitea Actions reads workflows from .github/workflows/ (and .gitea/workflows/).
|
||||||
# This workflow targets a self-hosted Gitea instance:
|
# This workflow targets a self-hosted Gitea instance: release existence checks,
|
||||||
# * release existence checks, creation and asset uploads go through the Gitea
|
# creation and asset uploads go through the Gitea REST API (curl), not the GitHub
|
||||||
# REST API (curl), not the GitHub `gh` CLI;
|
# `gh` CLI. arm64 is cross-compiled on the x86_64 runner
|
||||||
# * config-baseline data is passed between jobs via Gitea release assets, NOT via
|
# (CROSS_COMPILE=aarch64-linux-gnu-), so only a single ubuntu-latest runner is needed.
|
||||||
# actions/upload-artifact@v4 — the upstream artifact v4 actions detect Gitea as
|
|
||||||
# GHES and abort, so they are avoided entirely;
|
|
||||||
# * arm64 kernels are cross-compiled on the x86_64 runner
|
|
||||||
# (CROSS_COMPILE=aarch64-linux-gnu-), so only a single ubuntu-latest runner is
|
|
||||||
# required.
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -74,8 +69,7 @@ jobs:
|
|||||||
|
|
||||||
missing=0
|
missing=0
|
||||||
for arch in x86_64 arm64; do
|
for arch in x86_64 arm64; do
|
||||||
for suffix in "" "-max"; do
|
tag="$arch-$version"
|
||||||
tag="$arch-$version$suffix"
|
|
||||||
if release_exists "$tag"; then
|
if release_exists "$tag"; then
|
||||||
echo "$tag already exists."
|
echo "$tag already exists."
|
||||||
else
|
else
|
||||||
@@ -83,7 +77,6 @@ jobs:
|
|||||||
missing=1
|
missing=1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$missing" -eq 0 ]; then
|
if [ "$missing" -eq 0 ]; then
|
||||||
echo "build_needed=false" >> "$GITHUB_OUTPUT"
|
echo "build_needed=false" >> "$GITHUB_OUTPUT"
|
||||||
@@ -100,35 +93,15 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# All targets build on a single x86_64 runner; arm64 is cross-compiled.
|
# Both targets build on a single x86_64 runner; arm64 is cross-compiled.
|
||||||
- arch: x86_64
|
- arch: x86_64
|
||||||
runs_on: ubuntu-latest
|
runs_on: ubuntu-latest
|
||||||
cross_compile: ""
|
cross_compile: ""
|
||||||
profile: standard
|
|
||||||
profile_name: BBRv3
|
|
||||||
release_suffix: ""
|
|
||||||
localversion: -bbrv3
|
localversion: -bbrv3
|
||||||
- arch: arm64
|
- arch: arm64
|
||||||
runs_on: ubuntu-latest
|
runs_on: ubuntu-latest
|
||||||
cross_compile: aarch64-linux-gnu-
|
cross_compile: aarch64-linux-gnu-
|
||||||
profile: standard
|
|
||||||
profile_name: BBRv3
|
|
||||||
release_suffix: ""
|
|
||||||
localversion: -bbrv3
|
localversion: -bbrv3
|
||||||
- arch: x86_64
|
|
||||||
runs_on: ubuntu-latest
|
|
||||||
cross_compile: ""
|
|
||||||
profile: max
|
|
||||||
profile_name: BBRv3 Max
|
|
||||||
release_suffix: -max
|
|
||||||
localversion: -bbrv3-max
|
|
||||||
- arch: arm64
|
|
||||||
runs_on: ubuntu-latest
|
|
||||||
cross_compile: aarch64-linux-gnu-
|
|
||||||
profile: max
|
|
||||||
profile_name: BBRv3 Max
|
|
||||||
release_suffix: -max
|
|
||||||
localversion: -bbrv3-max
|
|
||||||
runs-on: ${{ matrix.runs_on }}
|
runs-on: ${{ matrix.runs_on }}
|
||||||
env:
|
env:
|
||||||
ARCH: ${{ matrix.arch }}
|
ARCH: ${{ matrix.arch }}
|
||||||
@@ -137,8 +110,7 @@ jobs:
|
|||||||
- name: 检查是否已发布
|
- name: 检查是否已发布
|
||||||
id: check_release
|
id: check_release
|
||||||
env:
|
env:
|
||||||
TAG: ${{ matrix.arch }}-${{ needs.preflight.outputs.kernel_version }}${{ matrix.release_suffix }}
|
TAG: ${{ matrix.arch }}-${{ needs.preflight.outputs.kernel_version }}
|
||||||
PROFILE_NAME: ${{ matrix.profile_name }}
|
|
||||||
run: |
|
run: |
|
||||||
code=$(curl -sS -o /dev/null -w '%{http_code}' \
|
code=$(curl -sS -o /dev/null -w '%{http_code}' \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
@@ -148,7 +120,7 @@ jobs:
|
|||||||
echo "$TAG already exists; skipping build."
|
echo "$TAG already exists; skipping build."
|
||||||
else
|
else
|
||||||
echo "BUILD_NEEDED=true" >> "$GITHUB_ENV"
|
echo "BUILD_NEEDED=true" >> "$GITHUB_ENV"
|
||||||
echo "$TAG does not exist; building latest kernel with $PROFILE_NAME."
|
echo "$TAG does not exist; building latest BBRv3 kernel."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: 检出代码
|
- name: 检出代码
|
||||||
@@ -190,27 +162,13 @@ jobs:
|
|||||||
bash "$GITHUB_WORKSPACE/scripts/apply-bbrv3-port.sh"
|
bash "$GITHUB_WORKSPACE/scripts/apply-bbrv3-port.sh"
|
||||||
grep -n "BBR_VERSION" net/ipv4/tcp_bbr.c
|
grep -n "BBR_VERSION" net/ipv4/tcp_bbr.c
|
||||||
|
|
||||||
- name: 应用 BBRv3 Max 极限内核配置
|
|
||||||
if: env.BUILD_NEEDED == 'true' && matrix.profile == 'max'
|
|
||||||
working-directory: ./kernel/linux
|
|
||||||
run: |
|
|
||||||
bash "$GITHUB_WORKSPACE/scripts/apply-bbrv3-max-profile.sh"
|
|
||||||
|
|
||||||
- name: 编译声明
|
- name: 编译声明
|
||||||
if: env.BUILD_NEEDED == 'true'
|
if: env.BUILD_NEEDED == 'true'
|
||||||
working-directory: ./kernel/linux
|
working-directory: ./kernel/linux
|
||||||
env:
|
|
||||||
PROFILE: ${{ matrix.profile }}
|
|
||||||
run: |
|
run: |
|
||||||
grep -v "MODULE_DESCRIPTION" net/ipv4/tcp_bbr.c > net/ipv4/tcp_bbr.c.tmp
|
grep -v "MODULE_DESCRIPTION" net/ipv4/tcp_bbr.c > net/ipv4/tcp_bbr.c.tmp
|
||||||
mv net/ipv4/tcp_bbr.c.tmp net/ipv4/tcp_bbr.c
|
mv net/ipv4/tcp_bbr.c.tmp net/ipv4/tcp_bbr.c
|
||||||
|
|
||||||
if [ "$PROFILE" = "max" ]; then
|
|
||||||
echo 'MODULE_DESCRIPTION("TCP BBR v3 Max - aggressive throughput profile by Joey");' >> net/ipv4/tcp_bbr.c
|
|
||||||
else
|
|
||||||
echo 'MODULE_DESCRIPTION("TCP BBR v3 (Bottleneck Bandwidth and RTT) - Compiled & Optimized by Joey");' >> net/ipv4/tcp_bbr.c
|
echo 'MODULE_DESCRIPTION("TCP BBR v3 (Bottleneck Bandwidth and RTT) - Compiled & Optimized by Joey");' >> net/ipv4/tcp_bbr.c
|
||||||
fi
|
|
||||||
|
|
||||||
tail -n 5 net/ipv4/tcp_bbr.c
|
tail -n 5 net/ipv4/tcp_bbr.c
|
||||||
|
|
||||||
- name: 更新 Makefile 中的版本号
|
- name: 更新 Makefile 中的版本号
|
||||||
@@ -264,7 +222,7 @@ jobs:
|
|||||||
- name: 发布前复查是否已发布
|
- name: 发布前复查是否已发布
|
||||||
if: env.BUILD_NEEDED == 'true'
|
if: env.BUILD_NEEDED == 'true'
|
||||||
env:
|
env:
|
||||||
TAG: ${{ matrix.arch }}-${{ needs.preflight.outputs.kernel_version }}${{ matrix.release_suffix }}
|
TAG: ${{ matrix.arch }}-${{ needs.preflight.outputs.kernel_version }}
|
||||||
run: |
|
run: |
|
||||||
code=$(curl -sS -o /dev/null -w '%{http_code}' \
|
code=$(curl -sS -o /dev/null -w '%{http_code}' \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
@@ -280,13 +238,12 @@ jobs:
|
|||||||
- name: 发布到 Gitea Release
|
- name: 发布到 Gitea Release
|
||||||
if: env.BUILD_NEEDED == 'true' && env.PUBLISH_NEEDED == 'true'
|
if: env.BUILD_NEEDED == 'true' && env.PUBLISH_NEEDED == 'true'
|
||||||
env:
|
env:
|
||||||
TAG: ${{ matrix.arch }}-${{ needs.preflight.outputs.kernel_version }}${{ matrix.release_suffix }}
|
TAG: ${{ matrix.arch }}-${{ needs.preflight.outputs.kernel_version }}
|
||||||
PROFILE_NAME: ${{ matrix.profile_name }}
|
|
||||||
TARGET_ARCH: ${{ matrix.arch }}
|
TARGET_ARCH: ${{ matrix.arch }}
|
||||||
TARGET_SHA: ${{ github.sha }}
|
TARGET_SHA: ${{ github.sha }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
body="带有 $PROFILE_NAME 的最新内核,适用于 $TARGET_ARCH 架构。Compiled & Optimized by Joey."
|
body="带有 BBRv3 的最新内核,适用于 $TARGET_ARCH 架构。Compiled & Optimized by Joey."
|
||||||
|
|
||||||
auth=(-H "Authorization: token $GITEA_TOKEN")
|
auth=(-H "Authorization: token $GITEA_TOKEN")
|
||||||
|
|
||||||
@@ -309,14 +266,11 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect assets: kernel debs plus the versioned arch config.
|
# Upload the kernel .deb packages as release assets.
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
assets=( ./kernel/linux-*.deb )
|
assets=( ./kernel/linux-*.deb )
|
||||||
cfg="./build-configs/$TARGET_ARCH-$KERNEL_VERSION.config"
|
|
||||||
[ -f "$cfg" ] && assets+=( "$cfg" )
|
|
||||||
|
|
||||||
if [ "${#assets[@]}" -eq 0 ]; then
|
if [ "${#assets[@]}" -eq 0 ]; then
|
||||||
echo "No assets found to upload for $TAG" >&2
|
echo "No .deb assets found to upload for $TAG" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -328,55 +282,3 @@ jobs:
|
|||||||
-F "attachment=@$f" >/dev/null
|
-F "attachment=@$f" >/dev/null
|
||||||
done
|
done
|
||||||
echo "Published $TAG with ${#assets[@]} asset(s)."
|
echo "Published $TAG with ${#assets[@]} asset(s)."
|
||||||
|
|
||||||
update-config-baseline:
|
|
||||||
needs: [preflight, build]
|
|
||||||
if: ${{ needs.preflight.outputs.build_needed == 'true' && needs.build.result == 'success' }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
KERNEL_VERSION: ${{ needs.preflight.outputs.kernel_version }}
|
|
||||||
steps:
|
|
||||||
- name: 检出代码
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: 回写配置基线
|
|
||||||
run: |
|
|
||||||
set -euxo pipefail
|
|
||||||
auth=(-H "Authorization: token $GITEA_TOKEN")
|
|
||||||
|
|
||||||
# Pull the generated .config for a freshly published standard release back
|
|
||||||
# into the repo baseline. Config travels as a Gitea release asset (named
|
|
||||||
# "<arch>-<version>.config"), so no actions/artifact is needed.
|
|
||||||
refresh_baseline() {
|
|
||||||
local arch="$1" baseline="$2"
|
|
||||||
local tag="$arch-$KERNEL_VERSION" # standard release (no -max)
|
|
||||||
local rel asset_name url
|
|
||||||
rel=$(curl -sS "${auth[@]}" "$GITEA_API/releases/tags/$tag")
|
|
||||||
if [ -z "$(echo "$rel" | jq -r '.id // empty')" ]; then
|
|
||||||
echo "Release $tag not found; skipping $baseline."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
asset_name="$arch-$KERNEL_VERSION.config"
|
|
||||||
url=$(echo "$rel" | jq -r --arg n "$asset_name" \
|
|
||||||
'.assets[]? | select(.name == $n) | .browser_download_url' | head -n1)
|
|
||||||
if [ -z "$url" ]; then
|
|
||||||
echo "Config asset $asset_name not found on $tag; skipping $baseline."
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
curl -fsSL "${auth[@]}" -o "$baseline" "$url"
|
|
||||||
echo "Refreshed $baseline from $tag."
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh_baseline x86_64 x86-64.config
|
|
||||||
refresh_baseline arm64 arm64.config
|
|
||||||
|
|
||||||
if git diff --quiet -- x86-64.config arm64.config; then
|
|
||||||
echo "Generated configs match current baselines."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
git config user.name "gitea-actions[bot]"
|
|
||||||
git config user.email "gitea-actions[bot]@noreply.git.chilldove.com"
|
|
||||||
git add x86-64.config arm64.config
|
|
||||||
git commit -m "Refresh generated kernel config baselines [skip ci]"
|
|
||||||
git push
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# BBRv3 管理脚本
|
# BBRv3 内核安装脚本
|
||||||
|
|
||||||
一个用于 Debian/Ubuntu VPS 的 BBRv3 内核安装与网络加速管理脚本。
|
一个用于 Debian/Ubuntu VPS 的 BBRv3 内核安装脚本。脚本会自动识别系统架构,从本仓库的 Gitea Releases 下载匹配的 BBRv3 内核 `.deb` 包并安装。内核默认启用 BBR 拥塞控制并内置 `sch_cake`;安装脚本会写入 `/etc/sysctl.d/99-bbrv3.conf`,把默认队列算法设为 `cake` 并开启 ECN(`net.ipv4.tcp_ecn=1`),安装并重启后 BBR + CAKE + ECN 自动生效。
|
||||||
|
|
||||||
脚本入口:
|
脚本入口:
|
||||||
|
|
||||||
@@ -8,22 +8,11 @@
|
|||||||
bash <(curl -fsSL https://git.chilldove.com/icePigeon/linux-kernel-bbrv3/raw/branch/main/install.sh)
|
bash <(curl -fsSL https://git.chilldove.com/icePigeon/linux-kernel-bbrv3/raw/branch/main/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
首次运行后脚本会自动安装联网快捷命令,后续可直接运行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
b
|
|
||||||
```
|
|
||||||
|
|
||||||
快捷命令每次都会从 Gitea 拉取最新版脚本执行,不使用本地缓存脚本。
|
|
||||||
|
|
||||||
脚本会自动识别当前系统架构,从本仓库 Gitea Releases 下载匹配的 BBRv3 内核 `.deb` 包,并提供安装、指定版本安装、状态检查、加速模式切换和卸载功能。安装内核时可选择标准 BBRv3 或 BBRv3 Max 激进吞吐内核。
|
|
||||||
|
|
||||||
## 支持环境
|
## 支持环境
|
||||||
|
|
||||||
| 项目 | 要求 |
|
| 项目 | 要求 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 最低支持系统 | Ubuntu 24.04+ / Debian 12+ |
|
| 最低支持系统 | Ubuntu 24.04+ / Debian 12+ |
|
||||||
| 推荐系统 | Ubuntu 24.04+ / Debian 12+ |
|
|
||||||
| 包管理器 | `apt-get` |
|
| 包管理器 | `apt-get` |
|
||||||
| 架构 | `x86_64` / `aarch64` |
|
| 架构 | `x86_64` / `aarch64` |
|
||||||
| 引导方式 | 建议使用 GRUB |
|
| 引导方式 | 建议使用 GRUB |
|
||||||
@@ -31,40 +20,21 @@ b
|
|||||||
|
|
||||||
不建议在树莓派、NanoPi 等依赖 U-Boot 或厂商定制内核链路的设备上使用。此类设备的内核安装和启动流程通常与通用 Debian/Ubuntu VPS 不一致。
|
不建议在树莓派、NanoPi 等依赖 U-Boot 或厂商定制内核链路的设备上使用。此类设备的内核安装和启动流程通常与通用 Debian/Ubuntu VPS 不一致。
|
||||||
|
|
||||||
Debian testing/unstable 如果缺少 `VERSION_ID`,脚本会按 `VERSION_CODENAME` 识别 `bookworm`、`trixie`、`forky` 和 `sid`。Alpine Linux 暂不支持安装本项目内核包,因为当前 release 产物是 `.deb`,安装和引导流程依赖 Debian/Ubuntu 的包管理与内核安装链路。
|
Debian testing/unstable 如缺少 `VERSION_ID`,脚本会按 `VERSION_CODENAME` 识别 `bookworm`、`trixie`、`forky` 和 `sid`。Alpine 等非 Debian 系统不支持安装本项目内核包(产物是 `.deb`,依赖 Debian/Ubuntu 的包管理与内核安装链路)。
|
||||||
|
|
||||||
本项目当前内核主线为 Linux 7.x。安装内核时脚本会按最低支持系统拦截过旧环境,避免因用户态、initramfs 或引导链路过旧导致启动失败或 kernel panic。推荐系统是更稳妥的部署选择;旧系统仍可使用状态检查、网络调优、清空优化和卸载功能。
|
本项目内核主线为 Linux 7.x。安装内核时脚本会按最低支持系统拦截过旧环境,避免因用户态、initramfs 或引导链路过旧导致启动失败或 kernel panic。
|
||||||
|
|
||||||
## 菜单功能
|
## 菜单功能
|
||||||
|
|
||||||
运行脚本后会进入交互菜单:
|
运行脚本后进入交互菜单:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
1. 安装或更新 BBR v3 最新版
|
1. 安装或更新 BBR v3 内核(最新版)
|
||||||
2. 指定版本安装
|
2. 安装指定版本
|
||||||
3. 检查 BBR v3 状态
|
3. 检查 BBR v3 状态
|
||||||
4. 启用 BBR + FQ
|
4. 卸载 BBR v3 内核
|
||||||
5. 启用 BBR + FQ_CODEL
|
|
||||||
6. 启用 BBR + FQ_PIE
|
|
||||||
7. 启用 BBR + CAKE
|
|
||||||
8. 亚太机器 TCP 调优
|
|
||||||
9. 卸载 BBR 内核
|
|
||||||
10. BBR v3 智能带宽优化
|
|
||||||
11. 清空网络优化配置
|
|
||||||
12. BBR v3 疯批模式(极限测速挑战)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
常用流程:
|
|
||||||
|
|
||||||
1. 选择 `1` 安装或更新 BBRv3 内核,并按提示选择标准版或 Max 极限版。
|
|
||||||
2. 按提示重启系统。
|
|
||||||
3. 重新运行脚本,选择 `3` 检查 BBRv3 状态。
|
|
||||||
4. 按需选择 `4` 到 `7` 设置队列算法。
|
|
||||||
5. 亚太线路机器可选择 `8` 写入 TCP 收发窗口与空闲慢启动调优。
|
|
||||||
6. 不确定线路参数时可选择 `10` 自动测速并按带宽档位计算 TCP 缓冲区。
|
|
||||||
7. 做自有链路极限测速挑战时可选择 `12` 写入激进冲速率参数。
|
|
||||||
8. 需要撤回调优时可选择 `11` 清空脚本写入的网络优化配置。
|
|
||||||
|
|
||||||
## 内核与 BBR 策略
|
## 内核与 BBR 策略
|
||||||
|
|
||||||
本项目的构建目标是:
|
本项目的构建目标是:
|
||||||
@@ -82,36 +52,21 @@ linux-7.0.y -> patches/bbrv3-linux-7.0.patch
|
|||||||
linux-7.1.y -> patches/bbrv3-linux-7.1.patch
|
linux-7.1.y -> patches/bbrv3-linux-7.1.patch
|
||||||
```
|
```
|
||||||
|
|
||||||
同一个主线系列内的小版本更新会自动复用同一个 patch,例如 `7.0.11 -> 7.0.12`。如果内核跳到新的主线系列但仓库内还没有对应 patch,构建会直接失败,避免产出不可验证的内核包。
|
同一主线系列内的小版本更新会自动复用同一个 patch,例如 `7.0.11 -> 7.0.12`。如果内核跳到新的主线系列但仓库内还没有对应 patch,构建会直接失败,避免产出不可验证的内核包。
|
||||||
|
|
||||||
## 安装最新版
|
## 安装最新版
|
||||||
|
|
||||||
```bash
|
运行脚本后选择:
|
||||||
bash <(curl -fsSL https://git.chilldove.com/icePigeon/linux-kernel-bbrv3/raw/branch/main/install.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
首次运行后也可以直接输入:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
b
|
|
||||||
```
|
|
||||||
|
|
||||||
该命令会联网拉取最新版脚本后运行。
|
|
||||||
|
|
||||||
选择:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
1. 安装或更新 BBR v3 最新版
|
1. 安装或更新 BBR v3 内核(最新版)
|
||||||
```
|
```
|
||||||
|
|
||||||
脚本会:
|
脚本会:
|
||||||
|
|
||||||
- 检查系统是否为 Debian/Ubuntu。
|
- 检查系统是否为 Debian/Ubuntu,架构是否为 `x86_64` 或 `aarch64`。
|
||||||
- 检查架构是否为 `x86_64` 或 `aarch64`。
|
- 从 Gitea Releases 获取当前架构匹配的最新版本。
|
||||||
- 让用户选择标准 BBRv3 或 BBRv3 Max 激进吞吐内核。
|
- 下载内核 `.deb` 包,安装并更新引导配置。
|
||||||
- 从 Gitea Releases 获取当前架构和内核类型匹配的最新版本。
|
|
||||||
- 下载非 debug 的内核 `.deb` 包。
|
|
||||||
- 安装新内核并更新引导配置。
|
|
||||||
- 提示是否重启。
|
- 提示是否重启。
|
||||||
|
|
||||||
如果访问私有仓库或遇到 Gitea API 限流,可先设置 token:
|
如果访问私有仓库或遇到 Gitea API 限流,可先设置 token:
|
||||||
@@ -121,27 +76,23 @@ export GITEA_TOKEN=你的 Gitea Token
|
|||||||
bash <(curl -fsSL https://git.chilldove.com/icePigeon/linux-kernel-bbrv3/raw/branch/main/install.sh)
|
bash <(curl -fsSL https://git.chilldove.com/icePigeon/linux-kernel-bbrv3/raw/branch/main/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 指定版本安装
|
## 安装指定版本
|
||||||
|
|
||||||
运行脚本后选择:
|
运行脚本后选择:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
2. 指定版本安装
|
2. 安装指定版本
|
||||||
```
|
```
|
||||||
|
|
||||||
脚本会先让用户选择标准 BBRv3 或 BBRv3 Max,再列出当前架构可用的 release tag,并按编号安装指定版本。
|
脚本会列出当前架构可用的 release tag,并按编号安装指定版本。
|
||||||
|
|
||||||
release tag 格式:
|
release tag 格式:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
x86_64-7.0.11
|
x86_64-7.0.11
|
||||||
arm64-7.0.11
|
arm64-7.0.11
|
||||||
x86_64-7.0.11-max
|
|
||||||
arm64-7.0.11-max
|
|
||||||
```
|
```
|
||||||
|
|
||||||
其中不带 `-max` 的 tag 是标准 BBRv3 内核,带 `-max` 的 tag 是 BBRv3 Max 激进吞吐内核。Max 版会提高 Startup、ProbeBW 和 cwnd 策略的进攻性,但保留 BBRv3 的 loss、ECN、inflight 和 ProbeBW 反馈闭环,只适合自有链路吞吐测试,不建议日常生产使用。
|
|
||||||
|
|
||||||
## 检查 BBRv3 状态
|
## 检查 BBRv3 状态
|
||||||
|
|
||||||
运行脚本后选择:
|
运行脚本后选择:
|
||||||
@@ -154,7 +105,7 @@ arm64-7.0.11-max
|
|||||||
|
|
||||||
- `tcp_bbr` 模块版本是否为 `3`。
|
- `tcp_bbr` 模块版本是否为 `3`。
|
||||||
- 当前 TCP 拥塞控制算法是否为 `bbr`。
|
- 当前 TCP 拥塞控制算法是否为 `bbr`。
|
||||||
- Dirty Frag 相关模块黑名单是否写入。
|
- 当前默认队列算法是否为 `cake`。
|
||||||
|
|
||||||
也可以手动检查:
|
也可以手动检查:
|
||||||
|
|
||||||
@@ -162,234 +113,33 @@ arm64-7.0.11-max
|
|||||||
uname -r
|
uname -r
|
||||||
sysctl net.ipv4.tcp_congestion_control
|
sysctl net.ipv4.tcp_congestion_control
|
||||||
sysctl net.core.default_qdisc
|
sysctl net.core.default_qdisc
|
||||||
|
sysctl net.ipv4.tcp_ecn
|
||||||
modinfo tcp_bbr 2>/dev/null | grep '^version:'
|
modinfo tcp_bbr 2>/dev/null | grep '^version:'
|
||||||
```
|
```
|
||||||
|
|
||||||
## 加速模式
|
|
||||||
|
|
||||||
脚本支持以下组合:
|
|
||||||
|
|
||||||
| 菜单 | 拥塞控制 | 队列算法 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| 4 | `bbr` | `fq` |
|
|
||||||
| 5 | `bbr` | `fq_codel` |
|
|
||||||
| 6 | `bbr` | `fq_pie` |
|
|
||||||
| 7 | `bbr` | `cake` |
|
|
||||||
|
|
||||||
选择后脚本会立即尝试应用配置,并询问是否永久写入:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/etc/sysctl.d/99-joeyblog.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
脚本不仅会写入 `net.core.default_qdisc`,还会尝试把当前默认路由出口网卡的 root qdisc 立即替换为所选算法,避免只对新建队列生效、当前网卡实际仍保持旧队列。
|
|
||||||
|
|
||||||
对于需要模块加载的队列算法,脚本会尝试加载对应 `sch_*` 模块,并在需要时写入:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/etc/modules-load.d/joeyblog-qdisc.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
## 亚太机器 TCP 调优
|
|
||||||
|
|
||||||
运行脚本后选择:
|
|
||||||
|
|
||||||
```text
|
|
||||||
8. 亚太机器 TCP 调优
|
|
||||||
```
|
|
||||||
|
|
||||||
脚本会立即应用并永久写入以下配置:
|
|
||||||
|
|
||||||
```text
|
|
||||||
net.ipv4.tcp_wmem = 4096 16384 12582912
|
|
||||||
net.ipv4.tcp_rmem = 4096 131072 33554432
|
|
||||||
net.ipv4.tcp_limit_output_bytes = 4194304
|
|
||||||
net.ipv4.tcp_slow_start_after_idle = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
配置文件路径:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/etc/sysctl.d/99-joeyblog.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
## BBR v3 智能带宽优化
|
|
||||||
|
|
||||||
运行脚本后选择:
|
|
||||||
|
|
||||||
```text
|
|
||||||
10. BBR v3 智能带宽优化
|
|
||||||
```
|
|
||||||
|
|
||||||
脚本会优先安装并运行 Ookla 官方 `speedtest 1.2.0`,自动尝试附近测速服务器并获取上传/下载带宽;如果检测到 Python 版 `speedtest-cli`,会先自动移除并安装需要的 Ookla 官方版本。测速失败时会提示手动输入上传带宽。Speedtest 的测速节点延迟会被隐藏,不展示也不参与 RTT 计算,避免把测速节点延迟误当作真实业务线路延迟。
|
|
||||||
|
|
||||||
优化逻辑:
|
|
||||||
|
|
||||||
- 自动启用 `bbr` 拥塞控制和 `fq` 队列算法。
|
|
||||||
- 根据上传带宽和地区模式映射推荐 TCP buffer 档位。
|
|
||||||
- RTT 必须由用户手动输入,应填写真实链接延迟,使用 v2rayN 测出来的结果即可;不使用 Speedtest 测出来的 Ping。
|
|
||||||
- 用户手动选择亚太、美欧或手动 RTT + buffer 档位,不再按测速 RTT 自动判断。
|
|
||||||
- 亚太线路使用较保守的 buffer,美欧高延迟线路使用更大 buffer。
|
|
||||||
- 按机器内存设置 TCP buffer 上限,避免小内存 VPS 过度放大缓冲区。
|
|
||||||
- 同步写入 `net.core.rmem_max` / `net.core.wmem_max` / `tcp_rmem` / `tcp_wmem`。
|
|
||||||
- 保留 `tcp_limit_output_bytes = 4194304` 和 `tcp_slow_start_after_idle = 0`。
|
|
||||||
|
|
||||||
地区模式参考:
|
|
||||||
|
|
||||||
| 模式 | RTT 参考 |
|
|
||||||
| --- | --- |
|
|
||||||
| 亚太线路 | 通常小于 `100ms` |
|
|
||||||
| 美欧线路 | 通常 `150-300ms` |
|
|
||||||
| 手动 RTT | 按用户输入 RTT,并手动选择亚太或美欧 buffer 档位 |
|
|
||||||
|
|
||||||
配置同样写入:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/etc/sysctl.d/99-joeyblog.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
## BBR v3 疯批模式
|
|
||||||
|
|
||||||
运行脚本后选择:
|
|
||||||
|
|
||||||
```text
|
|
||||||
12. BBR v3 疯批模式(极限测速挑战)
|
|
||||||
```
|
|
||||||
|
|
||||||
该模式只面向自有链路的极限测速挑战,不建议日常使用。目标是尽量压榨单向吞吐和跑满带宽上限,会主动牺牲重传率、延迟抖动、排队延迟、连接稳定性、交互体验和流量公平性。
|
|
||||||
|
|
||||||
脚本会强制启用 `bbr` 拥塞控制和 `fq` 队列算法,并立即尝试替换当前默认路由出口网卡的 root qdisc。
|
|
||||||
|
|
||||||
写入参数:
|
|
||||||
|
|
||||||
```text
|
|
||||||
net.core.default_qdisc=fq
|
|
||||||
net.ipv4.tcp_congestion_control=bbr
|
|
||||||
net.core.rmem_max = 1073741824
|
|
||||||
net.core.wmem_max = 1073741824
|
|
||||||
net.core.optmem_max = 1073741824
|
|
||||||
net.core.netdev_max_backlog = 1000000
|
|
||||||
net.core.somaxconn = 65535
|
|
||||||
net.ipv4.tcp_wmem = 4096 1048576 1073741824
|
|
||||||
net.ipv4.tcp_rmem = 4096 1048576 1073741824
|
|
||||||
net.ipv4.tcp_limit_output_bytes = 268435456
|
|
||||||
net.ipv4.tcp_slow_start_after_idle = 0
|
|
||||||
net.ipv4.tcp_notsent_lowat = 4294967295
|
|
||||||
net.ipv4.tcp_autocorking = 0
|
|
||||||
net.ipv4.tcp_no_metrics_save = 1
|
|
||||||
net.ipv4.tcp_mtu_probing = 1
|
|
||||||
net.ipv4.tcp_fastopen = 3
|
|
||||||
net.ipv4.tcp_window_scaling = 1
|
|
||||||
net.ipv4.tcp_moderate_rcvbuf = 1
|
|
||||||
net.ipv4.tcp_ecn = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
脚本还会把当前默认出口网卡的运行态 `txqueuelen` 拉高到 `100000`,让测速时本机发送队列更激进。该项不是 sysctl 参数,不会写入 `/etc/sysctl.d/99-joeyblog.conf`。
|
|
||||||
|
|
||||||
其中核心参数应用失败会中止;不同内核可能不支持部分附加参数,脚本会尽量写入,失败的附加项不会阻断整个模式。
|
|
||||||
|
|
||||||
## 清空网络优化配置
|
|
||||||
|
|
||||||
运行脚本后选择:
|
|
||||||
|
|
||||||
```text
|
|
||||||
11. 清空网络优化配置
|
|
||||||
```
|
|
||||||
|
|
||||||
脚本会清理本项目写入的网络优化持久配置:
|
|
||||||
|
|
||||||
- `net.core.default_qdisc`
|
|
||||||
- `net.ipv4.tcp_congestion_control`
|
|
||||||
- `net.core.rmem_max` / `net.core.wmem_max` / `net.core.optmem_max`
|
|
||||||
- `net.core.netdev_max_backlog` / `net.core.somaxconn`
|
|
||||||
- `net.ipv4.tcp_rmem` / `net.ipv4.tcp_wmem`
|
|
||||||
- `net.ipv4.tcp_limit_output_bytes`
|
|
||||||
- `net.ipv4.tcp_slow_start_after_idle`
|
|
||||||
- `net.ipv4.tcp_notsent_lowat`
|
|
||||||
- `net.ipv4.tcp_autocorking`
|
|
||||||
- `net.ipv4.tcp_no_metrics_save`
|
|
||||||
- `net.ipv4.tcp_mtu_probing`
|
|
||||||
- `net.ipv4.tcp_fastopen`
|
|
||||||
- `net.ipv4.tcp_window_scaling`
|
|
||||||
- `net.ipv4.tcp_moderate_rcvbuf`
|
|
||||||
- `net.ipv4.tcp_ecn`
|
|
||||||
|
|
||||||
同时删除:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/etc/modules-load.d/joeyblog-qdisc.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
该功能只清空网络优化配置,不卸载 BBR 内核,也不移除 Dirty Frag 安全缓解规则。当前运行态参数可能需要重启后完全恢复为系统默认值。
|
|
||||||
|
|
||||||
## 安全缓解
|
|
||||||
|
|
||||||
脚本启动时会写入 Dirty Frag 风险面收敛规则:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/etc/modprobe.d/99-joeyblog-security.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
包含:
|
|
||||||
|
|
||||||
- `esp4` / `esp6` / `rxrpc` 黑名单,用于收敛 Dirty Frag 相关风险面。
|
|
||||||
|
|
||||||
如果模块当前已加载,脚本会尝试卸载;如果模块被占用,则黑名单会在重启后生效。
|
|
||||||
|
|
||||||
CVE-2026-31431 对应的 AEAD userspace 接口在新构建内核中由内核配置侧收敛:
|
|
||||||
|
|
||||||
```text
|
|
||||||
# CONFIG_CRYPTO_USER_API_AEAD is not set
|
|
||||||
```
|
|
||||||
|
|
||||||
因此安装脚本不再额外写入 `algif_aead` 黑名单。
|
|
||||||
如果旧版本脚本已经写入过该黑名单,新脚本只会在当前运行内核确认关闭 `CONFIG_CRYPTO_USER_API_AEAD` 后移除它。
|
|
||||||
|
|
||||||
## CVE-2026-31431 检测
|
|
||||||
|
|
||||||
仅检测,不利用:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
command -v python3 >/dev/null 2>&1 || (sudo apt update && sudo apt install -y python3)
|
|
||||||
curl -fsSL -o cve_2026_31431_detector.py https://git.chilldove.com/icePigeon/linux-kernel-bbrv3/raw/branch/main/cve_2026_31431_detector.py
|
|
||||||
chmod +x cve_2026_31431_detector.py
|
|
||||||
sudo python3 cve_2026_31431_detector.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## 内核包来源
|
|
||||||
|
|
||||||
`.deb` 内核包由 Gitea Actions 构建并发布到本仓库 Releases。
|
|
||||||
|
|
||||||
构建流程会:
|
|
||||||
|
|
||||||
- 读取 kernel.org 最新 stable 版本。
|
|
||||||
- 下载 `gregkh/linux` 对应 stable 分支。
|
|
||||||
- 应用仓库内固定 BBRv3 patch。
|
|
||||||
- 强制默认启用 BBR 和 fq。
|
|
||||||
- 关闭 debug info。
|
|
||||||
- 拒绝发布 `*-dbg*.deb` / `*-dbgsym*.deb`。
|
|
||||||
|
|
||||||
构建不会自动更新 BBR patch 本身。
|
|
||||||
|
|
||||||
## 卸载
|
## 卸载
|
||||||
|
|
||||||
运行脚本后选择:
|
运行脚本后选择:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
9. 卸载 BBR 内核
|
4. 卸载 BBR v3 内核
|
||||||
```
|
```
|
||||||
|
|
||||||
脚本会卸载由本项目安装的 BBR v3 内核包(包名带 `-bbrv3` / `-bbrv3-max` 后缀),并更新引导配置。卸载后建议重启。
|
脚本会卸载由本项目安装的 BBR v3 内核包(包名带 `-bbrv3` 后缀),删除 `/etc/sysctl.d/99-bbrv3.conf`,并更新引导配置。卸载后建议重启。
|
||||||
|
|
||||||
## 反馈
|
## 内核包来源
|
||||||
|
|
||||||
博客:
|
`.deb` 内核包由 Gitea Actions 构建并发布到本仓库 Releases,提供 `x86_64` 与 `arm64` 两种标准 BBRv3 内核(arm64 在同一台 x86_64 runner 上交叉编译)。
|
||||||
|
|
||||||
[JoeyBlog](https://joeyblog.net)
|
构建流程会:
|
||||||
|
|
||||||
反馈群组:
|
- 读取 kernel.org 最新 stable 版本。
|
||||||
|
- 下载 `gregkh/linux` 对应 stable 分支。
|
||||||
|
- 应用仓库内固定 BBRv3 patch。
|
||||||
|
- 默认启用 BBR,并把 `sch_cake` 编入内核(=y),安装脚本据此把默认队列设为 cake。
|
||||||
|
- 关闭 debug info,拒绝发布 `*-dbg*.deb` / `*-dbgsym*.deb`。
|
||||||
|
|
||||||
[Telegram Feedback Group](https://t.me/+ft-zI76oovgwNmRh)
|
构建不会自动更新 BBR patch 本身。
|
||||||
|
|
||||||
## 免责声明
|
## 免责声明
|
||||||
|
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
CVE-2026-31431 风险面检测脚本(仅检测,不利用)
|
|
||||||
|
|
||||||
检测项:
|
|
||||||
1) CVE-2026-31431 风险面(AEAD userspace 接口)
|
|
||||||
2) Dirty Frag 风险面(ESP/RXRPC 相关模块与配置)
|
|
||||||
"""
|
|
||||||
|
|
||||||
import gzip
|
|
||||||
import os
|
|
||||||
import socket
|
|
||||||
import subprocess
|
|
||||||
from typing import Optional, Tuple
|
|
||||||
|
|
||||||
|
|
||||||
def get_kernel_release() -> str:
|
|
||||||
return subprocess.check_output(["uname", "-r"], text=True).strip()
|
|
||||||
|
|
||||||
|
|
||||||
def read_kernel_config(kernel_release: str) -> Optional[str]:
|
|
||||||
boot_cfg = f"/boot/config-{kernel_release}"
|
|
||||||
if os.path.exists(boot_cfg):
|
|
||||||
with open(boot_cfg, "r", encoding="utf-8", errors="ignore") as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
proc_cfg = "/proc/config.gz"
|
|
||||||
if os.path.exists(proc_cfg):
|
|
||||||
with gzip.open(proc_cfg, "rt", encoding="utf-8", errors="ignore") as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def parse_aead_config(config_text: Optional[str]) -> str:
|
|
||||||
if not config_text:
|
|
||||||
return "未知(未找到内核配置)"
|
|
||||||
|
|
||||||
for line in config_text.splitlines():
|
|
||||||
if line.startswith("CONFIG_CRYPTO_USER_API_AEAD="):
|
|
||||||
return line.split("=", 1)[1].strip()
|
|
||||||
if line.strip() == "# CONFIG_CRYPTO_USER_API_AEAD is not set":
|
|
||||||
return "n"
|
|
||||||
return "未知(配置项不存在)"
|
|
||||||
|
|
||||||
|
|
||||||
def parse_tristate_symbol(config_text: Optional[str], symbol: str) -> str:
|
|
||||||
if not config_text:
|
|
||||||
return "未知(未找到内核配置)"
|
|
||||||
|
|
||||||
key = f"CONFIG_{symbol}="
|
|
||||||
disabled = f"# CONFIG_{symbol} is not set"
|
|
||||||
for line in config_text.splitlines():
|
|
||||||
if line.startswith(key):
|
|
||||||
return line.split("=", 1)[1].strip()
|
|
||||||
if line.strip() == disabled:
|
|
||||||
return "n"
|
|
||||||
return "未知(配置项不存在)"
|
|
||||||
|
|
||||||
|
|
||||||
def is_module_loaded(module_name: str) -> bool:
|
|
||||||
try:
|
|
||||||
with open("/proc/modules", "r", encoding="utf-8", errors="ignore") as f:
|
|
||||||
for line in f:
|
|
||||||
if line.startswith(module_name + " "):
|
|
||||||
return True
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def check_af_alg_aead_bind() -> Tuple[bool, str]:
|
|
||||||
af_alg = getattr(socket, "AF_ALG", 38)
|
|
||||||
sock_type = getattr(socket, "SOCK_SEQPACKET", 5)
|
|
||||||
|
|
||||||
try:
|
|
||||||
sock = socket.socket(af_alg, sock_type, 0)
|
|
||||||
except OSError as e:
|
|
||||||
return False, f"创建 socket 失败: {e}"
|
|
||||||
|
|
||||||
try:
|
|
||||||
sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
|
|
||||||
return True, "bind 成功"
|
|
||||||
except OSError as e:
|
|
||||||
return False, f"bind 失败: {e}"
|
|
||||||
finally:
|
|
||||||
try:
|
|
||||||
sock.close()
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def read_security_conf(path: str) -> str:
|
|
||||||
if not os.path.exists(path):
|
|
||||||
return ""
|
|
||||||
try:
|
|
||||||
with open(path, "r", encoding="utf-8", errors="ignore") as f:
|
|
||||||
return f.read()
|
|
||||||
except OSError:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def has_rule(text: str, rule: str) -> bool:
|
|
||||||
return any(line.strip() == rule for line in text.splitlines())
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
kernel = get_kernel_release()
|
|
||||||
cfg = read_kernel_config(kernel)
|
|
||||||
aead_cfg = parse_aead_config(cfg)
|
|
||||||
mod_loaded = is_module_loaded("algif_aead")
|
|
||||||
bind_ok, bind_msg = check_af_alg_aead_bind()
|
|
||||||
|
|
||||||
xfrm_esp = parse_tristate_symbol(cfg, "XFRM_ESP")
|
|
||||||
inet_esp = parse_tristate_symbol(cfg, "INET_ESP")
|
|
||||||
inet6_esp = parse_tristate_symbol(cfg, "INET6_ESP")
|
|
||||||
af_rxrpc = parse_tristate_symbol(cfg, "AF_RXRPC")
|
|
||||||
|
|
||||||
esp4_loaded = is_module_loaded("esp4")
|
|
||||||
esp6_loaded = is_module_loaded("esp6")
|
|
||||||
rxrpc_loaded = is_module_loaded("rxrpc")
|
|
||||||
|
|
||||||
security_conf_path = "/etc/modprobe.d/99-joeyblog-security.conf"
|
|
||||||
security_conf = read_security_conf(security_conf_path)
|
|
||||||
dirtyfrag_rules_ok = all(
|
|
||||||
has_rule(security_conf, rule)
|
|
||||||
for rule in (
|
|
||||||
"blacklist esp4",
|
|
||||||
"install esp4 /bin/false",
|
|
||||||
"blacklist esp6",
|
|
||||||
"install esp6 /bin/false",
|
|
||||||
"blacklist rxrpc",
|
|
||||||
"install rxrpc /bin/false",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"[*] 当前内核: {kernel}")
|
|
||||||
print("")
|
|
||||||
print("[CVE-2026-31431 检测]")
|
|
||||||
print(f"[*] CONFIG_CRYPTO_USER_API_AEAD: {aead_cfg}")
|
|
||||||
print(f"[*] algif_aead 已加载: {mod_loaded}")
|
|
||||||
print(f"[*] AF_ALG AEAD bind 可用: {bind_ok} ({bind_msg})")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
print("[Dirty Frag 检测]")
|
|
||||||
print(f"[*] CONFIG_XFRM_ESP: {xfrm_esp}")
|
|
||||||
print(f"[*] CONFIG_INET_ESP: {inet_esp}")
|
|
||||||
print(f"[*] CONFIG_INET6_ESP: {inet6_esp}")
|
|
||||||
print(f"[*] CONFIG_AF_RXRPC: {af_rxrpc}")
|
|
||||||
print(f"[*] esp4 已加载: {esp4_loaded}")
|
|
||||||
print(f"[*] esp6 已加载: {esp6_loaded}")
|
|
||||||
print(f"[*] rxrpc 已加载: {rxrpc_loaded}")
|
|
||||||
print(f"[*] Dirty Frag 黑名单规则完整: {dirtyfrag_rules_ok} ({security_conf_path})")
|
|
||||||
|
|
||||||
print("")
|
|
||||||
print("[检测结论]")
|
|
||||||
|
|
||||||
high_risk_surface = (aead_cfg in {"y", "m"}) and bind_ok
|
|
||||||
reduced_surface = (aead_cfg == "n") or (not bind_ok)
|
|
||||||
dirtyfrag_cfg_exposed = any(v in {"y", "m"} for v in (xfrm_esp, inet_esp, inet6_esp, af_rxrpc))
|
|
||||||
dirtyfrag_runtime_exposed = esp4_loaded or esp6_loaded or rxrpc_loaded
|
|
||||||
dirtyfrag_high_risk = dirtyfrag_cfg_exposed and (dirtyfrag_runtime_exposed or not dirtyfrag_rules_ok)
|
|
||||||
dirtyfrag_reduced = (not dirtyfrag_cfg_exposed) or (dirtyfrag_rules_ok and not dirtyfrag_runtime_exposed)
|
|
||||||
|
|
||||||
if high_risk_surface:
|
|
||||||
print("[!] 检测到高风险暴露面。")
|
|
||||||
print("[!] 若内核未包含上游修复补丁,系统可能受 CVE-2026-31431 影响。")
|
|
||||||
print("[!] 建议:升级到新构建内核,或禁用 CRYPTO_USER_API_AEAD;旧内核可临时屏蔽 algif_aead。")
|
|
||||||
elif reduced_surface:
|
|
||||||
print("[+] 风险面已收敛/已缓解。")
|
|
||||||
else:
|
|
||||||
print("[?] 结果不确定,请继续核对内核补丁级别。")
|
|
||||||
|
|
||||||
if dirtyfrag_high_risk:
|
|
||||||
print("[!] Dirty Frag 风险面暴露。")
|
|
||||||
print("[!] 建议:禁用 XFRM_ESP/INET_ESP/INET6_ESP/AF_RXRPC,并屏蔽 esp4/esp6/rxrpc。")
|
|
||||||
elif dirtyfrag_reduced:
|
|
||||||
print("[+] Dirty Frag 风险面已收敛/已缓解。")
|
|
||||||
else:
|
|
||||||
print("[?] Dirty Frag 结果不确定,请继续核对内核补丁级别。")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
+73
-1000
File diff suppressed because it is too large
Load Diff
@@ -1,91 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
target="${1:-net/ipv4/tcp_bbr.c}"
|
|
||||||
|
|
||||||
if [[ ! -f "$target" ]]; then
|
|
||||||
echo "BBRv3 source file not found: $target" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q '^#define BBR_VERSION[[:space:]]*3' "$target"; then
|
|
||||||
echo "BBRv3 max profile requires BBR_VERSION=3 in $target." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
python3 - "$target" <<'PY'
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
path = Path(sys.argv[1])
|
|
||||||
text = path.read_text()
|
|
||||||
|
|
||||||
replacements = {
|
|
||||||
r"static const u32 bbr_probe_rtt_win_ms = .*?;": "static const u32 bbr_probe_rtt_win_ms = 10000;",
|
|
||||||
r"static const u32 bbr_probe_rtt_cwnd_gain = .*?;": "static const u32 bbr_probe_rtt_cwnd_gain = BBR_UNIT;",
|
|
||||||
r"static const u32 bbr_probe_rtt_mode_ms = .*?;": "static const u32 bbr_probe_rtt_mode_ms = 10;",
|
|
||||||
r"static const u32 bbr_tso_rtt_shift = .*?;": "static const u32 bbr_tso_rtt_shift = 2;",
|
|
||||||
r"static const int bbr_pacing_margin_percent = .*?;": "static const int bbr_pacing_margin_percent = 0;",
|
|
||||||
r"static const int bbr_startup_pacing_gain = .*?;": "static const int bbr_startup_pacing_gain = BBR_UNIT * 3;",
|
|
||||||
r"static const int bbr_startup_cwnd_gain = .*?;": "static const int bbr_startup_cwnd_gain = BBR_UNIT * 5 / 2;",
|
|
||||||
r"static const int bbr_drain_gain = .*?;": "static const int bbr_drain_gain = BBR_UNIT / 2;",
|
|
||||||
r"static const int bbr_cwnd_gain = .*?;": "static const int bbr_cwnd_gain = BBR_UNIT * 5 / 2;",
|
|
||||||
r"static const u32 bbr_cwnd_min_target = .*?;": "static const u32 bbr_cwnd_min_target = 64;",
|
|
||||||
r"static const u32 bbr_full_bw_thresh = .*?;": "static const u32 bbr_full_bw_thresh = BBR_UNIT * 105 / 100;",
|
|
||||||
r"static const u32 bbr_full_bw_cnt = .*?;": "static const u32 bbr_full_bw_cnt = 8;",
|
|
||||||
r"static const int bbr_extra_acked_gain = .*?;": "static const int bbr_extra_acked_gain = BBR_UNIT * 2;",
|
|
||||||
r"static const u32 bbr_extra_acked_max_us = .*?;": "static const u32 bbr_extra_acked_max_us = 750 * 1000;",
|
|
||||||
r"static const bool bbr_precise_ece_ack = .*?;": "static const bool bbr_precise_ece_ack = true;",
|
|
||||||
r"static const u32 bbr_ecn_max_rtt_us = .*?;": "static const u32 bbr_ecn_max_rtt_us = 0;",
|
|
||||||
r"static const u32 bbr_beta = .*?;": "static const u32 bbr_beta = BBR_UNIT * 20 / 100;",
|
|
||||||
r"static const u32 bbr_ecn_alpha_gain = .*?;": "static const u32 bbr_ecn_alpha_gain = BBR_UNIT * 1 / 32;",
|
|
||||||
r"static const u32 bbr_ecn_alpha_init = .*?;": "static const u32 bbr_ecn_alpha_init = BBR_UNIT * 1 / 2;",
|
|
||||||
r"static const u32 bbr_ecn_factor = .*?;": "static const u32 bbr_ecn_factor = BBR_UNIT * 20 / 100;",
|
|
||||||
r"static const u32 bbr_ecn_thresh = .*?;": "static const u32 bbr_ecn_thresh = BBR_UNIT * 7 / 10;",
|
|
||||||
r"static const u32 bbr_ecn_reprobe_gain = .*?;": "static const u32 bbr_ecn_reprobe_gain = BBR_UNIT * 3 / 4;",
|
|
||||||
r"static const u32 bbr_loss_thresh = [^\n]*": "static const u32 bbr_loss_thresh = BBR_UNIT * 3 / 100; /* max: tolerate 3% loss before backing off */",
|
|
||||||
r"static const bool bbr_loss_probe_recovery = .*?;": "static const bool bbr_loss_probe_recovery = true;",
|
|
||||||
r"static const u32 bbr_full_loss_cnt = .*?;": "static const u32 bbr_full_loss_cnt = 8;",
|
|
||||||
r"static const u32 bbr_full_ecn_cnt = .*?;": "static const u32 bbr_full_ecn_cnt = 4;",
|
|
||||||
r"static const u32 bbr_inflight_headroom = .*?;": "static const u32 bbr_inflight_headroom = BBR_UNIT * 10 / 100;",
|
|
||||||
r"static const u32 bbr_bw_probe_cwnd_gain = .*?;": "static const u32 bbr_bw_probe_cwnd_gain = 2;",
|
|
||||||
r"static const u32 bbr_bw_probe_max_rounds = .*?;": "static const u32 bbr_bw_probe_max_rounds = 16;",
|
|
||||||
r"static const u32 bbr_bw_probe_rand_rounds = .*?;": "static const u32 bbr_bw_probe_rand_rounds = 2;",
|
|
||||||
r"static const u32 bbr_bw_probe_base_us = .*?;": "static const u32 bbr_bw_probe_base_us = 750 * 1000;",
|
|
||||||
r"static const u32 bbr_bw_probe_rand_us = .*?;": "static const u32 bbr_bw_probe_rand_us = 250 * 1000;",
|
|
||||||
}
|
|
||||||
|
|
||||||
missing = []
|
|
||||||
for pattern, replacement in replacements.items():
|
|
||||||
text, count = re.subn(pattern, replacement, text, count=1)
|
|
||||||
if count != 1:
|
|
||||||
missing.append(pattern)
|
|
||||||
|
|
||||||
pacing_pattern = re.compile(
|
|
||||||
r"static const int bbr_pacing_gain\[\] = \{\n"
|
|
||||||
r".*?\n"
|
|
||||||
r"\};",
|
|
||||||
re.S,
|
|
||||||
)
|
|
||||||
pacing_replacement = """static const int bbr_pacing_gain[] = {
|
|
||||||
\tBBR_UNIT * 3 / 2,\t/* UP: aggressive but keep BBR's feedback usable */
|
|
||||||
\tBBR_UNIT * 3 / 4,\t/* DOWN: drain the queue after probing */
|
|
||||||
\tBBR_UNIT,\t\t/* CRUISE: hold the measured pipe */
|
|
||||||
\tBBR_UNIT * 5 / 4,\t/* REFILL: refill faster than standard BBRv3 */
|
|
||||||
};"""
|
|
||||||
text, pacing_count = pacing_pattern.subn(pacing_replacement, text, count=1)
|
|
||||||
if pacing_count != 1:
|
|
||||||
missing.append("static const int bbr_pacing_gain[]")
|
|
||||||
|
|
||||||
if missing:
|
|
||||||
print("Failed to apply BBRv3 max profile; missing patterns:", file=sys.stderr)
|
|
||||||
for item in missing:
|
|
||||||
print(f" {item}", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
path.write_text(text)
|
|
||||||
PY
|
|
||||||
|
|
||||||
grep -nE 'bbr_(startup_pacing_gain|startup_cwnd_gain|cwnd_gain|pacing_gain|beta|loss_thresh|full_loss_cnt|full_ecn_cnt|inflight_headroom|bw_probe_cwnd_gain|probe_rtt_mode_ms|pacing_margin_percent)' "$target"
|
|
||||||
echo "Applied BBRv3 max profile to $target"
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
kernel_version="${1:-}"
|
|
||||||
arch="${2:-$(uname -m)}"
|
|
||||||
repo_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
|
||||||
workdir="${BBRV3_MAX_WORKDIR:-$repo_root/kernel-max}"
|
|
||||||
|
|
||||||
if [[ -z "$kernel_version" ]]; then
|
|
||||||
raw_version=$(curl -fsSL https://www.kernel.org/finger_banner |
|
|
||||||
awk -F: '/latest stable version/ {gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2; exit}')
|
|
||||||
if [[ "$raw_version" =~ ^[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
kernel_version="${raw_version}.0"
|
|
||||||
else
|
|
||||||
kernel_version="$raw_version"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$arch" in
|
|
||||||
aarch64|arm64)
|
|
||||||
build_arch="arm64"
|
|
||||||
config_arch="arm64"
|
|
||||||
;;
|
|
||||||
x86_64)
|
|
||||||
build_arch="x86_64"
|
|
||||||
config_arch="x86_64"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported arch: $arch" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if ! [[ "$kernel_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
echo "Unexpected kernel version: $kernel_version" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
branch=$(echo "$kernel_version" | grep -oE '^[0-9]+\.[0-9]+')
|
|
||||||
mkdir -p "$workdir"
|
|
||||||
|
|
||||||
if [[ ! -d "$workdir/linux/.git" ]]; then
|
|
||||||
git clone --depth=1 --branch "linux-$branch.y" \
|
|
||||||
https://github.com/gregkh/linux.git "$workdir/linux"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$workdir/linux"
|
|
||||||
git fetch --depth=1 origin "linux-$branch.y"
|
|
||||||
git reset --hard FETCH_HEAD
|
|
||||||
git clean -fdx
|
|
||||||
|
|
||||||
bash "$repo_root/scripts/apply-bbrv3-port.sh"
|
|
||||||
bash "$repo_root/scripts/apply-bbrv3-max-profile.sh"
|
|
||||||
|
|
||||||
grep -v "MODULE_DESCRIPTION" net/ipv4/tcp_bbr.c > net/ipv4/tcp_bbr.c.tmp
|
|
||||||
mv net/ipv4/tcp_bbr.c.tmp net/ipv4/tcp_bbr.c
|
|
||||||
echo 'MODULE_DESCRIPTION("TCP BBR v3 Max - aggressive throughput profile by Joey");' >> net/ipv4/tcp_bbr.c
|
|
||||||
|
|
||||||
IFS='.' read -r v p s <<< "$kernel_version"
|
|
||||||
sed -i "s/^VERSION *=.*/VERSION = $v/" Makefile
|
|
||||||
sed -i "s/^PATCHLEVEL *=.*/PATCHLEVEL = $p/" Makefile
|
|
||||||
sed -i "s/^SUBLEVEL *=.*/SUBLEVEL = $s/" Makefile
|
|
||||||
|
|
||||||
export GITHUB_WORKSPACE="$repo_root"
|
|
||||||
export KERNEL_VERSION="$kernel_version"
|
|
||||||
bash "$repo_root/scripts/prepare-kernel-config.sh" "$config_arch"
|
|
||||||
|
|
||||||
if [[ "$build_arch" == "arm64" ]]; then
|
|
||||||
make ARCH=arm64 bindeb-pkg -j"$(nproc)" LOCALVERSION=-bbrv3-max KDEB_COMPRESS=gzip skipdbg=true
|
|
||||||
else
|
|
||||||
make bindeb-pkg -j"$(nproc)" LOCALVERSION=-bbrv3-max KDEB_COMPRESS=gzip skipdbg=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if find "$workdir" -maxdepth 1 \( -name '*-dbg*.deb' -o -name '*-dbgsym*.deb' \) | grep -q .; then
|
|
||||||
echo "ERROR: debug deb package was generated." >&2
|
|
||||||
find "$workdir" -maxdepth 1 \( -name '*-dbg*.deb' -o -name '*-dbgsym*.deb' \) -print >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
find "$workdir" -maxdepth 1 -name 'linux-*.deb' -print | sort
|
|
||||||
@@ -27,7 +27,10 @@ apply_policy_config() {
|
|||||||
scripts/config --module NET_SCH_FQ_CODEL
|
scripts/config --module NET_SCH_FQ_CODEL
|
||||||
scripts/config --module NET_SCH_PIE
|
scripts/config --module NET_SCH_PIE
|
||||||
scripts/config --module NET_SCH_FQ_PIE
|
scripts/config --module NET_SCH_FQ_PIE
|
||||||
scripts/config --module NET_SCH_CAKE
|
# CAKE built in (=y) so net.core.default_qdisc=cake works at boot without
|
||||||
|
# depending on module load timing. The kernel's compile-time default qdisc
|
||||||
|
# choice has no "cake" option, so the installer sets it via a sysctl drop-in.
|
||||||
|
scripts/config --enable NET_SCH_CAKE
|
||||||
scripts/config --disable DEFAULT_FQ_CODEL
|
scripts/config --disable DEFAULT_FQ_CODEL
|
||||||
scripts/config --disable DEFAULT_PFIFO_FAST
|
scripts/config --disable DEFAULT_PFIFO_FAST
|
||||||
scripts/config --enable DEFAULT_FQ
|
scripts/config --enable DEFAULT_FQ
|
||||||
@@ -98,7 +101,7 @@ validate_config() {
|
|||||||
require_config_line 'CONFIG_NET_SCH_FQ_CODEL=m' 'CONFIG_NET_SCH_FQ_CODEL is not module-enabled.'
|
require_config_line 'CONFIG_NET_SCH_FQ_CODEL=m' 'CONFIG_NET_SCH_FQ_CODEL is not module-enabled.'
|
||||||
require_config_line 'CONFIG_NET_SCH_PIE=m' 'CONFIG_NET_SCH_PIE is not module-enabled.'
|
require_config_line 'CONFIG_NET_SCH_PIE=m' 'CONFIG_NET_SCH_PIE is not module-enabled.'
|
||||||
require_config_line 'CONFIG_NET_SCH_FQ_PIE=m' 'CONFIG_NET_SCH_FQ_PIE is not module-enabled.'
|
require_config_line 'CONFIG_NET_SCH_FQ_PIE=m' 'CONFIG_NET_SCH_FQ_PIE is not module-enabled.'
|
||||||
require_config_line 'CONFIG_NET_SCH_CAKE=m' 'CONFIG_NET_SCH_CAKE is not module-enabled.'
|
require_config_line 'CONFIG_NET_SCH_CAKE=y' 'CONFIG_NET_SCH_CAKE is not built in.'
|
||||||
require_config_line 'CONFIG_NET_SCH_DEFAULT=y' 'CONFIG_NET_SCH_DEFAULT is not enabled.'
|
require_config_line 'CONFIG_NET_SCH_DEFAULT=y' 'CONFIG_NET_SCH_DEFAULT is not enabled.'
|
||||||
require_config_line 'CONFIG_DEFAULT_FQ=y' 'CONFIG_DEFAULT_FQ is not enabled.'
|
require_config_line 'CONFIG_DEFAULT_FQ=y' 'CONFIG_DEFAULT_FQ is not enabled.'
|
||||||
require_config_line 'CONFIG_DEFAULT_NET_SCH="fq"' 'CONFIG_DEFAULT_NET_SCH is not fq.'
|
require_config_line 'CONFIG_DEFAULT_NET_SCH="fq"' 'CONFIG_DEFAULT_NET_SCH is not fq.'
|
||||||
@@ -129,7 +132,3 @@ run_olddefconfig
|
|||||||
apply_policy_config
|
apply_policy_config
|
||||||
run_olddefconfig
|
run_olddefconfig
|
||||||
validate_config
|
validate_config
|
||||||
|
|
||||||
mkdir -p "$GITHUB_WORKSPACE/build-configs"
|
|
||||||
cp .config "$GITHUB_WORKSPACE/build-configs/${arch}.config"
|
|
||||||
cp .config "$GITHUB_WORKSPACE/build-configs/${arch}-${KERNEL_VERSION}.config"
|
|
||||||
|
|||||||
Reference in New Issue
Block a user