实现有价值的IT服务
全部博文(709)
分类: IT职场
2005-11-17 11:42:19
1.什么是状态检测
每个网络连接包括以下信息:源地址、目的地址、源端口和目的端口,叫作套接字对(socket pairs);协议类型、连接状态(TCP协议)和超时时间等。防火墙把这些信息叫作状态(stateful),能够检测每个连接状态的防火墙叫作状态包过滤防火墙。它除了能够完成简单包过滤防火墙的包过滤工作外,还在自己的内存中维护一个跟踪连接状态的表,比简单包过滤防火墙具有更大的安全性。
iptables中的状态检测功能是由state选项来实现的。对这个选项,在iptables的手册页中有以下描述:
state
这个模块能够跟踪分组的连接状态(即状态检测)。
--state state
这里,state是一个用逗号分割的列表,表示要匹配的连接状态。有效的状态选项包括:INVAILD,表示分组对应的连接是未知的;ESTABLISHED,表示分组对应的连接已经进行了双向的分组传输,也就是说连接已经建立;NEW,表示这个分组需要发起一个连接,或者说,分组对应的连接在两个方向上都没有进行过分组传输;RELATED,表示分组要发起一个新的连接,但是这个连接和一个现有的连接有关,例如:FTP的数据传输连接和控制连接之间就是RELATED关系。
对于本地产生分组,在PREROUTING或者OUTPUT链中都可以对连接的状态进行跟踪。在进行状态检测之前,需要重组分组的分片。这就是为什么在iptables中不再使用ipchains的ip_always_defrag开关。
UDP和TCP连接的状态表由/proc/net/ip_conntrack进行维护。稍后我们再介绍它的内容。
状态表能够保存的最大连接数保存在/proc/sys/net/ipv4/ip_conntrack_max中。它取决于硬件的物理内存。
2.iptables的状态检测是如何工作的?
2.1.iptables概述
在讨论iptables状态检测之前,我们先大体看一下整个netfilter框架。如果要在两个网络接口之间转发一个分组,这个分组将以以下的顺序接收规则链的检查:
PREROUTING链
如果必要对这个分组进行目的网络地址转换(DNAT)和mangle处理。同时,iptables的状态检测机制将重组分组,并且以以下某种方式跟踪其状态:
分组是否匹配状态表中的一个已经实现(ESTABLISHED)的连接。
它是否是和状态表中某个UDP/TCP连接相关(RELATED)的一个ICMP分组。
这个分组是否要发起一个新(NEW)的连接。
如果分组和任何连接无关,就被认为是无效(INVALID)的。
FORWARD链
把分组的状态和过滤表中的规则进行匹配,如果分组与所有的规则都无法匹配,就使用默认的策略进行处理。
POSTROUTING链
如果有必要,就对分组进行源网络地址转换(SNAT),
注意:所有的分组都必须和过滤表的规则进行比较。如果你修改了规则,要拒绝所有的网络流量,那么即使分组的状态匹配状态表中的一个ESTABLISHED条目,也将被拒绝。
下面,我们对UDP、TCP和ICMP三个协议分别进行分析。
2.2.UDP连接
UDP(用户数据包协议)是一种无状态协议,以为这个协议没有序列号。不过,这并不意味着我们不能跟踪UDP连接。虽然没有序列号,但是我们还可以使用其它的一些信息跟踪UDP连接的状态。下面是状态表中关于UDP连接的条目:
udp 17 19 src=192.168.1.2 dst=192.168.1.50 sport=1032 dport=53 [UNREPLIED] src=192.168.1.50 dst=192.168.1.2 sport=53 dport=1032 use=1
这个状态表项只有在iptables过滤规则允许建立新的连接时,才能建立。以下的规则可以产生这类状态表项,这两条规则只允许向外的UDP连接:
iptables -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -P udp -m state --state NEW,ESTABLISHED -j ACCEPT
上面的状态表项包含如下信息:
连接的协议是UDP(IP协议号17)。
这个状态表项还有19秒中就超时。
发起连接方向上的源、目的地址和源、目的端口。
应答方向上的源、目的地址和源、目的端口。这个连接使用UNREPLIED标记,表示还没有收到应答。
UDP连接的超时时间在/usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c文件中设置,如果改变了这个值,需要重新编译Linux内核源代码才能生效。下面是UDP连接超时时间的相关的源代码:
#define UDP_TIMEOUT (30*HZ)
#define UDP_STREAM_TIMEOUT (180*HZ)
一个UDP请求等待应答的时间是30*HZ(这个值一般是30秒)。在上面的例子中,等待的时间已经消耗了11秒,还剩余19秒,如果在这段时间之内没有收到应答分组,这个表项就会被删除。一旦收到了应答,这个值就被重置为30,UNREPLIED标志也被删除。这个表项编程如下形式:
udp 17 28 src=192.168.1.2 dst=192.168.1.50 sport=1032 dport=53 src=192.168.1.50 dst=192.168.1.2 sport=53 dport=1032 use=1
如果在这一对源、目的地址和源、目的端口上,发生了多个请求和应答,这个表项就作为一个数据流表项,它的超时时间是180秒。这种情况下,这个表项就变成如下形式:
udp 17 177 src=192.168.1.2 dst=192.168.1.50 sport=1032 dport=53 src=192.168.1.50 dst=192.168.1.2 sport=53 dport=1032 [ASSURED] use=1
这时我们看到这个表项使用ASSURED标志。一旦连接表项使用ASSURED标志,那么即使在网络负沉重的情况下,也不会被丢弃。如果状态表已经饱和,当新的连接到达时,使用UNREPLIED标志的表项会受被丢弃。
2.3.TCP连接
一个TCP连接是通过三次握手的方式完成的。首先,客户程序发出一个同步请求(发出一个SYN分组);接着,服务器端回应一个SYN|ACK分组;最后返回一个ACK分组,连接完成。整个过程如下所示:
Client Server
SYN --->
<--- SYN+ACK
ACK --->
<--- ACK
ACK --->
.........
.........
SYN和ACK是由TCP分组头的标志决定的。在每个TCP分组头还有32位的序列号和应答号用于跟踪会话。
为了跟踪一个TCP连接的状态,你需要使用下面这样的规则:
iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED -j ACCEPT
2.3.1.连接建立过程中状态表的变化
下面,我们详细讨论在连接建立的每个阶段中,状态表发生的变化:
一旦一个初始SYN分组进入OUTPUT链,并且输出规则允许这个分组建立一个新的连接,状态表的相关表项将如下所示:
cp 6 119 SYN_SENT src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 [UNREPLIED] src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 use=1
其中,TCP连接状态是SYN_SENT,连接被标记为UNREPLIED。
现在,我们等待SYN+ACK分组的响应。一旦得到响应,这个TCP连接表项就变为:
tcp 6 57 SYN_RECV src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 use=1
连接的状态变为SYN_RECV,UNREPLIED标志被清除。
现在我们需要等待完成握手的ACK分组。ACK分组到达后,我们首先对其序列号进行一些检查,如果正确,就把这个连接的状态变为ESTABLISHED,并且使用ASSURED标记这个连接。这时,这个连接的状态如下所示:
cp 6 431995 ESTABLISHED src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 [ASSURED] use=1
2.3.2.透视状态表
上面,我们涉及了很多CP连接的状态。现在,我们分析一下TCP连接的状态检测。实际上,状态表只知道NEW、ESTABLISHED、RELATED和INVALID。
要注意:状态检测的状态不等于TCP状态。当一个SYN分组的响应SYN+ACK分组到达,Netfilter的状态检测模块就会认为连接已经建立。但是,这时还没有完成三次握手,因此TCP连接还没有建立。
另外,包过滤规则不能删除状态表中的表项,只有连接超时,对应的状态表项才会被删除。ACK分组能够建立一个NEW状态表项。向防火墙之后一台并不存在主机发送ACK分组,并不会返回RST分组,可以证明这个结论。因此,你需要使用以下的规则明确新的TCP连接应该是SYN分组建立的:
iptables -A INPUT -p tcp !--syn -m state --state NEW -j DROP
这样可以阻止空会话的继续进行。
2.3.3.超时
所谓状态表项的超时值是指每个表项存在的最大时间,这些超时值的大小在/usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c文件中设置。以下是相关的代码:
static unsigned long tcp_timeouts[]
= { 30 MINS, /* TCP_CONNTRACK_NONE, */
5 DAYS, /* TCP_CONNTRACK_ESTABLISHED, */
2 MINS, /* TCP_CONNTRACK_SYN_SENT, */
60 SECS, /* TCP_CONNTRACK_SYN_RECV, */
2 MINS, /* TCP_CONNTRACK_FIN_WAIT, */
2 MINS, /* TCP_CONNTRACK_TIME_WAIT, */
10 SECS, /* TCP_CONNTRACK_CLOSE, */
60 SECS, /* TCP_CONNTRACK_CLOSE_WAIT, */
30 SECS, /* TCP_CONNTRACK_LAST_ACK, */
2 MINS, /* TCP_CONNTRACK_LISTEN, */
};
2.3.4.连接的中断
关闭一个TCP连接可以有两种方式。第一种类似于建立TCP连接的三次握手。一旦一个TCP会话完成,要终止会话的一方首先发出一个FIN为1的分组。接收方TCP确认这个FIN分组,并同志自己这边的应用程序不要在接收数据了。这个过程可以如下所示:
Client Server
.........
.........
FIN+ACK --->
<--- ACK
<--- FIN+ACK
ACK --->
在这个过程之中或者之后,状态表的连接状态变为TIME_WAIT。在默认情况下,2分钟之后从状态表删除。
除此之外,还有其它关闭中断的方式。TCP会话的任何一方发出一个RST标志为1的分组,可以快速断开一个TCP连接。而且,RST分组不需要应答。在这种情况下,状态表项的状态变为CLOSE,10秒之后被删除。和http连接经常通过这种方式中断,如果一个连接很长时间没有请求了,服务器端就会发出一个RST分组中断连接。
2.4.ICMP
在iptables看来,只有四种ICMP分组,这些分组类型可以被归为NEW、ESTABLISHED两类:
ECHO请求(ping,和ECHO应答(pong,0)。
时间戳请求(13)和应答(14)。
信息请求(15)和应答(16)。
地址掩码请求(17)和应答(1。
这些ICMP分组类型中,请求分组属于NEW,应答分组属于ESTABLISHED。而其它类型的ICMP分组不基于请求/应答方式,一律被归入RELATED。
我们先看一个简单的例子:
iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED, RELATED -j ACCEPT
iptables -A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
这链条规则进行如下的过滤:
一个ICMP echo请求是一个NEW连接。因此,允许ICMP echo请求通过OUTPUT链。
当对应的应答返回,此时连接的状态是ESTABLISED,因此允许通过INPUT链。而INPUT链没有NEW状态,因此不允许echo请求通过INPUT链。也就是说,这两条规则允许内部主机ping外部主机,而不允许外部主机ping内部主机。
一个重定向ICMP(5)分组不是基于请求/应答方式的,因此属于RELATED。INPUT和OUTPUT链都允许RELATED状态的连接,因此重定向(5)分组可以通过INPUT和OUTPUT链。
3.FTP协议的状态检测
上面,我们比较详细地介绍了iptables的态检测机制。现在,我们以FTP状态检测为例介绍如何使用iptables进行连接状态检测。
首先,你需要加载ip_conntrack_ftp模块。使用如下规则就可以允许建立FTP控制连接(这里没有考虑IMCP问题):
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLESED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISED -j ACCEPT
除了控制连接之外,FTP协议还需要一个数据通道,不过,数据连接可以通过主动和被动两种模式建立,我们需要分别讨论。
3.1.主动模式
在主动模式下,客户程序在控制通道上,使用PORT命令告诉FTP服务器自己这边的数据传输端口,然后FTP从20端口向这个端口发起一个连接。连接建立后,服务器端和客户端就可以使用这个连接传输数据了,例如:传诵的文件、ls等命令的结果等。因此,在主动模式下FTP数据传输通道是反向建立的,它从FTP服务器端向客户端发起。
在主动模式下,客户端使用的数据传输端口是不固定的,因此我们需要在规则中使用端口范围。由于客户端使用的端口都是大于1024的,这并不会降低系统的安全性。
在iptables中,有一个专门跟踪FTP状态的模块--ip_conntrack_ftp。这个模块能够识别出PORT命令,并从中提取端口号。这样,FTP数据传输连接就被归入RELATED状态,它和向外的FTP控制连接相关,因此我们不需要在INPUT链中使用NEW状态。下面的规则可以实现我们的意图:
iptables -A INPUT -p tcp --sport 20 -m state --state ESTABLISED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISED -j ACCEPT
3.2.被动模式
和主动模式相反,在被动模式下,指定连接端口的PORT命令是服务器端发出的。FTP服务器通过PORT命令告诉客户端自己使用的FTP数据传输端口,然后等待客户端建立数据传输连接。在被动模式下,建立数据传输连接的方向和建立控制连接的方向是相同的。因此,被动模式具有比主动模式更好的安全性。
由于ip_conntrack_ftp模块能够从PORT命令提取端口,因此我们在OUTPUT链中也不必使用NEW状态,下面的规则可以实现对被动模式下的FTP状态检测:
iptables -A INPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT
综合以上的分析,我们可以得到FTP连接的状态检测规则,对于主动模式的FTP,需要下面的iptables规则:
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLESED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISED -j ACCEPT
iptables -A INPUT -p tcp --sport 20 -m state --state ESTABLISED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISED -j ACCEPT
对于被动模式的FTP连接,需要使用如下iptables规则
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLESED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISED -j ACCEPT
iptables -A INPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 1024: --dport 1024: -m state --state ESTABLISHED,RELATED -j ACCEPT
本文中提到的状态检测,在iptables中实际叫作连接跟踪(Connection tracking),出于自己的习惯,我在本文中一律改为状态检测
==============================================================
写于2001年初,包括下面4个内容
一. china,cernet双路接入3网卡NAT网关.
二、用ipchains写的3网卡路由器策略
三、经典linux NAT网关配置
四、一个较长的网关及安全策略实例
一. china,cernet双路接入3网卡NAT网关.
我们事业部现在的办公上网设备包括一个2500路由器,2台超强3000服务器,分别作路由选择和两路的NAT网关,这是部门刚成立时就用的设备,
作NAT的操作系统是Win2k Advance Server, 因为win2k特别消耗资源,再加上办公网流量过大,有多人看视频流时,网关有时会Down机。
我的想法是一台3网卡的服务器,来代替以上3台设备,操作系统及软件为linux2.4 kernel + netfilter + squid,
能够作路由以及两路的NAT。
优点:
1. 节省数万元的路由器和服务器,可以用作网站,对外集成或办公网其他需求。
2. 增加了防火墙功能,策略为外部无法访问网关本身和内部网络,内部可以访问外部所有服务。(与checkpoint效果一样)。linux内核实现,没有费用。
3. 利用netfilter 端口重定向至squid代理端口,可以进行透明代理及http加速,针对慢速站点和多人重复访问的站点,加快internet访问速度,节省大量带宽。(我做过测试,对于访问过的站点,第二次访问同一张图片,提速能够到达10秒以上,试验环境为办公网络内部的一台PC机作内部代理网关)
4. 客户端仍同以前一样,无需任何设置。
具体配置如下:
具有一个默认的gateway是 chinanet链路的 gateway
cernet 链路的路由网关设为 166.111.212.129
在Redhat下添加cernet路由表的具体语法是:
route add -net 162.105.0.0 -netmask 255.255.0.0 gw 166.111.212.129 dev eth0
对网关进行保护的语法为:
iptables -N block
iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT
iptables -A block -j DROP
## Jump to that chain from INPUT and FORWARD chains.
iptables -A INPUT -j block
iptables -A FORWARD -j block
NAT的语法为:
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j SNAT --to gw_etho_ip
透明代理的语法为:
iptables -t nat -A PREROUTING -i eth0 -p tcp -s 192.168.100.0/24 --dport 80 -j REDIRECT --to-port 3128
二、用ipchains写的3网卡路由器策略
通过路由器划分隔离多个子网,
控制子网间的访问, 控制某个子网的上网IP
公司众多公司多路接入上网.
我的方案是多块网卡接入,一块网卡做外网卡,在上面做NAT,因为打开了ip_forwarding,
为了保证各个公司的办公网段彼此是分开的,必须用防火墙分隔开.互相不能访问.
为了简化防火墙语法,最好各个公司的网段都属于192.168.0.0.这个B类地址.
只需一条策略即可禁止各个私有网端之间互相访问.
CLASS_C=192.168.0.0/16
ipchains -A forward -s $CLASS_C -d $CLASS_C -j DENY
或
iptables -A FORWARD -s $CLASS_C -d $CLASS_C -j DENY
具体脚本如下:
##### define variable
CLASS_C="192.168.0.0/16"
DZNET="192.168.1.0/24"
ZBNET="192.168.80.0/24"
WJNET="192.168.100.0/24"
LIJUN="192.168.100.47"
WJGW1="192.168.100.1/32"
WJGW2="192.168.100.10/32"
WJGW3="192.168.100.11/32"
WJGW="192.168.100.20/32"
ETH0_IP="192.168.80.1/32"
ETH1_IP="192.168.100.20/32"
ETH2_IP="192.168.1.1/32"
##### initialize
echo 1 > /proc/sys/net/ipv4/ip_forward
ipchains -F
ipchains -P input ACCEPT
ipchains -P output ACCEPT
ipchains -P forward ACCEPT
##### protect router
# others can't visit linux router ,only admin lijun
ipchains -A input -s $LIJUN -j ACCEPT
ipchains -A input -p icmp -d $ETH0_IP -j ACCEPT
ipchains -A input -p icmp -d $ETH1_IP -j ACCEPT
ipchains -A input -p icmp -d $ETH2_IP -j ACCEPT
ipchains -A input -d $ETH0_IP -j DENY
ipchains -A input -d $ETH1_IP -j DENY
ipchains -A input -d $ETH2_IP -j DENY
##### allow only legal users and net send packets to internet. not allow visit each.
# allow lijun visit anywhere
ipchains -A forward -s $LIJUN -j ACCEPT
ipchains -A forward -s 192.168.100.155 -j ACCEPT
#ipchains -A forward -p tcp ! -y -d $LIJUN -j ACCEPT
#ipchains -A forward -p udp -s $CLASS_C 1:1023 -d $LIJUN 1024:65535 -j ACCEPT
ipchains -A forward -s $CLASS_C -d $LIJUN -j ACCEPT
ipchains -A forward -s $CLASS_C -d 192.168.100.155 -j ACCEPT
#ipchains -A forward -p icmp -s $CLASS_C -d $LIJUN -j ACCEPT
#allow any only to ping gw and cant's visit each other
ipchains -A forward -p icmp -d $WJGW -j ACCEPT
ipchains -A forward -p icmp -s $WJGW -j ACCEPT
ipchains -A forward -p icmp -d $WJGW1 -j ACCEPT
ipchains -A forward -p icmp -s $WJGW1 -j ACCEPT
ipchains -A forward -p icmp -d $WJGW2 -j ACCEPT
ipchains -A forward -p icmp -s $WJGW2 -j ACCEPT
ipchains -A forward -p icmp -d $WJGW3 -j ACCEPT
ipchains -A forward -p icmp -s $WJGW3 -j ACCEPT
ipchains -A forward -s $CLASS_C -d $CLASS_C -j DENY
#allow DZNET to send packets to internet
ipchains -A forward -s $DZNET -j ACCEPT
#only allow ZBNET legal users to send packet s to internet
ipchains -A forward -s 192.168.80.21 -j ACCEPT
ipchains -A forward -s 192.168.80.22 -j ACCEPT
ipchains -A forward -s 192.168.80.23 -j ACCEPT
ipchains -A forward -s 192.168.80.25 -j ACCEPT
ipchains -A forward -s 192.168.80.26 -j ACCEPT
ipchains -A forward -s 192.168.80.30 -j ACCEPT
ipchains -A forward -s 192.168.80.39 -j ACCEPT
ipchains -A forward -s 192.168.80.35 -j ACCEPT
ipchains -A forward -s 192.168.80.43 -j ACCEPT
ipchains -A forward -s 192.168.80.36 -j ACCEPT
ipchains -A forward -s 192.168.80.48 -j ACCEPT
ipchains -A forward -s 192.168.80.33 -j ACCEPT
ipchains -A forward -s 192.168.80.37 -j ACCEPT
ipchains -A forward -s 192.168.80.29 -j ACCEPT
ipchains -A forward -s 192.168.80.4 -j ACCEPT
ipchains -A forward -s 192.168.80.42 -j ACCEPT
ipchains -A forward -s 192.168.80.51 -j ACCEPT
ipchains -A forward -s 192.168.80.58 -j ACCEPT
ipchains -A forward -s 192.168.80.68 -j ACCEPT
ipchains -A forward -s 192.168.80.81 -j ACCEPT
ipchains -A forward -s 192.168.80.84 -j ACCEPT
ipchains -A forward -s 192.168.80.103 -j ACCEPT
ipchains -A forward -s 192.168.80.110 -j ACCEPT
ipchains -A forward -s 192.168.80.144 -j ACCEPT
ipchains -A forward -s 192.168.80.100 -j ACCEPT
ipchains -A forward -s 192.168.80.119 -j ACCEPT
ipchains -A forward -s 192.168.80.130 -j ACCEPT
ipchains -A forward -s 192.168.80.210 -j ACCEPT
ipchains -A forward -s 192.168.80.220 -j ACCEPT
ipchains -A forward -s 192.168.80.55 -j ACCEPT
ipchains -A forward -s 192.168.80.47 -j ACCEPT
ipchains -A forward -s 192.168.80.49 -j ACCEPT
ipchains -A forward -s 192.168.80.50 -j ACCEPT
ipchains -A forward -s 192.168.80.38 -j ACCEPT
ipchains -A forward -s 192.168.80.46 -j ACCEPT
ipchains -A forward -s 192.168.80.107 -j ACCEPT
# other deny
ipchains -A forward -s $ZBNET -j DENY
三、经典 linux NAT网关配置
iptables -F
iptables -F -t nat
# Creat chain which blocks new connections, except if coming from inside.
iptables -N block
iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A block -m state --state NEW -i ! eth0 -j ACCEPT
iptables -A block -j DROP
iptables -A INPUT -j block
iptables -A FORWARD -j block
# NAT so the inside private ip can go to the internet throught the public ip
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j SNAT --to 1.2.3.4
# http service redirect to squid proxy
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128
四、一个较长的网管及安全策略实例
##### define variable
NETSITES="211.68.29.0/24"
CLASS_C="192.168.0.0/16"
LIJUN="192.168.100.47"
LIJUN2="192.168.100.155"
LUOXM="192.168.100.43"
LIJUN_IP="211.68.29.13"
LOGGER="192.168.100.193"
OUT_IF_IP="211.68.29.9"
IN_IF_IP="192.168.100.1"
IN_IF_2IP="192.168.10.1"
OUT_ETH="eth1"
IN_ETH="eth0"
MAIL1="211.68.29.38"
DNS1="211.68.29.7"
DNS2="211.68.29.8"
MUD="211.68.29.81"
NAT1_IP="211.68.29.223"
NAT1_IN_IP="192.168.100.217"
##### initialize
ifconfig eth0 add 192.168.10.1
ifconfig eth1 add 211.68.29.13
ifconfig eth1 add 211.68.29.184
ifconfig eth1 add 211.68.29.223
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -F
iptables -F -t nat
iptables -F block
iptables -X block
##### Creat chain which blocks new connections, except coming from inside.
iptables -N block
iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A block -m state --state NEW -i ! $OUT_ETH -j ACCEPT
iptables -A block -j DROP
### allow thtf zb use oicq
iptables -A FORWARD -s 192.168.80.0/24 -p tcp --dport 8000 -o $OUT_ETH -j DROP
#Forbid to use OICQ.
iptables -A FORWARD -s $CLASS_C -p tcp -d 0.0.0.0/0 --dport 8000 -o $OUT_ETH -j DROP
iptables -A FORWARD -s $CLASS_C -p udp -d 0.0.0.0/0 --dport 8000 -o $OUT_ETH -j DROP
#Forbid to use LianZhong Game.
iptables -A FORWARD -s $CLASS_C -p tcp -d 0.0.0.0/0 --dport 2000 -o $OUT_ETH -j DROP
iptables -A FORWARD -s $CLASS_C -p udp -d 0.0.0.0/0 --dport 2000 -o $OUT_ETH -j DROP
##### protect router from inside net and outside net
##### anyone in insidenet can't visit linux router ,only admin
iptables -A INPUT -s $LIJUN -j ACCEPT
iptables -A INPUT -s $LIJUN2 -j ACCEPT
iptables -A INPUT -s $LUOXM -j ACCEPT
iptables -A INPUT -p icmp -d $IN_IF_IP -j ACCEPT
iptables -A INPUT -p icmp -d $IN_IF_2IP -j ACCEPT
iptables -A INPUT -d $IN_IF_IP -j DROP
iptables -A INPUT -j block
### move to bottom
#iptables -A FORWARD -j block
##### NAT so the inside private ip can go to the internet throught the public ip
#lijun has a full nat ip
iptables -t nat -A POSTROUTING -s $LIJUN -o $OUT_ETH -j SNAT --to $LIJUN_IP
iptables -t nat -A PREROUTING -d $LIJUN_IP -i $OUT_ETH -j DNAT --to $LIJUN
iptables -t nat -A POSTROUTING -s $NAT1_IN_IP -o $OUT_ETH -j SNAT --to $NAT1_IP
iptables -t nat -A PREROUTING -d $NAT1_IP -i $OUT_ETH -j DNAT --to $NAT1_IN_IP
iptables -t nat -A POSTROUTING -s $CLASS_C -o $OUT_ETH -j SNAT --to $OUT_IF_IP
##### http service redirect to squid proxy
iptables -t nat -A PREROUTING -i $OUT_ETH -p tcp --dport 80 -j REDIRECT --to-port 3128
##### ip cheat redirect some ip to other ip , use dnat
#for lijun test
iptables -t nat -A PREROUTING -s 192.168.100.155 -d 211.68.29.80 -p tcp --dport 80 -j DNAT --to 211.68.29.87
iptables -t nat -A PREROUTING -d 211.68.29.223 -p tcp --dport 80 -j DNAT --to 192.168.100.217
iptables -t nat -A PREROUTING -s 192.168.10.0/24 -d 211.68.29.80 -j DNAT --to 211.68.29.81
iptables -t nat -A PREROUTING -s 192.168.10.0/24 -d 211.101.224.18 -j DNAT --to 211.68.29.81
#iptables -t nat -A PREROUTING -s 192.168.100.14 -p tcp --dport 80 -j DNAT --to 202.112.0.36
#for officenet can visit netsite chinanet_ip on ciscio router
iptables -t nat -A PREROUTING -d 211.101.224.3 -j DNAT --to 211.68.29.7
iptables -t nat -A PREROUTING -d 211.101.224.2 -j DNAT --to 211.68.29.8
iptables -t nat -A PREROUTING -d 211.101.224.30 -j DNAT --to 211.68.29.9
iptables -t nat -A PREROUTING -d 211.101.224.29 -j DNAT --to 211.68.29.180
iptables -t nat -A PREROUTING -d 211.101.224.27 -j DNAT --to 211.68.29.181
iptables -t nat -A PREROUTING -d 211.101.224.18 -j DNAT --to 211.68.29.221
iptables -t nat -A PREROUTING -d 211.101.224.23 -j DNAT --to 211.68.29.26
iptables -t nat -A PREROUTING -d 211.101.224.24 -j DNAT --to 211.68.29.27
#iptables -t nat -A PREROUTING -d 211.101.224.21 -j DNAT --to 211.68.29.33
iptables -t nat -A PREROUTING -d 211.101.224.22 -j DNAT --to 211.68.29.37
iptables -t nat -A PREROUTING -d 211.101.224.25 -j DNAT --to 211.68.29.38
iptables -t nat -A PREROUTING -d 211.101.224.28 -j DNAT --to 211.68.29.80
### deny officenet visit each other
iptables -A FORWARD -s $CLASS_C -d $CLASS_C -j DROP
##### all officeip only visit 80 & 8080 except some people can visit ftp ,telnet
### super admin can visit sites without limit.
#iptables -A FORWARD -s 192.168.100.155 -d 211.68.29.81 -p tcp --dport 21 -j ACCEPT
#iptables -A FORWARD -s 192.168.100.155 -d 211.68.29.81 -p tcp --dport ftp -o $OUT_ETH -j DROP
#for temp use
iptables -A FORWARD -s 192.168.100.0/24 -d $NETSITES -j ACCEPT
#temp use end
iptables -A FORWARD -s $LIJUN -d $NETSITES -j ACCEPT
#iptables -A FORWARD -s $LIJUN2 -d $NETSITES -j ACCEPT
iptables -A FORWARD -s 192.168.100.78 -d $NETSITES -j ACCEPT
iptables -A FORWARD -s 192.168.100.74 -d $NETSITES -j ACCEPT
iptables -A FORWARD -s 192.168.100.229 -d $NETSITES -j ACCEPT
### for log
#iptables -A FORWARD -s $LOGGER -d ! $NETSITES -p tcp --dport 80 --syn -j LOG --log-ip-options
iptables -A FORWARD -s $LOGGER -d $NETSITES -p tcp --syn -j LOG
### for deny someone
#example
#iptables -A FORWARD -s 192.168.100.14 -j DROP
### normal users only can visit sites icmp& http & 8080 & mailservice & dns & 6688 6689
iptables -A FORWARD -s $CLASS_C -d $NETSITES -p icmp -j ACCEPT
iptables -A FORWARD -d $NETSITES -p tcp --dport 80 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $NETSITES -p tcp --dport 8080 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $NETSITES -p tcp --dport 8081 -o $OUT_ETH -j ACCEPT
#for oracle
iptables -A FORWARD -d $NETSITES -p tcp --dport 1521 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $MAIL1 -p tcp --dport smtp -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $MAIL1 -p tcp --dport pop3 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $MAIL1 -p tcp --dport imap -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $MAIL1 -p tcp --dport 2600 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $DNS1 -p tcp --dport 53 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $DNS1 -p udp --dport 53 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $DNS2 -p tcp --dport 53 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $DNS2 -p udp --dport 53 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $MUD -p tcp --dport 6688 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -d $MUD -p tcp --dport 6689 -o $OUT_ETH -j ACCEPT
### zbnet & dianzi net can't visit sites other service
iptables -A FORWARD -s 192.168.80.0/24 -d $NETSITES -o $OUT_ETH -j DROP
iptables -A FORWARD -s 192.168.1.0/24 -d $NETSITES -o $OUT_ETH -j DROP
### users can visite ftp and telnet
## passive ftp mode allow
iptables -A FORWARD -p tcp -s $CLASS_C --sport 1024: -d $NETSITES --dport 1024: -o $OUT_ETH -j ACCEPT
# example:
#iptables -A FORWARD -s 192.168.100.155 -d $NETSITES -p tcp --dport 21 -m mac --mac-source 00:A0:0C:C0:92:26 -j ACCEPT
iptables -A FORWARD -s 192.168.100.155 -d 211.68.29.81 -p tcp --dport ftp -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.61 -d $NETSITES -p tcp --dport ftp -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.14 -d $NETSITES -p tcp --dport ftp -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.48 -d $NETSITES -p tcp --dport ftp -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.67 -d $NETSITES -p tcp --dport ftp -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.155 -d 211.68.29.81 -p tcp --dport 23 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.61 -d $NETSITES -p tcp --dport 23 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.14 -d $NETSITES -p tcp --dport 23 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.48 -d $NETSITES -p tcp --dport 23 -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.67 -d $NETSITES -p tcp --dport 23 -o $OUT_ETH -j ACCEPT
### user can visite sites rsync
# example:
iptables -A FORWARD -s 192.168.100.0/24 -d $NETSITES -p tcp --dport rsync -o $OUT_ETH -j ACCEPT
iptables -A FORWARD -s 192.168.100.0/24 -d $NETSITES -p udp --dport rsync -o $OUT_ETH -j ACCEPT
### users can visit sites other new service
# example:
# iptables -A FORWARD -s 192.168.100.0/24 -d $NETSITES -p tcp --dport 1234 -o $OUT_ETH -j ACCEPT
### allow ftp no.1 mode
iptables -A FORWARD -s 0.0.0.0/0 -p tcp --sport ftp-data -d $CLASS_C -i $OUT_ETH -j ACCEPT
### other service drop
iptables -A FORWARD -s 192.168.100.0/24 -d $NETSITES -j DROP
iptables -A FORWARD -s 192.168.10.0/24 -d $NETSITES -j DROP
### officenet can visit anywhere out of netsites
iptables -A FORWARD -s $CLASS_C -j ACCEPT
### allow return data to officenet
#iptables -A FORWARD -s 0.0.0.0/0 -p tcp --sport ftp-data -d $CLASS_C -i $OUT_ETH -j ACCEPT
iptables -A FORWARD -p tcp -d $CLASS_C ! --syn -i $OUT_ETH -j ACCEPT
iptables -A FORWARD -p udp -d $CLASS_C -i $OUT_ETH -j ACCEPT
iptables -A FORWARD -p icmp -d $CLASS_C -i $OUT_ETH -j ACCEPT
### protect router
iptables -A FORWARD -j block
#iptables -A FORWARD -j DROP