web-search-proxy: A lightweight search & fetch proxy
以下内容包含AIGC
我工作的地方有一批外包同事,开发环境是内网虚拟机,完全隔离外网。出于数据安全考虑(防止代码库和文档外发),这个设定本身没什么问题,但带来了一个很现实的摩擦:他们没法上网。
查个库的最新版本,翻翻 changelog,确认一个 API 的用法——这些事情需要在外网电脑查完,再手动粘贴到虚拟机里。每天重复,很烦。
之前我在内网搭了一套 new-api(LLM Gateway) 负载均衡了 2 个 MiniMax 的 max订阅,帮他们接通了 Claude Code,模型接入的问题算是解决了。但 Claude Code 依然没有联网能力,遇到事实类问题还是一样抓瞎。它能写代码,但它不知道:某个库半年前发布了 breaking change、某个场景有哪些正在快速崛起的开源解决方案。
所以我花了半天时间,用 Claude Code 写了给 Claude Code 用的联网工具。
web-search-proxy 是什么
一个轻量的 HTTP 代理服务,部署在有外网访问权限的机器上,暴露两个接口:
POST /search:通过 DuckDuckGo 搜索,返回标题、链接、摘要POST /fetch:抓取任意 URL 的页面内容,支持纯文本或 Markdown 输出
Claude Code 通过 Skill 机制调用这两个接口,就能在内网环境里完成搜索和页面读取,不需要浏览器,不需要复杂配置。
架构很简单:内网虚拟机里的 Claude Code → 内网的 web-search-proxy 实例 → 外网。代理服务本身部署在能访问外网的节点上就行。
从信息安全的角度看,这个设计中,信息的流向本身就是单向的:服务只接收内网发来的 POST 请求,触发向外网发出 GET 请求并把响应转发回来。请求入参有长度上限,Agent 没有办法把大段内网内容夹带出去。数据流向始终是“外网 → 内网”,不存在反向泄露的通道。这样既符合数据安全的管控要求,又解决了内网 Agent 获取不到互联网信息的痛点。
半天能干什么
开发过程基本是这样:我用小作文描述需求,Sonnet 做计划、写代码,我看结果、发现问题、调整方向,循环。
用的是从 AWS Kiro 逆向出来的 Sonnet 中转(我穷,不想原价给反华急先锋 Anthropic 送美金,更不能接受被 A÷ 随意封号的风险),我认为 Sonnet 模型在普通编程任务上已经足够胜任了,我无法想象把 Fable 5 当成豆包聊生活琐事的人是多么有钱。整个项目 TypeScript + Express,两个核心接口加上域名黑名单、可选的 /logs 查询审计日志接口、GitHub Actions 自动构建推送 DockerHub,半天跑通。
/fetch 默认返回的是原始 HTML,我增加了 sanitize 和 markdown 两个参数——前者把 HTML 剥成纯文本,后者转成 Markdown —— 更适合人类和Agent阅读的技术文档。还有 BLOCKED_DOMAINS 的设计,支持通配符和 [bare](拦截所有裸主机名,防止 proxy 服务被滥用去 fetch redis、192.168.x.x 这类内网服务),Sonnet 改了一版就对了。
说这些不是要炫耀什么开发速度。我想说的是:AI 多轮 Rush 的过程中,人需要在环路里。Sonnet 可以很快地给你一个能跑的版本,但“能跑”和“对”之间,还差一个有判断力的人。这个判断力不是编码能力,是你知道自己要什么、知道哪里不对、知道怎么描述清楚。
AGI 还没来。在它到来之前,Agent 完成长程任务仍然依赖人的观察和反馈才能有效闭环。人的价值不在于能不能比 AI 写得更快,而在于品位、判断力,还有知道什么时候该拉一把方向盘。
怎么用
最快的方式,一行 Docker:
1 | docker run -d -p 3030:3030 --restart unless-stopped icheerme/web-search-proxy:latest |
或者 docker-compose:
1 | services: |
然后装 Skill:把仓库里 skill/SKILL.md 的 YOUR_PROXY_HOST 替换成你的服务地址,在 Claude Code 里 /add-skill 加载。之后 Claude 会自动识别什么时候需要搜索,自己调用,不用你手动指定。
几个有用的环境变量:
| 变量 | 说明 |
|---|---|
BLOCKED_DOMAINS |
fetch 黑名单,支持精确匹配、*.internal 通配符、[bare] 拦截裸主机名 |
ADMIN_PASSWORD |
设置后启用 GET /logs?password=xxx,查最近 50 条记录 |
技术栈:Node.js 20 · TypeScript · Express · Turndown。
后续计划
目前搜索后端是 DuckDuckGo,免费但深度有限。接下来打算加一个 POST /tavily 接口,接入 Tavily Search API,支持配置多个 API Key 轮询——这样就能把这个服务变成一个中心化的 Tavily 搜索节点,内网所有 Agent 共用,做“最大化搜索”时不用担心单 Key 的速率限制。
项目在这里:github.com/icheer/web-search-proxy
如果你也在做类似的内网 AI 基础设施,希望能有点参考价值。