Web Proxy 这道关:应用怎么知道自己该走代理
Posted on 二 13 10月 2026 in Tech
| Abstract | Web Proxy 这道关:应用怎么知道自己该走代理 |
|---|---|
| Authors | Walter Fan |
| Category | Tech |
| Version | v1.1 |
| Updated | 2026-10-13 |
| License | CC-BY-NC-ND 4.0 |
大纲
展开看看
- 一句话:Web Proxy 是企业把安全策略和网络出口收口的那道关,应用“无感知”地被代理是设计目标;真正的坑是应用怎么发现自己该走代理。
- 为什么需要代理:安全要求(审计、DLP、恶意域名拦截)和网络限制(出口收口、合规、内外网隔离)两条线,不是性能优化。
- 应用怎么发现代理:三条路径——显式配置(环境变量 / 系统设置)、PAC 脚本、WPAD 自动发现。坑都在这里:curl 认环境变量、浏览器认系统设置、Java 认自己的
-D参数,三套各走各的。 - CONNECT 挡不住 TLS:HTTP 明文走 absolute-form,HTTPS 走
CONNECT隧道,代理默认只搬密文字节。想看内容就得 TLS 拦截(SslBump),代价是全网装自签 CA。 - 代理部署在哪:出口网关、Sidecar、显式转发代理三种位置;开源方案 Squid / Envoy / mitmproxy / tinyproxy 各有各的位置。
- 信令与媒体:信令(HTTP/WebSocket)走代理天经地义;实时媒体(RTP/SRTP)走 HTTP 代理是反模式,该用 TURN。
- 媒体被逼上 443:安全策略只放行 443 时,正道是让 TURN 自己贴着 443(
turns:TURN over TLS),用真 TLS 骗过 DPI。TLS 只覆盖客户端到 TURN 这一跳、只为翻墙不为保密;优先级 UDP > TCP > TLS。还有 TURN/UDP 443、ICE-TCP、WebSocket/SFU、QUIC/WebTransport 几条路。
做协作平台这些年,我见过最多的线上问题分类里,有一类永远排在前面:“在公司网络里连不上,回家就好了。” 排查到最后,十有八九指向同一个东西——公司出口上那台 Web Proxy,以及应用根本不知道自己该走它。
很多人把代理理解成“帮你中转一下流量的服务器”。这个理解不算错,但抓错了重点。企业里的 Web Proxy 不是为了帮你中转,而是为了管住你:所有出网流量从这里过一遍,安全审计、数据防泄漏、恶意域名拦截、合规留痕,全在这一层做。应用“无感知”地被代理,恰恰是它的设计目标。
所以这篇文章的主线只有一条:应用到底怎么知道自己该走代理? 这个问题看着小,却是绝大多数代理相关故障的根因。讲清它,顺带把代理的部署位置、开源选型、信令媒体走代理的注意事项一起收了。
为什么要有这道关:安全要求和网络限制
企业上 Web Proxy,动机就两条线。
安全要求。 公司得知道员工的机器往外发了什么、连了哪些域名。有了统一代理,就能做这几件事:
- 审计留痕:谁在什么时间访问了哪个域名,有日志可查。合规审计(SOC 2、等保)要的就是这个。
- 数据防泄漏(DLP):出站流量里有没有带着客户名单、源代码、密钥往外传。
- 恶意域名拦截:已知的 C2 服务器、钓鱼站、矿池域名,在代理这一层直接拦掉,不用指望每台终端的杀毒软件。
网络限制。 很多公司的内网机器压根没有公网路由——你 ping 8.8.8.8 是不通的。想出网,唯一的路就是走代理。这么设计有几个现实原因:
- 出口收口:全公司一个出口,防火墙规则、带宽管理、NAT 地址都好管。
- 内外网隔离:开发网、办公网、生产网各自独立,跨网访问必须经过代理这道闸。
- 合规边界:金融、医疗这些行业,监管要求出网流量必须经过可审计的网关。
一句话:
代理是企业把“安全策略”和“网络出口”收口到一个点的办法。 它存在的价值不是加速,而是“让所有出网流量都从一个可控的地方过”。
想明白这一点,下面的坑就有了解释——既然代理是强加的、是要“管住你”的,那它当然希望应用无感知地被代理。而“无感知”和“配置正确”之间的那条缝,就是所有故障的来源。
核心问题:应用怎么发现自己该走代理
这是全文的题眼。一台机器上几十个进程,浏览器、curl、git、你写的那个 Python 脚本、JVM 里的服务——它们怎么知道“我这次请求得先发给代理,而不是直连目标”?
答案是:没有统一答案。 操作系统并不会强制所有进程走代理(透明代理除外,后面讲)。绝大多数情况下,是每个应用自己去某个地方查“我该不该走代理”。查的地方不一样,就是 90% 代理故障的根源。
发现代理一共三条路径,从“手动”到“自动”:
| 发现方式 | 谁来配 | 应用从哪读 | 典型翻车点 |
|---|---|---|---|
| 显式配置 | 人 / 运维 | 环境变量、系统网络设置、应用自己的配置 | 各应用读的地方不一样,配了 A 没配 B |
| PAC 脚本 | 运维集中管 | 一个 JavaScript 文件,按 URL 决定走哪个代理 | 脚本逻辑写错、文件拉不下来 |
| WPAD 自动发现 | 几乎不用配 | 通过 DHCP/DNS 猜 PAC 文件位置 | 安全风险大,很多地方已禁用 |
下面一条条拆。
路径一:显式配置——最常见,也最容易配漏
“显式”意思是有人明明白白告诉应用:代理在 http://proxy.corp:8080。但“告诉”这个动作,在不同应用那里是不同的接口:
- 命令行工具(curl、wget、git、pip、npm)认环境变量
HTTP_PROXY/HTTPS_PROXY/NO_PROXY。注意大小写:curl 两种都认,有些程序只认小写。 - 浏览器和桌面应用(Chrome、Edge、Outlook)认操作系统的网络设置。Windows 在“Internet 选项 → 连接 → 局域网设置”,macOS 在“系统设置 → 网络 → 代理”。它们不读环境变量。
- JVM 应用认自己的那套
-Dhttp.proxyHost/-Dhttp.proxyPort系统属性,环境变量和系统设置它都可以不理。 - Go 程序默认读环境变量(
net/http的ProxyFromEnvironment),但也可能被代码里写死。
坑就在这里:你在终端里 export HTTP_PROXY 之后 curl 通了,就以为代理配好了;结果同一台机器上的 Chrome 还是连不上,因为它读的是系统设置,不是你的环境变量。一台机器上同时存在好几套互不相干的代理配置,是常态,不是异常。
NO_PROXY(或系统设置里的“例外列表”)同样重要却常被忽略:内网地址、localhost、127.0.0.1 必须排除掉,否则连本机服务都要绕一圈代理,轻则变慢,重则直接连不上。
路径二:PAC——把“走不走代理”的决策集中到一个脚本
手动给每台机器配代理,运维会疯。PAC(Proxy Auto-Config)的办法是:写一个 JavaScript 文件放在 Web 服务器上,里面有个固定签名的函数:
function FindProxyForURL(url, host) {
// 内网直连,不走代理
if (isInNet(host, "10.0.0.0", "255.0.0.0")) {
return "DIRECT";
}
// 其它一律走公司代理,挂了就直连兜底
return "PROXY proxy.corp:8080; DIRECT";
}
应用每次要发请求,先把 URL 和 host 喂给这个函数,函数返回“DIRECT”(直连)还是“PROXY 某地址”。决策逻辑集中在一个文件里,改一处,全公司生效。客户端那头只需要配一次 PAC 文件的 URL。
PAC 的两个经典坑:一是 FindProxyForURL 每次请求都会被调一遍,里面别写 dnsResolve 这种慢操作,否则每个请求都卡一下;二是 PAC 文件本身得拉得下来——它通常是 HTTP 明文托管的,PAC 服务器一挂,所有依赖它的客户端瞬间集体失联。
路径三:WPAD——“连 PAC 的 URL 都不想配”,但别用
WPAD(Web Proxy Auto-Discovery)更进一步:连 PAC 文件的 URL 都不用人工配,客户端自己去“猜”。猜法有两条:
- DHCP:客户端发 DHCPINFORM 查询,DHCP 服务器通过 option 252 直接把 PAC 文件地址塞回来。
- DNS:客户端拿自己的域名前面拼一个
wpad,去拉http://wpad.<你的域>/wpad.dat。文件名必须是wpad.dat,MIME 类型必须是application/x-ns-proxy-autoconfig,否则有些浏览器不认。
听起来很省事,Windows 默认还开着这个(“自动检测设置”那个勾)。但 WPAD 是个安全重灾区,我的建议是关掉它。 道理很简单:既然客户端是靠“猜”去拉文件,攻击者就能在同一个网络里架个 DHCP/DNS,抢先把一个恶意 PAC 文件喂给你。2016 年 DEF CON 上,Context Information Security 的研究者演示过:恶意 PAC 文件里的 FindProxyForURL 能拿到完整 URL(包括 HTTPS 的路径和参数),再用 dnsResolve 把这些本该被 TLS 保护的 token 泄漏出去——HTTPS 加密没被破解,但被绕过去了。他们当时的原话是“No seriously, turn off WPAD!”
如果确实要用 PAC,正确姿势是:关掉 WPAD 自动发现,显式配一个 PAC 的 URL,并且用 HTTPS 托管。
下面这张图把三条路径和它们的决策顺序串起来:
@startuml
skinparam monochrome false
skinparam shadowing false
skinparam defaultFontName "SansSerif"
start
:应用准备发起一个 HTTP(S) 请求;
if (应用自己配置/环境变量/系统设置\n指定了代理?) then (是)
:按显式配置选择代理;
else (否)
if (配置了 PAC 的 URL?) then (是)
:拉取 PAC 文件;
:执行 FindProxyForURL(url, host);
else (否)
if (开启了 WPAD 自动发现?) then (是)
:DHCP option 252 / DNS wpad.dat\n猜 PAC 位置(有安全风险);
:执行 FindProxyForURL(url, host);
else (否)
:直连目标;
stop
endif
endif
endif
if (结果是 DIRECT?) then (是)
:直连目标;
else (否)
:把请求交给指定的代理;
endif
stop
@enduml

CONNECT 隧道:为什么代理默认看不见你的 HTTPS
搞清楚应用怎么找到代理之后,下一个要命的问题是:代理到底能看见什么?这直接决定了它能不能做审计、DLP,以及信令媒体走代理时会发生什么。
关键分水岭是明文 HTTP 和 HTTPS 的处理方式完全不同:
- 明文 HTTP:客户端把完整 URL(absolute-form,形如
GET http://example.com/path HTTP/1.1)发给代理,代理一眼看全——方法、路径、头、body 全都是明文。审计、缓存、改写都能做。 - HTTPS:客户端先发一个
CONNECT example.com:443请求,代理回200,然后在客户端和目标之间开一条 TCP 隧道。接下来 TLS 握手是客户端和目标服务器直接谈的,代理只负责盲转两边的加密字节。
这条隧道意味着:对 HTTPS 流量,代理默认只能看到“你连了哪个 host、哪个端口、什么时间、传了多少字节”,看不到 URL 路径、cookie、请求体。 认证凭据走 Proxy-Authorization 头给代理,和你发给目标服务器的内容是两回事。
那企业要审计 HTTPS 内容怎么办?只能做 TLS 拦截(也叫 SSL 中间人、SslBump):代理把自己伪装成目标服务器,用自己签的证书和客户端握手,解密、看内容、再用另一条 TLS 连到真正的目标。Squid 的 SslBump、mitmproxy 走的都是这条路。
但 TLS 拦截的代价很大,用之前想清楚:
- 得在所有终端的信任库里装代理的自签 CA 证书,否则浏览器满屏证书告警。
- 证书绑定(certificate pinning)的应用会直接拒绝——移动端 App、很多桌面客户端都做了 pinning,拦截一上来它们就连不上。
- 你等于在企业内部造了一个“合法的中间人”,这个 CA 私钥一旦泄漏,全公司的 HTTPS 都裸奔。
一句话记住:
CONNECT隧道让代理默认是“瞎子”——只知道你连了谁,不知道你说了什么。 想让它“睁眼”,就得全网装自签 CA 做 TLS 拦截,这是一笔安全账,不是技术开关。
代理部署在哪,有哪些开源方案
明白了发现机制和可见性,部署位置的选择就有了依据。常见有三种位置:
| 部署位置 | 长什么样 | 适合场景 |
|---|---|---|
| 出口网关 | 一台(集群)代理守在网络出口,所有出网流量过它 | 企业办公网、合规出口,经典用法 |
| Sidecar / 本地代理 | 每台机器或每个 Pod 旁边跑一个本地代理进程 | 容器环境、给单个应用注入凭据或策略 |
| 显式转发代理 | 应用明确把请求发给某个代理地址 | CI/CD、爬虫、需要换出口 IP 的场景 |
开源方案按定位挑,别一上来就问“哪个最好”,先问“我要它站在哪、做什么”:
- Squid——老牌转发代理,GPL。缓存、访问控制列表(ACL)、SslBump 一应俱全,企业出口网关的默认选项。想做 TLS 拦截审计,它是成熟答案。
- Envoy——云原生时代的主力,L4/L7 全能。既能当反向代理,也支持正向代理和
CONNECT隧道,还有credential_injector这类过滤器帮你注入认证头。跑在 K8s 里做 Sidecar、做出口网关都合适。 - mitmproxy——为“看见和改写 HTTPS”而生的 TLS 拦截代理。它不是用来扛生产流量的,而是调试神器:排查“到底哪一步请求出错了”,拿它当中间人一抓就清楚。
- tinyproxy——极轻量的 HTTP/HTTPS 转发代理。不需要缓存和复杂 ACL、只想要一个能用的转发代理时,它够了。
选型别纠结。出口网关要审计选 Squid,云原生环境选 Envoy,调试抓包选 mitmproxy,要个最小转发选 tinyproxy。 需求对上了,答案基本就定了。
信令走代理天经地义,媒体走 HTTP 代理是反模式
最后说一个做实时音视频才会撞上的坑,也是我想专门留给同行的一段。协作平台里的流量粗分两类:信令和媒体。它们对代理的态度截然相反。
信令(登录、加入会议、收发控制消息)本质就是 HTTP 或 WebSocket,走代理没问题,也应该走:
- WebSocket 的升级握手就是一个普通 HTTP 请求,代理能识别。
- 信令对延迟没那么敏感,偶尔多几十毫秒不影响体验。
- 它天然适配前面那套
CONNECT隧道机制,该审计审计,该留痕留痕。
媒体(RTP/SRTP 承载的音视频流)则完全是另一回事。实时媒体跑在 UDP 上,追求的是低延迟、抗抖动、丢包了宁可丢也不重传。而 HTTP 代理是为 TCP、为可靠传输设计的。把实时媒体硬塞进 HTTP 代理,是反模式,原因很具体:
- 协议不匹配:RTP 是 UDP,HTTP 代理是 TCP 世界的居民。要走代理就得把 UDP 媒体塞进 TCP 隧道,TCP 的重传和队头阻塞会让实时音视频的延迟和卡顿雪上加霜。
- 该用的工具是 TURN,不是 Web Proxy:WebRTC 体系里,穿越 NAT 和防火墙的标准件是 STUN/TURN。TURN 服务器专门为中继媒体设计,支持 UDP 中继,这才是媒体“绕过限制”的正道。
- 走 443 是最后的兜底:确实有网络把 UDP 全堵死、只放行 TCP 443。这种时候媒体只能想办法从 443 挤出去——怎么挤,就是下一节要专门讲的。但这是“保命”,不是“正常方案”。
一句话:
信令是“消息”,适合走代理;媒体是“流”,应该走 TURN。 让媒体走 HTTP 代理,是拿错了工具;真要从 443 出去,也不是走 Web Proxy,而是让 TURN 自己贴着 443。
媒体被逼上 443:TURN over TLS 到底怎么回事
出于安全策略,很多企业网只放行一个出口:TCP 443。UDP 全堵、3478(STUN/TURN 的标准端口)也堵。这时候 WebRTC 的 ICE 候选列表会很惨——host、srflx 全是 UDP,默认的 turn:host:3478 也是 UDP,一个能用的都没有,连通性检查还没开始就全死了。
媒体要活下去,就得从 443 挤出去。但这里有个关键误解要先澄清:媒体走 443,走的不是那台 Web Proxy,而是让 TURN 服务器自己在 443 上监听、并且把流量裹进真正的 TLS 里。 这就是 TURN over TLS(turns: 这个 scheme,来自 RFC 7065)。
为什么偏偏是 TLS,而不是裸 TCP
你可能会问:既然 443 放行,那 TURN 直接走 TCP 443 不就行了,为什么非得套一层 TLS?
因为把守 443 的往往不是个只看端口号的傻防火墙,而是做深度包检测(DPI)的应用感知防火墙。它放行 443 的前提是:这上面跑的得像 HTTPS。你在 443 上发裸的 TURN-over-TCP,它一看“这开头不是 TLS 握手”,照样给你丢了。而 TURN over TLS 发出去的就是一个货真价实的 TLS 握手,DPI 盒子分辨不出它和普通 HTTPS 的区别,于是放行。
一句话:443 这道门认的不是端口,是“长得像不像 HTTPS”。TLS 让 TURN 流量混进 HTTPS 车流里。
一次 TURN over TLS 的完整路径
拆开看,一次走 443 的媒体是这样流动的:
@startuml
skinparam monochrome false
skinparam shadowing false
skinparam defaultFontName "SansSerif"
actor "浏览器/客户端" as C
participant "企业 DPI 防火墙\n(只放行 443)" as FW
participant "TURN 服务器\n(turns:host:443)" as T
participant "对端 / SFU 媒体服务器" as P
C -> FW : TLS 握手 (看起来就是 HTTPS)
FW -> T : 放行——分辨不出和 HTTPS 的区别
C -> T : 在 TLS 隧道里跑 TURN\n(Allocate, 认证)
T --> C : 分配一个 relay 地址
note over C, T : 这一跳:TLS over TCP 443
note over T, P : 这一跳:UDP 中继 (RFC 8656)
C -> T : SRTP 媒体 (已是 DTLS-SRTP)
T -> P : 转发为 UDP
P -> T : 回程 UDP
T -> C : 裹回 TLS 送回
@enduml

有两个容易被忽略的点:
- TLS 只覆盖“客户端到 TURN 服务器”这一跳。 从 TURN 服务器到对端(或你的 SFU)那一跳,RFC 8656 的 allocation 仍然是 UDP 中继。所以路径是“客户端 --TLS/TCP 443--> TURN --UDP--> 对端”。把 TURN 服务器摆在媒体服务器旁边,第二跳就很便宜。
- 这层 TLS 不为保密,只为翻墙。 媒体本身已经是 DTLS-SRTP 加密过的,外面再套一层 TLS 纯粹是为了骗过防火墙。代价是:多一次 TLS 握手、多一层加解密 CPU、以及 TCP 自带的队头阻塞——丢一个段,后面排队的包全得等重传。所以 libwebrtc 给候选打优先级时,UDP > TCP > TLS,TLS 永远排最后,只有别的都不通才轮到它。这个顺序别去改它。
客户端配置通常把几种 transport 都列上,让 ICE 自己从快到慢挑:
const pc = new RTCPeerConnection({
iceServers: [{
urls: [
'turn:turn.example.com:3478?transport=udp', // 首选:最快
'turn:turn.example.com:3478?transport=tcp', // UDP 堵了退到 TCP
'turns:turn.example.com:443?transport=tcp', // 443 只剩 TLS 时兜底
],
username, credential,
}],
});
一个实现上的坑:turns: URL 的证书必须对得上 hostname,浏览器会校验,所以不能用裸 IP、不能用自签证书,否则这条兜底路径直接废掉。
媒体从 443 出去,还有哪些别的方案
TURN over TLS 不是唯一解,按“贴近 443 的程度”排一下,各有取舍:
| 方案 | 怎么走 443 | 优点 | 代价 / 边界 |
|---|---|---|---|
| TURN/UDP on 443 | TURN 服务器在 UDP 443 上监听 | 还是 UDP,没有 TCP 队头阻塞,延迟最低 | 要网络放行 UDP 443(为 QUIC 放行的网络常有);纯 UDP 堵死的网络没用 |
| TURN over TLS (TCP 443) | turns: 裹进真 TLS |
过 DPI,最通的兜底 | TCP 队头阻塞、双层加密、握手开销 |
| ICE-TCP | 直接用 TCP 传媒体(RFC 6544,RTP 按 RFC 4571 加帧),不经 TURN | 省一台中继 | 只在对端有公网可达时有用;仍是 TCP 的毛病 |
| 媒体走 WebSocket/SFU | 客户端先 WSS 443 连 SFU,SFU 再在 ICE 里塞 TURN 候选 | 信令通道已经在 443,架构统一 | 本质还是回到 TURN;LiveKit 这类就是这么干的 |
| QUIC / WebTransport(新) | 基于 HTTP/3,天生跑在 UDP 443 上 | NAT 友好、连接迁移、少队头阻塞 | 还在演进;P2P 场景仍离不开 ICE/STUN/TURN 做穿越 |
两个判断:
- 优先选 UDP 443,而不是 TLS/TCP 443。 只要网络肯放 UDP 443(给 QUIC/HTTP3 放行的越来越多),TURN/UDP on 443 既能过“只认 443”的防火墙,又保住了 UDP 的低延迟。LiveKit 的默认推荐就是先上 TURN/UDP 443,TLS 443 只在“连 UDP 443 都堵”时才开。注意 UDP 443 和 TCP 443 是两个独立 socket,同一台机器可以同时监听,互不打架。
- 别指望 Web Proxy 替你中继媒体。 不管哪种方案,媒体从 443 出去靠的都是 TURN(或 SFU 背后的 TURN)贴着 443,而不是那台做 HTTP 审计的正向代理。如果企业网只给一个显式 HTTP 代理、连 TURN over TLS 都要穿过它,那要看浏览器引擎和代理配置支不支持,能通就谢天谢地了,别当设计目标。
一句话:
媒体被逼上 443,正道是让 TURN 自己贴着 443(优先 UDP,不行再 TLS),而不是把媒体塞进 Web Proxy。 TLS 那层是为了骗过 DPI,不是为了加密——媒体早就被 DTLS-SRTP 加过密了。
总结:代理是一道“收口”的关,坑在发现而不在转发
回到开头那条主线。Web Proxy 在企业里的角色,是把安全策略和网络出口收口到一个可控的点——它要“管住”所有出网流量,所以追求的是让应用无感知地被代理。而“无感知”这三个字,恰恰是所有故障的温床:应用不是统一地被代理,而是各自去不同的地方查“我该走代理吗”,查漏了、查错了,就连不上。
下次再碰到“公司网连不上、回家就好”,别急着怀疑网络,先按这张单子过一遍:
- 这个应用从哪读代理配置? 环境变量、系统设置、还是它自己的参数?curl 通不代表 Chrome 通。
NO_PROXY/ 例外列表配了吗? 内网和 localhost 有没有被误导进代理。- 走的是 PAC 还是 WPAD? PAC 服务器活着吗?WPAD 是不是该关掉了。
- 是 HTTPS 吗? 那代理默认看不见内容,审计失败不代表请求失败;反过来,证书告警往往是 TLS 拦截在作祟。
- 这是信令还是媒体? 媒体连不上,别去改代理,去查 TURN。
代理这东西,真正难的从来不是“怎么转发一个请求”,而是“让一屋子互不相干的应用,都准确地知道自己该走哪条路”。把发现机制这一层吃透,大半的代理问题都能在五分钟内定位。
全文思维导图
@startmindmap
<style>
mindmapDiagram {
node {
BackgroundColor #F8F9FA
RoundCorner 10
Padding 10
FontSize 13
}
:depth(0) {
BackgroundColor #1E3A5F
FontColor white
FontSize 18
FontStyle bold
}
:depth(1) {
FontSize 15
FontStyle bold
}
:depth(2) {
FontSize 13
}
}
</style>
* Web Proxy
** 为什么需要
*** 安全:审计、DLP、恶意域名拦截
*** 网络限制:出口收口、内外网隔离、合规
*** 目标是无感知地管住出网流量
** 应用怎么发现(题眼)
*** 显式配置:环境变量/系统设置/应用参数
*** PAC:FindProxyForURL 集中决策
*** WPAD:DHCP 252/DNS wpad.dat,有风险,建议关
** 代理能看见什么
*** HTTP:absolute-form,全明文
*** HTTPS:CONNECT 隧道,默认只见 host
*** TLS 拦截 SslBump,代价是全网装 CA
** 部署与开源
*** 位置:出口网关/Sidecar/显式转发
*** Squid / Envoy / mitmproxy / tinyproxy
** 信令与媒体
*** 信令 HTTP/WebSocket 走代理
*** 媒体 RTP/SRTP 该走 TURN,不是 Web Proxy
** 媒体被逼上 443
*** TURN over TLS:turns: 裹进真 TLS 过 DPI
*** TLS 只覆盖客户端到 TURN,relay 仍是 UDP
*** TLS 为翻墙不为保密(媒体已 DTLS-SRTP)
*** 优先级 UDP > TCP > TLS,TLS 排最后
*** 其它方案:TURN/UDP 443、ICE-TCP、WebSocket/SFU、QUIC/WebTransport
@endmindmap

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。 欢迎在我的个人网站 https://www.fanyamin.com 访问原文并评论。