[求助] Go 项目中大量第三方 SDK 需要访问外部域名,但甲方要求全部走内网代理,有哪些优雅处理方式?

112 天前
 shannn

各位大佬,

我们在给甲方部署一个 Go 项目 时,遇到一个关于外部网络访问受限的问题,想请教有没有通用、优雅的解决方案。

✅ 背景信息:

1. 项目使用 Go 编写,集成了多个第三方 SDK ,比如:
	•	阿里云 SDK ( Aliyun )
	•	AWS SDK
	•	Let’s Encrypt (自动申请证书)
	•	其他 RESTful API 客户端
2. 这些 SDK 会直接访问公网域名,比如:
	•	https://alidns.aliyuncs.com
	•	https://acme-v02.api.letsencrypt.org
	•	https://sts.amazonaws.com

🚧 甲方网络要求:

1.	甲方有严格的出口策略,服务器不能直接访问公网。
2.	所有流量必须经过其提供的 内网网关,并统一审计。
3.	我们需要先提交所需的“外部域名列表”,然后他们会提供 一一对应的代理地址,比如:
	•	https://alidns.aliyuncs.com → http://alidns.my.local
	•	https://acme-v02.api.letsencrypt.org → http://acme.my.local
4.	服务实际运行时,必须通过这些映射地址访问外部服务。

⛰️我们面临的核心挑战是:

1.	Go 项目中大量使用第三方 SDK ,这些 SDK 会直接访问外部域名。
2.	我们不想直接修改 SDK 的代码,不想维护一堆 fork 。
3.	域名数量多、来源复杂,难以完全靠手工收集和配置。

🤔 当前尝试:

1.	部分 SDK (如 AWS )提供了自定义 Endpoint 的设置方式,我们可以通过代码配置替换了对应的 URL 。
2.	其他 SDK (如 tencentcloud go sdk 、Aliyun Go SDK ):
	•	有的不支持 endpoint 替换,或者是在计算签名要包含 host 参数
	•	有的需要深度改代码或 fork
3.	考虑过系统层或中间层方案,比如:
	•	hosts 劫持(不适用于 HTTPS + SNI )
	•	本地 HTTP 代理 + 域名重写(如 mitmproxy 、squid )
	•	iptables + redsocks 实现透明代理(过于复杂)
	•	Go 中自定义 http.Transport + DialContext:受限于 SDK 能否复用全局 http.Client

❓想请教大家:

1.	有没有通用方式拦截 Go 项目中 SDK 发起的 HTTPS 请求,并做统一的域名映射或代理转发?
	•	比如运行时 Hook 、网络中间层、标准库配置等。
2.	是否有成熟的内网网关代理解决方案(支持 hostname 映射、HTTPS 转发)适合这种场景?
3.	有没有人做过类似政企、金融、军工、政府等受限内网部署,你们是怎么处理第三方 SDK 出口问题的?

非常感谢大家宝贵的经验和建议!🙏 如有成熟工具、框架、示例代码或经验文章,也欢迎推荐。

6695 次点击
所在节点    Go 编程语言
72 条回复
lysShub
112 天前
替换 net.DefaultResolver
nuk
112 天前
可以不改 SDK ,直接改官方库,然后 map 一下地址
crackidz
112 天前
环境变量就行,你们内部接口不需要走代理的就自己单独初始一个不用代理的 client
zljklang
112 天前
写 hosts 文件嘛
realpg
112 天前
全局代理, 代理处分流
用 ss 那种带分流的代理软件...
Augix
112 天前
透明代理又不能 HTTPS 转 HTTP ,你这只能 DNS 劫持+自签证书+Nginx 转发到上游 HTTP 地址
gam2046
112 天前
怕是有点难办

https://alidns.aliyuncs.com → http://alidns.my.local

这个过程中,你有测试过,具体网关是什么行为嘛,https 降级成 http ,那基本不可能是简单的一个 http/socks 代理那种形式了,因此其他回答里提到的 https_proxy 这种环境变量是白扯的。

同样的 DNS 劫持无法实现,因为客户端发起请求时,需要降级到 http ,这一点单纯 DNS 劫持做不到。

相对而言,fork ,改代码可能结果与工期更为可控。

非要整花活的话,运行程序的本机,DNS 设置为自己或其他可控的机器,先让原始请求到自己的代理,然后自签证书返回给客户端,你这边的代理,再根据外部域名列表,请求到.my.local 的地址。

相当于你自己需要写个代理,先把 https 降级。

而且这种情况下,还得原始的 SDK 内没有采用一些证书固定的方案,否则也降级不了。
IndexOutOfBounds
112 天前
问题表达形式不错呀
lasuar
112 天前
第三方不支持替换 url 的 sdk 能有多少?改代码可能还是最靠谱的。
ksedz
112 天前
隔离环境最好用的还是 go mod vendor
ksedz
112 天前
看错了,忽略吧
shannn
112 天前
@lasuar 不想改腾讯云的 go sdk 了
kekxv
112 天前
看起来只有几个 sdk ,最合适的方法,应该是直接 fork 他们的仓库,然后加上参数或者配置之后,给他们提交 pr ,这样就不需要自己单独维护一套代码
ansuanboy
112 天前
可以使用双层代理,
向甲方申请一个代理出口到你们公司自己的公网代理入口
然后自己写代码创建一个 http 代理服务器,代理所有 SDK 请求包并自定义封装一层。
再通过甲方的代理出口代理到你们自己的公网代理服务入口,解包发出实际请求,再将响应内容返回
整个过程只涉及四层网络结构,http\https 都可以穿透
chf007
112 天前
一般第三方 sdk ,域名这种变量,一般都会暴露配置出来的啊,你们用的时候都不配置一下的么?或初始化时配置,或通过环境变量配置,只要把这些集中管理一下就行了。
mooyo
112 天前
你这个咋看着像 fake ip ,和 fake ip 实现类似吧?
flat
112 天前
如果甲方允许在代理服务器上部署代理,那就很简单,直接用代理就行。但是如果不行,就只能看原本的 sdk 支持不支持域名替换了。前面那些内网 dns 的啥的,都不行,你配置解析到那个代理服务器有啥用,那个机器上又没有类似 nginx 的东西监听你原本的这个域名。只监听了人家给你提供的新域名。
flat
112 天前
@flat

一般的 http 库都支持这几个环境变量,配置下就能用,但是只是走代理
export HTTP_PROXY=http://127.0.0.1:8888
export HTTPS_PROXY=http://127.0.0.1:8888
export NO_PROXY=localhost,127.0.0.1
zxp
112 天前
在公网上部署 1 个接口服务,设置成通过 a.com 域名访问,把需要访问外部域名的第三方 SDK 全部剥离出来集成到接口服务上,内网开放 1 个可以访问接口服务的代理域名,内网应用只需要通过代理域名访问这个接口服务就行了。
shannn
112 天前
@chf007

我们这边不考虑走 SDK 层配置 endpoint 的方案了,主要原因有两个:
1. 不同 SDK 支持程度不一,有的可以配,有的只能改源码;
2. 后续维护成本高,一旦 SDK 升级或接入新的 SDK ,就得重新梳理和适配,影响开发效率。

我们更倾向于类似代理转发方案,这样:
• 能集中发现和整理 SDK 中访问的外部域名;
• 和甲方的域名映射策略配合更灵活;
• 后续不需要动业务代码,部署也更可控。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1134781

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX