Repository navigation
Replies: 4 comments 2 replies
|
你这个报错我看得很熟,因为链路就在
const literalFamily = isIP(unbracketed)
const resolved = literalFamily === 0
? await raceWithSignal(resolver(unbracketed, { all: true, order: 'verbatim' }), signal)
: [{ address: unbracketed, family: literalFamily }]
if (!isPublicIpAddress(entry.address)) {
throw new WebError(`URL hostname "${hostname}" resolves to a non-public IP address`, 'WEB_BLOCKED_URL')
}所以在 TUN + fake-ip 下, 这是 SSRF 防护和"走代理"之间的设计冲突:防护问的是"这个域名解析到哪里",而带代理时真正决定连到哪里的是代理。本机解析结果是 fake-ip,不代表目标在内网。 改法我认为只有一个方向是安全的:当存在显式代理配置时,把目的地址的判定交给代理——即不再用本机 顺带提醒:如果按上面的方向改, |
|
I traced this end to end against
const route = proxyRouteFor(url)
if (route.proxied && !isNonPublicIpLiteral(url.hostname)) {
return await publicHttpNetwork.requestVia(route.dispatcher, url, headers, signal)
}
const addresses = await this.resolveAddresses(url.hostname, signal) // local DNS happens only hereA proxied hop never resolves locally — the proxy performs the origin's DNS. So seeing local resolution, plus if (policy === undefined || dispatcher === undefined) return DIRECT_ROUTEThe policy logic itself is fine; the question is whether the install ran in the process that performed the fetch. For
Every link holds, so on a genuinely rc.2 build this should have tunnelled. Version skew is therefore the leading explanation, and it is cheap to rule out: could you post the output of One thing makes this hard to diagnose from the outside, and it is worth fixing regardless of the cause. The policy's own diagnostics — invalid value, SOCKS scheme, unsupported protocol — are reported once, to stderr at boot ( Two details worth knowing while this is open. |
|
Following this thread up: the diagnostic gap I described above is now a package, so the next person who hits this can see which link failed instead of inferring it. https://github.com/argszero/dsh-web-fetch-proxy-doctor It observes a failed
To be clear about what it is: this is a diagnostic, not a fix for the report above. On |
|
你说得对,我上一条的机制说错了,收紧一句:代理分支根本不做本地解析,所以"防护先于代理触发"这个框架不成立。 我核了 const route = proxyRouteFor(url)
if (route.proxied && !isNonPublicIpLiteral(url.hostname)) {
return await publicHttpNetwork.requestVia(route.dispatcher, url, headers, signal)
}
const addresses = await this.resolveAddresses(url.hostname, signal)
那就只剩 export function proxyRouteFor(url: URL): ProxyRoute {
const policy = active
const dispatcher = installed
if (policy === undefined || dispatcher === undefined) return DIRECT_ROUTE
所以我上一条建议的"存在代理时把域名判定交给代理"——代码已经是这么做的,我的建议等于让现状再实现一遍。真正的诊断方向应该反过来:去看那个进程里 install 有没有跑,而不是看 SSRF 防护。可以加的诊断点也就一个: 你后面那条 doctor 插件正好补的就是这个静默点,方向对。 |
Uh oh!
There was an error while loading. Please reload this page.
环境背景:
本机在公司内网,Clash Verge(mihomo 内核)开启 TUN 模式并启用 fake-ip(域名被解析到保留网段
198.18.x.x)。应用程序必须经过 Clash 代理才能正常访问公网。现象:
在
dsh web中让 Agent 执行web_fetch https://api-docs.deepseek.com,稳定报错:同时 Clash 连接界面里没有出现来自该 node 进程的任何连接记录。
对照实验:
同一进程、同一代理配置下,让 Agent 执行
curl https://api-docs.deepseek.com(同样是 Agent 发起),Clash 连接界面立即出现该域名的连接记录,且能正常访问。复现步骤:
dsh web:web_fetch https://api-docs.deepseek.com。问题反馈:
web_fetch没有走代理(Clash 无连接记录),而是仍做本地 DNS 解析并因解析到198.18.x.x报错。web_fetch在配置代理后确实走代理,避免被本机 fake-ip 解析结果误拦。All reactions