WireGuard:Golang 实现
前言 本文基于 WireGuard Golang 实现,平台是 Linux,Git 版本是:12269c2 内容 关于收发包 通过创建 TUN 设备,跟系统的网络栈交互。 数据抽象的介绍 关于限速器 WireGuard 在最终进行数据的加密、解密之前,需要通过加密协议 Noise Protocol 基于加密算法协商出对称加密密钥(临时的),这个协商的过程(握手)会涉及到加/解密,哈希运算。为了避免针对响应方 CPU 负载的 DoS 攻击,响应方会根据实时负载情况对握手的请求进行限速,根据请求方的来源 IP 实例化对应的令牌桶(每个来源 IP 对应一个令牌桶),基于令牌桶对握手包进行频率限制。默认的限制策略是每秒钟 20 个握手包,每个时刻(即每纳秒)最多允许 5 个握手包的突发流量。 关于索引表 每个数据包的包头第 4 到第 8 字节会存储一个 32 bits 的无符号整数作为索引,通过索引和索引表(map[uint32]IndexTableEntry),可以查到对应的 Peer、Handshake、Keypair。 索引值本身是个随机值,在: func (table *IndexTable) NewIndexForHandshake(peer *Peer, handshake *Handshake) (uint32, error) 函数中被创建,使用该索引值时使用了两阶段锁(索引表首先基于读锁检查索引是否已被占用,如果该索引未被使用,再基于写锁创建对应的索引条目)。 索引表的作用是? 索引表会在两种场合被使用。 第一种是握手时,WireGuard 初始方创建握手包和消费响应包,完成 Triple-way DH 流程。初始方创建、发送握手包,然后等待、消费响应包,中间有个发送并等待响应的中间状态,这个中间状态的值被存储在 Handshake 实例中,Handshake 作为索引表的值(值是一个结构体,其中一个字段),通过索引和该握手包绑定在一起。当开始消费响应包时,通过响应包头部的接收方 ID(响应方将初始握手包中的发送方 ID 作为接收方 ID 返回),查询索引表从而获得创建握手包时的 Handshake 实例,从而完成整个 Triple-way DH 流程。...