obfs4 文档翻译

写在前面:根据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
  1. 客户端握手过程如下:

    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)
    
    
    1. 客户端从服务器接收serverResponse
    2. 客户端从serverResponse计算M_S并使用它来定位serverResponse中的MAC_S。 然后计算MAC_S并将其与从服务器接收的值进行比较。 如果找不到M_S或MAC_S值不匹配,客户端必须断开连接。
    3. 客户端通过Elligator 2对应关系反向从Y'导出Y.
    4. 客户端完成ntor握手的客户端,导出256位共享密钥(KEY_SEED)和身份验证标记(AUTH)。 然后,客户端将AUTH的派生值与serverResponse中包含的值进行比较。 如果AUTH值不匹配,客户端必须断开连接。
  2. 服务器握手过程如下:

    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 帧中加密和验证。

1550542204099.png

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

1550542276909.png

由于接收方具有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]字节的随机数据)。

posted @ 2021-04-27 20:04  掉到鱼缸里的猫  阅读(1516)  评论(0编辑  收藏  举报