# 10.3 Mihomo 配置

Mihomo 是 Clash 系列的衍生版本，已在 FreeBSD 的 Ports 中提供。本节介绍 Mihomo 的安装与配置方法。

## 安装 Mihomo

使用 pkg 安装：

```sh
# pkg install net/mihomo
```

或者使用 Ports 安装：

```sh
# cd /usr/ports/net/mihomo/ 
# make install clean
```

文件结构：

```sh
/usr/
├── ports/
│   └── net/
│       └── mihomo/ # Mihomo Ports 目录
├── local/
│   ├── bin/
│   │   └── mihomo # Mihomo 可执行文件
│   └── etc/
│       └── rc.d/
│           └── mihomo # Mihomo RC 服务脚本
└── etc/
    └── rc.conf # 系统服务配置文件
```

如果觉得配置较为麻烦，也可以在 Linux 兼容层中使用，FreeBSD 的网络同样可以受其控制，这得益于 FreeBSD 强大的 Linux 二进制兼容能力。

## RC 脚本

已向 Ports 维护者发出请求合并（[Bug 291295 - net/mihomo: Add rc.conf and some Post-installation](https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=291295)），该请求旨在为 Mihomo 添加系统服务管理支持，但目前尚未收到回应。在官方集成完成前，可使用下文提供的自定义 RC 脚本实现服务化管理。

### RC 脚本

为了方便管理 Mihomo 服务，可以使用以下脚本。将以下脚本保存为名为 mihomo 的文件，并放置到路径 `/usr/local/etc/rc.d/` 下。最后使用 root 账户为该文件赋予可执行权限：`chmod +x /usr/local/etc/rc.d/mihomo`。

```sh
#!/bin/sh

. /etc/rc.subr   # 引入 rc.d 脚本框架，这是 FreeBSD 服务脚本的标准前置依赖

name="mihomo"    # 定义服务名，用于标识和管理该服务
desc="mihomo server"    # 服务描述，用于提供服务的简要说明
rcvar="mihomo_enable"    # 服务开关变量，控制服务是否开机自启

: ${mihomo_datadir:="/var/run/mihomo"}
: ${mihomo_user:="root"}    # 默认用户；如使用其他用户，请确保 /etc/mihomo 目录及 $pidfile 和 log 文件可写，这是权限安全的基本要求
: ${mihomo_extra_flags:=""}	# mihomo 的额外参数，用于传递自定义启动选项

procname="/usr/local/bin/mihomo"    # 与 pidfile 配合，用于检测服务进程，这是 rc.d 框架识别服务进程的关键
pidfile="${mihomo_datadir}/mihomo.pid"    # 用于检测服务进程，存储主进程的进程标识符（Process ID，PID）
logfile="${mihomo_datadir}/mihomo.log"
start_cmd="mihomo_start"    # 设置 start 命令调用 mihomo_start 函数，stop 等命令由 rc.d 框架默认实现，这种设计能自定义启动逻辑
extra_commands="init reconfig regeoip"    # 设置其他的自定义命令，扩展 rc.d 框架的标准命令集
reconfig_cmd="mihomo_reconfig"    # 指定 reconfig 命令调用 mihomo_reconfig 函数，用于下载 config.yaml 文件
regeoip_cmd="mihomo_regeoip"    # 指定 regeoip 命令调用 mihomo_regeoip 函数，用于下载 geoip.dat 文件，可通过 mihomo_extra_flags="-m" 指定使用该文件
init_cmd="mihomo_init"    # 指定 init 命令调用 mihomo_init 函数。创建数据文件目录，指定属主，避免普通用户身份执行时的读写权限问题

mihomo_start()
{    # 使用 daemon 启动 mihomo，指定 -p 参数使用 pidfile，使 mihomo 成为 daemon 的子进程，由 daemon 自动管理 pidfile，从而在 mihomo 进程退出时自动清理 pidfile，这是 Unix 守护进程管理的标准实践
	daemon -u ${mihomo_user} -p "$pidfile" -o "${logfile}" $procname -d "${mihomo_datadir}" -f "${mihomo_datadir}/config.yaml" ${mihomo_extra_flags}
}
mihomo_reconfig()
{
	startmsg "begin to refresh config.yaml"
	startmsg "config.yaml : ${mihomo_config}"
	if ( fetch -o ${mihomo_datadir}/config.yaml.new "${mihomo_config}" );then
		mv ${mihomo_datadir}/config.yaml.new ${mihomo_datadir}/config.yaml    # 下载成功将覆盖原有配置，下载失败保留原有配置，这种原子操作保证了配置更新的安全性   
        startmsg "rename config.yaml.new to config.yaml"
	else
		err "fetch config.yaml failed! check $$mihomo_config!"
	fi
}
mihomo_regeoip()
{
	startmsg "begin to refresh geoip.dat"
	startmsg "geoip.dat : $mihomo_geoip"
	if ( fetch -o ${mihomo_datadir}/geoip.new "${mihomo_geoip}" );then
		mv ${mihomo_datadir}/geoip.new ${mihomo_datadir}/geoip.dat
        startmsg "rename geoip.new to geoip.dat"
	else
		err "fetch geoip.dat failed! check $$mihomo_geoip"
	fi
}
mihomo_init()
{
	startmsg "begin init"
	install -d -m 0700 -o ${mihomo_user} ${mihomo_datadir}
    startmsg "all data is in ${mihomo_datadir}"
    startmsg "remember reconfig/regeoip before start"
}

load_rc_config $name
run_rc_command "$1"
```

### 可用参数及选项

RC 脚本提供了多个命令行参数和配置选项，以下是一些常用参数。这些命令会直接将配置写入 `/etc/rc.conf`，如配置有误，可直接修改对应行，`/etc/rc.conf` 是 FreeBSD 系统配置的核心文件。

* 启用 Mihomo 服务项及开机自启，将服务注册到系统启动流程中：

```sh
service mihomo enable
```

* 立刻启用 Mihomo，启动服务进程：

```sh
service mihomo start
```

* 立刻停用 Mihomo，终止服务进程：

```sh
service mihomo stop
```

* 查看 Mihomo 状态，检查服务运行状态：

```sh
service mihomo status
```

* 在此指定你的订阅链接地址（示例地址仅用于演示，需自行替换为有效链接），订阅链接是获取代理节点配置的标准方式：

```sh
sysrc mihomo_config="https://xxxx.yyy"
```

* 用于地理位置判断的 GeoIP 数据，主要用于根据 IP 地址的地理归属进行流量分流或规则匹配，这是实现智能分流的基础数据：

```sh
sysrc mihomo_geoip="https://ghfast.top/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat" # 可选，但建议使用
```

* 指定其他 Mihomo 参数，用于传递额外的自定义选项：

```sh
sysrc mihomo_extra_flags="-m" # 可选，但建议使用
```

* `-m`：指定 Mihomo 的 geoip.dat 文件路径，具体说明参见 rc 脚本，该参数启用 GeoIP 数据文件的使用。
* 指定调用 Mihomo 的用户，用于控制服务运行的身份，这是安全实践的重要组成部分：

```sh
sysrc mihomo_user="mihomo"  # 默认用户是 root
```

* 指定 Mihomo 的数据路径，配置服务运行时数据的存储位置：

```sh
sysrc mihomo_datadir="/var/run/mihomo"
```

相关文件结构：

```sh
/var/
└── run/
    └── mihomo/ # Mihomo 数据目录
        ├── mihomo.pid # 进程标识符（Process ID，PID）文件
        ├── mihomo.log # 日志文件
        ├── config.yaml # 配置文件
        └── geoip.dat # GeoIP 数据文件
```

* 初始化（创建）Mihomo 的数据目录，准备服务运行环境：

```sh
service mihomo init
```

* 更新订阅。`start` 前先更新即可使用最新的订阅信息，确保配置文件是最新版本：

```sh
service mihomo reconfig 
```

* 更新 regeoip，更新地理位置数据库：

```sh
service mihomo regeoip # 首次启用时建议使用，但无需频繁更新，因为 IP 地理位置数据变化相对缓慢
```

### 最小 RC 示例

以下是一个最简配置示例，可在理解其含义并按需修改后写入 `/etc/rc.conf` 文件，这个示例展示了最小化的可用配置：

```ini
mihomo_config="https://xxx.yyy" # 读者的订阅链接地址，请勿照抄，否则将不生效
mihomo_geoip="https://ghfast.top/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat" # GeoIP 数据
mihomo_enable="YES" # 开机启用/服务项
```

读者可根据自身需求自行调整配置，通过组合上述参数实现个性化设置。

### 未竟事项

以下是一些有待探索的问题，读者可自行研究解决方案，这些问题代表了该领域进一步探索的方向：

* 如何实现“直连”、“代理”、“全局”的分流？这三种模式是代理系统的基础功能模式。
* 如何实现 TUN 虚拟网卡代理（是否可能）？TUN 模式可以实现更底层的网络流量拦截。
* 如何根据订阅链接进行测速？测速功能对于选择最优代理节点具有重要意义。
* 如何指定订阅链接中的代理组中的某个代理？（比如仅使用位于美国的某个代理 A）这涉及代理节点的精细化选择。

## Clash for FreeBSD

除了 Mihomo 之外，还有 Clash for FreeBSD 项目可以使用，这为用户提供了另一种代理解决方案。

> **警告**
>
> 目前该项目尚不支持某些订阅类型，这是当前的局限性。

遇到此类问题时，程序会输出以下错误信息，这是订阅格式不兼容的典型表现：

```sh
判断订阅内容是否符合clash配置文件标准:
解码后的内容不符合clash标准，尝试将其转换为标准格式
ELF binary type "0" not known.
配置文件转换标准格式失败
```

如果读者遇到类似问题，建议使用其他解决方案，如上述 Mihomo 方案。

### 下载项目

首先，克隆 Clash for FreeBSD 仓库到本地，通过 Git 版本控制系统获取项目代码：

```bash
$ git clone https://github.com/wenyinos/clash-for-freebsd
```

```sh
clash-for-freebsd/
├── start.sh # 启动脚本
├── shutdown.sh # 停止脚本
├── restart.sh # 重启脚本
├── .env # 环境变量配置文件
└── conf/
    └── config.yaml # Clash 配置文件
```

```sh
/etc/
└── profile.d/
    └── clash.sh # Clash 环境变量配置脚本
```

### 启动程序

仓库克隆完成后，可直接运行脚本文件 start.sh 启动程序，这些脚本封装了复杂的启动流程。

* 进入项目目录：

```bash
$ cd clash-for-freebsd                                  # 进入 Clash for FreeBSD 目录
$ chmod +x start.sh shutdown.sh restart.sh             # 设置启动、停止和重启脚本为可执行权限，这是 Unix 脚本执行的前置条件
```

* 编辑 `.env` 文件，修改变量 `CLASH_URL` 的值（即把你的 Clash 订阅链接放进去），`.env` 文件是环境变量配置的常用方式。

> **注意**
>
> `.env` 文件中的变量 `CLASH_SECRET` 为自定义 Clash 的 Secret，当值为空时，脚本将自动生成随机字符串，Secret 用于 Web 管理界面的身份验证。

* 安装 bash，并将其设置为 root 用户及当前登录用户的 Shell，具体步骤请参见相关文档，这是当前脚本的依赖限制。
* 运行启动脚本：

```bash
# bash start.sh

正在检测订阅地址...
Clash订阅地址可访问！                                      [  OK  ]

正在下载Clash配置文件...
配置文件config.yaml下载成功！                              [  OK  ]

正在启动Clash服务...
服务启动成功！                                             [  OK  ]

Clash Dashboard 访问地址：http://<ip>:9090/ui
Secret：xxxxxxxxxxxxx

请执行以下命令加载环境变量: source /etc/profile.d/clash.sh

请执行以下命令开启系统代理: proxy_on

若要临时关闭系统代理，请执行: proxy_off

```

* 加载环境变量并启用系统代理：

```bash
$ source /etc/profile.d/clash.sh   # 加载 Clash 环境变量配置
$ proxy_on                         # 启用 Clash 代理
```

* 列出本地监听的端口中包含 9090 或 789 的套接字，通过 sockstat 工具检查网络端口监听状态，这是 FreeBSD 中查看网络套接字的标准方法：

```bash
# sockstat -l | egrep '9090|789'
root     clash-free  2706 7   tcp46  *:9090                *:*
root     clash-free  2706 8   tcp46  *:7890                *:*
root     clash-free  2706 9   tcp46  *:7891                *:*
root     clash-free  2706 10  udp46  *:7891                *:*
root     clash-free  2706 11  tcp46  *:7892                *:*
root     clash-free  2706 12  udp46  *:7892                *:*
```

* 查看环境中设置的 HTTP 和 HTTPS 代理变量，验证环境变量配置是否正确：

```bash
$ env | grep -E 'http_proxy|https_proxy'
http_proxy=http://127.0.0.1:7890
https_proxy=http://127.0.0.1:7890
```

如果以上步骤的输出结果类似，且能够正常访问 [https://Google.com](https://google.com)，则说明 Clash 程序已成功启动，这是验证代理工作状态的有效方法。

### 重启程序

如果需要对 Clash 配置进行修改，请修改 `conf/config.yaml` 文件。然后运行 `restart.sh` 脚本进行重启，使新配置生效。

> **注意**
>
> 重启脚本 `restart.sh` 不会更新订阅信息，仅重启服务进程。

### 访问 Web 端

程序启动后，可以通过 Web 界面进行管理，这提供了直观的图形化管理方式。访问 <http://127.0.0.1:9090/ui> 在网页中输入上面输出的 Secret 值即可。

### 停止程序

如果需要停止 Clash for FreeBSD 服务，请按以下步骤操作，确保服务和系统代理都正确关闭：

* 进入项目目录：

```bash
$ cd clash-for-freebsd
```

* 关闭服务：

```bash
# bash shutdown.sh

服务关闭成功，请执行以下命令关闭系统代理：`proxy_off`

```

```bash
$ proxy_off
```

随后检查程序端口、进程以及环境变量 `http_proxy|https_proxy`，若均不存在，则说明服务已正常关闭，这是确保清理工作的完整性检查。

### 参考资料

* wenyinos. clash-for-freebsd: freebsd command-line proxy tool\[EB/OL]. \[2026-03-25]. <https://github.com/wenyinos/clash-for-freebsd>. 提供了 FreeBSD 下 Clash 代理的完整部署方案，支持订阅链接管理。

### 未竟事宜

以下是 Clash for FreeBSD 项目有待改进的地方，这些改进方向有助于提高项目的通用性和易用性：

* 需要更新以支持所有类型的订阅链接，扩大项目的适用范围。
* 与 bash 解耦合，支持默认的 sh，使其更符合 FreeBSD 的默认环境。

## 课后习题

1. 安装并配置 Mihomo，使用自定义 RC 脚本实现系统服务，配置完整的分流规则（直连、代理、全局），验证不同模式下的网络流量走向。
2. 重构 Mihomo RC 脚本，将其与 bash 解耦合并移植到 FreeBSD 默认的 sh 环境，验证功能完整性并对比与原脚本的差异。
3. 修改 Clash for FreeBSD 项目，使其支持多种订阅链接格式，或实现 TUN 虚拟网卡代理功能，验证修改后的系统行为。
