# UA-Mask 使用教程 面向 OpenWrt 用户的一站式配置与排错指南,帮助你从 0 到 1 搭好 UA-Mask 并与 OpenClash 等共存。 ## 目录 - [快速开始(5 分钟)](#快速开始-5-分钟) - [界面字段详解(与 LuCI 一一对应)](#界面字段详解与-luci-一一对应) - [与 OpenClash 共存](#与-openclash-共存) - [运行统计详解(页面“状态”卡片)](#运行统计详解页面状态卡片) - [流量卸载(基于 ipset/nfset)](#流量卸载基于-ipsetnfset) - [防检测策略与推荐组合](#防检测策略与推荐组合) - [匹配规则编写示例](#匹配规则编写示例) - [验证与排错(必看)](#验证与排错必看) - [抓包定位 UA 泄露(tcpdump + Wireshark)](#抓包定位-ua-泄露tcpdump--wireshark) - [工作模式(性能预设)](#工作模式性能预设) - [安装与编译](#安装与编译) - [附录:UCI 配置参考(/etc/config/UAmask)](#附录uci-配置参考etcconfiguAmask) - [关于更名与项目理念(摘要)](#关于更名与项目理念摘要) - [项目发展历史](#项目演进心路历程) ## 快速开始(5 分钟) 1) 安装(任选其一) - 预编译包:到 Releases 下载与你设备架构匹配的 `.ipk`,然后在路由器上安装。 - iptables 用户若要启用“流量卸载”,请先安装 ipset。 ```sh opkg update opkg install UAmask_*.ipk # 仅 iptables 用户且需要 set 绕过时 opkg install ipset ``` 2) 打开 Web 界面:系统 -> 服务 -> UA-Mask,勾选“启用”,先别急着保存。 3) 常规设置(General) - 性能预设:默认 Medium(大多设备够用)。 - User-Agent 标识(ua):填一个“通用浏览器 UA”,例如: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119 Safari/537.36 - 匹配规则:保留“基于关键词(推荐)”。关键词默认已覆盖常见系统(Windows/Android/iPhone…)。 4) 网络与防火墙(Network) - 监听端口:12032(默认)。 - 监听接口:br-lan(默认)。 - 代理主机流量:如果你的路由“本机”也需要被修改 UA,才开启。与 OpenClash 共存时建议遵循下文“完美分流方案”。 - 绕过目标端口:默认 22 443。 - 若你“安全优先”,建议移除 443(原因见下文“安全优先方案”)。 - 启用流量卸载(可选,高性能):iptables 用户务必先装 ipset。 5) 保存并应用。运行状态显示“运行中”。 6) 验证 - 从 LAN 内的一台设备访问[ua检验](http://ua.233996.xyz/),应看到 UA 已变为你设定的值。 提示:UA-Mask 仅在“明文 HTTP”中可见效果;HTTPS 流量不会修改 UA(TLS 加密后 UA 不可见)。 --- ## 界面字段详解(与 LuCI 一一对应) ### 1. 常规设置(General) - 性能预设(operating_profile) - Low:200 并发,2000 LRU,8K 缓冲,内存占用最低。 - Medium:500 并发,3000 LRU,8K 缓冲,均衡(默认)。 - High:1000 并发,5000 LRU,8K 缓冲,高吞吐。 - 自定义(custom):自行设定缓冲/池/缓存/GOGC。 - I/O 缓冲区大小(buffer_size):每连接读写缓冲,越大吞吐越高但更占内存。默认 8192。 - 工作协程池大小(pool_size):限制最大并发、降低 GC;为 0 则每连接独立协程。 - LRU 缓存大小(cache_size):提升命中率;约每 1000 条 ~300KB RAM。 - GOGC:Go GC 比例,使用协程池时建议保持 100。 - User-Agent 标识(ua):实际替换成的 UA 字符串。 - 匹配规则(match_mode) - 基于关键词:UA 包含任一关键词即整串替换(性能最佳)。 - 基于正则:配合“替换方式”使用(完整替换/部分替换)。 - 修改所有流量:强制全改(一般不必)。 - 关键词列表(keywords):逗号分隔,命中即整串替换。 - 正则表达式(ua_regex):例如 (iPhone|Android|Windows)。 - 替换方式(replace_method):正则命中后“完整替换”或“部分替换”。 - User-Agent 白名单(whitelist):这些 UA 命中后直接放行(逗号分隔)。 ### 2. 网络与防火墙(Network) - 监听端口(port):默认 12032。 - 监听接口(iface):默认 br-lan,可多接口空格分隔。 - 启用流量卸载(enable_firewall_set):创建 ipset/nfset 以“跳过”特定 ip:port,提高性能(见下节“流量卸载”)。 - UA 关键词白名单(Firewall_ua_whitelist):命中这些 UA 关键词的连接,将目标 ip:port 动态加入 set 卸载(典型如 Steam)。 - 绕过非http流量(Firewall_ua_bypass):当识别为“非 HTTP”后,交由决策器评估并暂时卸载该 ip:port,降低负载。 - 匹配时断开连接(Firewall_drop_on_match):命中“UA 关键词白名单”时立即断开,强制新连接走卸载路径,加速生效。 - 代理主机流量(proxy_host):是否也代理路由器自身的流量;为避免与其他代理回环冲突,若不需要可关闭。 - 绕过 GID(bypass_gid):默认 65533,用于豁免自身流量;脚本同时豁免 OpenClash 的 65534,防循环。 - 绕过目标端口(bypass_ports):默认“22 443”。 - 绕过目标 IP(bypass_ips):默认局域网与保留网段。 ### 3. 高级设置(决策器) - 决策器设置(firewall_advanced_settings):开启后可自定义卸载决策逻辑参数。 - 非 HTTP 判定阈值(firewall_nonhttp_threshold):将某 ip:port 判定为“非 HTTP”前需累计的非 HTTP 事件次数(默认 5)。 - 决策延迟时间(秒)(firewall_decision_delay):达到阈值后,延迟多久再做卸载决策,避免误判(默认 60s)。 - 防火墙规则超时(秒)(firewall_timeout):加入 set 的元素超时(默认 28800 秒=8 小时)。 说明: - 决策过程中如出现 HTTP 活动,会触发“HTTP 豁免期”,对该 ip:port 的卸载判定被一票否决并延后,进一步降低误判与 UA 泄露风险。 ### 4. 应用日志(Softlog) - 日志等级(log_level):debug/info/warn/error 等。 - 应用日志路径(log_file):建议放 /tmp,避免刷写闪存。 - 查看/清空日志:页面内置“查看最近 200 行”与“一键清空”。 --- ## 与 OpenClash 共存 UA-Mask 已对 Clash 做了共存优化:即使开启了“代理本机”,也会自动豁免 Clash 的流量(GID 65534),避免循环。 ### 完美分流方案(推荐) - 配置:UA-Mask(代理本机:关闭)+ OpenClash(代理本机:开启,绕过大陆:开启) - 效果:非 22/443 端口的 HTTP 流量先由 UA-Mask 修改 UA,再交给 OpenClash;OpenClash 将国内直连、国外走代理。 - 备注:若关闭 OpenClash 的“绕过大陆”,则所有 HTTP/HTTPS 都会先过 UA-Mask 再过 OpenClash。 ```mermaid graph LR A[LAN 流量] --> B{防火墙规则} B -->|22 443 端口| C{OpenClash规则} B -->|其他端口| D[UA-Mask] C -->|国内流量| E[OUTPUT 直连] C -->|需要代理| F[Clash 核心] D --"本机代理开启"--> C{OpenClash规则} ``` ### 最大兼容方案(不推荐) - 配置:UA-Mask(代理本机:关闭)+ OpenClash(代理本机:关闭,绕过大陆:开启) - 效果:OpenClash 仅代理 UA-Mask 绕过的端口(默认 22/443)。 - 缺陷:其他端口(如 80)的流量在被 UA-Mask 修改后全部直连,不走 OpenClash。 ```mermaid graph LR A[LAN 流量] --> B{防火墙规则} B -->|端口 22, 443| C{openclash规则} B -->|非 22, 443 端口| D[UA-Mask] C -->|国内流量| E[OUTPUT 直连] C -->|需要代理| F[Clash 核心] D --> E[OUTPUT 直连] ``` 验证共存: - iptables 机型:确保 UA-Mask 的 PREROUTING 规则在链首(服务重启会 -I 插入到最前)。 ```sh iptables -t nat -nvL PREROUTING --line-numbers | sed -n '1,30p' iptables -t nat -S UAmask_prerouting ``` - nftables 机型: ```sh fw4 print ruleset | grep -n UAmask -n nft list set inet fw4 UAmask_bypass_set 2>/dev/null || true ``` --- ## 运行统计详解(页面“状态”卡片) - 当前连接:实时并发连接数。 - 请求总数:累计 HTTP 请求数。 - 处理速率:RPS((当前总数-上次总数)/刷新间隔)。 - 成功修改:完成 UA 修改的请求数。 - 直接放行:因白名单/不匹配而放行的请求数。 - 规则处理:真正执行关键词/正则匹配(未命中缓存)的请求数。 - 缓存(修改):缓存命中且判定“修改”的次数。 - 缓存(放行):缓存命中且判定“放行”的次数。 - 总缓存率:(缓存(修改)+缓存(放行)) / HTTP 请求数。 --- ## 流量卸载(基于 ipset/nfset) 为降低 CPU 负载、提升高并发性能,引入“流量卸载(set 绕过)”。启用路径:服务 -> UA-Mask -> 网络与防火墙 -> 勾选“启用流量卸载”。 iptables 用户:请先安装 ipset。 包含两种卸载: 1) 绕过非 http 流量(Firewall_ua_bypass) - 原理:识别到某 ip:port 多次出现“非 HTTP”连接后,进入“决策延迟”观察期;若期间无 HTTP 活动,一次性加入 UAmask_bypass_set,超时后自动移除(默认 8 小时,可在“防火墙规则超时(秒)”调整)。 - 安全:若观察期内出现 HTTP 活动,会触发“HTTP 豁免期”,之前的非 HTTP 累积分数被一票否决,避免误判导致 UA 泄露。 - 效果:该 ip:port 的后续新连接被防火墙直接放行,不再进入 UA-Mask 检测,显著减负。 2) UA 关键词白名单(Firewall_ua_whitelist) - 原理:若某连接的 UA 命中你配置的“UA 关键词”,立即把该目标 ip:port 加入 set 卸载。 - 适用:高带宽、长连接但 UA“无敏感标识”的流量(如 Steam 下载)。 - 示例关键词:Valve/Steam, steam, steamworks, 360pcdn, ByteDancePcdn(按需取舍)。 - 可选:匹配时断开连接(Firewall_drop_on_match)。命中后立刻断开现有连接,促使后续连接直接走卸载路径。可能会出现应用端“需重试”的提示,非苛求性能时可不启用。 重要提醒(性能 vs 风险) - 被加入卸载 set 的 ip:port 在超时时间内会“完全绕过 UA-Mask”。这有可能导致“真实 UA 泄露”。请按你的环境权衡使用,尽量结合“非 HTTP 决策器”与谨慎的白名单关键词。 --- ## 防检测策略与推荐组合 方案一:性能优先(大多数环境) - 匹配规则:正则 + 部分替换(兼容性好)。 - 启用流量卸载;同时开启“绕过非 http 流量”和“UA 关键词白名单”(加入 Steam 等关键词)。 方案二:安全优先(严格环境) - 关闭流量卸载与 UA 关键词白名单。 - 检查“绕过目标端口”中移除 443,以防极少数明文 HTTP 走 443 导致 UA 泄露。 --- ## 匹配规则编写示例 - 关键词模式(整串替换) - 例:Windows,Linux,Android,iPhone,Macintosh,iPad,OpenHarmony - 正则模式 - 完整替换:ua_regex = (Windows NT|Android|iPhone|iPad|Macintosh) - 部分替换:把 UA 中的“Android [0-9.]+”替换为“Android 10” - ua_regex: Android [0-9.]+ - 替换方式:部分替换 - 修改所有流量 - 在 HTTPS 上也不会生效(因为 UA 位于明文 HTTP 头部)。 --- ## 验证与排错(必看) 基础检查 - 进程: ```sh pidof UAmask || echo not running ``` - 日志: ```sh logread -e UAmask | tail -n 50 tail -n 200 /tmp/UAmask/UAmask.log 2>/dev/null ``` 防火墙规则 - iptables: ```sh iptables -t nat -S UAmask_prerouting iptables -t nat -S UAmask_output ipset list UAmask_bypass_set 2>/dev/null || true ``` - nftables: ```sh fw4 print ruleset | sed -n '/UAmask_/,+15p' nft list set inet fw4 UAmask_bypass_set 2>/dev/null || true ``` 常见问题 - “HTTPS 看不到效果”:属正常,UA 仅在 HTTP 明文里;用 http://httpbin.org/user-agent 验证。 - “访问变慢/CPU 高”:尽量使用“关键词模式”;或改为 Medium/Low 预设;减少正则复杂度。 - “与 OpenClash 冲突/循环”:按本文“完美分流方案”设置;必要时重启 UA-Mask 使其规则位于更前面;保留绕过 GID 65534。 - “Steam 下载 UA 泄露担忧”:别启用“UA 关键词白名单”或仅在下载时短时启用;或不用 set 卸载。 - “运行统计不更新”:服务需运行一段时间才生成 /tmp/UAmask.stats;先确认进程与日志。 - “启动失败”:确认 /usr/bin/UAmask 存在;若启用流量卸载,iptables 机型需安装 ipset。 - “配置校验失败”:OpenWrt 会从 UCI 生成 `/var/run/UAmask/config.json`,可执行 `/usr/bin/UAmask -check-config -config /var/run/UAmask/config.json` 查看校验结果。 - 查看 Go core 最终生效配置:`/usr/bin/UAmask -dump-effective-config -config /var/run/UAmask/config.json`。该 JSON 是运行时生成文件,请修改 UCI/LuCI,而不是直接编辑它。 --- ### 抓包定位 UA 泄露(tcpdump + Wireshark) 目标:在 WAN 侧抓包并用 Wireshark 检查是否存在“未被 UA-Mask 修改的明文 HTTP 请求”。 1) 确认 WAN 接口名(可能是 pppoe-wan/wan/eth0.2 等) ```sh WAN="$(uci -q get network.wan.device || uci -q get network.wan.ifname || ifstatus wan | jsonfilter -e '@.device')" echo "$WAN" ``` 2) 抓取样本到路由器 /tmp/capture.pcap - 轻量(常见明文 HTTP 端口) ```sh tcpdump -i "$WAN" -s 0 -U -w /tmp/capture.pcap 'tcp port 80 or tcp port 8080 or tcp port 8000' ``` - 全量(30 秒,流量大时慎用) ```sh timeout 30s tcpdump -i "$WAN" -s 0 -U -w /tmp/capture.pcap tcp # 无 timeout 命令时,按 Ctrl+C 结束 ``` 3) 在 LAN 侧复现访问场景,然后停止抓包 4) 将抓包文件拉到本机 - Windows PowerShell(启用 OpenSSH 的情况下) ```powershell scp root@192.168.1.1:/tmp/capture.pcap . ``` - 或使用 WinSCP/pscp.exe 图形或命令行工具 5) Wireshark 分析 UA - 打开 capture.pcap,输入显示过滤器: ``` http.request and http.user_agent ``` - 将 http.user_agent 设置为列:在任意包的“http.user_agent”字段上右键 -> Apply as Column - 若 HTTP 使用的不是 80 端口: - 方式 A:右键该端口的一个 TCP 包 -> Decode As... -> 选择 HTTP - 方式 B:Preferences -> Protocols -> HTTP -> TCP Ports,追加 8080,8000,8880,3128 等 - 判断是否存在“未被替换”的 UA(与 UA-Mask 配置值不一致的、或带有设备真实标识的 UA) 6) 若确认存在 UA 泄露,定位与修复 - 检查是否被加入卸载 set(会直接跳过 UA-Mask): ```sh # iptables 机型(ipset) ipset list UAmask_bypass_set 2>/dev/null | sed -n '1,100p' # nftables 机型 nft list set inet fw4 UAmask_bypass_set 2>/dev/null ``` - 临时移除可疑 ip:port: ```sh # iptables 机型(hash:ip,port) ipset del UAmask_bypass_set , # nftables 机型(ip . port 二元组) nft delete element inet fw4 UAmask_bypass_set { . } ``` - 调整配置后复测: - 关闭“绕过非 http 流量” - 清空或精简“UA 关键词白名单”(避免把高带宽下载目标加到卸载) - 安全优先时,在“绕过目标端口”移除 443 - 确认 UA-Mask 规则优先级在前(见“与 OpenClash 共存/验证共存”命令) - 尽量使用“关键词模式”或“正则+部分替换”提升命中率与兼容性 ## 工作模式(性能预设) - Low:2000 LRU、8K 缓冲,协程池 200 —— 内存低。 - Medium:3000 LRU、8K 缓冲,协程池 500 —— 平衡(默认)。 - High:5000 LRU、8K 缓冲,协程池 1000 —— 高吞吐。 - 自定义:按需设定 cache_size、buffer_size、pool_size、GOGC。 --- ## 安装与编译 ### 预编译包 1. 前往 Releases。 2. 下载匹配架构的 `.ipk`。 3. 在路由器上安装(见“快速开始”)。 ### 源码编译 1. 将本项目克隆到 OpenWrt 源码的 package/luci 目录。 2. 先完整编译过一次固件更稳(make download;并发编译如 make -j8)。 3. 编译本包: ```sh make clean make package/UA-Mask/compile ``` 生成位置:$(rootdir)/bin/packages/$(targetdir)/base/ 下的 UAmask_xxx.ipk 固件内置:menuconfig 中 network/Web Servers/Proxies/UAmask 选中 *。 --- ## 附录:UCI 配置参考(/etc/config/UAmask) 示例(默认值可能随版本略有调整): ```conf config 'UAmask' 'enabled' option enabled '0' config 'UAmask' 'main' option port '12032' option ua 'FFF' option log_level 'info' option iface 'br-lan' option proxy_host '0' option bypass_gid '65533' option bypass_ports '22 443' option bypass_ips '172.16.0.0/12 192.168.0.0/16 127.0.0.0/8 169.254.0.0/16' option ua_regex '(iPhone|iPad|Android|Macintosh|Windows|Linux|Apple|Mac OS X|Mobile)' option whitelist '' option log_file '/tmp/UAmask/UAmask.log' # 运行参数(预设/自定义) # option operating_profile 'Medium|Low|High|custom' # option cache_size '3000' # option buffer_size '8192' # option pool_size '500' # option gogc_value '100' # option match_mode 'keywords|regex|all' # option keywords 'Windows,Linux,Android,iPhone,Macintosh,iPad,OpenHarmony' # option replace_method 'full|partial' # 流量卸载 # option enable_firewall_set '0|1' # option Firewall_ua_whitelist '' # option Firewall_ua_bypass '0|1' # option Firewall_drop_on_match '0|1' # 决策器(高级设置开启后生效) # option firewall_advanced_settings '0|1' # option firewall_nonhttp_threshold '5' # option firewall_decision_delay '60' # option firewall_timeout '28800' ``` --- ## 关于更名与项目理念 - 更名:UA3F-tproxy 演进为 UA-Mask,突出“精简、高性能、专注 UA 修改”。 - 目标:硬路由可用、软路由高吞吐;热路径优化、零拷贝、缓存与池化,兼顾稳定与性能。 我们会持续打磨性能与易用性,让每台路由器都能一键获得更安全、稳定的 UA Mask 能力。 ## 项目演进心路历程 1. **此前方案**:最开始的方案是 `防火墙 -> OpenClash -> SOCKS5 -> UA3F`。这个方案虽然可行,但流量链路过长,导致 CPU 负载轻易达到瓶颈,直到后来萌生了自行实现的想法。 ![最初的思考](./img/before-think.png) ![高昂的 CPU 占用](./img/before-bad.png) 2. **第一次优化**:为了解决性能问题,我们想到绕开 OpenClash,直接通过防火墙将流量转发给 UA-Mask(彼时还叫ua3f-tproxy)。这大大提升了处理效率。 ![性能优化的灵感](./img/after-spark-1.png) 3. **与 OpenClash 共存**:但新问题随之而来——如何与 OpenClash 共存?我们设计了新的方案:在 PREROUTING 链将流量先交给 UA-Mask,处理后再由 OUTPUT 链的 OpenClash 进行分流,并利用“绕过大陆”功能避免不必要的流量进入 Clash 核心。 ![关于共存的思考](./img/after-think-clash.png) ![完美的共存方案](./img/after-spark-clash.png) 4. **引入 ipset/nfset 卸载**:我们发现,超过 90% 的流量(如 Steam 下载)并不需要修改 UA。因此,引入 `ipset/nfset`,将这些高带宽流量动态加入卸载列表,使其直接通过内核转发,不再消耗 UA-Mask 的资源,实现了性能的飞跃。 ![发现高带宽流量的瓶颈](./img/ipset-think.png) ![引入 set 绕过的灵感](./img/ipset-spark.png) ![爱上纯内核转发的性能](./img/ipset-love.png) 5. **最终架构**:结合以上所有优化,形成了当前稳定、高效、兼容性强的最终架构。 ![最终的整体架构](./img/structure-all.png)