解决开启代理后无法访问公司内网:自定义 DNS 规则置顶方案
前言
最近在公司办公网络环境下使用代理工具时, 经常会遇到一个非常棘手的问题:开启系统代理后,公司的内网域名(例如内部的 Gitlab、Jira 或 .local 结尾的测试环境)无法解析,或者解析到了错误的公网 IP。
虽然可以在 UI 界面手动修改配置,但每次更新机场订阅,配置就会被覆盖,非常麻烦。网上关于 代理配置的教程很多,但针对 企业内网 DNS 专线解析 且 防覆盖 的方案却很少。
本文将分享一段基于 JavaScript 的预处理脚本,通过重组 nameserver-policy 顺序并强制注入路由规则,完美解决"开代理后内网断连"的问题。
适用读者:使用代理,需要同时访问外网和公司内网(Intranet)的开发者。
问题分析
在默认的代理配置中,存在两个导致内网无法访问的"坑":
- DNS 污染与优先级 :代理订阅通常会下发自己的 DNS 规则。如果简单的合并配置,内网 DNS 规则可能会排在后面,或者被通用的规则截获,导致内网域名向
8.8.8.8等公网 DNS 查询,自然无法解析。 - Fake-IP 问题 :代理默认开启 Fake-IP 模式。如果内网服务验证请求来源 IP,或者通过 IP 直连,Fake-IP 返回的
198.18.x.x虚拟地址会导致连接超时。 - 规则覆盖 :代理订阅更新会重置
rules,我们需要一种动态的方法,每次更新时自动把内网直连规则插队到 第一行。
解决方案:JavaScript 预处理脚本
先把你们公司的DNS服务器找到并记录下来,后面需要写到脚本中。
DNS可以看你连接公司网络后的属性,一般会自动分配,你记录下来就行,比如我们公司的是'10.168.236.20', '10.168.236.30' (如图):
代理支持使用 JavaScript 对下载的配置文件进行"后处理"(Post-processing)。请将以下代码复制到 代理订阅页面的 Script (脚本) 全局扩展配置中并保存(如图)。

javascript
// Define main function (script entry)
// function main(config, profileName) {
// return config;
// }
// Script: 强制内网 DNS 规则置顶 + 保留订阅规则
function main(config) {
// --- 1. 基础检查与开启 DNS ---
if (!config.dns) config.dns = {};
config.dns.enable = true;
// --- 2. 【核心修改】重组 nameserver-policy 顺序 ---
// A. 先把你公司的规则定义好, 每个域名添加一行就行,要换成你们公司自己的xxx.com域名,你可以全局替换掉。
// '10.168.236.20', '10.168.236.30' 要换成你们公司自己的DNS地址,你可以全局替换掉。
// 最后一行不要删(10.in-addr.arpa这行)。
const myCompanyPolicy = {
'+.company-gitlab.com': ['10.168.236.20', '10.168.236.30'],
'+.company-wiki.com': ['10.168.236.20', '10.168.236.30'],
'+.local': ['10.168.236.20', '10.168.236.30'],
'10.in-addr.arpa': ['10.168.236.20', '10.168.236.30']
};
// B. 获取代理原有的规则(如果没有则为空对象)
const airportPolicy = config.dns['nameserver-policy'] || {};
// C. 【关键步骤】新建一个对象:先展开你的,再展开机场的
// 这样在最终生成的 YAML 中,你的规则会排在最上面
config.dns['nameserver-policy'] = {
...myCompanyPolicy,
...airportPolicy
};
// --- 3. 注入 Fake-IP 过滤 (防止内网域名被返回假 IP) ---
if (!config.dns['fake-ip-filter']) {
config.dns['fake-ip-filter'] = [];
}
config.dns['fake-ip-filter'].push(
'+.company-gitlab.com',
'+.company-wiki.com',
'+.local'
);
// --- 4. 路由规则插队 (确保 rules 在最前面) ---
const myDirectRules = [
// 域名强制直连
"DOMAIN-SUFFIX,company-gitlab.com,DIRECT",
"DOMAIN-SUFFIX,company-wiki.com,DIRECT",
// IP 强制直连
"IP-CIDR,10.0.0.0/8,DIRECT",
"IP-CIDR,172.16.0.0/12,DIRECT",
"IP-CIDR,192.168.0.0/16,DIRECT"
];
if (!config.rules) config.rules = [];
// 插入到头部
config.rules.unshift(...myDirectRules);
return config;
}
核心逻辑解析
这段脚本之所以有效,主要依赖于以下三个关键点:
1. DNS 策略的"置顶"逻辑
在代理的 YAML 配置文件中,nameserver-policy 定义了特定域名使用特定的 DNS 服务器进行解析。
javascript
config.dns['nameserver-policy'] = {
...myCompanyPolicy,
...airportPolicy
};
这里使用了 ES6 的对象展开运算符 。我们将 myCompanyPolicy 放在前面。虽然 JSON 对象本质无序,但在生成 YAML 配置文件时,代理 往往会依据写入顺序或特定度进行匹配。将内网规则显式地放在对象合并的头部,可以直观地确保内网解析策略不被遗漏。
2. Fake-IP Filter 的必要性
很多公司内网服务(如 AD 域控、旧版 OA)不识别 代理 生成的 198.18.0.1 这种 Fake-IP。
通过 config.dns['fake-ip-filter'].push(...),我们强制让 .local 或公司域名返回真实的 局域网 IP (如 10.168.x.x),这是内网互通的基础。
3. 路由规则的 unshift 插队
这是最容易被忽视的一点。普通的追加规则(push)会将规则放到列表末尾。
如果机场订阅的规则列表中包含类似 MATCH,Proxy 或者 GEOIP,CN,DIRECT 的规则排在前面,你的内网规则可能根本轮不到执行。
使用 config.rules.unshift(...myDirectRules) 可以确保我们的直连规则永远位于列表的 第 1 行,拥有最高优先级。
总结与建议
通过这段简单的 JavaScript 脚本,我们实现了一个"既要又要"的完美网络环境:
- 内网办公:走公司 DNS 和直连,稳定且不断连。
- 全自动:无论订阅怎么更新,脚本都会自动执行,无需人工干预。
建议大家在配置时,先在终端使用 nslookup internal.domain 测试一下 DNS 解析是否正确指向了内网 IP。
如果你在配置 或网络分流过程中遇到其他奇奇怪怪的问题,欢迎在评论区留言探讨!
注 :不同的 UI 客户端脚本注入方式略有不同,但
main函数逻辑是通用的。