【性能】如何优化 NAT 性能?

【性能】如何优化 NAT 性能?,第1张

NAT 技术可以重写 IP 数据包的源 IP 或者目的 IP,被普遍地用来解决公网 IP 地址短缺的问题。它的主要原理就是,网络中的多台主机,通过共享同一个公网 IP 地址,来访问外网资源。同时,由于 NAT 屏蔽了内网网络,自然也就为局域网中的机器提供了安全隔离。

你既可以在支持网络地址转换的路由器(称为 NAT 网关)中配置 NAT,也可以在 Linux 服务器中配置 NAT。如果采用第二种方式,Linux 服务器实际上充当的是“软”路由器的角色。

Linux 内核提供的 Netfilter 框架,允许对网络数据包进行修改(比如 NAT)和过滤(比如防火墙)。在这个基础上,iptables、ip6tables、ebtables 等工具,又提供了更易用的命令行接口,以便系统管理员配置和管理 NAT、防火墙的规则。

其中,iptables 就是最常用的一种配置工具。要掌握 iptables 的原理和使用方法,最核心的就是弄清楚,网络数据包通过 Netfilter 时的工作流向。

熟悉 iptables 中的表和链后,我们以 NAPT 的三个分类为例,来具体解读一下:

在使用 iptables 配置 NAT 规则时,Linux 需要转发来自其他 IP 的网络包,所以你 千万不要忘记开启 Linux 的 IP 转发功能 。

Linux 中的 NAT ,基于内核的连接跟踪模块实现。所以,它维护每个连接状态的同时,也会带来很高的性能成本,对网络性能有一定影响。

那么,碰到 NAT 性能问题时,我们又该怎么办呢?

SystemTap  是 Linux 的一种动态追踪框架,它把用户提供的脚本,转换为内核模块来执行,用来监测和跟踪内核的行为。关于它的原理,你暂时不用深究,这里你只要知道怎么安装就可以了。

# yum   -y  install systemtap kernel-devel

# yum info  systemtap 

我们之前使用 tcpdump 抓包的方法,找出了延迟增大的根源。那么今天的案例,我们仍然可以用类似的方法寻找线索。不过,现在换个思路,因为今天我们已经事先知道了问题的根源——那就是 NAT。

回忆一下 Netfilter 中,网络包的流向以及 NAT 的原理,你会发现,要保证 NAT 正常工作,就至少需要两个步骤:

这个脚本,跟踪内核函数 kfree_skb() 的调用,并统计丢包的位置。

文件保存好后,执行下面的 stap 命令,就可以运行丢包跟踪脚本。

这里的 stap,是 SystemTap 的命令行工具:

#  man 1 perf-record

###############################################################

-a, --all-cpus

          System-wide collection from all CPUs (default if no target is specified).

-g

          Enables call-graph (stack chain/backtrace) recording

#################################################################

在 perf report 界面中,输入查找命令 / 然后,在d出的对话框中,输入 nf_hook_slow;最后再展开调用栈,就可以得到下面这个调用图:

不过,你可能还是很好奇,连接跟踪表里,到底都包含了哪些东西?这里的东西,又是怎么刷新的呢?

实际上,你可以用 conntrack 命令行工具 ,来查看连接跟踪表的内容。

# yum provides conntrack

# yum  -y install conntrack-tools

#  yum info   conntrack-tools

#  conntrack -L -o extended | wc -l

#  conntrack -L -o extended | awk '/^.*tcp.*$/ {sum[$6]++} END {for(i in sum) print i, sum[i]}'

#  conntrack -L -o extended | awk '{print $7}' | cut -d "=" -f 2 | sort | uniq -c | sort -nr | head -n 10

因为NAT 基于 Linux 内核的连接跟踪机制来实现,所以在分析 NAT 性能问题时,我们可以先从 conntrack 角度来分析,比如用 systemtap、perf 等,分析内核中 conntrack 的行文;然后,通过调整 netfilter 内核选项的参数,来进行优化。

其实,Linux 这种通过连接跟踪机制实现的 NAT,也常被称为有状态的 NAT,而维护状态,也带来了很高的性能成本。

所以,除了调整内核行为外,在不需要状态跟踪的场景下(比如只需要按预定的 IP 和端口进行映射,而不需要动态映射),我们也可以使用无状态的 NAT (比如用 tc 或基于 DPDK 开发),来进一步提升性能。

案例篇:如何优化 NAT 性能?(上)

https://time.geekbang.org/column/article/83189

案例篇:如何优化 NAT 性能?(下)

https://time.geekbang.org/column/article/83520

 一、概述

1. 什么是NAT

在传统的标准的TCP/IP通信过程中,所有的路由器仅仅是充当一个中间人的角色,也就是通常所说的存储转发,路由器并不会对转发的数据包进行修改,更为确切的说,除了将源MAC地址换成自己的MAC地址以外,路由器不会对转发的数据包做任何修改。NAT(Network Address Translation网络地址翻译)恰恰是出于某种特殊需要而对数据包的源ip地址、目的ip地址、源端口、目的端口进行改写的 *** 作。

2. 为什么要进行NAT

我们来看看再什么情况下我们需要做NAT。

假设有一家ISP提供园区Internet接入服务,为了方便管理,该ISP分配给园区用户的IP地址都是伪IP,但是部分用户要求建立自己的WWW服务器对外发布信息,这时候我们就可以通过NAT来提供这种服务了。我们可以在防火墙的外部网卡上绑定多个合法IP地址,然后通过NAT技术使发给其中某一个IP地址的包转发至内部某一用户的WWW服务器上,然后再将该内部WWW服务器响应包伪装成该合法IP发出的包。

再比如使用拨号上网的网吧,因为只有一个合法的IP地址,必须采用某种手段让其他机器也可以上网,通常是采用

代理服务器的方式,但是代理服务器,尤其是应用层代理服务器,只能支持有限的协议,如果过了一段时间后又有新的服务出来,则只能等待代理服务器支持该新应用的升级版本。如果采用NAT来解决这个问题,

因为是在应用层以下进行处理,NAT不但可以获得很高的访问速度,而且可以无缝的支持任何新的服务或应用。

还有一个方面的应用就是重定向,也就是当接收到一个包后,不是转发这个包,而是将其重定向到系统上的某一个应用程序。最常见的应用就是和squid配合使用成为透明代理,在对http流量进行缓存的同时,可以提供对Internet的无缝访问。

3. NAT的类型

在linux2.4的NAT-HOWTO中,作者从原理的角度将NAT分成了两种类型,即源NAT(SNAT)和目的NAT(DNAT),顾名思义,所谓SNAT就是改变转发数据包的源地址,所谓DNAT就是改变转发数据包的目的地址。

二、原理

在“用iptales实现包过虑型防火墙”一文中我们说过,netfilter是Linux 核心中一个通用架构,它提供了一系列的"表"(tables),每个表由若干"链"(chains)组成,而每条链中可以有一条或数条规则(rule)组成。并且系统缺省的表是"filter"。但是在使用NAT的时候,我们所使用的表不再是"filter",而是"nat"表,所以我们必须使用"-t nat"选项来显式地指明这一点。因为系统缺省的表是"filter",所以在使用filter功能时,我们没有必要显式的指明"-t filter"。

同filter表一样,nat表也有三条缺省的"链"(chains),这三条链也是规则的容器,它们分别是:

PREROUTING:可以在这里定义进行目的NAT的规则,因为路由器进行路由时只检查数据包的目的ip地址,所以为了使数据包得以正确路由,我们必须在路由之前就进行目的NAT

POSTROUTING:可以在这里定义进行源NAT的规则,系统在决定了数据包的路由以后在执行该链中的规则。

OUTPUT:定义对本地产生的数据包的目的NAT规则。

三、 *** 作语法

如前所述,在使用iptables的NAT功能时,我们必须在每一条规则中使用"-t nat"显示的指明使用nat表。然后使用以下的选项:

1. 对规则的 *** 作

加入(append) 一个新规则到一个链 (-A)的最后。

在链内某个位置插入(insert) 一个新规则(-I),通常是插在最前面。

在链内某个位置替换(replace) 一条规则 (-R)。

在链内某个位置删除(delete) 一条规则 (-D)。

删除(delete) 链内第一条规则 (-D)。

2. 指定源地址和目的地址

通过--source/--src/-s来指定源地址(这里的/表示或者的意思,下同),通过--destination/--dst/-s来指定目的地址。可以使用以下四中方法来指定ip地址:

a. 使用完整的域名,如“www.linuxaid.com.cn”

b. 使用ip地址,如“192.168.1.1”

c. 用x.x.x.x/x.x.x.x指定一个网络地址,如“192.168.1.0/255.255.255.0”

d. 用x.x.x.x/x指定一个网络地址,如“192.168.1.0/24”这里的24表明了子网掩码的有效位数,这是 UNIX环境中通常使用的表示方法。

缺省的子网掩码数是32,也就是说指定192.168.1.1等效于192.168.1.1/32。

3. 指定网络接口

可以使用--in-interface/-i或--out-interface/-o来指定网络接口。从NAT的原理可以看出,对于PREROUTING链,我们只能用-i指定进来的网络接口而对于POSTROUTING和OUTPUT我们只能用-o指定出去的网络接口。

4. 指定协议及端口

可以通过--protocol/-p选项来指定协议,如果是udp和tcp协议,还可--source-port/--sport和 --destination-port/--dport来指明端口。

四、准备工作

1. 编译内核,编译时选中以下选项,具体可参看“用iptales实现包过虑型防火墙”一文:

Full NAT

MASQUERADE target support

REDIRECT target support

2. 要使用NAT表时,必须首先载入相关模块:

modprobe ip_tables

modprobe ip_nat_ftp

iptable_nat 模块会在运行时自动载入。

五、使用实例

1. 源NAT(SNAT)

比如,更改所有来自192.168.1.0/24的数据包的源ip地址为1.2.3.4:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 1.2.3.4

这里需要注意的是,系统在路由及过虑等处理直到数据包要被送出时才进行SNAT。

有一种SNAT的特殊情况是ip欺骗,也就是所谓的Masquerading,通常建议在使用拨号上网的时候使用,或者说在合法ip地址不固定的情况下使用。比如

# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

可以看出,这时候我们没有必要显式的指定源ip地址等信息。

2. 目的SNAT(DNAT)

比如,更改所有来自192.168.1.0/24的数据包的目的ip地址为1.2.3.4:

iptables -t nat -A PREROUTING -s 192.168.1.0/24 -i eth1 -j DNAT --to 1.2.3.4

这里需要注意的是,系统是先进行DNAT,然后才进行路由及过虑等 *** 作。

有一种DNAT的特殊情况是重定向,也就是所谓的Redirection,这时候就相当于将符合条件的数据包的目的ip地址改为数据包进入系统时的网络接口的ip地址。通常是在与squid配置形成透明代理时使用,假设squid的监听端口是3128,我们可以通过以下语句来将来自192.168.1.0/24,目的端口为80的数据包重定向到squid监听

端口:

iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.1.0/24 --dport 80

-j REDIRECT --to-port 3128

六、综合例子

1. 使用拨号带动局域网上网

小型企业、网吧等多使用拨号网络上网,通常可能使用代理,但是考虑到成本、对协议的支持等因素,建议使用ip欺骗方式带动区域网上网。

成功升级内核后安装iptables,然后执行以下脚本:

#载入相关模块

modprobe ip_tables

modprobe ip_nat_ftp

#进行ip伪装

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

2. ip映射

假设有一家ISP提供园区Internet接入服务,为了方便管理,该ISP分配给园区用户的IP地址都是伪IP,但是部分用户要求建立自己的WWW服务器对外发布信息。我们可以再防火墙的外部网卡上绑定多个合法IP地址,然后通过ip映射使发给其中某一个IP地址的包转发至内部某一用户的WWW服务器上,然后再将该内部WWW服务器响应包伪装成该合法IP发出的包。

我们假设以下情景:

该ISP分配给A单位www服务器的ip为:

伪ip:192.168.1.100

真实ip:202.110.123.100

该ISP分配给B单位www服务器的ip为:

伪ip:192.168.1.200

真实ip:202.110.123.200

linux防火墙的ip地址分别为:

内网接口eth1:192.168.1.1

外网接口eth0:202.110.123.1

然后我们将分配给A、B单位的真实ip绑定到防火墙的外网接口,以root权限执行以下命令:

ifconfig eth0 add 202.110.123.100 netmask 255.255.255.0

ifconfig eth0 add 202.110.123.200 netmask 255.255.255.0

成功升级内核后安装iptables,然后执行以下脚本:

#载入相关模块

modprobe ip_tables

modprobe ip_nat_ftp

首先,对防火墙接收到的目的ip为202.110.123.100和202.110.123.200的所有数据包进行目的NAT(DNAT):

iptables -A PREROUTING -i eth0 -d 202.110.123.100 -j DNAT --to 192.168.1.100

iptables -A PREROUTING -i eth0 -d 202.110.123.200 -j DNAT --to 192.168.1.200

其次,对防火墙接收到的源ip地址为192.168.1.100和192.168.1.200的数据包进行源NAT(SNAT):

iptables -A POSTROUTING -o eth0 -s 192.168.1.100 -j SNAT --to 202.110.123.100

iptables -A POSTROUTING -o eth0 -s 192.168.1.200 -j SNAT --to 202.110.123.200

这样,所有目的ip为202.110.123.100和202.110.123.200的数据包都将分别被转发给192.168.1.100和192.168.1.200而所有来自192.168.1.100和192.168.1.200的数据包都将分 别被伪装成由202.110.123.100和202.110.123.200,从而也就实现了ip映射


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/6252548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-19
下一篇 2023-03-19

发表评论

登录后才能评论

评论列表(0条)

保存