几种设计

ipsec: 基于 Linux transform (“xfrm”) layer, 在内核中通过structure参数判断, user space 中有个后台进程负责更新stucture(基于 key交换的结果, 通常是 IKEv2), 这就复杂了很多, 并且因为分层的抽象, 防火墙规则 配置也很复杂 wireguard: 使用了虚拟的interface(比如wg0), 使用简单, 状态管理透明 基于 openssh 的思维, 支持 base64 编码 加密: Trevor Perrin’s Noise, 没有用 tls 在 3层工作: ip. 支持 ipv6 <-> ipv4 openvpn: tls + user space tun/tap (类似wireguard), 性能低, user/kernel space 多次copy, 需要 long-lived daemon, 但是因为基于tls, 会导致 很多问题

wireguard 设计

常规交互:

  1. 1-RTT key exchange handshake
  2. 加密数据传输
  • 使用 12-byte TAI64N [7] timestamp, 通过每次使用更大的timestamp 避免了 回放攻击
  • 支持 预共享 加密key, 避免 量子计算的攻击
  • 在高负载下, 支持 cookie reply, 延迟握手时间, 第一次握手返回cookie, 到期后基于cookie 进行握手

timer & Stateless UX

  1. 传输的消息数量有限制, 超过后会重新分发对称key, 创建新的session
  2. Rekey-After-Time 时间后会重新创建新的session, 分发新的对称key
  3. handshake initiation 重传, 第一条用户消息会触发 handshake initiation. 但是存在 Rekey-Timeout 或者 消息达到限制, 需要重新构建 handshake initiation
  4. 通过心跳保活
  5. 在高负载下的 使用 cookie 替换 handshake initiation/response, 并且cookie 是延迟一段时间后( Rekey-Timeout ) 再进行 handshake initiation

linux kernel

目标: 简单快速, 少于 4k 行; 速度快, 能够匹敌 IPSec; 对于incoming packets 更轻量的资源分配; kernel 亲和; 生产可用

  1. Queuing System: 针对大packet(super packet, 超过MTU)会拆包发送, 并且是立刻全部发送 以增加缓存命中率 (指令、分支预测维度); 对于handshake场景, 会将packet所在队列的所有元素 整个作为大包(super packet, 只有发消息的时候, 才会建立会话, 发送 handshake initiation); 整个packet的加密、解密都是 就地(inplace) 完成, 以及通过 sendfile 的 user space 数据和文件, 基于 zero-copy/零拷贝 的 super packet queuing system. 除此之外, 可以选择打开 generic segmentation offloadhardware checksum offloading、scatter gather I/O, 主要是为了说 将 super packet 直接提交给 wireguard处理, 因为拆包后 缓存命中率会显著降低

  2. Softirq & Parallelism: xfrm 不需要在 softirq 进行 密码操作, wifi 的 无线 WPA 加密 用的 mac802111 也会在 softirq 做加密, 内核的 padata 支持并行的 加密解密 提升 CPU 利用率, 比较有意思的是, padata 支持有序步骤的 并行操作. 值得注意的是, handshake initiation/response、cookie reply 都是在分散的、并行的 低优worker thread 上执行, 避免洪水攻击(ECDH非常慢)

  3. RTNL-based Virtual Interface & Containerization: 通过 RTNL 和 link 交互, RTNL 支持了 跨 network interface 的 virtual interface

  4. linux 支持了两种路由表实现: LC-trie(IPV4) 和 radix trie(IPv6), 内部都用了 FIB 路由层. wireguard 通过 radix trie 实现了 加密路由表, 通过 RCU 实现无所查询. hash 函数使用 extremely fast SipHash2-4 [1] MAC. 直接使用 加密API 而不是依赖系统的, 可以降低 heap/stack 依赖, 在 各种intel/ARM/MIPS 上使用 ChaCha20Poly1305 加密, 最快实现取决于硬件. 基于 Netfilter hashlimit 实现限流

  5. 另一种方式是 隔离wireguard interface 和 routing table, 区分出两种 namespace, 避免了全部的查询, 以及 明文攻击

  6. 为了更加通用, 后续会在用户态 基于 tun 实现, 语言主要是 rust go haskell, 目前rust 推荐 cloudflare 的实现: https://github.com/cloudflare/boringtun

性能

wireguard 性能最好.

ipsec中, 目前 拥有 AES-NI 加速的 AES-GCM 套件 是比 ChaCha20Poly1305 快的, 但是后面会有 基础设施 加速 ChaCha20Poly1305, 以及 在没有 AES 基础场景下, ChaCha20Poly1305 还是首选

补充

  • siphash: 高性能、安全, 针对短消息进行了高速优化,

  • TAI 64: 基于 铯原子 的 国际实时标准

参考