一:前言

防火墙用于实现Linux下访问控制的功能的,它分为硬件的或者软件的防火墙两种。无论是在哪个网络中,防火墙工作的地方一定是在网络的边缘。而我们的任务就是需要去定义到底防火墙如何工作,这就是防火墙的策略,规则,以达到让它对出入网络的IP、数据进行检测。

目前市面上比较常见的有3、4层的防火墙,叫网络层的防火墙,还有7层的防火墙,其实是代理层的网关

   对于TCP/IP的七层模型来讲,我们知道第三层是网络层,三层的防火墙会在这层对源地址和目标地址进行检测。但是对于七层的防火墙,不管你源端口或者目标端口,源地址或者目标地址是什么,都将对你所有的东西进行检查。所以,七层防火墙更加安全,但是这却带来了效率更低。所以市面上通常的防火墙方案,都是两者结合的。而又由于我们都需要从防火墙所控制的这个口来访问,所以防火墙的工作效率就成了用户能够访问数据多少的一个最重要的控制,配置的不好甚至有可能成为流量的瓶颈。

二:iptables 工作原理

iptables的结构:iptables -> Tables -> Chains -> Rules. 简单地讲,tables由chains组成,而chains又由rules组成。

五个规则链。

  1.PREROUTING (路由前)

  2.INPUT (数据包流入口)

  3.FORWARD (转发管卡)

  4.OUTPUT(数据包出口)

  5.POSTROUTING(路由后)

  这是NetFilter规定的五个规则链,任何一个数据包,只要经过本机,必将经过这五个链中的其中一个链。      

iptables具有Filter, NAT, Mangle, Raw四种内建表:

1. Filter表

Filter表示iptables的默认表,因此如果你没有自定义表,那么就默认使用filter表,它具有以下三种内建链:

  • INPUT链 – 处理来自外部的数据。

  • OUTPUT链 – 处理向外发送的数据。

  • FORWARD链 – 将数据转发到本机的其他网卡设备上。

2. NAT表

NAT表有三种内建链:

  • PREROUTING链 – 处理刚到达本机并在路由转发前的数据包。它会转换数据包中的目标IP地址(destination ip address),通常用于DNAT(destination NAT)。

  • POSTROUTING链 – 处理即将离开本机的数据包。它会转换数据包中的源IP地址(source ip address),通常用于SNAT(source NAT)。

  • OUTPUT链 – 处理本机产生的数据包。

3. Mangle表

Mangle表用于指定如何处理数据包。它能改变TCP头中的QoS位。Mangle表具有5个内建链:

  • PREROUTING

  • OUTPUT

  • FORWARD

  • INPUT

  • POSTROUTING

4. Raw表

Raw表用于处理异常,它具有2个内建链:

  • PREROUTING chain

  • OUTPUT chain

 iptables还支持自己定义链。但是自己定义的链,必须是跟某种特定的链关联起来的。在一个关卡设定,指定当有数据的时候专门去找某个特定的链来处理,当那个链处理完之后,再返回。接着在特定的链中继续检查。

注意规则的次序非常关键,谁的规则越严格,应该放的越靠前,而检查规则的时候,是按照从上往下的方式进行检查的。


牢记以下三点式理解iptables规则的关键:

  • Rules包括一个条件和一个目标(target)

  • 如果满足条件,就执行目标(target)中的规则或者特定值。

  • 如果不满足条件,就判断下一条Rules。

在target里指定的特殊值:

  • ACCEPT – 允许防火墙接收数据包

  • DROP – 防火墙丢弃包

  • QUEUE – 防火墙将数据包移交到用户空间

  • RETURN – 防火墙停止执行当前链中的后续Rules,并返回到调用链(the calling chain)中。

三.规则的写法:

格式:iptables [-t table] COMMAND chain CRETIRIA -j ACTION

  -t table :3个filter nat mangle

  COMMAND:定义如何对规则进行管理

  chain:指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的

  CRETIRIA:指定匹配标准

  -j ACTION :指定如何进行处理

比如:不允许172.16.0.0/24的进行访问。

  iptables -t filter -A INPUT -s 172.16.0.0/16 -p udp --dport 53 -j DROP

查看mangle表:  # iptables -t mangle --list   如果不指定-t选项,就只会显示默认的filter表。

四:详解COMMAND:

1.链管理命令(这都是立即生效的)

-P :设置默认策略的

默认策略一般只有两种(关着的还是开着的

iptables -P INPUT (DROP|ACCEPT)  默认是关的/默认是开的

比如:

iptables -P INPUT DROP 这就把默认规则给拒绝了。并且没有定义哪个动作,所以关于外界连接的所有规则包括Xshell连接之类的,远程连接都被拒绝了。

-F: FLASH,清空规则链的(注意每个链的管理权限)

   iptables -t nat -F PREROUTING

   iptables -t nat -F 清空nat表的所有链

-N:NEW 支持用户新建一个链

  iptables -N inbound_tcp_web 表示附在tcp表上用于检查web的。

-X: 用于删除用户自定义的空链

  使用方法跟-N相同,但是在删除之前必须要将里面的规则给清空了

-E:用来Rename chain主要是用来给用户自定义的链重命名

   -E oldname newname

-Z:清空链,及链中默认规则的计数器的(有两个计数器,被匹配到多少个数据包,多少个字节)

   iptables -Z :清空

2.规则管理命令

        -A:追加,在当前链的最后新增一个规则

        -I num : 插入,把当前规则插入为第几条。

           -I 3 :插入为第三条

        -R num:Replays替换/修改第几条规则

           格式:iptables -R 3 …………

        -D num:删除,明确指定删除第几条规则

3.查看管理命令 “-L”

  -n:以数字的方式显示ip,它会将ip直接显示出来,如果不加-n,则会将ip反向解析成主机名。

  -v:显示详细信息

  --line-numbers : 显示规则的行号

  -t nat:显示所有的关卡的信息

五:详解匹配标准

1.通用匹配:源地址目标地址的匹配

    -s:指定作为源地址匹配,这里不能指定主机名称,必须是IP

       IP | IP/MASK | 0.0.0.0/0.0.0.0

       而且地址可以取反,加一个“!”表示除了哪个IP之外

    -d:表示匹配目标地址

    -p:用于匹配协议的(这里的协议通常有3种,TCP/UDP/ICMP)

    -i eth0:从这块网卡流入的数据

       流入一般用在INPUT和PREROUTING上

    -o eth0:从这块网卡流出的数据

       流出一般在OUTPUT和POSTROUTING上

2.扩展匹配

2.1隐含扩展:对协议的扩展

   -p tcp :TCP协议的扩展。一般有三种扩展

  --dport XX-XX:指定目标端口,不能指定多个非连续端口,只能指定单个端口,比如

  --dport 21  或者 --dport 21-23 (此时表示21,22,23)

  --sport:指定源端口

  --tcp-fiags:TCP的标志位(SYN,ACK,FIN,PSH,RST,URG)

   对于它,一般要跟两个参数:

  1.检查的标志位

  2.必须为1的标志位

--tcpflags syn,ack,fin,rst syn   =    --syn

表示检查这4个位,这4个位中syn必须为1,其他的必须为0。所以这个意思就是用于检测三次握手的第一次包的。对于这种专门匹配第一包的SYN为1的包,还有一种简写方式,叫做--syn

   -p udp:UDP协议的扩展

       --dport

       --sport

   -p icmp:icmp数据报文的扩展

       --icmp-type:

echo-request(请求回显),一般用8 来表示

所以 --icmp-type 8 匹配请求回显数据包

echo-reply (响应的数据包)一般用0来表示

2.2显式扩展(-m)

    扩展各种模块

     -m multiport:表示启用多端口扩展

     之后我们就可以启用比如 --dports 21,23,80

六:详解-j ACTION

常用的ACTION:

DROP:悄悄丢弃

一般我们多用DROP来隐藏我们的身份,以及隐藏我们的链表

REJECT:明示拒绝

ACCEPT:接受

custom_chain:转向一个自定义的链

DNAT

SNAT

MASQUERADE:源地址伪装

REDIRECT:重定向:主要用于实现端口重定向

MARK:打防火墙标记的

RETURN:返回

在自定义链执行完毕后使用返回,来返回原规则链。


练习题:

    1.只要是来自于172.16.0.0/16网段的都允许访问我本机的172.16.100.1的SSHD服务

    分析:首先肯定是在允许表中定义的。因为不需要做NAT地址转换之类的,然后查看我们SSHD服务,在22号端口上,处理机制是接受,对于这个表,需要有一来一回两个规则,如果我们允许也好,拒绝也好,对于访问本机服务,我们最好是定义在INPUT链上,而OUTPUT再予以定义就好。(会话的初始端先定义),所以加规则就是:

    定义进来的: iptables -t filter -A INPUT -s 172.16.0.0/16 -d 172.16.100.1 -p tcp --dport 22 -j ACCEPT

    定义出去的: iptables -t filter -A OUTPUT -s 172.16.100.1 -d 172.16.0.0/16 -p tcp --dport 22 -j ACCEPT

    将默认策略改成DROP:

   iptables -P INPUT DROP

   iptables -P OUTPUT DROP

   iptables -P FORWARD DROP

1.SSH

# 1.允许接收远程主机的SSH请求

iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# 2.允许发送本地主机的SSH响应

iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

  • -m state: 启用状态匹配模块(state matching module)

  • -state: 状态匹配模块的参数。当SSH客户端第一个数据包到达服务器时,状态字段为NEW;建立连接后数据包的状态字段都是ESTABLISHED

  • –sport 22: sshd监听22端口,同时也通过该端口和客户端建立连接、传送数据。因此对于SSH服务器而言,源端口就是22

  • –dport 22: ssh客户端程序可以从本机的随机端口与SSH服务器的22端口建立连接。因此对于SSH客户端而言,目的端口就是22

如果服务器也需要使用SSH连接其他远程主机,则还需要增加以下配置:

# 1.送出的数据包目的端口为22

iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

# 2.接收的数据包源端口为22

iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

2.HTTP-----HTTP的配置与SSH类似:

# 1.允许接收远程主机的HTTP请求

iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

# 1.允许发送本地主机的HTTP响应

iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

七:状态检测:

是一种显式扩展,用于检测会话之间的连接关系的,有了检测我们可以实现会话间功能的扩展

       什么是状态检测?对于整个TCP协议来讲,它是一个有连接的协议,三次握手中,第一次握手,我们就叫NEW连接,而从第二次握手以后的,ack都为1,这是正常的数据传输,和tcp的第二次第三次握手,叫做已建立的连接(ESTABLISHED),还有一种状态,比较诡异的,比如:SYN=1 ACK=1 RST=1,对于这种我们无法识别的,我们都称之为INVALID无法识别的。还有第四种,FTP这种古老的拥有的特征,每个端口都是独立的,21号和20号端口都是一去一回,他们之间是有关系的,这种关系我们称之为RELATED。

所以我们的状态一共有四种:

       NEW

       ESTABLISHED

       RELATED

       INVALID

所以我们对于刚才的练习题,可以增加状态检测。比如进来的只允许状态为NEW和ESTABLISHED的进来,出去只允许ESTABLISHED的状态出去,这就可以将比较常见的反弹式***有很好的控制机制。

练习题的扩展:

进来的拒绝但出去的允许,进来的只允许ESTABLISHED进来,出去只允许ESTABLISHED出去。默认规则都使用拒绝

iptables -L -n --line-number  :查看之前的规则位于第几行

改写INPUT

       iptables -R INPUT 2 -s 172.16.0.0/16 -d 172.16.100.1 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

       iptables -R OUTPUT 1 -m state --state ESTABLISHED -j ACCEPT


此时如果想再放行一个80端口如何放行呢?

       iptables -A INPUT -d 172.16.100.1 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

       iptables -R INPUT 1 -d 172.16.100.1 -p udp --dport 53 -j ACCEPT


练习题2:

假如我们允许自己ping别人,但是别人ping自己ping不通如何实现呢?

分析:对于ping这个协议,进来的为8(ping),出去的为0(响应).我们为了达到目的,需要8出去,允许0进来

在出去的端口上:iptables -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT

在进来的端口上:iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT

小扩展:对于127.0.0.1比较特殊,我们需要明确定义它

iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT

iptables -A OUTPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT


八:SNAT和DNAT的实现

由于我们现在IP地址十分紧俏,已经分配完了,这就导致我们必须要进行地址转换,来节约我们仅剩的一点IP资源。那么通过iptables如何实现NAT的地址转换呢?

1.SNAT基于原地址的转换

基于原地址的转换一般用在我们的许多内网用户通过一个外网的口上网的时候,这时我们将我们内网的地址转换为一个外网的IP,我们就可以实现连接其他外网IP的功能

所以我们在iptables中就要定义到底如何转换:

比如我们现在要将所有192.168.10.0网段的IP在经过的时候全都转换成172.16.100.1这个假设出来的外网地址:

iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to-source 172.16.100.1

这样,只要是来自本地网络的试图通过网卡访问网络的,都会被统统转换成172.16.100.1这个IP.

那么,如果172.16.100.1不是固定的怎么办?

我们都知道当我们使用联通或者电信上网的时候,一般它都会在每次你开机的时候随机生成一个外网的IP,意思就是外网地址是动态变换的。这时我们就要将外网地址换成 MASQUERADE(动态伪装):它可以实现自动寻找到外网地址,而自动将其改为正确的外网地址。所以,我们就需要这样设置:

        iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE

        这里要注意:地址伪装并不适用于所有的地方。

2.DNAT目标地址转换

对于目标地址转换,数据流向是从外向内的,外面的是客户端,里面的是服务器端通过目标地址转换,我们可以让外面的ip通过我们对外的外网ip来访问我们服务器不同的服务器,而我们的服务却放在内网服务器的不同的服务器上

   如何做目标地址转换呢?:

iptables -t nat -A PREROUTING -d 192.168.10.18 -p tcp --dport 80 -j DNAT --todestination 172.16.100.2

   目标地址转换要做在到达网卡之前进行转换,所以要做在PREROUTING这个位置上

九:控制规则的存放以及开启

注意:你所定义的所有内容,当你重启的时候都会失效,要想我们能够生效,需要使用一个命令将它保存起来

   1.service iptables save 命令

它会保存在/etc/sysconfig/iptables这个文件中

   2.iptables-save 命令

iptables-save > /etc/sysconfig/iptables

   3.iptables-restore 命令

开机的时候,它会自动加载/etc/sysconfig/iptabels

如果开机不能加载或者没有加载,而你想让一个自己写的配置文件(假设为iptables.2)手动生效的话:

   iptables-restore < /etc/sysconfig/iptables.2

则完成了将iptables中定义的规则手动生效


自定义链

在自定义链之前先查看一下防火墙规则

# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination     
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0       
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0       
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination     
REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

开始自定义链

iptables -N test //test是新建的链,默认是在filter表
iptables -A test -p tcp --dport 30004 -j DROP
iptables -A test -p tcp --dport 30005 -j DROP
iptables -A test -p tcp -m multiport --dport 20001,20003,20004 -j DROP

新建的链表默认是不生效的,需要把新建的链挂到系统默认的链表中去

如把上面的禁止访问的端口放在input链,那么,其它机器就不能访问本机的20001等端口了。

iptables -A INPUT -j test

再次查看防火墙规则

# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination      
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0        
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0        
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
test       all  --  0.0.0.0/0            0.0.0.0/0 
                                                    
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination      
REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
                                                
Chain test (1 references)
target     prot opt source               destination      
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:30004
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:30005
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           multiport dports 20001,20003,20004

对于状态机制,一般把 established related两个状态放行

iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

参考:http://bbs.51cto.com/thread-1104209-1.html


参考:http://my.oschina.net/itblog/blog/204401

http://www.jbxue.com/LINUXjishu/9815.html

http://tanxw.blog.51cto.com/4309543/1389114

http://essun.blog.51cto.com/721033/1386787

http://nmshuishui.blog.51cto.com/1850554/1384802

http://blog.chinaunix.net/uid-26212859-id-3479994.html

http://www.svipc.com/thread-365-1-1.html

http://lyp0909.blog.51cto.com/508999/509408



关于tcp_wrappers学习请参考

http://linuxme.blog.51cto.com/1850814/369947

http://www.51ou.com/browse/xitongguanli/38321.html

http://tobe1st.blog.163.com/blog/static/78780695200975102720912/

1.1 tcp wrappers概述

tcp wrappers为由xinetd这支superdaemon管理的服务提供了安全性。由xinetd super daemon管理的服务以及支持libwrap模块的服务都可以使用它tcp wrappers进行安全控制。

可以通过使用tcp wrappers结合防火墙(iptables)提供更加安全的系统保护。

wKiom1aUldHjYAUZAACXRayP4-Q679.jpg

1.2 tcp wrappers的配置文件

tcp wrappers的配置文件有两个,一个是/etc/hosts.allow,一个是/etc/hosts.deny

/etc/hosts.allow:允许指定的客户端对指定的服务访问。

/etc/hosts.deny:拒绝指定的客户端对指定的服务访问。

1.3 确认服务是否支持tcp wrappers

Linux系统下面并不是所有的服务都支持tcp wrappers,由xinetd管理的服务都支持tcp wrappers,其他的服务可以通过ldd指令来查看。ldd指令用于查看二进制指令所需要的动态链接库,如果服务有支持libwrap.so这个动态链接库,则表示该服务支持TCP Wrappers

[root@test01 ~]# ldd $(which sshd) | grep libwrap
	libwrap.so.0 => /lib64/libwrap.so.0 (0x00007fa039d12000)
[root@test01 ~]#

上述表明sshd这个服务是支持tcp wrappers的。

如果没有libwrap,则表示该服务不支持tcp wrappers

1.4 tcp wrappers的规则定义

/etc/hosts.allow:允许指定的客户端对指定的服务访问。

/etc/hosts.deny:拒绝指定的客户端对指定的服务访问。

修改完成之后,不需要重新启动服务经会立即生效。

匹配规则如下:

1./etc/hosts.allow/etc/hosts.deny无匹配记录时,访问可以通过。

2./etc/hosts.allow有匹配记录时访问可以通过。

3./etc/hosts.allow/etc/hosts.deny都匹配时访问可以通过。

总结起来就是:

1.默认策略是允许,即没有在hosts.allowhosts.deny中出现的,允许通过。

2.先查看hosts.allow,在查看hosts.deny

wKiom1aUljzgWAvdAABcs9MHg-g074.jpg

访问控制规则:

每一个控制文件都可以包含多行,按照定义的顺序处理每一行,找到匹配后就跳出该规则。以#开始的表示注释,如果一行写不完可以使用反斜线(\),进行脱跳,表示上一行的延续。


hosts.allowhosts.deny定义格式如下:

daemon_list : client_list [ : shell_command ]deny|allow

daemon_list:指定由TCP wrappers需要控制的服务名称。如果该服务是由xinetd管理的服务,要写启动脚本的名称,如/etc/xinetd.d/telnet,否则的话则直接写服务名称,如sshd

下述为tftp服务的配置文件:/etc/xinetd.d/tftp

如果要想使用tcp wrappers控制tftp的话,需要在hosts.allowhosts.deny文件中,写上tftp的启动脚本:/use/sbin/in.tftpd

service tftp
{
       socket_type             = dgram
       protocol                = udp
       wait                    = yes
       user                    = root
server                  = /usr/sbin/in.tftpd
       server_args             = -s /tftpboot
       disable                 = no
       per_source              = 11
       cps                     = 100 2
       flags                   = IPv4
}

client_list指定tcpwrappers需要控制哪些客户端对哪些服务的访问。

可以用如下方法表示:

单一主机:192.168.0.1,表示的是192.168.0.1这台主机。

指定网段:192.168.0.或者是192.168.0.0/255.255.255.0表示的是192.168.0.0/24整个网段。

指定DNS后缀:.frame.com,所有DNS后缀为.frame.com的主机。

指定FQDNserver.frame.com ,表示的是FQDNserver.frame.com的主机。

所有客户端:ALL

操作符:

EXCEPT:除……之外。如list1 EXCEPTlist2,匹配list1里面的机器,除了list2.

EXCEPT可以用在daemon_listclient_list中。

shell_command

shell command最好使用绝对路径。在执行shellcommand时,系统会启动一个/bin/sh的子进程去执行这些指令,所有的输入、输出、错误输出都被送到/dev/null里面。如果想在后台执行的话,可以加上&

shell command中的变量:

%a (%A): The client (server)host address.
      %c: Client information: user@host,user@address, a host name, or just an address,  
          depending  on  how  much information is available.
      %d:The daemon process name
      %h (%H):The client (server) host name oraddress, if the host name is unavailable.
      %n (%N):The client (server) host name(or "unknown" or "paranoid").
      %p:The daemon process id.
      %s:Server  information: daemon@host, daemon@address, or just a daemon name, 
         depending on howmuch information is available.
      %u:The client user name (or"unknown").
      %%:Expands to a single ‘%′ character.

执行外部指令:spawn

spawn的格式为:

spawn (shell command)

可以使用spawn执行一些外部指令,可以实现日志的记录以及其他的一些信息,如:

[root@server1 tmp]#cat /etc/hosts.allow
#
# hosts.allow   This file describes the names of the hostswhich are
#               allowed to use the local INETservices, as decided
#               by the '/usr/sbin/tcpd' server.
#

sshd:172.17.100.1:spawn(/bin/echo %a from %h attempted to access %d >> /tmp/sshd.log ) :allow
[root@server1 tmp]#cat sshd.log
172.17.100.1from 172.17.100.1 attempted to access sshd


Linux之Iptables防火墙管理与配置

http://fdgui.blog.51cto.com/3484207/1437643