Skip to content

第30章 性能、安全与工程选型 ​

30.1 比较的对象是一条完整路径 ​

一个代理方案至少包含入口、代理命令、安全层、承载、路由及目标连接。VLESS是代理语义,TLS或Encryption提供特定安全保护,XHTTP组织HTTP请求,Vision又会按状态改变处理路径。把这些名字并列成一张单一“协议速度表”,容易比较到不同层次。

工程判断应先固定应用需求和边界:需要可靠流还是保留UDP数据报语义;客户端到哪里需要保密;谁能够看到目标;是否要求过去流量在长期秘密泄漏后仍保密;网络允许哪些运输;是否必须通过HTTP中间节点;两端软件支持的是哪一份版本。它们决定候选条件,吞吐和延迟再在这些条件内讨论。

比较维度应明确的含义常见错误替代
建连延迟到哪个事件完成:代理认证、目标连接或网站首字节只报一个“延迟”数
吞吐/goodput实际交付的应用有效字节与时间网络发送字节率
CPU与内存哪个进程、方向、负载和复制路径只看算法名或一个总占用值
完整性哪些字段由哪把密钥认证有CRC/FNV就算密码认证
PFS哪种长期秘密何时泄漏,历史临时秘密是否仍在每次随机Salt或随机Body Key
后量子保护哪次交换、哪段数据和哪种攻击时点名称中出现mlkem
重放记录、握手、代理请求还是业务执行一个去重集合解决所有层
兼容性两端格式及路径上每个中间节点的处理可以导入配置或握手端口可达

例如Shadowsocks 2022的基础PSK保护没有PFS;现代VMess随机Body材料仍通过长期秘密保护的头传递;Trojan依赖实际TLS会话;VLESS+TLS/REALITY也须按真实临时交换及验证分析。VLESS Encryption的完整交换、缓存恢复与Vision绕过后剩余层又各不同。不能把“使用加密”写成同一项无条件安全保证。

同样需要区分客户端身份与服务器身份。Trojan摘要、VLESS用户标识、VMess AuthID、Hysteria认证字符串及TUIC Exporter Token的验证对象不同。它们决定代理授权,却通常不证明目标网站身份;网站TLS继续负责后者。代理服务器能够看到目标地址,也不等于必然能看见HTTPS的路径与Body。

协议规范、软件实现与实际运行是三类依据。规范说明应当表达什么,固定源码说明某分支如何实现,运行证据才说明这次连接实际走过哪里。本书已按章节固定来源并复算若干字节案例,没有用静态阅读冒充全部互通或性能实验。工程结论也沿用这个边界。

选型的结果因而更适合写成条件:某路径只提供可靠HTTP入口,就要选择两端支持且中间节点能持续转发的HTTP承载;某实时应用需要不可靠UDP,就不能忽略UDP-over-stream引入的等待;某目标要求后量子应用保密,就必须检查真正保留到数据阶段的交换与加密层。条件能解释取舍,协议名字本身不能。

这些维度来自前面各章已经展开的字段与状态;对应实现版本集中列在来源登记。后续各节将在此基础上分别量化头部、RTT、复制、共享状态和网络约束,而不构造跨不同安全前提的总分榜。

30.2 字节开销与RTT:先定义统计边界 ​

协议开销可以按一次连接、一个记录、一个HTTP请求或一份UDP负载统计。它们不能直接互换。握手的固定字节在长下载中可能很快摊薄,逐块Tag和Padding则持续出现;反过来,短连接可能主要受握手等待影响,即使请求头只有几十字节。

以example.com:443为相同目标,前章已核算这些代理层字节:

项目指定条件下的长度尚未计入
VLESS基础请求34安全层握手/记录、应用负载
VLESS带Vision Flow请求52Vision块及相应安全层
本书VMess构造头115,头P为0Body块、承载与运输
Trojan请求头76TLS握手/记录及负载
Hysteria2 TCPRequest零Padding构造19实现默认Padding、认证、QUIC
TUIC v5 Connect17连接认证、QUIC及负载

这些不是同等安全条件下的完整连接排名。VMess头包含受保护的Body密钥传递,TUIC认证在另一条流,Hysteria先做HTTP认证,VLESS安全层另计。将其中最小值称为“协议总开销最小”会删掉必要部分。

逐记录成本也须保留条件。TLS1.3在16字节Tag、无内Padding时,对一段应用内容增加5字节头、1字节内部类型及16字节Tag,共22;VLESS Encryption普通记录没有TLS内部类型,为21;Shadowsocks 2017每块的认证长度与负载Tag合计34。现代VMess普通Body块为2字节长度加Tag16,再加实际Padding;其认证长度实验路径又不同。

若一层能把n次小Write合成一个记录,它减少的是重复记录开销。把应用每个字节都单独写成记录,与把8KiB合成一个,CPU和字节成本都可能不同。TCP把一个记录拆成多段不会新增AEAD Tag,却会增加相应运输头和ACK行为;这两种切分必须分开计数。

RTT则数因果依赖。令客户端到代理RTT为r,代理到目标RTT为s,目标解析耗时d。假设首次TCP建连、普通TLS1.3完整交换、没有早期数据、对称路径、无排队,客户端取得可发应用数据的外层连接通常约需r完成TCP,再约r完成TLS。代理请求此后到达远端还要约r/2,目标TCP及网站TLS又有自己的依赖。

第25章完整Encryption案例据此得到浏览器收到首批网站服务器握手约3r+2s+d,已经说明Padding、传输时间和调度被排除。这里不把该公式推广成所有VLESS+TLS或QUIC实现的固定结果。QUIC可把TLS握手与运输建立结合,复用连接可省掉新的外层建连,但代理认证、目标拨号和应用交互是否还能重叠,要按真实时序画图。

RTT也不等于往返“包数”。TCP SYN和TLS记录可能搭载在不同包中,恢复与早期数据还会改变等待关系。代理头多一次Write不一定多一个RTT,VLESS响应头少几个字节也不必然减少等待。相反,一个很小的认证挑战若必须先收回复才能继续,就可能在高RTT路径上占显著时间。

串联代理应按每跳可用通道的依赖计算,而不是机械把所有物理RTT乘同一个常数。建立后一跳的握手会经过前面已建立的隧道;解析可能发生在不同位置。第8章已经给出这种条件模型,新增一跳既增加路径和终结点,也可能改变实际路由质量,不能仅凭跳数预测固定性能。

所有表内数字都能追溯到第19、22、24、26—29章字段与标明条件的算例。工程比较先把统计范围写全,再比较总字节、关键路径与持续成本,才能避免把不同负责层的数字放在同一个分母里。

30.3 CPU、系统调用、拷贝与内存不是一笔费用 ​

一个代理转发方向常见的普通路径是:内核接收缓冲把字节交给用户缓冲,应用解析或解密、重新组织,再写入另一Socket的内核发送缓冲。用户态还可能在TLS明文、代理块与HTTP Body缓冲之间移动数据。即使最后只交付同样1MB内容,分块、包装和调用次数也可不同。

可以把处理成本概念性拆成每字节工作、每块工作、每请求工作和每连接工作。AEAD通常有随内容量增长的成本,也有每记录初始化和Tag处理;HTTP字段和对象分配偏向每请求;握手与账号状态偏向每连接。把所有开销都写成“加密多一层”,无法解释短小请求和长下载为什么表现不同。

假设64KiB数据按8KiB缓冲转发,且每次read/write都恰好完成,单方向需要8次读和8次写;按1KiB则是64次读和64次写。真实短读、非阻塞、批量接口和库缓冲会改变次数,这只是调用粒度的算术。增加缓冲可能减少调用,但也可能增加驻留内存或等待凑批时间,不能无限增大后期待所有指标同时改善。

Linux splice等路径尝试减少用户态与内核之间反复搬运,某些条件下可传递内核页引用。不过系统调用、网络栈、校验、缓存访问和发送仍然存在;涉及必须解密、重新加密或重写HTTP帧的层,也通常需要相应内容处理。第23章已说明Vision的层次剥离、就绪状态与平台条件,不能把Zero-Copy写成全路径零计算。Linux splice文档

TLS、AEAD硬件加速也只改变相应工作的一部分。AES指令和乘法支持可降低某些AES-GCM成本,ChaCha20-Poly1305在不同平台有不同实现;没有测量就不能把某算法在某CPU上的优势推广到所有设备。虚拟化、频率调度、包大小和单线程瓶颈还可能比算法选择更显著。

内存应数所有驻留状态。假设10,000条连接各为两方向保留64KiB用户缓冲,仅这部分约为1.22GiB;还未计Socket缓冲、握手、对象、HTTP/QUIC流状态、重排数据及回收器元数据。若只是按需借用共享缓冲池,实际驻留又可能远小于这个假设,不能把配置容量简单当成已分配常驻量。

缓冲池减少反复分配,可能提高复用效率,却也可能延长内存驻留。某次请求已经结束,不等于池或运行时立刻把页面还给系统;进程RSS也不等于当前所有有效负载字节。GC暂停、扫描及分配速度需要与对象生命期分析,而非只看一个内存总数。

QUIC通常还维护重传所需流数据、ACK状态、定时器及数据报队列;XHTTP packet-up可能暂存乱序批次;Shadowsocks 2022需要重放集合和UDP窗口。一个机制减少握手或重传等待,可能同时增加状态。可靠性、内存上限和失败清理应作为同一设计讨论。

最后,CPU平均占用低不证明没有CPU瓶颈。一条关键处理线程占满一个核心,在多核总百分比中仍可能很小;大量等待也可能让CPU低而吞吐低。需要解释的是哪个阶段限制了继续推进,不能用低占用反证“网络一定有问题”。本节不提供具体软件的占用或性能百分比。

数据路径以第2、23、24、29章固定源码为基础;内核分段、批量与线上包的关系可参阅Segmentation Offloads。这里所有缓冲和调用数量均为明确假设的成本例,非运行测量。

30.4 复用减少建连,也扩大共享故障范围 ​

多路复用把多个逻辑任务放到同一运输连接上,连接池则在多个可复用运输对象之间分配任务。二者可以同时存在,也不必总同时存在。一个HTTP/2 Transport可以在一个连接里复用请求,XMUX又可管理多个Transport对象;内部VLESS Mux、外部HTTP流和浏览器自己的网站HTTP/2更属于不同层。

例如浏览器在一条网站TLS连接内复用许多HTTP/2请求,代理把这整条网站连接视为一条TCP任务;XHTTP再用一条持续下载和若干上传请求承载该任务。外部HTTP/2看到的是XHTTP请求流号,不能替浏览器调度内层加密的各个网站HTTP/2流。内外多路复用的流ID和窗口完全独立。

复用首先摊薄运输与安全握手,也可能保留拥塞窗口和压缩状态。代价是多个任务共享连接级窗口、发送容量、调度、密钥状态及失败。HTTP/2在TCP之上还共享TCP缺口的交付等待;QUIC流可减少跨流交付阻塞,却仍共享拥塞和连接额度。

若一个大下载把连接窗口用满,小请求即使属于另一个HTTP/2或QUIC流,也可能暂时不能推进。公平调度或优先级可以改善某些情况,却不能让总发送量超过同一瓶颈容量。应用把所有任务放进同一连接,也不表示库一定按用户想要的顺序服务它们。

再看故障:一条逻辑流被拒绝,可以只影响该任务;底层TCP重置或QUIC连接关闭,却可能同时中断许多任务。连接池增加多个运输对象,能降低某个连接失败的集中范围,也增加握手、内存、空闲维护和拥塞实例。若池中对象实际上再由HTTP库管理连接,仍须按真实连接状态判断,不能仅数池条目。

长连接还会积累状态边界。它可能持有流量密钥、压缩字典、票据、账号上下文和重排缓存;换连接能更新部分状态,却不自动删除所有秘密,或恢复目标应用事务。第22章的缓存PFS与第27章的Body计数边界都说明,连接生命期不能只看“能一直通就越久越好”。

空闲策略涉及几种不同计时:Socket运输空闲、HTTP请求最长寿命、QUIC连接空闲、代理任务活跃、UDP关联保存和业务超时。某层心跳成功,只能说明它实际触及的路径仍能处理该消息;不能证明网站连接活着。把下载Padding误当作所有层统一心跳,也会误读故障。

正常退役与故障关闭应分开。第24章XMUX可以先把对象移出候选池,等待已有任务排空;新任务转到新对象,旧下载不必立刻中断。若直接在到期时关闭仍有任务的运输连接,则完成的是另一种生命周期策略。两种策略的连接统计和用户感受自然不同。

代理链中,这些共享范围还会嵌套。前置一条隧道承载后面多个目标,前置连接失败会同时影响它们;增加末跳连接数不能消除这一个公共故障点。架构图应标出哪些逻辑任务共享哪段运输和认证状态,而不只画若干箭头。

HTTP/2和QUIC保证见第11—12章;池对象、排空及运行计数以固定Xray XMUX为具体例,TUIC连接内关联以固定规范为例。这里没有给出普遍最优连接数。

30.5 高RTT、丢包与排队:先找等待来自哪里 ​

高RTT会放大必须串行完成的交互,也会提高维持一定速率所需的在途量。一份只需增加一次往返的认证,在RTT由50 ms变为200 ms时,其理想额外等待也由50 ms变为200 ms;省掉这次交互可能很有价值。它不代表协议传字节的CPU效率已经改变。

在一条已复用连接上,新目标仍可能经过远端DNS、目标TCP及网站TLS。若瓶颈在代理到网站,单纯缩短客户端到代理的握手未必显著改变页面结果。代理链还可能通过更好的物理路由降低某段损失或时延,也可能绕路;“多跳一定更慢”与“中转一定优化”都忽略了具体路径。

丢包要先判断位置和性质。TCP或QUIC可靠流在缺失区间交付前要补齐,UDP DATAGRAM可以丢弃而不等重传。前者保留完整字节,后者保留及时性选择;对于文件下载和实时语音,优先目标本来不同。把DATAGRAM丢掉的数据不计入耗时,当然可能显得更快,却没有完成同样任务。

随机差错、队列溢出、接收方来不及处理及路径MTU黑洞都可能表现为“丢了包”。增加发送速率对随机非拥塞损失与拥塞溢出的后果不同。Hysteria的Brutal按目标速率与确认比例处理,不自动知道损失原因;BBR和Reno也依赖观察与模型,不是直接读取链路真实容量。

排队可在没有明显丢包时制造很高延迟。假设某100 Mbit/s瓶颈之前积压10,000,000字节,理想排空时间约0.8秒。一个只有几百字节的新交互可能先等这段队列,即使它自己的传输只需很短时间。更多缓存暂时避免丢弃,却可能把代价改成更长排队。

代理自身也有队列:应用入口、解密缓冲、HTTP Body、上传重排、QUIC流和UDP接收通道。如果下游消费变慢,上游背压是必要反馈。绕过背压不断累积应用缓冲,会让本地写入看起来更顺,却不能减少实际交付等待;内存耗尽后的集中失败可能更严重。

乱序与丢失同样不能混为一谈。QUIC不同流可独立交付,但XHTTP先收到批次1而缺批次0,仍要等待;UDP分片未齐也不能拼成完整原包。丢失检测或超时若早于正常乱序完成,可能产生不必要重传或丢弃;若过晚又延误恢复。具体定时器由协议和实现共同决定,不能给所有应用套一个固定超时。

重试会增加新工作。客户端在慢响应时重建代理连接,目标应用自己也重发请求,多个层次叠加可能放大负载;旧任务也未必已经停止。安全层0-RTT或代理无额外响应可以缩短某些启动等待,但重复业务执行仍需应用幂等性或事务机制处理。

一个合理解释可以写成完整链条:当前等待在某段可靠流缺口、某层流控、某个重排队列或某次目标握手;所选机制改变该处依赖,代价是更多状态、额外流量或不同丢失语义。这样的解释比“高丢包网络专用协议必然更快”更能预测换负载后会发生什么。

可靠交付、拥塞反馈和丢失恢复以RFC 9000、RFC 9002及TCP的RFC 9293为基础;实际代理队列及算法边界见第24、29章固定源码。0.8秒与50/200 ms均为明确假设的算术,不是链路测量。

30.6 CDN、反向代理与多跳:把解密位置画出来 ​

CDN或反向代理不是一段没有行为的线路。L4转发主要搬运输字节,L7节点则解析HTTP、可能终结TLS并重新组织请求。选择承载之前,先确定所需的是哪一种服务,以及它在哪一层结束安全会话。

路径形态中间节点至少处理什么需要保留的条件
透明TCP中转承载TLS/REALITY运输连接与转发字节不错误终结或改写上层握手
WebSocket经HTTP节点HTTP升级及后续双向数据支持升级、超时及持续转发
gRPC经HTTP节点HTTP/2与请求/响应流相容gRPC路径、Body与流式行为
XHTTP经HTTP节点各模式请求与响应、元数据保留会话关联、流式时机、缓冲及大小条件
原始Trojan/自定义QUIC代理特定代理字节或自定义QUIC流不能仅以普通HTTP解析替代

如果外层TLS在CDN终结,CDN可以读到HTTP字段与Body。Body中若是基础VLESS头,用户标识和目标也可见;若还有独立Encryption,其保护范围以实际保留的记录阶段为准。网站TLS仍可保护HTTP应用明文,但不能回过头隐藏外面已明示的代理目标。

REALITY需要客户端验证其专用握手。普通HTTP CDN用自己的证书完成前段TLS,不会因为回源地址是REALITY服务端就自动变成合法REALITY对端。透明运输中转可以保留握手,HTTP终结则改变协议对象。这是第21章验证逻辑决定的边界,不是换一个Host字符串就能消除的差别。

XHTTP不同。它本来允许相应HTTP请求经过中间节点,但仍依赖上行Body、下行响应和会话状态汇合。前段HTTP/3、后段HTTP/2可以成立,不等于所有模式都能穿过所有缓冲策略。DownloadSettings也不是跨服务器同步sessions表的机制。若中间节点重写路径、删除Padding载体或把上下行分到不同处理器,格式合法仍可能无法形成可用代理连接。

多跳可以改变信息分布。设客户端C先通过A建立到B的通道,再在其中与B建立独立认证加密会话。A知道C连接到B;B可能只在运输层看到A,却解开最终代理请求知道目标W。要让A不直接读到W,C到B的内层保护必须真正终结在B,而不是由A先解密再重新加密。谁生成每一层密钥,比箭头经过几台服务器更重要。

这种分布仍不是匿名性证明。A、B可能共享日志或串通,长度和时序可能关联;某些上游头还可能明确传递来源。CDN看到用户来源及访问入口,源站也可能收到转发来源字段。不能仅凭源站TCP源地址变成CDN,就认定客户端地址对所有组件不可见。

每增加终结点,还增加证书/静态材料管理、故障和状态清理责任。共享身份凭据会让多台节点具备相同冒充能力;中转上的普通HTTP回源也可能暴露解密数据。外层加密、内层网站加密和代理授权应在每段标出,避免把安全边界画成自动贯穿所有节点的一条线。

工程架构最后还要考虑可用性:一个公共前置隧道故障可影响后面所有落地,一个分布式入口若不共享所需会话状态又会破坏复用。增加路径数量不是只增加冗余,也会增加路由与一致性条件。本节不针对任一商业CDN承诺兼容性;具体机制依据第8、20、21及24章已核验的处理路径。

HTTP终结与代理职责见RFC 9110,流式缓冲的具体例见Nginx代理模块;REALITY验证及XHTTP会话实现分别见固定Xray reality.go与hub.go。

30.7 DNS隐私:问题是由谁查询、经哪里查询 ​

DNS泄漏应相对于原本期望的隐私和路由边界定义。如果策略要求目标解析留在远端,却由本地应用先向本地解析器发出了查询,这就是路径偏离;查询即使后来又在远端重复,也不会撤销先前暴露。反过来,主动选择可信本地解析器是另一种设计,不能只因解析发生在本机就一律称为泄漏。

一个代理连接至少可能涉及代理端点域名、目标网站域名、加密DNS服务自身的端点域名,以及其他后台组件查询。它们由不同组件发起,不必经过同一条路。节点连通只证明某段路径可用,不证明这些查询都符合策略。

查询或地址转换可能执行者应区分的路径
代理服务器域名解析本地内核、代理程序或引导解析器建立代理前怎样找到端点
目标域名解析浏览器、本地代理或远端落地请求传域名还是已解析IP
DoH/DoT服务端点解析应用或系统引导逻辑查询尚未建立加密DNS连接之前
Fake-IP到原域名还原保存映射的本地代理组件这是映射查找,不等于又做公网DNS

SOCKS域名请求、VLESS域名目标及类似机制允许把目标名称交到远端。但浏览器自己的预解析、系统服务、TUN之外的流量或其他应用仍可能查询本地DNS。仅证明一条目标连接由远端解析,不足以证明整台设备的查询都被接管。

TUN入口接收IP包,通常只能从包本身得到目标IP,不天然携带原DNS名称。Fake-IP类方案通过先回答一个合成地址,保存“合成地址—域名”映射,等应用连接该地址时恢复原域名,再按代理策略处理。它把名称信息保留在本地状态中,而不是让任意远端从这个合成IP反算域名。映射丢失或请求绕过保存映射的组件,语义就可能无法恢复。

嗅探可以从部分HTTP Host或可见TLS SNI提取名称,但它有协议和时机限制,也不等于DNS查询。ECH可能保护相应名称信息;某些应用根本不使用这些格式。不能把“有TUN+嗅探”理解成所有IP连接都必然能恢复唯一域名,也不能据一个域名对应多个CDN地址就推断IP反查能得到原请求名。

DoT用TLS保护DNS运输,DoH把DNS消息放进HTTPS。它们可保护客户端到指定解析端点这一段,使沿途不能直接读取DNS内容;解析器本身仍知道查询,端点的后续递归和日志又有自己的边界。DNSSEC则主要验证DNS数据真实性,不等于给查询路径加密。RFC 7858、RFC 8484

加密DNS也需要路由。若DoH连接直接从本地发出,内容虽然加密,观察者仍能看到客户端访问哪个解析端点;若要求它经代理,又要解决找到代理及解析DoH端点所需的引导依赖。把所有解析都写成“必须先通过尚未建立的同一代理”,可能形成循环,不能靠更长配置规则掩盖。

只限制UDP/53不会覆盖TCP DNS、DoT、DoH、HTTP/3承载或应用自建解析。查询是否泄漏还取决于IPv6、分流规则、代理链前置拨号和失败时的回退行为。某次连接失败后改走系统解析器,可能改变隐私路径;这一行为应以实现证据说明,而非仅看首选DNS配置。

最后,即使所有目标DNS都按策略通过远端,远端代理仍可能直接从请求头知道目标;网站还可能通过登录信息识别用户。减少本地DNS暴露解决的是特定信息路径,不是消除所有来源、目标和应用身份关联。第8、25章已据具体请求与落地解析追踪这些终结点,本节没有把局部DNS成功扩大成整机匿名性。

30.8 MTU、MSS与代理数据报大小 ​

MTU限制的是某条链路或路径可承载的网络层包大小,不是应用一次Write的上限。MSS是TCP协商及发送计算使用的数据段大小参数,UDP应用负载、QUIC DATAGRAM额度和TLS记录大小又处在不同层。把这些都叫“包长”,很容易用错减法。

假设路径MTU为1500,IPv4无选项头20字节、TCP基本头20字节,则常见MSS尺度为1460;IPv6基本头40字节时为1440。若TCP还带时间戳等选项,发送端需为实际选项腾空间,不能仍把1460字节应用数据加所有选项后硬塞进同一个1500字节IP包。具体MSS行为按TCP规则与实现计算。

UDP没有TCP的MSS协商。相同假设下,IPv4 UDP可留1500−20−8=1472字节负载,IPv6为1500−40−8=1452。它们只适用于这些基础头和MTU条件;IP扩展头、隧道及其他包装都会进一步占空间。不能把1472写成所有UDP代理共同的最大应用数据。

QUIC又在UDP负载里放连接头、包号、AEAD Tag和帧。DATAGRAM帧的代理负载还含Hysteria/TUIC的会话、分片与目标字段。因此原始应用UDP可用空间,要从当前QUIC与DATAGRAM允许的大小再减代理头,而不是只从1500减IP/UDP。不同Connection ID、帧长度编码和路径状态都可能改变余量。

QUIC关于客户端Initial的最小UDP数据报大小要求也不能反过来当成所有应用包固定大小。含客户端Initial的相应UDP数据报需满足至少1200字节要求,目的是提供基础路径与抗放大条件;之后短包、ACK与应用DATAGRAM的组织按实际情况决定。若路径无法承载所需大小,连接建立就可能失败,而不是协议自动把这条要求忽略。

TLS记录可包含远大于一个MSS的内容,TCP会按运输条件分段后再恢复字节流。16KiB级TLS记录不意味着IP必须支持同样大的单包。反过来,一个UDP应用数据报若被拆成多个代理分片,需要代理层重组;它与TCP自动分段不同,也与IP分片不同。

IPv4在一定条件下允许网络层分片,IPv6路由器不替转发包进行这种分片;无论哪种,丢一片通常都会使原始数据报无法交付。中间设备还可能丢弃碎片或相关反馈。因此代理设计常尽量控制外层数据报大小,并通过路径MTU发现或分片策略适应路径,而不是只依赖“系统会分片”。

DPLPMTUD在分包层使用探测和反馈判断可用大小,减少对ICMP反馈必达的依赖。若路径只丢较大的包,小包与握手部分成功、大数据反复停滞,可以成为大小相关故障的线索;仍需排除拥塞、限流和接收缓冲等其他原因,不能凭现象直接断言MTU问题。RFC 8899

TUN的内层MTU与外层运输还须单独分析。若搬运完整IP包,外层封装必须留足它的空间;若用户态栈终结TCP、再创建新的代理流,则内层段长不会一一复制成外层段长。直接把TUN MTU当作每条外部TCP的MSS,可能误解数据路径。所选UDP代理是否再分片,也要按第29章的字段及实现限制判断。

抓包出现超过MTU的大块,不一定证明线上真发出巨帧。TSO/GSO可在观测后分段,GRO可在观测前合并;校验卸载也可能让本机捕获内容看起来尚未填好校验。观测位置决定看到的是发送前对象、线上包还是接收后合并对象。Linux分段卸载文档

这些层次来自TCP的RFC 9293及QUIC的RFC 9000;1500及相应减法都是注明条件的示例。协议字段能表示多大、软件缓冲接纳多大、路径实际能运输多大,应在每次分析中分别给出。

30.9 tcpdump、Wireshark与curl:观察点决定结论 ​

抓包记录某个接口和时间范围内可见的包。它可以展示TCP序号、ACK、握手时序、地址及流量规模,但不会自动知道浏览器的业务请求是否成功。客户端到代理、代理到目标及本地入口是不同观测段,某段出现ACK不能跨越代理推断另一段已交付。

tcpdump常用于保存或概览包。捕获过滤、截取长度、内核捕获缓冲和丢包计数影响记录是否完整;工具报告的捕获丢弃与真实网络丢失不同。文件中没看到某包,可能是应用未发送、接口或过滤条件不包含它、捕获自身丢弃,也可能是网络中没到,不能只选最后一种解释。tcpdump上游手册

Wireshark进一步重组和解析。TCP中的应用消息可能跨段,协议树把重组后的内容显示在某个包下,不意味着应用一次Read就取得这些内容。重传、乱序等分析标记依赖当前捕获及启发式;记录缺失、单向捕获或卸载也会影响判断。Wireshark重组说明

TLS应用内容通常不能只靠捕获解开。适当会话秘密可以帮助分析器解密,而TLS1.3临时交换不会因拿到一个公开证书或仅凭服务器证书私钥就自动恢复历史应用密钥。QUIC Initial的公开初始密钥又是特殊情况:能解析Initial ClientHello不等于已能解开后续1-RTT应用数据。第16章已经用完整Initial构造说明这个区别。Wireshark TLS说明

本机出现“坏校验和”或大于常规MTU的捕获,也须结合卸载位置解释,不能直接当作线上坏包。接收端是否真正拒绝、另一观测点看见什么、ACK是否推进,才与具体假设相关。Wireshark校验和说明

curl则是应用协议客户端,它的结果包括名称解析、连接、TLS和HTTP状态等可见阶段。它不是所有代理协议的通用解码器;即使经本地HTTP或SOCKS入口访问,也是在验证那条配置出来的应用路径。结果不能自动覆盖浏览器自己的连接复用、DNS或QUIC行为。

常见时间字段是从操作开始到某事件的累计值:time_namelookup到解析完成,time_connect到连接目标或代理的TCP完成,time_appconnect到相应安全握手完成,time_starttransfer到首字节。它们不是四段可以直接相加的独立耗时;代理、重定向和复用会改变解释。curl官方手册

假设一组单次、无重定向的构造观测值依次为0.02、0.08、0.16、0.40秒。0.40−0.16=0.24秒只能说明安全握手结束后到首字节还有这段等待,其中可能含请求运输、代理排队、目标处理及回程;不能把0.24秒全命名为网站计算时间。这个例子不是本书真实测量。

HTTP状态也属于具体响应者。CONNECT的200表明相应代理接受隧道,XHTTP下载200早于VLESS认证的情况已经在第24章说明;网站自己的HTTP 200则又在里面。将日志中的一个200当成整条链每层都成功,往往比缺少工具更容易导致误判。

有用的证据应能定位:这条记录来自哪段、哪份连接、哪个状态阶段;它支持什么假设,又还有哪些原因产生同样表象。工具提供观测,协议状态和源码帮助解释观测,两者不能相互代替。本节只解释其证据能力,没有安排操作实验或命令步骤。

30.10 ss、strace与iperf3:从系统状态解释瓶颈 ​

ss展示Socket及相关运输状态,strace展示进程与内核的接口活动,iperf3产生并统计特定运输负载。它们回答的是不同问题,不能用某一个工具的“正常”替代整条代理路径的证据。

对于已建立TCP,ss中的队列与RTT、重传计时、MSS、拥塞窗口等信息可以帮助解释内核是否还在等待运输条件。它看到的通常是一段Socket状态,不直接知道里面是VLESS、Trojan还是一个网站TLS。UDP上的QUIC流、拥塞模型和应用重排主要在用户态,不能指望同一组TCP字段完整展示它们。ss手册

假设代理出站发送队列持续积压,可能是远端消费慢、接收窗口不足、拥塞或发送能力受限;如果入站接收队列也积压,又可能有应用没有及时读取。仅一个瞬间的非零队列不能确定原因,短时批量收发本来就会产生队列。它应与ACK推进、应用读写及相邻段状态对应。

RTT和拥塞窗口也不是网站响应时间。某个Socket可能只是客户端到前置代理,后面另有数段连接;其RTT低不能排除远端DNS或网站慢。TCP ESTABLISHED只表示该段运输处于建立状态,不证明账号通过、TLS认证完成或目标仍可用。

strace记录系统调用、信号等进程与内核边界活动。它可以帮助确定程序是否在读写某Socket、等待事件、遭遇EAGAIN或执行splice,但通常不能直接展示用户态函数里的加密、HTTP解析和队列操作。长时间等待某次调用也可能包含调度和对端等待,不等于那段时间都在计算密码。strace项目说明

EAGAIN在非阻塞网络中常表示当前条件尚未满足,并非协议永久失败。看到read返回少于请求量,也不能据此判定丢失了应用消息;第3章的短读契约仍然成立。反过来,某路径实际调用splice可以支持“尝试走了内核搬运接口”,却不能单独证明所有字节全程没有拷贝,或由此计算出吞吐提升百分比。

观测本身有成本。逐次系统调用跟踪、完整打印或附加解码可能改变调度和速度。由被跟踪进程的一个低吞吐结果,不能未经区分就断言它原本的最大能力;同样,只看没有详细跟踪时的总CPU,也难以定位热点。源码路径、系统边界和应用统计应相互限定结论。

iperf3的TCP/UDP负载主要用来描述选定端点与运输路径上的数据交付能力。并发流、方向、发送速率和数据报大小改变实际负载,可能也改变CPU或拥塞结果;它不是浏览器完整页面或特定代理握手的等价替身。官方说明并发流在CPU受限时可以取得高于单流的吞吐,这也说明总值不能直接归给一条交互流。ESnet iperf3文档

还须确认流量实际经过哪里。系统HTTP代理设置不自动证明任意运输工具都经过同样代理;若TUN或其他路由接管了它,控制连接和数据连接也可能分别受规则影响。只在直连路径得到较高吞吐,不能替一条多跳加密链证明相同能力;UDP发送端达到目标速率,也不能替接收有效字节或及时性统计。

三个工具可以支持一个因果解释:某段Socket是否积压,进程有没有消费它,实际读写如何推进,所选负载在目标路径上收到多少有效数据。它们不自动完成账号、安全、DNS及网站应用的验证。本节没有提供工具命令或实验任务,也没有把假定结果冒充本书实测。

30.11 从约束选择组合,而不是从排名选择名字 ​

协议选型可以先排除不满足必要条件的路径,再在剩余组合中比较成本。必要条件若没有满足,较短请求头或更快密码实现也不能让方案可用。例如UDP被完全阻断时,原生QUIC代理没有可工作的基础运输;只允许普通HTTP入口时,任意二进制代理也不能直接当HTTP请求交给它。

已知约束或需求可分析的方向必须同时检查
仅有稳定TCP通路可靠流承载的代理与相应安全层目标UDP是否被改成流内运输,交互等待是否可接受
必须经过HTTP反向代理两端支持的WS、gRPC或XHTTP等HTTP版本、双向流、缓冲、大小、超时及会话汇合
实时UDP需要保留不可靠语义独立UDP保护或QUIC DATAGRAM模式MTU、分片、接收队列、目标UDP段及拥塞
大量短任务连接复用与适合的流映射共享窗口、调度与单连接失败范围
长下载且CPU可能受限减少重复包装、复制及调用的路径平台、真实快路径、硬件和安全层是否仍满足要求
需要过去应用数据抵抗长期秘密泄漏实际保留的PFS层静态/缓存秘密留存、恢复模式、Vision是否绕过
需要混合后量子交换保护数据协商并保留到所需数据阶段的混合层实际组、认证、缓存状态与网站内层保护
多跳分散可见信息明确每层独立密钥及终结点串通、日志、DNS与共同故障点

表中是机制方向,不是软件配置建议清单。比如“HTTP入口”还不足以确定XHTTP模式:缓冲有限上传但及时转发持续下载的节点,可能适合packet-up;允许持续上行的路径才具备stream-up前提;单请求全双工还需要stream-one对应条件。协议版本、后端能力和Extra配置覆盖也会改变最终路径。

实时UDP同样不自动指向唯一答案。Shadowsocks 2022有独立UDP会话与重放窗口,Hysteria2使用DATAGRAM及自己的分片/关联,TUIC有DATAGRAM和可靠流两种映射。谁能满足时效、损失和访问策略,取决于实际路径、实现及负载。不能因其中一个支持可靠模式,就把它默认优于愿意丢弃过期包的方案。

安全要求应写成秘密与时间,而不只写加密算法。例如“服务器长期私钥之后泄漏,过去数据仍不可恢复”需要临时秘密不能从长期材料和记录重算;纯PSK加随机Salt不足够。若缓存保留了PFS材料,要把这段时间和删除条件纳入判断;若Vision绕过了那层记录,则继续看剩余层,不能把名称中的混合交换覆盖所有后续数据。

兼容性则要落实成双方真正执行的编码。TUIC v4与v5、Shadowsocks 2017与2022、VMess历史头与现代头不能只靠共享界面名称互通。服务端配置接受某字段、客户端导入不报错、端口能建立TCP或UDP,都只证明各自部分条件。固定源码中的分支和实际运行证据更接近问题本身。

可维护性也有具体内容:版本能否固定,账号和静态材料如何更新,状态丢失后怎样恢复,失败是否有可定位证据,中转层是否由自己控制。功能更多的组合可以覆盖特定网络约束,也会增加需要理解和排障的边界;少一层只有在仍满足必要条件时才是有效简化。

最终方案应能用一段因果说明描述:为哪种应用语义,经过哪条允许的运输路径,在谁处完成哪次认证与解密,保留什么会话状态,可能受哪个共享瓶颈限制。这个说明成立后,协议名称只是索引,不再承担它不能证明的性能、安全或隐私保证。

具体能力和限制以第18—29章固定规范及源码为依据,版本汇总见来源登记。本节没有给未经同条件验证的总分、默认“最佳协议”或商业服务推荐。

30.12 三个架构案例:需求怎样落实到数据路径 ​

经过HTTP入口的浏览器访问 ​

设客户端到源站不能稳定直连,但有一个能处理有限上传、及时转发持续下载的HTTP入口E。应用需求是浏览器HTTPS访问,允许代理知道目标,入口E是否可读代理目标则需要明确决定。

一种可分析结构是客户端经外层TLS到E,再由E把XHTTP packet-up请求及持续下载汇合到同一个源站处理器P。选择packet-up的依据是有限上传条件,能否工作仍取决于路径、Padding载体、批次大小、超时和会话汇合。前段HTTP/3、后段HTTP/2并不破坏其逻辑,但两段分别有窗口与拥塞。

若Body里直接是基础VLESS,E终结TLS后可以读到用户标识和目标;网站TLS只保护网站应用内容。若需求是不让E直接读取代理头,可以在HTTP承载之上保留独立的端到端安全层到P,但必须核对实际组合及数据阶段是否仍保留该层。仅增加Padding或随机路径,不能达到这个目标。

P解析目标并在自身网络发起DNS与目标连接。E能看到客户端来源、访问入口及流量形状,P能看到目标;是否还传递来源头、E与P是否共享日志,进一步决定信息边界。这里没有普通HTTP CDN替REALITY完成专用认证的假设,也没有把E能接HTTP等同于支持所有XHTTP模式。

有可用UDP路径的实时会话 ​

再设应用是实时UDP,宁愿丢掉过期数据也不愿等待可靠重传,客户端到代理有可用UDP路径。Hysteria2 DATAGRAM、TUIC native或具有相容独立UDP保护的方案都可以作为候选,选择理由是保留这一段的不可靠语义,而不是某名字天然最快。

每份应用数据必须加上代理、DATAGRAM和QUIC包等实际开销后仍能合适运输。超过额度时,分片让任一片丢失都影响原包;过大的接收队列又可能把旧数据拖到失效才交付。Hysteria所读Defragger与TUIC所读重组缓存不同,必须按实际实现考虑并发分片。

如果应用需求改成尽量完整交付,可以考虑TUIC可靠流模式,但目标UDP段仍不保证可靠。拥塞输入也要对应真实可用速率;将Brutal参数高设并不能创造容量。这个案例的结果应以有效、及时到达的应用数据解释,而非只看发送端字节率。

QUIC握手与代理认证还分别验证服务器和用户。客户端网络变化时能否继续,需要运输迁移、代理状态及具体配置共同支持。所谓Full Cone关联解决的是服务器UDP Socket的映射与接收能力,不保证用户物理网络的NAT属性改变。

分离前置入口与最终落地 ​

最后设C不能直接连接B,但可通过A获得到B的可靠通道。C先通过A建立面向B的连接,再在通道内与B完成独立服务器验证和加密代理会话,由B访问W。A终结前置那层,B终结内层;目标域名保留在内层请求,由B解析。

在这个条件下,A可直接知道C与B,B在运输层通常看到A并知道W;若内层真正在C/B间认证加密,A不直接得到代理头中的W。网站TLS又把应用明文继续终结在浏览器和W。三份职责和秘密分别存在,不能用“有两跳加密”代替它们。

前置A是公共故障点,它的连接关闭会影响其承载的后续任务。B的账号和目标策略、DNS、出口与网站故障也可独立发生。若把后续任务复用在一条前置连接里,建连减少但共享影响变大;若拆开,状态与握手增加。没有一组固定跳数或池大小能够同时对所有负载最优。

各方串通、时序关联、来源元数据及网站登录仍可打破简单的身份分离想象。这个架构只是按终结点分配可直接读取的信息,不构成匿名性证明。长期材料泄漏后的历史保密,也要看对应临时交换、缓存和实际保留的数据层,不能从多跳本身推出。

这三个案例都从应用语义和路径约束出发,再决定字段如何到达、在哪里解密、保存什么状态、哪些事件必须等待。阅读一个新协议时,同样可以追踪它的定界、密钥、状态和失败分支,并把规范、实现与观测放到各自位置。到这一步,配置里的协议名才对应一条能够逐层解释的实际通信过程。

案例依据分别来自第24章XHTTP、第25章完整通信、第29章QUIC代理及第8章代理链的固定来源。它们是机制推导案例,没有伪装成生产部署记录或未经测量的性能结论。

从字节与状态机出发,理解每一层的职责。