1、NAT原理

NAT技术可以重写 IP 数据包的源 IP 和目的 IP。 网络中的多台主机。通过共享同一个公网 IP 地址,来访问外网资源。同时,由于 NAT 屏蔽了内网网络,就为局域网中的机器提供了安全隔离。
NAT的主要目的,是实现地址转换。根据实现方式的不同,分为:

  • 静态NAT:即内网 IP 和公网 IP 是一对一的永久映射关系
  • 动态NAT:即内网 IP 和公网 IP 池中,动态选择一个进行映射
  • 网络地址端口转换 NAPT(Network Address and Port Translation):即把内网 IP 映射到公网 IP 的不同端口上,让多个内网 IP 可以共享同一 IP 地址。

NAPT 是流行的 NAT 类型。根据转换方式不同,NAPT 分为三类:

  • 源地址转换 SNAT:即目的地址不变,只替换源 IP 或 源端口。SNAT 主要用于,多个内网 IP 共享同一个公网 IP ,来访问外网资源的场景。
  • 目的地址转换 DNAT:即源 IP 保持不变,只替换目的 IP 或者 目的端口。DNAT 主要通过公网 IP 的不同端口号,来访问内网的多种服务,同时会隐藏后端服务器的真实 IP 地址。
  • 双向地址转换(SNAT+DNAT):当接收到网络包时,执行DNAT,把目的 IP 转换为 内网 IP;在发送网络包时,执行 SNAT,把源 IP 替换为 外部 IP。

双向地址转换,就是外网IP 和内网IP 的一对一的映射关系,常用在虚拟环境中,为虚拟机分配浮动的公网IP地址。

2、理解

假设:

  • 内网服务器的内网 IP地址是:192.168.0.2
  • NAT 网管中的公网IP地址是:100.100.100.100
  • 要访问的目的服务器 baidu.com 的地址为:123.125.115.110

SNAT 和 DNAT 的过程,如图所示
image.png

  1. 当服务器器访问 baidu.com 时,NAT 网关会把源地址,从服务器的内网IP 192.168.0.2 替换成公网 IP 地址 100.100.100.100,然后才发送给 baidu.com。
  2. 当 baidu.com 发回响应包时,NAT 网关又会把目的地址,从公网 IP 100.100.100.100 替换成服务器内网IP 192.168.0.2,然后再发送给内网中的服务器。

    3、iptables 与 NAT

    Linux 内核提供 Netfilter 框架,允许对网络数据包进行修改(如 NAT)和过滤(如 防火墙)。在这个基础上,iptables、ip6tables、ebtables 等工具,又提供了更易用的命令行接口,以便系统管理员配置和管理 NAT、防火墙的规则。
    image.png
    在这张图中,绿色背景的方框,表示表(table),用来管理链。Linux 支持 4 种表,包括 filter(用于过滤)、nat(用于 NAT)、mangle(用于修改分组数据) 和 raw(用于原始数据包)等。
    跟 table 一起的白色背景方框,则表示链(chain),用来管理具体的 iptables 规则。每个表中可以包含多条链,比如:
  • filter 表中,内置 INPUT、OUTPUT 和 FORWARD 链;
  • nat 表中,内置 PREROUTING、POSTROUTING、OUTPUT 等。

灰色的 conntrack,表示连接跟踪模块。它通过内核中的连接跟踪表(也就是哈希表),记录网络连接的状态,是 iptables 状态过滤(-m state)和 NAT 的实现基础。

iptables 的所有规则,就会放到这些表和链中,并按照图中顺序和规则的优先级顺序来执行。

要实现 NAT 功能,主要是在 nat 表进行操作。而 nat 表内置了三个链:

  • PREROUTING,用于路由判断前所执行的规则,比如,对接收到的数据包进行 DNAT。
  • POSTROUTING,用于路由判断后所执行的规则,比如,对发送或转发的数据包进行 SNAT 或 MASQUERADE。
  • OUTPUT,类似于 PREROUTING,但只处理从本机发送出去的包。

    1、SNAT

    SNAT 需要在 nat 表的 POSTROUTING 链中配置。常用两种方式来配置它。
    第一种方法,是为一个子网统一配置 SNAT,并由 Linux 选择默认的出口 IP。这实际上就是经常说的 MASQUERADE:
    1. iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -j MASQUERADE
    第二种方法,是为具体的 IP 地址配置 SNAT,并指定转换后的源地址:
    1. iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100

    2、DNAT

    DNAT 需要在 nat 表的 PREROUTING 或者 OUTPUT 链中配置,其中, PREROUTING 链更常用一些(因为它还可以用于转发的包)。
    1. iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2

    3、双向地址转换

    同时添加 SNAT 和 DNAT 规则,为公网 IP 和内网 IP 实现一对一的映射关系,即:
    1. iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 100.100.100.100
    2. iptables -t nat -A PREROUTING -d 100.100.100.100 -j DNAT --to-destination 192.168.0.2
    在使用 iptables 配置 NAT 规则时,Linux 需要转发来自其他 IP 的网络包,需要开启 Linux 的 IP 转发功能。
    1. # 如果是 1,表示开启了 IP 转发
    2. sysctl net.ipv4.ip_forward
    image.png
    开启配置
    1. sysctl -w net.ipv4.ip_forward=1

    4、NAT性能

    NAT 基于 Linux 内核的连接跟踪机制来实现。所以,在分析 NAT 性能问题时,可以先从 conntrack 角度来分析,比如用 systemtap、perf 等,分析内核中 conntrack 的行文;然后,通过调整 netfilter 内核选项的参数,来进行优化。
    Linux 这种通过连接跟踪机制实现的 NAT,也常被称为有状态的 NAT,而维护状态,也带来了很高的性能成本。
    除了调整内核行为外,在不需要状态跟踪的场景下(比如只需要按预定的 IP 和端口进行映射,而不需要动态映射),也可以使用无状态的 NAT (比如用 tc 或基于 DPDK 开发),来进一步提升性能。