免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9257 | 回复: 13
打印 上一主题 下一主题

[网络管理] 有关ip_conntrack_max问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-12 11:05 |只看该作者 |倒序浏览
机器原来的ip_conntrack_max是65536,修改/proc/sys/net/ipv4/netfilter/ip_conntrack_max  设置成1048576后,后来在机器运行中临时用iptables 添加了一个简单的snat规则,ip_conntrack_max竟然恢复到默认值65536 了。请问是不是iptables命令会更改ip_conntrack_max的值?怎么才能避免这个情况?谢谢

论坛徽章:
0
2 [报告]
发表于 2008-09-12 13:09 |只看该作者
-允许的最大跟踪连接条目,在这篇文档中我们叫作CONNTRACK_MAX
-存储跟踪连接条目列表的哈西表的大小,在这篇文档中我们叫做HASHSIZE(下面是这个结构的描述)

CONNTRACK_MAX是在内核内存中netfilter可以同时处理的“任务”(连接跟踪条目)。

一个跟踪连接的条目是存储在一个链接起来的列表的一个节点上,每个列表都是一个哈西表的元素。因此每个哈西表的条目(也叫一个桶-bucket)包含了一个链接起来的跟踪连接条目。
要访问一个特定包的跟踪连接条目,内核必须:
-针对一个包中的已经定义的一些字符计算哈西值。这是一个不间断的计算。
  这个哈西值就会被当作哈西表的索引来使用,而跟踪连接条目的列表就存储在这里。
-反复的查看链接列表中的跟踪连接条目以找到匹配的那一个。
  这是一个耗资源的操作,依赖于列表的大小(也依赖于列表中被操作的跟踪连接条目的位置)。

哈西表包含了HASHSIZE大小的链接条目。当条目满的时候(总的跟踪连接条目数达到了CONNTRACK_MAX),理想状态下,每个列表(在最优化的条件下)将包含大约CONNTRACK_MAX/HASHSIZE的条目数。

不管你是否有连接,哈西表都将占用一个固定大小的非交换内核内存。但是最大连接跟踪条目会检测最多可以存储多少条目(globally into the
linked lists),也就是说他们最多可以占用多少的内核内存。

这篇文档将给你一些关于为了达到最好的netfilter conntracking/NAT系统性能,如何调优HASHSIZE和CONNTRACK_MAX值的提示。

CONNTRACK_MAX和HASHSIZE的默认值
============================================

一般来说,CONNTRACK_MAX和HASHSIZE都会设置在“合理”使用的值上,依据可使用的RAM的大小来计算这个值。

CONNTRACK_MAX的默认值
------------------------------

在i386架构上,CONNTRACK_MAX = RAMSIZE (以bytes记) / 16384 =
RAMSIZE (以MegaBytes记) * 64,
因此,一个32位的带512M内存的PC在默认情况下能够处理512*1024^2/16384 = 512*64 = 32768个并发的netfilter连接。

但是真正的公式是:
CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (x / 32)
这里x是指针的bit数,(例如,32或者64bit)

请注意:
-默认的CONNTRACK_MAX值不会低于128
-对于带有超过1G内存的系统,CONNTRACK_MAX的默认值会被限制在65536(但是可以手工设置成更大的值)

HASHSIZE的默认值
-------------------------

通常,CONNTRACK_MAX = HASHSIZE * 8。这意味着每个链接的列表平均包含8个conntrack的条目(在优化的情况并且CONNTRACK_MAX达到的情况下),每个链接的列表就是一个哈西表条目(一个桶)。

在i386架构上,HASHSIZE = CONNTRACK_MAX / 8 =
RAMSIZE (以bytes记) / 131072 = RAMSIZE (以MegaBytes记) * 8。
举例来说,一个32位、带512M内存的PC可以存储512*1024^2/128/1024 =
512*8 = 4096 个桶(链接表)

但是真正的公式是:
HASHSIZE = CONNTRACK_MAX / 8 = RAMSIZE (以bytes记) / 131072 / (x / 32)
这里x是指针的bit数,(例如,32或者64bit)

请注意:
-默认HASHSIZE的值不会小于16
-对于带有超过1G内存的系统,HASHSIZE的默认值会被限制在8192(但是可以手工设置成更大的值)

读取CONNTRACK_MAX和HASHSIZE
==================================

现在通过/proc文件系统我们可以在运行时读取CONNTRACK_MAX的值。

在Linux kernel 2.4.23版本前,使用:
# cat /proc/sys/net/ipv4/ip_conntrack_max

在Linux kernel 2.4.23版本后,使用:
# cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max
  (旧的 /proc/sys/net/ipv4/ip_conntrack_max是不建议使用的!)

当前的HASHSIZE总是可以在syslog信息中找到(对任何一个内核版本),桶(也就是HASHSIZE)的数目是在ip_conntrack初始化的时候显示出来的。
对于linux内核2.4.24以后,当前的HASHSIZE值可以在运行时使用下面的命令读取:
# cat /proc/sys/net/ipv4/netfilter/ip_conntrack_buckets


修改CONNTRACK_MAX和HASHSIZE
====================================

默认的CONNTRACK_MAX和HASHSIZE的值都会因主机的不同而不同,但你可以在只做防火墙的高负载的系统上增加他们。
因此CONNTRACK_MAX和HASHSIZE值如果需要的话可以手工更改。

读取桶是一个连续性的操作(我们的兴趣在于得到一个哈西列表),请记得内核需要不停的遍历一个链接的列表去查找一个跟踪连接条目。因此一个链接列表(CONNTRACK_MAX/HASHSIZE的值在优化的状态下并且达到上限)的平均值不能设置太大。这个比值默认值是8(当值是自动计算的时候)。
在系统有足够的内存并且性能真的很重要的时候,你可以试着使平均值是一个跟踪连接条目配一个哈西桶,这意味着HASHSIZE = CONNTRACK_MAX。


设置CONNTRACK_MAX
---------------------

跟踪连接的条目是存储在链接的表中的,因此最大的跟踪链接条目(CONNTRACK_MAX)可以很容易的动态调整。

linux内核2.4.23之前,使用:
# echo $CONNTRACK_MAX > /proc/sys/net/ipv4/ip_conntrack_max

linux内核2.4.23之后,使用:
# echo $CONNTRACK_MAX > /proc/sys/net/ipv4/netfilter/ip_conntrack_max

这里$CONNTRACK_MAX是一个整数。

设置HASHSIZE
----------------

因为数学上的原因,哈西表占有固定的大小。因此HASHSIZE必须在哈西表被创建和开始填充之前就确定。

在linux内核2.4.21之前,必须使用素数作为哈西表的大小,而且要保证这个哈西表能够有效并通用。非素数的奇数或者其他的数值都是强烈不推荐使用的,因为这样哈西的分配不能达到最优化的状态。

从linux内核2.4.21(还有2.6内核)跟踪连接使用jenkins2b算法,这样就可以使用所有的数值,但是使用2^n次方运作的最有效。


如果netfilter的跟踪连接是被编译进内核中的,哈西表的大小就可以在编译的时候设置,或者(2.6内核之后)可以作为一个启动选项ip_conntrack.hashsize=$HASHSIZE。

如果netfilter的跟踪连接是编译成一个模块,哈西表的大小可以在加载模块的时候设置,使用下面的命令:
# modprobe ip_conntrack hashsize=$HASHSIZE


详细可参见http://www.wallfire.org/misc/netfilter_conntrack_perf.txt

论坛徽章:
0
3 [报告]
发表于 2008-09-12 13:21 |只看该作者
谢谢楼上的,我想问的是iptables命令会把ip_conntrack_max恢复到默认值,怎么才能彻底解决?是重新编译内核吗?

论坛徽章:
0
4 [报告]
发表于 2008-09-12 13:37 |只看该作者
哎。楼主还是没仔细看
方法一:
echo 262144 > /proc/sys/net/ipv4/netfilter/ip_conntrack_max
重新启动或切换系统级别即失效
可以写到/etc/rc.d/rc.local

方法二:
或是在 /etc/sysctl.conf 加入: net.ipv4.ip_conntrack_max =数值
重新启动有效

或使用指令: sysctl -w net.ipv4.ip_conntrack_max=数值
调用iptables前执行有效,也可以写到/etc/rc.d/rc.local

方法三:
在grub(或者lilo)的启动项中添加这个参数
kernel /boot/vmlinuz-2.4.18-3 ro root=/dev/hda1 hdc=ide-scsi 增加ip_conntrack.hashsize=数值

[ 本帖最后由 剑次狼 于 2008-9-12 13:40 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2008-09-12 13:45 |只看该作者
在其他的机器上试验了一下,好像ip_conntrack_max 正常。不知道为什么上面那个机器会发生恢复ip_conntrack_max 默认值的情况。郁闷……

论坛徽章:
0
6 [报告]
发表于 2008-09-12 13:46 |只看该作者
谢谢,我是用楼上的第一个方法做的。

论坛徽章:
0
7 [报告]
发表于 2008-09-12 13:50 |只看该作者
原帖由 zhou_rock 于 2008-9-12 13:45 发表
在其他的机器上试验了一下,好像ip_conntrack_max 正常。不知道为什么上面那个机器会发生恢复ip_conntrack_max 默认值的情况。郁闷……

我也用测试机测试了。加了规则都没变化。
有可能是你那机器内存溢出了自动恢复了?

你还是用别的方法设置重起下吧再看看。

论坛徽章:
0
8 [报告]
发表于 2008-09-12 13:56 |只看该作者
另外用# modprobe ip_conntrack hashsize=$HASHSIZE  ,重新启动机器后(测试机),ip_conntrack_max自动修改成了$HASHSIZE×8的数了。是不是这个方法更好一些。

论坛徽章:
0
9 [报告]
发表于 2008-09-12 21:14 |只看该作者
本来测下modprobe ip_conntrack hashsize的效果,结果测试机出问题了,

论坛徽章:
0
10 [报告]
发表于 2008-09-13 07:23 |只看该作者
原帖由 zhou_rock 于 2008-9-12 13:56 发表
另外用# modprobe ip_conntrack hashsize=$HASHSIZE  ,重新启动机器后(测试机),ip_conntrack_max自动修改成了$HASHSIZE×8的数了。是不是这个方法更好一些。

int max_factor = 8;
int ret;

/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
* machine has 512 buckets. >= 1GB machines have 16384 buckets. */

if (!nf_conntrack_htable_size) {
        nf_conntrack_htable_size
                = (((num_physpages << PAGE_SHIFT) / 16384)
                   / sizeof(struct hlist_head));
        if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
                nf_conntrack_htable_size = 16384;
        if (nf_conntrack_htable_size < 32)
                nf_conntrack_htable_size = 32;

        /* Use a max. factor of four by default to get the same max as
         * with the old struct list_heads. When a table size is given
         * we use the old value of 8 to avoid reducing the max.
         * entries. */

        max_factor = 4;
}
nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
                                          &nf_conntrack_vmalloc);
if (!nf_conntrack_hash) {
        printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
        goto err_out;
}

nf_conntrack_max = max_factor * nf_conntrack_htable_size;

printk("nf_conntrack version %s (%u buckets, %d max)\n",
       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
       nf_conntrack_max);


另外,conntrack_max 过大,超过了内存限制,sk_buff 结构又比较庞大的话,当连接数过多时会造成内核内存移除而导致系统崩溃
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP