首页  /  Linux 进阶  /  正文

iptables 限流与规则持久化

Linux 进阶 2026-10-02📖 13 分钟👁 —
🛡️ Linux 进阶 · iptables 防火墙第 3 / 4 页1234📖 完整导航 →

一、匹配网络状态(TCP/IP 连接)

通过防火墙控制连接状态,靠的是 -m state --state:

-m state --state

四个状态先认全:

NEW 新连接、ESTABLISHED 已建立、RELATED 关联的新连接、INVALID 非法
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

二、限制并发和速率

-m limit 是限制模块,用起来和 nginx 的限速配置很像,管两件事:桶内数量和并发数量。

# 每分钟放行10个数据包,相当于每6s放行个
-m limit --limit 10/minute # 相当于 60s/10=6s


# 指定固定时间内的请求速率为 n
# 后面的时间:时 分 秒(常用分钟和秒)
-m limit --limit second/minute/hour


-m limit --limit 10/minute --limit-burst 5 # 每 6s 释放工牌
# --limit-burst 限制并发数

为什么光限速还不够、还要限并发数?假设每分钟放 3000 个数据包,但前 30 秒就全放走了,服务器该有的压力一点没少,和没配一样。所以要限制并发数,也就是限制连续进行的访问。

来试一下:

# 每分钟10个请求,5并发
iptables -F
iptables -I INPUT -p icmp -m limit --limit 10/minute --limit-burst 5 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP 
# 修改默认规则为DROP(默认规则最后改,没有规则匹配默认的,连接断开)

[root@localhost ~]# iptables -nL
Chain INPUT (policy DROP) # 默认已改
target     prot opt source               destination         
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0            limit: avg 10/min burst 5
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   

# ping发现:隔一段时间就会卡顿,然后放行
# 每 6s ping一次,就说明并发限制成功(刚开始处理5个ping包,接下来每 6s ping一次)
已发送 34 个包, 已接收 10 个包, 70.5882% packet loss, time 33825ms
rtt min/avg/max/mdev = 0.278/0.903/1.537/0.386 ms
# 丢包率高,有70%


# 看包的发送间隔 icmp_seq

64 字节,来自 192.168.73.128: icmp_seq=1 ttl=64 时间=0.278 毫秒
64 字节,来自 192.168.73.128: icmp_seq=2 ttl=64 时间=1.03 毫秒
64 字节,来自 192.168.73.128: icmp_seq=3 ttl=64 时间=0.552 毫秒
64 字节,来自 192.168.73.128: icmp_seq=4 ttl=64 时间=0.708 毫秒
64 字节,来自 192.168.73.128: icmp_seq=5 ttl=64 时间=0.762 毫秒
64 字节,来自 192.168.73.128: icmp_seq=7 ttl=64 时间=0.899 毫秒
64 字节,来自 192.168.73.128: icmp_seq=13 ttl=64 时间=1.54 毫秒
64 字节,来自 192.168.73.128: icmp_seq=19 ttl=64 时间=1.44 毫秒
64 字节,来自 192.168.73.128: icmp_seq=25 ttl=64 时间=1.24 毫秒
64 字节,来自 192.168.73.128: icmp_seq=31 ttl=64 时间=0.589 毫秒

三、防火墙规则的保存和恢复

保存是 >、恢复是 <,指向文件。

1. 保存

# 保存
iptables-save
[root@localhost ~]# iptables-save
# Generated by iptables-save v1.8.11 (nf_tables) on Sat Aug 29 20:47:08 2026
*filter
:INPUT DROP [30:3480]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1945:188370]
-A INPUT -p icmp -m limit --limit 10/min -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT # 前面加 iptables 就是完整命令
COMMIT
# Completed on Sat Aug 29 20:47:08 2026


# 写入文件
iptables-save >/etc/sysconfig/iptables

# 这个文件原本记录的是默认配置
[root@localhost ~]# cat /etc/sysconfig/iptables
# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

2. 恢复

从指定文件加载规则,覆盖当前内核里的规则。这一步要谨慎,很容易被踢出 ssh:

# 恢复默认规则
# -F不对默认规则生效,需要先改回默认规则,否则会被踢出ssh
iptables -P INPUT ACCEPT
iptables -F
iptables -nL
iptables-restore </etc/sysconfig/iptables
[root@localhost ~]# iptables-restore </etc/sysconfig/iptables
[root@localhost ~]# iptables -nL
Chain INPUT (policy DROP)
target     prot opt source               destination         
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0            limit: avg 10/min burst 5
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

3. Linux 启动时为什么会自动读配置

[root@localhost ~]# systemctl cat iptables.service
# /usr/lib/systemd/system/iptables.service
[Unit]
Description=IPv4 firewall with iptables
AssertPathExists=/etc/sysconfig/iptables # 下面的脚本运行会读取该文件
Before=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/iptables/iptables.init start # systemctl start时运行的脚本
ExecReload=/usr/libexec/iptables/iptables.init reload
ExecStop=/usr/libexec/iptables/iptables.init stop
Environment=BOOTUP=serial
Environment=CONSOLETYPE=serial

[Install]
WantedBy=multi-user.target


# 看start的shell脚本,主要看case语句的 开和关匹配

cat /usr/libexec/iptables/iptables.init

case "$1" in
    start)
	[ -f "$VAR_SUBSYS_IPTABLES" ] && exit 0
	start # 调用了start函数
	RETVAL=$?
	;;
    stop)
	[ "x$IPTABLES_SAVE_ON_STOP" = "xyes" ] && save
	stop
	RETVAL=$?
	;;

esac

# vim输入/start()可以 匹配/搜索 函数
start() {
    # Do not start if there is no config file.
    if [ ! -f "$IPTABLES_DATA" ]; then # 检查配置文件
        echo -n $"${IPTABLES}: No config file."; warning; echo
        return 6
    fi

    # check if ipv6 module load is deactivated
    if [ "${_IPV}" = "ipv6" ] \ # 检查ipv6
        && grep -qIsE "^install[[:space:]]+${_IPV}[[:space:]]+/bin/(true|false)" /etc/modprobe.conf /etc/modprobe.d/* ; then
        echo $"${IPTABLES}: ${_IPV} is disabled."
        return 150
    fi

    echo -n $"${IPTABLES}: Applying firewall rules: "

    OPT=
    [ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c" # 比较参数
    if [ $IPTABLES_RESTORE_WAIT -ne 0 ]; then
       OPT="${OPT} --wait ${IPTABLES_RESTORE_WAIT}"
       if [ $IPTABLES_RESTORE_WAIT_INTERVAL -lt 1000000 ]; then
           OPT="${OPT} --wait-interval ${IPTABLES_RESTORE_WAIT_INTERVAL}"
       fi
    fi
# 这里是恢复的命令:restore 函数的核心
    $IPTABLES-restore $OPT $IPTABLES_DATA
    if [ $? -eq 0 ]; then # 上一条命令输出为0(通过)
        success; echo
    else
        failure; echo;
        if [ -f "$IPTABLES_FALLBACK_DATA" ]; then
            echo -n $"${IPTABLES}: Applying firewall fallback rules: "
            $IPTABLES-restore $OPT $IPTABLES_FALLBACK_DATA
            if [ $? -eq 0 ]; then
                success; echo
            else
                failure; echo; return 1
            fi
        else
            return 1
        fi
    fi

    # Load additional modules (helpers)
    if [ -n "$IPTABLES_MODULES" ]; then
        echo -n $"${IPTABLES}: Loading additional modules: "
        ret=0
        for mod in $IPTABLES_MODULES; do
            echo -n "$mod "
            modprobe $mod > /dev/null 2>&1
            let ret+=$?;
        done
        [ $ret -eq 0 ] && success || failure
        echo
    fi

    # Load sysctl settings
    load_sysctl

    touch $VAR_SUBSYS_IPTABLES
    return $ret
}


# 找到restore函数的核心$IPTABLES
# 发现在最上面设置了变量
IPTABLES=iptables

# 所以执行 systemctl start iptables的本质:
$IPTABLES-restore $OPT $IPTABLES_DATA
# 就是在执行 iptables-restore < /etc/sysconfig/iptables

这个 unit 文件照着 systemctl cat 看一遍就清楚了:

systemctl cat iptables.service,ExecStart 调的是 iptables.init 脚本

4. 案例小结

这块重点内容是要烂在脑子里的,笔试很可能考:

案例小结:封 ip/端口/网段、禁止 ping、限制速度和并发

顺便记住一句:云服务器的安全组,本质上就是防火墙的 filter 表。


四、filter 生产环境配置

filter 的默认规则通常配成白名单模式,也就是改成 DROP。既然默认是拒绝,那下面这几样都得显式改成 ACCEPT:ssh 放行、服务端口、连接状态、数据包进出、转发。

关于 -j 有一句口诀:改链就不加,写规则就加。

第一步,ssh:

# 如果默认拒绝一定先改回来
iptables -P INPUT ACCEPT
iptables -F
iptables -X
iptables -Z
iptables -nL
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -nL

回环网卡:

# 网卡参数
# -i为进,-o为出,后面跟上网卡名

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -nL

默认规则和 80/443 端口,默认规则在配置完所有规则之后再改:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

iptables -A INPUT -m multiport -p tcp --dport 80,443 -j ACCEPT
iptables -A INPUT -s 10.3.3.0/24 -j ACCEPT
iptables -A INPUT -s 192.168.73.0/24 -j ACCEPT
# 此处还可添加VPN网段,比如 10.7.1.0/24
iptables -A INPUT -s 10.7.1.0/24 -j ACCEPT

iptables-save >/etc/sysconfig/iptables

连接状态:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

总结起来长这样:

[root@localhost ~]# iptables-save
# Generated by iptables-save v1.8.11 (nf_tables) on Sat Aug 29 22:01:37 2026
*filter
:INPUT DROP [16:1816]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [68:6324]
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
-A INPUT -s 10.3.3.0/24 -j ACCEPT
-A INPUT -s 192.168.73.0/24 -j ACCEPT
-A INPUT -s 10.7.1.0/24 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Sat Aug 29 22:01:37 2026

iptables-save >/etc/sysconfig/iptables


[root@localhost ~]# iptables -nL
Chain INPUT (policy DROP)
target     prot opt source               destination         
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 80,443
ACCEPT     all  --  10.3.3.0/24          0.0.0.0/0           
ACCEPT     all  --  192.168.73.0/24      0.0.0.0/0           
ACCEPT     all  --  10.7.1.0/24          0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

Chain FORWARD (policy DROP)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

这一套配完,iptables-save >/etc/sysconfig/iptables 一存,开机就是白名单模式了。