• Linux Netfilter框架之conntrack连接跟踪机制


    一、Linux的Netfilter框架

    对于不经常接触Linux内核的应用层开发者来说,可能对Netfilter了解的比较少。但大多数Linux用户多少都用过或知道iptables,然而,iptables的功能实现就是在Netfilter之上完成的。

    Netfilter框架由著名的Linux开发人员Rusty Russell于1998年开发,旨在改进以前实现ipchains(Linux2.2.x)和ipfwadm(Linux2.0.x)。

    Netfilter是 Linux 内核中的一个框架,它为以定制处理器形式实施的各种网络相关操作提供了灵活性。Netfilter提供数据包过滤、网络地址翻译和端口翻译的各种选项。

    Netfilter其详细构成:

    Linux的Netfilter框架提供了如下功能:

    • 数据包筛选 (iptables)

    • 数据包过滤

    • 网络地址转换 (NAT)

    • 数据包修改 (修改数据包头信息mangling)

    • 连接跟踪

    • 收集网络统计信息

    Netfilter是 Linux 内核中进行数据包过滤,连接跟踪(Connect Track),网络地址转换(NAT)等功能的主要实现框架;该框架在网络协议栈处理数据包的关键流程中定义了一系列钩子点(Hook 点),并在这些钩子点中注册一系列函数对数据包进行处理。这些注册在钩子点的函数即为设置在网络协议栈内的数据包通行策略,换句话说就是,这些函数可以决定内核是接受还是丢弃某个数据包,函数的处理结果决定网络数据包的“命运”。

    从图中我们可以看到,Netfilter 框架采用模块化设计理念,并且贯穿了 Linux 系统的内核态和用户态。

    在用户态层面,根据不同的协议类型,为上层用户提供了不同的系统调用工具,比如我们常用的针对IPv4协议iptables,IPv6 协议的ip6tables,针对ARP协议的arptables,针对网桥控制的ebtables,针对网络连接追踪的conntrack等。

    不同的用户态工具在内核中有对应的模块进行实现,而底层都需要调用 Netfilter hook API 接口进行实现。

    同时也发现,之前提到的iptables,Linux防火墙工具其实也是 Netfilter 框架中的一个组件。

    Netfilter数据包路径

    正常数据包在Netfilter中的路径:

    二、conntrack概述

    一般conntrack用来指代“Connection Tracking”,即连接跟踪,是建立在 Netfilter框架之上的重要功能之一。 连接跟踪允许内核跟踪所有逻辑网络连接或会话,从而关联可能构成该连接的所有数据包。 NAT 依赖此信息以相同的方式转换所有相关数据包,而 iptables 可以使用此信息充当有状态防火墙。

    连接跟踪(Connection Tracking) 用来跟踪会话连接,这样就可以根据数据包是否属于某个连接来做策略。

    例如(除有特殊配置,此命令会造成ssh远程连接中断,谨慎执行!):

    iptables -P INPUT DROP

    此命令将filter表中的INPUT链的默认策略设置成DROP,如果没有其他策略那么所有的连接都会中断,如果你是ssh远程登录的服务器,不好意思你可能已经把自己踢掉了。

    但是,如果你提前添加一条命令:

    1. iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
    2. iptables -P INPUT DROP

    第一条命令会调用conntrack模块,对已经建立连接的数据包不丢弃。也就是当前建立的ssh连接可以继续使用,但是你建立不了新的ssh连接了。这就是Connection Tracking识别连接中的数据包的简单用法。

    Conntrack modules and hooks这篇文章的概览很清楚地介绍了连接跟踪系统的作用,这里翻译记录在这里,对我来说其中最重要的一点是理解conntrack是一位“透明观察者” 。

    连接跟踪的目的是什么,它有什么作用?

    一旦激活连接跟踪(Linux 内核中的 ct 系统),它会检查 IPv4 和/或 IPv6 网络数据包及其有效负载,以确定哪些数据包相互关联,例如在面向连接的协议(如 TCP)的范围内。 ct 系统作为透明观察者执行此任务,并不积极参与端点之间的通信。连接的端点是本地的还是远程与 ct 系统无关。它们可以都位于远程主机上,在这种情况下,ct 系统在给特定连接的数据包充当路由或桥接角色的主机上观察它们。

    一个连接中的一个甚至两个端点都可以是运行 ct 系统的同一主机上的本地套接字。这对ct系统来说没区别。 ct 系统维护所有跟踪连接的最新(实时)列表。基于此,它通过为每个数据包提供一个指向其跟踪连接实例之一的引用(指针)来给网络数据包遍历内核网络堆栈时“分类”。因此,其他内核组件可以访问此连接关联并基于此做出决策。使用它的两个最突出的候选者是 NAT 子系统以及Iptables和Nftables 的状态包过滤模块。 ct 系统本身从不改变/操纵数据包。

    它通常也不会丢弃数据包,只可能在极少数情况下发生这种情况。在检查数据包内容时,它主要关注 OSI模型的第 3 层和第 4 层。它能够跟踪 TCP、UDP、ICMP、ICMPv6、SCTP、DCCP 和 GRE 连接。可见ct 系统对“连接”的定义不限于面向连接的协议,因为刚才提到的某些协议不是面向连接的。例如它将 ICMP echo 请求和echo回复 (ping) 视为“连接”并处理。 ct 系统提供了几个辅助/扩展组件,将其跟踪能力扩展到应用层,例如跟踪协议,如 FTP、TFTP、IRC、PPTP、SIP等。

    conntrack-tools是一组用于 Linux 的免费软件用户空间工具,允许系统管理员与连接跟踪系统进行交互,conntrack-tools包括用户空间守护进程 conntrackd 和命令行界面 conntrack。

    内核中关于conntrack模块的配置参数及默认值可以参考Kernel文档或者通过以下命令来查看:

    sysctl -a | grep conntrack 

    三、Connection Tracking 状态

    nf_conntrack(在老版本的 Linux 内核中叫 ip_conntrack)是一个内核模块,用于跟踪一个连接的状态的。连接状态跟踪可以供其他模块使用,最常见的两个使用场景是 iptables 的 nat 的 state 模块。 iptables 的 nat 通过规则来修改目的/源地址,但光修改地址不行,我们还需要能让回来的包能路由到最初的来源主机。这就需要借助 nf_conntrack 来找到原来那个连接的记录才行。而 state 模块则是直接使用 nf_conntrack 里记录的连接的状态来匹配用户定义的相关规则。例如下面这条 INPUT 规则用于放行 80 端口上的状态为 NEW 的连接上的包。

    iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT

    iptables中的状态检测功能是由state选项来实现iptable的。对这个选项,在iptables的手册页中有以下描述:

    state

    这个模块能够跟踪分组的连接状态(即状态检测)。

    格式:--state XXXXX

    这里,state是一个用逗号分割的列表,表示要匹配的连接状态。

    在iptables中有四种状态:NEW,ESTABLISHED,RELATED,INVALID。

    NEW,表示这个分组需要发起一个连接,或者说,分组对应的连接在两个方向上都没有进行过分组传输。NEW说明 这个包是我们看到的第一个包。意思就是,这是conntrack模块看到的某个连接第一个包,它即将被匹配了。比如,我们看到一个SYN包,是我们所留意 的连接的第一个包,就要匹配它。第一个包也可能不是SYN包,但它仍会被认为是NEW状态。比如一个特意发出的探测包,可能只有RST位,但仍然是 NEW。

    ESTABLISHED,表示分组对应的连接已经进行了双向的分组传输,也就是说连接已经建立,而且会继续匹配 这个连接的包。处于ESTABLISHED状态的连接是非常容易理解的。只要发送并接到应答,连接就是ESTABLISHED的了。一个连接要从NEW变 为ESTABLISHED,只需要接到应答包即可,不管这个包是发往防火墙的,还是要由防火墙转发的。ICMP的错误和重定向等信息包也被看作是 ESTABLISHED,只要它们是我们所发出的信息的应答。

    ELATED,表示分组要发起一个新的连接,但是这个连接和一个现有的连接有关,例如:FTP的数据传输连接 和控制连接之间就是RELATED关系。RELATED是个比较麻烦的状态。当一个连接和某个已处于ESTABLISHED状态的连接有关系时,就被认为 是RELATED的了。换句话说,一个连接要想是RELATED的,首先要有一个ESTABLISHED的连接。这个ESTABLISHED连接再产生一 个主连接之外的连接,这个新的连接就是RELATED的了,当然前提是conntrack模块要能理解RELATED。ftp是个很好的例子,FTP- data连接就是和FTP-control有RELATED的。还有其他的例子,

    INVAILD,表示分组对应的连接是未知的,说明数据包不能被识别属于哪个连接或没有任何状态。有几个原因可以产生这种情况,比如,内存溢出,收到不知属于哪个连接的ICMP错误信息。一般地,我们DROP这个状态的任何东西。

    对于FTP这种控制命令和数据传输使用不同端口需要建立多条连接的,也可以进行追踪,这是依靠Connection Tracking Helpers实现的。

    Connection Tracking中连接的状态不等于TCP链接的状态,实际上它对UDP,ICMP等是否属于相关的会话连接都可以识别,支持的状态有这么几种:

    INVALID 无效连接

    ESTABLISHED 已建立的连接

    NEW 刚开始建立的连接

    RELATED 相关连接,例如上文提到的FTP两个连接的关系

    SNAT snat连接

    DNAT dnat连接

    要使用此功能,确保内核开启了相关模块:

    1. modprobe nf_conntrack
    2. modprobe nf_conntrack_ftp # 对于ftp的跟踪

    相应配置:

    1. ### 开启数据包统计(包数和字节数)
    2. # echo "net.netfilter.nf_conntrack_acct=1" >> /etc/sysctl.conf
    3. ### 开启流续时间统计(delta-time)
    4. # echo "net.netfilter.nf_conntrack_timestamp=1" >> /etc/sysctl.conf
    5. ### 配置跟踪的最大连接数量,高并发服务器超过此数量可能引起丢包
    6. # echo "net.netfilter.nf_conntrack_max=102400" >> /etc/sysctl.conf
    7. # sysctl -p

    四、conntrack常用命令

    有一个conntrack命令,属于conntrack-tools工具包,是针对连接跟踪的命令行工具。(有些系统单独执行此命令没有结果,需要配合上文使用了conntrack模块的iptables命令才能有输出)。

    conntrack命令可以显示,删除和更新跟踪表现有状态条目,还可以监听流事件。

    1. 安装:

    yum install -y conntrack

     容器中报错:

    docker容器对权限有些限制,有人建议用如下命令开启,本人未验证,仅供参考

     docker run --privileged=true --net=host

    2. 使用:

    conntrack-tools用户手册:The conntrack-tools user manual (netfilter.org)

    查看conntrack表记录:

    1. # conntrack -L
    2. tcp 6 300 ESTABLISHED src=192.168.56.107 dst=192.168.56.1 sport=22 dport=64099 src=192.168.56.1 dst=192.168.56.107 sport=64099 dport=22 [ASSURED] mark=0 use=1
    3. conntrack v1.4.5 (conntrack-tools): 1 flow entries have been shown.

    此命令可以显示,添加,删除连接的跟踪,还有一些过滤参数。

    过滤条件输出:

    1. # conntrack -U -p tcp --dport 3486 --mark 10
    2. tcp 6 431982 ESTABLISHED src=192.168.2.100 dst=123.59.27.117 sport=34846 dport=993 packets=169 bytes=14322 src=123.59.27.117 dst=192.168.2.100 sport=993 dport=34846 packets=113 bytes=34787 [ASSURED] mark=1 secmark=0 use=1
    3. conntrack v0.9.7 (conntrack-tools): 1 flow entries has been updated.

    清空conntrack表记录:

    conntrack -D

    显示当前正在被追踪的流:

    1. # conntrack -L -o ktimestamp
    2. tcp 6 431666 ESTABLISHED src=10.0.0.2 dst=20.0.0.6 sport=33715 dport=22 packets=17 bytes=2094 src=20.0.0.6 dst=10.0.0.2 sport=22 dport=33715 packets=14 bytes=1870 [ASSURED] mark=0 zone=1 delta-time=336 [start=Wed Sep 13 15:48:40 2017] use=1
    3. icmp 1 29 src=20.0.0.11 dst=20.0.0.6 type=8 code=0 id=40449 packets=5 bytes=420 src=20.0.0.6 dst=20.0.0.11 type=0 code=0 id=40449 packets=5 bytes=420 mark=0 zone=9 delta-time=4 [start=Wed Sep 13 15:55:46 2017] use=1

    监控流事件:

    1. # conntrack -E -o ktimestamp
    2. [NEW] tcp 6 120 SYN_SENT src=10.0.0.2 dst=20.0.0.6 sport=33717 dport=22 [UNREPLIED] src=20.0.0.6 dst=10.0.0.2 sport=22 dport=33717 zone=1
    3. [DESTROY] tcp 6 src=10.0.0.2 dst=20.0.0.6 sport=33717 dport=22 packets=31 bytes=3042 src=20.0.0.6 dst=10.0.0.2 sport=22 dport=33717 packets=23 bytes=2666 [ASSURED] zone=1 delta-time=142 [start=Wed Sep 13 16:07:06 2017] [stop=Wed Sep 13 16:09:28 2017]

    设置输出格式:

    默认conntrack -L显示自第一次看到流以来经过的秒数。

    添加–o ktimestamp可以查看绝对开始日期:

    conntrack -L -o ktimestamp。

    但是注意,查看绝对日期的功能需要先执行以下命名以启用该功能,否则输出结果与conntrack -L无异。

    echo 1 > /proc/sys/net/netfilter/nf_conntrack_timestamp

    其他支持的格式还有"extended,xml,timestamp,id,labels".

    全部命令列表:

    1. [root@localhost ~]# conntrack --help
    2. Command line interface for the connection tracking system. Version 1.4.4
    3. Usage: conntrack [commands] [options]
    4. Commands:
    5. -L [table] [options] List conntrack or expectation table
    6. -G [table] parameters Get conntrack or expectation
    7. -D [table] parameters Delete conntrack or expectation
    8. -I [table] parameters Create a conntrack or expectation
    9. -U [table] parameters Update a conntrack
    10. -E [table] [options] Show events
    11. -F [table] Flush table
    12. -C [table] Show counter
    13. -S Show statistics
    14. Tables: conntrack, expect, dying, unconfirmed
    15. Conntrack parameters and options:
    16. -n, --src-nat ip source NAT ip
    17. -g, --dst-nat ip destination NAT ip
    18. -j, --any-nat ip source or destination NAT ip
    19. -m, --mark mark Set mark
    20. -c, --secmark secmark Set selinux secmark
    21. -e, --event-mask eventmask Event mask, eg. NEW,DESTROY
    22. -z, --zero Zero counters while listing
    23. -o, --output type[,...] Output format, eg. xml
    24. -l, --label label[,...] conntrack labels
    25. Expectation parameters and options:
    26. --tuple-src ip Source address in expect tuple
    27. --tuple-dst ip Destination address in expect tuple
    28. Updating parameters and options:
    29. --label-add label Add label
    30. --label-del label Delete label
    31. Common parameters and options:
    32. -s, --src, --orig-src ip Source address from original direction
    33. -d, --dst, --orig-dst ip Destination address from original direction
    34. -r, --reply-src ip Source addres from reply direction
    35. -q, --reply-dst ip Destination address from reply direction
    36. -p, --protonum proto Layer 4 Protocol, eg. 'tcp'
    37. -f, --family proto Layer 3 Protocol, eg. 'ipv6'
    38. -t, --timeout timeout Set timeout
    39. -u, --status status Set status, eg. ASSURED
    40. -w, --zone value Set conntrack zone
    41. --orig-zone value Set zone for original direction
    42. --reply-zone value Set zone for reply direction
    43. -b, --buffer-size Netlink socket buffer size
    44. --mask-src ip Source mask address
    45. --mask-dst ip Destination mask address

    谷歌翻译如下:

    1. 连接跟踪系统的命令行界面。版本1.4.4
    2. 用法:conntrack [命令] [选项]
    3. 命令:
    4. -L [表] [选项]列出conntrack或期望表
    5. -G [表]参数获取conntrack或期望值
    6. -D [表]参数删除conntrack或期望
    7. -I [表]参数创建连接跟踪或期望
    8. -U [table]参数更新conntrack
    9. -E [表] [选项]显示事件
    10. -F [表]刷新表
    11. -C [表]显示计数器
    12. -S显示统计
    13. 表格:conntrack,期望,死亡,未确认
    14. Conntrack参数和选项:
    15. -n,--src-nat ip源NAT ip
    16. -g,--dst-nat ip目标NAT ip
    17. -j,-any-nat ip源或目标NAT ip
    18. -m,--mark标记设置标记
    19. -c,--secmark secmark设置selinux secmark
    20. -e,--event-mask eventmask事件掩码,例如。新,毁灭
    21. -z,--zero列出时的零计数器
    22. -o,--output type [,...]输出格式,例如XML文件
    23. -l,--label标签[,...] conntrack标签
    24. 期望参数和选项:
    25. --tuple-src ip预期元组中的源地址
    26. --tuple-dst ip预期的元组中的目标地址
    27. 更新参数和选项:
    28. --label-添加标签添加标签
    29. --label-del标签删除标签
    30. 常用参数和选项:
    31. -s,-src,-orig-src ip原始方向的源地址
    32. -d,--dst,--orig-dst ip原始方向的目标地址
    33. -r,--reply-src ip来自回复方向的源地址
    34. -q,--reply-dst ip回复方向的目标地址
    35. -p,--protonum proto第4层协议,例如'tcp'
    36. -f,--family proto第3层协议,例如。 'ipv6'
    37. -t,--timeout超时设置超时
    38. -u,--status status设置状态,例如保证
    39. -w,--zone值设置conntrack区域
    40. --orig-zone值设置原始方向的区域
    41. --reply-zone值设置回复方向的区域
    42. -b,--buffer-size Netlink套接字缓冲区大小
    43. --mask-src ip源掩码地址
    44. --mask-dst ip目标掩码地址

    五、nf_conntrack模块常用命令

    1. 查看nf_conntrack表当前连接数
    2. cat /proc/sys/net/netfilter/nf_conntrack_count
    3. 查看nf_conntrack表最大连接数
    4. cat /proc/sys/net/netfilter/nf_conntrack_max
    5. 通过dmesg可以查看nf_conntrack的状况:
    6. dmesg |grep nf_conntrack
    7. 查看存储conntrack条目的哈希表大小,此为只读文件
    8. cat /proc/sys/net/netfilter/nf_conntrack_buckets
    9. 查看nf_conntrack的TCP连接记录时间
    10. cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
    11. 通过内核参数查看命令,查看所有参数配置
    12. sysctl -a | grep nf_conntrack
    13. 通过conntrack命令行工具查看conntrack的内容
    14. yum install -y conntrack
    15. conntrack -L
    16. 加载对应跟踪模块
    17. [root@plop ~]# modprobe /proc/net/nf_conntrack_ipv4
    18. [root@plop ~]# lsmod | grep nf_conntrack
    19. nf_conntrack_ipv4 9506 0
    20. nf_defrag_ipv4 1483 1 nf_conntrack_ipv4
    21. nf_conntrack_ipv6 8748 2
    22. nf_defrag_ipv6 11182 1 nf_conntrack_ipv6
    23. nf_conntrack 79758 3 nf_conntrack_ipv4,nf_conntrack_ipv6,xt_state
    24. ipv6 317340 28 sctp,ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6
    25. 移除 nf_conntrack 模块
    26. $ sudo modprobe -r xt_NOTRACK nf_conntrack_netbios_ns nf_conntrack_ipv4 xt_state
    27. $ sudo modprobe -r nf_conntrack
    28. 查看当前的连接数:
    29. grep nf_conntrack /proc/slabinfo
    30. 查出目前 nf_conntrack 的排名:
    31. cat /proc/net/nf_conntrack | cut -d ' ' -f 10 | cut -d '=' -f 2 | sort | uniq -c | sort -nr | head -n 10

    nf_conntrack会话表样例

    通过conntrack -L/proc/net/nf_conntrack是完全一样的,除了少了前面的两列。 

    下面以cat /proc/net/nf_conntrack为例进行说明:

    1. ipv4 2 tcp 6 25 SYN_SENT src=182.168.77.7 dst=42.236.9.57 sport=57430 dport=443 [UNREPLIED] src=42.236.9.57 dst=182.168.77.7 sport=443 dport=57430 mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2
    2. ipv4 2 tcp 6 299 ESTABLISHED src=172.18.15.56 dst=172.18.15.96 sport=40248 dport=22 src=172.18.15.96 dst=172.18.15.56 sport=22 dport=40248 [ASSURED] mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2
    3. ipv4 2 tcp 6 5 SYN_SENT src=182.168.77.7 dst=221.181.72.250 sport=57428 dport=443 [UNREPLIED] src=221.181.72.250 dst=182.168.77.7 sport=443 dport=57428 mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2
    4. ipv4 2 tcp 6 1 SYN_SENT src=182.168.77.7 dst=221.181.72.250 sport=57427 dport=80 [UNREPLIED] src=221.181.72.250 dst=182.168.77.7 sport=80 dport=57427 mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2

    每一列表达的意思

    • 第一列:网络层协议名字。
    • 第二列:网络层协议号。
    • 第三列:传输层协议名字。
    • 第四列:传输层协议号。
    • 第五列:无后续包进入时无效的秒数,即老化时间。
    • 第六列:不是所有协议都有,连接状态。
    • 其它的列都是通过名字的方式(key与value对)表述,或和呈现标识([UNREPLIED], [ASSURED], …)。一行的不同列可能包含相同的名字(例如src和dst),第一个表示请求方,第二个表示应答方。

    呈现标识含义

    • [ASSURED]: 在两个方面(即请求和响应)方向都看到了流量。
    • [UNREPLIED]: 尚未在响应方向上看到流量。如果连接跟踪缓存溢出,则首先删除这些连接。

    请注意,某些列名仅出现在特定协议中(例如,TCP和UDP的sport和dport,ICMP的type和code)。 仅当内核使用特定选项构建时,才会显示其他列名称(例如mark)。

    举例说明

    • ipv4 2 tcp 6 300 ESTABLISHED src=1.1.1.2 dst=2.2.2.2 sport=2000 dport=80 src=2.2.2.2 dst=1.1.1.1 sport=80 dport=12000 [ASSURED] mark=0 use=2 

      属于从主机1.1.1.2,端口2000到主机2.2.2.2,端口80的已建立的TCP连接,从中将响应发送到主机1.1.1.2,端口2000,在五分钟内超时。对于此连接,已在两个方向上看到数据包。

    • ipv4 2 icmp 1 3 src=1.1.1.2 dst=1.1.1.1 type=8 code=0 id=32354 src=1.1.1.1 dst=1.1.1.2 type=0 code=0 id=32354 mark=0 use=2 

      属于从主机1.1.1.2到主机1.1.1.1的ICMP回应请求数据包,具有从主机1.1.1.1到主机1.1.1.2的预期回应应答数据包,在三秒内超时。响应目标主机不一定与请求源主机相同,因为请求源地址可能已被响应目标主机伪装。

    主要标识

    请注意,以下信息可能不是最新信息!

    1. Fields available for all entries:
    2. bytes (if accounting is enabled, request and response)
    3. delta-time (if CONFIG_NF_CONNTRACK_TIMESTAMP is enabled)
    4. dst (request and response)
    5. mark (if CONFIG_NF_CONNTRACK_MARK is enabled)
    6. packets (if accounting is enabled, request and response)
    7. secctx (if CONFIG_NF_CONNTRACK_SECMARK is enabled)
    8. src (request and response)
    9. use
    10. zone (if CONFIG_NF_CONNTRACK_ZONES is enabled)
    11. Fields available for dccp, sctp, tcp, udp and udplite transmission layer protocols:
    12. dport (request and response)
    13. sport (request and response)
    14. Fields available for icmp transmission layer protocol:
    15. code (request and response)
    16. id (request and response)
    17. type (request and response)
    18. Fields available for gre transmission layer protocol:
    19. dstkey (request and response)
    20. srckey (request and response)
    21. stream_timeout
    22. timeout
    23. Allowed values for the sixth field:
    24. dccp transmission layer protocol
    25. CLOSEREQ
    26. CLOSING
    27. IGNORE
    28. INVALID
    29. NONE
    30. OPEN
    31. PARTOPEN
    32. REQUEST
    33. RESPOND
    34. TIME_WAIT
    35. sctp transmission layer protocol
    36. CLOSED
    37. COOKIE_ECHOED
    38. COOKIE_WAIT
    39. ESTABLISHED
    40. NONE
    41. SHUTDOWN_ACK_SENT
    42. SHUTDOWN_RECD
    43. SHUTDOWN_SENT
    44. tcp transmission layer protocol
    45. CLOSE
    46. CLOSE_WAIT
    47. ESTABLISHED
    48. FIN_WAIT
    49. LAST_ACK
    50. NONE
    51. SYN_RECV
    52. SYN_SENT
    53. SYN_SENT2
    54. TIME_WAIT

    六、nf_conntrack相关内核参数和解释

    参考内核帮助文档/usr/share/doc/kernel-doc-3.10.0/Documentation/networking/nf_conntrack-sysctl.txt 

    /proc/sys/net/netfilter/nf_conntrack_*:

    • nf_conntrack_acct 
      值类型:BOOLEAN 
      0 - disabled (default)
      not 0 - enabled 
      启用连接跟踪流记帐。64位字节和数据包每个流量的计数器被添加。

    • nf_conntrack_buckets 
      值类型:INTEGER (read-only
      哈希表的大小。 如果在模块加载期间未指定为参数,则通过将总内存除以16384来计算默认大小以确定存储区的数量,但是哈希表将永远不会少于32并且限制为16384个存储区。 对于内存超过4GB的系统,它将是65536个桶。

    • nf_conntrack_checksum 
      值类型:BOOLEAN 
      0 - disabled 
      not 0 - enabled (default) 
      验证传入数据包的校验和。 具有错误校验和的数据包处于INVALID状态。 如果启用此选项,则不会考虑此类数据包进行连接跟踪。

    • nf_conntrack_count 
      值类型:INTEGER (read-only
      当前分配的流条目数。

    • nf_conntrack_events 
      值类型:BOOLEAN 
      0 - disabled 
      not 0 - enabled (default) 
      如果启用此选项,则连接跟踪代码将通过ctnetlink为用户空间提供连接跟踪事件。

    • nf_conntrack_events_retry_timeout 
      值类型:INTEGER (seconds) 
      default 15 
      此选项仅在使用“可靠连接跟踪事件”时才相关。 通常,ctnetlink是“有损”的,也就是说,当用户空间监听器无法跟上时,事件通常会被丢弃。 
      用户空间可以请求“可靠的事件模式”。 当此模式处于活动状态时,conntrack将仅在事件发布后销毁。 如果事件传递失败,则内核会定期重新尝试将事件发送到用户空间。 
      这是内核在重新尝试传递destroy事件时应使用的最大间隔。 
      数字越大意味着交付重试次数越少,处理待办事项的时间就越长。

    • nf_conntrack_expect_max 
      值类型:INTEGER 
      期望表的最大大小。 默认值为nf_conntrack_buckets / 256.最小值为1。

    • nf_conntrack_frag6_high_thresh 
      值类型:INTEGER 
      用于重组IPv6片段的最大内存。 当为达到重组目标时分配nf_conntrack_frag6_high_thresh字节的内存时,若超出此值片段处理程序将抛出数据包。

    • nf_conntrack_frag6_timeout 
      值类型:INTEGER (seconds) 
      default 60 
      ipv6分片在内存中保存的老化时间。

    • nf_conntrack_generic_timeout 
      值类型:INTEGER (seconds) 
      default 600 
      通用超时的默认值。 这指的是第4层未知/不支持的协议。

    • nf_conntrack_helper 
      值类型:BOOLEAN 
      0 - disabled 
      not 0 - enabled (default) 
      启用自动conntrack帮助程序分配。

    • nf_conntrack_icmp_timeout 
      值类型:INTEGER (seconds) 
      default 30 
      ICMP连接状态超时的默认值。

    • nf_conntrack_icmpv6_timeout 
      值类型:INTEGER (seconds) 
      default 30 
      ICMP6连接状态超时的默认值。

    • nf_conntrack_log_invalid 
      值类型:INTEGER 
      0 - disable (default) 
      1 - log ICMP packets 
      6 - log TCP packets 
      17 - log UDP packets 
      33 - log DCCP packets 
      41 - log ICMPv6 packets 
      136 - log UDPLITE packets 
      255 - log packets of any protocol 
      根据值类型记录指定类型无效数据包。

    • nf_conntrack_max 
      值类型:INTEGER 
      连接跟踪表的大小。 默认值为nf_conntrack_buckets值* 4。

    • nf_conntrack_tcp_be_liberal 
      值类型:BOOLEAN 
      0 - disabled (default) 
      not 0 - enabled 
      Be conservative in what you do, be liberal in what you accept from others.If it’s non-zero, we mark only out of window RST segments as INVALID.

    • nf_conntrack_tcp_loose 
      值类型:BOOLEAN 
      0 - disabled 
      not 0 - enabled (default) 
      如果它设置为零,我们将禁用拾取已建立的连接。 
      它的意思是,是否仅仅允许为经过TCP三次握手的流创建nf_conntrack表项还是说为任意收到的TCP数据包(有可能是一个构造出来的攻击包)查询未果后均创建新的nf_conntrack表项。

    • nf_conntrack_tcp_max_retrans 
      值类型:INTEGER 
      default 3 
      在未收到来自目标的(可接受)ACK的情况下可以重新传输的最大数据包数。 如果达到此数字,将启动更短的计时器。

    • nf_conntrack_tcp_timeout_close 
      值类型:INTEGER (seconds) 
      default 10

    • nf_conntrack_tcp_timeout_close_wait 
      值类型:INTEGER (seconds) 
      default 60

    • nf_conntrack_tcp_timeout_established 
      值类型:INTEGER (seconds) 
      default 432000 (5 days) 
      默认是432000=3600245即5天的超时时间,超时后清空对应的那条记录。

    • nf_conntrack_tcp_timeout_fin_wait 
      值类型:INTEGER (seconds) 
      default 120

    • nf_conntrack_tcp_timeout_last_ack 
      值类型:INTEGER (seconds) 
      default 30

    • nf_conntrack_tcp_timeout_max_retrans 
      值类型:INTEGER (seconds) 
      default 300

    • nf_conntrack_tcp_timeout_syn_recv 
      值类型:INTEGER (seconds) 
      default 60

    • nf_conntrack_tcp_timeout_syn_sent 
      值类型:INTEGER (seconds) 
      default 120

    • nf_conntrack_tcp_timeout_time_wait 
      值类型:INTEGER (seconds) 
      default 120

    • nf_conntrack_tcp_timeout_unacknowledged 
      值类型:INTEGER (seconds) 
      default 300

    • nf_conntrack_timestamp 
      值类型:BOOLEAN 
      0 - disabled (default) 
      not 0 - enabled 
      启用连接跟踪流时间戳。

    • nf_conntrack_udp_timeout 
      值类型:INTEGER (seconds) 
      default 30

    • nf_conntrack_udp_timeout_stream2 
      值类型:INTEGER (seconds) 
      default 180 
      如果检测到UDP流,将使用此扩展超时。

    还有多少秒这条会话信息会从跟踪表清除,取决于超时参数的配置,以及是否有包传输,有包传输时,这个时间会重置为超时时间。

    如何判断会话表是否满

    当会话表中的记录大于内核设置nf_conntrack_max的值时,会导致会话表满。

    1. nf_conntrack_max - INTEGER
    2. Size of connection tracking table. Default value is
    3. nf_conntrack_buckets value * 4.

    案例: less /var/log/messages

    1. Nov 3 23:30:27 digoal_host kernel: : [63500383.870591] nf_conntrack: table full, dropping packet.
    2. Nov 3 23:30:27 digoal_host kernel: : [63500383.962423] nf_conntrack: table full, dropping packet.
    3. Nov 3 23:30:27 digoal_host kernel: : [63500384.060399] nf_conntrack: table full, dropping packet.

    会话表满的解决办法:

    nf_conntrack table full的问题,会导致丢包,影响网络质量,严重时甚至导致网络不可用。

    解决方法举例:

    1、排查是否DDoS攻击,如果是,从预防攻击层面解决问题。

    2、清空会话表。

    重启iptables,会自动清空nf_conntrack table。注意,重启前先保存当前iptables配置(iptables-save > /etc/sysconfig/iptables ; service iptables restart)。

    3、应用程序正常关闭会话

    设计应用时,正常关闭会话很重要。

    4、加大表的上限(需要考虑内存的消耗)

    例举故障原因:

    1. 内核参数 net.nf_conntrack_max 系统默认值为”65536”,当nf_conntrack模块被装置且服务器上连接超过这个设定的值时,系统会主动丢掉新连接包,直到连接小于此设置值才会恢复。同时内核参数“net.netfilter.nf_conntrack_tcp_timeout_established”系统默认值为”432000”,代表nf_conntrack的TCP连接记录时间默认是5天,致使nf_conntrack的值减不下来,丢包持续时间长。

    2. nf_conntrack模块在首次装载或重新装载时,内核参数net.nf_conntrack_max会重新设置为默认值“65536”,并且不会调用sysctl设置为我们的预设值。

    3. 触发nf_conntrack模块首次装载比较隐蔽,任何调用IPtable NAT功能的操作都会触发。当系统没有挂载nf_conntrack模块时,iptables 相关命令(iptables -L -t nat)就成触发nf_conntrack模块装置,致使net.nf_conntrack_max 重设为65536。

    4. 触发nf_conntrack模块重新装载的操作很多,CentOS6 中“service iptables restart”,CentOS7中“systemctl restart iptables.service”都会触发设置重置,致使net.nf_conntrack_max 重设为65536。

    七、nf_conntrack重要的几个配置文件

    nf_conntrack_max决定连接跟踪表的大小,当nf_conntrack模块被装置且服务器上连接超过这个设定的值时,系统会主动丢掉新连接包,直到连接小于此设置值才会恢复。 

    nf_conntrack_buckets决定存储conntrack条目的哈希表大小,若是单方面修 nf_conntrack_max,而不修改nf_conntrack_buckets,只是影响查找速度,挂在不了桶上的新跟踪项目,会挂在到桶中的链表上(原理为hash表结构)。 

    nf_conntrack_tcp_timeout_established系统默认值为”432000”,代表nf_conntrack的TCP连接记录时间默认是5天,致使nf_conntrack的值减不下来,丢包持续时间长。 

    通过修改这两个值即可,但是nf_conntrack_buckets时个只读文件,无法进行修改。

    修改参数

    通过sysctl命令进行修改:

    1. $ sysctl -w net.netfilter.nf_conntrack_max=1048576
    2. $ sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600
    3. $ sysctl -p #使生效

    或是直接永久性修改永久生效

    1. vi /etc/sysctl.conf
    2. net.netfilter.nf_conntrack_max=1048576
    3. net.netfilter.nf_conntrack_tcp_timeout_established=3600

    对于上述解决方案无法修改nf_conntrack_buckets的参数,因为此为只读文件,通过上述nf_conntrack-sysctl.txt文件可知知,可以通过模块加载的时候设置参数。此时可以采用下面方案进行修改:

    通过系统初始化脚本创建配置文件”/etc/modprobe.d/nf_conntrack.conf”, 内容为“options nf_conntrack hashsize=262144”,通过nf_conntrack模块挂接参数”hashsize”自动设置“net.nf_conntrack_max=2097152”(nf_conntrack_max=hashsize*8),保证后续新初始化服务器配置正确。

    通过自动化部署工具全网推送配置文件”/etc/modprobe.d/nf_conntrack.conf”, 内容为“options nf_conntrack hashsize=262144”,保证nf_conntrack模块在首次装载或重新装载时“net.nf_conntrack_max”内核参数设置为我们预期的“2097152”。

    更新系统初始化脚本,设置“net.netfilter.nf_conntrack_tcp_timeout_established=1800”,减少nf_conntrack的TCP连接记录时间。

    如果并不需要nf_conntrack及其相关模块可以在/etc/modprobe.d目录新建文件blacklist.conf ,文件中加入:install nf_conntrack /bin/false 这样做的副作用是无法再使用Iptables NAT相关功能。

    八、计算公式

    可以增大 conntrack 的条目(sessions, connection tracking entries) CONNTRACK_MAX 或者增加存储 conntrack 条目哈希表的大小 HASHSIZE 

    默认情况下,CONNTRACK_MAX 和 HASHSIZE 会根据系统内存大小计算出一个比较合理的值: 

    对于 CONNTRACK_MAX,其计算公式: 

    CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32

    比如一个 64 位 48G 的机器可以同时处理 48*1024^3/16384/2 = 1572864 条 netfilter 连接。对于大于 1G 内存的系统,默认的 CONNTRACK_MAX 是 65535。

    对于 HASHSIZE,默认的有这样的转换关系: 

    CONNTRACK_MAX = HASHSIZE * 8 

    这表示每个链接列表里面平均有 8 个 conntrack 条目。其真正的计算公式如下: 

    HASHSIZE = CONNTRACK_MAX / 8 = RAMSIZE (in bytes) / 131072 / (ARCH / 32

    比如一个 64 位 48G 的机器可以存储 48*1024^3/131072/2 = 196608 的buckets(连接列表)。对于大于 1G 内存的系统,默认的 HASHSIZE 是 8192。

  • 相关阅读:
    JavaScript系列之async与await
    企业网络自动化配置
    美团面试:如何实现线程任务编排?
    47. UE5 RPG 实现角色死亡效果
    华为设备MFF配置命令
    手写一个Spring IOC框架
    MySQL为什么用b+树
    java写一个用于生成雪花id的工具类
    yolov5 OpenVINO windows部署实战
    【C++】类型转换
  • 原文地址:https://blog.csdn.net/qq_35029061/article/details/125907874