安全运维中几条实用的 iptables 规则总结
案例一
假设运行 iptables 的 Linux 主机作为企业的网关防火墙,
其上有2个以太网卡:eth0 连接 Internet,使用公网 IP ;eth1 连接企业内网,使用局域网 IP,要限制内网用户访问 www.evil.com
iptables -A OUTPUT -o eth0 -p tcp -d www.evil.com --dport 80 -j DROP
或者
iptables -A OUTPUT -o eth0 -p tcp -d ! www.evil.com --dport 80 -j ACCEPT
注意,如果这里的策略不能生效,将域名换为 FQDN ,即 www.evil.com.
另外,因为没有使用 iptables 的扩展模块,所以域名会进行 DNS 解析,得到结果后才向内存写入该条策略;这意味着,必须分别在出站方向放行 UDP 的目标端口 53 ;在入站方向放行 UDP 的源端口 53
案例二
网络拓扑同案例一,假设企业有内部网站,并且只允许员工访问其内部站点
iptables -A FORWARD -i eth1 -o eth0 -p tcp --dport 80 -j DROP
eth0 和 eth1 是以太网接口;Linux 支持的其它类型网络接口,常见的有:
ppp0 第一个 PPPOE(以太网上的点到点协议) 接口
lo 本地环回接口,即 127.0.0.1
fddi0 第一个光纤数字用户设备接口,即光纤接口
案例三
假设运行 iptables 的 Linux 主机作为 SSH 服务器,IP 地址为 192.168.0.1
把每个尝试远程 ssh 登录的客户端 IP 记录在一个临时列表中,只要列表中的 IP一小时以内,尝试登录次数达到3次(包括密码输错3次,以及重复登录-退出达到3次,以及连续登录达到3次,例如连开3个 putty 登录)
第3次登录时将被拒绝,持续一小时后才能再次登录,注意,前2次成功的登录并不会断开,除非你自行退出,否则已经成功的登录会话将保持连接,后续的登录尝试将被拒绝一小时
下面这3条规则必须一起使用,并且假设第一条规则将添加至 INPUT 链的第一条规则,注意 -I 选项后接的 INPUT 链规则编号,按照这里的操作输入,这3条规则将变成 INPUT 链的前3条规则,从而达到优先匹配进站的 SSH 连接请求的目的:
iptables -I INPUT -d 192.168.0.1 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH iptables -I INPUT 2 -d 192.168.0.1 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 3600 --hitcount 3 --name SSH -j DROP iptables -I INPUT 3 -d 192.168.0.1 -p tcp -m tcp --dport 22 -j ACCEPT
这对于阻止暴力破解 SSH 登录的弱口令非常有效,当然,设置足够健壮,复杂,易于记忆的密码,也是必需的
案例四
运维管理员在运行 iptables 的 Linux 网关主机上检测到来自某个 B 类 IP 网段
172.16.0.0/16
的频繁扫描流量,希望设置 iptables 规则封堵该 IP 地址段的 65534 台可疑主机,两小时后解封:
iptables -I INPUT -s 172.16.0.0/16 -j DROP iptables -I FORWARD -s 172.16.0.0/16 -j DROP at now +2 hours iptables -D INPUT 1 iptables -D FORWARD 1//此处按Ctrl+D组合键 job 4 at 2014-10-01 09:26
案例五
场景类似案例四,但是这次允许转发来自 C类 IP 网段
192.168.0.0/24 中 253 台主机的 DNS 解析请求与本地 DNS 回送的 DNS 应答数据包,在案例四的策略基础上,再添加下面规则:
iptables -A FORWARD -s 192.168.0.0/24 -p udp --dport 53 -j ACCEPT iptables -A FORWARD -d 192.168.0.0/24 -p udp --sport 53 -j ACCEPT
案例六:结合NAT与FILTER表实现允许内网特定主机使用公网IP访问特定互联网服务。
假设企业内部一台作为网关路由器的 CentOS 上有2块网卡:eth0 的 IP 101.102.103.104 连接公网,网卡eth1 的 IP 172.16.1.1 连接内网 172.16.1.0/24,
(拓扑如图一所示)
要实现内网中其它计算机共用公网IP访问互联网,则需要在作为网关路由器上的Linux上制定下列 iptables 规则(规则一):
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -o eth0 -j SNAT --to-source 101.102.103.104
上述规则表示来自源地址(-s)范围 172.16.1.0/24 的数据包在经过路由后(POSTROUTING),从 eth0 网卡出去前(-o),将源 IP 转换(SNAT --to-source)为 101.102.103.104;注意,如果是在供 iptables-restore 读取的规则文件中编写,则可以省略 “iptanles -t -nat”前缀,前提是该规则位于“*nat”字段下。
如果图一中的 CentOS 路由器前端还有一个使用 PPPoE 协议拨号的 ADSL/Cable Modem,那么从 ISP 分配到的公网 IP 通常是动态的,每隔一段时间会自动协商并且更新一次(当然现在的企业很少是这种情况,企业通常向 ISP 租用能分配到多个静态公网 IP 的专线),此时就需要将规则一改成下列:
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -o eth0 -j SNAT MASQUERADE
这样 NetFilter 内核模块将自动使用动态公网IP进行转换;
如果图一中的 CentOS 路由器本身就带有 PPPoE 拨号所需的特殊接口网卡(这类接口通常是由家用路由器或者Cisco等大型互联网路由器提供),那么需要将规则一改成下列:
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -o pppX -j SNAT --to-source 101.102.103.104
上述规则中的X值取决于你的网络环境,可以使用 ifconfig 查看。
如果图一中的 CentOS 路由器的网卡 eth0 从 ISP 分配到多个静态公网 IP:
101.102.103.104~101.102.103.110,要实现内网计算机“轮询”使用这7个公网IP 访问互联网,则需要将规则一改成下列:
iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -o eth0 -j SNAT --to-source 101.102.103.104-101.102.103.110
在前面 nat 表的 POSTROUTING 链的 SNAT 例子中,仅仅实现了公网 IP——内网IP 的转换,假设现在图一中的 PC 1(172.16.1.2 )要使用路由器的公网 IP 访问互联网上的 web(即HTTP,web服务器监听在 TCP 80端口)服务,则需要进一步在 iptables 的 filter 表中指定相应的规则如下:
iptables -t filter -A FORWARD -s 172.16.1.2/32 -i eth1 -o eth0 -p tcp -m tcp --dport 80 -j ACCEPT
上述规则表示允许转发从网卡 eth1 进入(-i eth1),从网卡 eth0 出去(-o eth0);源地址为 172.16.1.2,协议为 tcp(-p tcp ),目标端口为 80(--dport 80)的数据包。
注意,在制定上述规则前需要确认 filter 表的 forward 链的默认规则为 drop,意味着默认禁止在内外网转发所有数据包,然后再像上面这样逐一去“开通”允许转发的数据包特征,这也就是让 iptables 基于白名单匹配的规则制定思路。
选择 forward 链的原因在于,来自或去往 172.16.1.0/24 网段的数据包需要经由本路由器路由决策后“转发”(forward)。
我们知道,TCP连接是双向的,光有上面这条转发规则还不够,因为这样只能让数据包从内网出去;应答的数据包不能从外网进来,因此需要下面这条规则一起使用,注意所有的参数都取决于数据包流向而改变:
iptables -t filter -A FORWARD -d 172.16.1.2/32 -i eth0 -o eth1 -p tcp -m tcp --sport 80 -j ACCEPT
再次参考图一。由于反方向回来的数据包会自动通过 nat 表的 PREROUTING 链执行转换,再通过 filter 表过滤,因此 forward 链在匹配时都是转换后的内网 IP(此例中),如下书写规则将导致 iptables 无法转发数据包:
iptables -t filter -A FORWARD -d 101.102.103.104 -i eth0 -o eth1 -p tcp -m tcp --sport 80 -j ACCEPT
上面 2 条规则和 nat 表的 SNAT 规则一起使用,仅实现了 172.16.1.2 这台主机使用公网 IP 访问互联网的 HTTP(80端口)服务,要访问 HTTPS 服务(HTTP Over SSL,web 服务器监听在 TCP 443端口)和域名解析,还需要允许TCP 443 和 UDP 53端口,并且应该将域名解析的规则放在 HTTP 和 HTTPS的规则之前,如下:
iptables -t filter -A FORWARD -s 172.16.1.2/32 -i eth1 -o eth0 -p udp -m udp --dport 53 -j ACCEPT iptables -t filter -A FORWARD -d 172.16.1.2/32 -i eth0 -o eth1 -p udp -m udp --sport 53 -j ACCEPT iptables -t filter -A FORWARD -s 172.16.1.2/32 -i eth1 -o eth0 -p tcp -m tcp --dport 80 -j ACCEPT iptables -t filter -A FORWARD -d 172.16.1.2/32 -i eth0 -o eth1 -p tcp -m tcp --sport 80 -j ACCEPT
这样就实现了通过iptables允许内网特定主机使用公网IP访问特定互联网服务。
我们也可以直接用文本编辑器编写规则,具体书写语法可以参考用 iptables-save
命令生成的规则文件,当然也可以直接对其进行修改。如果要实现系统在启动时自动读取该文件中的规则来过滤,则需要在 /etc/rc.d/rc.local 配置文件中添加一行:
/sbin/iptables-restore < /root/桌面/my-iptables-rule
上面假定规则文件的存放位置在 /root/桌面,名为 my-iptables-rule,并且需要
iptables 命令的完整路径(可以使用 whereis iptables 查找),最后,记得将文件的所有者与所属主改成 root,权限改为 700
案例七:通过NAT表实现多个内网服务器共用一个公网IP对外提供服务(NATP,网络地址端口转换)。
假设企业内部一台作为网关路由器的 CentOS 上有3块网卡:eth0 的 IP 101.102.103.104 连接公网,网卡eth1 的 IP 172.16.1.1 连接内网 172.16.1.0/24,网卡 eth2 的 IP 192.168.1.1 连接内网 192.168.1.0/24;
内网 192.168.1.0/24 作为非军事防御区(DMZ),其中一台 Server1 IP 为
192.168.1.2,对外提供HTTP+HTTPS 服务,另一台 Sever2 IP 为 192.168.1.3,
对外提供传统 Mail 服务(非 web mail),
(拓扑如图二所示)
要实现互联网用户能够访问 DMZ 中Sever1 上的 HTTP/S 服务,需要在CentOS上制定下列 iptables 规则:
iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to 192.168.1.2:80 iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to 192.168.1.2:443
结合图二,不难看出上述规则就是将入站方向请求连接 CentOS 公网 IP 的 TCP目标端口80和443的数据包在路由前,将其目标地址转换为 DMZ中 Servre1 的相应地址和端口,然后路由至相应网段;对于Sever2上的 Mail 服务,以及使用其它应用层协议的服务,制定规则类似:
iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 25 -j DNAT --to 192.168.1.3:25 iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 110 -j DNAT --to 192.168.1.3:110
另外,如果Sever1也需要主动(TCP数据包的状态非ESTABLISHED,而是 NEW)访问互联网上的其它服务器(下载更新软件和安全补丁),还需要添加下列规则:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 101.102.103.104
结合图二应该可以很容易了解上述规则中的各项参数作用,另外,规则中的 -s 192.168.1.0/24 ,意味着 Sever2 也可以主动访问互联网了。
案例八 :制定 iptables 安全规则实现阻挡 NMAP, Hping 等网络扫描工具发出的探测包
上述踩点工具通常会在全端口范围内(1-65535)扫描目标的开放端口,然后尝试枚举相应服务的版本,漏洞,其原理无非是发出带有特定 TCP 标识位组合的扫描包,然后通过目标返回的响应来判断,因此我们可以通过 iptables 丢弃这些探测包,从而保证网关和内网主机安全,具体规则如下:
丢弃隐蔽扫描包:
iptables -t filter -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
丢弃所有标识位都清位的扫描包(NMAP中的NULL扫描):
iptables -t filter -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
丢弃SYN和RST都置位的扫描包:
iptables -t filter -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
丢弃FIN和RST都置位的扫描包:
iptables -t filter -A INPUT -p tcp --tcp-flags FIN,RST SYN,RST -j DROP
丢弃只有FIN置位,没有预期与ACK一起置位的扫描包(NMAP的XMAS扫描之一):
iptables -t filter -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
丢弃只有PSH置位,没有预期与ACK一起置位的扫描包(NMAP的XMAS扫描之一):
iptables -t filter -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP
丢弃只有URG置位,没有预期与ACK一起置位的扫描包(NMAP的XMAS扫描之一):
iptables -t filter -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP
案例九:一个作为个人桌面型PC使用的 Linux iptables 规则文件,使用 iptables-save 自动生成,可以作为日后自行编写规则文件的基础模板:
# Generated by iptables-save v1.4.7 on Sun Aug 30 22:18:39 2015 *nat :PREROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [367:22484] :OUTPUT ACCEPT [370:22712] COMMIT # Completed on Sun Aug 30 22:18:39 2015 # Generated by iptables-save v1.4.7 on Sun Aug 30 22:18:39 2015 *mangle :PREROUTING ACCEPT [13883:18761885] :INPUT ACCEPT [13883:18761885] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [8935:760997] :POSTROUTING ACCEPT [8932:760769] COMMIT # Completed on Sun Aug 30 22:18:39 2015 # Generated by iptables-save v1.4.7 on Sun Aug 30 22:18:39 2015 *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT DROP [3:228] -A INPUT -m state --state NEW -j DROP -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP -A INPUT -p tcp -m tcp --tcp-flags FIN,RST SYN,RST -j DROP -A INPUT -p tcp -m tcp --tcp-flags FIN,ACK FIN -j DROP -A INPUT -p tcp -m tcp --tcp-flags PSH,ACK PSH -j DROP -A INPUT -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -p udp -m udp --sport 53 -j ACCEPT -A INPUT -p tcp -m tcp --sport 80 -j ACCEPT -A INPUT -p tcp -m tcp --sport 443 -j ACCEPT -A OUTPUT -o lo -j ACCEPT -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT -A OUTPUT -p tcp -m multiport --dports 1024:65535 -j LOG -A OUTPUT -p udp -m multiport --dports 1024:65535 -j LOG COMMIT # Completed on Sun Aug 30 22:18:39 2015
注意部署最后2条规则的用意:
一般情况,从本地出站的主动请求连接的数据包,应该都是访问互联网上公用服务如 80,443,53,22 等目标端口的数据包,也就是 dport 为 1024 以下的,如果 dport 在 1024 以上的出站包,就有问题了,有可能是连接目标机上 P2P 对等点或者反弹式***/ rootkit 客户端开放的高位端口,因此我们可以将其记录下来并查看日志,追踪其目标地址(配合 rsyslog 服务),这是通过 iptables 的 multiport 模块实现的,连续端口用冒号连接,非连续端口用逗号隔开。
该文件中的策略安全性还可以进一步加强,例如,将 nat表中的三个链默认动作设置为 drop;
并且,如果该表使用在NAT网关路由器上,还需要执行下列命令开启内核转发 IPv4 数据包的功能:
echo 1 > /proc/sys/net/ipv4/ip_forward
或者
vim /etc/sysctl.conf net.ipv4.ip_forward = 1
由于 /proc 路径下的所有内容实际在内存中,即基于内存的虚拟文件系统,因此第一种方法只能临时生效,重启后失效(内存是易失性存储器)
第二种方法修改的是磁盘上的文件,由内核每次在启动时读取,因为磁盘是非易失的,因此永久有效。