Test wikitext: Difference between revisions

From 清冽之泉
Jump to navigation Jump to search
Blanked the page
Tag: Blanking
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
网站突然变慢、无法访问,或者重启 Apache 后立即恢复,可能不是带宽已经耗尽,而是大量 TCP 连接占用了 Apache 的进程、线程或连接队列。排查这类问题时,只需先建立一个简单框架:ss 负责观察连接,ipset 负责保存 IP 名单,iptables 负责决定放行或丢弃,connlimit 限制一个 IP 同时占用的连接数,hashlimit 限制一个 IP 建立新连接的速度。


== 观察连接现场:ss 与 watch ==
`ss` 是 Linux 中查看 Socket 状态的工具,可以把它理解成服务器网络层的现场监控器。它能够显示服务器是否仍在监听端口、目前有多少连接,以及这些连接处在 TCP 通信的哪个阶段。
下面的命令显示整个系统的 Socket 概况:
<syntaxhighlight lang="bash">
ss -s
</syntaxhighlight>
它适合快速判断服务器的连接总量是否突然异常,但不能直接说明 443 端口有多少连接。
下面的命令检查是否仍有程序监听 HTTPS 端口:
<syntaxhighlight lang="bash">
ss -lntp '( sport = :443 )'
</syntaxhighlight>
如果没有任何输出,说明当前没有程序监听 443 端口。问题通常应从 Apache 是否运行、HTTPS 配置是否成功加载、端口是否被其他程序占用等方向排查。
下面的命令统计已经完成 TCP 握手的 HTTPS 连接:
<syntaxhighlight lang="bash">
ss -Hnt state established '( sport = :443 )' | wc -l
</syntaxhighlight>
`ESTABLISHED` 表示 TCP 三次握手已经完成。这些连接可能来自正常用户、搜索引擎、爬虫、KeepAlive 或慢连接,因此连接数量很高并不自动等于正在遭受攻击。
下面的命令统计尚未完成握手的 HTTPS 连接:
<syntaxhighlight lang="bash">
ss -Hnt state syn-recv '( sport = :443 )' | wc -l
</syntaxhighlight>
如果 `SYN-RECV` 长时间异常增多,说明服务器收到了大量连接请求,但其中许多握手没有完成。这可能与 SYN flood、网络丢包或者 TCP 握手队列压力有关。
`watch` 本身不懂网络,它只是反复执行另一条命令。例如:
<syntaxhighlight lang="bash">
watch -n 1 "ss -Hnt state established '( sport = :443 )' | wc -l"
</syntaxhighlight>
这表示每秒重新统计一次已经建立的 HTTPS 连接。
'''ss 负责观察,watch 负责持续观察。'''
== 管理名单与检查流量:ipset 和 iptables ==
`ipset` 是一个 IP 名单管理工具。它可以保存单个 IP,也可以保存整个网段。它本身不决定放行还是封禁,只负责维护名单。
例如,`mw_white` 可以保存白名单,`mw_ban` 可以保存黑名单。iptables 只需使用一条规则,便能查询整个名单,不必为每个 IP 分别建立一条防火墙规则。
向黑名单加入一个 IP:
<syntaxhighlight lang="bash">
ipset add mw_ban 74.7.227.12
</syntaxhighlight>
向黑名单加入整个 `/24` 网段:
<syntaxhighlight lang="bash">
ipset add mw_ban 74.7.227.0/24
</syntaxhighlight>
一个 `/24` 网段通常包含最多 256 个 IPv4 地址。封禁整个网段能够一次处理大量同源地址,但也比封禁单个 IP 更容易影响同一网段中的正常来源。
iptables 是真正执行网络判断的工具。进入服务器的数据包会按照规则的先后顺序接受检查。规则可以检查来源地址、目标端口、连接状态和 ipset 名单,然后决定继续检查、接受、返回上一层规则或者直接丢弃。
`DROP` 表示静默丢弃数据包。`RETURN` 表示结束当前自定义链,返回调用它的上一层链继续检查。
`-I` 是插入规则,`-A` 是把规则追加到链尾。由于 iptables 从上到下检查规则,规则顺序会直接影响最终结果。
下面的命令可以查看 INPUT 链、规则编号和每条规则的命中次数:
<syntaxhighlight lang="bash">
iptables -L INPUT -n -v --line-numbers
</syntaxhighlight>
规则左侧的数据包数量会随着命中而增加,因此可以据此判断具体是哪条规则正在发挥作用。
'''ipset 是名单册,iptables 是按照名单和条件执行判断的门卫。'''
== 两种核心限制:connlimit 和 hashlimit ==
`connlimit` 解决的是并发连接问题。它关心的不是某个 IP 一天访问了多少次,而是这个 IP 此刻同时保持着多少条 TCP 连接。
如果一个来源 IP 同时保持几十甚至几百条连接,它可能持续占用服务器的 Socket、Apache 进程或工作线程。connlimit 可以在连接数量超过阈值以后,拒绝这个来源继续建立新连接。
'''connlimit 限制的是一个 IP 同时占用多少个座位。'''
`hashlimit` 解决的是新连接速度问题。有些异常流量不会长期保持大量连接,而是不断重复建立连接、关闭连接、再次建立连接。即使同时存在的连接数量不高,这种行为仍然会反复消耗 TCP 握手、TLS 握手和 Apache 资源。
使用 `--hashlimit-mode srcip` 时,每个来源 IP 都会单独计算速度。某个 IP 超过速率,只会影响这个 IP,不会让所有访问者共同争抢一个总额度。
'''hashlimit 限制的是一个 IP 冲进大门的速度。'''
hashlimit 看到的是 TCP 新连接,而不是 MediaWiki 页面请求。一个已经建立的 KeepAlive 连接可以连续发送多个 HTTP 请求,不会因为每次请求页面而重新进入 TCP 新连接状态。
因此,connlimit 和 hashlimit 主要处理连接层面的异常。真正的 HTTP 请求洪水还需要 CDN、WAF、反向代理或者 Apache 应用层规则处理。
== 最小防护规则 ==
为了避免把新增规则散落在原有 INPUT 链中,可以建立一条独立的自定义链。所有网站连接限制都集中放在这条链里,撤销时也只需要删除这一条入口和自定义链。
应用规则前,可以把当前状态保存为文本备份:
<syntaxhighlight lang="bash">
# 保存当前 iptables 规则
iptables-save > /root/iptables-before-web-guard.v4
# 保存当前 ipset 名单
ipset save > /root/ipset-before-web-guard.set
</syntaxhighlight>
建立独立的网站防护链:
<syntaxhighlight lang="bash">
# 如果防护链不存在,就创建它
iptables -nL MW-WEB-GUARD >/dev/null 2>&1 || \
iptables -N MW-WEB-GUARD
# 清空防护链中的旧测试规则
iptables -F MW-WEB-GUARD
</syntaxhighlight>
白名单来源跳过本链中的连接限制,但仍会返回 INPUT 链,继续接受服务器原有规则的检查:
<syntaxhighlight lang="bash">
# 白名单跳过本链中的并发和速率限制
iptables -A MW-WEB-GUARD \
  -m set --match-set mw_white src \
  -j RETURN
</syntaxhighlight>
限制单个 IPv4 地址同时占用过多网站连接:
<syntaxhighlight lang="bash">
# 单个 IPv4 地址同时超过 40 条网站连接时,拒绝继续建立新连接
iptables -A MW-WEB-GUARD \
  -p tcp --syn \
  -m connlimit \
  --connlimit-saddr \
  --connlimit-above 40 \
  --connlimit-mask 32 \
  -j DROP
</syntaxhighlight>
这条规则只在对方建立新连接时检查。`--connlimit-saddr` 表示按照来源地址统计,`--connlimit-mask 32` 表示每个 IPv4 地址单独计算。
限制单个 IPv4 地址持续高速建立新连接:
<syntaxhighlight lang="bash">
# 单个 IPv4 地址持续超过每秒 10 个新连接时,丢弃超出的连接
iptables -A MW-WEB-GUARD \
  -p tcp --syn \
  -m hashlimit \
  --hashlimit-name mw_web_new \
  --hashlimit-mode srcip \
  --hashlimit-above 10/second \
  --hashlimit-burst 30 \
  --hashlimit-htable-expire 600000 \
  -j DROP
</syntaxhighlight>
`10/second` 是持续速率,`burst 30` 用来容忍短时间的正常突发。该规则只丢弃超速期间的新连接,不会把来源 IP 永久加入黑名单。长期不活跃的速率记录会在十分钟后清理。
让进入 80 和 443 端口的 TCP 流量经过自定义防护链:
<syntaxhighlight lang="bash">
# 如果入口规则不存在,就把 80、443 流量送入网站防护链
iptables -C INPUT \
  -p tcp \
  -m multiport --dports 80,443 \
  -j MW-WEB-GUARD 2>/dev/null || \
iptables -I INPUT 1 \
  -p tcp \
  -m multiport --dports 80,443 \
  -j MW-WEB-GUARD
</syntaxhighlight>
`iptables -C` 用来检查入口规则是否已经存在。只有规则不存在时,后面的插入命令才会执行,因此重复运行不会不断产生相同入口。
流量进入 `MW-WEB-GUARD` 后,白名单会先返回原 INPUT 链。其他来源依次检查并发连接数和建立新连接的速度。没有超限的流量走到自定义链末尾时,也会自动返回 INPUT 链,继续经过原有的腾讯云规则、黑名单规则和其他防火墙规则。
这套命令使用的是 IPv4 的 `iptables`。如果服务器同时通过 IPv6 对外提供网站服务,IPv6 流量需要由 `ip6tables`、nftables 或相应的 IPv6 防火墙规则处理。
== 查看命中与撤销规则 ==
下面的命令显示自定义防护链及其命中次数:
<syntaxhighlight lang="bash">
iptables -L MW-WEB-GUARD -n -v --line-numbers
</syntaxhighlight>
如果 connlimit 或 hashlimit 规则前面的数据包计数持续增加,说明相应规则正在丢弃超限的新连接。
下面的命令显示 INPUT 链中的入口:
<syntaxhighlight lang="bash">
iptables -L INPUT -n -v --line-numbers
</syntaxhighlight>
INPUT 链中应当存在一条把 80、443 端口流量送入 `MW-WEB-GUARD` 的规则。
压力测试可以使用 Apache 自带的 `ab` 工具。例如:
<syntaxhighlight lang="bash">
ab -n 500 -c 50 https://qingliezhiquan.com/
</syntaxhighlight>
这表示总共发送 500 个请求,同时保持最多 50 个并发请求。由于 ab 默认会频繁建立新连接,它可能同时触发 connlimit 和 hashlimit。
如果压力测试的来源 IP 存在于 `mw_white` 中,该来源会跳过本链限制,因此不会验证这两条规则。
撤销规则时,先删除 INPUT 链中的入口:
<syntaxhighlight lang="bash">
# 删除 INPUT 通往网站防护链的入口
iptables -D INPUT \
  -p tcp \
  -m multiport --dports 80,443 \
  -j MW-WEB-GUARD
</syntaxhighlight>
然后清空并删除自定义链:
<syntaxhighlight lang="bash">
# 清空网站防护链
iptables -F MW-WEB-GUARD
# 删除网站防护链
iptables -X MW-WEB-GUARD
</syntaxhighlight>
由于新增限制都集中在自定义链中,这些操作不会删除 `mw_white`、`mw_ban`、腾讯云链或其他原有规则。
也可以使用备份完整恢复此前的 iptables 状态:
<syntaxhighlight lang="bash">
iptables-restore < /root/iptables-before-web-guard.v4
</syntaxhighlight>
== Apache 与防火墙的边界 ==
iptables 工作在 Apache 外部。它可以根据 IP、端口、TCP 标志、连接数量和连接速度丢弃流量,但它看不懂具体访问的是哪个 MediaWiki 页面,也不知道一个已经建立的连接中发送了多少次 HTTP 请求。
Apache 负责处理已经进入服务器的 HTTP 请求。慢速发送请求头、慢速上传请求体、KeepAlive 长时间空闲以及 Apache 工作线程被占满,都属于 Apache 层的问题。
`KeepAliveTimeout` 控制一次请求完成后,持久连接还可以空闲等待多久。等待时间较短,可以减少空闲连接长期占用服务器资源。
`RequestReadTimeout` 控制客户端必须在多长时间内、以怎样的最低速度发送完请求头或请求体。它主要用来处理故意极慢发送数据的 HTTP 客户端。
Apache 的 `event MPM` 比 `prefork MPM` 更擅长处理大量空闲 KeepAlive 连接,因为它不必让主要工作线程一直等待空闲连接。但 MPM 的选择还与 PHP 使用的是 mod_php 还是 PHP-FPM 有关。
'''iptables 负责控制谁能建立连接,Apache 负责控制连接进入以后怎样处理请求。'''
== 最终概念 ==
`ss` 用来观察服务器当前存在什么连接,以及这些连接处于什么 TCP 状态。
`ipset` 用来保存 IP 和网段名单。
`iptables` 用来按照规则顺序决定流量的去向。
`connlimit` 用来限制单个 IP 同时占用的连接数量。
`hashlimit` 用来限制单个 IP 建立新连接的速度。
Apache 负责处理已经进入服务器的 HTTP 请求。
CDN、WAF 和云厂商负责在服务器上游处理分布式攻击、带宽型攻击和应用层请求洪水。
最小防护结构只需要保留三个核心方向:已经确认的恶意来源进入 `mw_ban`,单 IP 并发连接过高由 connlimit 处理,单 IP 建立新连接过快由 hashlimit 处理。
'''防火墙规则的价值不在于数量,而在于每条规则都明确知道自己限制的对象。'''

Latest revision as of 23:32, 13 July 2026

网站突然变慢、无法访问,或者重启 Apache 后立即恢复,可能不是带宽已经耗尽,而是大量 TCP 连接占用了 Apache 的进程、线程或连接队列。排查这类问题时,只需先建立一个简单框架:ss 负责观察连接,ipset 负责保存 IP 名单,iptables 负责决定放行或丢弃,connlimit 限制一个 IP 同时占用的连接数,hashlimit 限制一个 IP 建立新连接的速度。

观察连接现场:ss 与 watch

`ss` 是 Linux 中查看 Socket 状态的工具,可以把它理解成服务器网络层的现场监控器。它能够显示服务器是否仍在监听端口、目前有多少连接,以及这些连接处在 TCP 通信的哪个阶段。

下面的命令显示整个系统的 Socket 概况:

ss -s

它适合快速判断服务器的连接总量是否突然异常,但不能直接说明 443 端口有多少连接。

下面的命令检查是否仍有程序监听 HTTPS 端口:

ss -lntp '( sport = :443 )'

如果没有任何输出,说明当前没有程序监听 443 端口。问题通常应从 Apache 是否运行、HTTPS 配置是否成功加载、端口是否被其他程序占用等方向排查。

下面的命令统计已经完成 TCP 握手的 HTTPS 连接:

ss -Hnt state established '( sport = :443 )' | wc -l

`ESTABLISHED` 表示 TCP 三次握手已经完成。这些连接可能来自正常用户、搜索引擎、爬虫、KeepAlive 或慢连接,因此连接数量很高并不自动等于正在遭受攻击。

下面的命令统计尚未完成握手的 HTTPS 连接:

ss -Hnt state syn-recv '( sport = :443 )' | wc -l

如果 `SYN-RECV` 长时间异常增多,说明服务器收到了大量连接请求,但其中许多握手没有完成。这可能与 SYN flood、网络丢包或者 TCP 握手队列压力有关。

`watch` 本身不懂网络,它只是反复执行另一条命令。例如:

watch -n 1 "ss -Hnt state established '( sport = :443 )' | wc -l"

这表示每秒重新统计一次已经建立的 HTTPS 连接。

ss 负责观察,watch 负责持续观察。

管理名单与检查流量:ipset 和 iptables

`ipset` 是一个 IP 名单管理工具。它可以保存单个 IP,也可以保存整个网段。它本身不决定放行还是封禁,只负责维护名单。

例如,`mw_white` 可以保存白名单,`mw_ban` 可以保存黑名单。iptables 只需使用一条规则,便能查询整个名单,不必为每个 IP 分别建立一条防火墙规则。

向黑名单加入一个 IP:

ipset add mw_ban 74.7.227.12

向黑名单加入整个 `/24` 网段:

ipset add mw_ban 74.7.227.0/24

一个 `/24` 网段通常包含最多 256 个 IPv4 地址。封禁整个网段能够一次处理大量同源地址,但也比封禁单个 IP 更容易影响同一网段中的正常来源。

iptables 是真正执行网络判断的工具。进入服务器的数据包会按照规则的先后顺序接受检查。规则可以检查来源地址、目标端口、连接状态和 ipset 名单,然后决定继续检查、接受、返回上一层规则或者直接丢弃。

`DROP` 表示静默丢弃数据包。`RETURN` 表示结束当前自定义链,返回调用它的上一层链继续检查。

`-I` 是插入规则,`-A` 是把规则追加到链尾。由于 iptables 从上到下检查规则,规则顺序会直接影响最终结果。

下面的命令可以查看 INPUT 链、规则编号和每条规则的命中次数:

iptables -L INPUT -n -v --line-numbers

规则左侧的数据包数量会随着命中而增加,因此可以据此判断具体是哪条规则正在发挥作用。

ipset 是名单册,iptables 是按照名单和条件执行判断的门卫。

两种核心限制:connlimit 和 hashlimit

`connlimit` 解决的是并发连接问题。它关心的不是某个 IP 一天访问了多少次,而是这个 IP 此刻同时保持着多少条 TCP 连接。

如果一个来源 IP 同时保持几十甚至几百条连接,它可能持续占用服务器的 Socket、Apache 进程或工作线程。connlimit 可以在连接数量超过阈值以后,拒绝这个来源继续建立新连接。

connlimit 限制的是一个 IP 同时占用多少个座位。

`hashlimit` 解决的是新连接速度问题。有些异常流量不会长期保持大量连接,而是不断重复建立连接、关闭连接、再次建立连接。即使同时存在的连接数量不高,这种行为仍然会反复消耗 TCP 握手、TLS 握手和 Apache 资源。

使用 `--hashlimit-mode srcip` 时,每个来源 IP 都会单独计算速度。某个 IP 超过速率,只会影响这个 IP,不会让所有访问者共同争抢一个总额度。

hashlimit 限制的是一个 IP 冲进大门的速度。

hashlimit 看到的是 TCP 新连接,而不是 MediaWiki 页面请求。一个已经建立的 KeepAlive 连接可以连续发送多个 HTTP 请求,不会因为每次请求页面而重新进入 TCP 新连接状态。

因此,connlimit 和 hashlimit 主要处理连接层面的异常。真正的 HTTP 请求洪水还需要 CDN、WAF、反向代理或者 Apache 应用层规则处理。

最小防护规则

为了避免把新增规则散落在原有 INPUT 链中,可以建立一条独立的自定义链。所有网站连接限制都集中放在这条链里,撤销时也只需要删除这一条入口和自定义链。

应用规则前,可以把当前状态保存为文本备份:

# 保存当前 iptables 规则
iptables-save > /root/iptables-before-web-guard.v4

# 保存当前 ipset 名单
ipset save > /root/ipset-before-web-guard.set

建立独立的网站防护链:

# 如果防护链不存在,就创建它
iptables -nL MW-WEB-GUARD >/dev/null 2>&1 || \
iptables -N MW-WEB-GUARD

# 清空防护链中的旧测试规则
iptables -F MW-WEB-GUARD

白名单来源跳过本链中的连接限制,但仍会返回 INPUT 链,继续接受服务器原有规则的检查:

# 白名单跳过本链中的并发和速率限制
iptables -A MW-WEB-GUARD \
  -m set --match-set mw_white src \
  -j RETURN

限制单个 IPv4 地址同时占用过多网站连接:

# 单个 IPv4 地址同时超过 40 条网站连接时,拒绝继续建立新连接
iptables -A MW-WEB-GUARD \
  -p tcp --syn \
  -m connlimit \
  --connlimit-saddr \
  --connlimit-above 40 \
  --connlimit-mask 32 \
  -j DROP

这条规则只在对方建立新连接时检查。`--connlimit-saddr` 表示按照来源地址统计,`--connlimit-mask 32` 表示每个 IPv4 地址单独计算。

限制单个 IPv4 地址持续高速建立新连接:

# 单个 IPv4 地址持续超过每秒 10 个新连接时,丢弃超出的连接
iptables -A MW-WEB-GUARD \
  -p tcp --syn \
  -m hashlimit \
  --hashlimit-name mw_web_new \
  --hashlimit-mode srcip \
  --hashlimit-above 10/second \
  --hashlimit-burst 30 \
  --hashlimit-htable-expire 600000 \
  -j DROP

`10/second` 是持续速率,`burst 30` 用来容忍短时间的正常突发。该规则只丢弃超速期间的新连接,不会把来源 IP 永久加入黑名单。长期不活跃的速率记录会在十分钟后清理。

让进入 80 和 443 端口的 TCP 流量经过自定义防护链:

# 如果入口规则不存在,就把 80、443 流量送入网站防护链
iptables -C INPUT \
  -p tcp \
  -m multiport --dports 80,443 \
  -j MW-WEB-GUARD 2>/dev/null || \
iptables -I INPUT 1 \
  -p tcp \
  -m multiport --dports 80,443 \
  -j MW-WEB-GUARD

`iptables -C` 用来检查入口规则是否已经存在。只有规则不存在时,后面的插入命令才会执行,因此重复运行不会不断产生相同入口。

流量进入 `MW-WEB-GUARD` 后,白名单会先返回原 INPUT 链。其他来源依次检查并发连接数和建立新连接的速度。没有超限的流量走到自定义链末尾时,也会自动返回 INPUT 链,继续经过原有的腾讯云规则、黑名单规则和其他防火墙规则。

这套命令使用的是 IPv4 的 `iptables`。如果服务器同时通过 IPv6 对外提供网站服务,IPv6 流量需要由 `ip6tables`、nftables 或相应的 IPv6 防火墙规则处理。

查看命中与撤销规则

下面的命令显示自定义防护链及其命中次数:

iptables -L MW-WEB-GUARD -n -v --line-numbers

如果 connlimit 或 hashlimit 规则前面的数据包计数持续增加,说明相应规则正在丢弃超限的新连接。

下面的命令显示 INPUT 链中的入口:

iptables -L INPUT -n -v --line-numbers

INPUT 链中应当存在一条把 80、443 端口流量送入 `MW-WEB-GUARD` 的规则。

压力测试可以使用 Apache 自带的 `ab` 工具。例如:

ab -n 500 -c 50 https://qingliezhiquan.com/

这表示总共发送 500 个请求,同时保持最多 50 个并发请求。由于 ab 默认会频繁建立新连接,它可能同时触发 connlimit 和 hashlimit。

如果压力测试的来源 IP 存在于 `mw_white` 中,该来源会跳过本链限制,因此不会验证这两条规则。

撤销规则时,先删除 INPUT 链中的入口:

# 删除 INPUT 通往网站防护链的入口
iptables -D INPUT \
  -p tcp \
  -m multiport --dports 80,443 \
  -j MW-WEB-GUARD

然后清空并删除自定义链:

# 清空网站防护链
iptables -F MW-WEB-GUARD

# 删除网站防护链
iptables -X MW-WEB-GUARD

由于新增限制都集中在自定义链中,这些操作不会删除 `mw_white`、`mw_ban`、腾讯云链或其他原有规则。

也可以使用备份完整恢复此前的 iptables 状态:

iptables-restore < /root/iptables-before-web-guard.v4

Apache 与防火墙的边界

iptables 工作在 Apache 外部。它可以根据 IP、端口、TCP 标志、连接数量和连接速度丢弃流量,但它看不懂具体访问的是哪个 MediaWiki 页面,也不知道一个已经建立的连接中发送了多少次 HTTP 请求。

Apache 负责处理已经进入服务器的 HTTP 请求。慢速发送请求头、慢速上传请求体、KeepAlive 长时间空闲以及 Apache 工作线程被占满,都属于 Apache 层的问题。

`KeepAliveTimeout` 控制一次请求完成后,持久连接还可以空闲等待多久。等待时间较短,可以减少空闲连接长期占用服务器资源。

`RequestReadTimeout` 控制客户端必须在多长时间内、以怎样的最低速度发送完请求头或请求体。它主要用来处理故意极慢发送数据的 HTTP 客户端。

Apache 的 `event MPM` 比 `prefork MPM` 更擅长处理大量空闲 KeepAlive 连接,因为它不必让主要工作线程一直等待空闲连接。但 MPM 的选择还与 PHP 使用的是 mod_php 还是 PHP-FPM 有关。

iptables 负责控制谁能建立连接,Apache 负责控制连接进入以后怎样处理请求。

最终概念

`ss` 用来观察服务器当前存在什么连接,以及这些连接处于什么 TCP 状态。

`ipset` 用来保存 IP 和网段名单。

`iptables` 用来按照规则顺序决定流量的去向。

`connlimit` 用来限制单个 IP 同时占用的连接数量。

`hashlimit` 用来限制单个 IP 建立新连接的速度。

Apache 负责处理已经进入服务器的 HTTP 请求。

CDN、WAF 和云厂商负责在服务器上游处理分布式攻击、带宽型攻击和应用层请求洪水。

最小防护结构只需要保留三个核心方向:已经确认的恶意来源进入 `mw_ban`,单 IP 并发连接过高由 connlimit 处理,单 IP 建立新连接过快由 hashlimit 处理。

防火墙规则的价值不在于数量,而在于每条规则都明确知道自己限制的对象。