目录
iptables脚本
本文讲述个人使用的iptables脚本,iptables是Linux下的netfilter防火墙配置工具。
配置iptables需要有TCP/IP协议的背景知识,以及对netfilter架构的了解,在此推荐Iptables-tutorial,这是一个非常不错的网站,个人的新版本脚本也大量借鉴了其中的做法,感谢作者的贡献。
脚本框架
iptables脚本遵循基本的脚本规范,提供start、stop、restart功能。基本框架如下:
# # Global configuration. # IPTABLES="/usr/sbin/iptables" MODPROBE="/sbin/modprobe" start() { ... } resume_all() { ... } stop() { ... } case "$1" in 'start') start ;; 'stop') stop resume_all ;; 'restart') stop start ;; *) echo "usage $0 start|stop|restart" esac
脚本类型
不同角色的机器需要不同的防火墙设置,这里按照客户机、网关、服务器三种最常用的角色,分别提供三种脚本模板:
- 客户机模板:rc.iptables-client.ref
- 网关模板:rc.iptables-gate.ref
- 服务器模板:rc.iptables-server.ref
此外,还有一个增加了OpenVPN支持的网关模板:rc.iptables-gate-openvpn.ref,详细说明可参见OpenVPN的简单配置的相关部分。
使用时,先根据具体环境选择模板,再按实际情况进行更改调整。
不同角色脚本的主要区别在start()函数,下面就各个函数做简要说明(脚本里也有注释)。
脚本函数
客户机start()函数
配置接口参数
参数包括ip地址,接口名称等。对于客户机这些参数一般不用设置,因为客户机通常作为终端使用,不需要那么精确控制:
# 1.1 Local Area Network configuration. # LAN_IP="10.10.10.10" LAN_IFACE="eth0" LAN_BROADCAST="10.10.10.255" # # 1.2 Loopback configuration. # LO_IP="127.0.0.1" LO_IFACE="lo"
装载内核模块
这里缺省只装载ip_conntrack_ftp,以处理FTP应用:
# 2.1 Required modules. # $MODPROBE ip_conntrack_ftp # # 2.2 Non-Required modules. # #$MODPROBE ip_conntrack_tftp #$MODPROBE ip_conntrack_irc
接下来是Filter表的设置,客户机不涉及NAT表和Mangle表设置。
缺省策略
缺省策略设置为禁止一切数据:
# 3.1 Set default policies. # $IPTABLES -P INPUT DROP $IPTABLES -P OUTPUT DROP $IPTABLES -P FORWARD DROP
分片包
虽然分片包有存在的理由,但在当今的网络现状下,已经很少了。分片出现更多的是源于攻击,所以禁止分片包(缺省直接丢弃,也可打开注释同时记录到日志里):
# 3.2 Drop all fragment packets. # #$IPTABLES -A INPUT -f -j LOG --log-prefix "iptables[fragment]:" $IPTABLES -A INPUT -f -j DROP
Loopback接口
对于本地loopback接口不做限制:
# 3.3 Loopback rules. # $IPTABLES -A INPUT -i $LO_IFACE -j ACCEPT
Input链设置
客户机一般是不提供对外服务的,所以只允许相应的应答包进入本机(包括ESTABLISHED和RELATED状态):
# 3.4.1 Allow all established and related packets. # $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
提供的对外服务需要明确指定(这里缺省提供ssh和ping服务),别的服务可参照添加:
# 3.4.2 Allow ssh. # $IPTABLES -A INPUT -p tcp --dport ssh --syn -m state --state NEW -j ACCEPT # # 3.4.3 Allow ping. # $IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
在Windows网络环境下,会有大量的广播数据包,对Linux是没用的,如果需要,可以丢弃这些包:
# 3.4.4 In Microsoft Networks you will be swamped by broadcast. These lines # will prevent them from showing up in the logs. # #$IPTABLES -A INPUT -d $LAN_BROADCAST -p udp --dport 135:139 -j DROP # # 3.4.5 If we get dhcp request from the outside of our network, our logs # will be swamped as well. This rule will block them from getting logged. # #$IPTABLES -A INPUT -d 255.255.255.255 -p udp --dport 67:68 -j DROP # # 3.4.6 If you have a Microsoft Network on the outside of your firewall, # you may also get flooded by Multicast. We drop them so we do not get # flooded by logs. # #$IPTABLES -A INPUT -d 224.0.0.0/8 -j DROP
如果需要,可以将其他数据包记录到日志里,供后续处理:
# 3.4.7 Log rules. # #$IPTABLES -A INPUT -j LOG --log-prefix "iptables[input]:"
Output链设置
客户机可以访问任何地方,不做限制:
# 3.5.1 Allow full access. # $IPTABLES -A OUTPUT -j ACCEPT
Forward链设置
客户机是单点终端,不涉及Forward方面的配置。
网关start()函数
虽然角色不同,但start()函数的基本框架是一致的,所以相同的设置将不再重复讲述,完整的说明可参见脚本内容。
配置接口参数
网关作为网络的枢纽,一般都是有多个接口的,比如内网、外网、dmz接口,有的还配有专门的管理接口mng。
这里按四个接口的规格进行设计:
# 1.1 Local Area Network configuration. # LAN_IP="10.10.10.1" LAN_IP_RANGE="10.10.10.0/24" LAN_IFACE="eth0" LAN_BROADCAST="10.10.10.255" # # 1.2 Internet configuration. # WAN_IP="172.16.0.10" WAN_IFACE="eth1" #WAN_IFACE="ppp+" WAN_BROADCAST="172.16.0.255" # # 1.3 DMZ configuration. # DMZ_IP="10.10.20.1" DMZ_IFACE="eth2" DMZ_BROADCAST="10.10.20.255" DMZ_HTTP_IP="10.10.20.10" DMZ_FTP_IP="10.10.20.20" DMZ_DNS_IP="10.10.20.30" # # 1.4 Management configuration. # MNG_IP="10.10.30.1" MNG_IFACE="eth3" MNG_BROADCAST="10.10.30.255"
装载内核模块
网关通常要做NAT,所以FTP应用多加载了ip_nat_ftp模块:
# 2.1 Required modules. # $MODPROBE ip_conntrack_ftp $MODPROBE ip_nat_ftp # # 2.2 Non-Required modules. # #$MODPROBE ip_conntrack_tftp #$MODPROBE ip_conntrack_irc #$MODPROBE ip_nat_tftp #$MODPROBE ip_nat_irc
接下来是Filter表的设置。
分片包
除了禁止到达本机的分片包外,也不转发分片包:
# 3.2 Drop all fragment packets. # #$IPTABLES -A INPUT -f -j LOG --log-prefix "iptables[fragment]:" $IPTABLES -A INPUT -f -j DROP #$IPTABLES -A FORWARD -f -j LOG --log-prefix "iptables[fragment]:" $IPTABLES -A FORWARD -f -j DROP
Loopback接口
对于本地loopback接口同样不做限制(相比客户机,这里多了一条OUTPUT设置,因为后续要对Output链进行具体配置):
# 3.3 Loopback rules(allow all lookback packets). # $IPTABLES -A INPUT -i $LO_IFACE -j ACCEPT $IPTABLES -A OUTPUT -o $LO_IFACE -j ACCEPT
Input链设置
允许相应的应答包进入本机(包括ESTABLISHED和RELATED状态):
# 3.4.1 Allow all established and related packets. # $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
网关提供服务要慎之又慎。这里缺省允许在内网接口和管理接口接入ssh,允许在内网接口、管理接口和DMZ接口接受ping请求:
# 3.4.2 Allow ssh for management in LAN and MNG network. # $IPTABLES -A INPUT -i $LAN_IFACE -p tcp --dport ssh --syn -m state \ --state NEW -j ACCEPT $IPTABLES -A INPUT -i $MNG_IFACE -p tcp --dport ssh --syn -m state \ --state NEW -j ACCEPT # # 3.4.3 Allow ping in LAN, DMZ and MNG network. # $IPTABLES -A INPUT -i $LAN_IFACE -p icmp --icmp-type echo-request -j ACCEPT $IPTABLES -A INPUT -i $DMZ_IFACE -p icmp --icmp-type echo-request -j ACCEPT $IPTABLES -A INPUT -i $MNG_IFACE -p icmp --icmp-type echo-request -j ACCEPT
如果为内网提供DHCP服务,则打开如下规则:
# 3.4.4 Allow dhcp requests from LAN. # #$IPTABLES -A INPUT -i $LAN_IFACE -p udp --sport bootpc \ # --dport bootps -j ACCEPT
如果为内网提供DNS域名查询服务,则打开如下规则:
# 3.4.5 Allow dns requests from LAN. # #$IPTABLES -A INPUT -i $LAN_IFACE -p udp --dport domain -m state \ # --state NEW -j ACCEPT
Output链设置
首先允许相应的应答包离开本机(即ESTABLISHED和RELATED状态):
# 3.5.1 Allow all established and related packets. # $IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
允许网关访问的服务,如下依次定义:
# 3.5.2 Allow ftp(21). # $IPTABLES -A OUTPUT -p tcp --dport ftp --syn -m state --state NEW -j ACCEPT # # 3.5.3 Allow ssh(22). # $IPTABLES -A OUTPUT -p tcp --dport ssh --syn -m state --state NEW -j ACCEPT # # 3.5.4 Allow smtp(25). # $IPTABLES -A OUTPUT -p tcp --dport smtp --syn -m state --state NEW -j ACCEPT # # 3.5.5 Allow dns request(53). # $IPTABLES -A OUTPUT -p udp --dport domain -m state --state NEW -j ACCEPT # # 3.5.6 Allow dhcp request(67). # $IPTABLES -A OUTPUT -p udp --dport bootps -m state --state NEW -j ACCEPT # # 3.5.7 Allow http(80). # $IPTABLES -A OUTPUT -p tcp --dport http --syn -m state --state NEW -j ACCEPT # # 3.5.8 Allow https(443). # $IPTABLES -A OUTPUT -p tcp --dport https --syn -m state --state NEW -j ACCEPT # # 3.5.9 Allow ping. # $IPTABLES -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
对于非正常的访问,可记录进日志:
# 3.5.10 Log rules. # #$IPTABLES -A OUTPUT -j LOG --log-prefix "iptables[output]:"
Forward链设置
首先允许转发所有的应答数据(即ESTABLISHED和RELATED状态):
# 3.6.1 Allow all established and related packets. # $IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
具体定义内网对外网的访问(缺省都是关闭的,可按需打开):
# 3.6.2 LAN --> WAN rules. # # 3.6.2.1 Allow ftp(21). # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p tcp --dport ftp \ # --syn -m state --state NEW -j ACCEPT # # 3.6.2.2 Allow ssh(22). # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p tcp --dport ssh \ # --syn -m state --state NEW -j ACCEPT # # 3.6.2.3 Allow smtp(25). # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p tcp --dport smtp \ # --syn -m state --state NEW -j ACCEPT # # 3.6.2.4 Allow dns request(53). # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p udp --dport domain \ # -m state --state NEW -j ACCEPT # # 3.6.2.5 Allow http(80). # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p tcp --dport http \ # --syn -m state --state NEW -j ACCEPT # # 3.6.2.6 Allow https(443). # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p tcp --dport https \ # --syn -m state --state NEW -j ACCEPT # # 3.6.2.7 Allow ping. # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -p icmp \ # --icmp-type echo-request -j ACCEPT
允许内网对DMZ网络的完全访问(缺省关闭):
# 3.6.3 LAN --> DMZ rules. # # 3.6.3.1 Allow full access. # #$IPTABLES -A FORWARD -i $LAN_IFACE -o $DMZ_IFACE -m state \ # --state NEW -j ACCEPT
具体定义外网对DMZ服务的访问(缺省关闭):
# 3.6.4 DMZ <-- WAN rules. # # 3.6.4.1 Allow ftp(21). # #$IPTABLES -A FORWARD -i $WAN_IFACE -o $DMZ_IFACE -p tcp --dport ftp \ # --syn -m state --state NEW -j ACCEPT # # 3.6.4.2 Allow dns request(53). # #$IPTABLES -A FORWARD -i $WAN_IFACE -o $DMZ_IFACE -p tcp --dport domain \ # --syn -m state --state NEW -j ACCEPT #$IPTABLES -A FORWARD -i $WAN_IFACE -o $DMZ_IFACE -p udp --dport domain \ # -m state --state NEW -j ACCEPT # # 3.6.4.3 Allow http(80). # #$IPTABLES -A FORWARD -i $WAN_IFACE -o $DMZ_IFACE -p tcp --dport http \ # --syn -m state --state NEW -j ACCEPT # # 3.6.4.4 Allow https(443). # #$IPTABLES -A FORWARD -i $WAN_IFACE -o $DMZ_IFACE -p tcp --dport https \ # --syn -m state --state NEW -j ACCEPT
对于非正常的流量,可记录进日志:
# 3.6.5 Log rules. # #$IPTABLES -A FORWARD -j LOG --log-prefix "iptables[forward]:"
接下来是NAT表的设置。
Postrouting链设置
在Postrouting链的最通常设置就是SNAT了,IP伪装(MASQUERADE)是SNAT的一种特例:
# 4.2 POSTROUTING chain. # #$IPTABLES -t nat -A POSTROUTING -o $WAN_IFACE -j SNAT --to $WAN_IP #$IPTABLES -t nat -A POSTROUTING -o $WAN_IFACE -j MASQUERADE
Prerouting链设置
在开启SNAT的情况下,外网只能看到网关,不知道后面DMZ网络的结构,需要在网关做DNAT(重定向):
# 4.1 PREROUTING chain. # # 4.1.1 Allow ftp(21). # #$IPTABLES -t nat -A PREROUTING -i $WAN_IFACE -p tcp --dport ftp \ # -j DNAT --to $DMZ_FTP_IP # # 4.1.2 Allow dns request(53). # #$IPTABLES -t nat -A PREROUTING -i $WAN_IFACE -p tcp --dport domain \ # -j DNAT --to $DMZ_DNS_IP #$IPTABLES -t nat -A PREROUTING -i $WAN_IFACE -p udp --dport domain \ # -j DNAT --to $DMZ_DNS_IP # # 4.1.3 Allow http(80). # #$IPTABLES -t nat -A PREROUTING -i $WAN_IFACE -p tcp --dport http \ # -j DNAT --to $DMZ_HTTP_IP # # 4.1.4 Allow https(80). # #$IPTABLES -t nat -A PREROUTING -i $WAN_IFACE -p tcp --dport https \ # -j DNAT --to $DMZ_HTTP_IP
Mangle表暂未涉及。
服务器start()函数
服务器除了对外提供相应的服务外,通常并不允许自己随意访问外部网络,因而在Output链控制更为严格。
Input链设置
允许相应的应答包进入本机(ESTABLISHED和RELATED状态):
# 3.4.1 Allow all established and related packets. $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
具体定义提供的服务(下面是一些常用服务的模板,可按需打开):
# 3.4.2 Allow ftp(21). # #$IPTABLES -A INPUT -p tcp --dport ftp --syn -m state --state NEW -j ACCEPT # # 3.4.3 Allow ssh(22). # #$IPTABLES -A INPUT -p tcp --dport ssh --syn -m state --state NEW -j ACCEPT # # 3.4.4 Allow smtp(25). # #$IPTABLES -A INPUT -p tcp --dport smtp --syn -m state --state NEW -j ACCEPT # # 3.4.5 Allow dns request(53). # #$IPTABLES -A INPUT -p udp --dport domain -m state --state NEW -j ACCEPT # # 3.4.6 Allow dhcp request(67). # #$IPTABLES -A INPUT -p udp --dport bootps -m state --state NEW -j ACCEPT # # 3.4.7 Allow http(80). # #$IPTABLES -A INPUT -p tcp --dport http --syn -m state --state NEW -j ACCEPT # # 3.4.8 Allow https(443). # #$IPTABLES -A INPUT -p tcp --dport https --syn -m state --state NEW -j ACCEPT # # 3.4.9 Allow ping. # #$IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
Output链设置
缺省只允许应答包离开(ESTABLISHED和RELATED状态):
# 3.5 Output rules. # # 3.5.1 Allow all established and related packets. # $IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Forward链设置
服务器不涉及Forward链。
stop()函数
功能很明确,清除所有规则:
stop() { # # Flush all the rules in the filter table. # $IPTABLES -F # # Erase all chains that's not default in filter table. # $IPTABLES -X # # Flush all the rules in the nat table. # $IPTABLES -t nat -F # # Erase all chains that's not default in nat table. # $IPTABLES -t nat -X # # Flush all the rules in the mangle table. # $IPTABLES -t mangle -F # # Erase all chains that's not default in mangle table. # $IPTABLES -t mangle -X }
resume_all()函数
在stop()函数中,我们并没有恢复缺省策略为ACCEPT,这是因为restart功能的实现是先调用stop(),然后调用start()。如果stop()取消了所有限制,那么在start()启动之前,就会有一个时间空间,使机器处在无防火墙监管之下。
为此,额外提供一个resume_all()函数,在真正执行stop功能时,恢复所有缺省策略:
resume_all() { # # Reset the default policies in the filter table. # $IPTABLES -P INPUT ACCEPT $IPTABLES -P OUTPUT ACCEPT $IPTABLES -P FORWARD ACCEPT # # Reset the default policies in the nat table. # $IPTABLES -t nat -P PREROUTING ACCEPT $IPTABLES -t nat -P POSTROUTING ACCEPT $IPTABLES -t nat -P OUTPUT ACCEPT # # Reset the default policies in the mangle table. # $IPTABLES -t mangle -P PREROUTING ACCEPT $IPTABLES -t mangle -P POSTROUTING ACCEPT $IPTABLES -t mangle -P INPUT ACCEPT $IPTABLES -t mangle -P OUTPUT ACCEPT $IPTABLES -t mangle -P FORWARD ACCEPT }
应用
本文的iptables脚本是一个通用脚本,与具体使用哪个Linux发行版没有关系。但现在很多发行版都或多或少的提供了自己的iptables配置方案,一般情况下,还是建议使用发行版自己的实现,毕竟这是整体解决方案,而且发行版其他涉及防火墙设置的很多应用都会与此耦合,不小心就会“牵一发动全身”。
下面只讲述脚本在slackware下的使用方法。
slackware
slackware的脚本都存放在/etc/rc.d/目录下,故首先把相应模板脚本放到/etc/rc.d/目录下,改名为rc.iptables:
cp rc.iptables-XXXX.ref /etc/rc.d/rc.iptables
给新脚本增加执行权限:
chmod +x /etc/rc.d/rc.iptables
编辑/etc/rc.d/rc.S文件,在末尾添加调用rc.iptables的语句:
# If there is my iptables script, run it before network up. if [ -x /etc/rc.d/rc.iptables ]; then . /etc/rc.d/rc.iptables start fi
另外,对于网关脚本,需要打开内核的IP转发功能,才能实现Forward功能。具体方法是:
echo 1 > /proc/sys/net/ipv4/ip_forward
不过,slackwaer本身已提供了一个脚本rc.ip_forward来做这事,只需给它增加执行权限即可:
chmod +x /etc/rc.d/rc.ip_forward