Linux下Netfilter/IPtables防火墙案例分析
时间:2015-05-04 01:42 来源:www.it.net.cn 作者:IT
2015-01-13 17:15 246人阅读 评论(0) 收藏 举报
一、概述
在计算机领域内,防火墙是一种能够依照设定的规则,对网络传输进行控制,以确保信息安全的软硬件组成的防护系统。
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张表中定义好规则,作用在不同的链上。如下图:
4E957D02E43941C694C1D40D2050BC12.jpg (31.46 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
二、iptables简介
安装很简单,只需要安装用户空间工具iptables就行。在CentOS6光盘上有,可以rpm、yum安装。包安装请参看以前的博文,这里不再赘述。
# yum -y install iptables
语法规则(简要说明)
iptables [-t TABLE] COMMAND CHAIN CRETIRIA -j TARGET
-t 指明表,表有filter、nat、mangle和raw,filter是缺省值。
下面我们就从默认规则中初步了解一下iptables:
29EB781E37FE4B688D814C8C2FC0B6FF.jpg (36.15 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
[语法]
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端口。
A7E42B1EB227488AB4CFF53D77BB7EBC.jpg (22.67 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
开始测试
4D9E2BD077954100A9F1F7E8C8F895BA.jpg (24.37 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
8C4C4FB249434B9793D1FEB17A9C0E96.jpg (64.29 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
综上可知,默认规则很好的组织了由外向内的攻击,还阻止了通过本机转发的数据,但是却对流出的报文未做任何限制。
其实这样是有风险的,有时候问题来自内部,正如特洛伊木马一样,把木马带进了城,到时候,木马(其实是木马中的人)会主动从内打开城门,让部队攻入城内。
三、案例说明
案例一 主机防火墙
2399B79445444B4C9EEA90501BA36B23.jpg (37.52 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
一台网络中的服务器,应该主动采用一些策略来避免来自内部和外部网络的攻击和试探。
为了便于管理服务器,需要使用开放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
测试一下
D2AA624CD9F74158B34CC7BB0EC42418.jpg (18.59 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
案例三 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工具测试
7E2C3FB1C8B94866ACA39C5ABB3930DE.jpg (23.71 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
主动模式测试
我们查看一下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。
8A925F908B734F1AAD1E8711BC46E900.jpg (55.74 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
测试成功。注意图片中的红框部分,使用的是PORT模式
76FAED6614D944EF8B5AD19D5E9ED885.jpg (24.51 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
案例四 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
规划
E0A9CC512457479887435DFD49A55433.jpg (45.67 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
环境准备
按照规划配置虚拟机,其中防火墙是双网卡。规划中内网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。
BD18C9C716DE4400956F37ABF5ACDB1F.jpg (50.29 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
上面的测试可以看到,从192.168.23.150测试ping地址172.16.0.100无法ping通。
再看172.16.0.100上的抓包
64B343026ED0435BA89E75FD61A58F69.jpg (70.63 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
由图可知,icmp请求包已经到达,说明防火墙服务器172.16.23.200已经开启了转发功能。但是目标主机并没有回应ping请求。
因为172.16.0.100的网关指向了172.16.0.1。而这个网关不知道192.168.23.0网络在哪里。
解决的办法有三个
(1)修改网关指向172.16.23.200
4DF09496320043BD9F363B74BFEC1181.jpg (39.64 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
修改网关后,从内网192.168.23.150再次ping地址172.16.0.100。成功。
6DC7D04CE7B04964B6B95BB61162FCAB.jpg (70.35 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
(2)增加路由
172.16.0.100的网关依然是172.16.0.1,在本机上增加路由配置。如果主机是Linux,命令有所不同,但原理相同。
0D32D2B9554842F8BF44C294B429F648.jpg (60.2 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
4159A57870F64806A9A17DFD09BCDB32.jpg (68.91 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
(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默认网页
57F909B0D13D4691A61A364FD75F8922.jpg (33.54 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
查询DNS信息
# dig –t A www.test.com @172.16.114.114
在172.16.0.100上抓包看一下,注意此时的IP地址。TCP三次握手,四次断开清清楚楚。
BCAEFE6D81BD4A029EE4A09300554494.jpg (87.25 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
在172.16.114.114使用tcpdump抓取udp 53号端口的数据包保存在文件中使用wireshark打开
BD41427BCF9449C0A20C4B745B08DB53.jpg (74.67 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
从抓包的情况来看,请求的全部都是内网地址。下面启用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
测试
看看网页抓到的包,地址已经被替换了。
1A52262124414A42B21C9671A4D4D071.jpg (81.22 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
再看看DNS请求的包,地址也变了。
237E9F0CF38349789595F800B7B9C734.jpg (56.4 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
启动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。如下图
009EFC9A69A441EF91CB336B6728DF47.jpg (61.99 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
此时目标地址已经是在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
再次测试成功
530CFE5CCD154569B1D4A3654F1DFCBC.jpg (47.19 KB, 下载次数: 0)
下载附件 保存到相册
2014-8-28 23:37 上传
(责任编辑:IT)
2015-01-13 17:15 246人阅读 评论(0) 收藏 举报 一、概述 在计算机领域内,防火墙是一种能够依照设定的规则,对网络传输进行控制,以确保信息安全的软硬件组成的防护系统。 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张表中定义好规则,作用在不同的链上。如下图: 4E957D02E43941C694C1D40D2050BC12.jpg (31.46 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 二、iptables简介 安装很简单,只需要安装用户空间工具iptables就行。在CentOS6光盘上有,可以rpm、yum安装。包安装请参看以前的博文,这里不再赘述。 # yum -y install iptables 语法规则(简要说明) iptables [-t TABLE] COMMAND CHAIN CRETIRIA -j TARGET -t 指明表,表有filter、nat、mangle和raw,filter是缺省值。 下面我们就从默认规则中初步了解一下iptables: 29EB781E37FE4B688D814C8C2FC0B6FF.jpg (36.15 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 [语法] 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端口。 A7E42B1EB227488AB4CFF53D77BB7EBC.jpg (22.67 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 开始测试 4D9E2BD077954100A9F1F7E8C8F895BA.jpg (24.37 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 8C4C4FB249434B9793D1FEB17A9C0E96.jpg (64.29 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 综上可知,默认规则很好的组织了由外向内的攻击,还阻止了通过本机转发的数据,但是却对流出的报文未做任何限制。 其实这样是有风险的,有时候问题来自内部,正如特洛伊木马一样,把木马带进了城,到时候,木马(其实是木马中的人)会主动从内打开城门,让部队攻入城内。 三、案例说明 案例一 主机防火墙 2399B79445444B4C9EEA90501BA36B23.jpg (37.52 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 一台网络中的服务器,应该主动采用一些策略来避免来自内部和外部网络的攻击和试探。 为了便于管理服务器,需要使用开放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 测试一下 D2AA624CD9F74158B34CC7BB0EC42418.jpg (18.59 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 案例三 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工具测试 7E2C3FB1C8B94866ACA39C5ABB3930DE.jpg (23.71 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 主动模式测试 我们查看一下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。 8A925F908B734F1AAD1E8711BC46E900.jpg (55.74 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 测试成功。注意图片中的红框部分,使用的是PORT模式 76FAED6614D944EF8B5AD19D5E9ED885.jpg (24.51 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 案例四 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 规划 E0A9CC512457479887435DFD49A55433.jpg (45.67 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 环境准备 按照规划配置虚拟机,其中防火墙是双网卡。规划中内网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。 BD18C9C716DE4400956F37ABF5ACDB1F.jpg (50.29 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 上面的测试可以看到,从192.168.23.150测试ping地址172.16.0.100无法ping通。 再看172.16.0.100上的抓包 64B343026ED0435BA89E75FD61A58F69.jpg (70.63 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 由图可知,icmp请求包已经到达,说明防火墙服务器172.16.23.200已经开启了转发功能。但是目标主机并没有回应ping请求。 因为172.16.0.100的网关指向了172.16.0.1。而这个网关不知道192.168.23.0网络在哪里。 解决的办法有三个 (1)修改网关指向172.16.23.200 4DF09496320043BD9F363B74BFEC1181.jpg (39.64 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 修改网关后,从内网192.168.23.150再次ping地址172.16.0.100。成功。 6DC7D04CE7B04964B6B95BB61162FCAB.jpg (70.35 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 (2)增加路由 172.16.0.100的网关依然是172.16.0.1,在本机上增加路由配置。如果主机是Linux,命令有所不同,但原理相同。 0D32D2B9554842F8BF44C294B429F648.jpg (60.2 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 4159A57870F64806A9A17DFD09BCDB32.jpg (68.91 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 (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默认网页 57F909B0D13D4691A61A364FD75F8922.jpg (33.54 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 查询DNS信息 # dig –t A www.test.com @172.16.114.114 在172.16.0.100上抓包看一下,注意此时的IP地址。TCP三次握手,四次断开清清楚楚。 BCAEFE6D81BD4A029EE4A09300554494.jpg (87.25 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 在172.16.114.114使用tcpdump抓取udp 53号端口的数据包保存在文件中使用wireshark打开 BD41427BCF9449C0A20C4B745B08DB53.jpg (74.67 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 从抓包的情况来看,请求的全部都是内网地址。下面启用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 测试 看看网页抓到的包,地址已经被替换了。 1A52262124414A42B21C9671A4D4D071.jpg (81.22 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 再看看DNS请求的包,地址也变了。 237E9F0CF38349789595F800B7B9C734.jpg (56.4 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 启动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。如下图 009EFC9A69A441EF91CB336B6728DF47.jpg (61.99 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 此时目标地址已经是在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 再次测试成功 530CFE5CCD154569B1D4A3654F1DFCBC.jpg (47.19 KB, 下载次数: 0) 下载附件 保存到相册 2014-8-28 23:37 上传 (责任编辑:IT) |