搭建 Mihomo 旁路代理的完整指南:分流代理,释放主路由性能
一、什么是旁路由透明代理?
“旁路由”并不是一个官方的网络术语,而是民间对一种常见网络方案的称呼。它指的是在主路由旁边,再设置一个专门处理复杂任务的设备。
在这个方案中,我们的# 搭建 Mihomo 旁路代理的完整指南:分流代理,释放主路由性能网络结构如下:
- 主路由:作为家庭网络的“大门”,负责 Wi-Fi、DHCP 等基础功能。它的性能可能不强,我们不希望它承担过重的任务。
- 旁路由:一台性能更强的、7x24 小时运行的 Linux 设备(例如 PVE 虚拟机/LXC 容器、树莓派、NUC 小主机等)。它在网络中只是一个普通设备,不作为网关。
我们的目标是:
- 所有设备的网络流量都先经过主路由。
- 主路由对流量进行智能识别,判断哪些是需要代理的“国外流量”,哪些是“国内流量”。
- 主路由将“国外流量”转发给旁路由处理。国内流量则直接放行。
- 旁路由上的
mihomo核心接收到转发来的流量,执行代理,实现“科学上网”。
这样做的好处:
- 释放主路由性能:主路由只做最简单的识别和转发,CPU 负荷极低,确保了家庭网络 Wi-Fi 的稳定和低延迟。
- 发挥旁路由性能:复杂的代理规则、大量的连接数都由性能更强的旁路由承担,可以达到更高的代理速度。
- 安全稳定:无需给主路由刷写可能不稳定的第三方固件,保证了核心网络设备的稳定性。
二、旁路由配置:运行 Mihomo 服务
首先,我们需要在旁路由(例如您的 LXC Ubuntu 容器)上配置好 mihomo。
1. 准备 Mihomo
-
下载并安装
mihomo核心程序。仓库:github.com/metacubex/m… -
准备好您的配置文件(例如
config.yaml),确保其tproxy-port已经开启,并且iptables: enable: true,这是实现透明代理的关键。# config.yaml 关键配置 mixed-port: 7897 tproxy-port: 9898 # 透明代理端口 allow-lan: true iptables: enable: true # 必须开启,mihomo 会自动管理自己的 iptables 规则 inbound-interface: eth0 # 旁路由的网卡名
2. 设置持久化服务 (Systemd)
为了让 mihomo 能开机自启并在异常时自动重启,我们为它创建一个 systemd 服务。
-
在旁路由上创建文件
/etc/systemd/system/mihomo.service,内容如下(请根据您的实际路径修改ExecStart):[Unit] Description=mihomo proxy service After=network-online.target Wants=network-online.target [Service] Type=simple ExecStart=/usr/local/bin/mihomo -f /root/mihomo/config.yaml User=root Restart=on-failure RestartSec=5s # 在服务启动后,执行豁免规则脚本,解决端口转发冲突问题 ExecStartPost=/usr/local/bin/apply_iptables_fixes.sh [Install] WantedBy=multi-user.target -
同时,创建
/usr/local/bin/apply_iptables_fixes.sh脚本,用于解决 SSH 等端口转发的冲突问题(详见排错实践): -
最后,启用并启动服务:
sudo chmod +x /usr/local/bin/apply_iptables_fixes.sh sudo systemctl daemon-reload sudo systemctl enable mihomo sudo systemctl start mihomo
三、主路由配置:智能识别与转发流量
这是整个方案的核心,主路由需要完成两件大事:识别流量、转发流量。
为了实现持久化并解决复杂的启动时序问题,我们采用 OpenWRT 系统中最可靠的 uci + 自定义脚本的方式。
1. 识别流量:使用 IPSet + iptables MARK
- IPSet: 我们使用
ipset来创建一个名为china_ip的集合,并将所有国内 IP 地址段放进去。相比于成千上万条iptables规则,ipset的匹配效率极高。 - iptables MARK: 我们在
mangle表中设置规则,对流量进行“打标记”。逻辑是:“如果一个数据包的目标地址不在china_ip集合里,就给它打上一个标记(例如1)”。
2. 转发流量:使用策略路由 (Policy-Based Routing)
- Linux 内核允许我们创建多张路由表。我们创建一个新的路由表(例如
100)。 - 我们设置一条策略规则:
ip rule add fwmark 1 table 100。意思是:“所有被打了标记1的数据包,都不要走默认的路由表,而是去查阅第100号路由表”。 - 我们再在第
100号路由表里只写一条规则:ip route add default via <旁路由IP> table 100。意思是:“所有查到这张表的数据包,你们的下一跳(网关)都是旁路由”。
3. 最终方案:创建持久化启动脚本
我们将所有命令整合到一个独立的启动脚本中,然后通过 uci 命令让它在防火墙启动时被调用。
第一步:创建 /data/my_proxy_script.sh 脚本
在主路由上创建该文件,并写入以下健壮的脚本内容:
#!/bin/sh
(
set -x
echo "--- Starting custom route script at $(date) ---"
# 1. 智能等待网络就绪
echo "Waiting for 'br-lan' interface..."
while ! ip a | grep -q 'br-lan'; do sleep 5; done
echo "'br-lan' is up. Waiting 15s more..."
sleep 15
# 2. 配置 IPSet
ipset create china_ip hash:net -exist
wget -O /tmp/china_ip_list.new 'https://fastly.jsdelivr.net/gh/17mon/china_ip_list@master/china_ip_list.txt'
if [ -s "/tmp/china_ip_list.new" ]; then
ipset flush china_ip
awk '!/^#|^$/{print "add china_ip " $0}' /tmp/china_ip_list.new | ipset restore
fi
rm -f /tmp/china_ip_list.new
# 3. 配置策略路由
ip rule add fwmark 1 table 100 2>/dev/null
ip route flush table 100
ip route add default via 192.168.31.2 dev br-lan table 100
# 4. 配置 Mangle 表打标记
iptables -t mangle -N PROXY_MARK 2>/dev/null
iptables -t mangle -F PROXY_MARK
iptables -t mangle -A PROXY_MARK -m set --match-set china_ip dst -j RETURN
iptables -t mangle -A PROXY_MARK -s 192.168.31.2 -j RETURN
iptables -t mangle -A PROXY_MARK -s 192.168.31.0/24 -j MARK --set-mark 1
iptables -t mangle -C PREROUTING -s 192.168.31.0/24 -j PROXY_MARK 2>/dev/null || iptables -t mangle -A PREROUTING -s 192.168.31.0/24 -j PROXY_MARK
# 5. 配置 Filter 表放行转发
iptables -t filter -C FORWARD -m mark --mark 0x1 -j ACCEPT 2>/dev/null || iptables -t filter -I FORWARD 1 -m mark --mark 0x1 -j ACCEPT
echo "--- Finished custom route script at $(date) ---"
) > /tmp/my_proxy_startup.log 2>&1 &
第二步:赋予脚本执行权限
chmod +x /data/my_proxy_script.sh
第三步:使用 uci 创建独立的防火墙启动项
# 清理一下,以防有旧的残留
uci delete firewall.MyProxy 2>/dev/null
# 创建新的防火墙 include 任务
uci set firewall.MyProxy=include
uci set firewall.MyProxy.type='script'
uci set firewall.MyProxy.path='/data/my_proxy_script.sh'
uci set firewall.MyProxy.enabled='1'
# 提交更改,使其永久生效
uci commit firewall
# 重启防火墙使配置生效
/etc/init.d/firewall restart
通过以上步骤,您就拥有了一个完全独立、持久化且能解决启动时序问题的透明代理方案。
四、常见问题与深度排错
在配置过程中,您可能会遇到各种意想不到的问题,例如规则不生效、端口转发冲突、HTTPS 证书错误、重启后规则丢失等。这些问题的根源往往与硬件加速、防火墙转发策略、脚本启动时序等底层机制有关。
我们已将一次完整的、从零开始的排错过程详细记录成文,其中包含了对这些常见问题的深入分析和最终解决方案。
详细内容请参考:[[旁路由透明代理与端口转发排错实战]]
通过以上步骤,您就可以搭建一套稳定、高效且不影响主路由性能的旁路由透明代理系统。