Raspberry Pi installs mihomo and configures transparent proxy

Image: Gansu Museum Bronze Running Horse (Horse Treading on Swallow)

I have been running OpenClash on the Xiaomi AX3000T router before, and it has been stable to use. But over time, OpenClash ate too much memory, and one day when I saw it, its usage skyrocketed to 233MB. The router went out of mode and SSH couldn’t connect, so I had to shut down and restart. The little memory on the router couldn’t handle it, so I turned my attention to the Raspberry Pi, which had been sitting idle for a long time. It’s better to let it do this job.

Official one click script to install Docker:

curl -fsSL https://get.docker.com | sh

After installation, add the current user to the Docker group to avoid having to do so every time

sudo usermod -aG docker $USER

Then log out and log in again. Because accessing Docker Hub in China is not very stable, I have installed image acceleration:

sudo tee /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": ["https://docker.1ms.run"]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

Docker is ready, let’s deploy mihomo next. Create a directory to store configuration and data:

mkdir -p ~/mihomo && cd ~/mihomo

First, prepare the configuration file and place it in~/mihomo/config. yaml, then run it with 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. Use the host’s network directly through the port; Cap add=NET-ADMIN grants operation permissions to iptables,&# 8211; Restart=always. It automatically restarts after booting up and hanging up.

If you previously used OpenClash configuration, you cannot use it directly! We need to remove OpenClash specific fields, such as experimental, dns.enhanced mode: Redis host, and other extension fields. The key configuration items are roughly as follows:

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

You can also subscribe to:

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

Port allocation: 7890 is HTTP proxy, 7891 is SOCKS57892 is REDIRECT transparent proxy for iptables, 7893 is Mixed proxy, 53 is DNS, and 9090 is API and web panel. After the configuration is changed, Docker restart mihomo.
Next is the most critical transparent proxy for iptables. The idea is to hijack LAN traffic to port 7892 of mihomo using iptables. Create script~/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 "透明代理规则已设置"

Script to cancel transparent proxy:

#!/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

To automatically set iptables rules upon startup, create a systemd service:

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

To enable command-line tools to also use proxies, set environment variables in/etc/profile.d/proxies. 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

Attention! /etc/profiler. d/proxy. sh only works for login shells (bash – l)! System services, cron tasks, and non login shells will not automatically source this file. If you have a systemd service that requires proxy, you must explicitly add the Environment=line in the service unit file, otherwise the process will connect directly and the domestic network will be blocked! I have stepped on this pit and after investigating for a long time, I found that it is an issue with the environment variables.
Test if the proxy is working:

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

If it can return 200 normally, it means the configuration is successful. Web panel access: http://Raspberry Pi IP: 9090/ui, it is recommended to use Yacd or Metacubedd.
Finally, let’s talk about the biggest pit I stepped into. At first, I wanted to use TProxy mode instead of REDIRECT because TProxy could theoretically proxy UDP traffic better. As a result, TProxy didn’t work for most of the day. Upon investigation, it was found that the Raspberry Pi kernel discards packets marked with fwmark instead of routing them correctly, and packets marked with fwmark are directly discarded. After searching online, many people have encountered the same problem and it is basically confirmed that it is caused by the Raspberry Pi kernel. So if you also use Raspberry Pi, be honest and use REDIRECT mode. Although it can only proxy TCP, its advantage lies in stability and reliability.

Throughout the entire process, mihomo runs very stably in Docker, with much less memory usage than running OpenClash on a router. All devices in the LAN automatically use transparent proxies without the need for separate configuration, making it very enjoyable to use.

Reference materials:

mihomo Official documents

Docker Official installation documentation

metacubex/mihomo Docker Mirror image

iptables REDIRECT Transparent Proxy Principle

 

Released on August 22, 2026.

Leave a Reply