Files
yexuejc a9ebb5e2cd
CI / Build / Vet / Test (push) Canceled after 0s
chore: 开源化准备(LICENSE/CI/测试/文档)+ 全量中文注释
首个提交。webproxy 是部署在服务器上的 Web 正向代理:打开网页输入任意
URL,由服务器代为请求目标站点,经 HTML/CSS 重写、静态资源代理、
重定向/Cookie/表单处理后回填浏览器,核心场景是经服务器访问其所在
内网的客户网站。

- 开源件:MIT LICENSE、根级 SECURITY.md、CONTRIBUTING.md、
  CHANGELOG.md、Makefile、CI(gofmt/vet/build/test)
- 安全止损:.gitignore 排除 debug.log(含内网 IP)/二进制/调试散文件/
  本地 config.json;config.example.json 默认 blacklist,不关 SSRF
- module 路径规范化为 github.com/yexuejc/webproxy
- 测试:新增 proxy_test.go(URL 编解码/子域解析/SSRF 分类/Origin 改写);
  tests/cookietest 手工 E2E 程序加 build tag 并拆为独立子包,不污染
  go test ./...
- 注释:全部 Go 源码按函数作用/场景/入参/出参 + 分支 + 变量标准补齐
- 清理:删除旧"浏览器持有 Cookie"方案弃用代码(rewriteSetCookie/
  stripDomainSecure/reCookieDomain/reCookieSecure);会话 Cookie 改由
  服务端按 origin 的 jar 持有,绕开跨站 iframe 的 SameSite 扣发
2026-10-20 21:33:28 +08:00

4.7 KiB
Raw Permalink Blame History

安全说明

1. 威胁模型(按危害排序)

# 威胁 说明 现状
1 开放代理被滥用 无鉴权暴露公网 → 被扫到当成免费代理/跳板,耗流量、引溯源投诉 未防护(鉴权未实现,见第 3 节加固项)
2 SSRF(服务端请求伪造) 攻击者借你的服务器打内网/云元数据 169.254.169.254/127.0.0.1 管理口/file:// 等 默认防护,三档可配(见第 2 节)
3 同源 XSS 被代理页面与 UI 同源(iframe 无 sandbox),恶意站点 JS 可触达父窗口/cookie(sid 已 HttpOnly) 部分防护,缓解项见第 3 节
4 会话 grow sessions 无 TTL,长期运行缓慢增长 已知,重启即清(规划 TTL 清理)
5 上游证书风险 目标 HTTPS 证书默认校验;insecure_skip_verify 打开后中间人可解密内网流量 由配置项控制,公网目标不建议开

2. 已实现的防护

防护 实现
协议白/黑名单 默认仅 http/https;blacklist 档禁用 file/gopher/ftp/ftps/dict/tftp/ldap/sftp
IP 分类拦截 默认拦 127/8、::1(loopback)、169.254/16(link-local,含云元数据);可选 block_private、block_reserved
附加黑名单 denied_ips CIDR 列表,逐 IP 命中即拒
白名单模式 whitelist 档仅放行 allowed_ips / allowed_domains(精确+子域)
DNS 重绑定防护 先 LookupIP 校验、再用校验过的 IP pin 连接,消除 TOCTOU 窗口
自引用防护 目标 Host == 代理 Host 直接 400,防 /p/ 咬尾
会话隔离 sid Cookie(HttpOnly,Path=/)→ 独立 CookieJar,多使用者登录态不串
响应头清洗 剥离上游 X-Frame-Options/CSP/COOP(iframe 嵌入与 JS 注入所需)、Content-Length(重写后长度必变)、Location(统一改写)
TLS 加固 上游 TLS 最低 1.2

SSRF 分档与场景配置的完整说明见 CONFIG.md 第 2 节。

3. 上线前加固清单

3.1 入口鉴权(最高优先级)

当前没有任何登录机制。公网暴露前,任选其一:

  1. 反代 Basic Auth(最省事):nginx/Traefik/Caddy 前置,认证通过才转发到 8765;
  2. VPN/零信任:只通过 Tailscale/WireGuard/企业 VPN 访问,代理只听内网 listen;
  3. 后续版本计划内置账号登录(当前未实现,别依赖)。

反代示例(nginx,同时解决 HTTPS 和 Basic Auth):

server {
  listen 443 ssl;
  server_name proxy.example.com;
  ssl_certificate     /etc/nginx/cert.pem;
  ssl_certificate_key /etc/nginx/key.pem;

  auth_basic "webproxy";
  auth_basic_user_file /etc/nginx/.htpasswd;

  location / {
    proxy_pass http://127.0.0.1:8765;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;    # 如后续启用 WS
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 300s;
  }
}

3.2 SSRF 策略收紧建议

上线形态 建议
专用服务器、网络平面干净 mode: "off" 可接受;仍建议 denied_ips 写上同机管理网段
共享服务器/VM mode: "blacklist"(默认)+ block_private: true,私网按站点放开 denied_ips 的补集用白名单补
公网多人可用 mode: "whitelist" + 入口鉴权,双闸门

3.3 同源 XSS 缓解(可选,有取舍)

给 UI 的 iframe 加 sandbox="allow-scripts allow-forms allow-popups"(不加 allow-same-origin)可让被代理页面跑在独立源,父窗口不再可触达。代价:沙箱源不带 sid Cookie,登录态隔离会失效,需等服务端改为按 iframe 参数/子域传会话再启用。单机自用、且不访问不可信站点时可维持现状。

3.4 运维面

  • 只暴露必要端口,安全组做源 IP 限制更佳;
  • docker logs/systemd journal 定期巡检 403 记录(403 的突增=有人在扫你的代理);
  • 升级/改配置前备份 config.json,保留可回退版本。

4. 残留风险如实说明

  1. 无鉴权 = 无访问控制:在补上 3.1 之前,任何能访问到端口的人都能使用该代理,请勿直接公网裸奔;
  2. 黑名单是"默认放行"语义:blacklist 档放行未列出的一切目标,它防的是"经典被打点",不是"最小权限";要最小权限用 whitelist;
  3. 同源面:见 3.3,未启用 sandbox 前,请只把不可信站点的问题留在"知情"层面;
  4. 性能/资源:默认纯 Go 转发开销极低,无已知拒绝服务放大点(无全量缓存),但 HTML/CSS 走内存,超大页面有内存压力(规划流式)。