Firewall(防火墙):组件,工作在网络边缘(主机边缘),对进出网络数据包基于一定的规则检查,并在匹配某规则时由规则定义的处理进行处理的一组功能的组件。
防火墙类型:根据工作的层次的不同来划分,常见的防火墙工作在OSI第三层,即网络层防火墙,工作在OSI第七层的称为应用层防火墙,或者代理服务器(代理网关)。
网络层防火墙又称包过滤防火墙,在网络层对数据包进行选择,选择的依据是系统内设置的过滤逻辑,被称为访问控制列表(ACL),通过检查数据流中每个数据的源地址,目的地址,所用端口号和协议状态等因素,或他们的咋喝来确定是否允许该数据包通过。
优点:对用户来说透明,处理速度快且易于维护。
缺点:一旦黑客突破防火墙,就可以轻易地伪造数据包的源地址,目的地址和IP的端口号,即“IP地址伪造”。
包过滤防火墙图示
代理服务型防火墙(Proxy Service)将所有跨越防火墙的网络通信链路分为两段。当代理服务器接收到用户对某个站点的访问请求后会检查该请求是否符合控制规则。如果规则允许,则代理服务器会替用户去那个站点取回所需要的信息,转发给用户。内外网用户的访问都是通过代理服务器上的“链接”来实现的,从而起到了隔离防火墙内外计算机系统的作用。特点:在应用层对数据进行检查,比较安全。但是会增加防火墙的负载。
代理服务型防火墙图示
现实生产环境中所使用的防火墙一般都是二者结合体。即先检查网络数据,通过之后再送到应用层去检查。
netfilter组件称为内核空间,它被集成在linux内核中。netfilter是一种内核中用于扩展各种网络服务的结构化底层框架。它是在内核中选取五个位置放了五个hook function,而这五个hook function向用户开放,用户可以通过一个工具(iptables)向其写规则。
netfilter 主要由信息过滤表(table)组成,包含了控制IP包处理的规则集(rules)。根据规则所处理的IP包的类型,规则被分组放在链(chain)中,从而使内核对来自某些源,前往某些目的地或具有某些协议类型的信息包处置方法,如完成信息包的处理、控制和过滤等工作。
iptables也称为用户空间,是一个工作在用户层用来写规则的工具,写好的规则被送往netfilter。这些规则告诉内核中的netfilter组件如何去处理信息包。
五个hook function(规则链):Input ,Output,Forward,prerouting,postrouting。
filter:Input,Output,Forward
四种处理机制(表):过滤(filter) 主要用于过滤数据包,该表根据管理员预定义的一组规则过滤符
合条件的数据包。filter表是iptables默认的表。
l INPUT:主要与想要进入我们 Linux 本机的数据包有关;
l OUTPUT:主要与我们 Linux 本机所要送出的数据包有关;
l FORWARD:与 Linux 本机比较没有关系, 他可以传递数据包到后台的计算机中,与下列 nat table 相关性较高。
地址转换(NAT) 主要用于网络地址转换,该表可实现一对一。一对多,多对多
等工作,iptables就是使用该表实现共享上网功能。
l PREROUTING:在进行路由判断之前所要进行的规则(DNAT/REDIRECT)
l POSTROUTING:在进行路由判断之后所要进行的规则(SNAT/MASQUERADE)
l OUTPUT:与发送出去的数据包包有关
包重构(mangle)对指定的数据包进行修改,例如更改TTL和TOS等,实际中很
少使用。
RAW 很少使用
一条链可以包含一条或者数条规则。
nat:prerouting,postrouting,output
mangle:Input ,Output,Forward,prerouting,postrouting。
RAW:prerouting,output
iptables传输数据包的过程
1 当一个数据包进入网卡时,数据包首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去。
2 如果数据包就是进入本机的,数据包就会沿着图向下移动,到达INPUT链。数据包到达INPUT链后,任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包经过OUTPUT链,然后到达POSTROTING链输出。
3 如果数据包是要转发出去的,且内核允许转发,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出。
iptables中各表与链的相互关系 《鸟哥的私房菜》
书写规则:
iptables [-t table] command CHAIN [NUM ] match criteria -j TARGET
CHAIN: 对链进行的操作
-N:new 新建一条链
-X 删除一条用户自定义链(空链)
-F:flush 清空一条链,默认清空表中所有链
-Z:zero 清空计数器,iptables中每条规则默认有两个计数器,用于记录本条规则所匹配到的数据包的个数和本条规则所匹配到的数据包的总大小
-P:policy 定义链的默认处理策略
-E 重命名链
RULE:对规则进行的操作
-A:append 追加,在链的最后加一条规则
-I:insert 插入一条规则 一般使用-I CHAIN NUM 给规则加一个编号。
-R:replace 替换某条规则,规则被替换并不会改变顺序,必须要指定替换的规则编号:-R CHAIN NUM。
-D:delete 删除一条规则,可以输入完整规则,或者直接指定标号加以删除:-D CHAIN NUM。
LIST:查看
-L:list 列出链中的所有规则
辅助性子命令:-n numeric 以数字的形式来显示地址,默认显示主机名称
-v verbose 显示详细信息 ,支持-vv -vvv格式,v越多,信息越详细。
-x 显示原有信息,不要做单位换算
--line-numbers 显示规则的行号
Match Creteria(匹配规则):
基本匹配
-s,--src,--source 匹配数据包的源地址
-d,--dst,--destination 匹配数据包的目标地址
-i, 指定数据包的流入接口(逻辑接口)
-o, 指定数据包的流出接口
-p, 做协议匹配 protocol,(tcp|udp|icmp)
扩展匹配:对某一种功能的扩展
隐含扩展 :对某一种协议的扩展
-p tcp
--sport 指定源端口
--dport 指定目的端口
--tcp-flags(SYN,ACK,FIN,PSH,URG,RST,ALL,NONE)指定TCP的标志位
需要跟两个标志位列表,如:SYN,ACK,FIN,RST SYN 第一个列表表示要检查的位,第二个
列表表示第一个列表中出现的位必须为1,未出现的必须为0
--syn 只允许新连接
-p udp 无连接协议
--sport 指定源端口
--dport 指定目的端口
-p icmp
--icmp-type echo-request,8(ping出去,请求回应,) echo-reply,0(给予回应)
显式扩展 :额外附加的更多的匹配规则,功能性地扩展
-m state 状态检测扩展
NEW 用户发起一个全新的请求
ESTABLISHED 对一个全新的请求进行回应
RELATED 两个完整连接之间的相互关系,一个完整的连接,需要依赖于另一个完整的连接
INVALID 无法识别的状态
-m multiport --sports 22,80,443 指定多个源端口
--dports 22,80,443 指定多个目标端口
--ports 非连续端口
-m connlimit 限定并发连接速率
!--connlimit-above 5 高于五个将拒绝
-m string 字符串匹配
--algo bm|kmp 指定算法
--string pattern
-m time 基于时间的匹配
--timestart
--timestop
--days
-j TARGET 处理动作
ACCEPT 接受
DROP 悄悄丢弃,请求端没有任何回应
REJECT 明确拒绝
SNAT 源地址转换
DNAT 目标地址转换
REDIRECT 端口重定向
LOG 将访问记录下来
[root@server27 ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
下面我们写两条规则:
只允许192.168.0.0网段的主机通过SSH访问该主机
允许本机通过SSH连接192.168.0.0网段的其他主机
[root@server27 ~]# iptables -A INPUT -s 192.168.0.0/24 -d 192.168.0.127 -p tcp --dport 22 -j ACCEPT
[root@server27 ~]# iptables -A OUTPUT -s 192.168.0.127 -d 192.168.0.0/24 -p tcp --sport 22 -j ACCEPT
[root@server27 ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 192.168.0.0/24 192.168.0.127 tcp dpt:22
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 192.168.0.127 192.168.0.0/24 tcp spt:22
定义默认策略
[root@server27 ~]# iptables -t filter -P INPUT DROP
[root@server27 ~]# iptables -t filter -P OUTPUT DROP
PS:上面规则一定不要写错了,否则你将会把自己拒之门外。
允许本机PING本网段任何主机
[root@server27 ~]# iptables -t filter -A OUTPUT -s 192.168.0.127 -d 0.0.0.0/0.0.0.0 -p icmp --icmp-type 8 -j ACCEPT //**出去的数据包
[root@server27 ~]# iptables -t filter -A INPUT -s 0.0.0.0/0.0.0.0 -d 192.168.0.127 -p icmp --icmp-type 0 -j ACCEPT //** 回来的数据包
[root@server27 ~]# ping 192.168.0.236 -c 4
PING 192.168.0.236 (192.168.0.236) 56(84) bytes of data.
64 bytes from 192.168.0.236: icmp_seq=1 ttl=64 time=0.242 ms
64 bytes from 192.168.0.236: icmp_seq=2 ttl=64 time=0.249 ms
64 bytes from 192.168.0.236: icmp_seq=3 ttl=64 time=0.437 ms
64 bytes from 192.168.0.236: icmp_seq=4 ttl=64 time=0.204 ms
允许本网段任何主机PING本机
[root@server27 ~]# iptables -t filter -A OUTPUT -s 192.168.0.127 -d 0.0.0.0/0.0.0.0 -p icmp --icmp-type 0 -j ACCEPT
[root@server27 ~]# iptables -t filter -A INPUT -d 192.168.0.127 -s 0.0.0.0/0.0.0.0 -p icmp --icmp-type 8 -j ACCEPT
PS:当目标网络指定为任意主机时,应该为0.0.0.0/0.0.0.0
凡是来自192.168.0.0/24网段的主机均使用一个自定义的新链
先开启http服务
自定义一条链,拒绝192.168.0.0/24网段的主机对http服务的访问
[root@server27 ~]# iptables -N attach-input
[root@server27 ~]# iptables -A attach-input -s 192.168.0.0/24 -d 192.168.0.127 -p tcp --dport 80 -j DROP
[root@server27 ~]# iptables -L -n
此时,自定义链依旧无法使用,我们只能在固定链上做转发请求数据包到自定义链上,才能实现自定义链的功能。
[root@server27 ~]# iptables -A INPUT -s 192.168.0.0/24 -j attach-input
[root@server27 ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
attach-input all -- 192.168.0.0/24 0.0.0.0/0
此时已经无法访问到网页。
将INPUT链删除之后,马上又可以访问了。
[root@server27 ~]# iptables -F INPUT
删除自定义链,先清空链,再清空规则
[root@server27 ~]# iptables -F attach-input
[root@server27 ~]# iptables -X attach-input
PS:每条规则都可以使用“!”取反。如: -s '!' 192.168.0.0/24,加单引号防止被识别成其他字符。
下面我们来实现显式扩展状态检测的功能:
先将默认策略置为DROP
[root@server27 ~]# iptables -P INPUT DROP
[root@server27 ~]# iptables -P OUTPUT DROP
[root@server27 ~]# iptables -P FORWARD DROP
[root@server27 ~]# iptables -A INPUT -d 192.168.0.127 -p tcp --dport 80 -j ACCEPT //*进来的数据包
[root@server27 ~]# iptables -A OUTPUT -s 192.168.0.127 -p tcp --sport 80 -j ACCEPT //*出去的数据包
但是这两条规则对于反弹式木马是无效的。
我们可以基于显式扩展写这样两条规则:
[root@server27 ~]# iptables -I INPUT 1 -d 192.168.0.127 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT //**进来的数据包
[root@server27 ~]# iptables -I OUTPUT -s 192.168.0.127 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT //**出去的数据包
删除我们之前建立的那两条规则:
[root@server27 ~]# iptables -D INPUT 2
[root@server27 ~]# iptables -D OUTPUT 2
此时,已经可以正常访问http服务。
我们试一下ftp服务:
先开启ftp服务
先建立这样四条规则,看看能不能达到效果,
[root@server27 ~]# iptables -A INPUT -d 192.168.0.127 -p tcp --dport 21 -j ACCEPT
[root@server27 ~]# iptables -A INPUT -d 192.168.0.127 -p tcp --dport 20 -j ACCEPT
[root@server27 ~]# iptables -A OUTPUT -s 192.168.0.127 -p tcp --sport 21 -j ACCEPT
[root@server27 ~]# iptables -A OUTPUT -s 192.168.0.127 -p tcp --sport 20 -j ACCEPT
客户端请求是被动模式,实验证明,我们仅仅开始21 20端口无法达到效果。这样我们就得用到状态检测的RELATED机制。
PS:要想实现FTP的访问需先手动加载额外的模块:ip_conntrack_ftp,ip_conntrack_tftp,ip_nat_ftp,,ip_nat_tftp(and others)
[root@server27 ~]# modprobe ip_conntrack_ftp
[root@server27 ~]# modprobe ip_nat_ftp
[root@server27 ~]# modprobe ip_nat_tftp
[root@server27 ~]# modprobe ip_conntrack_tftp
实现自动加载的功能:编辑/etc/sysconfig/iptables-config文件,在“IPTABLES_MODULES=”后面写上要添加的模块就可以了。
[root@server27 ~]# iptables -A INPUT -d 192.168.0.127 -p tcp --dport 21 -j ACCEPT
[root@server27 ~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
[root@server27 ~]# iptables -A INPUT -d 192.168.0.127 -p tcp -m state --state RELATED -j ACCEPT
[root@server27 ~]# iptables -R OUTPUT 2 -m state --state ESTABLISHED,RELATED -j ACCEPT //**修改上一条规则,增加RELATED状态
[root@server27 ~]# iptables -R INPUT 3 -d 192.168.0.127 -p tcp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT //**修改INPUT第三条规则,增加NEW,ESTABLISHED状态
此时ftp已经可以访问了,要保证所有的规则能够永久有效需要使用:service iptables save来保存。
基于字符串匹配的显式扩展功能:
[root@server27 ~]# iptables -A INTPUT -d 192.168.0.127 -p tcp --dport 80 -m string --algo kmp --string 'qq.com' -j REJECT
PS:iptables工作在OSI第三层,第四层。默认情况下,iptables无法限定第七层的应用程序,要想实现限制七层某些应用程序的功能,需要重编译内核,在内核上打上补丁 layer7。.
源地址换换和目标地址转换:
PS:源地址转换必须在POSTROUTING链上做。
目标地址转换必须在PREROUTING链上做。
下面我们来实现源地址的功能:
我们假设这样一种场景:
192.168.0.254是工作在外网的一台WEB服务器,中间的那台是企业里的NAT服务器,我们在上面添加iptables的规则,使其实现地址转换的功能,PC机是工作在企业内部。我们的最终目的是192.168.80.30这台计算机通过NAT服务器可以访问到192.168.0.254的WEB服务。
实验环境搭建:192.168.0.254 192.168.0.127使用虚拟机网卡的桥接功能;
192.168.80.129 192.168.080.130使用虚拟机网卡的仅主机功能;
为PC机设置网关:
[root@station39 ~]# route add default gw 192.168.80.129
下面开始来配置NAT服务器:
首先要开启NAT服务器的内核路由功能:
[root@server27 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@server27 ~]# cat /proc/sys/net/ipv4/ip_forward
1
设置规则:
[root@server27 ~]# iptables -t nat -A POSTROUTING -s 192.168.80.0/24 -d 192.168.0.0/24 -j SNAT --to-source 192.168.0.127
[root@server27 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 192.168.80.0/24 192.168.0.0/24 to:192.168.0.127
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
OK,我们用192.168.80.130这台主机访问一下192.168.0.254,看,已经可以了!
只需一条规则就可以搞定,很方便吧!
PS:如果我们使用路由功能来访问254这台主机的话,WEB服务器的访问日志将记录的访问地址是192.168.80.130,而如果我们使用地址转换的功能来访问的话,访问日志记录的访问地址则是192.168.0.127。.
一般我们上网的时候,所获得的IP都是动态的,怎么办?
做源地址转换的时候,还有一个小功能MASQUERADE(地址伪装),使用这个功能,我们不需要
指定目标地址,它会自动探测能够上互联网的地址,并自动将内网地址转换过来。缺陷:比较耗费资源。
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
接下来开始实现目标地址转换功能:
场景:假设192.168.80网段为一个提供WEB服务的网站的内网,中间的为网站的NAT服务器,远端的客户端192.168.0.26想通过中间的NAT服务器来访问内部的192.168.80.130提供的WEB服务,这里就要用到目标地址转换了。
环境搭设:192.168.80.130 192.168.80.129使用虚拟机网卡的仅主机功能
192.168.0.26 192.168.0.127使用虚拟机网卡的桥接功能
设置192.168.80.130的网关:
[root@station39 ~]# route add default gw 192.168.80.129
开始在NAT服务器上设置规则:
这里依然要打开内核的路由功能。
开始之前先将刚才做的源地址转换实验的规则给清除了
[root@server27 ~]# iptables -t nat -F
开始写规则:
[root@server27 ~]# iptables -t nat -A PREROUTING -s 192.168.0.0/24 -d 192.168.0.127 -p tcp --dport 80 -j DNAT --to-destination 192.168.80.130
[root@server27 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- 192.168.0.0/24 192.168.0.127 tcp dpt:80 to:192.168.80.130
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
OK!规则已经写好了,我们使用192.168.0.26来访问一下192.168.0.127试试,已经可以访问了,其实提供WEB服务的是192.168..80.130这台主机,这就是目标地址转换的功能。
我们再查看一下192.168.80.130这台WEB服务器的访问日志:
看,源地址并没有发生改变!只是访问的目标地址被转换到192.168.80.130上来了,这就是目标地址转换。
l7-filter 七层过滤,对内核打补丁之后,能够支持对应用层数据的过滤。
编译过程相对繁琐一些,也不是本文主要讲述内容,所以就不在此详细说明,有兴趣的朋友可以去网上查找相关教程。
编译完成并启用内核之后,就可以使用l7filter的过滤功能了。
我们添加这样两条规则:
[root@server27 ~]# iptables -t nat -A POSTROUTING -s 192.168.80.0/24 -d 192.168.0.0/24 -j SNAT --to-source 192.168.0.127
[root@server27 ~]# iptables -t nat -A FORWARD -m layer7 --l7proto qq -j REJECT
这里就不再演示效果了。
保存iptables规则:
/etc/init.d/iptables save
service iptables save
保存位置:在/etc/sysconfig/iptables文件内:
# Generated by iptables-save v1.3.5 on Fri Mar 4 19:44:47 2011
*filter
:INPUT DROP [33:2399]
:FORWARD DROP [0:0]
:OUTPUT DROP [7:540]
-A INPUT -d 192.168.0.127 -p tcp -m tcp --dport 21 -j ACCEPT
-A INPUT -d 192.168.0.127 -p tcp -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Fri Mar 4 19:44:47 2011
指定规则保存位置:
iptables-save > /etc/sysconfig/iptables/iptables.20110307
生效保存的规则
iptables-restore < /etc/sysconfig/iptables/iptables.20110307
避免在远程连接写规则的时候一不小心自己被防火墙拒之门外,可以写一个小脚本:
#!/bin/bash
iptables -F
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
at now+10min
测试完成之后停掉脚本就可以了。