Firewall(防火墙):工作在网络边缘(主机边缘),对进出网络数据包基于一定的规则检查,并在匹配某规则时由规则定义的处理进行处理的一组功能的组件。

防火墙类型:根据工作的层次的不同来划分,常见的防火墙工作在OSI第三层,即网络层防火墙,工作在OSI第七层的称为应用层防火墙,或者代理服务器(代理网关)。

 

网络层防火墙

网络层防火墙又称包过滤防火墙,在网络层对数据包进行选择,选择的依据是系统内设置的过滤逻辑,被称为访问控制列表(ACL),通过检查数据流中每个数据的源地址,目的地址,所用端口号和协议状态等因素,或他们的咋喝来确定是否允许该数据包通过。

优点:对用户来说透明,处理速度快且易于维护。

缺点:一旦黑客突破防火墙,就可以轻易地伪造数据包的源地址,目的地址和IP的端口号,即“IP地址伪造”。

iptables-details-and-configuration-01

包过滤防火墙图示

 

代理服务型防火墙

代理服务型防火墙(Proxy Service)将所有跨越防火墙的网络通信链路分为两段。当代理服务器接收到用户对某个站点的访问请求后会检查该请求是否符合控制规则。如果规则允许,则代理服务器会替用户去那个站点取回所需要的信息,转发给用户。内外网用户的访问都是通过代理服务器上的“链接”来实现的,从而起到了隔离防火墙内外计算机系统的作用。

特点:在应用层对数据进行检查,比较安全。但是会增加防火墙的负载。

iptables-details-and-configuration-02

代理服务型防火墙图示

 

现实生产环境中所使用的防火墙一般都是二者结合体。

即先检查网络数据,通过之后再送到应用层去检查。

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-details-and-configuration-03

                       iptables传输数据包的过程

  1   当一个数据包进入网卡时,数据包首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去。

  2   如果数据包就是进入本机的,数据包就会沿着图向下移动,到达INPUT链。数据包到达INPUT链后,任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包经过OUTPUT链,然后到达POSTROTING链输出。

  3  如果数据包是要转发出去的,且内核允许转发,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出。

iptables-details-and-configuration-04

                      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

iptables-details-and-configuration-05

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

iptables-details-and-configuration-06

此时,自定义链依旧无法使用,我们只能在固定链上做转发请求数据包到自定义链上,才能实现自定义链的功能。

[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

iptables-details-and-configuration-07

此时,已经可以正常访问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=”后面写上要添加的模块就可以了。

iptables-details-and-configuration-08

[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状态

iptables-details-and-configuration-09

此时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链上做。

下面我们来实现源地址的功能:

我们假设这样一种场景:

iptables-details-and-configuration-10

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,看,已经可以了!

iptables-details-and-configuration-11

只需一条规则就可以搞定,很方便吧!

PS:如果我们使用路由功能来访问254这台主机的话,WEB服务器的访问日志将记录的访问地址是192.168.80.130,而如果我们使用地址转换的功能来访问的话,访问日志记录的访问地址则是192.168.0.127。.

一般我们上网的时候,所获得的IP都是动态的,怎么办?

做源地址转换的时候,还有一个小功能MASQUERADE(地址伪装),使用这个功能,我们不需要

指定目标地址,它会自动探测能够上互联网的地址,并自动将内网地址转换过来。缺陷:比较耗费资源。

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

接下来开始实现目标地址转换功能:

iptables-details-and-configuration-12

场景:假设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这台主机,这就是目标地址转换的功能。

iptables-details-and-configuration-13

我们再查看一下192.168.80.130这台WEB服务器的访问日志:

iptables-details-and-configuration-14

看,源地址并没有发生改变!只是访问的目标地址被转换到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 -L -n
iptalbes -P INPUT ACCEPT
iptables -F
iptables -P  INPUT   ACCEPT
iptables -P  OUTPUT  ACCEPT
at now+10min

测试完成之后停掉脚本就可以了。

 

原文: 开源中国