Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 626|回复: 0

nf_conntrack: table full, dropping packet 问题排查和解决

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-9-1 10:58:09 | 显示全部楼层 |阅读模式

     

    nf_conntrack模块在kernel 2.6.15(2006-01-03发布) 被引入,支持ipv4和ipv6,取代只支持ipv4的ip_connktrack,用于跟踪连接的状态,供其他模块使用。

     

    最常见的使用场景是 iptables 的 nat 和 state 模块:

     

    • nat 根据转发规则修改IP包的源/目标地址,靠nf_conntrack的记录才能让返回的包能路由到发请求的机器。
    • state 直接用 nf_conntrack 记录的连接状态(NEW/ESTABLISHED/RELATED/INVALID)来匹配防火墙过滤规则。

     

     

     

    iptables
     

     

     

     

    nf_conntrack用1个哈希表记录已建立的连接,包括其他机器到本机、本机到其他机器、本机到本机(例如 ping 127.0.0.1也会被跟踪)。

     

    如果连接进来比释放的快,把哈希表塞满了,新连接的数据包会被丢掉,此时netfilter变成了一个黑洞,导致拒绝服务。 这发生在3层(网络层),应用程序毫无办法。

     

    各发行版区别:

     

    • CentOS (7.3) 默认加载该模块
    • Ubuntu (16.10+) 和 Kali Linux (2016.1+) 默认不加载,不会有这问题

     

    为什么需要这种状态跟踪机制呢?比如你的80端口开启,而你的程序被植入反弹式木马,导致服务器主动从80端口向外部发起连接请求,这个时候你怎么控制呢。关掉80端口,那么你的网站也无法正常运行了。

    但有了连接跟踪你就可以设置只允许回复关于80端口的外部请求(ESATBLISHED状态),而无法发起向外部的请求(NEW状态)。所以有了连接跟踪就可以做到在这种层面上的限制,慢慢往下看就明白了各状态的意义。

    在内核中由Netfilter的特定框架做的连接跟踪称作conntrack(connection tracking)。conntrack可以作为模块安装,也可以作为内核的一部分。大部分情况下,我们想要也需要更详细的连接跟踪。

    conntrack中有许多用来处理TCP,UDP或ICMP协议的部件。这些模块从数据包中提取详细的、唯一的信息,因此能保持对每一个数据流的跟踪。这些信息也告知conntrack流当前的状态。

    例如,UDP流一般由他们的目的地址、源地址、目的端口和源端口唯一确定。

    在以前的内核里,我们可以打开或关闭重组功能。然而连接跟踪被引入内核后,这个选项就被取消了。因为没有包的重组,连接跟踪就不能正常工作。现在重组已经整合入conntrack,并且在conntrack启动时自动启动。不要关闭重组功能,除非你要关闭连接跟踪。除了本地产生的包由OUTPUT链处理外,所有连接跟踪都是在PREROUTING链里进行处理的,意思就是, iptables会在PREROUTING链里从新计算所有的状态。

    如果我们发送一个流的初始化包,状态就会在OUTPUT链里被设置为NEW,当我们收到回应的包时,状态就会在PREROUTING链里被设置为ESTABLISHED。如果第一个包不是本地产生的,那就会在PREROUTING链里被设置为NEW状态。综上,所有状态的改变和计算都是在nat表中的PREROUTING链和OUTPUT链里完成的。conntrack默认最大跟踪65536个连接

    连接跟踪表溢出
    连接跟踪表nf_conntrack,Linux为每个经过内核网络栈的数据包,生成一个新的连接记录项,当服务器处理的连接过多时,连接跟踪表被打满,服务器会丢弃新建连接的数据包。
    如何确认
    通过dmesg可以确认是否有该情况发生

    dmesg | grep nf_conntrack

    如果输出值中有“nf_conntrack: table full, dropping packet”,说明服务器nf_conntrack表已经被打满。

    通过/proc文件系统查看nf_conntrack表实时状态:

    跟踪连接详细信息:

    cat /proc/net/nf_conntrack

    查看nf_conntrack表最大连接数

    cat /proc/sys/net/netfilter/nf_conntrack_max


    查看nf_conntrack表当前连接数

    cat /proc/sys/net/netfilter/nf_conntrack_count

    查看nf_conntrack_buckets哈希表最大大小

    cat /proc/sys/net/netfilter/nf_conntrack_buckets

    查看netfilter相关的内核参数

    sysctl -a | grep conntrack

    如果确认服务器因连接跟踪表溢出而开始丢包,首先需要判断是否正遭受DDOS攻击,如果是正常的业务流量造成,可以考虑调整nf_conntrack的参数
    nf_conntrack_max决定连接跟踪表的大小,默认值是65536,可以根据系统内存大小计算一个合理值:CONNTRACK_MAX = RAMSIZE(in bytes)/16384/(ARCH/32),如32G内存可以设置1048576;
    一个连接占用312字节内存,65536大约25M内存占用,存储在内核空间,这部分内存不能swap,当CONNTRACK_MAX为 1048576,HASHSIZE buckets为 262144 时,最多占390MB内存开销,对现在的vps服务器来说毫无压力,你用512M的vps跑业务当我没说。
    nf_conntrack_buckets决定存储conntrack条目的哈希表大小,默认值是nf_conntrack_max的1/4,延续这种计算方式:BUCKETS = CONNTRACK_MAX/4,如32G内存可以设置262144;
    net.netfilter.nf_conntrack_tcp_timeout_established # 决定ESTABLISHED状态连接的超时时间,默认值是5天,可以缩短到1小时,即3600,这个值基本上没什么效果,还是加上吧。
    net.netfilter.nf_conntrack_tcp_timeout_fin_wait # 默认 120 秒
    net.netfilter.nf_conntrack_tcp_timeout_time_wait # 默认 120 秒,可以适当修改这个值
    net.netfilter.nf_conntrack_tcp_timeout_close_wait # 默认 60 秒,CLOSE_WAIT是被动方收到FIN发ACK,然后会转到LAST_ACK发FIN,除非程序写得有问题,正常来说这状态持续时间很短。
    net.netfilter.nf_conntrack_generic_timeout # 默认 600 秒(10分钟)通用超时设置,作用于4层(传输层)未知或不支持的协议
    net.netfilter.nf_conntrack_tcp_timeout_max_retrans # 默认 300 秒
    net.netfilter.nf_conntrack_tcp_timeout_unacknowledged # 默认 300 秒
    推荐bucket至少 262144,max至少 1048576,不够再继续加,或者缩短超时时间可以让netfilter更快地把跟踪的记录从哈希表里移除。
    哈希表使用情况:

    grep conntrack /proc/slabinfo

    前面三个数字代表
    当前活动对象数、当前使用对象总数、每个对象的内存占用大小(字节)

    sysctl -w net.netfilter.nf_conntrack_max=1048576

    echo 262144 > /sys/module/nf_conntrack/parameters/hashsize

    sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600

    通过sysctl -w和echo的命令,是临时生效的,重启会复原也可以编辑文件添加:

    vim /etc/sysctl.conf

    net.netfilter.nf_conntrack_max = 1048576

    net.netfilter.nf_conntrack_tcp_timeout_established = 3600

    修改后,执行sysctl -p 生效
    和buckets表开机自动修改

    echo "echo 262144 > /sys/module/nf_conntrack/parameters/hashsize" >> /etc/rc.d/rc.local

    如果业务没有涉及到状态链路相关的应用,直接不加载这个模块就可以了。

     

     

     

     

     

     

     

     


     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-3 15:12 , Processed in 0.069198 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表