BY eHWRITTEN ON HALO4 MIN READ

ubuntu 26 架构下的 Mihomo 全局 TUN 透明代理工程部署实录

在现代 Linux 系统(如基于 Wayland 显示服务器和 nftables 的 Ubuntu 26)中,实现网络请求的全局无感接管,最优解是弃用传统的环境变量(http_proxy),转而在内核层面建立 TUN 虚拟接口。 本文记录了跳过图形界面前端,直接基于 Mihomo (Clash Me

在现代 Linux 系统(如基于 Wayland 显示服务器和 nftables 的 Ubuntu 26)中,实现网络请求的全局无感接管,最优解是弃用传统的环境变量(http_proxy),转而在内核层面建立 TUN 虚拟接口。

本文记录了跳过图形界面前端,直接基于 Mihomo (Clash Meta) 核心二进制文件,从零构建系统级透明代理的完整工程流程及底层排障逻辑。


一、 架构选型与底层逻辑抽象

在部署初期,面临代理协议栈的选型:Sing-box、Mihomo 还是 Proxychains-ng。

  • 配置协议壁垒: Sing-box 的核心路由逻辑基于严格的 JSON Schema 进行反序列化,而服务商提供的多为基于 YAML 的 Clash 订阅链接。若强行使用 Sing-box,必须引入外部的 Subconverter API 进行数据流转换。
  • 拦截机制局限: Proxychains-ng 依赖 LD_PRELOAD 动态库注入拦截系统调用,无法接管静态编译程序(如 Go 语言程序)的流量。
  • 最终决断: 直接采用 Mihomo 内核。其原生内置了对 Clash YAML 拓扑树的支持,且具备高性能的 TUN 驱动模块,可实现零数据损耗的规则集映射。

二、 初始配置获取与数据层“自举悖论”

第一阶段是将云端的代理节点数据同步至本地。

1. 报文拉取 创建默认目录并利用 curl 直接拉取订阅:

mkdir -p ~/.config/mihomo/
curl -L -o ~/.config/mihomo/config.yaml "您的Clash订阅链接"

2. 触发 MMDB 下载阻塞 当以普通用户身份在前台执行 mihomo 进行首次测试时,引擎会在日志中抛出挂起状态:Can't find MMDB, start download

  • 技术机制: 配置文件中的 GEOIP 规则依赖 Country.mmdb 数据库将目标 IP 反解析为地理位置。
  • 自举悖论: 启动代理需要该数据库,而下载数据库往往又需要代理环境。若网络连通性极差导致内核下载超时,需中止进程,手动通过物理注入绕过下载链路:
curl -L -o ~/.config/mihomo/Country.mmdb https://fastly.jsdelivr.net/gh/Dreamacro/maxmind-geoip@release/Country.mmdb

三、 内核权限分离与 Systemd 托管架构

前台运行缺乏内核级网络管理权限(CAP_NET_ADMIN),必须将其迁移为系统级守护进程。

1. 物理目录迁移 将所有配置文件移交至 /etc/ 目录:

sudo mkdir -p /etc/mihomo
sudo cp -r ~/.config/mihomo/* /etc/mihomo/

2. Systemd 状态机注册与 203/EXEC 排障 创建服务描述单元文件:sudo vim /etc/systemd/system/mihomo.service

注意绝对路径陷阱: 在编写 ExecStart 时,若错误地将二进制文件路径写为 /usr/local/bin/mihomo,而实际通过包管理器安装的路径为 /usr/bin/mihomo,Systemd 会因无法在指定路径寻址到执行文件而抛出致命错误 (code=exited, status=203/EXEC)。 正确的服务文件应严格核对物理路径(通过 which mihomo 获取),并应用最小特权原则:

[Unit]
Description=Mihomo Proxy Daemon
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/mihomo -d /etc/mihomo
Restart=on-failure
RestartSec=5s
LimitNPROC=500
LimitNOFILE=1048576
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

四、 TUN 接口注入与 DNS 逻辑死锁的解除

仅仅通过 Systemd 提权是不够的,必须在 config.yaml 中向内核注入 OSI 第三层的网络参数。这是部署中最易出错的一环。

致命错误还原: 初期仅在配置中加入了 tun: enable: truedns-hijack: any:53,重启服务后发现底层网卡并未建立。 科学论证: 这是典型的逻辑死锁。TUN 模块拦截了 DNS 请求,但由于核心未配置内置的 Fake-IP DNS 引擎,数据包被丢弃。为防止系统产生全局 DNS 黑洞,Mihomo 主动放弃了网卡初始化。

最终修复方案: 必须在 /etc/mihomo/config.yaml 顶层同步注入完整的 TUN 栈和 Fake-IP 映射池:

tun:
  enable: true
  stack: system           
  auto-route: true        
  auto-detect-interface: true 
  dns-hijack:
    - any:53              

dns:
  enable: true
  listen: 0.0.0.0:1053          
  ipv6: false                   
  enhanced-mode: fake-ip        # TUN 模式的核心依赖
  fake-ip-range: 198.18.0.1/16  
  nameserver:
    - 223.5.5.5                 
    - 114.114.114.114
  fallback:
    - 8.8.8.8                   
    - 1.1.1.1
  fallback-filter:
    geoip: true
    geoip-code: CN

五、 物理层验证与引导持久化

应用新配置后,执行重载命令使之生效:

sudo systemctl daemon-reload
sudo systemctl restart mihomo

1. 认知偏差与表征验证 传统的验证习惯是输入 ip a | grep tun。然而这会产生没有输出的假象。现代版本的 Mihomo 在向内核调用 ioctl 建立接口时,默认命名为 mihomoMeta科学的验证指令:

# 验证网卡表征
ip a | grep -iE 'mihomo|meta'

# 验证内核路由表是否将 0.0.0.0/0 指向了虚拟网卡
ip route show table all | grep default

# 应用层盲测(跳过终端缓存)
curl -I https://www.google.com

curl 瞬间返回 HTTP/2 200 时,系统级全局透明代理即构建完毕。

2. 开机自启机制 由于已经执行过 sudo systemctl enable --now mihomo,Systemd 已在 /etc/systemd/system/multi-user.target.wants/ 下生成了持久化符号链接。此架构已深植于内核引导序列,支持发生网络波动时的自动容灾重启,实现了真正的静默无感运行。