Chinaunix首页 | 论坛 | 博客
  • 博客访问: 58365
  • 博文数量: 16
  • 博客积分: 930
  • 博客等级: 准尉
  • 技术积分: 215
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-16 16:57
文章分类

全部博文(16)

文章存档

2007年(13)

2006年(3)

我的朋友
最近访客

分类: 网络与安全

2007-06-24 15:17:15

实际工作中我们会有这样的需求:让多台计算机/局域网共享一条线路访问Internet,要实现这项功能通常有两种方法:
 
l         使用NAT(Network Address Translation)
l         架设代理服务器(Proxy Server)
 
一个典型的应用环境如下图所示:
图中我们把网络划分为两个区域:Private区和Internet区。对外提供服务的Internet服务器也放在Private区,和局域网其它主机使用同一网段地址(当然,也可以不单独设Internet服务器而在接入服务器上安装Internet服务)。Linux接入服务器就是我们下面工作的重点,它负责带动局域网内的主机访问Internet,并保护局域网内的主机和服务器不受来自Internet的攻击。
 
为方便后面的脚本编写,首先来明确几个必要的参数。Linux接入服务器上面向Internet的网卡eth0配置如下,这些数据是从ISP那里得到的:
IP地址 61.156.35.114(只有一个公网IP地址,这么少?足够了)
子网掩码 255.255.255.192
网关地址 61.156.35.126
DNS服务器 202.102.152.3 202.102.134.68
局域网内的IP地址是192.168.100.0/255.255.255.0,我们在局域网内部安装了Internet服务器,地址为192.168.100.1,通过设置Linux接入服务器上的安全规则使它可以对外提供www、smtp、pop3等服务。Linux接入服务器上面向Private的网卡是eth1,其IP地址为:IP地址 192.168.100.254。
 
在接入Internet时,直接连接到Internet上的计算机是安全问题的焦点。无论是一台计算机还是由计算机连接起来的局域网(LAN),其焦点都是与Internet直接相连的机器(或设备),这台机器按照其功能人们通常称之为Internet网关、防火墙或代理服务器,我习惯于称它为Internet接入服务器。
 
作为接入服务器:我们希望我们的局域网可以共享我们的Internet连接,并且根据实际情况的需要,控制局域网内主机或用户能否通过这个网关自由或有限的访问Internet。如果局域网访问Internet的流量较大,使用频繁,我们还希望这台主机能够实现各种缓存功能(DNS缓存、WEB缓存),以减少流量和加快访问速度。
 
作为防火墙:我们在局域网内运行着本地私有服务,诸如共享打印机或共享文件系统,我们希望这些服务仅在局域网内有效,或者某些服务可以公开到Internet上,这可以通过设置相应的安全策略来实现。
 
图中的Linux接入服务器所实现的就是我们常说的代理服务器/防火墙。局域网内的终端通过Linux服务器来访问Internet,Linux 服务器是局域网和Internet连接之间的一个网关(Gateway),这时所有对Internet的访问都会经过Linux服务器。
 
从共享上网的功能来看,NAT的优点是局域网用户通过NAT方式上网时客户端不需要作任何的特殊设置,就和直接使用公网IP地址上网没什么区别;而Proxy则更方便对用户进行权限控制,并且还可以实现访问内容的本地缓存,以此加快访问速度以及内容过滤等等。
 
NAT和Proxy在Linux上的实现是Linux的典型应用之一,并且还可以结合NAT和Proxy配置透明代理(Transparent Proxy),实现两者的完美结合。本文就来介绍一下Linux NAT和封包过滤(Packet Filtering)防火墙。
 
 
§§ 安装iptables
 
开始之前有必要了解一下Linux内核对NAT、防火墙功能支持的历史,Linux内核在不同的版本使用不同的系统来实现这些功能:
Linux 2.0内核使用ipfwadm实现,实际应用中2.0版的内核已经不太常见了;
Linux 2.2内核使用ipchains实现,我的主页上摘录了一篇相当棒的关于ipchains的教程,正在使用Linux 2.2版内核的朋友可以阅读参考:

Red Hat Linux 7.3使用的是2.4版内核,Linux 2.4内核实现这部分功能的机制是netfilter和iptables,这个系统可以完成封包过滤(packet filtering)、网络地址转换NAT(network address translation)以及其它对数据包(packet)的操作。
 
netfilter是Linux 2.4.x内核内嵌的功能,由它实现对流经它的数据包的处理,iptables则被定义成一个规则表格,用来描述如何对封包进行处理。netfilter、iptables、连接跟踪、以及NAT功能共同组成了Linux 2.4.x内核的网络安全体系。除了通过NAT让局域网共享线路上网之外,这些功能还可以让你在Linux上创建一个功能完善的防火墙系统。
 
很多文章在讲iptables时都会提到要重新编译内核以提供对netfilter和iptables的支持,这让大多数的新手感到无从下手。实事上,目前广泛应用的各种Linux发行版的内核已经提供了默认支持,除非特别需要,没有必要进行内核的重编译。
 
首先安装iptables软件包。查询一下系统上是否安装了iptables软件包:
 
[root@rh73 ~]# rpm -qa|grep iptables
 
如果没有,那么找到Red Hat Linux 7.3的安装光盘,开始安装iptables:
 
[root@rh73 /mnt/cdrom/Red Hat/RPMS]# rpm -ivh iptables-1.2.5-3.i386.rpm
Preparing...                ########################################### [100%]
   1:iptables               ########################################### [100%]
 
还要注意的一点是,Red Hat Linux高版本(7.1版之后)开始正式支持iptables,但仍会同时提供基于Linux 2.2.x内核的ipchains。这两个系统是不能同时存在的,因此,有必要确认并停止ipchains的服务:
 
[root@rh73 ~]# /etc/rc.d/init.d/ipchains stop
[root@rh73 ~]# chkconfig --level 0123456 ipchains off
 
如果更彻底一点,可以把已经安装的ipchains卸载掉:
 
[root@rh73 ~]# rpm -e ipchains
 
 
§§ 最简单的NAT脚本
 
为了更直观的认识在Linux上实现NAT,我们先来编写一个脚本fw.sh,其内容如下:
 
#!/bin/sh
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
 
只有三行,写完后存盘。然后修改文件属性,加上可执行权限:
 
[root@rh73 ~]# chmod +x fw.sh
 
运行这个脚本
 
[root@rh73 ~]# ./fw.sh
 
到客户端试一下。如果你不是使用前面介绍的DHCP给客户端机器自动配置网卡参数,则需要手工的配置客户端网卡的IP地址、子网掩码、默认网关(根据前面安装时的配置,这里应该是Linux服务器上eth1的地址192.168.100.254),以及ISP提供给你的DNS服务器地址。现在在浏览器里输入一个网址 ... ... 如果没有什么意外,现在已经可以上网了!
 
回过头来看看这个脚本:
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
这一行是通知Linux内核启动ip转发,只有启动了ip转发功能才能使用NAT。
 
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
 
这一行的意思是:把来自192.168.100.0子网并通过eth0出去的访问请求做NAT,把数据包的源地址修改为61.156.35.114。192.168.100.0/24也可以写成192.168.100.0/255.255.255.0,24代表了子网掩码掩到第24位,即255.255.255.0。
 
如果你的ISP没有分配给你固定的公网地址,那么这一行可以写成:
 
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j MASQUERADE
 
modem或isdn等拨号方式上网,假如是通过ppp0拨号上网,可以这样写:
 
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o ppp0 -j MASQUERADE
 
这是NAT是一种特例,我们称其为IP伪装(masquerading)。
 
这里是针对一个子网(192.168.100.0/24)做NAT,也可以具体到某台主机:
 
iptables -A POSTROUTING -t nat -s 192.168.100.9 -o eth0 -j MASQUERADE
 
 
§§ NAT——Network Address Translation
 
让我们仔细来了解一下Linux 2.4的NAT。前面我们编写的脚本中使用NAT功能可以带动局域网访问Internet,而Linux的NAT可以做的事情远不止这些。
 
在NAT table中,数据包通常被送到几个不同的目的地DNAT、SNAT和MASQUERADE,通常我们可以根据这个把NAT分为两种不同的类型:Destination NAT(DNAT)和Source NAT(SNAT)。
 
Destination NAT将改变数据包要到达的目的地。使用DNAT我们可以把来自Internet上发送到我们的真实IP地址上的请求转发到内部的某台服务器上,比如我们把内部的两台服务器分别配置成公司的WEB服务器和MAIL服务器,通过设置DNAT规则,可以把外部对我们服务器公网地址的WWW请求,送到局域网内部的WEB服务器上,也可以把MAIL服务的请求,送到内部的MAIL服务器上,这种NAT以前也被称为端口转发。
 
重定向(Redirection)是Destination NAT的一个特例。某些场合我们人为的把经过Linux的数据包送往本机的另外一个程序来处理,比如我们知道使用代理服务器程序的缓存功能可以加快访问Internet的速度,这在使用速度较低的Internet连接时非常有意义。这时就可以把经过Linux服务器访问Internet的请求送给某个代理服务程序,由该代理服务器完成访问请求,我们经常提到的透明代理就是这种方式,之所以称为透明,是因为在这种工作方式下你感觉不到代理的存在。squid可以配置完成这项工作。
 
Source NAT改变数据包的来源地址。使用SNAT最典型的例子就是前面我们那个脚本实现的功能,这时,来自内部局域网通过Linux接入服务器的packet的源地址都被修改为服务器外网卡的公网地址。这样也可以起到隐藏内部地址的作用,无论你从内部的哪台机器上访问Internet,从Internet上看到的,都是你的外网卡的IP地址。
 
伪装(masquerading)是SNAT的一种特殊形式,在使用上和SNAT完全一样。两者的区别在于:在Internet接入时,如果服务器端使用的是DHCP、拨号等没有固定IP地址的接入方式,masquerading可以自动的判断使用哪个IP地址,而SNAT则更多的用于有固定IP地址的场合。
 
 
§§ 控制NAT规则表
 
前面已经看到了,我们使用iptables来创建NAT规则,使用”-t nat”参数来修改NAT table,告诉Linux内核哪些连接请求将被改变和如何改变。
 
NAT规则表包含两个称为“chains”的列表:PREROUTING(用于Destination NAT,当包进入时检查);POSTROUTING(用于Source NAT,包离开时检查,我们前面已经用过了)。通过NAT主机的数据包按顺序与规则表内的规则匹配。如下图所示:
            _____                                     _____
           /     \                                   /     \
    -->--PREROUTING -->[Routing ]----------------->POSTROUTING----->
           \D-NAT/     [Decision]                    \S-NAT/
                           |                            ^
                           |                            |
                           |                            |
                           |                            |
                           |                            |
                           |                            |
                           |                            |
                           --------> Local Process ------
 
这个图表描述了经过Linux服务器的数据包是被如何处理的,数据包通过Linux服务器时进行路由操作,并且被检查是否与DNAT或SNAT规则匹配,与规则匹配的数据包将被作相应处理。
 
下面举例说明如何使用iptables来定义NAT规则
 
Source NAT
 
Source NAT在数据包送出之前改变数据包的源地址,其规则在POSTROUTING chain中定义。
 
几个参数:
-j SNAT 定义SNAT
--to-source 指定转换后的源地址[:port],可以简写成--to
[:port],端口,是一个可选项,仅在指明TCP或UDP协议时使用
-o 出口接口(outgoing interface)
 
举例:
 
把数据包源地址转换为 1.2.3.4.
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4
还有前面我们用到的
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
 
把数据包源地址转换为1.2.3.4, 1.2.3.5 或 1.2.3.6
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6
 
把数据包源地址转换为1.2.3.4, 使用端口范围是1-1023
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to 1.2.3.4:1-1023
 
伪装(Masquerading)
 
伪装是Source NAT的一种特例,常用在诸如拨号上网等使用动态IP地址的情况下:
 
伪装所有通过ppp0送出的数据包
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
 
有固定IP地址的时候也可以使用IP伪装,比如前面我们用到的
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
也可以写成
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 –o eth0 -j MASQUERADE
 
Destination NAT
 
Destination NAT规则在PREROUTING chain中定义,它改变数据包中目的地址的值。
 
几个参数:
-j DNAT 定义DNAT
--to-destination[:port] 指定转换后的目标地址[:port],可以简写成--to
[:port],端口,是一个可选项,仅在指明TCP或UDP协议时使用
-i 入口接口 (incoming interface)
 
举例:
 
转换数据包目标地址为 5.6.7.8
iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8
 
转换数据包目标地址为 5.6.7.8, 5.6.7.9 or 5.6.7.10.
iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8-5.6.7.10
 
改变WWW访问请求的目标地址到5.6.7.8的8080端口
iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 \
        -j DNAT --to 5.6.7.8:8080
 
重定向(Redirection)
 
重定向是Destination NAT的一个特例。比如我们经常提到的squid透明代理是把客户端对80端口的请求(WWW请求)重定向送到squid代理:
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 \
        -j REDIRECT --to-port 3128
 
 
§§ 使用NAT时对特殊协议的处理
 
除了上网浏览页面,我们还可能需要用到其它的Internet服务,比如ftp,现在我们打开一个DOS窗口,登录到某个ftp服务器,如下图:

注意一下这个提示信息:
 
500 Illegal PORT command.
425 Can't build data connection: Connection refused
 
我们现在无法正常列出该ftp服务器上的内容,更无法传送文件了。
 
来看看是什么原因:FTP一般需要使用两个端口,端口21只是一个命令端口, 真正传送数据的时候, 还需要另外一个数据端口(通常是TCP/UDP 20)。问题就出现在第二个数据端口上。打开这个数据端口的时候有两种方式,一种是passive(PASV command)方式,由FTP Server端提供一个连接的IP/Port,FTP Client连接到这个IP/Port上进行数据传输。另一种是active(PORT command)方式,由FTP Client提供IP/Port,再由FTP Server回叫至Client提供的地址。具体采用哪一种方式, 是由FTP Client决定的,Client通过PASV或PORT命令通知Server采用什么方式。正是这样的握手方式,给Server端和Client端都造成了麻烦。这个问题的具体描述详见
 
对于客户端来说,有这样几种情况:
 
FTP Client采用passive方式,告诉FTP Server端提供一个数据端口。一般的FTP Client软件都支持passive方式,我使用的网络蚂蚁,网际快车(FlashGet)默认方式都是passive。
 
FTP Client不支持passive方式或者使用浏览器作为FTP Client。通过浏览器直接访问FTP使用的是active方式,问题就出现在这里。
 
另外还有一些FTP站点不支持passive方式。这时,就需要我们修改Linux NAT,添加相应的模块来支持active模式:
 
[root@rh73 ~]# modprobe ip_nat_ftp
[root@rh73 ~]# modprobe ip_conntrack_ftp
 
这时再登录访问ftp就没有问题了。类似的,其他服务如irc也有对应的模块来支持。可以把这两行内容写在fw.sh里面:
#!/bin/sh
 
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
 
 
§§ Destination NAT到同一网络内
 
如同在前面的网络拓扑里描述的,实际应用中,我们还可能会把内部的某台主机作为服务器对外提供服务,这就可能遇到DNAT到同一网络内的问题。最典型的例子是:在内部我们有一台服务器运行着web服务,现在我们想让Internet上的用户通过Linux服务器来访问到它。
 
比如,让内部的192.168.100.1这台服务器充当web服务器,当别人把访问web的请求发送到我们的公网地址,假设为61.156.35.114,通过设置DNAT规则,让内部的192.168.100.1来做出响应:
 
iptables -t nat -A PREROUTING -d 61.156.35.114 -p tcp --dport 80 -j DNAT --to 192.168.100.1
 
假设我申请了域名指向61.156.35.114,从公网上访问是没有问题的,但从192.168.100.0这个网络上的终端却无法用来访问web服务,原因是:The NAT code will now (since 2.4.0-test6), block the outgoing ICMP redirect which is produced when the NAT'ed packet heads out the same interface it came in on, but the receiving server will still try to reply directly to the client (which won't recognize the reply)。
 
解决问题的办法有两个:
 
a、设置一个内部的DNS,把你的域名指向到内部的IP地址192.168.100.1,其它的域名解析正常进行。这样,当你从内部访问时,你的DNS会自动把它指向192.168.100.1,而不经过Linux服务器。
 
b、修改NAT规则,增加这样一行:
iptables -A POSTROUTING -s 192.168.100.0/255.255.255.0 -d 192.168.100.1 -p tcp --dport 80  \
-j SNAT --to-source 192.168.100.254
 
截止到这里,我们已经知道如何使用iptables来设置NAT规则实现从局域网到Internet的访问,并且知道了如何利用ip地址或网卡MAC地址控制上网权限。如果在局域网内设置了Internet服务器,我们还可以通过设置DNAT规则来实现从Internet到局域网内特定服务的访问。
 
 
§§ 封包过滤——Packet Filter
 
刚才使用NAT解决了局域网接入问题,现在就来看看netfilter的强大的封包过滤功能,该功能常被用来配置防火墙。
 
封包过滤(Packet Filter)是使用特定的软件来察看经过Linux服务器的数据包的包头,并根据过滤规则的设置决定数据包的命运。比如丢弃(DROP)该数据包,接收(ACCEPT)该数据包(允许通过),或者其它的动作。
 
 
§§ 控制封包过滤规则
 
来看看Linux下的封包过滤是如何工作的。Linux内核中默认的有三个被称为“防火墙规则”的过滤表,分别是:INPUT、OUTPUT和FORWARD。如下图所示:
                                  _____
        Incoming                 /     \         Outgoing
           ------>[Routing ]--->|FORWARD|-------->
                  [Decision]     \_____/         ^
                       |                         |
                       v                       ____
                      ___                     /    \
                     /   \                   |OUTPUT|
                    |INPUT|                   \____/
                     \___/                       ^
                       |                         |
                        ----> Local Process -----
 
数据包通过网络接口(比如网卡)进入Linux服务器,首先,该数据包将被进行路由操作(Routing Decision)以决定它的去向,然后分别与INPUT、FORWARD、OUTPUT规则表匹配以决定是否允许该数据包通过或转发。防火墙规则表完全决定了通过该服务器的数据包的命运。
 
对照我们前面描述的网络连接,我们通过Linux服务器上的eth0连接到Internet,下面修改后的脚本将在实现NAT的同时,禁止任何来自Internet的主动访问,即整个网络的访问权限是单向的,只允许从内部网向Internet的访问。
[root@rh73 ~]# cat fw.sh
#!/bin/sh
 
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
#把默认的INPUT和FORWARD策略置为DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
 
#禁止来自Internet到eth0主动发起的访问请求
iptables -A FORWARD ! -i eth0 -m state --state NEW -j ACCEPT  ①
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT  ②
 
iptables -A INPUT ! -i eth0 -m state --state NEW -j ACCEPT  ③
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT  ④
 
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
 
由于对于INPUT和FORWARD的规则设置相同,也可以把①②③④部分简化一下:
#创建一个新的规则表allowed
iptables -N allowed
iptables -A allowed ! -i eth0 -m state --state NEW -j ACCEPT
iptables -A allowed -m state --state ESTABLISHED,RELATED -j ACCEPT
 
#INPUT和FORWARD使用allowed规则表的设置
iptables -A INPUT -j allowed
iptables -A FORWARD -j allowed
 
这个脚本中又用到了iptables的几个新的参数和使用方法,下面将对此做一个小小的总结。
 
 
§§ iptables的常用命令和选项
 
前面我们一直使用iptables这个工具来创建和维护规则表,它通过丰富的命令和选项来设置这些规则,到目前为止本文只讲述其中很少的一部分内容,但我想在大多数场合下这已经足够用了,(但愿你也这么认为 8))。
 
iptables命令:
 
维护规则表的命令:
1.       (-N)创建一个新规则表
2.       (-X)删除一个空规则表
3.       (-P)改变内建规则表的默认策略
4.       (-L)列出规则表中的规则
5.       (-F)清空规则表中的规则
6.       (-Z)将规则表计数器清零
 
管理规则表中的规则:
1.       (-A)添加新规则到规则表
2.       (-I)插入新规则到规则表的某个位置
3.       (-R)替换规则表中的规则
4.       (-D)删除规则表中的某条规则
 
在调试iptables规则时,你也许需要反复修改你的脚本来实现某些特定的功能,这时建议在你的脚本里添加这样几行,以防止重复设置规则:
 
# 清除所有规则
iptables -F -t filter
iptables -X -t filter
iptables -Z -t filter
iptables -F -t nat
iptables -X -t nat
iptables -Z -t nat
 
# 设置内建规则表的默认策略
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
 
“-t”选项是“--table”的简写,它指明了你要对哪类规则表进行操作,默认的是指filter。
 
下面举例说明iptables的部分选项的使用:
 
指定源地址和目标地址
 
指定规则操作的源地址  -s 或 --source 或 -src
指定规则操作的目标地址 -d 或 --destination 或 -dst
 
允许来自192.168.100.0/24的数据包通过
iptables -A INPUT -s 192.168.100.0/24 -d 0.0.0.0/0 -j ACCEPT
 
“-j”选项是“--jump”的简写,它指明了匹配该条规则的数据包的具体处理方法,可能是ACCEPT、DROP等。
 
取反:在参数前加“!”号
 
接受除了来自192.168.100.0/24外的所有的数据包
iptables -A INPUT -s ! 192.168.100.0/24 -d 0.0.0.0/0 -j ACCEPT
 
指定协议(TCP、UDP或ICMP)
 
-p 或 --protocol
 
禁止icmp协议
iptables -A INPUT -p icmp -j DROP
 
指定接口
 
指定数据包进入的接口 -i 或 --in-interface
指定数据包送出的接口 -o 或 --out-interface
INPUT规则表中只允许指定-i接口,OUTPUT规则表中只允许指定-o接口,FORWARD表可以指定这两种接口。
 
允许从eth1进入的数据包
iptables -A INPUT -i eth1 -j ACCEPT
 
允许从eth0接口送出的数据包
iptables -A OUTPUT -o eth0 -j ACCEPT
 
转发从eth1进入,eth0送出的数据包
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
 
TCP/UDP扩展
指定源端口 --sport 或 --source-port
指定目的端口 --dport 或 --destination-port
 
允许从eth0进入访问到目标端口为21的tcp数据包
iptables -A INPUT -i eth0 -p tcp --dport 21 -j ACCEPT
 
允许从eth0进入访问到目标端口为21的udp数据包
iptables -A INPUT -i eth0 -p udp --dport 21 -j ACCEPT
 
状态匹配
--state state,state...
 
正如前面我们脚本中用到的,state是用逗号分隔的列表,表示要匹配的连接状态。有效的状态选项包括:INVAILD,表示数据包对应的连接是未知的;ESTABLISHED,表示数据包对应的连接已经进行了双向的数据包传输,也就是说连接已经建立;NEW,表示这个数据包请求发起一个连接;RELATED,表示数据包要发起一个新的连接,但是这个连接和一个现有的连接有关,例如:FTP的数据传输连接和控制连接之间就是RELATED关系。
 
禁止从eth0进来的NEW状态,也就是禁止来自eth0的新的访问请求
iptables -A INPUT -i eth0 -m state --state NEW -j DROP
 
“-m”是“--match”的简写。-m选项引出了iptables的state扩展模块,比如mac扩展模块,它实现根据主机网卡的MAC地址进行权限控制的规则:
 
iptables -A INPUT -p tcp -m mac --mac-source 01:02:03:04:05:06 -j ACCEPT
 
扩展模块是iptables体系中的特色,它使得iptables成为一个可扩展的安全体系结构。你可以从这里了解更多关于iptables扩展模块的知识:http://www.iptables.org/documentation/HOWTO//netfilter-extensions-HOWTO.html
 
 
§§ 对封包过滤设置的建议
 
封包过滤实现的是针对安全方面的策略,通常我们遵循“凡是没有明确允许的都是禁止的”这样的原则来设计安全策略:首先禁止所有的东西,然后根据需要再开启必要的部分。
 
启用路由验证(防止IP地址欺骗)。IP地址欺骗指使用伪装的IP地址作为IP包的源地址对受保护网络进行攻击,防火墙应该能够禁止来自外部网络而源地址是内部IP地址的数据包通过。比如来自你的外网接口eth0新建连接的数据包源地址是你的内部局域网的地址,正常情况下这种现象是不可能的,那么它应当被丢掉。
 
Linux内核支持防范IP地址欺骗的功能,对于一个接口比如eth0可以这样做:
echo 1 > /proc/sys/net/ipv4/conf/eth0/rp_filter
 
对于所有接口:
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
    echo 1 > $f
done
 
综合NAT和封包过滤这两部分内容,我们得到一个具有防火墙功能的脚本fw.sh,它已经初步实现了我们关于接入服务和防火墙两项功能的要求:
 
[root@rh73 ~]# cat fw.sh
#!/bin/sh
 
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
    echo 1 > $f
done
 
# 删除所有规则
iptables -F -t filter
iptables -X -t filter
iptables -Z -t filter
iptables -F -t nat
iptables -X -t nat
iptables -Z -t nat
 
# 设置内建规则表的默认策略
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
 
#禁止来自Internet到eth0主动发起的访问请求
iptables -A FORWARD ! -i eth0 -m state --state NEW -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
 
iptables -A INPUT ! -i eth0 -m state --state NEW -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
iptables -A POSTROUTING -t nat -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 61.156.35.114
 
 
§§ iptables-save和iptables-restore
 
iptables设置的规则可以用两个相关的工具iptables-save、iptables-restore来进行存储和恢复。
 
在控制台执行如下命令:
[root@rh73 ~]# iptables-save
# Generated by iptables-save v1.2.5 on Mon Aug  5 22:25:25 2002
*filter
:INPUT DROP [1:192]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [23:1015]
-A INPUT -i ! eth0 -m state --state NEW -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i ! eth0 -m state --state NEW -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Mon Aug  5 22:25:25 2002
# Generated by iptables-save v1.2.5 on Mon Aug  5 22:25:25 2002
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -s 192.168.100.0/255.255.255.0 -o eth0 -j SNAT --to-source 61.156.35.114
COMMIT
# Completed on Mon Aug  5 22:25:25 2002
 
也可以代-t参数,指明显示哪个规则表的内容:
 
[root@rh73 ~]# iptables-save -t filter
# Generated by iptables-save v1.2.5 on Mon Aug  5 22:26:20 2002
*filter
:INPUT DROP [49:14129]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [62:3729]
-A INPUT -i ! eth0 -m state --state NEW -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i ! eth0 -m state --state NEW -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
# Completed on Mon Aug  5 22:26:20 2002
 
可以把显示结果存储到文件中:
 
[root@rh73 ~]# iptables-save > filename
 
恢复iptables规则使用iptables-restore命令:
 
[root@rh73 ~]# iptables-restore < filename
 
 
§§ 使用Red Hat Linux提供的启动控制脚本
 
除了自己编写脚本,我们还可以使用Red Hat Linux带的iptables的启动控制脚本来管理iptables规则。使用Red Hat自带的/etc/rc.d/init.d/iptables脚本控制iptables,我们需要关心下面几个文件:
 
/etc/rc.d/init.d/iptables
iptables的控制脚本,可以用来启动、停止iptables
 
/etc/rc.modules
预加载模块支持特定的服务
 
/etc/sysconfig/iptables
iptables规则设置
 
/etc/sysctl.conf
内核参数设置
 
看看如何设置这几个文件:
 
设置/etc/rc.modules
 
[root@rh73 ~]# vi /etc/rc.modules
modprobe ip_nat_irc
modprobe ip_conntrack_irc
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp
 
存盘退出后,修改该文件的属性
 
[root@rh73 ~]# chmod +x /etc/rc.modules
 
设置/etc/sysconfig/iptables,其内容格式和iptables-save输出格式是完全一样的,可以直接用iptables-save获得刚才fw.sh脚本定义的策略。运行fw.sh脚本后,再运行:
 
[root@rh73 ~]# iptables-save > /etc/sysconfig/iptables
 
设置/etc/sysctl.conf来开启IP转发和防止地址欺骗特性:
 
[root@rh73 ~]# vi /etc/sysctl.conf
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
 
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
 
全部设置完后,运行ntsysv,确认选择了iptables一项,在系统启动时可以自动加载iptables设置的规则,然后重新启动服务器:
 
[root@rh73 ~]# shutdown –r now
 
系统在重起后自动加载iptables规则。在控制台也可以手工来控制启动/停止iptables:
 
启动iptables
 
[root@rh73 ~]# /etc/rc.d/init.d/iptables start
 
停掉iptables
 
[root@rh73 ~]# /etc/rc.d/init.d/iptables stop
 
 
§§ 一个相对完整的NAT和防火墙脚本
 
参照文章开始时给出的图示,网络中的Linux接入服务器除了具有启用NAT让局域网内终端共享上网的功能外,还通过设置让我们在局域网内部的服务器192.168.100.1对外提供www、smtp、pop3服务,同时,在该接入服务器上运行了sshd以方便远端对服务器进行必要的维护,下面这个脚本就实现了这些功能:
 
[root@rh73 ~]# cat fw.sh
#!/bin/sh
 
EXT_IF="eth0"
INT_IF="eth1"
 
EXT_IP="61.156.35.114"
INT_IP="192.168.100.254"
 
LAN="192.168.100.0/24"
 
# ssh dns
TRUSTED_LOCAL_TCP_PORT="22"
TRUSTED_LOCAL_UDP_PORT="22"
 
# smtp http pop3
FWD_TCP_PORT="25 80 110"
FWD_UDP_PORT="25 80 110"
SERVER_IP1="192.168.100.1"
 
# load any special modules
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp
modprobe ip_nat_irc
modprobe ip_conntrack_irc
 
# turn off ip forwarding
echo "0" > /proc/sys/net/ipv4/ip_forward
 
# delete any existing chains
iptables -F -t filter
iptables -X -t filter
iptables -Z -t filter
iptables -F -t nat
iptables -X -t nat
iptables -Z -t nat
 
# setting up default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
 
#---------------------- filter ---------------------
 
# allow ping from internet
iptables -A INPUT -i $EXT_IF -p icmp -j ACCEPT
 
# enable local traffic
iptables -N allowed
iptables -A allowed ! -i $EXT_IF -m state --state NEW -j ACCEPT
iptables -A allowed -m state --state ESTABLISHED,RELATED -j ACCEPT
 
iptables -A INPUT -j allowed
iptables -A FORWARD -j allowed
 
for PORT in $TRUSTED_LOCAL_TCP_PORT; do
        iptables -A INPUT -i $EXT_IF -p tcp --dport $PORT -m state --state NEW -j ACCEPT
done
 
for PORT in $TRUSTED_LOCAL_UDP_PORT; do
        iptables -A INPUT -i $EXT_IF -p udp --dport $PORT -m state --state NEW -j ACCEPT
done
 
#---------------------- nat ---------------------
 
# port forwarding
for PORT in $FWD_TCP_PORT; do
    iptables -A FORWARD -i $EXT_IF -o $INT_IF -d $SERVER_IP \
        -p tcp --dport $PORT -m state --state NEW -j ACCEPT
    iptables -t nat -A PREROUTING -d $EXT_IP \
        -p tcp --dport $PORT -j DNAT --to-destination $SERVER_IP
    iptables -t nat -A POSTROUTING -s $LAN -d $SERVER_IP \
        -p tcp --dport $PORT -j SNAT --to-source $INT_IP
done
 
for PORT in $FWD_UDP_PORT; do
    iptables -A FORWARD -i $EXT_IF -o $INT_IF -d $SERVER_IP \
        -p udp --dport $PORT -m state  --state NEW -j ACCEPT
    iptables -t nat -A PREROUTING -d $EXT_IP \
        -p udp --dport $PORT -j DNAT --to-destination $SERVER_IP
    iptables -t nat -A POSTROUTING -s $LAN -d $SERVER_IP \
        -p udp --dport $PORT -j SNAT --to-source $INT_IP
done
 
# Transparent Proxy
iptables -t nat -A PREROUTING -i $INT_IF -p tcp --dport 80 -j REDIRECT --to-port 3128
 
# MASQUERADE
iptables -t nat -A POSTROUTING -o $EXT_IF -j MASQUERADE
 
#------------------------------------------------------------------------
 
# turn on ip forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward
 
# setting up ip spoofing protection
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
        echo 1 > $f
done
 
关于iptables的使用就先说这些。这些内容虽然不足以让你搭建一个功能完善的Linux防火墙,但它已经可以帮助你来完成本文一开始提出的目标了。更详细的iptables的使用方法可以在控制台键入man iptables获得。后面我们将看看有关squid代理服务器的内容,并于iptables规则配合,让我们的接入服务器支持透明代理(上面的脚本中Transparent Proxy部分已经把iptables规则设置好了)。提醒一下,透明代理对于我们的接入服务器不是必要的,NAT已经可以很好的完成共享接入功能。
 
 
[参考文档]
 
Linux 2.4 NAT HOWTO
Linux 2.4 Packet Filtering HOWTO
Iptables Tutorial
 
 
[tips]
 
从上面的介绍我们知道iptables可以按照MAC地址来管理用户的权限,Linux系统中还可以使用arp指令来实现IP与Mac地址的捆绑,以此来防止网内IP地址盗用现象的发生:
arp -i eth0 -s xxx.xxx.xxx.xxx(IP) xx.xx.xx.xx.xx(MAC)
 
还可以把多个MAC和IP对应的内容存放在文件/etc/ethers内,格式如下:
08:00:20:00:61:CA 192.168.100.11
08:00:C0:00:60:AB 192.168.100.12
 
然后运行arp -f,就可以完成多个IP与MAC的捆绑操作。
 
 
 
有关netfilter/iptables,下面几篇文章可以一读:
 
 
来自IBM developerWorks网站的几篇文章:
netfilter:Linux 防火墙在内核中的实现
http://www-900.ibm.com/developerWorks/cn/linux/network/l-netip/index.shtml
 
使用 netfilter/iptables 为 Linux(内核 2.4.x)配置防火墙
http://www-900.ibm.com/developerWorks/cn/linux/network/s-netip/index.shtml
 
 
 
防火墙非常有趣,但在需要对防火墙规则进行快速且复杂的更改时,您会做些什么?很简单。请使用Daniel Robbins 的动态防火墙脚本,你可以使用这些脚本来增加网络安全性和响应性,并激发自己的创造性设计:
http://www-900.ibm.com/developerWorks/cn/linux/network/dif/index.shtml

 
 
 
阅读(784) | 评论(0) | 转发(0) |
0

上一篇:SOCKS5 Server

下一篇:DHCP服务器

给主人留下些什么吧!~~