http://www.netfilter.org/


1,包过滤防火墙  
 在网络层对数据包进行选择,主要是对数据包的所使用的协议,端口,源地址和目标地址等参数来进行过滤 

 

2,代理网关  squid    varnish   apache  nginx   
 把内网和外网是完全隔离的,内网和外网不能进行直接的TCP通讯,必须通过代理网关的处理
.exe .jpg


 
3,状态检测  
 TCP有三次握手的阶段,常用的WEB,文件下载,发送和接收邮件等等都是TCP
 状态检测防火墙除了包过滤防火墙所考查的参数之外,还要关心数据包连接的状态

 


netfilter / iptables   --iptables 的全名  2.4版本后都集成有这个组件

--查看一下iptables的模块

ls /lib/modules/2.6.18-164.el5/kernel/net/netfilter/
ls /lib/modules/2.6.18-164.el5/kernel/net/ipv4/netfilter/


    * stateless packet filtering (IPv4 and IPv6)
    * stateful packet filtering (IPv4 and IPv6)
    * all kinds of network address and port translation, e.g. NAT/NAPT (IPv4 only)
    * flexible and extensible infrastructure
    * multiple layers of API's for 3rd party extensions
    * large number of plugins/modules kept in 'patch-o-matic' repository

 

iptables  基本概念


四张表:    表里有链  (chain )

filter:  用来进行包过滤:  INPUT  OUTPUT FORWARD 
nat:   用来网络地址转换:   network  address translation ,允许一个内网地址块,通过NAT转换成公网IP,实现对公网的访问,解决IP地址不足
 PREROUTING   POSTROUTING OUTPUT


mangle :用来对数据包标志 
  PREROUTING INPUT OUTPUT  FORWARD  POSTROUTING


raw:对原始数据包的处理
 PREROUTING OUTPUT

 


Incoming                 /     \         Outgoing
       -->[Routing ]--->|FORWARD|------->
          [Decision]     \_____/        ^
               |                        |
               v                       ____
              ___                     /    \
             /   \                  |OUTPUT|
            |INPUT|                  \____/
             \___/                      ^
               |                        |
                ----> Local Process ----

 

iptables 
 -A  增加一条规则,默认就是在后面增加
 -D  删除
 -L  列出规则
 -n   以数值显示
 -I   在最前面插入规则
 -v   显示统计数据,与-L一起用,看到的信息更多


 -F  清空规则
 -z   清空计数器
 -x   清空自定义链

 -t   后接表名
 -P   policy,默认策略
 -p   后接协议名
 --dport  目标端口
 --sport  源端口
 -d  目标地址
 -s  源地址 
 -i  接网卡接口, 进入的网卡接口
 -o  接网卡接口, 出去的网卡接口
 -j  后接动作

 动作的分类:

 ACCEPT    接收数据包
 DROP    丢弃数据包
 REJECT   拒绝数据包,和DROP的区别就是REJECT会返回错误信息,DROP不会
 MASQUEREAD  IP地址伪装,使用NAT转换成外网IP,可以PPP拔号(外网IP不固定情况)
 SNAT   源地址转换,它与MASQUEREAD的区别是SNAT是接一个固定IP
 DNAT 目标地址转换
 LOG    记录日志

 

例1,列规则

 iptables -L  --默认看的就是filter表
 iptables -L -t filter

 iptables -L -t  nat
 iptables -L -t   mangle
 iptables -L -t   raw


例2,对ping的控制
ICMP 在传输层是基于tcp的,所以是双向的,可以对其input或ouput都可以控制


# iptables  -A INPUT -p icmp -j REJECT   --可以不加-t filter,默认就是对此表进行操作
 
# iptables -t filter -A INPUT -p icmp -j REJECT
  --有返回信息

# iptables -t filter -A OUTPUT -p icmp -j REJECT
  --无返回信息

# iptables -t filter -A INPUT -p icmp -j DROP
  --无返回信息

# iptables -t filter -A OUTPUT -p icmp -j DROP
  --无返回信息


只允许35ping本地,其它都拒绝
# iptables -t filter -A INPUT -p icmp -j REJECT
# iptables -t filter -A INPUT -s 10.1.1.35 -p icmp -j ACCEPT
 --错误写法


# iptables -t filter -A INPUT -s 10.1.1.35 -p icmp -j ACCEPT
# iptables -t filter -A INPUT -p icmp -j REJECT
 --正确写法


--如果要把一条规则加到前面,使用-I参数 
# iptables -t filter -A INPUT -p icmp -j REJECT
# iptables -t filter -I INPUT -s 10.1.1.35 -p icmp -j ACCEPT
 --正确写法


# iptables -t filter -I INPUT 2 -s 10.1.1.36 -p icmp -j ACCEPT
--把这一条加为第2条(指定数字为第几条)

------------------------------------------------
规则就是一个访问控制列表(ACL),读取的顺序是从上往下一条一条匹配,匹配一条就不继续往下匹配,最后匹配默认策略,所以正确写法应该是把刚才允许10.1.1.35的写到最前面
-----------------------------------------------

 

删除的方法:
 方法一:
# iptables -t filter -D  INPUT -s 10.1.1.35  -p icmp -j ACCEPT
  --加的时候怎么写,删除时就要怎么写  A 参数换成 D就可以
 方法二; 
# iptables -L -n  --line   
# iptables  -D INPUT  2
 --在规则比较多或者不好写规则的情况下,可以先用--line或者--line-number列出行号,再用行号删除

 方法三:
# iptables -F  
 --直接清空filter表的所有规则

 

例3,规则的保存与还原
# /etc/init.d/iptables save --这样是默认保存到/etc/sysconfig/iptables
# iptables-save > /etc/sysconfig/iptables--将当前规则保存到这个文件,文件可以自定义

# iptables -F
# iptables -X
# iptables -Z --使用这三条来清空filter表,如果别的表也要清空的话,就加-t 表名都清一次

# iptables-restore < /etc/sysconfig/iptables --把保存的规则还原回去


--/etc/sysconfig/iptables文件为默认保存文件,重启iptables服务会默认把此文件里的规则还原。当然也可以手工保存到另一个文件,就需要iptables-restore手工还原了。

 

例4,默认策略的修改
# iptables -P INPUT DROP --INPUT键默认策略改为DROP,改回来把DROP换成ACCEPT就行了
# iptables -P OUTPUT DROP --OUTPUT键默认策略改为DROP

 

例5,实现允许ssh过来,ssh出去,别的都拒绝  (要求,INPUT和OUTPUT双链默认策略都为DROP)

# iptables -P INPUT DROP
# iptables -P OUTPUT DROP

下面两条定义允许ssh进来
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT


下面两条定义允许ssh出去
# iptables -A INPUT -p tcp --sport 22 -j ACCEPT
# iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT

 

例6,在例五的基础上允许ping自己的IP,本地回环127.0.0.1和10.1.1.35

下面两条定义能ping自己和127本地回环 
# iptables -A INPUT -i lo -p icmp -j ACCEPT
# iptables -A OUTPUT -o lo -p icmp -j ACCEPT  
--这里用lo设备是127网段的所有回环地址都可以。如果指定ip127.0.0.1的话,只能控制这一个IP。在控制的范围上还是有区别的
下面两条定义此服务器和35这台机器可以互ping
# iptables -A INPUT -p icmp -s 10.1.1.35 -j ACCEPT
# iptables -A OUTPUT -p icmp -d 10.1.1.35 -j ACCEPT

 

 

--把默认策略先改为允许,然后把基本都安装起来,再把默认策略改回为drop
# yum install httpd*  sendmail* m4 bind* vsftpd* dhcp* samba* mysql* -y

 

例7,
在上面的基础上再加上只允许10.1.1.0这个网段访问你的httpd服务,和你只能访问10.1.1.0网段的httpd服务

# iptables -A INPUT -s 10.1.1.0/24 -p tcp --dport 80 -j ACCEPT
# iptables -A OUTPUT -d 10.1.1.0/24 -p tcp --sport 80 -j ACCEPT

 

以客户端身份能访问10网段内的web服务
# iptables -A OUTPUT -p tcp --dport 80 -d 10.1.1.0/24 -j ACCEPT
# iptables -A INPUT -p tcp --sport 80 -s 10.1.1.0/24 -j ACCEPT


例8
在上面的基础上再加上允许别人访问本台服务器的DNS
只需要做udp的53端口就可以了,不用写tcp 53(因为tcp 53主要是用于主从DNS服务器同步的)

# iptables -A INPUT -p udp --dport 53 -j ACCEPT
# iptables -A OUTPUT -p udp --sport 53 -j ACCEPT

客户端身份能访问别人的DNS服务

# iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
# iptables -A INPUT -p udp --sport 53 -j ACCEPT


-------------------------------

一些特殊的写法
连接端口
iptables -A INPUT -p tcp --dport 1:1000 -j ACCEPT
iptables -A INPUT -p tcp -m multiport  --dport 22,80,110 -j ACCEPT

硬件地址  
iptables -A INPUT -m mac --mac-source 00:23:CD:95:DA:0B -p all  --dport 80 -j ACCEPT


例9


下面两条实现了别人可以通过本机的邮件服务器收发邮件
iptables -A INPUT -p tcp -m multiport --dport 25,110,143 -j ACCEPT
iptables -A OUTPUT -p tcp -m multiport --sport 25,110,143 -j ACCEPT


下面两条实现了本机可以访问别人的邮件服务器收发邮件
iptables -A OUTPUT -p tcp -m multiport --dport 25,110,143 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --sport 25,110,143 -j ACCEPT

 


例10 dhcp

 iptables 对dhcp端口控制无效

  69

 


例11
samba

137   138   139   445

下面两条实现了别人可以通过本机的samba服务器进行文件服务器的访问
[root@iptables ~]# iptables -A INPUT -p tcp -m multiport --dport 137,138,139,445 -j ACCEPT
[root@iptables ~]# iptables -A OUTPUT -p tcp -m multiport --sport 137,138,139,445 -j ACCEPT

下面两条实现了本机可以访问别人的samba服务器
[root@iptables ~]# iptables -A OUTPUT -p tcp -m multiport --dport 137,138,139,445 -j ACCEPT
[root@iptables ~]# iptables -A INPUT -p tcp -m multiport --sport 137,138,139,445 -j ACCEPT

 

例12  FTP

用iptables实现ftp的主动模式能够访问

下面两句实现的是命令端口的连接
# iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 21 -j ACCEPT
 --不加这两句,客户端访问时都不能登录,加了后可以登录,但用ls列出ftp的共享信息的话就发现不行,这是因为20的数据端口还没有做规则

# iptables -A INPUT -p tcp --dport 20 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT
 --主动模式是20端口去主动连接,所以上面两条,实现了主动模式的连接,注意:如果使用linux的ftp命令来做实验的话,注意登录后使用passive命令关掉被动模式再试验

 


被动模式
客户端连接服务器的随机端口

vim /etc/vsftpd/vsftpd.conf
在最后加上
pasv_enable=YES
pasv_min_port=3000
pasv_max_port=3100  --最小端口范围和最大端口范围可以自定义

/etc/init.d/vsftpd  restart  --重启服务

下面两句就是针对上面的被动配置来设置的允许规则
# iptables -A INPUT -p tcp --dport 3000:3100 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 3000:3100 -j ACCEPT

 

--练习:上面的ftp是服务端写的规则,客户端应该怎么写去主动或被动访问别人的ftp服务器?

 


例13
nfs
--因为nfs用到rpc调用,端口不固定,所以需要把端口给固定起来.nis服务也会用到rpc调用,也需要做端口绑定(鸟哥书上面nis那章节有)


vim /etc/sysconfig/nfs     --在此文件里加上下面四句
LOCKD_TCPPORT=3000
LOCKD_UDPPORT=3000
MOUNTD_PORT=3001
STATD_PORT=3002

/etc/init.d/nfs restart
/etc/init.d/portmap restart --这里先把默认策略改成ACCEPT,再启动就可以启动起来,然后再把默认策略改回成DROP,再继续做下面的实验

netstat -ntl |grep 300   去查看,看到rpc.的守护进程的端口为自己绑定的端口


iptables -A INPUT -p tcp  --dport 3000:3002 -j ACCEPT
iptables -A OUTPUT -p tcp  --sport 3000:3002 -j ACCEPT
iptables -A INPUT -p udp  --dport 3000:3002 -j ACCEPT
iptables -A OUTPUT -p udp  --sport 3000:3002 -j ACCEPT

 

还要加上2049(nfs)和111(portmap)的端口的规则


iptables -A  INPUT -p tcp  --dport 2049 -j ACCEPT
iptables -A  OUTPUT -p tcp  --sport 2049 -j ACCEPT
iptables -A  INPUT -p udp  --dport 2049 -j ACCEPT
iptables -A  OUTPUT -p udp  --sport 2049 -j ACCEPT


iptables -A  INPUT -p tcp  --dport 111 -j ACCEPT
iptables -A  OUTPUT -p tcp  --sport 111 -j ACCEPT
iptables -A  INPUT -p udp  --dport 111 -j ACCEPT
iptables -A  OUTPUT -p udp  --sport 111 -j ACCEPT


--现在就可以用另一台机showmount -e 查看并进行挂载了

 

--练习:把上面的3000,3001,3002,2049,111合起来只写4条iptables来做

[root@localhost ~]# iptables -A INPUT -p tcp -m multiport --dport 111,2049,3000,3001,3002 -j ACCEPT
[root@localhost ~]# iptables -A INPUT -p udp -m multiport --dport 111,2049,3000,3001,3002 -j ACCEPT
[root@localhost ~]# iptables -A OUTPUT -p tcp -m multiport --sport 111,2049,3000,3001,3002 -j ACCEPT
[root@localhost ~]# iptables -A OUTPUT -p udp -m multiport --sport 111,2049,3000,3001,3002 -j ACCEPT

练习:上面四条做的是为NFS服务器的身份允许别人访问
如果你做为NFS客户端去访问别人的NFS服务器,又应该如何写?

 


例14
yum


视远程yum配置的类型而定


例15
mysql

3306

 

例16
oracle 监听
1521

 

==================================

 

准备两台虚拟机和真实机一起三台机做实验

 

  内网     iptables网关      外网
   
192.168.212.146 ---->  192.168.212.1  vmnet1 
       网关指向 
      打开路由   

      192.168.20.35 eth0  <-----  192.168.20.105
        网关指向

 

把gateway加上路由功能

echo "1" > /proc/sys/net/ipv4/ip_forward   --临时生效

vim /etc/sysctl.conf
net.ipv4.ip_forward = 1

sysctl -p    --改完后使用此命令,使之修改永久生效


路由功能加了后,网关都指向了gateway这台物理机,那么  两个网段的这两台机就能互相ping通

--禁止内网146这台和外网105互ping
# iptables -A FORWARD -p icmp -s 192.168.212.146  -j REJEC

--禁止内外网互ping
# iptables -A FORWARD -i vmnet1 -p icmp -j REJECT

# iptables -A FORWARD -o eth0 -p icmp -j REJECT


--禁止内网146这台上外网的192.168.20.105IP的这一个网站
# iptables -A FORWARD -s 192.168.212.146 -d 192.168.20.105 -p tcp --dport 80 -j REJECT
--这样的做法,如果要做网络管理(控制内部员工上网的行为,用iptables来做就比较繁锁,可以选用squid这种代理网关)

 


例2,
SNAT  源地址转换
 内网多个IP转换成外网IP去连接公网

现在内网146可以ping通外网105
还有105的/var/log/httpd/access_log 记录146访问过来的信息,IP为146内网IP


在外网105上把指向192.168.20.35的网关给del掉
那么内网146不能访问外网105了

 

在中间的网关机写上下面的一句
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.20.35


内网146就可以访问外网105了
并且外网105的/var/log/httpd/access_log 记录的访问记录是192.168.20.35的访问

 


# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
 -- MASQUERADE 是伪装的意思,默认就是自动转换成eth0的外网IP,可以用于外网IP不固定的情况(比如PPP拔号时)

 

--练习:
现在我的192.168.20.35是通过尚观路由器192.168.20.1可以实际上外网的
请问,我一个hostonly网段的虚拟机192.168.212.146如何才能通过NAT上外网


答案:
1,把192.168.212.146的网关指向192.168.212.1
2,把192.168.212.146的DNS指向192.168.20.1(尚观router)或者8.8.8.8(外部DNS),也就是和35一样的指向能上外网的DNS(146和35可以指的不一样)
3,在192.168.20.35上加两条iptables规则
# iptables -t nat -A POSTROUTING -o eth0 -p tcp --dport 80 -j SNAT --to-source 192.168.20.35
# iptables -t nat -A POSTROUTING -o eth0 -p udp --dport 53 -j SNAT --to-source 192.168.20.35

如果把DNS指向192.168.212.1(并且212.1这台没有开启DNS服务,因为会做缓存),那么就要在上面两条的基础上再加上一条就可以上网了
# iptables -t nat -A PREROUTING -p udp --dport 53 -i vmnet1 -j DNAT --to-destination 192.168.20.1


例3,
DNAT  目的地址转换
 也就是外网是客户端,要访问我们内网的服务器,客户端只是访问外网IP,内网里不同的服务器不同的IP,可以使用DNAT把不同的请求转换到不同的内网服务器


# iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to-destination 192.168.212.146

 

--这是表示只要是从eth0(外网)进来的80的访问,我就把它定向到内网192.168.212.146这台web服务器

 

====================================================

 

对mangle表的mark的讨论


MARK用来给包设置特殊的标记。iproute2能识别这些标记,并根据不同的标记(或没有标记)决定不同的路由。用这些标记我们可以做带宽限制和基于请求的分类。


用处一:
在lvs集群里,可以对进入的数据包打mark标记,然后针对标记再来进行分发

使用到iptables 的 set-mark和ipvsadm -f参数


--下面这段就是网上的一个例子,学到LVS后,可以对比这个做出来
==========================================

例子:LVS的 NAT 模式配置使用-f 选项
OS:   Redhat 9 内核:2.4.20
Load Balancer: eth0: 192.168.1.110/32 (负载服务器对外VIP)
                      eth1: 192.168.3.1/24
Realserver1: 192.168.3.2 (集群服务器)
                 掩码: 255.255.255.0
                 网关: 192.168.3.1
Realserver2: 192.168.3.3 (集群服务器)
                 掩码: 255.255.255.0
                 网关: 192.168.3.1

实验目的:在负载服务器上,配置LVS(NAT模式),做远程登陆服务器的集群。
实现最终用户访问负载服务器的对外VIP,负载服务器,将请求分发到集群下的服务器,
由集群服务器轮流提供ssh和telnet服务。

在Load Balancer上设置:
#echo "1" > /proc/sys/net/ipv4/ip_forward        #确保转发功能已打开
# iptables -t mangle -A PREROUTING -p tcp -d 192.168.1.110/32 --dport 22 -j MARK --set-mark 2
# iptables -t mangle -A PREROUTING -p tcp -d 192.168.1.110/32 --dport 23 -j MARK --set-mark 2
# iptables -t mangle -L PREROUTING         #查看上述两条规则是否加入到mangle表的PREROUTING链中
# ipvsadm -A -f 2 -s rr    #添加一个LVS服务,数据类型为fwmark为2的数据包,使用轮询策略
# ipvsadm -a -f 2 -r 192.168.3.2 -m -w 1    #添加真实服务器192.168.3.2到LVS(NAT模式)
                                                                         #数据类型为fwmark为2的服务中
# ipvsadm -a -f 2 -r 192.168.3.3 -m -w 1    #添加真实服务器192.168.3.3到LVS(NAT模式)
                                                                        #数据类型为fwmark为2的服务中

 

==========================================================

 


用处二:
可以和策略路由结合使用,进行路由的标记分发

参考:
http://bbs.chinaunix.net/thread-2228370-1-1.html
http://bbs.chinaunix.net/thread-2251893-1-1.html


用处三:
单服务器多个网卡同网段,想进行从哪个网卡来的数据就从哪个网卡出去

--一般来说,单服务器多网卡不要使用同一个网段的IP(为什么?明天分析)


用一个虚拟机两个host-only网卡,同网段

用真实机ping这两个网卡,然后在真实机上查看

[root@li ~]# arp -a |grep 212
bogon (192.168.212.146) at 00:0C:29:55:CC:D7 [ether] on vmnet1
bogon (192.168.212.147) at 00:0C:29:55:CC:D7 [ether] on vmnet1
--结果是两个网卡都是对应eth0的MAC


关掉eth1 147,然后arp -d 192.168.212.147清除,ping 192.168.212.147还是可以ping通


解决办法:
默认,linux所有的网卡都会回应arp,

echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/eth1/arp_ignore
--这样修改后,如果本网卡没有这个IP,则不回应arp

--这个参数,在LVS集群里也有应用

再ping146和147测试,得到的结果就是自己的IP对应自己的MAC地址
[root@li ~]# arp -a |grep 212
bogon (192.168.212.146) at 00:0C:29:55:CC:D7 [ether] on vmnet1
bogon (192.168.212.147) at 00:0C:29:55:CC:E1 [ether] on vmnet1


总结:iptables的set-mark用处并不多,并且所谓的策略路由(linux甚至可以使用zebra这样的软件配置成为一台路由器),
完全可以用cisco路由器(这样性能更好)来代替。