Linux上的快速路由和NAT

随着IPv4地址耗尽,许多电信运营商面临着使用地址转换来组织其客户对网络的访问的需求。在本文中,我将告诉您如何在商用服务器上获得电信级NAT级别的性能。

一点历史


耗尽IPv4地址空间的话题不再是新话题。在某个时候,等待名单出现在RIPE中,然后有一些交易所,他们在这些交易所上交换地址块并完成租金交易。逐渐地,电信运营商开始通过地址和端口的转换来提供Internet访问服务。某人没有设法获得足够的地址来给每个订户一个“白色”地址,而某人通过拒绝在二级市场上购买地址而开始省钱。网络设备制造商支持这一想法,因为此功能通常需要其他扩展模块或许可证。例如,在MX路由器阵容中使用瞻博网络(最新的MX104和MX204除外),NAPT可以在单独的MS-MIC服务卡上执行,Cisco ASR1k需要GN许可证,在Cisco ASR9k上,有一个单独的A9K-ISM-100模块和一个A9K-CGN-LIC许可证。一般来说,享乐要花很多钱。

iptables


执行NAT的任务不需要专门的计算资源;例如,安装在任何家庭路由器中的通用处理器都可以解决该问题。从运营商的角度来看,可以使用运行FreeBSD(ipfw / pf)或GNU / Linux(iptables)的商用服务器解决此问题。我们不会考虑FreeBSD,因为 我拒绝长时间使用此操作系统,因此让我们关注GNU / Linux。

打开地址转换一点都不困难。首先,您需要在nat表的iptables中编写规则:

iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -j SNAT --to <pool_start_addr>-<pool_end_addr> --persistent

操作系统将加载nf_conntrack模块,该模块将监视所有活动的连接并执行必要的转换。有几个微妙之处。首先,由于我们是在运营商规模上谈论NAT,因此有必要收紧超时时间,因为使用默认值,转换表的大小将迅速增长到灾难性的值。以下是我在服务器上使用的设置的示例:

net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 8192 65535

net.netfilter.nf_conntrack_generic_timeout = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 600
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 45
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_icmpv6_timeout = 30
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_events_retry_timeout = 15
net.netfilter.nf_conntrack_checksum=0

其次,由于转换表的默认大小不是为在电信运营商的条件下工作而设计的,因此必须增加它:

net.netfilter.nf_conntrack_max = 3145728

还需要增加存储所有转换的哈希表的存储桶数(这是nf_conntrack模块的一个选项):

options nf_conntrack hashsize=1572864

经过这些简单的操作,即可获得一个完全正常的构造,该构造可以将大量客户端地址转换为外部池。但是,此解决方案的性能很差。在我第一次尝试将GNU / Linux用于NAT时(大约在2013年),我能够以每服务器0.8Mpps的速度(Xeon E5-1650v2)获得大约7Gbit / s的性能。自那时以来,在GNU / Linux内核网络堆栈中进行了许多不同的优化,同一硬件上的一台服务器的性能在1.8-1.9 Mpps(这些是极限值)下已几乎提高到18-19 Gbit / s,但是对于流量的需求,由单个服务器处理,增长速度更快。结果,开发了适用于不同服务器的负载平衡方案,但这增加了设置的复杂性,服务并保持所提供服务的质量。

耐用品


如今,在软件“数据包传输”中,DPDK和XDP的使用已成为一种流行的方向。关于此主题的文章很多,进行了许多不同的演示,出现了商业产品(例如,来自VasExperts的SKAT)。但是,在电信运营商的程序员资源有限的情况下,在这些框架的基础上削减某种“份额”是很成问题的。将来要操作这种解决方案将更加困难,特别是,有必要开发诊断工具。例如,带有DPDK的常规tcpdump不能正常工作,它也不会“看到”使用XDP发送回线路的数据包。在所有关于将数据包转发输出到用户空间的新技术的讨论中,报告文章都没有引起注意。iptables维护者Pablo Neira Ayuso,致力于发展nftable中的流量分流。让我们更详细地研究这种机制。

主要思想是,如果路由器在流的两侧传递了一个会话的数据包(TCP会话进入ESTABLISHED状态),则无需通过所有防火墙规则传递此会话的后续数据包,因为通过将数据包进一步传送到路由,所有这些检查将在同一端。是的,实际上不需要选择路由-我们已经知道在该会话中哪个接口和哪个主机应该转发数据包。仅保留此信息并将其用于数据包处理的早期阶段进行路由。执行NAT时,有必要另外保存有关由nf_conntrack模块转换的地址和端口的更改的信息。是的,当然,在这种情况下,iptables中的各种聚合器和其他信息统计规则将停止工作,但是作为单独的独立NAT或例如边界的任务的一部分,这并不是很重要,因为服务是跨设备分布的。

组态


要使用此功能,我们需要:

  • 使用新的内核。尽管该功能本身出现在4.16内核中,但相当一段时间以来,它还是“原始的”,经常被称为内核恐慌。LTS内核4.19.90和5.4.5于2019年12月发布时,一切都趋于稳定。
  • 使用较新版本的nftables以nftables格式重写iptables规则。在0.9.0版中正常工作

如果第一段在原则上说清楚,最主要的是不要忘记在组装过程中将模块包括在配置中(CONFIG_NFT_FLOW_OFFLOAD = m),那么第二段需要说明。nftables规则与iptables中的描述完全不同。该文档揭示了几乎所有的要点,还有从iptables到nftables的特殊规则转换器因此,我仅举一个设置NAT和流量卸载的示例。一个小例子:<i_if>,<o_if>是流量通过的网络接口,实际上可以有两个以上。<pool_addr_start>,<pool_addr_end>-“白色”地址范围的开始和结束地址。

NAT配置非常简单:

#! /usr/sbin/nft -f

table nat {
        chain postrouting {
                type nat hook postrouting priority 100;
                oif <o_if> snat to <pool_addr_start>-<pool_addr_end> persistent
        }
}

流量卸载有点复杂,但可以理解:
#! /usr/sbin/nft -f

table inet filter {
        flowtable fastnat {
                hook ingress priority 0
                devices = { <i_if>, <o_if> }
        }

        chain forward {
                type filter hook forward priority 0; policy accept;
                ip protocol { tcp , udp } flow offload @fastnat;
        }
}

实际上,这就是整个设置。现在,所有TCP / UDP流量都将进入fastnat表,并且处理速度将大大提高。

结果


为了清楚地知道这是“快得多”,我将在两个相同硬件的真实服务器(至强E5-1650v2)上使用相同的Linux内核,但在iptables(NAT4)和nftable(NAT5)。



屏幕截图中没有每秒的数据包图,但是在这些服务器的负载配置文件中,平均数据包大小约为800字节,因此值高达1.5Mpps。如您所见,具有nftable的服务器的性能裕度非常大。当前,该服务器以3Mpps的速度处理高达30Gbit / s的速度,并且显然能够在没有可用CPU资源的情况下遇到40Gbps网络的物理限制。

我希望这些材料对试图提高服务器性能的网络工程师有用。

All Articles