首页 > 其他分享 >【wireguard-go】nat处理上下行数据及checksum计算分析

【wireguard-go】nat处理上下行数据及checksum计算分析

时间:2024-09-02 11:54:45浏览次数:12  
标签:checksum 校验 TCP 上下行 wireguard NAT IP地址 传输层 ICMP

NAT网关功能总结

1. 数据流向

在NAT网关中,数据流通过以下步骤进行处理:
在这里插入图片描述

图示颜色说明

  • 红色箭头:表示加密数据的流向。
  • 蓝色箭头:表示解密数据从 RoutineSequentialReceiver 流向 wg0 接口。
  • 绿色箭头:表示解密数据从 wg0 接口流向 Local Network Stack

详细说明

  • Remote Peer: 另一台服务器或设备发送加密数据到本地NAT网关。
  • RoutineSequentialReceiver: 接收并解密数据,然后将其发送到本地虚拟网卡(wg0)。
  • wg0: TUN接口,负责在本地虚拟网卡与本地网络堆栈之间传输数据。
  • Local Network Stack: 本地应用程序和系统内核处理从wg0接收到的解密数据。
  • RoutineReadFromTUN: 读取本地数据,将其加密并发送回Remote Peer。
2. NAT实现原理细节

NAT网关通过修改数据包中的IP地址(只修改了源 ip)来实现内部网络与外部网络的连接。

  1. IPv4 和 IPv6 处理
    • IPv4 NAT: 修改IPv4包的源IP地址(入站)来实现。更新IP层和传输层(如TCP/UDP/ICMP)的校验和。
    • IPv6 NAT: 类似于IPv4 NAT,需要处理更长的地址(128位)以及ICMPv6包的校验和。
  2. 分片与非分片处理
    • 非分片包: 包含完整的IP和传输层数据。NAT处理时,修改IP地址和校验和,并更新传输层的校验和。
    • 分片包: 分片包只要首片携带传输层。对于第一个分片,除了修改IP地址外,还需要更新传输层校验和。对于后续的分片,只需要更新IP层校验和(因为后续分片没有传输层头部)。
  3. 处理的协议
    • TCP/UDP: 处理传输层的校验和更新。使用增量校验和算法更新传输层校验和,以降低计算开销。
    • ICMP/ICMPv6: 处理网络层的校验和。ICMP/ICMPv6的校验和需要重新计算整个包的内容。
3. 校验和算法

详细的校验和计算方法和原理:

  1. IP层校验和计算: IPv4头部包含一个16位的校验和字段,用于检测数据包头部的传输错误。IPv6头部没有校验和字段,依赖于更高层的协议校验。
  2. 传输层校验和(TCP/UDP)计算: TCP和UDP都包含校验和字段,用于保护整个数据包(包括头部和数据)。校验和计算的范围包括伪头(伪头包括源IP地址、目标IP地址、协议号和TCP/UDP长度)、实际头部以及数据。
  3. ICMP/ICMPv6校验和计算: ICMP和ICMPv6的校验和是其头部和数据的16位校验和。不同于TCP和UDP,ICMP/ICMPv6的校验和不考虑IP地址的变化,因为ICMP的校验和只计算ICMP数据部分。

以下是Go语言实现的校验和计算函数:

// 计算数据包的校验和(通用算法)
func calculateChecksum(data []byte) uint16 {
    var sum uint32
    for i := 0; i < len(data)-1; i += 2 {
        sum += uint32(data[i])<<8 | uint32(data[i+1])
    }
    if len(data)%2 == 1 {
        sum += uint32(data[len(data)-1]) << 8
    }
    for (sum >> 16) > 0 {
        sum = (sum >> 16) + (sum & 0xffff)
    }
    return ^uint16(sum)
}

// 增量更新校验和函数 (基于RFC 1624的增量校验和算法)
func (device *Device) csumReplace4(sum uint16, from, to uint32) uint16 {
    // 将 sum 展开为 32 位并取反
    csum := ^uint32(sum)
    // 减去旧 IP 的贡献
    csum -= (from >> 16) & 0xFFFF
    csum -= from & 0xFFFF
    // 加上新 IP 的贡献
    csum += (to >> 16) & 0xFFFF
    csum += to & 0xFFFF
    // 折叠进位
    csum = (csum & 0xFFFF) + (csum >> 16)
    csum = (csum & 0xFFFF) + (csum >> 16)

    return ^uint16(csum)
}

// 传输层校验和更新函数 (IPv4)
func (device *Device) updateIPv4TransportChecksum(packet []byte, protocol byte, oldIP, newIP uint32) {
	ipHeaderLen := ipv4.HeaderLen

	checksumOffset := 0
	switch protocol {
	case TCP:
		checksumOffset = TCPoffsetChecksum
	case UDP:
		checksumOffset = UDPoffsetChecksum
	default:
		return
	}
	oldL4Checksum := binary.BigEndian.Uint16(packet[ipHeaderLen+checksumOffset : ipHeaderLen+checksumOffset+2])
	newL4Checksum := device.csumReplace4(oldL4Checksum, oldIP, newIP)
	binary.BigEndian.PutUint16(packet[ipHeaderLen+checksumOffset:ipHeaderLen+checksumOffset+2], newL4Checksum)
}

if protocol == ICMP {
		device.updateICMPv4Checksum(packet) // 只处理ICMP数据本身
}
// ICMP校验和更新函数
func (device *Device) updateICMPv4Checksum(packet []byte) {
	ipv4HeaderLen := ipv4.HeaderLen
	icmpv4Offset := ipv4HeaderLen // ICMP偏移量紧随IPv4头部
	// 重新计算整个ICMP数据包的校验和
	packet[icmpv4Offset+ICMPoffsetChecksum] = 0
	packet[icmpv4Offset+ICMPoffsetChecksum+1] = 0
	icmpv4Checksum := device.calculateChecksum(packet[icmpv4Offset:])
	binary.BigEndian.PutUint16(packet[icmpv4Offset+ICMPoffsetChecksum:icmpv4Offset+ICMPoffsetChecksum+2], icmpv4Checksum)
}

4. 校验和计算的重点
  1. IP层校验和计算
    • 仅适用于IPv4。IPv4头部校验和计算是基于整个头部的16位字的和,并对结果取反。
    • csumReplace4从当前校验和中减去旧地址的贡献并添加新地址的贡献来高效地更新校验和。增量更新校验和函数 (based on RFC 1624 增量checksum算法) https://www.rfc-editor.org/rfc/rfc1624
  2. 传输层校验和计算
    • TCP/UDP: 校验和计算涉及伪头(包括源IP地址、目标IP地址、协议号和TCP/UDP长度)以及实际数据,通用算法可以实现,但无法处理分片包的checksum(分片非首片不携带L4信息,整个包重组后才能计算),但是基于RFC 1624的增量校验和算法可以避免该问题,用于更新因IP地址变化而导致的传输层校验和变化。
    • ICMP/ICMPv6: 是基于其头部和数据部分的16位校验和。不同于TCP/UDP,不使用伪头。在处理NAT时,ICMP和ICMPv6的校验和计算仅基于ICMP/ICMPv6的数据部分,不考虑IP地址的变化。在NAT过程中,当IP地址变化时,传输层校验和的更新不影响ICMP校验和。
校验和计算算法解释

IP层和传输层校验和的区别与计算:

  • IP层校验和 用于检测IP头部的传输错误,而不涉及数据部分。IPv4使用校验和,IPv6则没有IP头部校验和。
  • 传输层校验和(TCP/UDP)保护整个数据包,包括伪头、实际头部和数据部分。它确保数据包从源到目的的完整性。

实现校验和更新的原因:
在处理NAT时,IP地址的改变会影响基于IP地址的校验和字段,如TCP/UDP的传输层校验和。为避免重新计算整个数据包的校验和,可以使用增量校验和算法(csumReplace4),只更新地址变化的部分,大大降低了计算开销,提高了效率。

5. NAT网关的流程图和UML图

  1. NAT处理数据包的流程图
    在这里插入图片描述

6. 参考资料

标签:checksum,校验,TCP,上下行,wireguard,NAT,IP地址,传输层,ICMP
From: https://blog.csdn.net/weixin_41578517/article/details/141815900

相关文章

  • Flannel Wireguard 模式
    FlannelWireGuard模式一、环境信息主机IPubuntu172.16.94.141软件版本docker26.1.4helmv3.15.0-rc.2kind0.18.0clab0.54.2kubernetes1.23.4ubuntuosUbuntu20.04.6LTSkernel5.11.5内核升级文档二、安装服务kind配置......
  • MIKroTIK wireguard 在阿里云与云下路由器项目记录
    一、项目背景:公司所有服务器都在阿里云上,需要内网互通。二、项目调研:市场上sd-wan大多分为2派(关于协议之间的对比可再出一个文章进行讨论):1、华为、思科等代表传统利用:Gre,Ipsec,SRv6等数通派(RFC)协议。其特点是:稳定性很好,设备厂家支持广泛无需厂家内部二次适配新协议。2、腾讯......
  • wireguard 安装配置
    1、安装sudoapt-getinstallwireguard2、生成私钥和公钥cd/etc/wireguardumask077wggenkey|teeserver_privatekey|wgpubkey>server_publickeywggenkey|teeclient_privatekey|wgpubkey>client_publickey3、开启内核IP转发echo"net.ipv4.ip_for......
  • 全双工网卡在实际工作中上下行的网速速率是否一致?千兆网卡的同时上下行速率上限是否一
    一直有个问题,就是理论上全双工网卡在运行时上下行的上限速率应该是一致的,但是实际网卡的标识的最高速率是否是指上下行速率之和还是和上下行速率一样。为了解决这个问题,于是拿了两台台式机,分别装有千兆网卡(全双工),并使用六类线网线,两台主机同时向对方拷贝文件,效果如下:结......
  • wireguard安装和使用
    目录ServerInstall&ConfigUbuntu20.0.4installwireguard生成私钥&公钥开启内核IP转发配置文件启动&停止wg-quicksystemctlClientInstall&Config下载ConfigmacOSServerInstall&ConfigUbuntu20.0.4installwireguardsudoaptinstallwireguard生成私钥&公钥Wir......
  • 计算机网络中的检验和(checksum)(包括计算文件的检验和附有c++代码)
    介绍:检验和(checksum),在数据处理和数据通信领域中,用于校验目的地一组数据项的和。它通常是以十六进制为数制表示的形式。如果校验和的数值超过十六进制的FF,也就是255.就要求其补码作为校验和。通常用来在通信中,尤其是远距离通信中保证数据的完整性和准确性。(此引用了检验和的百......
  • 实现CHECKSUM的C语言程序
    什么是校验和?在计算中,校验和是使用算法从较大的数据集创建的小数据,目的是对较大的数据集所做的任何更改都会导致不同的校验和。校验和通常用于验证已传输或存储的数据的完整性,因为数据中的错误或修改可能会导致校验和更改。它们还可用于验证数据的真实性,因为校验和通常是使用......
  • Web举例:防火墙二层,上下行连接交换机的主备备份组网
    Web举例:防火墙二层,上下行连接交换机的主备备份组网介绍了业务接口工作在二层,上下行连接交换机的主备备份组网的Web举例。组网需求如图1所示,两台FW的业务接口都工作在二层,上下行分别连接交换机。FW的上下行业务接口都加入到VLAN10和VLAN20中。现在希望两台FW以主备备份方......
  • wireguard协议参数说明
    简介Wireguard是一款快速现代的VPN,旨在提供易用性和高性能。其协议开源且相对简单,使得代码便于开发和审查。wireguard简单来说是一个三层p2p安全隧道,底层传输使用udp;用编程语言将该协议写成软件叫做实现,常见的有Linux内核中的实现,或者其他用户空间的实现,比如wireguard-go或者wir......
  • PostgreSQL 数据库安全之检验数据块的损坏- data_checksums 参数设置
    默认情况下,数据页不受校验和保护,但可以选择为集群启用这一功能。启用后,每个数据页都包含一个校验和,该校验和在写入该页时更新,并在每次读取该页时进行验证。只有数据页受校验和保护;内部数据结构和临时文件不是。校验和通常在使用initdb初始化集群时启用。还可以在以后的脱......