扩展:multiport、iprange、connlimit、limit、time、string{kmp|bm} state [NEW、ESTABLISHED、RELATED、INVALID],作为一个主机防火墙,我们本机出去,本机服务器
对服务器而言,很少需要主动发起新请求去连接别的机子。因为要在OUTPUT,很多情况下要放行ESTABLISHED和RELATED,对于INPUT也是,而NEW很少放行,放行也仅是放行客户端建立连接的服务。
如TCP 80开放NEW。
优化的规则:尽量减少规则条目,属于同一功能匹配严格的一般放入上面。
由于规则限定很细,很多时候,需要自己自定义一个链,如何自定义呢?
对于filter表来说就三个链,INPUT.FORWARD.OUTPUT。由于自定义的链没有在内核上,所以只有被调用才会使用。
------------------------------------------------------------------------------------
关于主机防火墙,控制主机本身的进出规则~
案例:如果访问web服务就要自定义一条链,web拒绝172.16.1.50-172.16.1.100范围内的主机访问。
如果不自定义表的话,就用这个命令。
[root@libin ~]# iptables -A INPUT -d 192.168.1.162 -p tcp --dport 80 -m iprange --src-range 172.16.1.50-172.16.1.100 -j DROP
效果如左图
但是我们要自己创建定义链就要使用命令:
iptables �Ct filter (表面对哪个表,默认是filter) �CN webin (新建一个叫webin的链)
一个叫webin的新链就建立好了,而我们的目的就是为了在这条webin的链上限定80的web服务。建立好了,我们开始创建规则吧
案例二
我们是web服务器端,我们可以让网络上任何主机都可以访问我们的80端口服务,但是限定192.168.1.128主机对服务器的web访问。
[root@libin ~]# iptables -A webin -d 192.168.1.162 -p tcp --dport 80 -s 192.168.1.128 -j DROP
而实际的效果是:
Chain webin (0 references)
target prot opt source destination
DROP tcp -- 192.168.1.128 192.168.1.162 tcp dpt:80
那么我们用192.168.1.128去测试一下实际效果:
[root@libin ~]# curl http://192.168.1.162
根本就是没有响应,说明拒绝了它的访问,如果我们同时允许除了它以外的其他人访问,也可以使用下列的命令。
iptables -A webin -d 192.168.1.162 -p tcp --dport 80 -m state --state NEW -j ACCEPT
-m state 因为我们想让它对第一次请求建立web服务的客户端放行,就要使用 �C state NEW 表明第一次访问连接的就允许放行。
而后我们可以修改INPUT链中加入这一条:
[root@libin ~]# iptables -A INPUT -d 192.168.1.162 -m state --state ESTABLISHED -j ACCEPT
[root@libin ~]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 192.168.1.162 tcp dpt:22
DROP tcp -- 0.0.0.0/0 192.168.1.162 tcp dpt:80 source IP range 172.16.1.50-172.16.1.100
ACCEPT all -- 0.0.0.0/0 192.168.1.162 state ESTABLISHED
说明如果放行处于连接中的web服务。
案例三:设想一下,如果我们需要多次使用到ssh服务去远程连接服务器,也可以通过建立一个新的链来规定我们的ssh的。
[root@libin ~]# iptables -t filter -N sshin
[root@libin ~]# iptables -L -n
Chain sshin (0 references)
target prot opt source destination
现在建立完新链了,但是没有做调用,还是不生效的,所以还要调用它。就拿刚才的webin为例吧,如果我们想生效这个webin链,只需要写
[root@libin ~]# iptables -A INPUT -d 192.168.1.162 --dport 80 -j webin
iptables v1.4.7: unknown option `--dport'
Try `iptables -h' or 'iptables --help' for more information.
这里报了一个错,它说不知道的选项--dport,笔者曾经在此犯过错误,后来笔者细心的一看,原来经常忘记加-p tcp /udp 这里需要-p 协议名称,需要加协议的!
[root@libin ~]# iptables -A INPUT -d 192.168.1.162 -p tcp --dport 80 -j webin
[root@libin ~]#
这样就ok啦
webin tcp -- 0.0.0.0/0 192.168.1.162 tcp dpt:80
显示写入跳转的规则,让我们看看匹配的实际效果。
[root@libin htdocs]# iptables -L -n -v
Chain INPUT (policy DROP 61 packets, 6558 bytes)
pkts bytes target prot opt in out source destination
1929 140K ACCEPT tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:22
0 0 DROP tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:80 source IP range 172.16.1.50-172.16.1.100
32 3404 ACCEPT all -- * * 0.0.0.0/0 192.168.1.162 state ESTABLISHED
6 312 webin tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:80
有6个包进来了,此时我们用物理机win7来做任意ip地址的客户端访问web服务器,此时会出现:
[root@libin htdocs]# iptables -L -n -v
Chain INPUT (policy DROP 84 packets, 9003 bytes)
pkts bytes target prot opt in out source destination
1935 140K ACCEPT tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:22
0 0 DROP tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:80 source IP range 172.16.1.50-172.16.1.100
37 4064 ACCEPT all -- * * 0.0.0.0/0 192.168.1.162 state ESTABLISHED
7 364 webin tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:80
出现了变化!
如果某个请求在定义的规则中匹配不到,怎么办?我们可以定义一个RETURN,定义如果匹配不到就回到主链上去
iptables �CA webin �Cd 192.168.1.126 �Cj RETURN
Chain webin (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP tcp -- * * 192.168.1.128 192.168.1.162 tcp dpt:80
8 416 ACCEPT tcp -- * * 0.0.0.0/0 192.168.1.162 tcp dpt:80 state NEW
0 0 RETURN all -- * * 0.0.0.0/0 192.168.1.162
意思是如果匹配不到,回到主链上去。
由此可见,我们可以设计出一个这样的概念,让我们的服务器192.168.1.128仅仅支持自己的ssh远程连接和支持192.168.1.10-192.168.1.253,其他的一律拒绝.
Chain INPUT (policy DROP 562 packets, 74975 bytes)
pkts bytes target prot opt in out source destination
4435 338K ACCEPT all -- * * 0.0.0.0/0 192.168.1.128 state ESTABLISHED
0 0 webin tcp -- * * 0.0.0.0/0 192.168.1.128 tcp dpt:80
37 2068 sshin tcp -- * * 0.0.0.0/0 192.168.1.128 tcp dpt:22
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy DROP 184 packets, 55088 bytes)
pkts bytes target prot opt in out source destination
2366 268K ACCEPT all -- * * 192.168.1.128 0.0.0.0/0 state ESTABLISHED
0 0 ACCEPT tcp -- * * 192.168.1.128 0.0.0.0/0 tcp spt:22
Chain sshin (1 references)
pkts bytes target prot opt in out source destination
2 104 ACCEPT tcp -- * * 192.168.1.179 192.168.1.128 tcp dpt:22
20 1128 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain webin (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 192.168.1.128 tcp dpt:80 source IP range 192.168.1.10-192.168.1.253 state NEW
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
注意这里的192.168.1.179是物理机的ip地址,它通过ssh连接192.168.1.128这个服务器。
让我们做个测试:
显然是失败了
最后还有一步,就是我们把现在定义好的规则给它保存起来如何~
这个是已经保存好的规则了!
现在我们将iptables规则清空:
[root@libin tmp]# iptables -P INPUT ACCEPT
[root@libin tmp]# iptables -P OUTPUT ACCEPT
[root@libin tmp]# iptables -F
[root@libin tmp]# iptables -L -n
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
Chain sshin (0 references)
target prot opt source destination
Chain webin (0 references)
target prot opt source destination
然后用iptables-restore重新读取文件,看看能不能生效:
[root@libin tmp]# iptables-restore < /tmp/iptables_1.txt
[root@libin tmp]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 192.168.1.128 state ESTABLISHED
webin tcp -- 0.0.0.0/0 192.168.1.128 tcp dpt:80
sshin tcp -- 0.0.0.0/0 192.168.1.128 tcp dpt:22
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy DROP)
target prot opt source destination
ACCEPT all -- 192.168.1.128 0.0.0.0/0 state ESTABLISHED
ACCEPT tcp -- 192.168.1.128 0.0.0.0/0 tcp spt:22
Chain sshin (1 references)
target prot opt source destination
ACCEPT tcp -- 192.168.1.179 192.168.1.128 tcp dpt:22
RETURN all -- 0.0.0.0/0 0.0.0.0/0
Chain webin (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 192.168.1.128 tcp dpt:80 source IP range 192.168.1.10-192.168.1.253 state NEW
RETURN all -- 0.0.0.0/0 0.0.0.0/0
看来还是能的!
而且使用iptables �CX 自定义链的链名(必须为空),可以删除自定义的链
[root@libin tmp]# iptables -L -n
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
Chain sshin (0 references)
target prot opt source destination
Chain webin (0 references)
target prot opt source destination
[root@libin tmp]# iptables -X sshin
[root@libin tmp]# iptables -X webin
[root@libin tmp]# iptables -L -n
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
没有webin和sshin啦!
使用重命名的(一定要是0引用的)iptables �CE 自定义的老链名称 新的链名
------------------------------------------------------------------------------------------------------------------------------------
下面则是网络防火墙部分
计划:模拟一个外内网通信的模型,然后进一步设置FORWARD转发功能,进一步限制!
图←服务器192.168.1.128支持nat功能,可以转发内外主机的ip报文
图←内网主机192.168.5.1用ping的方式连接外网主机,结果显示成功!
图←外网主机192.168.1.162可以ping同外网的主机!
现在开始限定,先加入放行规则为已建立连接的就放行
[root@libin ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
然后再添加:
[root@libin ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (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.5.10 tcp dpt:80 state NEW
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
意思就是对内网那个主机做80端口访问的都予以放行。这时我们就可以访问了。
[root@libin ~]# curl 192.168.5.10
<h1> this is 5.1 </h1>
[root@libin ~]#
出现了它的首页了。
那么我们如果清理了FORWARD链了呢?
[root@libin ~]# curl 192.168.5.10
就显示打不开,一直卡在那个页面上。
好的, 下面让我们看看ftp怎么限制访问:
这是内网主机开启了vsftpd,是ftp的服务器端
被动监听在21号端口!
然后我们用外网主机来联系它,通过网络防火墙:
[root@libin ~]# lftp 192.168.5.10
lftp 192.168.5.10:~> ls
`ls' at 0 [Connecting...]
显示连接不上。。
我们修改网络防火墙规则:这里没有定义具体的那些端口,进而试试:
[root@libin ~]# iptables -A FORWARD -d 192.168.5.10 -s 192.168.1.162 -p tcp -m state --state NEW -j ACCEPT
You have new mail in /var/spool/mail/root
[root@libin ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT tcp -- 192.168.1.162 192.168.5.10 state NEW
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
让我们来试一下:
显示连接不上去?为什么呢??还记得我们的ftp一般都是被动模式的,命令连接是被动的,还有一个数据连接呢?所以要加上RELATED,好吧,那我们加上去试一下。
[root@libin ~]# iptables -R FORWARD 2 -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@libin ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT tcp -- 192.168.1.162 192.168.5.10 state NEW
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
我们再去用外网主机FTP连接内网主机试试:
!!竟然还是不行,原来是我们的模块没有加载,让我们重新加载一下模块。
[root@libin ~]# modprobe nf_conntrack_ftp加载nf_conntrack_ftp模块
[root@libin ~]# lftp 192.168.5.10
lftp 192.168.5.10:~> ls
drwxr-xr-x 2 0 0 4096 Mar 01 2013 pub
看!可以了
其实每次手动加载模块是很麻烦的事,我们需要编辑配置文件/etc/sysconfig/iptables-config 这个文件,在里面找到:
# Load additional iptables modules (nat helpers)
# Default: -none-
# Space separated list of nat helpers (e.g. 'ip_nat_ftp ip_nat_irc'), which
# are loaded after the firewall rules are applied. Options for the helpers are
# stored in /etc/modprobe.conf.
IPTABLES_MODULES="nf_conntrack_ftp"就ok了
=======================================================================================================