配置 iptables 防火墙
Iptables 是专为 Linux 操作系统设计的防火墙,用于控制网络流量的通行。当有连接尝试访问服务器(或服务器向外发送请求)时,Iptables 会针对该连接检查规则链,并执行相应的设置。
所有现代 Linux 发行版都默认安装了 Iptables。
链的类型
iptables 有三种类型的链:INPUT、OUTPUT 和 FORWARD。
- INPUT — 用于处理入站连接。
- OUTPUT — 用于处理出站连接。
- FORWARD — 用于处理转发流量,例如路由器上的流量。如果您不需要配置路由,则不需要此类规则。
链是一组有序的规则。每条规则都包含一个匹配条件(例如数据包的源 IP 地址)以及对符合该条件的数据包要执行的动作(例如“允许”)。如果没有指定条件,则该规则适用于所有数据包。
在决定如何处理数据包时,iptables 会从规则列表的开头依次检查相应的链,直到找到匹配项为止。如果没有找到匹配项(连接不符合任何已创建的规则),则应用默认规则。
配置 iptables 规则时需要注意,许多端口要成功传输数据,需要先建立连接并收到响应。另外要小心,不要意外把自己拦在外面,例如通过 SSH 远程连接服务器也属于入站连接。
对连接执行的动作
可以对连接执行以下三种动作:
Accept — 允许连接。
Drop — 忽略(阻止)连接,且不向来源发送阻止通知。建议对连接到互联网的端口上的流量使用此动作,因为这样攻击者在扫描端口时获得的信息最少。
Reject — 拒绝连接,并通知请求来源连接已被阻止。默认会返回 "icmp-port-unreachable" 响应包,也可以另外指定其他消息(例如 "icmp-host-unreachable"、"icmp-net-prohibited"、"icmp-host-prohibited" 等)。
配置规则
本文中配置规则的通用格式如下:
iptables 操作 链 规则
该格式中省略了表,因为我们讨论的是主过滤表 filter 的配置,iptables 命令默认使用该表,无需额外指定。
这里的操作是指对规则执行的步骤(例如添加或删除规则)。
iptables 中可用操作的示例:
- -A — 向链中添加规则;
- -I — 按指定编号向链中插入规则;
- -D — 删除规则;
- -F — 删除所有规则;
- -L — 列出当前链中的所有规则;
- -P — 设置默认动作。
其他选项:
- -p — 指定数据包的协议;
- -s — 指定数据包的源 IP 地址;
- -j — 指定如何处理数据包(允许、阻止等)。
查看现有规则
使用以下命令列出所有规则:
iptables -L
或者使用输出更详细的命令:
iptables -L -n -v
您也可以查看特定链的规则,例如 INPUT 链:
iptables -L INPUT
默认规则
如果已创建的规则都不匹配入站数据包,则会应用默认规则。
要查看默认规则,请执行以下命令:
iptables -L | grep policy
如果您没有更改过默认策略,那么所有链初始都设置为允许。
要设置默认规则,请使用 -P 选项,例如:
iptables -P FORWARD DROP
配置示例
要向现有链中添加规则,请执行:
iptables -A
如果需要将规则放在列表中的其他位置而非末尾,可以使用以下命令格式并指定规则在列表中的编号:
iptables -I 链 编号 规则
例如,以下规则将成为 INPUT 链中的第一条规则:
iptables -I INPUT 1 --dport 80 -j ACCEPT
阻止来自特定 IP 的所有入站连接:
iptables -A INPUT -s 1.2.3.4 -j DROP
阻止来自特定子网的连接:
iptables -A INPUT -s 1.2.3.4/24 -j DROP
来源既可以是 IP 地址,也可以是主机名。例如,禁止来自 test.domain.ru 的所有连接:
iptables -A INPUT -s test.domain.ru -j DROP
禁止来自 test.domain.ru 以外主机的连接:
iptables -A INPUT ! -s test.domain.ru -j DROP
向所有人开放 25 端口(SMTP):
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT
对所有人封禁 25 端口(SMTP)(只需将 ACCEPT 替换为 DROP):
iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j DROP
向所有人开放 Apache 端口:
iptables -A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT
允许特定 IP 访问 3306 端口(MySQL):
iptables -A INPUT -s 1.2.3.4 -p tcp -m tcp --dport 3306 -j ACCEPT
配置日志记录:
iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j LOG --log-level INFO --log-prefix "New connection from 1.2.3.4/24:"
iptables -A INPUT -s 1.2.3.4/24 -m multiport --dports 22,8080,139,445 -j ACCEPT
这样配置后,来自 1.2.3.4/24 子网到服务器的每个新连接都会被记录到日志中。
为防御常见攻击,可以添加以下设置:
阻止所有“无法识别”的数据包:
iptables -A INPUT -m state --state INVALID -j DROP
阻止空数据包:
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
防御 syn-flood 攻击:
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP
阻止分片数据包并防御 ping flood:
iptables -A INPUT -p icmp --fragment -j LOG --log-prefix "ping flooding"
iptables -A INPUT -p icmp --fragment -j DROP
禁止 ping:
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
iptables -A INPUT -i eth0 -p icmp --icmp-type echo-request -j DROP
允许特定地址 ping:
iptables -A INPUT -s 1.2.3.4 -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -s 1.22.33.44 -p icmp --icmp-type echo-request -j ACCEPT
将 80 端口的并发连接数(connlimit)限制为 5:
iptables -A INPUT -p tcp -m tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m connlimit --connlimit-above 5 --connlimit-mask 32 -j DROP
保存更改
为了让已创建的规则在系统重启后仍然有效,需要将其保存。
在 CentOS 上使用以下命令:
/sbin/service iptables save
如果您使用的是 Debian 或 Ubuntu,建议安装 iptables-persistent 软件包来保存规则。可以使用以下命令安装:
apt install iptables-persistent
安装过程中会询问是否保存当前规则,请选择“是”。
修改 iptables 规则后,执行以下命令保存:
netfilter-persistent save
删除规则
要删除特定规则,请使用 -D 选项,例如:
iptables -D INPUT -s 1.2.3.4 -j DROP
要删除所有规则,请执行以下命令:
iptables -F
要删除特定链的规则,请执行:
iptables -F INPUT