iptables 入门
这一节开始说明 iptables 的观念及用法
iptables 中的指令,均需区分大小写。
ipchains 和 iptables 在语法上的主要的差异,注意如下∶
1. 在 ipchains 中,诸如 input 链,是使用小写的 chains 名,在 iptables 中,要改用大写 INPUT。
2. 在 iptables 中,要指定规则是欲作用在那一个规则表上(使用 -t 来指定,如 -t nat),若不指定,则预设是作用在 filter 这个表。
3. 在 ipchains 中, -i 是指介面(interface),但在 iptables 中,-i 则是指进入的方向,且多了 -o,代表出去的方向。
4. 在 iptables 中,来源 port 要使用关键字 --sport 或 --source-port
5. 在 iptables 中,目的 port 要使用关键字 --dport 或 --destination-port
6. 在 iptables 中,"丢弃" 的处置动作,不再使用 DENY 这个 target,改用 DROP。
7. 在 ipchains 的记录档功能 -l,已改为目标 -j LOG,并可指定记录档的标题。
8. 在 ipchains 中的旗标 -y,在 iptables 中可用 --syn 或 --tcp-flag SYN,ACK,FIN SYN
9. 在 iptables 中,imcp messages 型态,要加上关键字 --icmp-type,如∶
iptables -A OUTPUT -o eth0 -p icmp -s $FW_IP --icmp-type 8 -d any/0 -j ACCEPT
iptables 使用时的样板
在设定 iptables 的封包过滤规则时,有几个样板的动作,若先熟悉它们,往后就可自行套用,依此类推,很快地,您就可以进入这个天地之中。
观察目前的设定
作法如下∶
iptables -L -n
iptablse -t nat -L -n
定义变数
FW_IP="163.26.197.8"
打开核心 forward 功能
作法如下∶
###-----------------------------------------------------###
# 打开 forward 功能
###-----------------------------------------------------###
echo "1" > /proc/sys/net/ipv4/ip_forward
清除所有的规则
一开始要先清除所有的规则,重新开始,以免旧有的规则影响新的设定。作法如下∶
###-----------------------------------------------------###
# 清除先前的设定
###-----------------------------------------------------###
# 清除预设表 filter 中,所有规则链中的规则
iptables –F
# 清除预设表 filter 中,使用者自订链中的规则
iptables -X
# 清除mangle表中,所有规则链中的规则
iptables -F -t mangle
# 清除mangle表中,使用者自订链中的规则
iptables -t mangle -X
# 清除nat表中,所有规则链中的规则
iptables -F -t nat
# 清除nat表中,使用者自订链中的规则
iptables -t nat -X
选定预设的政策
接着,要选定各个不同的规则链,预设的政策为何。作法如下∶
预设全部丢弃∶
###-----------------------------------------------------###
# 设定 filter table 的预设政策
###-----------------------------------------------------###
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
或者预设全部接受∶
###-----------------------------------------------------###
# 设定 filter table 的预设政策
###-----------------------------------------------------###
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
各个规则链的预设政策可独立自主的设定,不必受其它链的影响。
以下练习,若目标为 DROP,则 policy 请设为 ACCEPT;若目标为 ACCEPT,则 policy 请设为 DROP,如此方可看出效果。
开放某一个介面
作法如下∶
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
注∶IPFW 或 Netfilter 的封包流向,local process 不会经过 FORWARD Chain,
因此 lo 只在 INPUT 及 OUTPUT 二个 chain 作用。
iptables -A INPUT -i eth1 -j ACCEPT
iptables -A OUTPUT -o eth1 -j ACCEPT
iptables -A FORWARD -i eth1 -j ACCEPT
iptables -A FORWARD -o eth1 -j ACCEPT
IP 伪装
使内部网路的封包经过伪装之后,使用对外的 eth0 网卡当作代表号,对外连线。作法如下∶
###-----------------------------------------------------###
# 启动内部对外转址
###-----------------------------------------------------###
iptables -t nat -A POSTROUTING -o eth0 -s 172.16.0.0/16 -j SNAT --to-source $FW_IP
上述指令意指∶把 172.16.0.0/16 这个网段,伪装成 $FW_IP 出去。
虚拟主机
利用转址、转 port 的方式,使外部网路的封包,可以到达内部网路中的伺服主机,俗称虚拟主机。这种方式可保护伺服主机大部份的 port 不被外界存取,只开放公开服务的通道(如 Web Server port 80),因此安全性甚高。
作法如下∶
###-----------------------------------------------------###
# 启动外部对内部转址
###-----------------------------------------------------###
# 凡对 $FW_IP:80 连线者, 则转址至 172.16.255.2:80
iptables -t nat -A PREROUTING -i eth0 -p tcp -d $FW_IP --dport 80 -j DNAT --to-destination 172.16.255.2:80
开放内部主机可以 telnet 至外部的主机
开放内部网路,可以 telnet 至外部主机。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open 外部主机 telnet port 23
###-----------------------------------------------------###
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 23 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 23 -d $FW_IP --dport 1024:65535 -j ACCEPT
开放邮包转递通道
开放任意的邮件主机送信包给你的 Mail Server,而你的 Mail Server 也可以送信包过去。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open SMTP port 25
###-----------------------------------------------------###
# 以下是∶别人可以送信给你
iptables -A INPUT -i eth0 -p tcp -s any/0 --sport 1024:65535 -d $FW_IP --dport 25 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp ! --syn -s $FW_IP --sport 25 -d any/0 --dport 1024:65535 -j ACCEPT
# 以下是∶你可以送信给别人
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 25 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 25 -d $FW_IP --dport 1024:65525 -j ACCEPT
开放对外离线下载信件的通道
开放内部网路可以对外部网路的 POP3 server 取信件。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open 对外部主机的 POP3 port 110
###-----------------------------------------------------###
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 110 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 110 -d $FW_IP --dport 1024:65535 -j ACCEPT
开放观看网页的通道
开放内部网路可以观看外部网路的网站。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open 对外部主机的 HTTP port 80
###-----------------------------------------------------###
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 80 -d $FW_IP --dport 1024:65535 -j ACCEPT
开放查询外部网路的 DNS 主机
开放内部网路,可以查询外部网路任何一台 DNS 主机。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open DNS port 53
###-----------------------------------------------------###
# 第一次会用 udp 封包来查询
iptables -A OUTPUT -o eth0 -p udp -s $FW_IP --sport 1024:65535 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p udp -s any/0 --sport 53 -d $FW_IP --dport 1024:65535 -j ACCEPT
# 若有错误,会改用 tcp 封包来查询
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 53 -d $FW_IP --dport 1024:65535 -j ACCEPT
# 开放这台主机上的 DNS 和外部的 DNS 主机互动查询∶使用 udp
iptables -A OUTPUT -o eth0 -p udp -s $FW_IP --sport 53 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p udp -s any/0 --sport 53 -d $FW_IP --dport 53 -j ACCEPT
# 开放这台主机上的 DNS 和外部的 DNS 主机互动查询∶使用 tcp
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 53 -d any/0 --dport 53 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! -y -s any/0 --sport 53 -d $FW_IP --dport 53 -j ACCEPT
开放内部主机可以 ssh 至外部的主机
开放内部网路,可以 ssh 至外部主机。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open 外部主机 ssh port 22
###-----------------------------------------------------###
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 22 -d $FW_IP --dport 1024:65535 -j ACCEPT
# 以下是 ssh protocol 比较不同的地方
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1020:1023 -d any/0 --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 22 -d $FW_IP --dport 1020:1023 -j ACCEPT
开放内部主机可以 ftp 至外部的主机
开放内部网路,可以 ftp 至外部主机。
作法如下∶(预设 policy 为 DROP)
###-----------------------------------------------------###
# open 对外部主机 ftp port 21
###-----------------------------------------------------###
# 以下是打开命令 channel 21
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 21 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 21 -d $FW_IP --dport 1024:65535 -j ACCEPT
# 以下是打开资料 channel 20
iptables -A INPUT -i eth0 -p tcp -s any/0 --sport 20 -d $FW_IP --dport 1024:65535 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp ! --syn -s $FW_IP --sport 1024:65535 -d any/0 --dport 20 -j ACCEPT
# 以下是打开 passive mode FTP 资料通道
iptables -A OUTPUT -o eth0 -p tcp -s $FW_IP --sport 1024:65535 -d any/0 --dport 1024:65535 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp ! --syn -s any/0 --sport 1024:65535 -d $FW_IP --dport 1024:65535 -j ACCEPT
开放 ping
可以对外 ping 任何一台主机。
作法如下∶(预设 policy 为 DROP)
iptables -A OUTPUT -o eth0 -p icmp -s $FW_IP --icmp-type 8 -d any/0 -j ACCEPT
iptables -A INPUT -i eth0 -p icm -s any/0 --icmp-type 0 -d $FW_IP -j ACCEPT
IPTABLES实例1
假设网络环境如下:某一单位,租用DDN专线上网,网络拓扑如下:
+----------------+
| 内部网段 | eth1+--------------+eth0 DDN
|------------------ |<=====>| firewall |<======>Internet
| 198.168.80.0 | +--------------+
+--------------+
eth0: 198.199.37.254
eth1: 198.168.80.254
以上的IP地址都是Internet上真实的IP,故没有用到IP欺骗。并且,我们假设在内部网中存在以下服务器:
www服务器:www.yourdomain.com 198.168.80.11
ftp服务器:ftp.yourdomain.com 198.168.80.12
email服务器:mail.yourdomain.com 198.168.80.13
下面我们将用iptables一步一步地来建立我们的包过滤防火墙,需要说明的是,在这个例子中,我们主要是对内部的各种服务器提供保护。
1. 在/etc/rc.d/目录下用touch命令建立firewall文件,执行chmod u+x firewll以更改文件属性,编辑/etc/rc.d/rc.local文件,在末尾加上 /etc/rc.d/firewall 以确保开机时能自动执行该脚本。
2. 刷新所有的链的规则
#!/bin/sh
echo "Starting iptables rules..."
#Refresh all chains
/sbin/iptables -F
3. 我们将首先禁止转发任何包,然后再一步步设置允许通过的包。
所以首先设置防火墙FORWARD链的策略为DROP:
/sbin/iptables -P FORWARD DROP
4.设置关于服务器的包过虑规则:
在这里需要注意的是,服务器/客户机交互是有来有往的,也就是说是双向的,所以我们不仅仅要设置数据包出去的规则,还要设置数据包返回的规则,我们先建立针对来自Internet数据包的过虑规则。
WWW服务:服务端口为80,采用tcp或udp协议。规则为:eth0=>允许目的为内部网WWW服务器的包。
#Allow www request packets from Internet clients to www servers
/sbin/iptables -A FORWARD -p tcp -d 198.168.80.11 --dport www -i eth0 -j ACCEPT
FTP服务:FTP服务有点特别,因为需要两个端口,因为FTP有命令通道和数据通道。其中命令端口为21,数据端口为20,并且有主动和消极两种服务模式,其消极模式连接过程为:FTP客户端首先向FTP服务器发起连接请求,三步握手后建立命令通道,然后由FTP服务器请求建立数据通道,成功后开始传输数据,现在大多数FTP客户端均支持消极模式,因为这种模式可以提高安全性。FTP服务采用tcp协议。规则为:eth0=>仅允许目的为内部网ftp服务器的包。
#Allow ftp request packets from Internet clients to Intranet ftp server
/sbin/iptables -A FORWARD -p tcp -d 198.168.80.12 --dport ftp -i eth0 -j ACCEPT
EMAIL服务:包含两个协议,一是smtp,一是pop3。出于安全性考虑,通常只提供对内的pop3服务,所以在这里我们只考虑针对smtp的安全性问题。smtp端口为21,采用tcp协议。eth0=>仅允许目的为email服务器的smtp请求。
/sbin/iptables -A FORWARD -p tcp -d 198.168.80.13 --dport smtp -i eth0 -j ACCEPT
5. 设置针对Intranet客户的过虑规则:
在本例中我们的防火墙位于网关的位置,所以我们主要是防止来自Internet的攻击,不能防止来自Intranet的攻击。假如我们的服务器都是基于linux的,也可以在每一部服务器上设置相关的过虑规则来防止来自Intranet的攻击。对于Internet对Intranet客户的返回包,我们定义如下规则。
/sbin/iptables -A FORWARD -p tcp -s 0/0 --sport ftp-data -d 198.168.80.0/24 -i eth0 -j ACCEPT
/sbin/iptables -A FORWARD -p tcp -d 198.168.80.0/24 ! -syn -i eth0 -j ACCEPT
/sbin/iptables -A FORWARD -p udp -d 198.168.80.0/24 -i eth0 -j ACCEPT
说明:第一条允许Intranet客户采用消极模式访问Internet的FTP服务器;第二条接收来自Internet的非连接请求tcp包;最后一条接收所有udp包,主要是针对oicq等使用udp的服务。
6. 接受来自整个Intranet的数据包过虑,我们定义如下规则:
/sbin/iptables -A FORWARD -s 198.168.80.0/24 -i eth1 -j ACCEPT
7. 处理ip碎片
我们接受所有的ip碎片,但采用limit匹配扩展对其单位时间可以通过的ip碎片数量进行限制,以防止ip碎片攻击。
/sbin/iptables -A FORWARD -f -m limit --limit 100/s --limit-burst 100 -j ACCEPT
说明:对不管来自哪里的ip碎片都进行限制,允许每秒通过100个ip碎片,该限制触发的条件是100个ip碎片。
8. 设置icmp包过滤
icmp包通常用于网络测试等,故允许所有的icmp包通过。但是黑客常常采用icmp进行攻击,如ping of death等,所以我们采用limit匹配扩展加以限制:
/sbin/iptables -A FORWARD -p icmp -m limit --limit 1/s --limit-burst 10 -j ACCEPT
说明:对不管来自哪里的icmp包都进行限制,允许每秒通过一个包,该限制触发的条件是10个包。
IPTABLES实例2
假设网络环境如下:某一单位,租用DDN专线上网,网络拓扑如下:
+--------------------+
| 内部网段 | eth0 +---------+ eth1 DDN
|-----------------------|<=====>| firewall |<======>Internet
| 210.35.92.128/25 | +----------+
+--------------------+
eth0: 210.35.92.129/25
eth1: 210.35.88.254/24
下面我们将用iptables一步一步地来建立我们的包过滤防火墙
#清除FORWARD表
iptables -F FORWARD
#制订FORARD表的策略
iptables -P FORWARD DORP
#拒绝声称为内部网地址,但是从外网卡来的包
iptables -A INPUT -s 210.35.92.128/25 -i eth1 -j DROP
#拒绝ICMP到内部网广播地址的smurf式的攻击
iptables -A FORWARD -p icmp -i eth1 -d 210.35.92.255/25 -j DORP
#我们想接受碎片包
iptables -A FORWARD -f -j ACCEPT
#我们接收已经建立tcp连接的tcp包
iptables -A FORWARD -m multiport -p tcp -d 210.35.92.128/25 --dports smtp,www ! -tcp-flages SYN,ACK ACK -j ACCEPT
iptables -A FORWARD -m multiport -p tcp -d 210.35.92.128/25 --sports smtp,www ! tcp-flages SYN,ACK ACK -j ACCEPT
#我们接受我们允许端口来的tcp请求连接
iptables -A FORWARD -m multiport -p tcp -i eth1 -d 210.35.92.128/25 --dports smtp,www --syn -j ACCEPT
#我们接受我们允许端口出去的tcp请求连接
iptables -A FORWARD -m multiport -p tcp -i eth0 -d 0/0 --dports smtp,www,ftp,ftp-data,irc --syn -j ACCEPT
#我们接受我们允许端口来的udp包
iptables -A FORWARD -m multiport -p udp -i eth1 -d 210.35.92.128/25 --dports smtp,www -j ACCEPT
iptables -A FORWARD -m multiport -p udp -i eth1 -d 210.35.92.128/25 --sports smtp,www -j ACCEPT
#我们接受我们允许端口出去的udp包
iptables -A FORWARD -m multiport -p udp -i eth0 -d 0/0 --dports smtp,www,ftp,ftp-data,irc
iptables -A FORWARD -m multiport -p udp -i eth0 -d 0/0 --sports smtp,www,ftp,ftp-data,irc
#我们接受我们允许类型的进来的ICMP包
iptables -A FORWARD -m multiport -p icmp -i eth1 -d 210.35.92.128/25 --dports 0,3,11 -j ACCEPT
#我们接受我们允许类型的出去的ICMP包
iptables -A FORWARD -m multiport -p icmp -i eth0 -d 0/0 --dports 8,3,11 -j ACCEPT
自己实践过的脚本
#!/bin/sh
#初始化iptables的netfilter和nat表,以及定制链的策略.
iptables -F
iptables -t nat -F
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
#内部回环网络永远打开.
iptables -A INPUT -i lo -s 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -o lo -s 127.0.0.1 -j ACCEPT
#测试网关是否和公网连通,及防止ping洪水攻击.
iptables -A INPUT -p icmp -i eth1 -m limit --limit 6/m --limit-burst 2 -j ACCEPT
iptables -A OUTPUT -p icmp -o eth1 -j ACCEPT
#端口映射FTP
iptables -t nat -A PREROUTING -i eth1 -p tcp -d 210.35.92.173 --dport ftp -j DNAT --to-destination 192.168.0.2
#端口映射www
iptables -t nat -A PREROUTING -i eth1 -p tcp -d 210.35.92.173 --dport www -j DNAT --to-destination 192.168.0.2
#邦定内网MAC和IP,防止不合格的成员访问网关.
iptables -A INPUT -i eth0 -s 192.168.0.2 -m mac --mac-source ! 00:E0:4E:E8:9B:BC -j REJECT
iptables -A INPUT -i eth0 -s ! 192.168.0.2 -m mac --mac-source 00:E0:4E:E8:9B:BC -j REJECT
#检测子网内部可否通信.
iptables -A INPUT -p icmp -i eth0 -s 192.168.0.0/24 -j ACCEPT
iptables -A OUTPUT -p icmp -o eth0 -d 192.168.0.0/24 -j ACCEPT
#内网可以访问所有子网内的服务.
iptables -A INPUT -s 192.168.0.0/24 -i eth0 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/24 -o eth0 -j ACCEPT
#邦定内网MAC和IP,防止不合格的成员访问公网.
iptables -A FORWARD -i eth0 -s 192.168.0.2 -m mac --mac-source ! 00:E0:4E:E8:9B:BC -j REJECT
iptables -A FORWARD -i eth0 -s ! 192.168.0.2 -m mac --mac-source 00:E0:4E:E8:9B:BC -j REJECT
#测试子网是否可以和公网通信.
iptables -A FORWARD -p icmp -d 192.168.0.0/24 -i eth1 -o eth0 -m limit --limit 6/m --limit-burst 2 -j ACCEPT
iptables -A FORWARD -p icmp -s 192.168.0.0/24 -i eth0 -o eth1 -j ACCEPT
#禁止QQ服务.
iptables -A FORWARD -p udp -s 192.168.0.0/24 --sport 4000 -i eth0 -o eth1 -j REJECT
#公网可以有限制地请求和子网建立连接,防止SYN洪水攻击.
iptables -A FORWARD -p tcp -i eth1 --syn -m limit --limit 1/s --limit 1 -j ACCEPT
#子网可以请求和公网建立任何tcp连接.
iptables -A FORWARD -p tcp -i eth0 -s 192.168.0.0/24 -o eth1 -j ACCEPT
#子网对公网访问时,有限制地接受碎片IP包,防止碎片攻击.
iptables -A FORWARD -p tcp -f -m limit --limit 100/s --limit-burst 100 -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -p tcp -f -i eth1 -o eth0 -j DROP
#子网接受其他的tcp包.
iptables -A FORWARD -p tcp -i eth1 -o eth0 -j ACCEPT
#子网可以访问其他UDP协议的公网服务.
iptables -A FORWARD -p udp -i eth0 -s 192.168.0.0/24 -o eth1 -j ACCEPT
iptables -A FORWARD -p udp -i eth1 -d 192.168.0.0/24 -o eth0 -m state --state ESTABLISHED -j ACCEPT
#子网访问公网的模式是伪装成网关的地址.
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth1 -j MASQUERADE
附加:
iptables的处理图:

iptables的NAT目标动作扩展
1)SNAT
# iptables -t nat -A POSTROUTING -j SNAT –to-source 1.2.3.4
2)MASQUERADE
# iptables -t nat -A POSTROUTING -j MASQUERADE -o ppp0
3)DNAT
# iptables -t nat -A PREROUTING -j DNAT –to-destination 1.2.3.4:8080 -p tcp –dport 80 -i eth1
4)REDIRECT
# iptables -t nat -A PREROUTING -j REDIRECT –to-port 3128 -i eth1 -p tcp –dport 80
可以用limit模块去避免以快速比率提升服务回应的阻断服务攻击(DoS)。
Syn-flood protection﹕
# iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
Furtive port scanner﹕
# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT
Ping of death﹕
# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT