iptables部署

1、iptables简介

 Netfilter/Iptables(以下简称Iptables)是unix/linux自带的一款优秀且开放源代码的安全自由的**基于包过滤的防火墙工具**,它的功能十分强大,使用非常灵活,可以对流入和流出服务器的数据包进行很精细的控制。特别是它可以在一台非常低的硬件配置下跑的非常好 Iptables是Linux2.4及2.6内核中集成的服务。其功能与安全性比其**ipfwadm,ipchains**强大的多,iptables主要工作在OSI七层的二、三、四层,如果重新编译内核,iptables也可以支持**7层控制**(squid代理+iptables)

 iptables的术语:

 容器:包含和被包含的关系 
 iptables是表的容器 
 iptables包含表 (4张表)表是链的容器,每个表都包含若干个链 
 链是规则的容器,真正过滤规则是属于链里面的 

 级别的形象比喻

 iptables国家 
 表省 
 链 市 
 规则 县 

 iptables工作流程

 1.防火墙是一层层过滤的。实际是按照配置规则的顺序从上到下,从前到后进行过滤的。 
 2.如果匹配上规则,即明确表是阻止还是通过,此时数据包就不在向下匹配新规则了。 
 3.如果所有规则中没有明确是阻止还是通过这个数据包,也就是么有匹配上新规则,向下进行匹配,直到匹配默认规则得到明确的组织还是通过 
 4.防火墙的默认规则是对应链的所有规则执行完才会执行的。

 iptables表(tables)和链(chains)

iptables 策略路由 iptables软路由_加载

 Filter表 是真正的防火墙功能 
  INPUT 进服务器 OUTPUT出服务器 FORWARD 流经服务器 
 Nat 表 负责数据包改写 网关共享上网、IP和端口映射 
  OUTPUT 
  PREROUTING 
  POSTROUTING 
 Mangle表 路由标记 用的不多 
  ####所有链全有 
 RAW 表 用处很少和Mangle一样 
 我们可以通过man iptables 来获取

 iptables表和链工作流程图

iptables 策略路由 iptables软路由_服务器_02

 提示: iptables主要由2个作用,第一是防火墙,第二是路由。 
 NAT功能: 
  企业案例:1)局域网上网共享(路由和网关)NAT POSTROUTING 
       2)外部IP和端口映射为内部IP和端口(DMZ功能),NAT PREROUTING 
 Filter功能,即防火墙FILTER INPUT FORWARD 
  企业案例:主要应用于服务器防火墙

2、配置iptables防火墙

 CENTOS系统默认已经安装了iptables,产看iptables的规则用如下命令:

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

 表示针对input,forward,output链 ACCEPT是默认规则,默认是运行通过的。如果没有指定表,默认就是filter表。如果要查看nat表的规则用:iptables -L -n -t nat

 查看iptables默认加载的内核模块

[root@lnmp01 ~]# lsmod|grep  ^ip
iptable_filter          2793  0 
ip_tables              17831  1 iptable_filter
ipv6                  334932  280

 加载如下模块到linux内核

modprobe ip_tables
modprobe iptable_filter
modprobe iptable_nat
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
modprobe ip_conntrack
modprobe ipt_state

 然后再用lsmod|egrep  ^ip命令来查看加载的iptalbes的模块

[root@lnmp01 ~]# lsmod|egrep  ^ip
iptable_nat             6051  0 
iptable_filter          2793  0 
ip_tables              17831  2 iptable_nat,iptable_filter
ipv6                  334932  280

 这样就可以看到nat模块也加载到内核了。

   清空所有规则,只留下默认规则

iptables -F
iptables -X
iptables -Z

  说明:

   iptables -F  //清除所有规则,不会处理默认的规则。

   iptables -X  //删除用户自定义的链。

   iptables -Z  //链的记数器清零。

 书写一个规则,禁用80端口的防火墙配置命令:

iptables -t filter -A INPUT -p tcp --dport 80 -j DROP
#或者用下面命令,不写fileter,因为默认的表就是filter
iptables  -A INPUT -p tcp --dport 80 -j DROP

   -A 添加规则到指定链的结尾,最后一条 
   -I 添加规则到指定链的开头,第一条 
   -t 指定表,也可以不指定默认是filter 
   -p 指定协议(all.tcp,udp.icmp)默认all 
   --dport 指定端口 
   -j 处理的行为 
   ACCPET接收、DROP丢弃、REJECT拒绝

   最好使用ACCPETDROP,因为拒绝会返回给用户信息。 

 清除规则可以使用iptables -F ,还可以使用iptables -D INPUT 1 

-D指定删除的链 
  --line-number 显示序列号 
  iptables -L -n --line-number

[root@lnmp01 ~]# iptables -L -n  --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

 添加的规则可以对链使用-A和-I参数-A表示(add或append),-I表示(insert插入)。如果想在一些规则中插入一条规则的话,就只能用-I参数了,如下:

iptables -t filter -A INPUT -p tcp --dport 80 -j DROP
iptables -t filter -A INPUT -p tcp --dport 81 -j DROP
iptables -t filter -A INPUT -p tcp --dport 82 -j DROP
iptables -t filter -A INPUT -p tcp --dport 83 -j DROP
iptables -t filter -I INPUT 2 -p tcp --dport 84 -j DROP

[root@lnmp01 ~]# iptables -L -n  --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 
2    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:84 
3    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:81 
4    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:82 
5    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:83

 可以看到添加的规则iptables -t filter -I INPUT 2 -p tcp --dport 84 -j DROP用了-I的参数,此规则备插入到了第一条规则和第三条规则之间了。

  那么如何对某个规则删除呢,可以使用如下方式来删除

  1. iptables -D INPUT -p tcp –dport 8080 -j DROP 
  2. iptables -F 删所有规则 
  3. /etc/init.d/iptables restart (用iptables命令行配置的命令都是临时生效) 
  4. iptables -D INPUT 规则序号

  不仅可以对端口配置规则,还可以对网段配置规则

iptables -A INPUT -s 10.0.0.0/24 -j DROP

 -s指定源地址 ,还可以使用不是这个网段的进行操作

iptables -A INPUT ! -s 10.0.0.0/24 -j DROP

 控制22端口 eth0网卡进来的数据

iptables -A INPUT -p tcp --dport 22 -i eth0 ! -s 10.0.0.0/24 -j DROP
iptables -A INPUT -p tcp --dport 22 -i eth0 ! -s 192.168.1.1 -j DROP

 还可以配置端口范围规则

iptables -A INPUT -p tcp --sport 22:80
iptables -A INPUT -p tcp --dport 21,22,23 -j DROP---->错误语法
iptables -I INPUT -p tcp -m multiport --dport 22,23,24,25 -j DROP
iptables -I INPUT -p tcp -m multiport ! --dport 22,23,24,25 -j DROP
iptables -I INPUT -p tcp --dport 3306:8809 -j ACCEPT
iptables -I INPUT -p tcp --dport 18:80 -j DROP  <----最佳方法

 匹配ICMP类型,icmp中有很多类型,其中8代表ping 

iptables -A INPUT -p icmp --icmp-type 8 -j DROP

-m state --state参数来配置规则了

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

m state --state说明:

-m state --state
    NEW:已经或启动新的连接
    ESTABLISHED:已建立的连接
    RELATED:正在启动的新连接
    INVALID:非法或无法识别的
FTP服务是特殊的,需要配状态连接

 限制指定时间包的允许通过数量及并发数,用参数-m limit --limit n/{second/minute/hour}和--limit-burst [n],前一个n表示指定时间内的请求速率“n”为速率,后面为时间分别为:秒、分、时,后一个n表示在同一时间内允许通过的请求“n”为数字,不指定默认为5

 配置示例如下:

iptables -I INPUT -s 10.0.1.0/24 -p icmp --icmp-type 8 -m limit --limit 5/min --limit-burst 2 -j ACCEPT

 又比如用limit参数来自定义链处理syn攻击

iptables -N syn-flood
iptables -A INPUT -i eth0 -syn -j syn-flood
iptables -A syn-flood -m limit -limit 5000/s -limit-burst 200 -j RETURN
iptables -A syn-flood -j DROP

3、生产环境配置主机防火墙的两种模式 
 1. 允许所有程序,对操作伤害的进行拒绝操纵 应用场景:企业配置上网网关路由 
 2. 拒绝所有操作,允许指定的操作 应用场景:服务器主机防火墙

 配置一个企业防火墙的步骤如下:

#清空防火墙规则,并设置一些必要的规则
iptables -F
iptables -X
iptables -Z
iptables -A INPUT -p tcp  --dport 52113 -s 10.0.0.0/24  -j ACCEPT 
iptables -A INPUT -i lo -j ACCEPT 
iptables -A OUTPUT -o lo -j ACCEPT

#设置默认规则
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP 

#允许合法的进入,比如企业内网络,其他idc机房的网络       
iptables -A INPUT -s 124.43.62.96/27 -p all -j ACCEP
iptables -A INPUT -s 192.168.1.0/24 -p all -j ACCEPT
iptables -A INPUT -s 10.0.0.0/24 -p all -j ACCEPT   
iptables -A INPUT -s 203.83.24.0/24 -p all -j ACCEPT
iptables -A INPUT -s 201.82.34.0/24 -p all -j ACCEPT

#提供必要的外部服务
iptables -A INPUT -p tcp  --dport 80 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8  -j ACCEPT

#允许关联的状态包  ftp协议
iptables -A INPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

 然后用nmap 扫描的主机ip  -p 1-65535来查看被扫描主机开放的端口有哪些。

 配置好规则后只是当前环境下生效,如果防火墙重启或清除规则命令的话,这些配置的规则就会失效,所以要对配置的规则进行保存处理

/etc/init.d/iptables save   配置会自动保存到/etc/sysconfig/iptables文件中。生产环境中如果有个规则要修改的话,可以直接修改/etc/sysconfig/iptables这个文件中的规则即可

案例一:自动封IP:分析web或应用日志或者网络连接状态封掉垃圾IP

#!/bin/sh
/bin/netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: 'print $1'|sort|uniq -c|sort -rn|head -10|grep -v -E '192.168|127.0'|awk 'if ($2!=null && $1>100) {print $2}'>/home/shell/dropip
for i in $(cat /home/shell/dropip)
do
	/sbin/iptables -I INPUT -s $i -j DROP
	echo "$i is killed at `date`">>/var/log/ddos
done

案例二:写一个脚本解决DOS攻击生产案例  

  提示:根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100,即调用防火墙命令封掉对应的IP,监控频率每隔3分钟。防火墙命令为:iptables -I INPUT -s 10.0.1.10 -j DROP 本脚本使用测试文件进行编写 

#!/bin/sh
#
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
IP_file="/server/scripts/ddos.txt"
IP_filter_command="iptables -I INPUT -j DROP -s"
IP_recover_command="iptables -D INPUT -j DROP -s"
function IP_check(){
  grep "EST"  ${IP_file}|awk -F "[ |:]+" '{print $6}'|sort |uniq -c|sort -rn -k1 > /server/scripts/ip.txt
}
function IP_filter(){
   exec < /server/scripts/ip.txt
   while read line
   do
     IP_count=`echo $line|awk '{print $1}'`
     IP=`echo $line|awk '{print $2}'`
     IP_fil=`iptables -L -n|grep "\b${IP}\b"|wc -l`
     if [ ${IP_count} -gt 25 -a ${IP_fil} -eq 0 ];then
        ${IP_filter_command} ${IP}
        echo "${IP}" >> /server/scripts/ip_filtered.txt
        action "Filter ${IP}" /bin/true
     fi
   done
}
function IP_recover(){
   exec < /server/scripts/ip.txt
   while read line
   do
     IP_count=`echo $line|awk '{print $1}'`
     IP=`echo $line|awk '{print $2}'`
     IP_fil=`iptables -L -n|grep "\b${IP}\b"|wc -l`
     if [ ${IP_count} -le 25 -a ${IP_fil} -eq 1 ];then
        ${IP_recover_command} ${IP}
        echo "${IP}" >> /server/scripts/ip_filtered.txt
        action "Recover ${IP}" /bin/true
     fi
   done
}
function main(){
    case "$1" in
      filter)
      IP_check
      echo "$(date +%F-%H:%M:%S) filtered by $(whoami)" >> /server/scripts/ip_filtered.txt
      IP_filter
      ;;
      recover)
      IP_check
      echo "$(date +%F-%H:%M:%S) recovered by $(whoami)" >> /server/scripts/ip_filtered.txt
      IP_recover
      ;;
      *)
      echo "USAGE:$0 {filter|recover}"
      exit 1
    esac
}
main $*

4、配置iptables的nat

 nat表设置

iptables 策略路由 iptables软路由_服务器_03

 局域网共享的两条命令方法:

 方法1:适合于有固定外网地址的:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 10.0.0.7

  (1)-s 192.168.1.0/24 办公室或IDC内网网段。

  (2)-o eth0 为网关的外网卡接口。

  (3)-j SNAT --to-source 10.0.0.19 是网关外网卡IP地址。 

 方法2:适合变化外网地址(ADSL):

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

 要使局域网能够共享上网的话,或者说使用nat表做地址转换的话,必要要开启内核转发功能

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

sysctl -p

 开启了内核转发功能,别忘了要保证farward也是要被允许的。即:

  保证iptables FORWARD要ACCEPT 
  iptables -P FORWARD ACCEPT

 如果客户机需要上网的话,还需要配置默认路由和DNS

#客户机的默认路由配置,指向nat网关的主机地址。例如:
route add default  gw 172.16.1.5

#对客户机的网卡的dns设置如下:
DNS1=202.96.209.5
DNS2=202.96.209.6

 配置好默认路由后用route  -n来检查本地的路由表

 案例:实现把访问nat网关的地址10.0.0.5:80的请求转到web服务的主机地址172.16.1.8:80

iptables -t nat -A PREROUTING -d 10.0.0.5 -p tcp --dport 80 -j DNAT --to-destination 172.16.1.8:80

5、iptables常用企业案例

 1、Linux主机防火墙(表:FILTER 控制链:INPUT) 
 2、局域网机器共享上网(表:NAT 控制链:POSTROUTING

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 10.0.0.7

 3、外部地址和端口,映射为内部地址和端口(表:NAT 控制的链:PREROUTING

iptables -t nat -A PREROUTING -d 10.0.0.7 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.8:9000

 iptables 生产应用场景

  1)局域网共享上网(适合做企业内部局域网上网网关,以及IDC机房内网的上网网关[nat POSTROUTING]) 
  2)服务器防火墙功能(适合IDC机房具有外网IP的服务器)(主要是filter INPUT的控制) 
  3)把外部IP及端口映射到局域网内部(可以一对一IP映射,也可以针对某一个端口映射)也可能是IDC把网站的外网VIP及网站端口映射到负载均衡器上(硬件防火墙)。(nat PREROUTING) 
  4)办公路由器+网关功能(zebra路由+iptables过滤及NAT+squid正向透明代理)80+ntop/iftop/iptraf流量查看+tc/cbq流量控制限速 
  5)邮件的网关

 iptables防火墙的应用

  1)主机防火墙 
  2)网关的应用(IP映射,端口映射) 
  3)过滤信息,监控限制流量及员工上网行为(squid(正向代理缓存加过滤)+ntop(图形流量监控)+通常(流量限制)+iptraf/iftop(流量查看)) 
    如果IPTABLES的服务器升级内核可以实现类似squid的过滤功能 
  4)网关装杀毒软件监听9999端口,(网关杀毒

  5)结合zebra配置企业级路由器

 问题:如果局域网上网人数太多,那么局域网的ip地址nat地址转换成外网的一个ip的话,可能外网一些web服务会认为这种方式访问是一种恶意攻击,解决办法就是将局域网划分为多个vlan,然后将每个vlan映射到不同的外网ip地址上,这样就保证了多人ip地址nat转换成外网ip不会太多,外网的web也就不认为这是一种恶意攻击而被禁掉。映射多个外网ip示例如下:

iptables -t nat -A POSTROUTING -s 10.0.0.1/255.255.255.0 -o eth0 -j SNAT --to-source 124.42.60.11-124.42.60.16
iptables -t nat -A POSTROUTING -s 172.16.1.0/255.255.255.0 -o eth0 -j SNAT --to-source 124.42.60.103-124.42.60.106

 拍错:dmesg里面显示ip_conntrack: table full, dropping packet.的错误提示.如何解决

  这个错误问题为内核需要对防火墙优化,优化参数如下:

net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120

  调整内核参数/etc/sysctl.conf后,需执行/sbin/sysctl -p使得修改生效。 
强调:如果并发比较大,或者日PV多的情况下,开启防火墙要注意,很可能导致网站访问缓慢 
大并发(并发1万,PV日3000万)要么购买硬件防火墙,要么不开iptables防火墙

zebra路由软件部署

zebra部署在linux系统,可以让linux系统作为路由器转发数据包,等同于路由器的作用。

1、下载zebra软件,进行编译安装

wget http://ftp.twaren.net/Unix/NonGNU/quagga/quagga-0.99.20.tar.gz

 安装说明:http://www.routingloops.co.uk/cisco/how-to-install-quagga-on-centos-6-5/

 编译安装如下:

cd  /home/goser/tools
tar  xf  quagga-0.99.20.tar.gz 
cd quagga-0.99.20
./configure
make &&  make install

2、生成zebra配置文件

cp  /usr/local/etc/zebra.conf.sample /usr/local/etc/zebra.conf

 可以查看到zebra的登录秘钥,默认的秘钥为zebra,当然也可以对此默认的秘钥做修改

cat  /usr/local/etc/zebra.conf
! -*- zebra -*-
!
! zebra sample configuration file
!
! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
!
hostname Router
password zebra
enable password zebra
!
! Interface's description. 
!
!interface lo
! description test of desc.
!
!interface sit0
! multicast

!
! Static default route sample.
!
!ip route 0.0.0.0/0 203.181.89.241
!

!log file zebra.log

3、运行zebra服务

/usr/local/sbin/zebra -d -u root 
privs_init: could not lookup group quagga

 这个提示为:需要quagga做才能运行zebra服务。所以先创建quagga用户组,再运行zebra服务

groupadd quagga
/usr/local/sbin/zebra -d -u root

 查看zebra服务启动所占用的端口号为2601

netstat  -lntup|grep zebra
tcp        0      0 0.0.0.0:2601                0.0.0.0:*                   LISTEN      35351/zebra         
tcp        0      0 :::2601                     :::*                        LISTEN      35351/zebra

4、通过telnet连接2601端口进入zebra环境,来配置路由即可

telnet  localhost 2601
Trying ::1...
Connected to localhost.
Escape character is '^]'.

Hello, this is Quagga (version 0.99.20).
Copyright 1996-2005 Kunihiro Ishiguro, et al.


User Access Verification

Password: 
Router> enable 
Password: 
Router# configure terminal 
Router(config)#

 当然也可以通过telnet  localhost  zebra进入zebra环境。

 5、进入zebra环境,配置如下:

#Linux上配置zebra路由:
client(config)#int eth0
client(config-if)#ip add 10.1.34.81 255.255.255.0
client(config-if)#int eth1
client(config-if)#ip add 110.233.24.96 255.255.255.224
client(config)#ip route 0.0.0.0 0.0.0.0 10.1.32.1
client(config)#ip route 110.233.24.96/27 eth1