前言
在 PVE 虚拟化环境中,本人为特定业务分配了一台 LXC 容器并有全局代理的需求。初衷是利用 TUN 模式接管网卡,但受限于宿主机未开启内核 TUN 支持,且考虑到通过 Tailscale 远程维护时重启宿主机存在失联风险,最终决定采用对内核侵入性更小、无需虚拟网卡的 TProxy 透明代理方案。
工具
nftables
sing-box (https://sing-box.sagernet.org) 或者其他代理工具
本教程采用 sing-box 作为示例,由于 sing-box 频繁 break change 配置文档,仅推荐爱折腾且有能力阅读文档的人使用。
基础知识补充
TProxy 即 Transparent Proxy。广义上指代一种网络代理技术,核心的特征在于“透明”,即客户端不能感知到代理的存在。在 TProxy 模式下,防火墙在 Prerouting 阶段识别特定的流量,并在不修改数据包目标地址的前提下,通过内核标记与策略路由,将本应转发出的数据包强制递交给本地的监听进程。
sing-box 配置模板
本配置模板在 sing-box version 1.13.11 测试下可用。
{
"log": {
"level": "info"
},
"dns": {
"servers": [
{
"tag": "local-dns",
"type": "udp",
"server": "223.5.5.5"
},
{
"tag": "proxy-dns",
"type": "tls",
"server": "8.8.8.8"
}
],
"rules": [
{
"query_type": [
"A",
"AAAA"
],
"server": "proxy-dns"
}
]
},
"inbounds": [
{
"type": "tproxy",
"tag": "tproxy-in",
"listen": "::",
"listen_port": 12345
},
{
"type": "direct",
"tag": "dns-in",
"listen": "127.0.0.1",
"listen_port": 53
}
],
"outbounds": [
{
"type": "shadowsocks",
"tag": "proxy",
"server": "",
"server_port": 11451,
"method": "2022-blake3-aes-256-gcm",
"password": "",
"detour": ""
},
{
"type": "direct",
"tag": "direct"
}
],
"route": {
"default_domain_resolver": "local-dns",
"rules": [
{
"port": 53,
"action": "hijack-dns"
},
{
"ip_cidr": [
"223.5.5.5"
],
"outbound": "direct"
},
{
"outbound": "proxy"
}
],
"auto_detect_interface": true
},
"experimental": {
"cache_file": {
"enabled": true
}
}
}
如果需要配置代理链,在落地节点同层级添加 "detour": "<tag>" 即可。
DNS 需要代理出站同上。
操作流程
确保你已经安装了 nftables 和 sing-box:
如果没有
sudo apt update
sudo apt install nftables -y
curl -fsSL https://sing-box.app/install.sh | sh
首先,配置 sing-box 暴露 TProxy 和 DNS 入站。
模板示例:
"inbounds": [
{
"type": "tproxy",
"tag": "tproxy-in",
"listen": "::",
"listen_port": 12345
},
{
"type": "direct",
"tag": "dns-in",
"listen": "127.0.0.1",
"listen_port": 53
}
]
其余部分不做过多阐述。
接下来配置 nftables。
vim /etc/nftables.conf
添加以下内容:
table inet singbox {
set private_ips {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 }
}
chain prerouting {
type filter hook prerouting priority mangle; policy accept;
ct direction reply return
iifname "lo" meta mark 1 udp dport 53 tproxy to :53 accept
iifname "lo" meta mark 1 meta l4proto { tcp, udp } tproxy to :12345 accept
}
chain output {
type route hook output priority mangle; policy accept;
ip daddr @private_ips return
fib daddr type local return
udp dport 53 meta mark set 1
meta l4proto { tcp, udp } meta mark set 1
}
}
保存后,执行 nft -c -f /etc/nftables.conf 检查语法是否有问题,随后执行 nft -f /etc/nftables.conf 加载配置文件。
如果你在使用 systemd 管理的 linux 系统,可以执行 systemd enable nftables.service 使 nftables 开机自启动。
最后,添加策略路由。
ip rule add fwmark 1 lookup 100
ip route add local default dev lo table 100
所有被打上特定标记的数据包,会被强行捕获并转交给本地回环设备(lo),从而进入本机的监听进程。在本教程中,nftables 会给符合条件的数据包打上标记,从而使得匹配的包走编号为 100 的自定义路由表。
针对 Debian / Ubuntu 系统,可以配置 /etc/network/interfaces 使策略路由配置持久化:
auto eth0
iface eth0 inet dhcp
post-up ip rule add fwmark 1 lookup 100
post-up ip route add local default dev lo table 100
注意修改 eth0 为自己的真实出站网卡。
在终端中执行 curl ipinfo.io,现在应该可以看到出站 IP 已经是你的代理 IP 了。
评论
评论加载中…