一、概述

在计算机领域内,防火墙是一种能够依照设定的规则,对网络传输进行控制,以确保信息安全的软硬件组成的防护系统。

Linux的Netfilter/IPTables架构

Netfilter/IPTables架构是Linux系统提供的自带的防火墙,它包含在Linux 2.4以后的内核中,功能十分强大,可以实现包过滤、NAT(网络地址转换)、数据包的分割等功能。

Netfilter工作在内核,而IPTables则是提供在用户空间的工具,可以让用户自定义规则集的表结构。

 

Netfilter/IPTables的框架

Netfilter工作在内核的IP协议栈上,它为多种协议提供了一套类似的钩子(HOOK),这些钩子函数设置在了报文传送的必经之路上。

报文按照来源和去向可以分为三类:流入的、流出的、流经的,其中流入、流经要经过路由才能区分,流出和流经也要经过路由转发。那么Netfilter就在这些必经之路上提供了5个钩子位置,分别是:

PREROUTING在路由决策之前
INPUT包将要被投递到本地socket之前
FORWARD经本机转发的包
OUTPUT本机发出的包
POSTROUTING路由决策后交给硬件之前

 

IPTables是用户空间的工具,它提供了4张表,分别是:

raw第一个处理的表,在连接追踪前作用,可以避免非常频繁的服务使用连接追踪功能
mangle它能够修改报文内容
nat网络地址转换,处理DNAT、SNAT转换
filter通用匹配的包过滤,不做任何修改

优先级顺序是:raw ---> mangle --->  nat ---> filter。也就是说在某一个链上有多张表,就是按照这个顺序依次处理。

4张表中定义好规则,作用在不同的链上。如下图:

规划1

 

二、iptables简介

安装很简单,只需要安装用户空间工具iptables就行。在CentOS6光盘上有,可以rpm、yum安装。包安装请参看以前的博文,这里不再赘述。

# yum -y install iptables

 

语法规则(简要说明)

iptables [-t TABLE] COMMAND CHAIN CRETIRIA -j TARGET

-t 指明表,表有filter、nat、mangle和raw,filter是缺省值。

 

下面我们就从默认规则中初步了解一下iptables:

0.0

[语法]

iptables的-L选项,是列出所选链的所有规则,默认显示filter表,可以使用-t nat、-t mangle、-t raw。

常用有几个子选项

-n 数字格式,不要反解IP

-v 详细信息输出

--line-numbers 显示规则行号

-x 精确显示

 

常用目标TARGET

ACCEPT 允许

DROP    丢弃

REJECT 拒绝

LOG      记录日志

 

[规则分析]

INPUT链

1、默认规则

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)

这一句说明INPUT链上默认的策略是允许放行。

根据默认策略,设置可以分为2种:

默认拒绝,把需要的数据放行,即白名单策略

默认允许,把不需要的数据拒绝,即黑名单策略

 

2、规则列表

1      201 14896 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED    
这一句基于状态检测的规则,它在INPUT链上判断所有协议数据包,如果是与之前有关联,或者已经建立了的连接放行

2        2   168 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0   

任何icmp协议请求都允许

3        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0  

在lo接口上的所有协议请求都允许,这是设置本地回环地址的行为      
4        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22

这一条比较重要,这是允许tcp新建立连接于22号端口,即默认的ssh服务端口,要与OUTPUT配合,才能完成整个数据的请求和响应    
5       79 10272 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

最后一条,所有协议所有地址都被拒绝,并告知主机禁止错误。

通过INPUT的规则设置,可以看出,虽然默认为允许放行,但是通过规则的分析,实际上除了本地接口lo外,只允许icmp和对TCP的22号端口的访问,其他全部拒绝,并返回指定错误。

 

FORWARD链

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) 
1        0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited

可以看出,拒绝所有转发请求,并返回错误。

 

OUTPUT链

只有默认策略,也就是允许所有数据包流出。

 

根据以上分析,我们来测试一下,启动httpd监听Tcp 80端口。

0.1

开始测试

0.2 

0.3

 

综上可知,默认规则很好的组织了由外向内的***,还阻止了通过本机转发的数据,但是却对流出的报文未做任何限制。

其实这样是有风险的,有时候问题来自内部,正如特洛伊***一样,把***带进了城,到时候,***(其实是***中的人)会主动从内打开城门,让部队攻入城内。

 

 

三、案例说明

案例一 主机防火墙

规划2

一台网络中的服务器,应该主动采用一些策略来避免来自内部和外部网络的***和试探。

为了便于管理服务器,需要使用开放ssh使用的TCP 22端口,而管理这台服务器的管理员,有可能使用固定的IP或者某个固定IP范围等地址登录这个主机。而且一般来说,这台服务器不会主动发起对外连接的请求。

 

我们采用如下策略和顺序

注意,操作顺序很重要,否则将被拒绝

  • 清空所有规则

  • INPUT链上只允许来自内部网络的地址为172.16.23.150的主机,对TCP 22端口的状态为NEW和ESTABLISHED的数据包通过,也就是说,允许进入的对ssh服务的请求和连接。

  • OUTPUT链上要对TCP源端口是22的数据包放行。

  • 最后,特别注意,在INPUT、OUTPUT、FORWARD这些链上的filter默认都是拒绝。

 

[root@localhost ~]# iptables -F    
[root@localhost ~]# iptables -L     
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         
[root@localhost ~]# iptables -A INPUT -s 172.16.23.150 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
 
[root@localhost ~]# iptables -A OUTPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT    
[root@localhost ~]# iptables -L     
Chain INPUT (policy DROP)     
target     prot opt source               destination         
ACCEPT     tcp  --  172.16.23.150        anywhere            tcp dpt:ssh state NEW,ESTABLISHED
 
Chain FORWARD (policy DROP)    
target     prot opt source               destination        
 
Chain OUTPUT (policy DROP)    
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere            tcp spt:ssh state ESTABLISHED     
[root@localhost ~]# iptables -P FORWARD DROP     
[root@localhost ~]# iptables -P INPUT DROP     
[root@localhost ~]# iptables -P OUTPUT DROP     
[root@localhost ~]# iptables -L -v     
Chain INPUT (policy DROP 0 packets, 0 bytes)     
pkts bytes target     prot opt in     out     source               destination         
  221 15872 ACCEPT     tcp  --  any    any     172.16.23.150        anywhere            state NEW,ESTABLISHED
 
Chain FORWARD (policy DROP 0 packets, 0 bytes)    
pkts bytes target     prot opt in     out     source               destination        
 
Chain OUTPUT (policy DROP 0 packets, 0 bytes)    
pkts bytes target     prot opt in     out     source               destination         
  143 14308 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp spt:ssh state ESTABLISHED
 

测试成功,远程连接依然可用,查看匹配到了很多数据。测试这台主机的80端口的WEB服务。

 

[ 分析 ]

这个方案限定了外面能够访问的服务,只能访问ssh服务。其他所有服务请求都丢弃了,而且把本机访问外网正常的请求也丢弃了,只允许ssh的响应才能通过。

基本上这台机器可以说不能向外提供任何服务,需要改进规则。

既然是服务器,假设它可以提供WEB功能,请看下一个案例。

 

案例二 WEB服务器

基于上一个案例,简单的一台服务器,提供WEB服务。比如说,公司内部的论坛搭建在上面。

那么,我们要开放TCP的80端口,由于它的访问比较频繁,所以不要和原有的规则写在一起。同时,允许所有协议状态为已经建立连接的数据的流出。

注意:操作的顺序,依然是先同时修改默认策略为ACCEPT,编写好规则后,修改默认规则为DROP。

[root@localhost ~]# iptables -P INPUT ACCEPT;iptables -P OUTPUT ACCEPT    
[root@localhost ~]# iptables -R OUTPUT 1 -m state --state ESTABLISHED -j ACCEPT     
[root@localhost ~]# iptables -I INPUT -d 172.16.23.136 -p tcp --dport 80 -j ACCEPT     
[root@localhost ~]# iptables -P INPUT DROP;iptables -P OUTPUT DROP     
[root@localhost ~]# iptables -Z     
[root@localhost ~]# iptables -L -nv     
Chain INPUT (policy DROP 0 packets, 0 bytes)     
pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.23.136       tcp dpt:80     
    6   396 ACCEPT     tcp  --  *      *       172.16.23.150        0.0.0.0/0           tcp dpt:22 state NEW,ESTABLISHED
 
Chain FORWARD (policy DROP 0 packets, 0 bytes)    
pkts bytes target     prot opt in     out     source               destination        
 
Chain OUTPUT (policy DROP 0 packets, 0 bytes)    
pkts bytes target     prot opt in     out     source               destination         
    4   400 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state ESTABLISHED

 

测试一下

0.4

 

案例三 FTP服务器

还是上面这一台服务器,增加FTP功能。

FTP服务比较特殊,默认监听在TCP 21号端口。

FTP的工作模型分为:主动模式和被动模式。

主动模式下,FTP服务器使用TCP 20连接客户端。

被动模式下,FTP服务器监听在通知客户端的端口上,等待客户端连接。而这个端口是大于1024的随机端口。

 

被动模式测试

被动模式下,客户端首先要发起对TCP 21端口的连接,状态为NEW,然后就可以建立连接通讯。之后的对21号端口的长连接的状态就是ESTABLISHED。

那么以后INPUT上的被动模式建立连接传输数据都算是和连接到21端口的连接有关联的连接,状态都是RELATED。

 

加载模块

[root@localhost ~]# modprobe nf_conntrack_ftp    
[root@localhost ~]# lsmod | grep nf_conntrack     
nf_conntrack_ftp       12913  0     
nf_conntrack_ipv4       9506  2     
nf_defrag_ipv4          1483  1 nf_conntrack_ipv4     
nf_conntrack_ipv6       8748  2     
nf_defrag_ipv6         11182  1 nf_conntrack_ipv6     
nf_conntrack           79758  4 nf_conntrack_ftp,nf_conntrack_ipv4,nf_conntrack_ipv6,xt_state     
ipv6                  317340  151 ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6    

修改配置文件/etc/sysconfig/iptables-config,永久生效    

IPTABLES_MODULES="nf_conntrack_ftp"

 

修改INPUT的规则

[root@localhost ~]# iptables -I INPUT 2 -d 172.16.23.136 -p tcp --dport 21 -m state --state NEW -j ACCEPT    
[root@localhost ~]# iptables -I INPUT -d 172.16.23.136 -m state --state RELATED,ESTABLISHED -j ACCEPT     
[root@localhost ~]# iptables -L INPUT -n     
Chain INPUT (policy DROP)     
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            172.16.23.136       state RELATED,ESTABLISHED     
ACCEPT     tcp  --  0.0.0.0/0            172.16.23.136       tcp dpt:80     
ACCEPT     tcp  --  0.0.0.0/0            172.16.23.136       tcp dpt:21 state NEW     
ACCEPT     tcp  --  172.16.23.150        0.0.0.0/0           tcp dpt:22 state NEW,ESTABLISHED
 
[root@localhost ~]# service iptables save    
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

测试成功

[root@localhost ~]# ftp 172.16.23.136    
Connected to 172.16.23.136 (172.16.23.136).     
220 (vsFTPd 2.2.2)     
Name (172.16.23.136:root): ftp     
331 Please specify the password.     
Password:     
230 Login successful.     
Remote system type is UNIX.     
Using binary mode to transfer files.     
ftp> ls     
227 Entering Passive Mode (172,16,23,136,123,167).     
150 Here comes the directory listing.     
drwxr-xr-x    2 0        0            4096 Mar 01  2013 pub     
226 Directory send OK.
 
[root@localhost ~]# ss -tnlap    
State      Recv-Q Send-Q                    Local Address:Port                      Peer Address:Port     
users:(("php-fpm",1380,7),("php-fpm",1381,0),("php-fpm",1382,0),("php-fpm",1383,0),("php-fpm",1384,0),("php-fpm",1385,0),("php-fpm",1416,0))     
ESTAB      0      0                         172.16.23.136:21                       172.16.23.134:56790  users:(("vsftpd",2783,0),("vsftpd",2783,1),("vsftpd",2783,2),("vsftpd",2785,0),("vsftpd",2785,1),("vsftpd",2785,2))     
TIME-WAIT  0      0                         172.16.23.136:31655                    172.16.23.134:50429

计算一下:123*256+167=31655,正好是服务器的端口号。

 

使用windows下ftp工具测试

0.5

主动模式测试

我们查看一下OUTPUT的规则:

[root@localhost ~]# iptables -L OUTPUT  -n    
Chain OUTPUT (policy DROP)     
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state ESTABLISHED

主动连接是要服务器监听在20端口,然后主动去连接客户端。但是这里不能放行状态为NEW的数据包。

尝试开放TCP 20端口的主动向外连接。

[root@localhost ~]# iptables -A OUTPUT -p tcp --sport 20 -m state --state NEW -j ACCEPT    
[root@localhost ~]# iptables -L OUTPUT  -n     
Chain OUTPUT (policy DROP)     
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state ESTABLISHED     
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp spt:20 state NEW

 

测试

修改ftp软件的数据连接模式,然后重新连接ftp。

0.6

测试成功。注意图片中的红框部分,使用的是PORT模式

0.7

 

案例四 DNS解析

还是服务器172.16.23.136,它需要解析www.baidu.com,先在目前的规则下试验一下。

[root@localhost ~]# cat /etc/resolv.conf    
# Generated by NetworkManager     
nameserver 172.16.0.1     
[root@localhost ~]# ping www.baidu.com     
ping: unknown host www.baidu.com

此路不通。因为OUTPUT链上就没有放行udp的协议。

[root@localhost ~]# iptables -I OUTPUT -s 172.16.23.136 -p udp --dport 53 -j ACCEPT

 

测试   

[root@localhost ~]# iptables -Z     
[root@localhost ~]# dig -t A www.baidu.com
 
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6_4.6 <<>> -t A www.baidu.com    
;; global options: +cmd     
;; Got answer:     
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20938     
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
 
;; QUESTION SECTION:    
;www.baidu.com.            IN    A
 
;; ANSWER SECTION:    
www.baidu.com.        1021    IN    CNAME    www.a.shifen.com.     
www.a.shifen.com.    30    IN    A    111.13.100.92     
www.a.shifen.com.    30    IN    A    111.13.100.91
 
;; Query time: 81 msec    
;; SERVER: 172.16.0.1#53(172.16.0.1)     
;; WHEN: Wed Aug 20 21:09:13 2014     
;; MSG SIZE  rcvd: 90
 
[root@localhost ~]# iptables -L -nv    
Chain INPUT (policy DROP 0 packets, 0 bytes)     
pkts bytes target     prot opt in     out     source               destination         
   26  1742 ACCEPT     all  --  *      *       0.0.0.0/0            172.16.23.136       state RELATED,ESTABLISHED     
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.23.136       tcp dpt:80     
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.23.136       tcp dpt:21 state NEW     
    0     0 ACCEPT     tcp  --  *      *       172.16.23.150        0.0.0.0/0           tcp dpt:22 state NEW,ESTABLISHED
 
Chain FORWARD (policy DROP 0 packets, 0 bytes)    
pkts bytes target     prot opt in     out     source               destination        
 
Chain OUTPUT (policy DROP 0 packets, 0 bytes)    
pkts bytes target     prot opt in     out     source               destination         
    1    59 ACCEPT     udp  --  *      *       172.16.23.136        0.0.0.0/0           udp dpt:53     
   16  2336 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state ESTABLISHED     
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp spt:20 state NEW
 

 

[ 分析 ]

以上的操作成功了。只开放了udp协议53端口出去,并没有放它进来啊?

通过清零操作,立即解析www.baidu.com,然后查看过滤数据的统计。

OUTPUT中匹配到了udp 53端口的数据,然后INPUT中只有第一条匹配到了。这是因为服务器主动向外发起请求,然后外网DNS服务器解析后,返回的数据状态时ESTABLISHED,所以允许通过。

 

 

案例五 NAT

规划

NAT规划V2

环境准备

按照规划配置虚拟机,其中防火墙是双网卡。规划中内网192.168.23.0/16使用虚拟网络VMNet3,外网172.16.0.0/16段处在VMNet2中。

为了便于实验,在172.16.0.100上部署windows,安装wireshark抓包工具,部署nginx(windows版)。当然可以再Linux上安装wireshark,以后博文再叙。

在192.168.23.150上安装elinks包。

在网关上,开通主机内路由,并写入配置文件

[root@localhost ~]# vim /etc/sysctl.conf    
[root@localhost ~]# grep "net.ipv4.ip_forward" /etc/sysctl.conf     
net.ipv4.ip_forward = 1     
[root@localhost ~]# sysctl -p     
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward     
1

 

实验

从客户机192.168.23.150往外网172.16.0.100去ping。

nat1.1

上面的测试可以看到,从192.168.23.150测试ping地址172.16.0.100无法ping通。

再看172.16.0.100上的抓包

nat1.2

由图可知,icmp请求包已经到达,说明防火墙服务器172.16.23.200已经开启了转发功能。但是目标主机并没有回应ping请求。

因为172.16.0.100的网关指向了172.16.0.1。而这个网关不知道192.168.23.0网络在哪里。

 

解决的办法有三个

(1)修改网关指向172.16.23.200

nat1.3

修改网关后,从内网192.168.23.150再次ping地址172.16.0.100。成功。

nat1.4

(2)增加路由

172.16.0.100的网关依然是172.16.0.1,在本机上增加路由配置。如果主机是Linux,命令有所不同,但原理相同。

nat1.5

nat1.6

(3)路由器增加路由

上面两种方法,都需要修改本地路由(网关就是默认路由)。这样不好,因为路由需要硬性的指定。而且第一种方法指向172.16.23.200后,其访问外部所有的数据包都要走这个网关,而这个网关不会替他路由的,这会影响用户访问其他网络包括互联网。

比较好的办法,将去192.168.23.0网络的路由配置在这个网络的路由器172.16.0.1上。配置方式同(2),不再赘述。

但是,这也只适用于本示例图的规划,实际网络中路由器不会指向某个私网的。也就是172.16.0.0这个网络不会知道192.168.23.0这个私有网络的。

那么如何解决这个问题呢?

这就是NAT

 

NAT

NAT叫网络地址转换,它能够替换数据报文中的源地址、目标地址、源端口、目标端口,从而达到隐藏内外网络的真实情况。意外的是,它缓解了IPV4地址紧张的局面。

Linux下,可以使用iptables实现NAT。

上例中,这种增加为私网增加路由的方式不可取,那么可以使用在私网边缘的防火墙服务器上配置iptables,下面开始启动并配置它。

分析

先做防火墙服务器做基本的配置。为了便于测试,规则上对连接ssh的端口、icmp协议并没有做严格限制

INPUT链允许对22号端口的ssh请求,允许已经建立的连接,允许icmp协议
OUTPUT链允许回应的连接,允许对私网的ssh连接
FORWARD链允许内网向外icmp协议,允许内网向外网的TCP 80访问,允许内网的DNS访问请求
# service iptables start    
iptables: Applying firewall rules:      [  OK  ]     
# iptables -F     
# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT     
# iptables -A INPUT -p icmp  -j ACCEPT     
# iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT     
# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT     
# iptables -A OUTPUT -d 192.168.23.0/24 -p tcp --dport 22 -m state --state NEW -j ACCEPT
 
# iptables -A FORWARD -p icmp -j ACCEPT
 
# iptables -I FORWARD -s 192.168.23.0/24 -p tcp --dport 80 -m state --state NEW,ESTABLISHED  -j ACCEPT    
# iptables -I FORWARD -d 192.168.23.0/24 -p tcp --sport 80 -m state --state ESTABLISHED  -j ACCEPT
 
# iptables -I FORWARD -s 192.168.23.0/24 -p udp --dport 53 -m state --state NEW,ESTABLISHED  -j ACCEPT    
# iptables -I FORWARD -d 192.168.23.0/24 -p udp --sport 53 -m state --state ESTABLISHED  -j ACCEPT
 
# iptables -P INPUT DROP;iptables -P OUTPUT DROP;iptables -P FORWARD DROP     
 
# iptables -L -n    
Chain INPUT (policy DROP)     
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     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW
 
Chain FORWARD (policy DROP)    
target     prot opt source               destination         
ACCEPT     udp  --  0.0.0.0/0            192.168.23.0/24     udp spt:53 state ESTABLISHED     
ACCEPT     udp  --  192.168.23.0/24      0.0.0.0/0           udp dpt:53 state NEW,ESTABLISHED     
ACCEPT     tcp  --  0.0.0.0/0            192.168.23.0/24     tcp spt:80 state ESTABLISHED     
ACCEPT     tcp  --  192.168.23.0/24      0.0.0.0/0           tcp dpt:80 state NEW,ESTABLISHED     
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0          
 
Chain OUTPUT (policy DROP)    
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state ESTABLISHED     
ACCEPT     tcp  --  0.0.0.0/0            192.168.23.0/24     tcp dpt:22 state NEW
 
# service iptables save    
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

 

测试

192.168.23.150上分别执行下面语句

# elinks –dump 172.16.0.100/index.html

返回nginx默认网页

nat1.7网页内容

查询DNS信息

# dig –t A www.test.com @172.16.114.114

 

在172.16.0.100上抓包看一下,注意此时的IP地址。TCP三次握手,四次断开清清楚楚。

nat1.7网页内容1

在172.16.114.114使用tcpdump抓取udp 53号端口的数据包保存在文件中使用wireshark打开

nat1.8DNS内容

从抓包的情况来看,请求的全部都是内网地址。下面启用NAT来隐藏内网地址。

 

启用SNAT

对外的访问

# iptables -t nat -A POSTROUTING -s 192.168.23.0/24 -j SNAT --to-source 172.16.23.200
# 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.23.0/24      0.0.0.0/0           to:172.16.23.200
 
Chain OUTPUT (policy ACCEPT)    
target     prot opt source               destination

 

测试

看看网页抓到的包,地址已经被替换了。

nat1.9nat1

再看看DNS请求的包,地址也变了。

nat1.10nat2

 

启动DNAT

对内的访问

内网DMZ中有一台WEB服务器,而防火墙不具备WEB的功能,因此它要把对80的请求转发至内网的WEB服务器。

对于外网主机来说,它不知道内网有这台WEB服务器存在,它只知道172.16.23.200这台主机提供WEB服务。

# iptables -t nat -A PREROUTING -d 172.16.23.200 -p tcp --dport 80 -j DNAT --to-destination 192.168.23.80

只有这一条,是不行的。因为前面在做FORWARD链的时候,只允许从内到外主动发起的WEB和DNS访问。所以一定会在DROP链上被DROP。如下图

nat1.11

此时目标地址已经是在PREROUTING链上被替换成内网地址192.168.23.80了

# iptables -I FORWARD -d 192.168.23.80 -p tcp --dport 80 -j ACCEPT     
# iptables -I FORWARD -s 192.168.23.80 -p tcp --sport 80 -j ACCEPT

 

再次测试成功

nat1.12

至此,使用NAT实现的内网可以访问外网WEB服务和DNS服务,外网可以访问内网的WEB站点的防火墙配置基本完成。这其中还需要根据访问量调整策略以优化性能。

 

 

七层过滤的实验,放在下一篇博文《编译2.6.35内核安装L7-filter2.23实现七层过滤及QQ协议分析》中说明。

 

参考资料

Netfilter架构

http://www.netfilter.org/documentation/HOWTO//netfilter-hacking-HOWTO-3.html