iptables是一个专门用来编写防火墙规则的工具,它所编写的规则是通过内核调用来送至netfilter上钩子函数上的规则链执行来发挥作用。在真正了解该如何使用iptables来编写规则之前,我们先来了解几个概念;
一、概念了解
(1)防火墙
防火墙即为隔离工具;工作于主机与网络边缘,对于进出本主机或本网络的报文根据事先定义的检查规则 作匹配检测,对于能够被规则匹配的报文做出相应处理的组件;
可以分为主机防火墙和网络防火墙;亦可分为硬件防火墙和软件防火墙;
本文主要讨论软件防火墙即netfilter,它工作在内核中的TCP/IP协议栈;
(2)钩子函数(hook function)
input
output
forward
prerouting
postrouting
(3)钩子函数对应的规则链
内置链
PREROUTING
INPUT
FORWARD
OUTPUT
POSTROUTING
自定义链:用于内置链的扩展和补充,可实现更灵活的规则管理机制;本身不对应钩子函数,所需必须被内置链调用才可以起效;
(4)功能表:可以实现具体一类功能集合的表
filter:按指定规则过滤防火墙的报文 。
nat:network address translation,网络地址转换;用于修改源IP或目标IP,也可以修改端口。
mangle:拆解报文,做出修改,并重新封装起来;一般是修改首部的TTL,打上防火墙标记实现端口联姻等。
raw:关闭nat表上启用的连接追踪功能。
注:在各个钩子上对应的功能表有检查优先级,优先级由高到底分别是raw、mangle、nat、filter。
(5)可应用到对应功能表的规则链
(6)netfilter过滤数据包过程
注1:报文的流向
流入本机:PREROUTING ---> INPUT
由本机流出:OUTPUT ----> POSTROUTING
转发:PREROUTING ---> FORWARD --> POSTROUTING
注2:路由选择发生的时刻
报文进入本机时,在PREROUTING之后,此时路由选择主要判断目标主机是什么
报文离开本机之前,在POSTROUTING之前,此时路由选择主要判断经由哪个接口(网卡)送往下一站
二、iptables的使用
(1)规则介绍
iptables的规则主要有以下两部分组成:
匹配条件:基本匹配条件和扩展匹配条件
处理动作:基本处理动作和扩展处理动作以及自定义处理机制(主要调用自定义链)
防火墙根据规则的匹配条件来尝试匹配报文,一旦匹配成功,就由规则定义的处理动作作出处理
(2)添加规则时的考量点:
要实现那种功能:用于判断应该添加到哪个功能表上;
报文流经的路径:用于判断应该添加到哪个规则链上;
(3)制定规则的次序的考量点:
同类规则(比如都是对于web,访问同一应用),将匹配范围小的规则放在前面;
不同类规则(访问不同应用),匹配到的报文频率较大的放在上面;这样可以减少许多无效检查。提高性能;
将那些可由一条规则描述的多个规则合并起来;
设置默认策略;
(4)iptables服务管理
CentOS 6
start:读取事先保存的规则,并应用到netfilter
stop:清空netfilter上的规则,以及还原默认策略等;
status:显示生效的规则;
restart:清空netfilter上的规则,读取事先保存的规则,并应用到netfilter
service iptables {start | stop | restart | status}
默认的规则文件:/etc/sysconfig/iptables
CentOS 7
systemctl { start | stop | restart | status } firewalld.service
(5)如何使用iptables编写规则
规则概述
iptables [-t table] COMMADND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
在有了以上的整体构架后,下面我们分部分来描述iptables的使用;
1> -t table
此处table即上述概念了解部分的四个功能表,即filter、nat、raw、mangle。此处值得指出的是,在考虑选择哪张表时应该考虑以上提到的添加规则的考量点。另外此处若不指出-t table则表示默认是filter表。
2> COMMAND
规则链管理
使用格式:
iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
选项解释:
-N :new,自定义一条新的规则链
-X [chain]:drop,delete,删除自定义的规则链
-P:Policy,用于设置默认策略;对filter表中的规则链而言,其默认策略是:
ACCEPT:接受报文
DROP:丢弃报文并且不通知给报文的来源
REJECT:丢弃报文还要通知报文的来源
-E : 重命名自定义链;引用计数不为0的自定义链不能被重命名,且不能被删除;
规则管理
使用格式:
iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] {-F |-Z} [chain [rulenum]] [options...]
注:此处的rule-specification指的是 [matches...] [target]指的是匹配条件和处理动作,将会在下面详细解释。
选项解释:
-A:append,追加一条规则;
-I [rulenum]:insert,插入;省略rulenum即不指出要添加的序号则默认是第一条
-D:delete,删除;删除时指定规则可以有以下两种方式。
(1)指明规则序号;
(2)指明规则本身(规则和处理动作);
-R:replace,替换指定链上的指定规则;
-F:flush,清空指定的规则链;
-Z:zero,将计数器置0;iptables的每条规则都有两个计数器:
(1)匹配到的报文的个数;
(2)匹配到的所有报文的大小之和;
查看指定规则链上的所有规则
使用格式:
iptables [-t table] -L [chain [rulenum]] [options...]
选项解释:
-L:list,查看指定链上的所有规则
-L的补充选项:
-n: numberic,以数字格式显示地址和端口号;否则会反解为服务名
-v:verbose,显示详细信息;-vv,-vvv表示显示更加详细的信息
-x:exactly,显示计数器结果的精确值;
--line-numbers:显示规则的序号
3> chain
此处的规则链即以上概念了解中提到的五条内置规则链和自定义链;
4> 匹配条件
先说明匹配条件共分为基本匹配条件和扩展匹配条件,而扩展匹配条件又分为隐式扩展和显式扩展;
基本匹配条件
基本匹配条件指的是无需添加任何额外模块,而由netfilter提供。
1、[!] -s, --source address[/mask][,...]:检查报文中的源IP地址是否符合此处的指定的地址或范围;
2、[!] -d, --destination address[/mask][,...]:检查报文中的目标IP地址是否符合此处的指定的地址或范围;
3、 [!] -p, --protocol protocol:指明协议(IP首部中指的传输层协议)此处的protocol(协议)可为:tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh 或者以“all”关键字来指出全部;
4、[!] -i, --in-interface name:数据报文流入的接口;只能应用于数据报文流入的环节,只能应用于INPUT, FORWARD 和 PREROUTING 这几条链。
5、[!] -o, --out-interface name:数据报文流出的接口;只能应用于数据报文流出的环节,只能应用于OUTPUT, FORWARD 和 POSTOUTING 这几条链。
扩展匹配条件(可使用 man iptables-extensions 查看帮助信息)
扩展匹配条件指的是需要加载额外的模块方能生效;
隐式扩展:不需要手动加载扩展模块;因为它们是对协议的扩展,所以,但凡使用-p指明了协议,就表示已经指明了要扩展的模块。
tcp
[!] --source-port,--sport port[:port] 匹配报文源端口;可以是端口范围
[!] --destination-port, --dport port[:port] 匹配报文源端口;可以是端口范围
[!] --tcp-flags mask comp
掩码(mask):一个以逗号分隔的标志位列表。
标志位(flags): SYN ACK FIN RST URG PSH ALL NONE
comp:是一个必须匹配的标志位,亦以逗号分隔;
例如:--tcp-flags SYN,ACK,FIN,RST SYN
上面这个指的是要检查的标志位是SYN,ACK,FIN,RST,四个,其中SYN必须为1,余下的必须为0
[!] --syn:用于匹配第一次握手,相当于"--tcp-flags SYN,ACK,FIN,RST SYN"
udp: 与tcp类似,此处不再赘述
[!] --source-port,--sport port[:port]
[!] --destination-port,--dport port[:port]
icmp:
[!] --icmp-type {type[/code]|typename}
此处的typename指的是echo-request和echo-reply
此处的type[/code]指的是8和0,分别对应请求报文和响应报文。
~]# iptables -I INPUT -d 192.168.1.72 -p icmp --icmp-type 8 -j DROP
显式扩展
显示扩展需要使用-m选项显式的指出额外的模块,接下来介绍比较常用的模块。
multiport扩展:以离散方式定义多端口匹配;最多指定15个端口。
[!] --source-ports,--sports port[,port|,port:port]...:指定多个源端口
[!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口
[!] --ports port[,port|,port:port]...:指定多个端口
~]# iptables -I INPUT -s 192.168.0.0/24 -d 192.168.1.71 -p tcp -m mutilport --dports 22,80 -j ACCEPT
iprange扩展:指明连续的(但一般不指整个网络)IP地址范围。
[!] --src-range from [-to]: 源地址
[!]--dst-range from [-to]: 目标地址
~]# iptables -A INPUT -d 192.168.1.71 -p tcp --dport 80 -m iprange --src-range 192.168.100.5-192.168.100.10 -j DROP
string扩展:对报文中的应用层数据做字符串模式匹配检测。
--algo {bm|kmp}:字符串匹配检测算法;
bm:Boyer-Moore
kmp:Knuth-Pratt-Morris
[!] --string pattern:要检测的字符串模式;
[!] --hex-string pattern:要检测的字符串模式,16进制格式;
~]# iptables -A OUTPUT -s 192.168.1.71 -d 192.168.0.0/24 -p tcp --sport 80 -m string --algo bm --string "gay" -j REJECT
time扩展:根据报文到达的时间与指定的时间范围进行匹配
--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]:起始日期
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]:结束日期
--timestart hh:mm[:ss] :起始时间
--timestop hh:mm[:ss] :结束时间
[!] --monthdays day[,day...]:月份
[!] --weekdays day[,day...]:周
--kerneltz:使用内核定义的时区而非默认的UTC时区
注意:多个选项之间是与逻辑。
~]# iptables -A INPUT -s 192.168.0.0/24 -d 192.168.1.71 -p tcp --dport 80 -m time --timestart 14:30 --timestop 18:30 --weekdays Sat,Sun --kerneltz -j DROP
connlimit模块:根据每客户端IP做并发连接的数量匹配
--connlimit-upto n:连接的数量小于n时匹配
--connlimit-above n:连接的数量大于n时匹配
~]# iptables -A INPUT -d 192.168.1.71 -p tcp --dport 21 -m connlimit --connlimit-above 2 -j REJECT
limit模块:根据收发报文的速率做匹配;可做流量控制
--limit rate[/second|/minute|/hours|/days]:限定速率为每秒/分钟/小时/天多少个。
--limit-burst number :指定峰值
# 限定ping主机192.168.1.71的请求报文为每分钟3个,且峰值为5个(即第一次涌进最多五个); ~]# iptables -I INPUT -d 192.168.1.71 -p icmp --icmp-type 8 -m limit --limitt 3/minute --limit-burst 5 -j ACCEPT # 设置icmp协议的默认策略 ~]# iptables -I INPUT 2 -p icmp -j REJECT
state扩展:根据“连接追踪机制”去检查连接的状态
连接追踪机制:追踪本机上的请求和响应之间的关系,状态有如下几种:
NEW:新发出的请求;连接追踪模板不存在此连接的相关信息条目,因此,将其识别为第一次发出的请求;
ESTABLISHED:NEW状态之后,连接追踪模板中为其建立的条目失效之前期间内的通信状态;
RELATED:相关联的连接:如ftp协议中的命令连接与数据连接之间的关系;
INVALID:无效的连接;
UNTRACKED:未进行追踪的连接
[!] --state state
# 仅接受状态为NEW和ESTABLISHED的通过22和80端口进入本机的报文 ~]# iptables -A INPUT -d 192.168.1.71 -p tcp -m multiport --dports 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT # 仅放出状态为ESTABLISHED通过22和80端口从本机出去的报文 ~]# iptables -A OUTPUT -s 192.168.1.71 -p tcp -m multiport --sports 22,80 -m state --state ESTABLISHED -j ACCEPT
注意:关于连接追踪机制有以下几点需要说明。
调整连接追踪功能所能够容纳的最大连接数量的内核参数:/proc/sys/net/nf_contrack_max
已经追踪到到的并记录下来的连接的内核参数:/proc/net/nf_conntrack
不同的协议的连接追踪时长的内核参数:/proc/sys/net/netfilter/
iptables的链接跟踪表最大容量为/proc/sys/net/ipv4/ip_conntrack_max,链接碰到各种状态的超时后就会从表中删除;当模板满载时,后续的连接可能会超时;解�Q方法一般有两个:
(1) 加大nf_conntrack_max 值
~]# vim /etc/sysctl.conf net.ipv4.nf_conntrack_max = 393216 net.ipv4.netfilter.nf_conntrack_max = 393216
(2) 降低 nf_conntrack timeout时间
~]# vim /etc/sysctl.conf net.ipv4.netfilter.nf_conntrack_tcp_timeout_established = 300 net.ipv4.netfilter.nf_conntrack_tcp_timeout_time_wait = 120 net.ipv4.netfilter.nf_conntrack_tcp_timeout_close_wait = 60 net.ipv4.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
4> 处理动作
使用格式:
-j targetname [per-target-options]
具体说明:
targetname:ACCEPT(接受)、DROP(拒绝)、REJECT(拒绝还要发送通知)、RETUEN(从自定义链返回调
用链)、REDIRECT(端口重定向)、LOG(记录日志)、MARK(做防火墙标记)、DNAT(目标地址转换)、
SNAT(源地址转换)、MASQUERADE(地址伪装)。
具体的各targetname选项可详见帮助文档。
(6)如何使用自定义链
自定义链:需要被调用才能生效;自定义链最后需要定义返回默认规则;
# 定义一个自定义的新链 ~]# iptables -N mychain # 可在自定义的链中写入规则 ~]# iptables -A mychain -d 192.168.1.71 -p tcp --dport 80 -j ACCEPT # 定义这条自定义链应该被哪一条内置链调用,此处以INPUT做示例;具体应该被哪一条规则链调用应# 看实际情况 ~]# iptables -A INPUT -j mychain # 最后应该定义返回,即当报文无法被自定义链的规则匹配时应该返回主链来被其他规则过滤 ~]# iptables -A mychain -j RETURN
注意:当要重命名或删除自定义链时要保证其被没有被在调用的状态。
(7)如何保存规则以及如何自动生效规则文件中的规则
规则的有效期限:使用iptables命令定义的规则,手动删除之前,其生效期限为kernel存活期限;
保存规则至指定的文件:
CentOS 6:
iptables-save > /PATH/TO/SOME_RULES_FILE # 将规则保存至指定的文件中;
service iptables save # 将规则保存至/etc/sysconfig/iptables文件中;
CentOS 7:
iptables-save > /PATH/TO/SOME_RULES_FILE # 将规则保存至指定的文件中;
重新载入预存规则文件中规则:
iptables-restore < /PATH/FROM/SOME_RULES_FILE
CentOS 6:service iptables restart
自动生效规则文件中的规则:
用脚本保存各iptables命令;让此脚本开机后自动运行;在/etc/rc.d/rc.local文件中添加脚本路径:/PATH/TO/SOME_SCRIPT_FILE
用规则文件保存各规则,开机时自动载入此规则文件中的规则:/etc/rc.d/rc.local文件添加:
iptables-restore < /PATH/FROM/IPTABLES_RULES_FILE
(8)规则优化
服务器端规则设定:任何不允许的访问,在请求到达时给予拒绝;
(1)可安全放行所有入站状态为ESTABLISHED状态的连接。
(2)可安全放行所有出站状态为ESTABLISHED状态的连接。
(3)谨慎放行入站的新请求。
(4)有特殊目的的限制访问功能,要于放行规则之前加以拒绝。
三、使用iptables定义被动连接模式下的ftp服务(假设ftp服务器地址为192.168.1.71)的安全策略
(1)装载ftp的连接追踪模块以及设定默认策略
~]# modprobe nf_conntrack_ftp ~]# iptables -P INPUT DROP ~]# iptables -P OUTPUT DROP ~]# iptables -P FORWARD DROP
(2)放行ftp的命令连接
# 放行进站状态为NEW和ESTABLISHED状态的ftp命令连接报文。 ~]# iptables -A INPUT -d 192.168.1.71 -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT # 仅放行出站状态为ESTABLISHED的ftp命令报文 ~]# iptables -A OUTPUT -s 192.168.1.71 -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT
(3)放行ftp的数据连接
# 因为ftp的被动连接模式下的数据端口是随机的,故此处指出状态为RELATED可每次根据连接追踪来 # 开放对应的端口 ~]# iptables -A INPUT -d 192.168.1.71 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT ~]# iptables -A OUTPUT -s 192.168.171 -p tcp -m state --state ESTABLISHED -j ACCEPT
最后的规则效果如下
~]# iptables -L -n Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 192.168.1.71 tcp dpt:22 ACCEPT tcp -- 0.0.0.0/0 192.168.1.71 tcp dpt:21 state NEW,ESTABLISHED ACCEPT tcp -- 0.0.0.0/0 192.168.1.71 state RELATED,ESTABLISHED Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.1.71 0.0.0.0/0 tcp spt:22 ACCEPT tcp -- 192.168.1.71 0.0.0.0/0 tcp spt:21 state ESTABLISHED ACCEPT tcp -- 192.168.1.71 0.0.0.0/0 state ESTABLISHED
(4)现在可根据以上的<规则优化>以及<制定规则的次序的考量点>来重新组合规则和调整次序来优化以上规则如下
# 入站优化规则 # 下面这条规则可匹配大部分报文故放在第一条,且放行处于连接状态的报文 ~]# iptables -A INPUT -d 192.168.1.71 -m state --state ESTABLISHED -j ACCEPT # 合并所有请求(ftp)21和(ssh)22号端口的报文 ~]# iptables -A INPUT -d 192.168.1.71 -p tcp -m multiport --dports 21,22 -m state --state NEW -j ACCEPT # 将数据连接的报文单独抽取出来,只有用到时方匹配 ~]# iptables -A INPUT -d 192.168.1.71 -p tcp -m state --state RELATED -j ACCEPT # 出站优化规则;注意此处假定服务器无需访问其他的服务,如yum源等,若是有,则需添加规则。 ~]# iptables -A OUTPUT -s 192.168.1.71 -m state --state ESTABLISHED -j ACCEPT # 最后呈现优化过的安全策略 ~]# iptables -L -n Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 192.168.1.71 state ESTABLISHED ACCEPT tcp -- 0.0.0.0/0 192.168.1.71 multiport dports 21,22 state NEW ACCEPT tcp -- 0.0.0.0/0 192.168.1.71 state RELATED Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy DROP) target prot opt source destination ACCEPT all -- 192.168.1.71 0.0.0.0/0 state ESTABLISHED
四、使用iptables来构建网络防火墙
在本机所写的防火墙规则可被成为主机防火墙;而使用另一台主机定义的防火墙规则来做报文过滤则被称为网络防火墙,这个过程主要用到FORWARD链。下面我们使用三台主机来做一个实验示例,网络拓扑图如下。
说明:
1、在这个实验中我们需要三台主机A、B、C。
2、A作为客户端访问,地址为192.168.1.71。
3、B作为网络防火墙,拥有两块网卡,一个网卡与A主机通信,地址为192.168.1.72;另一个网卡的地址为172.16.25.72,与C主机通信。
4、C主机作为服务器端,拥有一个地址为172.16.25.73,与B主机的第二块网卡模拟为一个内网。此处采用虚拟机,可将B主机的第二块网卡和C主机的网卡设置为自定义的VMnet2。
(1)构建网络环境
[root@A ~]# nmtui # 配置地址为192.168.1.71/24,网关为192.168.1.72 [root@C ~]# nmtui # 配置地址为172.16.25.73/16,网关为172.16.25.72
[root@B ~]# sysctl -w net.ipv4.ip_forward=1 # 打开转发功能 [root@B ~]# nmtui #使用这个图形工具配置B主机网卡1(eno16777736)地址为192.168.1.72/24、网卡2(eno33554984)为172.16.25.72/16如下
此时A、B、C三台主机应该都可以互相ping通。
(2)在B主机上设置网络防火墙规则
为了更加好的演示防火墙功能,我们在C主机安装httpd服务和ftp服务如下。
# 注此时我使用的是本地光盘的yum源。 [root@C ~]# yum install -y httpd [root@C ~]# systemctl start httpd [root@C ~]# yum install -y vsftpd [root@C ~]# systemctl start vsftpd [root@C ~]# cat /var/www/html/index.html #编辑一个页面文件 It's OK! # 使用A主机测试可访问ftp服务和http服务 [root@A ~]# lftp 172.16.25.73 lftp 172.16.25.73:~> cd pub cd ok, cwd=/pub [root@A ~]# curl http://172.16.25.73/index.html It's OK!
接下来在B主机上设置防火墙规则(主要是FORWARD链)
# 在进行如下设置后,A主机不可访问C主机的http、ftp、ssh等服务。 [root@B ~]# systemctl stop firewalld # CentOS 7主机要禁用firewalld服务来使用iptables [root@B ~]# iptables -P INPUT DROP [root@B ~]# iptables -P OUTPUT DROP [root@B ~]# iptables -P FORWARD DROP # 设置FORWARD链的默认策略为DROP # 使用防火墙规则开放自己指定的服务 # 开放访问C主机的http请求报文的转发 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73/16 -p tcp --dport 80 -j ACCEPT # 开放C主机http响应报文的转发 [root@B ~]# iptables -A FORWARD -s 172.16.25.73/16 -d 192.168.1.0/24 -p tcp --sport 80 -j ACCEPT # 此时http可以访问 [root@A ~]# curl http://172.16.25.73/index.html It's OK! # 开放访问C主机的ssh服务给192.168.1.0网段主机 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73/16 -p tcp --dport 22 -j ACCEPT [root@B ~]# iptables -A FORWARD -s 172.16.25.73/16 -d 192.168.1.0/24 -p tcp --sport 22 -j ACCEPT # 此时ssh服务可以访问 [root@A ~]# ssh 172.16.25.73 [email protected]'s password: Last login: Sun Feb 14 19:52:11 2016 from 192.168.1.71 [root@C ~]# # 使A主机可以ping通C主机 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73 -p icmp --icmp-type 8 -j ACCEPT [root@B ~]# iptables -A FORWARD -s 172.16.25.73 -d 192.168.1.0/24 -p icmp --icmp-type 0 -j ACCEPT # 使C主机可以ping通A主机 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73 -p icmp --icmp-type 0 -j ACCEPT [root@B ~]# iptables -A FORWARD -s 172.16.25.73 -d 192.168.1.0/24 -p icmp --icmp-type 8 -j ACCEPT # 开放C主机的ftp服务给A主机网段 # 打开B主机的连接追踪机制 [root@B ~]# modprobe nf_conntrack_ftp # 放行命令连接 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73 -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT [root@B ~]# iptables -A FORWARD -s 172.16.25.73 -d 192.168.1.0/24 -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT # 测试可以连接并发出命令 [root@A ~]# lftp 172.16.25.73 lftp 172.16.25.73:~> cd pub cd ok, cwd=/pub lftp 172.16.25.73:/pub> # 放行数据连接 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT [root@B ~]# iptables -A FORWARD -s 172.16.25.73 -d 192.168.1.0/24 -p tcp -m state --state ESTABLISHED -j ACCEPT # 测试可以传输数据 [root@A ~]# lftp 172.16.25.73 lftp 172.16.25.73:~> cd pub cd ok, cwd=/pub lftp 172.16.25.73:/pub> ls -rw-r--r-- 1 0 0 23 Feb 14 12:44 issue lftp 172.16.25.73:/pub> mget issue 23 bytes transferred # 此时的B主机的规则如下 [root@B ~]# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.1.0/24 172.16.0.0/16 tcp dpt:80 ACCEPT tcp -- 172.16.0.0/16 192.168.1.0/24 tcp spt:80 ACCEPT tcp -- 192.168.1.0/24 172.16.0.0/16 tcp dpt:22 ACCEPT tcp -- 172.16.0.0/16 192.168.1.0/24 tcp spt:22 ACCEPT icmp -- 192.168.1.0/24 172.16.25.73 icmptype 8 ACCEPT icmp -- 172.16.25.73 192.168.1.0/24 icmptype 0 ACCEPT icmp -- 192.168.1.0/24 172.16.25.73 icmptype 0 ACCEPT icmp -- 172.16.25.73 192.168.1.0/24 icmptype 8 ACCEPT tcp -- 192.168.1.0/24 172.16.25.73 tcp dpt:21 state NEW,ESTABLISHED ACCEPT tcp -- 172.16.25.73 192.168.1.0/24 tcp spt:21 state ESTABLISHED ACCEPT tcp -- 192.168.1.0/24 172.16.25.73 state RELATED,ESTABLISHED ACCEPT tcp -- 172.16.25.73 192.168.1.0/24 state ESTABLISHED Chain OUTPUT (policy ACCEPT) target prot opt source destination
(3)使用优化考量优化以上规则如下
# 放行所有状态为ESTABLISHED和RELATED状态且不论来源和去向的报文,此条规则匹配大部分报文 [root@B ~]# iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # 此时放行请求报文,ssh和http、ftp服务都已经可以正常访问 [root@B ~]# iptables -A FORWARD -s 192.168.1.0/24 -d 172.16.25.73 -p tcp -m multiport --dports 22,21,80 -m state --state NEW -j ACCEPT # 放行ping的请求 [root@B ~]# iptables -A FORWARD -p icmp -m state --state NEW -j ACCEPT # 此时如下规则即可匹配(2)中的所有规则 [root@B ~]# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT tcp -- 192.168.1.0/24 172.16.25.73 multiport dports 22,21,80 state NEW ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 state NEW Chain OUTPUT (policy ACCEPT) target prot opt source destination
通过以上的规则,即可实现网络防火墙的功能,我们可以使用网络防火墙通过过滤转发报文来保护服务器。以上演示是添加规则,在真实环境中,我们可以按照实际需求设定规则。
五、使用iptables来实现NAT功能。
NAT最初是为了实现隐藏本地主机的目的。而在现在则主要为了实现公网地址和私网地址的通信。这个功能主要有iptables的nat表来实现。
而NAT可分为以下三种:
SNAT:源地址转换,一般发生在POSTROUTING链(路由决策才可以决定是否更改地址,PREROUTING和FORWARD和POSTROUTING都有路由决策)和OUTPUT链(本机的多块网卡之间的地址转换)。
使用场景:本地网络中的主机通过某一特定地址访问外部网络时使用;
DNAT:目标地址转换,一般发生在PREROUTING链(在路由决策之前,否则会转入本机)。
使用场景:让本地网络中的某些主机的某些服务开放给外部网络中的用户访问;
PNAT:端口 转换,亦可称作端口映射,比如web服务的服务端口为80,可将真正的web服务器主机的web服务监听端口设置为8080,而后当客户端访问时是80端口,在经过网关时转换为8080来访问真正的web服务。
NAT表的target:
SNAT
--to-source [ipaddr[-ipaddr]][:port[-port]]
--random:当有多个地址时,加上此选项时表示从中随机选一个;以下一样。
DNAT
--to-destination [ipaddr[-ipaddr]][:port[-port]]
--random
MASQUERADE
--to-ports port[-port]
--random
(1)SNAT演示
在本场景中,网络拓扑图和以上网络防火墙的网络一致。此时假设A主机的地址192.168.1.71为外网地址;B主机的网卡1地址192.168.1.72的地址亦为外网地址;而B主机的网卡2地址172.16.25.72和C主机的地址172.16.25.73为私网地址。而A主机此时提供web服务。
1> 为主机A配置web服务
[root@A ~]# yum install -y httpd [root@A ~]# systemctl start httpd [root@A ~]# vim /var/www/html/index.html [root@A ~]# cat /var/www/html/index.html It's A host # 此时由于我们配置过网关,C主机可直接访问A主机 [root@C ~]# curl http://192.168.1.71/index.html It's A host # 此时查看A主机的http访问日志,源地址是C主机的地址。 [root@A ~]# tail -f /var/log/httpd/access_log 172.16.25.73 - - [14/Feb/2016:23:57:18 +0800] "GET / HTTP/1.1" 200 12 "-" "curl/7.29.0"
2> 在主机B添加源地址转换规则
# 这条规则即表明172.16.25.0网段的地址访问外部网络时的源地址都转换为192.168.1.72 [root@B ~]# iptables -t nat -A POSTROUTING -s 172.16.25.0/16 -j SNAT --to-source 192.168.1.72 # 此时使用C主机访问A主机的web服务 [root@C ~]# curl 192.168.1.71 It's A host [root@A ~]# tail -f /var/log/httpd/access_log 172.16.25.73 - - [14/Feb/2016:23:57:18 +0800] "GET / HTTP/1.1" 200 12 "-" "curl/7.29.0" # 此处的源地址转换为192.168.1.72即我们假设的那个外网地址 192.168.1.72 - - [15/Feb/2016:00:05:21 +0800] "GET / HTTP/1.1" 200 12 "-" "curl/7.29.0"
注意:此时NAT仅可以转换源地址,而网络安全控制还是在filter表上实现,参见以上网络防火墙的实现。
(2)MASQUERADE示例
也做源地址转换:当外网源地址为动态获取的地址时,MASQUERADE可自行判断要转换为的外网地址;
亦可作源端口转换,但是源端口一般很少用,故不做演示。
规则示例
# 将上面主机B的规则换为以下这条,效果同上。 [root@B ~]# iptables -t nat -A POSTROUTING -s 172.16.25.0/16 -j MASQUERADE
(3)DNAT示例
在本场景中,网络拓扑图和以上网络防火墙的网络一致。此时假设A主机的地址192.168.1.71为外网地址;B主机的网卡1地址192.168.1.72的地址亦为外网地址;而B主机的网卡2地址172.16.25.72和C主机的地址172.16.25.73为私网地址。而私网内的C主机此时提供web服务。
1> 为主机A配置web服务同上。
# 此时使用A主机访问C主机的web服务 [root@A ~]# curl http://172.16.25.73/index.html It's C host! # 此时C主机的访问日志显示源地址为外网地址。 [root@C ~]# tail -f /var/log/httpd/access_log 192.168.1.71 - - [15/Feb/2016:00:31:29 +0800] "GET /index.html HTTP/1.1" 200 13 "-" "curl/7.29.0"
2> 在主机B添加目标地址转换规则
# web服务对外网的地址是192.168.1.72,而真正提供web服务的主机地址是私网地址172.16.25.73 [root@B ~]# iptables -t nat -A PREROUTING -d 192.168.1.72 -p tcp --dport 80 -j DNAT --to-destination 172.16.25.73 # 此时使用A主机访问web服务,使用公网地址192.168.1.72访问。 [root@A ~]# curl http://192.168.1.72/index.html It's C host! [root@C ~]# tail /var/log/httpd/access_log 192.168.1.71 - - [15/Feb/2016:00:38:14 +0800] "GET /index.html HTTP/1.1" 200 13 "-" "curl/7.29.0" # 此时如果C主机的web服务端口不是80,而是8080;我们在B主机的转换规则可以是如下实现端口和目# 标地址转换 [root@B ~]# iptables -t nat -A PREROUTING -d 192.168.1.72 -p tcp --dport 80 -j DNAT --to-destination 172.16.25.73:8080
至此,iptables的功能我们已经大致了解,此上部分的内容涉及filter表和nat表,而对于其他两个表mangle和raw表来说,mangle表的一个使用场景是在LVS中实现端口联姻,比如将web服务的443端口和80端口在Directory主机(负载均衡调度器)上通过防火墙规则实现端口联姻,将web服务请求发往后端的同一台realserver上。而raw表不是特别常用,若有用到,可以查询man文档来自己学习。
注:以上测完均在CentOS 7主机上完成。