构建一台大容量的NAT服务器
Ippen Yang
(ippen@21cn.com)
1.前言
本文档主要描述如何利用Linux构建一台能力比较强的NAT服务器,并发连接数大约16万,流量200M-300M,如果你需要一个流量更高的NAT设备,请考虑购买专业厂商的设备。
2.许可协议
本文的许可协议遵循GNU Free Document License。协议的具体内容请参见。在遵循GNU Free Document License的基础上,可以自由地转载或发行本文,但请保留本文的完整性。
3.准备工作
CentOS 4.6光盘一套(4张CD)
PC服务器一台,P4 CPU,速度越快越好,256M内存(有没听错?没错! 256M内存就够了,如果资金充裕,可以用512M;如果你用1G内存,那叫浪费),2G或以上的硬盘(可以用CF电子盘)
两个高性能千兆网卡,到目前为止,我测试过几种网卡,Intel的PCI-X服务器网卡,Intel的PCI服务器网卡,Marvell PCI-E,3COM,前面三种网卡都不错,反而是3COM的网卡不行。
网卡最好用两个不同的接口,我现在用的主板,通常都是一张PCI-X网卡,一张PCI-E网卡,这样能避免内部接口速度影响转发效率
4.安装
首先安装CentOS,如果考虑编译内核,安装时记住要安装开发工具,因为要调整系统内核模块的一些参数,要编译系统模块。安装时要注意,不要建立交换区,切记!!!原因后面解释
安装完成后,运行setup,在system service中将不需要用的程序全部停止,基本上只需要保留ssh,iptables,network,snmpd,syslog几个,设置完后重新启动服务器。
编辑/etc/sysctl.conf,查找行“net.ipv4.ip_forward = 0”,然后将这行按下面的内容进行更改,原文件中没有的内容请自己添加
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
net.ipv4.netfilter.ip_conntrack_max = 262144
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 300
net.ipv4.route.max_size=2097152
net.ipv4.tcp_window_scaling=1
kernel.shmmax=268435456
kernel.shmall=268435456
编辑/etc/rc.local如下:
编辑/root/nat如下:
# eth1 is intranet interface
INCOMING=eth0
OUTGOING=eth1
ip addr add 222.222.222.8 dev $OUTGOING
ip addr add 222.222.222.9 dev $OUTGOING
ip addr add 222.222.222.10 dev $OUTGOING
ip addr add 222.222.222.11 dev $OUTGOING
IPPOOL=222.222.222.8-222.222.222.11
iptables -t nat -F
iptables -t nat -A POSTROUTING -s 内部IP地址/子网 -o $OUTGOING -j SNAT --to $IPPOOL
iptables-save -c >/etc/sysconfig/iptables
注意,这里假定互联网IP是222.222.222.8-222.222.222.11(上面黑色字体),请用真正使用的IP范围将黑色字体替换。内网地址也请根据实际环境变更。这个脚本只是NAT用,如果需要增加安全策略,请参考其它的iptables的脚本。
如果服务器的CPU是双核的,编辑/etc/grub.conf
#boot=/dev/sda1
default=1
timeout=1
#splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title CentOS-4 i386 (2.6.9-34.ELsmp)
root (hd0,0)
kernel /boot/vmlinuz-2.6.9-34.ELsmp ro root=LABEL=/
initrd /boot/initrd-2.6.9-34.ELsmp.img
title CentOS-4 i386-up (2.6.9-34.EL)
root (hd0,0)
kernel /boot/vmlinuz-2.6.9-34.EL ro root=LABEL=/
initrd /boot/initrd-2.6.9-34.EL.img
将服务器调整为单核方式运作,为什么?之前与CU的高手讨论过这个问题,也进行过测试,单核方式下运行的NAT效率的确比双核高,也更稳定,所以只用单核,不过现在只能买到双核的CPU,只好浪费一点了。
5.高级配置
由于linux系统内部的一些参数在NAT环境中并不合理,因此在一些情况下需要作些修改,由于涉及内核,建议不熟悉的朋友忽略这个部分。
这部分的调整对系统的优化有限,如果你的并发连接数不是非常高,也可以忽略这个部分。
首先下载linux的内核源文件,请上下载,下载后解包到硬盘中。
系统调整主要是三个默认的参数,参数buckets、ip_conntrack_max和tcp_timeout_established。
参数tcp_timeout_established 位于文件net/ipv4/netfilter/ip_conntrack_proto_tcp.c中,用vi打开文件,查找
unsigned long ip_ct_tcp_timeout_established = 5 DAYS;
原来的tcp_timeout_established是5天,这个数值太大了,很容易造成内存过度占用,导致系统死机,将其改为如下,
unsigned long ip_ct_tcp_timeout_established = 5 MINS;
参数buckets、ip_conntrack_max位于文件net/ipv4/netfilter/ip_conntrack_core.c中,用vi打开文件,查找如下的一段代码,可以看出,系统默认的buckets数值是内存数的1/16384,ip_conntrack_max是buckets的8倍,即时你有大于1G的内存,buckets也只是8192。
/* Idea from tcp.c: use 1/16384 of memory.
On i386: 32MB
* machine has 256 buckets.
>= 1GB machines have 8192 buckets. */
if (hashsize) {
ip_conntrack_htable_size = hashsize;
} else {
ip_conntrack_htable_size
= (((num_physpages << PAGE_SHIFT) / 16384)
/ sizeof(struct list_head));
if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
ip_conntrack_htable_size = 8192;
if (ip_conntrack_htable_size < 16)
ip_conntrack_htable_size = 16;
}
调整可以在这段代码后面直接对buckets和ip_conntrack_max赋值即可
/* Idea from tcp.c: use 1/16384 of memory.
On i386: 32MB
* machine has 256 buckets.
>= 1GB machines have 8192 buckets. */
if (hashsize) {
ip_conntrack_htable_size = hashsize;
} else {
ip_conntrack_htable_size
= (((num_physpages << PAGE_SHIFT) / 16384)
/ sizeof(struct list_head));
if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
ip_conntrack_htable_size = 8192;
if (ip_conntrack_htable_size < 16)
ip_conntrack_htable_size = 16;
}
ip_conntrack_htable_size = 32768;
ip_conntrack_max = 8 * ip_conntrack_htable_size;
参数改好后,编译modules,然后用编译后产生的文件ip_conntrack.ko代替系统中的同名文件(位于/lib/modules/2.6.9……),重新启动即可。
调整内核参数buckets的效果不是特别明显,在初始测试中,使用默认的buckets数值,但并发连接数到12.8万时,CPU的使用率有明显上升,稳定性变差,调整buckets数值后并发连接数能到16万,但流量上升不多,所以对系统编译不熟悉的朋友不必考虑这个方法,增加一台服务器就是了。
常见问题
Q.服务器空载时速度很快,但一加载流量就有明显的丢包,并且只有几兆流量,但实际流量远远不止几兆
A.请检查网线以及交换机端口、linux服务器网卡端口的全双工、半双工状态,用ethertool,这个现象非常明显和常见,通常都是全双工、半双工匹配问题。
Q.我的网内有2千用户,要什么样的服务器才能正常运作?
A.其实完全不必关心又多少用户,关键是系统的并发连接数,系统并发连接数最好不要超过16万并发连接数,超过了系统会有些不稳定,所以建议连接数高的用户采用增加服务器的方式。
目前的优化只能到这个程度了,如果有更好的优化方案,我会第一时间高诉各位的。
Q.使用更快的CPU和更大的内存能否提高并发连接数?
A.开始我也这样认为,但实际测试中,发现这个观点完全错误,NAT使用的内存量比较固定,我监测的结果,基本上在200M左右,所以在开始建议大家买的内存也是256M而已,更快的CPU对NAT是有帮助,但随着并发连接数的增加,NAT的效率越来越低,反而效果更差。
Q.是否一定要将互联网IP设置到OUT网卡上?
A.不一定,但这样设置,NAT服务器的CPU利用率会明显降低,强烈建议这样配置。
Q.为什么不使用交换区?
A.这个服务器只是用于NAT,不是代理服务器,为了提高NAT转发速率,就要完全避免读写硬盘,而物理内存使用完了后,系统就会使用交换区来存储数据,整个服务器速度就会被拖慢,直至死机。因此在这里完全不要使用交换区。
Q.其他linux版本能否使用?
A.Sure,推荐CentOS主要是方便不熟悉Linux系统的朋友,避免朋友们盲目地找不同的linux版本测试。这里仍然强调一下,使用2.6的内核,不要使用2.4内核,2.6的内核能查看并发连接数,并且NAT效率比2.4高。
Q.为什么我的NAT服务器不行?
A.这个问题很复杂,我现在回答不了^_^,请上CU的论坛发帖子。发邮件给我的话,就要有点耐心等回复了
感谢
所有在CU的朋友,特别是Platinum和JohnBull,给我提出很多有用的参考意见。