--- name: openclash-user-guide description: 'OpenClash 用户功能指南。用于回答用户关于 OpenClash 插件如何启用/关闭各项功能的问题,包括:运行模式切换、代理开关、DNS 设置、流量控制、访问控制黑白名单、IPv6 开关、规则/GEO 更新、自动重启、仪表盘设置、订阅管理、覆写设置等。每个选项均标注了对应的 UCI 配置项、修改的 Mihomo YAML 配置段、以及触发的脚本。Use when user asks how to enable, disable, configure, or troubleshoot any OpenClash feature on OpenWrt.' instructions: | You are an OpenClash expert assistant. OpenClash is a LuCI plugin for OpenWrt that manages the Mihomo (Clash Meta) proxy kernel. When answering user questions about OpenClash: 1. Always provide LuCI web UI navigation paths (e.g. 服务 → OpenClash → 插件设置 → 流量控制), not command-line unless explicitly requested. 2. Explain underlying principles (firewall chains, YAML transformation logic) — not just steps. 3. Check dependency integrity first when troubleshooting (see 完整依赖清单与故障排查 section). 4. Never guess — if information is not covered in this document, actively query Mihomo Wiki (https://wiki.metacubex.one/config/), Meta-Docs (https://github.com/MetaCubeX/Meta-Docs), OpenClash source code (https://github.com/vernesong/OpenClash/tree/dev), Mihomo core source code (https://github.com/MetaCubeX/mihomo/tree/Alpha), or Smart core source code (https://github.com/vernesong/mihomo/tree/Alpha). 5. Cite sources when information comes from external queries. type: knowledge-base tags: [openclash, openwrt, mihomo, clash, proxy, networking] argument-hint: '询问 OpenClash 功能如何开启/关闭' user-invocable: true disable-model-invocation: false --- # OpenClash 完整功能参考指南 ## AI 行为总则 > **本文档是 AI 的知识库,而非给用户看的说明书。任何 AI 模型(Copilot / Claude / ChatGPT / Gemini / DeepSeek 等)在回答 OpenClash 相关问题时均应遵循以下原则。** | 原则 | 说明 | |------|------| | **主动查证,不猜测** | 遇到本文档未覆盖的 Mihomo 配置字段或实现细节时,**禁止编造**。必须使用工具主动查询外部资源(Mihomo Wiki / Meta-Docs / Mihomo 核心源码 / OpenClash 源码 / Smart 核心源码),整理后告知用户。详见文档末尾「超出本文档范围的查询」节。 | | **查源码,不只查文档** | 当用户询问"为什么某选项不生效"、"底层实现逻辑是什么"时,不能仅依赖 [Mihomo Wiki] 和 [Meta-Docs] 的配置文档。必须进一步查阅 [Mihomo 核心源码](https://github.com/MetaCubeX/mihomo/tree/Alpha)、[OpenClash 源码](https://github.com/vernesong/OpenClash/tree/dev) 和 [Smart 核心源码](https://github.com/vernesong/mihomo/tree/Alpha) 中的对应脚本/函数,理解实际执行逻辑。 | | **给出 LuCI 操作路径** | 所有操作指导必须指向 LuCI Web 界面的具体操作路径(如「服务 → OpenClash → 插件设置 → 流量控制」),而非命令行。仅在用户明确要求命令行操作时才提供终端命令。 | | **解释原理,不只给步骤** | 说明配置选项背后的工作原理(如防火墙规则链、YAML 转换逻辑),帮助用户理解后再操作,降低误操作风险。 | | **先排查依赖** | 用户报告功能异常时,首先检查依赖包是否完整。本文档「完整依赖清单与故障排查」节提供了完整的依赖速查表。 | | **引用来源** | 当信息来自外部查询(Mihomo Wiki、源码、Issues 等),在回复末尾注明来源,让用户知道信息的权威性。 | | **先要日志,不盲猜** | 当用户问题描述不完整、缺少关键报错信息,或本文档无对应内容时,**不应猜测排查方向**。应首先要求用户提供调试日志,并给出日志生成指引:① **LuCI 页面操作**:「插件设置 → 调试日志」页面点击「生成日志」按钮;② **SSH 命令操作**:`/usr/share/openclash/openclash_debug.sh` 生成日志文件(输出路径`/tmp/openclash_debug.log`)。拿到日志后再对照本文档「日志与错误信息速查」节或者文档、源码进行诊断。 | | **查 Issues,不闭门造车** | 当用户遇到的功能问题在本文档中未覆盖,或报错信息在错误速查表中无匹配项时,**必须主动搜索 Issues** 查找是否存在相同或相似的问题:① 插件配置/订阅/防火墙/UI 相关问题 → 搜索 [OpenClash Issues](https://github.com/vernesong/OpenClash/issues);② 内核级问题(代理协议/TUN/DNS 解析/规则引擎等 Mihomo 核心行为) → 搜索 [Mihomo Issues](https://github.com/MetaCubeX/mihomo/issues)。优先参考:**作者/维护者的回复**(OpenClash 标有 Owner 标签的 vernesong;Mihomo 标有 Contributor/Collaborator 标签的回复)——代表官方立场或已知 bug;**高赞反应(👍)的社区回复**——代表经过验证的有效方案;**同类问题中的诊断命令**(如 `nft list set`、`dig`、`uci show` 等)——可直接复用于用户的问题排查。搜索时使用用户报错中的关键错误信息或功能描述作为关键词。 | **核心资源速查**: | 资源 | URL | 用途 | |------|-----|------| | Mihomo Wiki | `https://wiki.metacubex.one/config/` | Mihomo YAML 配置字段文档 | | Meta-Docs | `https://github.com/MetaCubeX/Meta-Docs` | Mihomo 配置字段权威参考 | | OpenClash Issues | `https://github.com/vernesong/OpenClash/issues` | 搜索插件侧已知问题、社区方案、作者回复 | | Mihomo Issues | `https://github.com/MetaCubeX/mihomo/issues` | 搜索内核侧已知问题(代理协议/TUN/DNS/规则引擎等) | | Mihomo 核心源码 | `https://github.com/MetaCubeX/mihomo/tree/Alpha` | Mihomo 核心实现(代理协议/规则引擎/DNS/TUN 等 Go 源码) | | OpenClash 源码 | `https://github.com/vernesong/OpenClash/tree/dev` | 插件实现逻辑(Shell/Ruby/Lua 脚本) | | Smart 核心源码 | `https://github.com/vernesong/mihomo/tree/Alpha` | Smart 策略、LightGBM 模型实现 | --- ## 完整依赖清单与故障排查 > **AI 行为指引**: 当用户报告启动失败、功能异常、日志报错时,AI 应首先对照下表检查依赖完整性。 > 指导用户在 LuCI 的「插件设置 → 调试日志」页面点击「生成调试日志」按钮,可自动生成完整的 > 依赖检查报告(含 `#===== 依赖检查 =====#` 段)。对于缺失的依赖,指导用户在 > LuCI 的「系统 → 软件包」中搜索安装,而非让用户执行命令行。 > > **固件提醒**: 推荐使用 ImmortalWrt 或 OpenWrt 官方固件(需自行将 `dnsmasq` 替换为 `dnsmasq-full`)。不推荐使用第三方魔改/高大全固件、以及已停止维护的旧版固件。旁路由组网存在固有的网络层面缺陷,强烈建议采用主路由架构部署 OpenClash。 ### 一、包依赖总览(来自 Makefile DEPENDS 和 init.d 运行时检查) OpenClash 依赖以下软件包,由 `opkg`/`apk` 在安装时自动拉取。若手动卸载了其中某个包,会导致对应功能异常。 | 依赖包 | 作用 | 缺失症状 | 安装命令 (LuCI) | |--------|------|----------|-----------------| | `dnsmasq-full` | DNS 转发与劫持(必须用 full 版,非精简版) | DNS 劫持失效、客户端无法解析域名 | 「系统→软件包」搜索 `dnsmasq-full` | | `bash` | 所有 Shell 脚本的解释器 | 启动脚本执行失败 | 搜索 `bash` | | `curl` | HTTP/HTTPS 下载(订阅、GEO、Dashboard) | 订阅更新失败、GEO 下载报错 | 搜索 `curl` | | `ca-bundle` | CA 证书包(curl HTTPS 验证) | curl SSL 证书错误 | 搜索 `ca-bundle` | | `ip-full` | 策略路由和 ipset/nftset 操作 | 路由表操作失败 | 搜索 `ip-full` | | `ruby` | YAML 解析与配置生成 | `yml_change.sh` 报错、配置无法生成 | 搜索 `ruby` | | `ruby-yaml` | Ruby YAML 库 | Ruby YAML 解析报错、订阅处理失败 | 搜索 `ruby-yaml` | | `ruby-psych` | Ruby YAML 解析引擎(新版依赖) | 同上,日志提示 "Ruby Works Abnormally" | 搜索 `ruby-psych` | | `ruby-pstore` | Ruby 持久化存储(订阅缓存) | 订阅配置缓存异常 | 搜索 `ruby-pstore` | | `kmod-tun` | TUN 虚拟网卡内核模块 | TUN 模式无法启动 | 搜索 `kmod-tun` | | `kmod-inet-diag` | 进程名诊断(PROCESS-NAME 规则) | PROCESS-NAME 规则不生效 | 搜索 `kmod-inet-diag` | | `unzip` | 解压 Dashboard/GEO 等压缩包 | Dashboard 下载后无法加载 | 搜索 `unzip` | | `luci-compat` | LuCI >= 19.07 兼容层(新版 LuCI 必装) | LuCI 页面布局错乱、JS 报错 | 搜索 `luci-compat` | ### 二、防火墙相关依赖(按 fw4/fw3 自动区分) | 环境 | 依赖包 | 作用 | 缺失症状 | 安装命令 (LuCI) | |------|--------|------|----------|-----------------| | **fw4 (nftables)** | `kmod-nft-tproxy` | nftables TPROXY 透明代理(UDP) | UDP 无法代理、启动日志报 "nft_tproxy module not found" | 搜索 `kmod-nft-tproxy` | | **fw3 (iptables)** | `kmod-ipt-tproxy` | iptables TPROXY 模块 | UDP 无法代理、日志报 "xt_TPROXY" | 搜索 `kmod-ipt-tproxy` | | **fw3 (iptables)** | `iptables-mod-tproxy` | iptables TPROXY 用户态工具 | TPROXY 规则无法创建 | 搜索 `iptables-mod-tproxy` | | **fw3 (iptables)** | `kmod-ipt-extra` | iptables 扩展匹配模块 | 高级规则匹配失败 | 搜索 `kmod-ipt-extra` | | **fw3 (iptables)** | `iptables-mod-extra` | iptables extra 用户态工具 | 同上 | 搜索 `iptables-mod-extra` | | **fw3 (iptables)** | `kmod-ipt-nat` | iptables NAT 内核模块 | REDIRECT/DNAT 规则失败 | 搜索 `kmod-ipt-nat` | | **fw3 (iptables)** | `ipset` | IP 集合管理工具 | 中国 IP 绕行、黑白名单失效 | 搜索 `ipset` | ### 三、dnsmasq 特殊要求 | 要求 | 说明 | |------|------| | **必须使用 `dnsmasq-full`** | OpenWrt 自带的 `dnsmasq` 精简版缺少 ipset/nftset 支持,OpenClash 的 DNS 劫持和 chnroute 旁路依赖此功能 | | **ipset 编译选项** | `dnsmasq --version` 输出需包含 `ipset`(fw3 环境必需) | | **nftset 编译选项** | `dnsmasq --version` 输出需包含 `nftset`(fw4 环境,影响 chnroute_pass 的 nftset 集成) | > **诊断方法**: 先在 LuCI 的「插件设置 → 调试日志」页面生成调试日志,在日志的依赖检查段确认 dnsmasq 版本。如需手动确认,可在路由器终端执行 `dnsmasq --version | head -1`。 > 如果不是,在 LuCI 的「系统 → 软件包」中卸载 `dnsmasq` 然后安装 `dnsmasq-full`。 ### 四、内核模块加载机制(`check_mod()` 函数) `init.d/openclash` 的 `check_mod()` 函数以四级回退方式检查和加载内核模块: 1. **容器检测** — 检测 Docker/LXC/Podman 等容器环境,容器内直接返回成功(无法加载内核模块) 2. **内核编译检查** — 检查 `/proc/config.gz` 中是否有 `CONFIG_=y`(静态编译进内核,无需 modprobe) 3. **已加载检查** — `lsmod | grep` 检查模块是否已在内核中加载 4. **动态加载尝试** — `modprobe ` 尝试加载,全部失败则输出 `LOG_ERROR` > **TUN 模块注意事项**: `check_mod "tun"` 仅在 **TUN 模式** 或 **IPv6 TUN 模式** 时才被调用。Redir-Host/Fake-IP(非 TUN)模式下不会检查 `kmod-tun`。 ### 五、更新后自动修复依赖(`openclash_update.sh`) 插件更新后,`install_missing_packages()` 会遍历以下关键包列表,对缺失的包自动重装(支持 `opkg` 和 `apk` 双包管理器,最多重试 3 次): ``` luci-compat kmod-inet-diag kmod-nft-tproxy kmod-ipt-nat iptables-mod-tproxy iptables-mod-extra ipset ``` ### 六、常见依赖故障速查 | 故障现象 | 可能原因 | LuCI 排查路径 | |----------|----------|--------------| | 启动失败,日志显示 "Ruby Works Abnormally" | `ruby` 或 `ruby-yaml` 未安装/损坏 | 「系统→软件包」确认 `ruby`、`ruby-yaml`、`ruby-psych` 已安装 | | TUN 模式启动报错 "tun module not found" | `kmod-tun` 未安装或内核版本不匹配 | 「系统→软件包」安装 `kmod-tun`,注意内核版本匹配 | | 订阅更新报 SSL 证书错误 | `ca-bundle` 未安装或过期 | 「系统→软件包」安装/更新 `ca-bundle` | | DNS 劫持不生效 | 安装了精简版 `dnsmasq` 而非 `dnsmasq-full` | 「系统→软件包」卸载 `dnsmasq`,安装 `dnsmasq-full` | | UDP 流量无法代理(fw4) | `kmod-nft-tproxy` 未安装 | 「系统→软件包」安装 `kmod-nft-tproxy` | | Dashboard 页面白屏/404 | `unzip` 未安装导致仪表盘解压失败 | 「系统→软件包」安装 `unzip`,然后重新下载仪表盘 | | LuCI 页面布局错乱、按钮无响应 | `luci-compat` 未安装 | 「系统→软件包」安装 `luci-compat` | | 进程名规则 (PROCESS-NAME) 不生效 | `kmod-inet-diag` 未安装 | 「系统→软件包」安装 `kmod-inet-diag` | | 更新插件后某些包丢失 | 更新过程中包被意外移除 | 更新脚本会自动修复,如仍未恢复,手动安装缺失包 | > **通用依赖诊断方法**: 在 LuCI 的「插件设置 → 调试日志」页面点击「生成调试日志」,然后在日志的 `#===== 依赖检查 =====#` 段查看所有依赖包的状态(已安装/未安装)。将此日志提供给技术支持时也包含完整的依赖信息。 --- ## 系统架构速查 ``` ┌─────────────────────────────────────────────────────────────────┐ │ LuCI Web UI (Lua CBI) — http://路由器LAN_IP/cgi-bin/luci │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ settings │ │ overwrite│ │ subscribe│ ... │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ UCI 读写 │ │ │ │ ▼ ▼ ▼ │ │ /etc/config/openclash — UCI 配置文件 (所有选项持久化在此) │ │ │ │ │ ▼ Shell Scripts ( /usr/share/openclash/ ) │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ openclash.sh → 订阅下载/更新/节点过滤 │ │ │ │ openclash_core.sh → 核心二进制更新 │ │ │ │ openclash_update.sh → 插件 IPK 更新 │ │ │ │ openclash_geo.sh → GEO 数据库下载 (ipdb/dat/geosite/asn) │ │ │ openclash_chnroute.sh → 大陆 IP 路由表更新 │ │ │ │ yml_change.sh → Ruby 修改 YAML (端口/模式/DNS/TUN/认证) │ │ │ yml_rules_change.sh → Ruby 修改 YAML (规则/Provider/URL-Test) │ │ │ openclash_debug.sh → 诊断日志收集 │ │ │ │ openclash_watchdog.sh → 核心存活 + 流媒体解锁守护 │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ 生成 / 覆写 │ │ /etc/openclash/config/*.yaml — 原始订阅配置 │ │ /etc/openclash/*.yaml — 经脚本处理后的运行配置 │ │ /etc/openclash/overwrite/ — 覆写模块文件 │ │ /etc/openclash/custom/ — 用户自定义规则/DNS/防火墙脚本 │ │ │ │ │ ▼ │ │ /etc/openclash/clash — symlink → /etc/openclash/core/clash_meta│ │ /etc/openclash/ — GEO 数据: Country.mmdb, GeoSite.dat 等 │ └─────────────────────────────────────────────────────────────────┘ API 入口: http://路由器LAN_IP:9090 (external-controller) Dashboard: http://路由器LAN_IP:9090/ui/ ``` **关键目录说明**: | 路径 | 作用 | |------|------| | `/etc/config/openclash` | UCI 配置文件,所有 LuCI 选项持久化在此 | | `/etc/openclash/` | OpenClash 工作目录(核心、GEO 数据、Chnroute 列表) | | `/etc/openclash/config/` | 原始订阅配置存放目录(`.yaml` 文件,经 `yml_change.sh` 处理后生成 `/etc/openclash/.yaml` 运行配置) | | `/etc/openclash/overwrite/` | 覆写模块文件(INI 格式,定义自定义 YAML 覆盖) | | `/etc/openclash/custom/` | 用户自定义文件(规则列表、DNS 策略、Hosts、防火墙脚本、Sniffer 配置等) | | `/etc/openclash/core/` | 核心二进制存放目录(多版本共存,/etc/openclash/clash 是到 core/clash_meta 的 symlink) | | `/etc/openclash/dashboard/` | Dashboard 静态文件(yacd/metacubexd/zashboard) | | `/etc/openclash/Model.bin` | LightGBM 智能策略模型文件(注意:不是目录,是单个 .bin 文件) | | `/usr/share/openclash/` | 插件脚本目录(Shell/Ruby/Lua 脚本) | | `/tmp/openclash.log` | 运行日志 | | `/tmp/openclash_start.log` | 启动日志 | | `/tmp/etc/openclash/` | 小闪存模式下的工作目录(重启后清空) | | `/var/etc/openclash.include` | 防火墙规则加载文件(由 firewall UCI 自动 include) | - **UCI 配置根**: `openclash` (所有选项均在 `uci show openclash` 可见) - **Mihomo 运行时 API**: `http://路由器LAN_IP:9090` — 部分动态选项通过 PATCH `/configs` 热生效。注意:API 地址是**路由器 LAN 口 IP**,不是 127.0.0.1(核心监听 `0.0.0.0`,但 LuCI 后端通过 `127.0.0.1` 直连核心 API) - **核心启动脚本**: `/etc/init.d/openclash {start|stop|restart|reload|enable|disable}` - **自定义文件目录**: `/etc/openclash/custom/` — 存放用户自定义规则/DNS/防火墙脚本 --- ## 系统启动完整流程 > 理解此流程是理解所有选项实现逻辑的基础 ``` /etc/init.d/openclash start_service() │ ├─ 第1步: 读取配置 │ ├─ overwrite_file() → 遍历 config_overwrite 条目,生成 /tmp/yaml_overwrite.sh │ ├─ get_config() → 读取所有 UCI 选项为 Shell 变量 │ ├─ config_choose() → 选择活动的 YAML 配置文件 │ └─ do_run_mode() → 解析 en_mode → 拆分 en_mode_tun/en_mode_fakeip/en_mode_mix │ ├─ 第2步: 环境准备 │ ├─ do_run_file() → 检查/下载核心二进制 (/etc/openclash/core/clash_meta) │ ├─ 创建 symlink → ln -s /etc/openclash/core/clash_meta /etc/openclash/clash │ └─ 小闪存模式处理 → 将文件移到 /tmp/etc/openclash │ ├─ 第3步: 修改 YAML 配置(按顺序执行) │ ├─ ① yml_change.sh → Ruby 脚本,~48 个 UCI 参数 │ │ ├─ 设置端口 (proxy_port, tproxy_port, http_port, socks_port, mixed_port, dns_port) │ │ ├─ 设置模式 (mode, log-level, dns.enhanced-mode) │ │ ├─ 设置 TUN (tun.enable, tun.stack, tun.device, tun.dns-hijack) │ │ ├─ 设置 DNS (dns.* 完整段: nameserver, fallback, fake-ip-range, respect-rules...) │ │ ├─ 设置 Sniffer (sniffer.* 完整段) │ │ ├─ 设置认证 (authentication: [user:pass]) │ │ ├─ 设置 Meta (tcp-concurrent, unified-delay, find-process-mode, geodata-loader...) │ │ ├─ 设置 GEO (geox-url.*, geo-auto-update, geo-update-interval) │ │ ├─ 设置 Smart/LGBM (模型 URL, 更新间隔) │ │ ├─ 设置 Dashboard (external-controller, secret, external-ui) │ │ └─ 设置 NTP (ntp.*), CORS, IPv6, routing-mark │ │ │ ├─ ② yml_rules_change.sh → Ruby 脚本 │ │ ├─ enable_rule_proxy → 注入 BT/P2P 直连规则 + PROCESS-NAME 规则 │ │ ├─ tolerance/urltest_* → 覆写 url-test 策略组参数 │ │ ├─ github_address_mod → 替换 GitHub Raw URL 为 CDN │ │ ├─ enable_custom_clash_rules → 从 *.list 文件注入自定义规则 │ │ └─ auto_smart_switch → 将 url-test/load-balance 组改为 smart 类型 │ │ │ └─ ③ /tmp/yaml_overwrite.sh → 来自覆写模块 [Overwrite] 段的自定义脚本 │ ├─ 第4步: 启动核心 │ └─ procd 启动 clash -d /etc/openclash -f │ ├─ respawn 配置: 重试 5 次, 间隔 3s, 超时 300s │ └─ rlimit_nofile: 1048576 (最大文件描述符) │ ├─ 第5步: 异步等待核心就绪 (check_core_status "start" &) │ ├─ 轮询 HTTP 200 from http://127.0.0.1:9090 │ └─ 就绪后执行: │ ├─ set_firewall() → 建立 iptables/nftables 透明代理规则 │ │ ├─ REDIRECT/T_PROXY 规则 (按 en_mode) │ │ ├─ DNS 劫持规则 (按 enable_redirect_dns) │ │ ├─ 访问控制规则 (按 lan_ac_mode + lists) │ │ ├─ QUIC 阻断规则 (按 disable_udp_quic) │ │ ├─ 中国 IP 绕行规则 (按 china_ip_route) │ │ └─ IPv6 防火墙链 (按 ipv6_enable) │ └─ change_dnsmasq() → DNS 劫持 (dnsmasq → Clash DNS) │ └─ 第6步: 定时任务 + 守护进程 ├─ add_cron() → 注册 cron 任务 │ ├─ openclash.sh → 定时更新订阅 │ ├─ openclash_geo.sh → 定时更新 GEO 数据 │ ├─ openclash_chnroute.sh → 定时更新大陆路由 │ └─ /etc/init.d/openclash restart → 定时自动重启 └─ start_watchdog() → 启动守护进程 ├─ openclash_watchdog.sh → 核心存活监控 └─ openclash_streaming_unlock.lua → 流媒体解锁守护 ``` **停止流程** (`stop_service()`): 1. 备份策略组状态历史 → 2. `revert_firewall()` 清除防火墙规则 → 3. kill clash + streaming unlock 进程 → 4. `revert_dnsmasq()` 恢复 DNS → 5. `del_cron()` 清除定时任务 **热生效 vs 需重启**: | 操作 | 方式 | 延迟 | |------|------|------| | 切换代理模式 (rule/global/direct) | Mihomo API `PATCH /configs` (mode) | 即时 | | 切换日志级别 | Mihomo API `PATCH /configs` (log-level) | 即时 | | 切换 Sniffer/Rules | Mihomo API `PATCH /configs` | 即时 | | 修改端口/TUN/DNS/覆写 | 需重启核心 (修改 YAML) | ~3-5s | | 修改防火墙规则 | `/etc/init.d/openclash reload` | 即时 | | 修改访问控制 | 需重启 (重建防火墙链) | ~5s | --- ## 防火墙与 DNS 规则详解(iptables + nftables 双后端) > OpenClash 同时支持 **fw3 (iptables/ipset)** 和 **fw4 (nftables)** 两种防火墙后端,通过 `command -v fw4` 自动检测: > - 存在 `fw4` → 使用 **nftables** (OpenWrt 22.03+) > - 不存在 `fw4` → 使用 **iptables + ipset** (旧版 OpenWrt) > 所有 `if [ -n "$FW4" ]` / `if [ -z "$FW4" ]` 分支互斥,两种后端的**规则逻辑完全相同**,仅语法不同。 > > **AI 行为指引**: 当用户询问透明代理/防火墙相关问题时(如"为什么设备无法上网"、"旁路由模式下流量不走代理"、 > "如何验证防火墙规则是否生效"、"TUN 模式下某协议不通"),AI 应首先让用户在 LuCI 的「运行状态」页面 > 确认核心状态为「运行中」;然后建议用户在 LuCI 的「插件设置 → 调试日志」页面生成调试日志 > (包含完整防火墙规则链)。如需实时排查,可在路由器终端执行 `nft list ruleset`(fw4)或 > `iptables -t nat -L -n`(fw3)查看实际规则。结合下表中的链结构和规则排序,对比用户的需求判断规则是否如预期生效。 > 如涉及底层实现细节,查阅 [OpenClash 源码](https://github.com/vernesong/OpenClash/tree/dev) 中 > `/etc/init.d/openclash` 的 `set_firewall()` 函数。 > 常见问题:规则排序错误(bypass 在 redirect 之后)、fwmark 未设置导致策略路由不生效、 > DNS 劫持端口与 dnsmasq 冲突。 ### 模式解析表 | UCI `en_mode` | `en_mode_tun` | 数据面 | DNS 面 | |---------------|---------------|--------|--------| | `redir-host` | *(空)* | TCP REDIRECT + UDP TPROXY | `dns.enhanced-mode: redir-host` | | `fake-ip` | *(空)* | TCP REDIRECT + UDP TPROXY | `dns.enhanced-mode: fake-ip` | | `redir-host-tun` | `1` | TCP+UDP 全 TUN | `dns.enhanced-mode: redir-host` | | `fake-ip-tun` | `1` | TCP+UDP 全 TUN | `dns.enhanced-mode: fake-ip` | | `redir-host-mix` | `2` | TCP REDIRECT + UDP TUN | `dns.enhanced-mode: redir-host` | | `fake-ip-mix` | `2` | TCP REDIRECT + UDP TUN | `dns.enhanced-mode: fake-ip` | **全局常量**: ```bash PROXY_FWMARK="0x162" # 所有被代理流量的防火墙标记 PROXY_ROUTE_TABLE="0x162" # 策略路由表 ID SKIP_GROUP="65534" # 绕过代理的组 ID (skgid) ``` --- ### 一、fw4 (nftables) 链结构 — `inet fw4` 表 #### A. DNS 劫持链 **`enable_redirect_dns=1` (Dnsmasq 转发模式)**: ```bash # PREROUTING: 劫持发往 53 端口的 DNS → 重定向到 dnsmasq 端口 nft insert rule inet fw4 dstnat position 0 \ meta l4proto {tcp,udp} th dport 53 \ counter redirect to comment "OpenClash DNS Hijack" # OUTPUT (仅 router_self_proxy=1): 路由器自身 DNS nft add chain inet fw4 nat_output { type nat hook output priority -1; } nft insert rule inet fw4 nat_output position 0 \ skgid != 65534 meta l4proto {tcp,udp} th dport 53 \ ip daddr {127.0.0.1} counter redirect to ``` **`enable_redirect_dns=2` (防火墙重定向模式)**: ```bash nft add chain inet fw4 openclash_dns_redirect nft add rule inet fw4 openclash_dns_redirect \ meta l4proto {tcp,udp} th dport 53 counter redirect to nft insert rule inet fw4 dstnat position 0 \ meta l4proto {tcp,udp} th dport 53 counter jump openclash_dns_redirect ``` #### B. 非 TUN 模式链 (`en_mode_tun` 为空或 `2`) | 链名 | 钩子来源 | 协议 | 动作 | |------|----------|------|------| | `openclash` | `dstnat` jump | TCP | REDIRECT → `$proxy_port`(7892) | | `openclash_mangle` | `mangle_prerouting` jump | UDP | TPROXY → `:$tproxy_port`(7895), mark `0x162` | | `openclash_upnp` | `openclash_mangle` jump | UDP | UPNP 端口排除 (RETURN) | | `openclash_output` | `nat_output` jump | TCP | 路由器自身 TCP REDIRECT | | `openclash_mangle_output` | `mangle_output` jump | UDP | 路由器自身 UDP 标记 | **`openclash` 链规则排序 (TCP REDIRECT)**: ```bash # 1. 本地网络绕过 nft add rule inet fw4 openclash ip daddr @localnetwork counter return # 2. 回复方向绕过 nft add rule inet fw4 openclash ct direction reply counter return # 3. Fake-IP 范围 (仅 fake-ip 模式) nft add rule inet fw4 openclash ip protocol tcp \ ip daddr {198.18.0.0/16} counter redirect to $proxy_port # 4. WAN 黑名单 IP (WAN-AC) nft add rule inet fw4 openclash ip daddr @wan_ac_black_ips counter return # 5. WAN 黑名单端口 nft add rule inet fw4 openclash th dport @wan_ac_black_ports counter return # 6. LAN 黑名单 IP (LAN-AC, lan_ac_mode=0) nft add rule inet fw4 openclash ip saddr @lan_ac_black_ips counter return # 7. LAN 黑名单 MAC nft add rule inet fw4 openclash ether saddr @lan_ac_black_macs counter return # 8. 白名单检查 (lan_ac_mode=1) # 非白名单 → RETURN: ether saddr != @lan_ac_white_macs \ # ip saddr != @lan_ac_white_ips counter return # 9. 非标准端口绕过 (redir-host 模式, common_ports != 0) nft add rule inet fw4 openclash th dport != @common_ports counter return # 10. 中国 IP 绕行 (china_ip_route) # mode=1: ip daddr @china_ip_route counter return # mode=2: ip daddr != @china_ip_route counter return # 11. 最终代理: 所有剩余 TCP → REDIRECT nft add rule inet fw4 openclash ip protocol tcp counter redirect to $proxy_port ``` **`openclash_mangle` 链规则排序 (UDP TPROXY)**: 同上 #1-#10,最终规则: ```bash # UPNP 排除 nft add rule inet fw4 openclash_mangle ip protocol udp counter jump openclash_upnp # TPROXY 最终规则 nft add rule inet fw4 openclash_mangle meta l4proto {udp} \ counter tproxy ip to 127.0.0.1:$tproxy_port meta mark set $PROXY_FWMARK accept ``` #### C. TUN 模式链 (`en_mode_tun=1`) | 链名 | 钩子来源 | 协议 | 动作 | |------|----------|------|------| | `openclash_mangle` | `mangle_prerouting` jump | TCP+UDP | 设置 fwmark `0x162` | | `openclash_mangle_output` | `mangle_output` jump | TCP+UDP | 路由器自身 fwmark | **`openclash_mangle` 规则排序 (TUN 模式)**: ```bash # 1. 跳过 TUN 接口自身流量 nft add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} \ iifname utun counter return # 2-10. 同非 TUN 模式的 bypass 检查 (localnetwork/ct reply/WAN-AC/LAN-AC/common_ports/china_ip_route) # 11. ICMP 代理 nft add rule inet fw4 openclash_mangle ip protocol icmp \ icmp type echo-request counter meta mark set $PROXY_FWMARK # 12. UPNP 排除 (UDP) nft add rule inet fw4 openclash_mangle ip protocol udp counter jump openclash_upnp # 13. 最终标记 — 全 TUN 模式标记 tcp+udp,混合模式仅标记 udp nft add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} \ counter meta mark set $PROXY_FWMARK ``` **TUN 转发规则** (utun 允许通过): ```bash nft insert rule inet fw4 forward position 0 oifname utun counter accept nft insert rule inet fw4 forward position 0 iifname utun counter accept nft insert rule inet fw4 input position 0 iifname utun counter accept nft insert rule inet fw4 srcnat position 0 oifname utun counter return ``` #### D. IPv6 链 (独立于 IPv4) | nftables 链 | 功能 | |-------------|------| | `openclash_v6` | IPv6 TCP REDIRECT | | `openclash_mangle_v6` | IPv6 UDP TPROXY / TUN fwmark | | `openclash_output_v6` | 路由器自身 IPv6 TCP | | `openclash_mangle_output_v6` | 路由器自身 IPv6 fwmark | | `openclash_post_v6` | 旁路由 SNAT/MASQUERADE | IPv6 模式 (`ipv6_mode`): `0`=TProxy, `1`=Redirect, `2`=TUN, `3`=Mix #### E. ICMP/Ping 处理详解 > **AI 行为指引**: 当用户询问「为什么 ping 不走代理」、「ping 通但 TCP 不通」、「Fake-IP 模式下 ping 198.18.x.x 被拒绝」等问题时,AI 应结合本节解释 ICMP 在非 TUN 和 TUN 模式下的不同处理方式。 OpenClash 对 ICMP(ping)请求的处理**取决于运行模式**: **1. 非 TUN 模式(Redir-Host / Fake-IP,`en_mode_tun` 为空)**: ICMP echo-request 在 `openclash_mangle` 链中被**仅标记 fwmark(0x162)但不重定向**: ```bash nft add rule inet fw4 openclash_mangle ip protocol icmp \ icmp type echo-request mark set "$PROXY_FWMARK" counter accept comment "OpenClash ICMP Mark" ``` - **ICMP 不会被代理**:非 TUN 模式下只有 TCP(REDIRECT)和 UDP(TPROXY)被重定向到 Mihomo 内核,ICMP 仅被标记 fwmark 后直接放行(`accept`)。这意味着 ping 请求走的是系统原始路由表,不会经过代理节点。 - **fwmark 的作用**:标记 0x162 仅影响策略路由选择(如旁路由回流),不影响代理行为本身。 - **绕过检查仍然生效**:ICMP 规则之前的 localnetwork/WAN-AC/LAN-AC/china_ip_route 等 RETURN 规则同样适用于 ICMP——被匹配的 ICMP 包会跳过标记规则。 - **路由器自身 ICMP**:当 `router_self_proxy=1` 时,路由器发出的 ping 在 `openclash_mangle_output` 链中同样被标记。 **2. TUN 模式(`en_mode_tun=1`)**: ICMP echo-request 在 `openclash_mangle` 链中被标记 fwmark,随后通过策略路由进入 TUN 虚拟网卡: ```bash # 步骤1: 标记 ICMP nft add rule inet fw4 openclash_mangle ip protocol icmp \ icmp type echo-request mark set "$PROXY_FWMARK" counter accept # 步骤2: 策略路由(系统层面)— 所有标记 0x162 的流量路由到 TUN ip rule add fwmark 0x162 table 0x162 ip route add default dev utun table 0x162 ``` - **ICMP 被代理**:TUN 模式下所有标记 fwmark 的流量(包括 ICMP)被策略路由导向 `utun` 虚拟网卡,由 Mihomo 内核的 TUN 协议栈处理。 - **Mihomo 内核配置**:TUN 模式下 Mihomo 支持两个 ICMP 相关选项: - `icmp-timeout`(默认自动):ICMP 连接超时时间(秒) - `disable-icmp-forwarding`(默认 false):设为 `true` 可禁用 TUN 的 ICMP 转发(ping 将不被代理) **3. Fake-IP 非 TUN 模式的 Ping 阻断**: **仅在 Fake-IP 非 TUN 模式下**(`en_mode=fake-ip`, `en_mode_tun` 为空),对 Fake-IP 地址段(默认 `198.18.0.0/16`)的 ping 会被防火墙**显式 REJECT**: ```bash # INPUT 链 — 阻止路由器自身收到发往 Fake-IP 的 ping nft insert rule inet fw4 input position 0 ip protocol icmp \ icmp type echo-request ip daddr { 198.18.0.0/16 } counter reject # FORWARD 链 — 阻止局域网设备间转发 Fake-IP 的 ping nft insert rule inet fw4 forward position 0 ip protocol icmp \ icmp type echo-request ip daddr { 198.18.0.0/16 } counter reject # OUTPUT 链 — 阻止路由器发出对 Fake-IP 的 ping(排除 OpenClash 自身进程 skgid=65534) nft insert rule inet fw4 output position 0 ip protocol icmp \ icmp type echo-request ip daddr { 198.18.0.0/16 } \ skgid != 65534 counter reject ``` 这是因为在非 TUN 模式下,Fake-IP 地址没有对应的 TCP/UDP 重定向路径(TCP 走 REDIRECT、UDP 走 TPROXY,但 ICMP 都不到达内核),发往这些地址的 ping 无意义且会干扰网络诊断。OUTPUT 链排除 `skgid=65534` 是为了避免影响 OpenClash 自身进程的内部通信。 > **TUN 模式下的区别**:Fake-IP **TUN 模式不添加这些 REJECT 规则**。因为 ICMP 经策略路由进入 TUN 虚拟网卡后,由内核的 `skipPingForwardingByAddr()` 判断——若目标是 Fake-IP,内核返回伪造 echo-reply(~0ms 虚假延迟),不产生实际网络流量。 **4. IPv6 ICMP(ICMPv6)**: 仅在 IPv6 TUN/混合模式(`ipv6_mode=2` 或 `3`)下标记: ```bash nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr icmpv6 \ icmpv6 type echo-request mark set "$PROXY_FWMARK" counter accept ``` IPv6 非 TUN 模式下 ICMPv6 **不被标记也不被代理**。IPv6 Fake-IP 地址范围的 ping 在**非 TUN 的 IPv6 模式下**被 REJECT(返回 `icmpv6 admin-prohibited`),条件为 `$ipv6_mode -ne 2 -a $ipv6_mode -ne 3`。TUN/Mix 模式下的 IPv6 Fake-IP ping 同样由内核的 `skipPingForwardingByAddr()` 处理(伪造回复)。 **总结**: | 运行模式 | ICMP 进入 TUN | ICMP fwmark | 实际处理 | |----------|-------------|-------------|----------| | Redir-Host (非TUN) | ❌ | ✅ 标记 0x162 | 仅标记后放行,不经内核处理 | | Fake-IP (非TUN) | ❌ | ✅ 标记 0x162 | 防火墙 REJECT Fake-IP 范围的 ping | | Redir-Host TUN | ✅ | ✅ 标记 0x162 | 真实 IP → DIRECT 直连延迟 | | Fake-IP TUN | ✅ | ✅ 标记 0x162 | 真实 IP → DIRECT 直连;Fake-IP → 伪造回复(~0ms 虚假延迟) | | Redir-Host Mix | ✅ | ✅ 标记 0x162 | 同 Redir-Host TUN:ICMP 标记后经策略路由进入 TUN,DIRECT 直连 | | Fake-IP Mix | ✅ | ✅ 标记 0x162 | 同 Fake-IP TUN:真实 IP → DIRECT 直连;Fake-IP → 内核伪造回复 | > **实用提示**:如果用户发现 ping 不通但网页正常,首先确认不是 Fake-IP **非 TUN** 模式下在 ping 被代理的域名(Fake-IP 返回 `198.18.x.x`,防火墙直接 REJECT)。Fake-IP TUN/Mix 模式下 ping Fake-IP 地址会返回虚假 ~0ms 延迟。非 Fake-IP 的真实 IP ping 在 TUN/Mix 模式下走 DIRECT 直连,延迟反映的是本地网络质量。 **内核侧 ICMP 处理机制**(`listener/sing_tun/prepare.go` — Mihomo TUN 监听器): 当 ICMP echo-request 经策略路由进入 TUN 虚拟网卡后,Mihomo 内核按以下优先级处理: 1. **目标是 Fake-IP 地址**(`resolver.IsFakeIP(addr)`) → 返回 `nil, nil`,内核用**伪造的 echo-reply** 回复。上层看到 "ping 成功" 但实际未经过网络,延迟显示为虚假的 ~0ms 2. **目标是 TUN 接口自身 IP**(`inet4_address` / `inet6_address` 范围内) → 同上,伪造回复 3. **`disable-icmp-forwarding: true`** → 所有 ICMP 均伪造回复 4. **以上均不满足**(真实 IP 且未禁用转发) → 通过 `ping.ConnectDestination()` 以 **DIRECT 模式**发出真实 ICMP 包,等待真实 reply。延迟为本地网络到目标的实际 RTT 5. **ICMP 超时**: 默认 10 秒(`sing.go` 常量),可通过 `icmp-timeout` 自定义 > **关键结论**: TUN 模式下 ping 的处理分两种情况——目标是 Fake-IP → 虚假 0ms 延迟;目标是真实 IP → DIRECT 直连延迟。ping **始终不经过代理节点**,这与 TCP/UDP 流量(经代理转发)的行为不同。 --- ### 二、fw3 (iptables/ipset) 等效链 | iptables 链 | 表 | 等效 nftables 链 | |-------------|-----|-----------------| | `openclash` | `nat` | `inet fw4 openclash` (TCP) | | `openclash` | `mangle` | `inet fw4 openclash_mangle` (UDP) | | `openclash_output` | `nat` | `inet fw4 openclash_output` (TCP) | | `openclash_output` | `mangle` | `inet fw4 openclash_mangle_output` (UDP) | | `openclash_post` | `nat` | `inet fw4 openclash_post` | | `openclash_wan_input` | `filter` | `inet fw4 openclash_wan_input` | | `openclash_dns_redirect` | `nat` | `inet fw4 openclash_dns_redirect` | | `openclash_upnp` | `mangle` | `inet fw4 openclash_upnp` | **fw3 兼容性层** — 自动检测 iptables 是否支持 owner/gid 模块: ```bash if iptables 不支持 owner 模块; then owner="-m mark --mark 0x1a0a" # 回退: 按 fwmark 匹配 noowner="-m mark ! --mark 0x1a0a" else owner="-m owner --gid-owner 65534" # 标准: owner 模块 noowner="-m owner ! --gid-owner 65534" fi ``` **示例 fw3 REDIRECT (TCP)**: ```bash iptables -t nat -N openclash iptables -t nat -A openclash -m set --match-set localnetwork dst -j RETURN iptables -t nat -A openclash -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports 7892 iptables -t nat -A openclash -p tcp -m set ! --match-set common_ports dst -j RETURN iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports 7892 iptables -t nat -A PREROUTING -p tcp -j openclash ``` **示例 fw3 TPROXY (UDP)**: ```bash iptables -t mangle -N openclash iptables -t mangle -A openclash -p udp -m set --match-set localnetwork dst -j RETURN iptables -t mangle -A openclash -p udp -j TPROXY --on-port 7895 --tproxy-mark 0x162 iptables -t mangle -A PREROUTING -p udp -j openclash ``` --- ### 三、各选项对防火墙规则的具体影响 | 选项 | 值 | 防火墙规则变化 | |------|---|---------------| | **`china_ip_route`** (实验性:绕过指定区域 IP / China IP Route) | `1` (绕过大陆) | 在代理规则前插入 `ip daddr @china_ip_route counter return` — 目标为国内 IP 的流量跳过代理 | | | `2` (绕过海外) | 插入 `ip daddr != @china_ip_route counter return` — 目标非国内 IP 的流量跳过代理 | | **`china_ip6_route`** (实验性:绕过指定区域 IPv6 / China IPv6 Route) | `1` (绕过大陆) | IPv6 等效规则:`ip6 daddr @china_ip6_route counter return` — 目标为国内 IPv6 的流量跳过代理 | | | `2` (绕过海外) | IPv6 等效规则:`ip6 daddr != @china_ip6_route counter return` | | **`disable_udp_quic`** (禁用 QUIC / Disable QUIC) | `1` | 非 TUN: `nft insert rule inet fw4 input position 0 udp dport 443 ip daddr != @china_ip_route counter reject` — 阻断入站 QUIC;TUN: `nft insert rule inet fw4 forward position 0 oifname utun udp dport 443 ... counter reject` — 阻断 TUN 出方向 QUIC | | **`lan_ac_mode`** (局域网访问控制模式 / LAN Access Control Mode) | `0` (黑名单) | 创建 `lan_ac_black_ips`/`lan_ac_black_macs` set,匹配到的 RETURN 跳过代理 | | | `1` (白名单) | 创建 `lan_ac_white_ips`/`lan_ac_white_macs` set,**不匹配**的 RETURN 跳过代理(反逻辑) | | **`common_ports`** (仅允许常用端口流量 / Common Ports Proxy Mode) | `非0` | 插入 `th dport != @common_ports counter return` — 仅代理指定端口,P2P/BT 端口被绕过。仅 redir-host 模式生效 | | **`router_self_proxy`** (路由本机代理 / Router-Self Proxy) | `1` | 创建 OUTPUT 链 (`openclash_output` + `openclash_mangle_output`),路由器自身流量被重定向/标记 | | | `0` | 删除 OUTPUT 链,路由器自身流量走原始路由 | | **`intranet_allowed`** (仅允许内网 / Only Intranet Allowed) | `1` | 创建 `openclash_wan_input` 链,DROP 来自 WAN 口对 `$cn_port`(9090) 及代理端口的访问 | | **`bypass_gateway_compatible`** (旁路网关(旁路由)兼容 / Bypass Gateway Compatible) | `1` | 创建 `openclash_post` 链,对已标记流量执行 MASQUERADE SNAT,解决旁路由回流问题 | | **`skip_proxy_address`** (绕过服务器地址 / Skip Proxy Address) | `1` | 创建 `openclash_proxy_server_ip` nft set,在代理规则前插入 `ip daddr @openclash_proxy_server_ip counter return`,防止代理嵌套 | | **`enable_redirect_dns`** (本地 DNS 劫持 / Redirect Local DNS Setting) | `1` | 在 `dstnat` 插入 DNS 53 端口 REDIRECT 规则到 dnsmasq 端口 | | | `2` | 创建 `openclash_dns_redirect` 链,DNS 流量直接 DNAT 到 `dns_port`(7874) | | **`local_network_pass`** (本地 IPv4 绕过地址 / Local IPv4 Network Bypassed List) | 已配置 | 创建 `localnetwork` nft set,在 `openclash` 链规则 #1 中匹配本地 IP 段 RETURN 跳过代理 | | **`chnroute_pass`** (绕过指定区域 IPv4 黑名单 / Chnroute Bypassed List) | 已配置 | 创建 `china_ip_route_pass` nft set,配合 dnsmasq 将指定域名解析的 IP 加入 set,防火墙规则中优先于 `china_ip_route` 匹配(确保这些 IP 不被绕行规则跳过) | | **`ipv6_enable`** (IPv6 流量代理 / Proxy IPv6 Traffic) | `1` | 创建完整的 IPv6 防火墙链:`openclash_v6`(TCP REDIRECT)、`openclash_mangle_v6`(UDP TPROXY)、`openclash_output_v6`(路由自身)、`openclash_post_v6`(旁路由 SNAT) | | **`local_network6_pass`** (本地 IPv6 绕过地址 / Local IPv6 Network Bypassed List) | 已配置 | 创建 IPv6 `localnetwork` nft set,IPv6 链中匹配本地 IPv6 段 RETURN | | **ICMP/Ping 处理**(无 UCI 选项,由运行模式决定) | Redir-Host / Fake-IP(非 TUN) | ICMP echo-request 仅标记 fwmark `0x162` 后 accept,**不被代理**(只有 TCP/UDP 被重定向到内核);Fake-IP 非 TUN 模式下对 `198.18.0.0/16` 的 ping 被防火墙 REJECT(INPUT/FORWARD/OUTPUT 三链阻断) | | | TUN 模式 / Mix 模式 | ICMP 标记 fwmark 后经策略路由进入 TUN 虚拟网卡,由 TUN 内核处理(真实 IP → DIRECT 直连延迟,Fake-IP → 伪造回复 ~0ms);可通过 Mihomo 的 `disable-icmp-forwarding` 禁用 | --- ### 四、Dnsmasq 修改详解 (`change_dnsmasq` / `revert_dnsmasq`) **修改流程** (`change_dnsmasq()`, 仅在 `enable_redirect_dns=1` 时执行): ```bash # 1. 备份原始配置到 openclash.config.* save_dnsmasq_server() → uci add_list openclash.config.dnsmasq_server="<原始server>" uci set openclash.config.dnsmasq_noresolv="$(uci get dhcp.@dnsmasq[0].noresolv)" uci set openclash.config.dnsmasq_resolvfile="$(uci get dhcp.@dnsmasq[0].resolvfile)" uci set openclash.config.dnsmasq_cachesize="$(uci get dhcp.@dnsmasq[0].cachesize)" # 2. 重定向 DNS uci del dhcp.@dnsmasq[-1].server uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#$dns_port" uci delete dhcp.@dnsmasq[0].resolvfile uci set dhcp.@dnsmasq[0].noresolv=1 uci set dhcp.@dnsmasq[0].localuse=1 uci set dhcp.@dnsmasq[0].cachesize=0 # 3. IPv6 DNS (ipv6_dns=1 时) uci set dhcp.@dnsmasq[0].filter_aaaa=0 # 允许 AAAA 记录 # 4. chnroute_pass 处理 — 加载 ipset/nftset load_ip_route_pass() # 创建 china_ip_route_pass ipset/nftset # 将 openclash_custom_chnroute_pass.list 中的域名加入 set # 对 china_ip_route_pass UCI 列表中的域名加入 set # 5. 自定义域名 DNS /usr/share/openclash/openclash_custom_domain_dns.sh # 6. 重启 dnsmasq /etc/init.d/dnsmasq restart ``` **恢复流程** (`revert_dnsmasq()`): ```bash # 1. 删除 OpenClash 注入的 server uci del dhcp.@dnsmasq[-1].server # 2. 恢复原始 server 列表 for server in $(uci get openclash.config.dnsmasq_server); do uci add_list dhcp.@dnsmasq[0].server="$server" done # 3. 恢复 resolvfile / noresolv / cachesize / filter_aaaa uci set dhcp.@dnsmasq[0].noresolv="$saved_noresolv" uci set dhcp.@dnsmasq[0].resolvfile="$saved_resolvfile" uci set dhcp.@dnsmasq[0].cachesize="$saved_cachesize" # 4. DNS 验证 — 测试修改后的 DNS 是否可用 if nslookup www.apple.com 127.0.0.1: 失败; then # 创建 fallback resolv.conf (114.114.114.114, 8.8.8.8) fi ``` **chnroute_pass 的 dnsmasq 集成**: - 创建 `china_ip_route_pass` ipset/nftset - 将 chnroute_pass 域名加入 set: `ipset=/domain.com/china_ip_route_pass` 或 `nftset=/domain.com/4#inet#fw4#china_ip_route_pass` - 效果: DNS 解析这些域名时加入 set 便于在匹配时绕过(而非被 chnroute 影响) --- ## 日志与错误信息速查 > **AI 行为指引**: 当用户提供日志报错信息时,AI 应首先在以下表格中查找匹配的错误关键字, > 根据「原因」列判断问题根源,然后按「排查方法」列指导用户在 LuCI 中操作。 > **若表中未覆盖该错误**,应主动搜索 [OpenClash GitHub Issues](https://github.com/vernesong/OpenClash/issues) 查找是否存在相同或相似的问题, > 优先参考高赞反应的社区回复和作者(vernesong)给出的解决方案。搜索时可使用错误关键字作为搜索词。 > > **两类日志说明**: > - **插件日志**(前九类):由 OpenClash 的 Shell/Ruby/Lua 脚本产生,含 `[Info]`/`[Tip]`/`[Warning]`/`[Error]` 前缀,写入 `/tmp/openclash.log`。可在 LuCI「运行日志」页面查看。 > - **内核日志**(第十、十一类):由 Mihomo 核心(Go 程序)产生,含 `level=debug/info/warning/error/fatal` 标记,同样写入 `/tmp/openclash.log`。`level=fatal` 会导致核心进程退出。可在 LuCI「运行日志」页面查看,或在「运行状态」页面看到 `OpenClash Start Failed` 提示。 ### 一、内核启动与运行错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Ruby Works Abnormally, Please Check The Ruby Library Depends!` (Ruby 依赖异常) | 「运行状态」启动流程 | `ruby` 或 `ruby-yaml` 包未安装/损坏 | 「系统→软件包」安装 `ruby`、`ruby-yaml`、`ruby-psych` | | `Unable To Parse Config File` (配置文件校验失败) | 「运行状态」启动流程 | YAML 配置文件语法错误或 age 解密失败 | 「配置管理」页面点击 Edit 检查 YAML 语法 | | `Core Start Failed, Please Check The Log Infos!` (内核启动失败) | 「运行状态」启动流程 | 核心进程未能启动 | 「运行状态」查看核心版本是否正确;「插件设置 → 调试日志」生成调试日志 | | `Core Initial Configuration Timeout` (内核初始化超时) | 「运行状态」启动流程 | 核心 API 在 300 秒内未就绪 | 检查 `/tmp/openclash.log` 中核心日志;确认「覆写设置→常规」的 cn_port 未被占用 | | `TUN Interface Start Failed` (TUN 接口启动失败) | 「运行状态」启动流程 | TUN 虚拟网卡创建失败 | 「系统→软件包」确认 `kmod-tun` 已安装 | | `【{module}】module not found` (内核模块未找到) | 「运行状态」启动流程 | 内核模块未安装/未加载(tun/tproxy 等) | 「系统→软件包」安装对应的 kmod 包 | | `LAN IP Address Get Error` (LAN IP 获取失败) | 「运行状态」启动流程 | LAN 接口 IP 无效或 `ip-full` 包缺失(旧内核 4.4.x 常见 br-lan 网桥无 IP) | 「插件设置→流量控制」选择正确的 LAN 接口名称(如 `br-lan`);「系统→软件包」安装 `ip-full`;终端 `ip address show br-lan` 确认存在 IPv4 地址;尝试切换运行模式为混合模式 | | `OpenClash Now Disabled, Need Start From Luci Page` (插件未启用) | 「运行状态」启动流程 | 插件被禁用(enable=0) | 「运行状态」页面点击启动开关 | ### 二、订阅与配置更新错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Config File Subscribed Failed` (订阅配置下载失败) | 「配置订阅」更新流程 | 订阅 URL 下载失败(curl 错误) | 「配置订阅」检查订阅 URL 是否正确;确认网络连通性 | | `Config File Tested Faild` (配置文件测试失败) | 「配置订阅」更新流程 | 下载的 YAML 未通过 `clash -t` 验证 | 「配置管理」页面 Edit 检查 YAML 语法;查看 `/tmp/openclash.log` | | `Updated Config Has No Proxy Field` (配置无节点字段) | 「配置订阅」更新流程 | 订阅配置中无 `proxies` 和 `proxy-providers` 字段 | 检查订阅源是否有效;可能订阅已过期 | | `Filter Proxies Failed` (节点筛选失败) | 「配置订阅」更新流程 | 节点关键字过滤正则异常 | 「配置订阅」检查 keyword/ex_keyword 格式 | | `Ruby Works Abnormally` (Ruby 异常) | 「配置订阅」更新流程 | Ruby 环境异常导致订阅处理失败 | 「系统→软件包」重装 `ruby`、`ruby-yaml` | | `Config File Format Validation Failed` (配置文件格式校验失败) | 「运行状态」启动流程 | YAML 解析后文件为空/丢失 | 「配置管理」检查配置目录权限和磁盘空间 | ### 三、GEO 与规则更新错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Download Failed: HTML Response Detected` (下载失败:检测到 HTML 响应) | 「插件设置→GEO 数据库订阅」 | CDN 返回的是 HTML 错误页而非 GEO 文件 | 「覆写设置→常规」检查 Github 地址修改 CDN 选项 | | `Download Failed: File Size Too Small` (下载失败:文件过小) | 「插件设置→GEO 数据库订阅」 | 下载文件 <1KB,内容不完整 | 「插件设置→GEO 数据库订阅」检查 GEO 自定义 URL 是否正确 | | `Update Error, Please Try Again Later` (更新失败,请稍后再试) | 「插件设置→GEO 数据库订阅」 | 网络下载失败 | 「运行状态」检查网络连通性;若使用代理下载,添加直连规则 | | `Control Panel Unzip Error!` (控制面板解压失败) | 「运行状态」仪表盘切换 | Dashboard 压缩包解压失败 | 「系统→软件包」确认 `unzip` 已安装 | | `LightGBM Model Update Error` (LGBM 模型更新失败) | 「覆写设置→智能设置」 | LGBM 模型下载失败 | 「覆写设置→智能设置」检查模型 URL | ### 四、内核与插件版本更新错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Core Version Check Error` (内核版本检测失败) | 「版本更新」 | GitHub 不可达,无法获取最新版本信息 | 「运行状态」检查网络连通性;如在大陆,设置 CDN | | `Core Update Failed` (内核更新失败,重试 3 次后) | 「版本更新」 | 核心下载/解压/替换失败 | 「版本更新」确认闪存空间和 CPU 架构选择;「系统 → 软件包」检查磁盘空间 | | `No Compiled Version Selected` (未选择编译版本) | 「版本更新」 | CPU 架构未选择(core_version=0) | 「版本更新」标签页选择对应的 CPU 架构 | | `Pre update test failed` (更新前测试失败,3 次后) | 「版本更新」 | 插件 IPK/APK 安装测试失败 | 手动在「系统→软件包」中更新或重装 luci-app-openclash | | `OpenClash update failed` (OpenClash 更新失败) | 「版本更新」 | 插件安装彻底失败 | 包已保存在 `/tmp/`,手动使用 `opkg install` 或 `apk add` 安装 | | `Failed to get version information` (获取版本信息失败) | 「版本更新」 | GitHub 版本检查失败 | 检查网络;「覆写设置→常规」设置 CDN | ### 五、防火墙与 DNS 错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Dnsmasq not Support nftset, Use ipset` (Dnsmasq 不支持 nftset) | 「运行状态」启动流程 | dnsmasq-full 未编译 nftset 支持 | 警告,非致命;如 chnroute 旁路异常则重装 dnsmasq-full | | `iptables DSCP module not available` (iptables DSCP 模块不可用) | 「运行状态」启动流程 | iptables 缺少 DSCP 模块 | 警告,DSCP 规则被跳过;或改用核心侧 DSCP | | `Can't Setting Only Intranet Allowed Function` (无法设置仅允许内网) | 「运行状态」启动流程 | 无法识别 WAN 接口 | 「插件设置→流量控制」检查 WAN 接口名称设置 | | `Nameserver Option Must Be Setted, Stop Customing DNS Servers` (Nameserver 未设置) | 「覆写设置→DNS」 | 自定义 DNS 启用但未配置任何 nameserver | 「覆写设置→DNS」添加至少一个 DNS 服务器 | | `Fallback-Filter Need fallback of DNS Been Setted` (Fallback-Filter 需要 Fallback DNS) | 「覆写设置→DNS」 | fallback-filter 需要先配置 fallback DNS | 「覆写设置→DNS」先添加 fallback 分组的 DNS 服务器 | | `DNS Loop Check` (DNS 回环检查) | 「覆写设置→DNS」 | DNS 配置存在回环风险 | 「覆写设置→DNS」检查服务器列表,避免将 Clash DNS 端口设为其上游 | ### 六、覆写模块错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `skip General key not allowed` (覆写 key 不允许) | 「覆写设置」覆写模块 | 覆写 [General] 中的 key 不在允许列表中 | 检查 key 拼写;参考覆写模块 10.2.1 节的允许 key 列表 | | `skip invalid Overwrite command` (无效覆写命令) | 「覆写设置」覆写模块 | [Overwrite] 段命令不以 `ruby_` 开头 | 修正命令语法,使用 `ruby_method_name` 格式 | | `Invalid YAML Override format` (无效 YAML 覆写格式) | 「覆写设置」覆写模块 | [YAML] 段不是有效的 Hash 结构 | 检查 YAML 缩进和格式 | | `Parse YAML Override failed` (YAML 覆写解析失败) | 「覆写设置」覆写模块 | [YAML] 段 Ruby 解析异常 | 逐行检查 YAML 语法 | | `Config File Overwrite Failed` (配置文件覆写失败) | 「覆写设置」覆写模块 | 覆写应用整体失败 | 检查所有覆写设置的语法 | | `DOWNLOAD FILE failed` (文件下载失败) | 「覆写设置」覆写模块 | 覆写模块 DOWNLOAD_FILE 下载失败 | 检查下载 URL 和网络连通性 | ### 七、流媒体解锁错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Streaming Unlock Could not Work Because of Router-Self Proxy Disabled` (流媒体解锁失效:本机代理关闭) | 「运行状态」看门狗 | 路由器自代理关闭导致流媒体解锁无法工作 | 「插件设置→流量控制」开启本机代理 | | `Something Wrong While Testing` (流媒体测试失败) | 「插件设置→流媒体增强」 | 流媒体测试脚本执行失败 | 「运行状态」确认核心运行中;「插件设置→流媒体增强」检查策略组配置 | ### 八、LuCI Web 界面错误 | 错误提示 | 问题位置 | 原因 | 排查方法 | |----------|---------|------|----------| | `Switch Faild` (切换失败) | 「运行状态」快捷设置 | API 不可达或核心未运行 | 「运行状态」确认核心状态;刷新页面后重试 | | `Config file does not exist` (配置文件不存在) | 「配置管理」 | 配置文件路径无效 | 「配置管理」检查文件名;确认文件存在于配置列表中 | | `File size exceeds 10MB limit` (文件超过 10MB 限制) | 「配置管理」上传 | 上传文件超过 10MB | 减小文件或拆分上传 | | `Cannot delete the last remaining dashboard` (无法删除最后一个仪表盘) | 「运行状态」仪表盘切换 | 只剩一个仪表盘时不允许删除 | 「运行状态」先下载新的仪表盘再删除旧的 | | `Failed to generate age key` (生成 Age 密钥失败) | 「配置订阅」Age 密钥 | 核心不支持 age keygen | 「版本更新」检查核心版本;手动生成 age 密钥 | | `Failed to calculate public key` (计算公钥失败) | 「配置订阅」Age 密钥 | 密钥格式无效 | 验证 age 密钥格式(应以 `AGE-SECRET-KEY-` 开头) | | `Bad address specified!` (地址无效) | 「运行状态」连接诊断 | 输入地址为空或无效 | 输入有效的主机名或 IP 地址 | | `OpenClash Start Failed: {msg}` (OpenClash 启动失败) | 「运行状态」 | 核心日志中出现 fatal/error 级别日志 | 查看完整错误消息;「插件设置 → 调试日志」生成调试日志 | | `Access Denied` (无法访问) / `Access Timed Out` (连接超时) | 「运行状态」IP 检测 | 网络连接问题 | 检查路由器网络连接 | ### 九、YAML 配置处理错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Load File Failed` (加载文件失败) | 「配置管理」配置加载 | Ruby 无法加载配置文件 | 确认配置文件存在且权限正确 | | `Set Custom DNS Failed` (自定义 DNS 设置失败) | 「覆写设置→DNS」 | DNS 覆写处理失败 | 检查「覆写设置→DNS」中的 DNS 服务器配置 | | `Set Fake-IP-Filter Failed` (Fake-IP-Filter 设置失败) | 「覆写设置→DNS」 | Fake-IP 过滤器配置异常 | 「覆写设置→DNS」检查 Fake-IP-Filter 文件和模式 | | `Set Hosts Rules Failed` (Hosts 规则设置失败) | 「覆写设置→DNS」 | 自定义 Hosts 格式错误 | 「覆写设置→DNS」检查 hosts 文件每行格式 | | `Set Custom Rules Failed` (自定义规则设置失败) | 「覆写设置→规则」 | 自定义规则注入异常 | 「覆写设置→规则」检查规则文件语法 | | `Skiped The Custom Rule Because Group & Proxy Not Found` (规则跳过:策略组/代理不存在) | 「覆写设置→规则」 | 规则引用了不存在的策略组/代理 | 「覆写设置→规则」检查规则中 MATCH/Proxy/策略组名称是否存在 | | `Set BT/P2P DIRECT Rules Failed` (BT/P2P 直连规则设置失败) | 「覆写设置→规则」 | BT 直连规则注入失败 | 「覆写设置→规则」关闭再重新开启「仅代理命中规则流量 (Rule Match Proxy Mode)」选项 | | `proxy-groups Get Failed` (策略组获取失败) | 「配置管理」策略组 | 配置中策略组解析异常 | 「配置管理」页面 Edit 检查 proxy-groups 段 | ### 十、Ruby YAML 模块错误 | 错误关键字 | 问题位置 | 原因 | 排查方法 | |-----------|---------|------|----------| | `Fix short-id values type failed` (short-id 类型修复失败) | 「配置管理」YAML 处理 | YAML 中 `short-id` 字段值类型修复时 Psych 解析异常 | 「配置管理」Edit 检查配置中 `short-id` 字段的值格式 | | `YAML overwrite failed:【key: ...】` (YAML 覆写失败) | 「覆写设置」覆写模块 | 覆写模块 YAML 合并时发生异常 | 「覆写设置」检查 `[YAML]` 段的语法和操作符使用 | | `YAML overwrite failed:【(match value) => ...】` (YAML 条件覆写匹配失败) | 「覆写设置」覆写模块 | 批量条件更新的 where 匹配逻辑异常 | 「覆写设置」检查 `key*` 操作符的 where 条件格式和正则 | | `YAML overwrite failed:【(batch update) => ...】` (YAML 批量更新失败) | 「覆写设置」覆写模块 | 批量条件更新执行时异常 | 「覆写设置」检查 `key*` 操作符的 set 子句语法 | | `Write file failed` (写文件失败) | 「配置管理」YAML 写入 | YAML 写入文件时 I/O 异常 | 检查磁盘空间和文件权限 | | `Decrypt attempt failed` (解密尝试失败) | 「配置订阅」Age 解密 | Age 加密文件解密失败 | 「配置订阅」检查 age 密钥是否正确;验证加密文件完整性 | | `Decrypted content empty or still encrypted` (解密后为空或仍加密) | 「配置订阅」Age 解密 | Age 解密后内容为空或仍为加密格式 | 「配置订阅」确认 age 密钥与加密时使用的密钥匹配 | | `Encrypt attempt failed` (加密尝试失败) | 「配置订阅」Age 加密 | Age 加密写入时失败 | 「配置订阅」检查 age 公钥格式;验证核心年龄功能 | | `Encrypted file: decryption failed` (加密文件解密失败) | 「配置订阅」Age 解密 | 所有 age 密钥尝试均解密失败 | 「配置订阅」检查所有订阅的 age 密钥;可能密钥不匹配 | ### 十一、Mihomo 内核配置解析错误(`level=fatal` / `level=error`) > 以下为 Mihomo 内核在**加载/解析 YAML 配置文件**时产生的错误。`level=fatal` 会导致核心进程退出。 > 日志查看:LuCI「运行日志」页面或「运行状态」页面(若启动失败会显示 `OpenClash Start Failed`)。 `Parse config error` 的具体子类型及修复方法: | 错误详情 | 配置段 | 修复方法 | |---------|--------|----------| | `proxy : missing type` | `proxies` | 在「配置管理」Edit 中给第 N 个代理节点添加 `type:` 字段(如 `ss`, `vmess`, `trojan` 等) | | `proxy : unsupport proxy type: ` | `proxies` | 代理类型名称拼写错误或不支持,检查 `type:` 值是否在 Mihomo 支持列表中 | | `proxy is the duplicate name` | `proxies` | 两个代理节点同名,在「配置管理」Edit 中修改其中一个的名称 | | `proxy group : missing name` | `proxy-groups` | 第 N 个策略组缺少 `name:` 字段,Edit 中补充 | | `: unsupported type` | `proxy-groups` | 策略组 `type:` 值无效,改为 `select`, `url-test`, `fallback`, `load-balance` 或 `smart` | | `loop is detected in ProxyGroup` | `proxy-groups` | 策略组之间存在循环引用(A 引用 B,B 又引用 A),打破循环链 | | `: use or proxies missing` | `proxy-groups` | 策略组没有配置 `proxies:` 或 `use:`,至少添加一个 | | `'' not found` | `proxy-groups` | 策略组引用了不存在的代理节点或 provider 名称,检查拼写 | | `can not defined a provider called 'default'` | `proxy-providers` | provider 使用了保留名 `default`,改用其他名称 | | `unsupport vehicle type: ` | `proxy-providers` / `rule-providers` | provider 的 `type:` 值无效,应为 `file`, `http` 或 `inline` | | `file must have a payload field` | `rule-providers` | 规则集文件缺少 `payload:` 字段,检查文件内容格式 | | `rules[] [] error: format invalid` | `rules` | 第 N 条规则格式错误,检查规则语法:`TYPE,payload,target,no-resolve` | | `rules[] [] error: proxy [] not found` | `rules` | 规则目标引用了不存在的策略组/代理名称 | | `rules[] [] error: rule set [] not found` | `rules` | 规则使用了 `RULE-SET,` 但未在 `rule-providers` 中定义该名称 | | `sub-rule error: circular references` | `sub-rules` | 子规则之间形成循环引用链,打破循环 | | `decrypt config error` | 全局 | Age 加密的配置文件解密失败,在「配置订阅」中检查 age 密钥 | | `configuration file ... is empty` | 全局 | 配置文件为空,在「配置管理」中检查配置是否正常下载 | | `[Smart] Invalid policy-priority rule: must be in 'pattern:factor' format` | `smart` 策略组 | 「覆写设置→智能设置」中 `smart_policy_priority` 格式错误,改为 `名称:系数` | | `DNS [addr] config with invalid ecs` | `dns` | DNS 服务器的 ECS 配置格式无效,「覆写设置→DNS」检查 DNS 服务器设置 | | `[Smart] Model.bin invalid, remove and download` | Smart 模型 | 「覆写设置→智能设置」点击手动更新模型按钮重新下载 | | `[CacheFile] remove invalid cache file error` | 运行缓存 | 「运行状态」停止 OpenClash,手动删除 `/etc/openclash/cache.db` 后重启 | > **通用排查**: 在「配置管理」页面点击 **Download Run** 下载经脚本处理后的运行时配置,对比原始订阅检查 `yml_change.sh` 和覆写模块生成的 YAML 是否正确。 ### 十二、DNS 泄露排查 > **核心验证方法**:在客户端执行 `nslookup www.google.com`,应返回:① DNS 服务器为 OpenWrt 路由器 IP;② 解析结果为 Fake-IP 范围地址(`198.18.x.x`)。若返回真实 IP 或上游 DNS 非路由器,说明 DNS 解析链路异常。正确链路应为:`设备 → Dnsmasq(53端口) → OpenClash(7874端口)`。 | 错误关键字 | 问题位置 | 原因 | 排查方法 | 来源 | |-----------|---------|------|----------|------| | DNS 泄露(ipleak / `ipleak.net` 检测到国内 DNS) | 「覆写设置→DNS」 | Redir-Host/Fake-IP 下 nameserver 和 fallback 并发请求,国内 DNS 结果可能被优先采纳 | ① Meta 内核建议**放弃 fallback**,仅用 `nameserver-policy` 做 DNS 分流(国内域名→国内 DNS,国外域名→国外 DNS);② 境外 DNS 地址后加 `#PROXY` 强制走代理(如 `https://1.1.1.1/dns-query#PROXY`);③ 删除原配置 YAML 的 `dns:` 段,仅通过「覆写设置→DNS」管理 DNS 配置避免冲突;④ 将 `proxy-server-nameserver` 设为国内 DNS 避免代理节点域名解析走境外 | [#3843](https://github.com/vernesong/OpenClash/issues/3843) | | `nameserver-policy` 未生效,DNS 仍走 nameserver | 「覆写设置→DNS」 | OpenClash 的「覆写设置→DNS」选项会与订阅配置的 `dns:` 段合并,可能导致预期外的 DNS 行为 | ① 在「覆写设置→DNS」启用「自定义 DNS 设置 (Custom DNS Setting)」后重新配置所有 DNS 规则;② 在「运行日志」中开启 Debug 等级观察实际 DNS 查询路径;③ 确认 `default-nameserver` 组的 DNS 服务器开启了「节点域名解析」选项 | 同上 | | DNS 泄露(开启 IPv6 后出现) | 「覆写设置→DNS」+「IPv6 设置」 | 运营商下发的 IPv6 DNS 绕过了 OpenClash 的 DNS 劫持,直接响应客户端请求("抢答") | ① 在 LuCI 的「网络→DHCP/DNS→高级设置」中取消 `过滤 IPv6 AAAA 记录`;② 在 LAN 接口 DHCP 服务器 IPv6 设置中**取消「本地 IPv6 DNS 服务器」**,强制设备使用路由器 IPv4 地址进行 DNS 解析;③ DHCPv6 服务设为已禁用,RA 设为服务器模式。原理:DNS 请求走 IPv4 通道,流量走 IPv6 通道——IPv4 DNS 同样可以查询 AAAA 记录返回 IPv6 地址 | — | | 旁路由环境下 DNS 泄露 | 「运行状态」 | 旁路由设备未正确指定上游 DNS 为 OpenWrt IP(尤其是 IPv6 DNS 留空) | ① 旁路由设备必须**手动指定 IPv4 DNS 为 OpenWrt 路由器 IP**;② **IPv6 DNS 必须留空**;③ 若使用 DHCP 分配,确保 DHCP 服务器不下发 IPv6 DNS 地址 | — | ### 十三、版本更新与下载失败 | 错误关键字 | 问题位置 | 原因 | 排查方法 | 来源 | |-----------|---------|------|----------|------| | `/tmp/openclash_last_version` 下载失败 | 「运行日志」/ 启动流程 | ① curl SSL 证书验证失败(`BADCERT_CN_MISMATCH` / `self signed certificate`);② GitHub Raw 域名被 DNS 污染或不可达;③ curl 超时(`Operation timed out`);④ 缺少 `libmbedtls` 库 | ①「覆写设置→常规」设置 **Github 地址修改 (github_address_mod)** 为 CDN(推荐 `https://fastly.jsdelivr.net/` 或 `https://testingcf.jsdelivr.net/`);②「系统→软件包」确认 `ca-bundle` 已安装;③ Fake-IP 模式在「覆写设置→DNS」的 fake-ip-filter 中排除 `raw.githubusercontent.com`;④ 修改 `/usr/share/openclash/openclash_core.sh` 中 curl 的超时参数 `-m 60` 改为 `-m 300`;⑤ 终端执行 `opkg install libmbedtls` 修复 curl 库依赖 | [#2791](https://github.com/vernesong/OpenClash/issues/2791) | | **Update Core** (更新内核) 点击后重启失败 | 「运行状态」页面 | v0.47.052 重启流程中 stop→start 间隔不足,旧核心进程未完全退出即启动新核心,触发「内核启动失败」 | ① 更新到 v0.47.054+(已在 Developer 分支修复);② 临时解决:编辑 `/etc/init.d/openclash`,在 restart 函数的 stop 和 start 之间加 `sleep 5`;③ 如更新后仍失败,检查内存是否不足(小型设备建议增加 swap) | [#4969](https://github.com/vernesong/OpenClash/issues/4969) | | 升级后依赖检查异常,无法启动 | 「运行日志」启动流程 | 更新后 `check_mod()` 或依赖检测逻辑误报 | ①「插件设置→调试日志」生成调试日志检查依赖段;②「系统→软件包」确认 `kmod-nft-tproxy`/`kmod-ipt-tproxy` 已安装;③ 切换 Dev 分支获取最新修复;④ 重装 `luci-app-openclash` | [#4807](https://github.com/vernesong/OpenClash/issues/4807) | | v0.47.052/055 无法开机自启 | 「运行状态」启动流程 | 启动时序竞争条件,procd respawn 在某些固件上触发过快 | ① 更新到最新 Dev 版本;②「插件设置→模式设置」设置 `delay_start` (启动延迟) 30-60 秒;③ 确保路由器有足够内存供启动时使用 | [#4973](https://github.com/vernesong/OpenClash/issues/4973) | ### 十四、功能异常类 | 错误关键字 | 问题位置 | 原因 | 排查方法 | 来源 | |-----------|---------|------|----------|------| | **向日葵/AnyDesk 等远程软件无法连接** | 局域网客户端 | 远程软件域名/QUIC 流量被代理或阻断 | ①「覆写设置→规则」添加直连规则:`DOMAIN-SUFFIX,oray.com,DIRECT`、`DOMAIN-SUFFIX,sunlogin.net,DIRECT` 等;② 确认 sniffer `skip-domain` 已包含 `oray.com` 和 `sunlogin.net`(默认已含);③ 尝试关闭「插件设置→流量控制」的 `disable_udp_quic` (禁用 QUIC) | [#3229](https://github.com/vernesong/OpenClash/issues/3229) | | **小米摄像机/智能家居外网无法访问** | 局域网 IoT 设备 | IoT 设备流量被代理导致 NAT 穿透失败 | ①「插件设置→黑白名单」添加摄像机 IP 到「不走代理的局域网设备 IP (LAN Bypassed Host List)」列表;② 确认 sniffer `skip-domain` 包含 `Mijia Cloud`(默认已含);③「覆写设置→规则」添加 IoT 域名直连规则:`DOMAIN-SUFFIX,xiaomi.com,DIRECT` | [#2431](https://github.com/vernesong/OpenClash/issues/2431) | | **绕过中国大陆IP (China IP Route) 功能突然失效** | 升级后 / 「运行状态」 | 版本升级后 `china_ip_route` 的 nftables/ipset 重建失败或 chnroute 列表未更新 | ①「插件设置→大陆白名单订阅」手动更新一次大陆 IP 列表;②「运行状态」页面 Area Bypass 先切到关闭再切回「绕过中国大陆 (Bypass Mainland China)」重新触发;③ 终端执行 `nft list set inet fw4 china_ip_route | head` 检查 nft set 是否存在且非空 | [#4031](https://github.com/vernesong/OpenClash/issues/4031) | | **自定义防火墙规则(开发者选项)不生效** | 「插件设置→开发者设置」 | 编辑后未重启或脚本语法错误 | ① 修改 `openclash_custom_firewall_rules.sh` 后需**重启 OpenClash**(不是重载防火墙);② 用 `bash -n` 检查脚本语法;③「插件设置→调试日志」生成调试日志检查是否成功执行(日志中含自定义脚本内容) | [#4005](https://github.com/vernesong/OpenClash/issues/4005) | | **DDNS 服务(如 DDNS-GO)工作异常** | 路由器 DDNS 插件 | DDNS 服务商 API 域名被错误分配 Fake-IP,导致 IP 检测失败 | ① 将 DDNS 服务商的 API 域名加入「覆写设置→DNS」的 Fake-IP-Filter 中(填入域名使其返回真实 IP);② 常见需排除的域名如 `ddns.oray.com`、`api.cloudflare.com` 等,具体根据所用服务商填写 | — | | **Cloudflare Tunnel (Cloudflared) 连接不稳定** | 路由器/内网设备 | Cloudflared 默认使用 QUIC 连接,而海外 QUIC 流量默认被 OpenClash 阻断 | ① 规则中已指定 Cloudflare Tunnel 相关域名直连;② 在 Cloudflared 启动参数中显式指定 `--protocol http2` 强制使用 HTTP/2(Docker 版:`command: [tunnel, --no-autoupdate, --protocol, http2, run, --token, ${CF_TOKEN}]`) | — | | **BT/PT 下载流量进入内核** | 下载设备 | 下载设备流量未正确分流 | ① 若下载设备为独立设备(如 NAS),在「覆写设置→规则→自定义规则」中添加 `SRC-IP-CIDR,192.168.1.x/32,DIRECT`;② 若同时启用了 IPv6,还需添加 IPv6 后缀规则 `SRC-IP-SUFFIX,::a1b2:c3d4,DIRECT`(后缀由 EUI-64 生成,可在设备上查看);③ 非独立设备可设置「非标端口」策略组直连来规避 80/443 以外的下载流量 | — | | **直连网站/APP/小程序打不开** | 局域网客户端 | 小众域名未被 geosite:cn 收录,被误判为非直连走代理 | ① 临时方案:将「漏网之鱼」策略组设为直连;② 永久方案:在「覆写设置→规则→自定义规则」中为对应域名添加 `DOMAIN-SUFFIX,xxx.com,DIRECT` 规则;③ 观察 zashboard 中命中策略组确认分流是否正确 | — | | **开启 IPv6 后某些直连访问卡顿** | 局域网客户端 | IPv6 DNS 抢答或运营商 IPv6 DNS 不稳定导致解析异常 | ① 禁用「覆写设置→DNS」的「追加上游 DNS」,改为在 NameServer 中手动添加 DoH 服务器(如 AliDNS);② 确保 LAN 口未下发 IPv6 DNS 地址 | — | | **非直连站点打不开且内核日志无记录** | 「运行状态」 | WAN 接口名称填写错误或 DNS 重定向未关闭 | ①「插件设置→流量控制」清空 WAN 接口名称;② 确认「网络→DHCP/DNS」中 DNS 重定向功能已关闭;③ 两者均正确时,检查 OpenWrt 中是否有其他劫持 53 端口或修改 Dnsmasq 的插件 | — | | **Hysteria / Hysteria2 / TUIC 节点连接失败、断流、握手超时** | 内核日志 `level=error` | ① Linux 内核 ≥6.6 的 quic-go GSO 兼容性问题(最常见);② Hysteria 协议对 `server`/`auth`/`tls`/`password` 字段配置敏感 | ① **优先尝试**:「插件设置→模式设置」开启**「禁用 quic-go GSO (Disable QUIC Go GSO)」**后重启 OpenClash;② 确认 YAML 中 `type: hysteria` 或 `type: hysteria2` 拼写正确、端口号正确;③ 检查节点的 `auth`/`password` 及 TLS 证书配置是否完整 | — | | **开启「绕过中国大陆 IP」后 Google Play 商店无法下载/更新** | 客户端(Android 设备) | `services.googleapis.cn` 等 Google 域名被国内 DNS 解析到中国大陆 IP(`220.181.x.x`),被 `china_ip_route` 规则匹配后走直连;但 Google 中国服务器禁止境外 IP(代理节点)访问,导致死循环 | **从 DNS 和规则两方面同时入手**:

**① DNS 层面** — 在「覆写设置→DNS→自定义 DNS 设置」中配置 `nameserver-policy` 强制 Google 域名走境外 DNS 解析,写入 YAML 的 `dns.nameserver-policy` 段:
```yaml
dns:
nameserver-policy:
'+.services.googleapis.cn': 'https://dns.google/dns-query'
'+.googleapis.cn': 'https://dns.google/dns-query'
'+.xn--ngstr-lra8j.com': 'https://dns.google/dns-query'
```
也可用 `8.8.8.8` 或 `1.1.1.1` 替代 `https://dns.google/dns-query`。效果:域名解析到 Google 境外 IP(如 `142.250.x.x`),而非国内 `220.181.x.x`。

**② 规则层面** — 在「覆写设置→规则→自定义规则」中添加,写入 YAML 的 `rules` 段:
```yaml
rules:
- DOMAIN-SUFFIX,services.googleapis.cn,Proxy
- DOMAIN-SUFFIX,googleapis.cn,Proxy
- DOMAIN-SUFFIX,xn--ngstr-lra8j.com,Proxy
```
其中 `Proxy` 替换为你的代理策略组名。更彻底的方式:`GEOSITE,google,Proxy` 将全部 Google 流量走代理。

**验证**:终端执行 `dig services.googleapis.cn @127.0.0.1 -p 7874` 应返回境外 IP;在 zashboard 连接日志中确认域名命中代理规则。 | [#5074](https://github.com/vernesong/OpenClash/issues/5074) | ### 十五、运行时状态异常 | 错误关键字 | 问题位置 | 原因 | 排查方法 | 来源 | |-----------|---------|------|----------|------| | **节点正常,突然无法访问外网** | 「运行状态」一切正常但客户端无网络 | DNS 劫持失效(dnsmasq 被其他插件修改)、防火墙规则乱序、TUN 路由表丢失 | ①「运行状态」确认核心和 DNS 端口正常;② 在「运行日志」中检查最近的错误;③「运行状态」点击「Reload Firewall (重置防火墙)」重建规则;④ 检查是否同时运行其他代理/DNS 插件(如 AdGuard Home、PassWall、SSR-Plus 等),OpenClash 不能与这些插件共存 | [#3516](https://github.com/vernesong/OpenClash/issues/3516) | | **防火墙 DNS 劫持规则不停被还原** | 「运行日志」反复出现防火墙重载记录 | 看门狗检测到规则异常后自动重载,形成循环(v0.46.001-beta 已知问题) | ① 更新到最新版本(已在后续版本修复);② 临时关闭看门狗自动修复(编辑 `openclash_watchdog.sh` 注释掉防火墙重载部分);③ 检查是否有其他程序在修改防火墙规则(如 Docker、UPnP 服务) | [#3765](https://github.com/vernesong/OpenClash/issues/3765) | ### 十六、旁路由 / 特定设备异常 | 错误关键字 | 问题位置 | 原因 | 排查方法 | 来源 | |-----------|---------|------|----------|------| | 旁路由 R2S 等 ARM 设备 iPhone 待机耗电严重 | 局域网 | 代理模式下 ARP 代理或 TUN 模式的 keepalive 导致 iPhone 频繁被唤醒 | ① 尝试切换为 Fake-IP 模式;② 关闭「仅允许内网 (Only Intranet Allowed)」以外的 WAN 口访问;③ 主路由 DHCP 下发的网关和 DNS 指向旁路由 IP | [#2614](https://github.com/vernesong/OpenClash/issues/2614) | | 在 Fake-IP 模式下无法使用 UU 加速器等游戏加速软件 | 「运行状态」 | 游戏加速器需要真实 DNS 解析来优化连接,Fake-IP 返回虚拟 IP 导致失效 | ① 在「覆写设置→DNS」的 fake-ip-filter 中添加加速器相关域名(如 `+.leigod.com`、`+.vivox.com`);② 将加速器所在设备的 IP 加入「不走代理的局域网设备 IP (LAN Bypassed Host List)」 | [#1751](https://github.com/vernesong/OpenClash/issues/1751) | --- # 第一部分:运行状态页面 (Overviews / client) > LuCI 路径: `服务` → `OpenClash` → `运行状态` > 数据来源: 前端 JS 同时请求多个后端端点:`/status` (运行状态、仪表盘设置)、`/toolbar_show` (流量统计)、`/update` (版本信息)、`/oc_settings` (快捷设置)、`/rule_mode` (代理模式)、`/config_file_list` (配置文件列表) 等。版本信息通过 `/update` 端点 (action_update) 返回,非 `/status` 端点。`/status` 仅返回运行状态布尔值、仪表盘可用性和 core_type,不包含版本号。 ## 1.1 核心控制卡片 | 元素 | 功能 | 后端操作 | |------|------|----------| | **启动/停止开关** | 切换核心运行状态 | 调用 `action_oc_action` → `/etc/init.d/openclash start/stop` | | **重启按钮** | 重启核心 | 调用 `/etc/init.d/openclash restart` | | **覆写模块按钮** | 在运行状态页弹出覆写编辑器(与菜单「服务→OpenClash→覆写设置」独立) | 调用 `editOverwrite()` → 在运行状态页弹出覆写编辑模态框 | | **插件/核心版本** | 显示当前版本号 | 核心版本: 执行 `/etc/openclash/core/clash_meta -v` 解析输出; 插件版本: 读取 opkg/apk 包数据库; 远程最新: 读取 `/tmp/clash_last_version`。前端通过 `/update` 端点 (action_update) 获取,非 `/status` 端点 | | **主题切换** | Light(太阳)/Dark(月亮)/Auto(自动) 三档切换 | 前端 CSS 变量 + localStorage | | **公告横幅** | 滚动显示项目公告 (24h 缓存) | `/announcement` 端点 | | **社交链接** | Wiki / Tutorials / Star / Telegram / Sponsor / Mihomo 图标 | 外部链接 `window.open()` | | **开发者头像** | 13 位贡献者头像网格 (悬停显示名称) | 来自 GitHub 头像 URL | ## 1.2 运行模式卡片 (Running Mode) | 模式 | UCI `en_mode` 值 | 说明 | |------|-----------------|------| | **Compat** (兼容) | `redir-host` | Redir-Host 模式,使用 iptables redirect 转发流量 | | **TUN 模式** | `redir-host-tun` / `fake-ip-tun` | 使用 TUN 虚拟网卡接管所有流量 | | **Mix** (混合) | `redir-host-mix` / `fake-ip-mix` | TUN + Redirect 混合,TCP 走 system 栈、UDP 走 gvisor 栈 | > 切换触发: `action_switch_run_mode` → 修改 UCI `en_mode`,若运行中则自动重启 ## 1.3 代理模式卡片 (Proxy Mode) | 模式 | Mihomo `mode` 值 | 效果 | |------|-----------------|------| | **Rule** (策略代理) | `rule` | 按 YAML 中 `rules:` 规则集合分流 | | **Global** (全局代理) | `global` | 所有流量走 GLOBAL 策略组所选代理 | | **Direct** (全局直连) | `direct` | 所有流量直连,不经过任何代理 | > 切换触发: `action_switch_rule_mode` → PATCH Mihomo API `/configs` 的 `mode` 字段,同时更新 UCI `proxy_mode` ## 1.4 快捷设置网格 | 设置项 | 功能 | UCI 选项 | 触发函数 | |--------|------|----------|----------| | **Area Bypass** (地区绕行) | 切换中国 IP/海外绕行 | `china_ip_route` (0/1/2) | `action_switch_oc_setting` → 修改 UCI + 重启 | | **Sniffer** (域名嗅探) | 是否启用 Mihomo 域名嗅探 | `enable_meta_sniffer` | `action_switch_oc_setting` → 动态修改运行时 YAML `sniffer.enable` | | **DNS Proxy** (DNS尊重规则) | DNS 查询是否遵守路由规则 | `enable_respect_rules` | `action_switch_oc_setting` → 动态修改 YAML `dns.respect-rules` | | **Stream Unlock** (流媒体解锁) | 一键启用流媒体解锁 | `stream_auto_select` | `action_switch_oc_setting` → 设置 `stream_auto_select=1` 及 Netflix/Disney/HBO 默认参数 | ## 1.5 配置文件卡片 | 操作 | 功能 | 后端路由 | |------|------|----------| | **配置文件选择器** | 下拉切换当前使用的 YAML 配置 | `action_switch_config` → 更新 `config_path` + 自动重启 | | **SwiTch** (切换) | 切换到选中的配置 | 同上 | | **更新配置** | 重新下载订阅并更新 | `action_update_config` → 调用 `openclash.sh` | | **Edit** (编辑) | 在线编辑 YAML 配置文件 | 弹出 `config_edit` 模态框 (基于 CodeMirror,支持原始/运行时视图切换、合并视图对比、覆写卡片栏) | | **编辑订阅** | 修改该配置的订阅参数 | 跳转到 `config-subscribe-edit` | | **上传** | 上传新的 YAML 配置文件 | 弹出 `config_upload` 模态框 (支持文件上传 + 订阅链接两个标签页) | | **刷新订阅按钮** | 手动刷新当前配置的订阅信息 | `/sub_info_get` 端点 | | **指定 URL 按钮** | 设置订阅信息查询 URL | `/set_subinfo_url` 端点 | | **订阅进度条** | 显示订阅流量使用情况 (已用/总量/百分比) | `/sub_info_get` 自动轮询 | ## 1.6 控制面板卡片 显示当前 Dashboard 访问地址及 Secret 密码。对应 UCI: - `cn_port` — API 端口 (默认 9090),对应 Mihomo `external-controller` - `dashboard_password` — API 密钥,对应 Mihomo `secret` - `dashboard_forward_domain` / `dashboard_forward_port` / `dashboard_forward_ssl` — 公网访问设置 - 提供 **复制 IP** 和 **复制密钥** 按钮 ## 1.7 混合代理卡片 显示 SOCKS5/HTTP 代理地址,可复制或生成 PAC 文件: - `mixed_port` (默认 7893), `http_port` (7890), `socks_port` (7891) - 用户认证: `authentication` TypedSection 中的 `username`/`password`,对应 Mihomo `authentication` 配置 - 提供 **复制代理地址**、**复制认证信息**、**生成 PAC 配置** 按钮 ## 1.8 仪表盘入口 (Control Panel) 4 种可选仪表盘:**Dashboard** (Yacd)、**Yacd**、**Metacubexd**、**Zashboard** - 对应 Mihomo `external-ui` 配置 - 切换触发: `action_switch_dashboard` → `openclash_download_dashboard.sh` - 默认仪表盘: UCI `default_dashboard` ## 1.9 快捷操作按钮 (Quick Action) | 操作 | 功能 | 后端 | |------|------|------| | **Close Connect** (关闭链接) | 断开所有代理连接 | `openclash_history_get.sh 'close_all_conection'` | | **Reload Firewall** (重置防火墙) | 重新应用 iptables/nftables 规则 | `/etc/init.d/openclash reload 'manual'` | | **清空 DNS 缓存** | 刷新 Fake-IP 和 DNS 缓存 | POST `/cache/fakeip/flush` + `/cache/dns/flush` | | **Check Update** (检查更新) | 同时更新插件 + 核心 + 订阅 + GEO | `openclash_update.sh 'one_key_update'` | ## 1.10 统计信息 页面底部显示 8 项实时统计指标,通过 WebSocket 和 XHR 轮询更新: | 指标 | 说明 | |------|------| | 上行速率 | 当前上传速率 | | 下行速率 | 当前下载速率 | | 上行总量 | 累计上传流量 | | 下行总量 | 累计下载流量 | | 连接数 | 当前活动连接数 | | 内存 | 核心内存占用 | | CPU | 核心 CPU 占用 | | 平均负载 | 系统平均负载 | ## 1.11 IP 检测页 (IP Address / 访问检查) **IP 地址部分 (IP Address)**: - 并行查询 4 个 IP 源:UpaiYun、IPIP.NET、IP.SB、IPIFY,每个显示 IP 地址 + 地理信息 - 隐私切换按钮(眼睛图标):点击后用 `***.***.***.***` 隐藏所有 IP 显示(状态持久化到 localStorage) **访问检测部分 (Access Check)**: - 两种检测模式:路由器模式(后端 XHR 代理检测)和浏览器模式(前端 fetch 直接检测),通过模式切换图标切换 - 4 个网站可达性检测:**Baidu Search** (百度搜索)、**NetEase Music** (网易云音乐)、GitHub、YouTube,各显示 HTTP 状态码和加载延迟(ms) - 刷新按钮:重新执行所有 IP 查询和 HTTP 检测 **轮询间隔**: HTTP 检测 5-20 秒,IP 检测 15-40 秒。 ## 1.12 oixCloud 面板 (oixCloud) 仅在设置了 `oix_token` 时显示,展示 oixCloud 订阅服务信息: - **Logo + 标语**(随机变化) - **公告横幅**(60 秒后自动消失) - **计划信息**:计划类型、到期时间、账户余额、推广余额、积分 - **流量统计**:今日已用、计划已用、剩余流量、总流量 - **签到按钮**:每日签到获取流量 - **底部链接**:"Powered by oixcloud.com" > 登录入口:在「插件设置 → oixCloud」标签页中通过 Login Account 按钮登录。 --- # 第二部分:插件设置页面 (Plugin Settings / settings) > UCI Section: `openclash` (anonymous section) > 所有选项通过 `uci set openclash.@openclash[0].