配图:甘肃博物馆铜奔马(马踏飞燕)
之前我一直在小米AX3000T路由器上跑OpenClash,用着倒也稳定。但时间一长OpenClash太吃内存,某天一看占用直接飙到233MB,路由器直接OOM,SSH都连不上,只能断电重启。路由器那点内存实在扛不住,我把目光转向了吃灰已久的树莓派,闲置也是闲置,不如让它来干这个活。
官方一键脚本安装docker:
curl -fsSL https://get.docker.com | sh
装完把当前用户加到docker组,免得每次都要sudo:
sudo usermod -aG docker $USER
然后退出重新登录。因为国内访问Docker Hub不太稳定,我配了镜像加速:
sudo tee /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": ["https://docker.1ms.run"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker准备好了,接下来部署mihomo。创建目录放配置和数据:
mkdir -p ~/mihomo && cd ~/mihomo
先把配置文件准备好放到~/mihomo/config.yaml,然后用Docker跑起来:
docker run -d --name mihomo --restart=always --network=host --cap-add=NET_ADMIN -v ./config.yaml:/root/.config/mihomo/config.yaml -v ./cache.db:/root/.config/mihomo/cache.db metacubex/mihomo:latest
–network=host用宿主机网络直接用端口,–cap-add=NET_ADMIN给iptables操作权限,–restart=always开机自启挂了自动重启。
如果你之前用的是OpenClash的配置,不能直接拿来用!得删掉OpenClash特有的字段,比如experimental、dns.enhanced-mode: redir-host这类扩展字段。关键配置项大概长这样:
mixed-port: 7893
port: 7890
socks-port: 7891
redir-port: 7892
allow-lan: true
bind-address: "*"
mode: rule
log-level: info
external-controller: 0.0.0.0:9090
dns:
enable: true
listen: 0.0.0.0:53
enhanced-mode: fake-ip
nameserver:
- 223.5.5.5
- 119.29.29.29
也可以用订阅方式:
proxy-providers:
my-provider:
type: http
url: "你的订阅链接"
interval: 3600
path: ./providers/my-provider.yaml
health-check:
enable: true
interval: 600
url: http://www.gstatic.com/generate_204
端口分配:7890是HTTP代理,7891是SOCKS5,7892是REDIRECT透明代理给iptables用,7893是Mixed混合代理,53是DNS,9090是API和Web面板。配置改好后docker restart mihomo重启一下。
接下来是最关键的iptables透明代理。思路是用iptables把局域网流量劫持到mihomo的7892端口。创建脚本~/transparent-proxy.sh:
#!/bin/bash
MIHOMO_REDIR_PORT=7892
LOCAL_SUBNET="192.168.0.0/16"
iptables -t nat -N MIHOMO
iptables -t nat -A MIHOMO -d 0.0.0.0/8 -j RETURN
iptables -t nat -A MIHOMO -d 10.0.0.0/8 -j RETURN
iptables -t nat -A MIHOMO -d 127.0.0.0/8 -j RETURN
iptables -t nat -A MIHOMO -d 169.254.0.0/16 -j RETURN
iptables -t nat -A MIHOMO -d 172.16.0.0/12 -j RETURN
iptables -t nat -A MIHOMO -d 192.168.0.0/16 -j RETURN
iptables -t nat -A MIHOMO -d 224.0.0.0/4 -j RETURN
iptables -t nat -A MIHOMO -d 240.0.0.0/4 -j RETURN
iptables -t nat -A MIHOMO -m owner --uid-owner root -j RETURN
iptables -t nat -A MIHOMO -p tcp -j REDIRECT --to-ports $MIHOMO_REDIR_PORT
iptables -t nat -A PREROUTING -p tcp -s $LOCAL_SUBNET -j MIHOMO
echo "透明代理规则已设置"
取消透明代理的脚本:
#!/bin/bash
LOCAL_SUBNET="192.168.0.0/16"
iptables -t nat -D PREROUTING -p tcp -s $LOCAL_SUBNET -j MIHOMO
iptables -t nat -F MIHOMO
iptables -t nat -X MIHOMO
echo "透明代理规则已清除"
chmod +x ~/transparent-proxy.sh ~/transparent-proxy-stop.sh
为了开机自动设置iptables规则,创建systemd服务:
sudo tee /etc/systemd/system/mihomo-proxy.service << 'EOF'
[Unit]
Description=mihomo transparent proxy iptables rules
After=network.target docker.service
Requires=docker.service
[Service]
Type=oneshot
ExecStart=/home/sry/transparent-proxy.sh
ExecStop=/home/sry/transparent-proxy-stop.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable mihomo-proxy.service
sudo systemctl start mihomo-proxy.service
为了让命令行工具也能走代理,在/etc/profile.d/proxy.sh里设置环境变量:
sudo tee /etc/profile.d/proxy.sh << 'EOF'
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7891
export no_proxy=localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12
EOF
source /etc/profile.d/proxy.sh
注意!/etc/profile.d/proxy.sh只对登录shell(bash -l)生效!systemd service、cron任务、非登录shell都不会自动source这个文件。如果你有systemd服务需要走代理,必须在service unit文件里显式添加Environment=行,不然进程会直连,国内网络直接被墙!这个坑我踩过,排查了好久才发现是环境变量的问题。
测试一下代理是否工作:
curl -x http://127.0.0.1:7890 https://www.google.com -I
curl --socks5 127.0.0.1:7891 https://www.google.com -I
能正常返回200就说明配置成功。Web面板访问http://树莓派IP:9090/ui,推荐用Yacd或Metacubexd。
最后说我踩的最大的坑。一开始我想用TProxy模式而不是REDIRECT,因为TProxy能代理UDP流量理论上更好。结果折腾了大半天TProxy死活不工作。排查发现树莓派的内核在收到带有fwmark标记的包后会直接丢弃而不是正确路由,标记过的包直接被丢。网上查了一圈不少人遇到同样的问题,基本确认是树莓派内核的锅。所以如果你也用树莓派,老老实实用REDIRECT模式吧,虽然只能代理TCP但胜在稳定可靠。
整个流程下来mihomo跑在Docker里非常稳定,内存占用比路由器上跑OpenClash小得多,局域网内所有设备自动走透明代理无需单独配置,用起来非常爽。
参考资料:
发布于2026/08/22。
