Automate latest stable BBRv3 builds without debug packages

This commit is contained in:
byjoey
2026-06-09 17:22:27 +08:00
commit deff87f064
9 changed files with 20522 additions and 0 deletions
+263
View File
@@ -0,0 +1,263 @@
name: 构建带有BBRv3的内核
on:
workflow_dispatch:
schedule:
# Daily automatic kernel refresh. BBRv3 itself stays pinned to the repo patch.
- cron: "17 3 * * *"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
actions: write
concurrency:
group: bbrv3-kernel-build
cancel-in-progress: false
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: 删除旧的工作流运行记录
uses: Mattraks/delete-workflow-runs@main
with:
retain_days: 0
keep_minimum_runs: 0
build:
needs: cleanup
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runs_on: ubuntu-latest
- arch: arm64
runs_on: ubuntu-24.04-arm
runs-on: ${{ matrix.runs_on }}
env:
ARCH: ${{ matrix.arch }}
KERNEL_VERSION: ""
steps:
- name: 获取内核版本
id: get_kernel_version
run: |
version=$(curl -s https://www.kernel.org \
| grep -A1 -m1 "stable:" \
| grep -oP '\d+\.\d+\.\d+')
echo "KERNEL_VERSION=$version" >> $GITHUB_ENV
- name: 检查是否已发布
id: check_release
run: |
tag="${{ matrix.arch }}-${KERNEL_VERSION}"
if gh release view "$tag" >/dev/null 2>&1; then
echo "BUILD_NEEDED=false" >> "$GITHUB_ENV"
echo "$tag already exists; skipping build."
else
echo "BUILD_NEEDED=true" >> "$GITHUB_ENV"
echo "$tag does not exist; building latest kernel with pinned BBRv3 patch."
fi
- name: 检出代码
if: env.BUILD_NEEDED == 'true'
uses: actions/checkout@v4
- name: 安装依赖项
if: env.BUILD_NEEDED == 'true'
run: |
sudo apt-get update
sudo apt-get install -y \
git build-essential \
libncurses-dev libssl-dev libelf-dev \
bison bc flex rsync debhelper \
dpkg-dev fakeroot kmod cpio dwarves \
libdw-dev lz4 zstd xz-utils curl jq
- name: 创建源码目录
if: env.BUILD_NEEDED == 'true'
run: mkdir -p ./kernel/linux
- name: 下载内核源代码
if: env.BUILD_NEEDED == 'true'
working-directory: ./kernel
run: |
branch=$(echo "${{ env.KERNEL_VERSION }}" | grep -oP '^\d+\.\d+')
git clone --depth=1 --branch linux-$branch.y \
https://github.com/gregkh/linux.git linux
- name: 应用 BBRv3 补丁
if: env.BUILD_NEEDED == 'true'
working-directory: ./kernel/linux
run: |
bash "$GITHUB_WORKSPACE/scripts/apply-bbrv3-port.sh"
grep -n "BBR_VERSION" net/ipv4/tcp_bbr.c
- name: 编译声明
if: env.BUILD_NEEDED == 'true'
working-directory: ./kernel/linux
run: |
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 (Bottleneck Bandwidth and RTT) - Compiled & Optimized by Joey");' >> net/ipv4/tcp_bbr.c
tail -n 5 net/ipv4/tcp_bbr.c
- name: 更新 Makefile 中的版本号
if: env.BUILD_NEEDED == 'true'
working-directory: ./kernel/linux
run: |
IFS='.' read -r v p s <<< "${{ env.KERNEL_VERSION }}"
sed -i "s/^VERSION *=.*/VERSION = $v/" Makefile
sed -i "s/^PATCHLEVEL *=.*/PATCHLEVEL = $p/" Makefile
sed -i "s/^SUBLEVEL *=.*/SUBLEVEL = $s/" Makefile
- name: 准备 .config 并禁用证书检查
if: env.BUILD_NEEDED == 'true'
working-directory: ./kernel/linux
run: |
if [ "${{ matrix.arch }}" = "arm64" ]; then
cp "$GITHUB_WORKSPACE/arm64.config" .config
else
cp "$GITHUB_WORKSPACE/x86-64.config" .config
fi
scripts/config --disable SYSTEM_TRUSTED_KEYS
scripts/config --disable SYSTEM_REVOCATION_KEYS
scripts/config --enable TCP_CONG_BBR
scripts/config --disable DEFAULT_CUBIC
scripts/config --enable DEFAULT_BBR
scripts/config --set-str DEFAULT_TCP_CONG bbr
# Avoid generating kernel debug info and linux-image-*-dbg packages.
scripts/config --disable DEBUG_INFO
scripts/config --enable DEBUG_INFO_NONE
scripts/config --disable DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
scripts/config --disable DEBUG_INFO_DWARF4
scripts/config --disable DEBUG_INFO_DWARF5
scripts/config --disable DEBUG_INFO_REDUCED
scripts/config --disable DEBUG_INFO_COMPRESSED
scripts/config --disable DEBUG_INFO_SPLIT
scripts/config --disable DEBUG_INFO_BTF
scripts/config --disable DEBUG_INFO_BTF_MODULES
scripts/config --disable MODULE_ALLOW_BTF_MISMATCH
# Mitigation for Dirty Frag attack surface.
scripts/config --disable AFS_FS
scripts/config --disable XFRM_ESP
scripts/config --disable INET_ESP
scripts/config --disable INET6_ESP
scripts/config --disable AF_RXRPC
scripts/config --disable RXKAD
if [ "${{ matrix.arch }}" = "arm64" ]; then
make ARCH=arm64 olddefconfig
else
make olddefconfig
fi
scripts/config --disable AFS_FS
scripts/config --disable XFRM_ESP
scripts/config --disable INET_ESP
scripts/config --disable INET6_ESP
scripts/config --disable AF_RXRPC
scripts/config --disable RXKAD
scripts/config --enable TCP_CONG_BBR
scripts/config --disable DEFAULT_CUBIC
scripts/config --enable DEFAULT_BBR
scripts/config --set-str DEFAULT_TCP_CONG bbr
scripts/config --disable DEBUG_INFO
scripts/config --enable DEBUG_INFO_NONE
scripts/config --disable DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
scripts/config --disable DEBUG_INFO_DWARF4
scripts/config --disable DEBUG_INFO_DWARF5
scripts/config --disable DEBUG_INFO_REDUCED
scripts/config --disable DEBUG_INFO_COMPRESSED
scripts/config --disable DEBUG_INFO_SPLIT
scripts/config --disable DEBUG_INFO_BTF
scripts/config --disable DEBUG_INFO_BTF_MODULES
scripts/config --disable MODULE_ALLOW_BTF_MISMATCH
if [ "${{ matrix.arch }}" = "arm64" ]; then
make ARCH=arm64 olddefconfig
else
make olddefconfig
fi
if grep -q '^CONFIG_XFRM_ESP=' .config; then
echo "ERROR: CONFIG_XFRM_ESP is enabled; refusing to continue."
exit 1
fi
if grep -q '^CONFIG_INET_ESP=' .config; then
echo "ERROR: CONFIG_INET_ESP is enabled; refusing to continue."
exit 1
fi
if grep -q '^CONFIG_INET6_ESP=' .config; then
echo "ERROR: CONFIG_INET6_ESP is enabled; refusing to continue."
exit 1
fi
if grep -q '^CONFIG_AF_RXRPC=' .config; then
echo "ERROR: CONFIG_AF_RXRPC is enabled; refusing to continue."
exit 1
fi
if grep -q '^CONFIG_DEBUG_INFO=' .config; then
echo "ERROR: CONFIG_DEBUG_INFO is enabled; refusing to build debug kernel packages."
exit 1
fi
if ! grep -q '^CONFIG_TCP_CONG_BBR=y' .config; then
echo "ERROR: CONFIG_TCP_CONG_BBR is not built in."
exit 1
fi
if ! grep -q '^CONFIG_DEFAULT_BBR=y' .config; then
echo "ERROR: CONFIG_DEFAULT_BBR is not enabled."
exit 1
fi
if ! grep -q '^CONFIG_DEFAULT_TCP_CONG="bbr"' .config; then
echo "ERROR: CONFIG_DEFAULT_TCP_CONG is not bbr."
exit 1
fi
grep -E 'CONFIG_(DEBUG_INFO_NONE|TCP_CONG_BBR|DEFAULT_BBR|DEFAULT_TCP_CONG)=' .config
- name: 构建内核 Debian 包
if: env.BUILD_NEEDED == 'true'
working-directory: ./kernel/linux
run: |
if [ "${{ matrix.arch }}" = "arm64" ]; then
make ARCH=arm64 bindeb-pkg -j$(nproc) LOCALVERSION=-joeyblog-bbrv3 KDEB_COMPRESS=gzip skipdbg=true
else
make bindeb-pkg -j$(nproc) LOCALVERSION=-joeyblog-bbrv3 KDEB_COMPRESS=gzip skipdbg=true
fi
- name: 检查 deb 包
if: env.BUILD_NEEDED == 'true'
run: |
if find ./kernel -maxdepth 1 -name '*-dbg*.deb' | grep -q .; then
echo "ERROR: debug deb package was generated."
find ./kernel -maxdepth 1 -name '*-dbg*.deb' -print
exit 1
fi
find ./kernel -maxdepth 1 -name 'linux-*.deb' -print | sort
- name: 上传配置文件
if: env.BUILD_NEEDED == 'true'
uses: actions/upload-artifact@v4
with:
name: config-${{ matrix.arch }}
path: ./kernel/linux/.config
- name: 上传 deb 包
if: env.BUILD_NEEDED == 'true'
uses: actions/upload-artifact@v4
with:
name: deb-${{ matrix.arch }}
path: ./kernel/linux-*.deb
- name: 发布到 GitHub Release
if: env.BUILD_NEEDED == 'true'
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ matrix.arch }}-${{ env.KERNEL_VERSION }}
files: ./kernel/linux-*.deb
body: "带有 BBRv3 的最新内核,适用于 ${{ matrix.arch }} 架构。Compiled & Optimized by Joey."
+2
View File
@@ -0,0 +1,2 @@
MIT 许可证
+169
View File
@@ -0,0 +1,169 @@
# Actions BBRv3 Kernel
面向 Debian/Ubuntu VPS 的 BBRv3 内核自动构建与安装项目。
本项目的核心目标很明确:**BBRv3 补丁固定,内核自动跟随 kernel.org 最新 stable 版本更新**。构建流程每天检查最新 stable 内核,下载对应 Linux stable 分支源码,然后把仓库内固定的 BBRv3 patch 打到新内核上并生成 Debian 包。
## 当前策略
- 内核版本:自动读取 kernel.org 最新 stable 版本。
- BBR 版本:固定使用仓库内的 BBRv3 port patch,不自动更新 BBR 实现。
- 支持架构:`x86_64``arm64`
- 构建产物:`linux-image``linux-headers``linux-libc-dev``.deb` 包。
- Debug 包:默认不编译、不上传、不发布 `linux-image-*-dbg`
- 发布方式:每个架构和内核版本生成独立 GitHub Release tag,例如 `x86_64-7.0.11``arm64-7.0.11`
## 自动更新边界
同一个内核主线系列内的小版本更新会自动复用同一个 patch。
例如:
```text
7.0.11 -> 7.0.12
使用 patches/bbrv3-linux-7.0.patch
```
如果 kernel.org 最新 stable 跳到新的主线系列,例如:
```text
7.0.x -> 7.1.x
```
构建脚本会寻找:
```text
patches/bbrv3-linux-7.1.patch
```
如果该 patch 不存在,构建会明确失败并停止。这是有意设计:跨主线系列时 TCP/BBR 相关代码可能变化,不能盲目把旧 patch 打上去。
## 安装
在 Debian/Ubuntu VPS 上执行:
```bash
bash <(curl -fsSL https://raw.githubusercontent.com/byJoey/Actions-bbr-v3/main/install.sh)
```
脚本会从当前 GitHub Releases 中选择适合本机架构的内核包,并提供安装、检查、切换队列算法和卸载入口。
## 支持环境
| 项目 | 要求 |
| --- | --- |
| 架构 | `x86_64` / `aarch64` |
| 系统 | Debian 10+ / Ubuntu 18.04+ |
| 引导 | GRUB |
| 场景 | VPS / 云服务器 / 独立服务器 |
不建议在树莓派、NanoPi 等使用 U-Boot 或厂商定制内核链路的设备上使用。
## GitHub Actions 构建流程
构建流程在 `.github/workflows/build.yml` 中定义:
1. 读取 kernel.org 最新 stable 版本。
2. 检查当前架构对应 release 是否已经存在,存在则跳过。
3. 下载 `gregkh/linux``linux-X.Y.y` stable 分支。
4. 使用 `scripts/apply-bbrv3-port.sh` 应用固定 BBRv3 patch。
5. 套用对应架构 `.config` 并运行 `olddefconfig`
6. 强制关闭 debug info,避免生成 `-dbg` 包。
7. 构建 Debian 包并发布到 GitHub Release。
手动触发:
```bash
gh workflow run build.yml
```
查看最近构建:
```bash
gh run list --limit 5
```
## BBRv3 Patch 管理
当前固定 patch
```text
patches/bbrv3-linux-7.0.patch
```
脚本会根据内核源码 `Makefile` 中的 `VERSION``PATCHLEVEL` 自动选择对应 patch
```text
linux-7.0.y -> patches/bbrv3-linux-7.0.patch
linux-7.1.y -> patches/bbrv3-linux-7.1.patch
```
这保证了两点:
- 小版本自动更新时不需要改 BBR。
- 新主线系列不兼容时会明确失败,避免产出不可验证的内核。
## 安全与配置
构建流程会在 `.config` 中强制关闭以下风险面:
- `CONFIG_AFS_FS`
- `CONFIG_AF_RXRPC`
- `CONFIG_RXKAD`
- `CONFIG_XFRM_ESP`
- `CONFIG_INET_ESP`
- `CONFIG_INET6_ESP`
- `CONFIG_SYSTEM_TRUSTED_KEYS`
- `CONFIG_SYSTEM_REVOCATION_KEYS`
同时关闭 debug info
- `CONFIG_DEBUG_INFO`
- `CONFIG_DEBUG_INFO_BTF`
- `CONFIG_DEBUG_INFO_BTF_MODULES`
构建结束后会检查是否生成 `*-dbg*.deb`。如果出现 debug debworkflow 会直接失败。
## 检测脚本
仓库提供 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://raw.githubusercontent.com/byJoey/Actions-bbr-v3/main/cve_2026_31431_detector.py
chmod +x cve_2026_31431_detector.py
sudo python3 cve_2026_31431_detector.py
```
检测脚本只做本机风险面检查,不执行漏洞利用。
## 常用命令
检查当前 TCP 拥塞算法:
```bash
sysctl net.ipv4.tcp_congestion_control
```
检查当前默认队列算法:
```bash
sysctl net.core.default_qdisc
```
启用常见组合:
```bash
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
sudo sysctl -w net.core.default_qdisc=fq
```
确认当前内核版本:
```bash
uname -r
```
## 免责声明
内核升级有风险。安装前建议保留可启动的旧内核,并确认 VPS 控制台或救援模式可用。使用本项目构建或安装的内核造成的系统启动失败、网络异常或数据损失,由使用者自行承担。
+5081
View File
File diff suppressed because it is too large Load Diff
+186
View File
@@ -0,0 +1,186 @@
#!/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()
+505
View File
@@ -0,0 +1,505 @@
#!/bin/bash
# 限制脚本仅支持基于 Debian/Ubuntu 的系统
if ! command -v apt-get &> /dev/null; then
echo -e "\033[31m此脚本仅支持基于 Debian/Ubuntu 的系统,请在支持 apt-get 的系统上运行!\033[0m"
exit 1
fi
# 在 root 环境且未安装 sudo 时提供兼容包装,避免命令直接失败
if ! command -v sudo &> /dev/null; then
if [[ "$(id -u)" -eq 0 ]]; then
sudo() { "$@"; }
else
echo -e "\033[31m缺少依赖:sudo。请先安装 sudo 后重试。\033[0m"
exit 1
fi
fi
# 检查并安装必要的依赖
REQUIRED_CMDS=("curl" "wget" "dpkg" "awk" "sed" "sysctl" "jq")
for cmd in "${REQUIRED_CMDS[@]}"; do
if ! command -v $cmd &> /dev/null; then
echo -e "\033[33m缺少依赖:$cmd,正在安装...\033[0m"
sudo apt-get update && sudo apt-get install -y $cmd > /dev/null 2>&1
fi
done
# 检测系统架构
ARCH=$(uname -m)
if [[ "$ARCH" != "aarch64" && "$ARCH" != "x86_64" ]]; then
echo -e "\033[31m( ̄□ ̄)哇!这个脚本只支持 ARM 和 x86_64 架构哦~ 您的系统架构是:$ARCH\033[0m"
exit 1
fi
# 获取当前 BBR 状态
CURRENT_ALGO=$(sysctl net.ipv4.tcp_congestion_control | awk '{print $3}')
CURRENT_QDISC=$(sysctl net.core.default_qdisc | awk '{print $3}')
# sysctl 配置文件路径
SYSCTL_CONF="/etc/sysctl.d/99-joeyblog.conf"
# 模块自动加载配置文件路径
MODULES_CONF="/etc/modules-load.d/joeyblog-qdisc.conf"
# 安全加固配置(缓解 CVE-2026-31431
SECURITY_MODPROBE_CONF="/etc/modprobe.d/99-joeyblog-security.conf"
# 可选:提升 GitHub API 限额(支持 GITHUB_TOKEN / GH_TOKEN
GITHUB_API_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
gh_api_get() {
local url="$1"
if [[ -n "$GITHUB_API_TOKEN" ]]; then
curl -fsSL \
-H "Authorization: Bearer $GITHUB_API_TOKEN" \
-H "Accept: application/vnd.github+json" \
"$url"
else
curl -fsSL "$url"
fi
}
check_release_api_response() {
local response="$1"
local api_message=""
api_message=$(echo "$response" | jq -r 'if type=="object" then .message // "" else "" end')
if [[ -n "$api_message" ]]; then
echo -e "\033[31mGitHub API 返回错误:$api_message\033[0m"
if echo "$api_message" | grep -qi "rate limit exceeded"; then
echo -e "\033[33m提示:可先执行 export GITHUB_TOKEN=你的令牌,再重新运行脚本。\033[0m"
fi
return 1
fi
if ! echo "$response" | jq -e 'type=="array"' > /dev/null 2>&1; then
echo -e "\033[31mGitHub API 返回数据格式异常,无法继续。\033[0m"
return 1
fi
}
# 函数:清理 sysctl.d 中的旧配置
clean_sysctl_conf() {
sudo touch "$SYSCTL_CONF"
sudo sed -i '/net.core.default_qdisc/d' "$SYSCTL_CONF"
sudo sed -i '/net.ipv4.tcp_congestion_control/d' "$SYSCTL_CONF"
}
# 函数:加载队列调度模块
load_qdisc_module() {
local qdisc_name="$1"
local module_name="sch_$qdisc_name"
# 检查队列算法是否已可用(通过尝试读取当前可用的 qdisc)
# 如果 sysctl 能成功设置,说明模块已存在
if sudo sysctl -w net.core.default_qdisc="$qdisc_name" > /dev/null 2>&1; then
# 恢复原设置
sudo sysctl -w net.core.default_qdisc="$CURRENT_QDISC" > /dev/null 2>&1
return 0
fi
# 检查模块是否已加载
if lsmod | grep -q "^${module_name//-/_}"; then
return 0
fi
# 模块不存在,尝试加载
echo -e "\033[36m正在加载内核模块 $module_name...\033[0m"
if sudo modprobe "$module_name" 2>/dev/null; then
echo -e "\033[1;32m✔ 模块 $module_name 加载成功\033[0m"
return 0
else
echo -e "\033[33m⚠ 模块 $module_name 加载失败,可能内核不支持\033[0m"
return 1
fi
}
# 函数:确保安全规则存在(不存在则追加)
ensure_security_rule() {
local rule="$1"
local changed_var="$2"
if ! grep -Fqx "$rule" "$SECURITY_MODPROBE_CONF" 2>/dev/null; then
echo "$rule" | sudo tee -a "$SECURITY_MODPROBE_CONF" > /dev/null
eval "$changed_var=1"
fi
}
# 函数:应用安全缓解(CVE-2026-31431 + Dirty Frag
apply_security_mitigations() {
local changed=0
sudo touch "$SECURITY_MODPROBE_CONF"
if ! grep -Fqx "# Managed by Actions-bbr-v3" "$SECURITY_MODPROBE_CONF" 2>/dev/null; then
echo "# Managed by Actions-bbr-v3" | sudo tee -a "$SECURITY_MODPROBE_CONF" > /dev/null
changed=1
fi
# CVE-2026-31431 mitigation
ensure_security_rule "blacklist algif_aead" changed
ensure_security_rule "install algif_aead /bin/false" changed
# Dirty Frag mitigation
ensure_security_rule "blacklist esp4" changed
ensure_security_rule "install esp4 /bin/false" changed
ensure_security_rule "blacklist esp6" changed
ensure_security_rule "install esp6 /bin/false" changed
ensure_security_rule "blacklist rxrpc" changed
ensure_security_rule "install rxrpc /bin/false" changed
for mod in algif_aead esp4 esp6 rxrpc; do
if lsmod | grep -q "^$mod"; then
if sudo modprobe -r "$mod" 2>/dev/null; then
echo -e "\033[1;32m✔ 已卸载 $mod 模块,当前会话已完成缓解\033[0m"
else
echo -e "\033[33m⚠ $mod 当前被占用,已写入黑名单,重启后将生效\033[0m"
fi
fi
done
if [[ "$changed" -eq 1 ]]; then
echo -e "\033[1;32m✔ 已写入安全策略:$SECURITY_MODPROBE_CONF\033[0m"
fi
}
# 函数:询问是否永久保存更改
ask_to_save() {
# 首先尝试加载队列调度模块
load_qdisc_module "$QDISC"
# 立即应用设置
echo -e "\033[36m正在应用配置...\033[0m"
sudo sysctl -w net.core.default_qdisc="$QDISC" > /dev/null 2>&1
sudo sysctl -w net.ipv4.tcp_congestion_control="$ALGO" > /dev/null 2>&1
# 验证是否生效
NEW_QDISC=$(sysctl -n net.core.default_qdisc 2>/dev/null)
NEW_ALGO=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null)
if [[ "$NEW_QDISC" == "$QDISC" && "$NEW_ALGO" == "$ALGO" ]]; then
echo -e "\033[1;32m✔ 配置已立即生效!\033[0m"
echo -e "\033[36m 当前队列算法:\033[1;32m$NEW_QDISC\033[0m"
echo -e "\033[36m 当前拥塞控制:\033[1;32m$NEW_ALGO\033[0m"
else
echo -e "\033[31m✘ 配置应用失败!\033[0m"
echo -e "\033[33m 队列算法期望:$QDISC,实际:$NEW_QDISC\033[0m"
echo -e "\033[33m 拥塞控制期望:$ALGO,实际:$NEW_ALGO\033[0m"
echo -e "\033[33m 可能原因:当前内核不支持 $QDISC 队列算法\033[0m"
return 1
fi
echo -n -e "\033[36m(。♥‿♥。) 要将这些配置永久保存到 $SYSCTL_CONF 吗?(y/n): \033[0m"
read -r SAVE
if [[ "$SAVE" == "y" || "$SAVE" == "Y" ]]; then
clean_sysctl_conf
echo "net.core.default_qdisc=$QDISC" | sudo tee -a "$SYSCTL_CONF" > /dev/null
echo "net.ipv4.tcp_congestion_control=$ALGO" | sudo tee -a "$SYSCTL_CONF" > /dev/null
sudo sysctl --system > /dev/null 2>&1
# 配置模块开机自动加载(fq 和 fq_codel 是内置的不需要)
if [[ "$QDISC" == "fq" || "$QDISC" == "fq_codel" ]]; then
# fq 和 fq_codel 是内核内置的,删除旧的模块配置文件
sudo rm -f "$MODULES_CONF"
echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存啦~\033[0m"
else
echo "sch_$QDISC" | sudo tee "$MODULES_CONF" > /dev/null
echo -e "\033[1;32m(☆^ー^☆) 更改已永久保存,模块 sch_$QDISC 将在开机时自动加载~\033[0m"
fi
else
echo -e "\033[33m(⌒_⌒;) 好吧,没有永久保存,重启后会恢复原设置呢~\033[0m"
fi
}
# 函数:获取已安装的 joeyblog 内核版本
get_installed_version() {
dpkg -l | grep "linux-image" | grep "joeyblog" | awk '{print $2}' | sed 's/linux-image-//' | head -n 1
}
# 函数:智能更新引导加载程序
update_bootloader() {
echo -e "\033[36m正在更新引导加载程序...\033[0m"
if command -v update-grub &> /dev/null; then
echo -e "\033[33m检测到 GRUB,正在执行 update-grub...\033[0m"
if sudo update-grub; then
echo -e "\033[1;32mGRUB 更新成功!\033[0m"
return 0
else
echo -e "\033[1;31mGRUB 更新失败!\033[0m"
return 1
fi
else
echo -e "\033[33m未找到 'update-grub'。您的系统可能使用 U-Boot 或其他引导程序。\033[0m"
echo -e "\033[33m在许多 ARM 系统上,内核安装包会自动处理引导更新,通常无需手动操作。\033[0m"
echo -e "\033[33m如果重启后新内核未生效,您可能需要手动更新引导配置,请参考您系统的文档。\033[0m"
return 0
fi
}
# 函数:安全地安装下载的包
install_packages() {
if ! ls /tmp/linux-*.deb &> /dev/null; then
echo -e "\033[31m错误:未在 /tmp 目录下找到内核文件,安装中止。\033[0m"
return 1
fi
for deb_file in /tmp/linux-*.deb; do
if ! dpkg-deb -I "$deb_file" > /dev/null 2>&1; then
echo -e "\033[31m当前系统无法读取安装包:$deb_file\033[0m"
echo -e "\033[33m可能原因:dpkg 版本过旧,不支持该压缩格式。建议升级 dpkg 后重试。\033[0m"
return 1
fi
done
echo -e "\033[36m开始卸载旧版内核... \033[0m"
INSTALLED_PACKAGES=$(dpkg -l | grep "joeyblog" | awk '{print $2}' | tr '\n' ' ')
if [[ -n "$INSTALLED_PACKAGES" ]]; then
sudo apt-get remove --purge $INSTALLED_PACKAGES -y > /dev/null 2>&1
fi
echo -e "\033[36m开始安装新内核... \033[0m"
if sudo dpkg -i /tmp/linux-*.deb && update_bootloader; then
echo -e "\033[1;32m内核安装并配置完成!\033[0m"
echo -n -e "\033[33m需要重启系统来加载新内核。是否立即重启? (y/n): \033[0m"
read -r REBOOT_NOW
if [[ "$REBOOT_NOW" == "y" || "$REBOOT_NOW" == "Y" ]]; then
echo -e "\033[36m系统即将重启...\033[0m"
sudo reboot
else
echo -e "\033[33m操作完成。请记得稍后手动重启 ('sudo reboot') 来应用新内核。\033[0m"
fi
else
echo -e "\033[1;31m内核安装或引导更新失败!系统可能处于不稳定状态。请不要重启并寻求手动修复!\033[0m"
fi
}
# 函数:检查并安装最新版本
install_latest_version() {
echo -e "\033[36m正在从 GitHub 获取最新版本信息...\033[0m"
BASE_URL="https://api.github.com/repos/byJoey/Actions-bbr-v3/releases"
RELEASE_DATA=$(gh_api_get "$BASE_URL")
if [[ -z "$RELEASE_DATA" ]]; then
echo -e "\033[31m从 GitHub 获取版本信息失败。请检查网络连接或 API 状态。\033[0m"
return 1
fi
check_release_api_response "$RELEASE_DATA" || return 1
local ARCH_FILTER=""
[[ "$ARCH" == "aarch64" ]] && ARCH_FILTER="arm64"
[[ "$ARCH" == "x86_64" ]] && ARCH_FILTER="x86_64"
LATEST_TAG_NAME=$(echo "$RELEASE_DATA" | jq -r --arg filter "$ARCH_FILTER" 'map(select(.tag_name | test($filter; "i"))) | sort_by(.published_at) | .[-1].tag_name')
if [[ -z "$LATEST_TAG_NAME" || "$LATEST_TAG_NAME" == "null" ]]; then
echo -e "\033[31m未找到适合当前架构 ($ARCH) 的最新版本。\033[0m"
return 1
fi
echo -e "\033[36m检测到最新版本:\033[0m\033[1;32m$LATEST_TAG_NAME\033[0m"
INSTALLED_VERSION=$(get_installed_version)
echo -e "\033[36m当前已安装版本:\033[0m\033[1;32m${INSTALLED_VERSION:-"未安装"}\033[0m"
CORE_LATEST_VERSION="${LATEST_TAG_NAME#x86_64-}"
CORE_LATEST_VERSION="${CORE_LATEST_VERSION#arm64-}"
if [[ -n "$INSTALLED_VERSION" && "$INSTALLED_VERSION" == "$CORE_LATEST_VERSION"* ]]; then
# 修复了此处的颜文字,将反引号 ` 替换为单引号 '
echo -e "\033[1;32m(o'▽'o) 您已安装最新版本,无需更新!\033[0m"
return 0
fi
echo -e "\033[33m发现新版本或未安装内核,准备下载...\033[0m"
ASSET_URLS=$(echo "$RELEASE_DATA" | jq -r --arg tag "$LATEST_TAG_NAME" '
.[] | select(.tag_name == $tag) | .assets[].browser_download_url
| select(test("(-dbg_|-dbgsym_)"; "i") | not)
')
rm -f /tmp/linux-*.deb
for URL in $ASSET_URLS; do
echo -e "\033[36m正在下载文件:$URL\033[0m"
wget -q --show-progress "$URL" -P /tmp/ || { echo -e "\033[31m下载失败:$URL\033[0m"; return 1; }
done
install_packages
}
# 函数:安装指定版本
install_specific_version() {
BASE_URL="https://api.github.com/repos/byJoey/Actions-bbr-v3/releases"
RELEASE_DATA=$(gh_api_get "$BASE_URL")
if [[ -z "$RELEASE_DATA" ]]; then
echo -e "\033[31m从 GitHub 获取版本信息失败。请检查网络连接或 API 状态。\033[0m"
return 1
fi
check_release_api_response "$RELEASE_DATA" || return 1
local ARCH_FILTER=""
[[ "$ARCH" == "aarch64" ]] && ARCH_FILTER="arm64"
[[ "$ARCH" == "x86_64" ]] && ARCH_FILTER="x86_64"
MATCH_TAGS=$(echo "$RELEASE_DATA" | jq -r --arg filter "$ARCH_FILTER" '.[] | select(.tag_name | test($filter; "i")) | .tag_name')
if [[ -z "$MATCH_TAGS" ]]; then
echo -e "\033[31m未找到适合当前架构的版本。\033[0m"
return 1
fi
echo -e "\033[36m以下为适用于当前架构的版本:\033[0m"
IFS=$'\n' read -rd '' -a TAG_ARRAY <<<"$MATCH_TAGS"
for i in "${!TAG_ARRAY[@]}"; do
echo -e "\033[33m $((i+1)). ${TAG_ARRAY[$i]}\033[0m"
done
echo -n -e "\033[36m请输入要安装的版本编号(例如 1):\033[0m"
read -r CHOICE
if ! [[ "$CHOICE" =~ ^[0-9]+$ ]] || (( CHOICE < 1 || CHOICE > ${#TAG_ARRAY[@]} )); then
echo -e "\033[31m输入无效编号,取消操作。\033[0m"
return 1
fi
INDEX=$((CHOICE-1))
SELECTED_TAG="${TAG_ARRAY[$INDEX]}"
echo -e "\033[36m已选择版本:\033[0m\033[1;32m$SELECTED_TAG\033[0m"
ASSET_URLS=$(echo "$RELEASE_DATA" | jq -r --arg tag "$SELECTED_TAG" '
.[] | select(.tag_name == $tag) | .assets[].browser_download_url
| select(test("(-dbg_|-dbgsym_)"; "i") | not)
')
rm -f /tmp/linux-*.deb
for URL in $ASSET_URLS; do
echo -e "\033[36m下载中:$URL\033[0m"
wget -q --show-progress "$URL" -P /tmp/ || { echo -e "\033[31m下载失败:$URL\033[0m"; return 1; }
done
install_packages
}
# 美化输出的分隔线
print_separator() {
echo -e "\033[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m"
}
# --- 主要执行流程 ---
clear
apply_security_mitigations
print_separator
echo -e "\033[1;35m(☆ω☆)✧*。 欢迎来到 BBR 管理脚本世界哒! ✧*。(☆ω☆)\033[0m"
print_separator
echo -e "\033[36m当前 TCP 拥塞控制算法:\033[0m\033[1;32m$CURRENT_ALGO\033[0m"
echo -e "\033[36m当前队列管理算法:    \033[0m\033[1;32m$CURRENT_QDISC\033[0m"
print_separator
echo -e "\033[1;33m作者:Joey | 博客:https://joeyblog.net | 反馈群组:https://t.me/+ft-zI76oovgwNmRh\033[0m"
print_separator
echo -e "\033[1;33m╭( ・ㅂ・)و ✧ 你可以选择以下操作哦:\033[0m"
echo -e "\033[33m 1. 🚀 安装或更新 BBR v3 (最新版)\033[0m"
echo -e "\033[33m 2. 📚 指定版本安装\033[0m"
echo -e "\033[33m 3. 🔍 检查 BBR v3 状态\033[0m"
echo -e "\033[33m 4. ⚡ 启用 BBR + FQ\033[0m"
echo -e "\033[33m 5. ⚡ 启用 BBR + FQ_CODEL\033[0m"
echo -e "\033[33m 6. ⚡ 启用 BBR + FQ_PIE\033[0m"
echo -e "\033[33m 7. ⚡ 启用 BBR + CAKE\033[0m"
echo -e "\033[33m 8. 🗑️ 卸载 BBR 内核\033[0m"
print_separator
echo -n -e "\033[36m请选择一个操作 (1-8) (。・ω・。): \033[0m"
read -r ACTION
case "$ACTION" in
1)
echo -e "\033[1;32m٩(。•́‿•̀。)۶ 您选择了安装或更新 BBR v3\033[0m"
install_latest_version
;;
2)
echo -e "\033[1;32m(。・∀・)ノ゙ 您选择了安装指定版本的 BBR\033[0m"
install_specific_version
;;
3)
echo -e "\033[1;32m(。・ω・。) 检查是否为 BBR v3...\033[0m"
BBR_MODULE_INFO=$(modinfo tcp_bbr 2>/dev/null)
if [[ -z "$BBR_MODULE_INFO" ]]; then
echo -e "\033[36m正在刷新模块依赖...\033[0m"
depmod -a
BBR_MODULE_INFO=$(modinfo tcp_bbr 2>/dev/null)
fi
if [[ -z "$BBR_MODULE_INFO" ]]; then
echo -e "\033[31m(⊙﹏⊙) 未加载 tcp_bbr 模块,无法检查版本。请先安装内核并重启。\033[0m"
exit 1
fi
BBR_VERSION=$(echo "$BBR_MODULE_INFO" | awk '/^version:/ {print $2}')
if [[ "$BBR_VERSION" == "3" ]]; then
echo -e "\033[36m✔ BBR 模块版本:\033[0m\033[1;32m$BBR_VERSION (v3)\033[0m"
else
echo -e "\033[33m( ̄﹃ ̄) 检测到 BBR 模块,但版本是:$BBR_VERSION,不是 v3\033[0m"
fi
CURRENT_ALGO=$(sysctl net.ipv4.tcp_congestion_control | awk '{print $3}')
if [[ "$CURRENT_ALGO" == "bbr" ]]; then
echo -e "\033[36m✔ TCP 拥塞控制算法:\033[0m\033[1;32m$CURRENT_ALGO\033[0m"
else
echo -e "\033[31m(⊙﹏⊙) 当前算法不是 bbr,而是:$CURRENT_ALGO\033[0m"
fi
if [[ "$BBR_VERSION" == "3" && "$CURRENT_ALGO" == "bbr" ]]; then
echo -e "\033[1;32mヽ(✿゚▽゚) 检测完成,BBR v3 已正确安装并生效!\033[0m"
else
echo -e "\033[33mBBR v3 未完全生效。请确保已安装内核并重启,然后使用选项 4-7 启用。\033[0m"
fi
if grep -Eq '^\s*blacklist\s+algif_aead' "$SECURITY_MODPROBE_CONF" 2>/dev/null; then
echo -e "\033[1;32m✔ CVE-2026-31431 缓解状态:已启用(algif_aead 已黑名单)\033[0m"
else
echo -e "\033[31m✘ CVE-2026-31431 缓解状态:未启用\033[0m"
echo -e "\033[33m 建议重新运行脚本,或手动写入 $SECURITY_MODPROBE_CONF\033[0m"
fi
if grep -Eq '^\s*blacklist\s+esp4' "$SECURITY_MODPROBE_CONF" 2>/dev/null \
&& grep -Eq '^\s*blacklist\s+esp6' "$SECURITY_MODPROBE_CONF" 2>/dev/null \
&& grep -Eq '^\s*blacklist\s+rxrpc' "$SECURITY_MODPROBE_CONF" 2>/dev/null; then
echo -e "\033[1;32m✔ Dirty Frag 缓解状态:已启用(esp4/esp6/rxrpc 已黑名单)\033[0m"
else
echo -e "\033[31m✘ Dirty Frag 缓解状态:未启用\033[0m"
echo -e "\033[33m 建议重新运行脚本,或手动写入 $SECURITY_MODPROBE_CONF\033[0m"
fi
;;
4)
echo -e "\033[1;32m(ノ◕ヮ◕)ノ*:・゚✧ 使用 BBR + FQ 加速!\033[0m"
ALGO="bbr"
QDISC="fq"
ask_to_save
;;
5)
echo -e "\033[1;32m(๑•̀ㅂ•́)و✧ 使用 BBR + FQ_CODEL 加速!\033[0m"
ALGO="bbr"
QDISC="fq_codel"
ask_to_save
;;
6)
echo -e "\033[1;32m٩(•‿•)۶ 使用 BBR + FQ_PIE 加速!\033[0m"
ALGO="bbr"
QDISC="fq_pie"
ask_to_save
;;
7)
echo -e "\033[1;32m(ノ≧∀≦)ノ 使用 BBR + CAKE 加速!\033[0m"
ALGO="bbr"
QDISC="cake"
ask_to_save
;;
8)
echo -e "\033[1;32mヽ(・∀・) 您选择了卸载 BBR 内核!\033[0m"
PACKAGES_TO_REMOVE=$(dpkg -l | grep "joeyblog" | awk '{print $2}' | tr '\n' ' ')
if [[ -n "$PACKAGES_TO_REMOVE" ]]; then
echo -e "\033[36m将要卸载以下内核包: \033[33m$PACKAGES_TO_REMOVE\033[0m"
sudo apt-get remove --purge $PACKAGES_TO_REMOVE -y
update_bootloader
echo -e "\033[1;32m内核包已卸载。请记得重启系统。\033[0m"
else
echo -e "\033[33m未找到由本脚本安装的 'joeyblog' 内核包。\033[0m"
fi
;;
*)
echo -e "\033[31m( ̄▽ ̄)ゞ 无效的选项,请输入 1-8 之间的数字哦~\033[0m"
;;
esac
File diff suppressed because it is too large Load Diff
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
repo_root=$(cd -- "$script_dir/.." && pwd)
kernel_version=$(awk '
/^VERSION[[:space:]]*=/ { version = $3 }
/^PATCHLEVEL[[:space:]]*=/ { patchlevel = $3 }
END {
if (version == "" || patchlevel == "") {
exit 1
}
print version "." patchlevel
}
' Makefile)
patch_file="${BBRV3_PATCH:-$repo_root/patches/bbrv3-linux-$kernel_version.patch}"
if [[ ! -f "$patch_file" ]]; then
echo "BBRv3 patch not found for linux-$kernel_version.y: $patch_file" >&2
echo "Add a matching patches/bbrv3-linux-$kernel_version.patch before building this kernel series." >&2
exit 1
fi
git apply --check "$patch_file"
git apply "$patch_file"
if ! grep -q '^#define BBR_VERSION[[:space:]]*3' net/ipv4/tcp_bbr.c; then
echo "BBRv3 patch applied, but BBR_VERSION=3 was not found." >&2
exit 1
fi
echo "Applied BBRv3 port: $patch_file"
+10914
View File
File diff suppressed because it is too large Load Diff