obfs4文档翻译

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

obfs4⽂档翻译
写在前⾯:根据翻译,其中还有⼀些内容没理解,后续慢慢补,欢迎⼤家讨论交流
obfs4是什么?
这是⼀个看起来没有混淆的协议,它融合了Philipp Winter的ScrambleSuit协议中的想法和概念。

选择obfs命名主要是因为它更短,就协议来说,obfs4⽐obfs2 / obfs3更接近ScrambleSuit。

ScrambleSuit和obfs4之间的显着差异:
握⼿总是进⾏全密钥交换(没有会话票务握⼿)
握⼿采⽤Tor项⽬中使⽤Elligator 2映射进⾏模糊处理的公钥的ntor握⼿。

链路层加密使⽤NaCl密码箱(Poly1305 / XSalsa20)。

另外,obfs4proxy还可以充当obfs2 / 3客户端和桥接器,以简化向新协议的过渡。

为啥不扩充 ScrambleSuit?
这是我的协议,如果我愿意,我会混淆。

由于对握⼿过程进⾏了很多更改,因此将ScrambleSuit扩展为编写⽀持两种握⼿变体的服务器实现⽽不是⾮常缓慢是不重要的是没有意义的。

Since a lot of the changes are to the handshaking process, it didn't make sense to extend ScrambleSuit as writing a server
implementation that supported both handshake variants without being obscenely slow is non-trivial.
介绍
这是TCP协议层的混淆,⽬的是防⽌第三⽅根据消息内容得知正在使⽤的协议。

与obfs3不同,虽然也是主要围绕为现有⾝份验证协议(如SSH或者TLS)提供⼀个层模糊处理,但obfs4尝试提供⾝份验证和数据完整性。

与obfs3和ScrambleSuit⼀样,该协议有两个阶段:在第⼀阶段,双⽅都建⽴密钥。

在第⼆,双⽅交换强加密的流量。

动机
ScrambleSuit的开发旨在改进obfs3协议,以对抗主动攻击者和伪装流签名(流特征?)。

像现有的obfs3协议⼀样,ScrambleSuit使⽤UniformDH进⾏加密握⼿,但模幂运算严重影响性能。

此外,密钥交换未经过⾝份验证,因此如果他们知道客户端/⽹桥共享密钥的话,主动攻击者就可以实施中间⼈攻击。

obfs4试图通过使⽤基于Tor项⽬的ntor握⼿的⾝份验证的密钥交换机制来解决这些缺点。

线路上所传输的Curve25519公钥是通过Elligator 2映射完成混淆的。

威胁模型
obfs4是在obfs2威胁模型的基础上修改⽽来:
obfs4对抗关注obfs4协议的被动深度包检测设备。

如果没有获得服务器的节点ID(Node ID)和⾝份公钥,这些机器应该⽆法验证obfs4协议的存在。

obfs4对抗试图探测obfs4服务器的主动攻击者。

如果没有获取服务器的节点ID和⾝份公钥,此类计算机应该⽆法验证obfs4服务器是否存在。

obfs4对抗获得服务器节点ID和⾝份公钥的主动攻击者。

如果没有获取服务器的⾝份私钥,此类计算机应该⽆法模拟服务器。

obfs4针对某些⾮内容协议指纹提供保护,特别是数据包⼤⼩和可选的数据包时序。

obfs4提供底层流量的完整性和机密性,以及服务器的⾝份验证。

符号和术语
所有Curve25519密钥和Elligator 2 实现都以⼩端序传输,以便于与当前的Curve25519和Elligator 2实现集成。

所有其他数字字段以⼤端序(⽹络字节顺序)值传输。

HMAC-SHA256-128(k,s)s为HMAC-SHA256摘要,k为密钥,截断长度为128位。

x | y是x和y的串联。

byte是8位的字节。

密钥建⽴阶段
作为配置的⼀部分,所有的obfs4服务器都有⼀个20字节的节点ID(NODEID)和Curve25519密钥对(B,b),⽤于使客户端知道给定的服务器并验证服务器。

服务器通过带外机制将⾝份密钥(B)和NODEID的公共组件分发给客户端。

1. 握⼿数据被填充到随机长度来模糊初始的流签名(流特征?)。

使⽤的常数如下:
MaximumHandshakeLength = 8192
握⼿请求或响应的最⼤⼤⼩(包括填充)
MarkLength = 16
HMAC-SHA256-128摘要中M_C / M_S的长度
MACLength = 16
HMAC-SHA256-128摘要中MAC_C/MAC_S的长度
RepresentativeLength = 32
Elligator 2 表⽰的 Curve25519 公钥的长度.
AuthLength = 32
ntor认证标记(HMAC-SHA256)的长度.
InlineSeedFrameLength = 45
未填充的TYPE_PRNG_SEED帧的长度。

ServerHandshakeLength = 96
握⼿响应中⾮填充数据的长度。

RepresentativeLength + AuthLength + MarkLength + MACLength
ServerMaxPadLength = 8096
握⼿响应中的最⼤填充量。

MaximumHandshakeLength - ServerHandshakeLength
ServerMinPadLength = InlineSeedFrameLength
握⼿响应中的最⼩填充量。

ClientHandshakeLength = 64
握⼿请求中⾮填充数据的长度。

RepresentativeLength + MarkLength + MACLength
ClientMinPadLength = 85
握⼿请求中的最⼩填充量。

(ServerHandshakeLength + ServerMinPadLength) - ClientHandshakeLength
ClientMaxPadLength = 8128
握⼿请求中的最⼤填充量。

MaximumHandshakeLength - ClientHandshakeLength
2. 客户端握⼿过程如下:
1. 客户端⽣成临时的的Curve25519密钥对X,x和代表公共组件X'的Elligator 2。

2. 客户端向服务器发送握⼿请求
clientRequest = X' | P_C | M_C | MAC_C
X' = Elligator 2 representative of X (32 bytes)
P_C = Random padding [ClientMinPadLength, ClientMaxPadLength] bytes
M_C = HMAC-SHA256-128(B | NODEID, X')
E = String representation of the number of hours since the UNIXepoch
MAC_C = HMAC-SHA256-128(B | NODEID, X' | P_C | M_C | E)
3. 客户端从服务器接收serverResponse
4. 客户端从serverResponse计算M_S并使⽤它来定位serverResponse中的MAC_S。

然后计算MAC_S并将其与从服务器接收的值
进⾏⽐较。

如果找不到M_S或MAC_S值不匹配,客户端必须断开连接。

5. 客户端通过Elligator 2对应关系反向从Y'导出Y.
6. 客户端完成ntor握⼿的客户端,导出256位共享密钥(KEY_SEED)和⾝份验证标记(AUTH)。

然后,客户端将AUTH的派⽣
值与serverResponse中包含的值进⾏⽐较。

如果AUTH值不匹配,客户端必须断开连接。

3. 服务器握⼿过程如下:
1. 服务器从客户端接收clientRequest。

2. 服务器从clientRequest计算M_C并使⽤它在clientRequest中定位MAC_C。

然后计算MAC_C并将其与从客户端接收的值进⾏⽐
较。

如果找不到M_C或MAC_C值不匹配,服务器必须停⽌处理来⾃客户端的数据。

实现必须计算并⽐较MAC_C的多个值与“E = {E-1,E,E + 1}”以解决客户端和服务器之间的时钟偏差。

在此时发⽣故障的情况下,实现应该延迟从客户端丢弃TCP连接⼀个随机间隔,以使主动探测更加困难。

3. 服务器通过Elligator 2映射反向从X'派⽣X.
4. 服务器⽣成临时的Curve25519密钥对Y,y和代表公共组件Y'的Elligator 2。

5. 服务器完成ntor握⼿的服务器端,导出256位共享密钥(KEY_SEED)和⾝份验证标记(AUTH)。

6. 服务器向客户端发送握⼿响应
serverResponse = Y' | AUTH | P_S | M_S | MAC_S
Y' = Elligator 2 Representative of Y (32 bytes)
AUTH = The ntor authentication tag (32 bytes)
P_S = Random padding [ServerMinPadLength, ServerMaxPadLength] bytes
M_S = HMAC-SHA256-128(B | NODEID, Y')
E' = E from the client request
MAC_S = HMAC-SHA256-128(B | NODEID, Y' | AUTH | P_S | M_S | E')
在每⼀⽅完成握⼿时,它们具有256位共享密钥KEY_SEED,然后通过ntor密钥派⽣函数产⽣⽤于加密/验证数据的144字节密钥材料。

密钥使⽤如下:
Bytes 000:031 - Server to Client 256 bit NaCl secretbox key.
Bytes 032:047 - Server to Client 128 bit NaCl secretbox nonce prefix.
Bytes 048:063 - Server to Client 128 bit SipHash-2-4 key.
Bytes 064:071 - Server to Client 64 bit SipHash-2-4 OFB IV.
Bytes 072:103 - Client to Server 256 bit NaCl secretbox key.
Bytes 104:119 - Client to Server 128 bit NaCl secretbox nonce prefix.
Bytes 120:135 - Client to Server 128 bit SipHash-2-4 key.
Bytes 136:143 - Client to Server 64 bit SipHash-2-4 OFB IV.
数据传输阶段
⼀旦双⽅完成握⼿,他们将分解的应⽤程序数据传输到“数据包”,然后在NaCl crypto_secretbox_xsalsa20poly1305 帧中加密和验证。

帧长度是指后续的secretbox的长度。

为了避免在流中发送可识别的长度字段,通过在OFB模式中对从SipHash-2-4导出的掩码进⾏异或来对帧长度进⾏混淆。

由于接收⽅具有SipHash-2-4密钥和IV,因此通过导出⽤于表⽰长度的掩码并对截断的摘要进⾏异或来获得密码箱的长度来解码长度。

有效载荷长度指的是帧的有效载荷部分的长度,并且不包括填充。

有效载荷长度可能为0,在这种情况下,所有剩余数据都经过验证和解密,但被忽略。

允许的最⼤帧长度为1448字节,每个帧允许传输最多1427个字节的有⽤有效载荷。

NaCl secretbox(Poly1305 / XSalsa20)格式为:
uint8_t [24]前缀(固定)
uint64_t counter(Big endian)
计数器初始化为1,并在每帧上递增。

由于协议被设计为在可靠介质上使⽤,因此会话的两侧都知道前缀和初始计数器值,因此不通过线路传输随机数。

计数器必须不包装,并且会话必须在发送2 ^ 64帧之前终⽌。

如果解密密码箱失败(由于标签不匹配),必须断开连接。

type字段(如果有)⽤于表⽰每个数据包中包含的有效负载类型。

TYPE_PAYLOAD (0x00):整个有效负载将被视为应⽤程序数据。

TYPE_PRNG_SEED (0x01):整个有效载荷将被视为协议多态性PRNG的种⼦。

格式是24字节。

实现应该为了向前兼容性⽽忽略未知的数据包类型,尽管每个帧仍然必须经过⾝份验证和解密。

协议多态性
实现必须实现协议多态性来混淆obfs4流特征。

实现应遵循ScrambleSuit的实现(参见“ScrambleSuit协议规范”,第4节)。

与ScrambleSuit ⼀样,实现可以省略到达间隔时间混淆作为性能权衡。

作为优化,如果它始终在serverResponse主体之后⽴即发送帧,可以将TYPE_PRNG_SEED帧视为serverResponse的⼀部分。

如果这样做,则TYPE_PRNG_SEED帧必须具有0字节的填充,并且必须在ServerMinPadLength为0的情况下⽣成P_S(P_S由[0,8096]字节的随机数据组成)。

然⽽,ClientMinPadLength的计算没有改变(P_C仍包含[85,8128]字节的随机数据)。

相关文档
最新文档