• 保护你的Web服务器 iptables防火墙脚本全解读


    http://os.51cto.com/art/201108/285352.htm

    本文针对iptables初学者。如果你刚刚学习了iptables的原理和基本语法,但还不清楚在线上服务器环境中如何实际的利用这个工具,那么建议阅读本文。

    iptables的两种主要工作模式

    对于iptables的数据包而言,有以下几个流向:

    PREROUTING→FORWARD→POSTROUTING

    PREROUTING→INPUT→本机→OUTPUT→POSTROUTING

    大家可以留意下,数据包的主要两种流向(其实也是我们后面iptables的两种工作模式):一是做为NAT路由器,另一种是做为主机防火墙。

    iptables数据流入和流出详细流程建议参考下图:

    图  iptables数据包流入和流出详细流程图

    图  iptables数据包流入和流出详细流程图

    iptables根据不同的数据包处理功能使用不同的规则表。它包括如下三个表:filter、nat和mangle。

    • filter是默认的表,它包含真正的防火墙过滤规则。内建的规则链包括:INPUT、OUTPUT和FORWARD。
    • nat表包含源和目的地址及端口转换使用的规则,内建的规则链包括PREROUTING、OUTPUT和POSTROUTING。
    • mangle表包含用于设置特殊的数据包路由标志的规则,这些标志随后被filter表中的规则检查。内建的规则链包括:PREROUTING、INPUT、FORWARD、POSTROUTING和OUTPUT。

    表对应的相关规则链的功能如下:

    • INPUT链:当一个数据包由内核中的路由计算确定为本地的Linux系统后,它会通过INPUT链的检查。             
    • OUTPUT链:保留给系统自身生成的数据包。
    • FORWARD链:经过Linux系统路由的数据包(即当iptables防火墙用于连接两个网络时,两个网络之间的数据包必须流经该防火墙)。
    • PREROUTING链:用于修改目的地地址(DNAT)。
    • POSTROUTING链:用于修改源地址(SNAT)。

    iptables详细语法如下所示:

    iptables [-t表名] <-A| I |D |R > 链名[规则编号] [-i | o 网卡名称] [-p 协议类型] [-s 源IP地址 | 源子网][--sport 源端口号] [-d 目标IP地址 | 目标子网][--dport 目标端口号] <-j 动作> 

    注:此语法规则详细,逻辑清晰,推荐以此公式记忆。我们在刚开始写iptables规则时就应该养成好习惯,用公式来规范脚本,这对于我们的以后工作大有帮助。

    这一节我们通过编写一个简单的用于邮件主机防护iptables脚本来熟悉iptables语法规则。网络拓朴很简单,iptables本身机器IP为:192.168.1.101/24,另一台机器的IP为:192.168.1.102。

    普通的邮件主机防护脚本

    普通的邮件主机防护脚本比较容易实现。邮件主机主要开放二个端口:80和25,其他端口则关闭,另外由于这里没有涉及多少功能,所以模块的载入也很简单,只涉及Filter表,而且脚本的初始化也很简单。

    我们可以按照编写iptables的流程顺序来写脚本,脚本内容如下:

    (注:此服务器置于自己的机房内,所以没有开放22端口,调试时直接进机房调试。如果远程操作,需要打开22端口。)

    #/bin/bash
    iptables -F
    iptables -X
    iptables -Z
     
    modprobe ip_tables
    modprobe iptable_nat
    modprobe ip_nat_ftp
    modprobe ip_conntrack
     
    iptables -P INPUT DROP
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
     
    iptables -A INPUT -i lo -j ACCEPT 
    iptables -A OUTPUT -o lo -j ACCEPT 
     
    iptables -A INPUT -p tcp -m multiport --dports 25,80 -j ACCEPT
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

    说明一下:

    前面三条可以将iptables初始化。

    modprobe这段是手动加载模块的过程。一般如果用 service iptables start 来启动iptables,会加载很多不必要的模块,所以这里我们采用手动加载的方式。ip_conntrack模块在平时的测试学习环境可以开启,方便追踪数据包的流向。不过,生产环境下我不建议大家开启此模块,以免加重服务器的负载。

    默认规则下方的两条用于开启系统回环端口,以免造成不必要的麻烦。具体是什么样的麻烦?大家可以先想一想,文末会给出解答。

    最后一条是允许RELATED和ESTABLISHED状态的连接通过iptables。为什么要这样设置,也会在文末解答。

    iptables脚本开启后,我们可以用命令查看一下结果,如下所示:

    iptables -nv -L

    此命令显示结果如下:

    Chain INPUT (policy DROP 13539 packets, 763K bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
      480 32744 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           multiport dports 25,80 
       13  1411 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
     
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
     
    Chain OUTPUT (policy ACCEPT 472 packets, 52779 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0   

    这时80和25之外的端口就被iptables成功隐蔽了。比如我们尝试在另一台机器上nmap扫描这台服务器:

    如果没有安装,就需要:

    yum install nmap 一下了!

    nmap -sT 192.168.1.101

    此命令显示结果如下:

    Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2011-05-25 00:46 CST
    Interesting ports on 192.168.1.101:
    Not shown: 1678 filtered ports
    PORT   STATE SERVICE
    25/tcp open  ssh
    80/tcp open  http
    MAC Address: 00:E0:62:12:7B:65 (Host Engineering)
     
    Nmap finished: 1 IP address (1 host up) scanned in 37.721 seconds

    看到这个结果说明iptables生效了。

    另外,对刚刚学习iptables的朋友提供一个建议。一开始玩iptables很容易犯的一个错误就是把自己锁在服务器外面了。针对这种情况,我们可以编写一个crontab计划任务,每5分钟关闭一次防火墙,等完全调试完后再关闭此crontab任务:

    vim /etc/crontab
    */5 * * * * /etc/init.d/iptables stop

    以上只是初级的防护脚本。至于其它的SYN和Ping及其它攻击,等大家熟悉了解其原理后,可以在此脚本的基础上添加。

    以下是上文中两个问题的解答:

    一、为什么要打开系统回环接口?

    Linux系统默认会有一块名为lo的环回网络接口,而真正的网卡一般则被Linux系统识别成名为eth0, eth1这样的网络接口。

    一般,lo接口对应的ip地址为127.0.0.1。

    当你从一台linux主机向自身发送数据包时,实际上的数据包是通过虚拟的lo接口来发送接受的,而不会通过你的物理网卡eth0/eth1。

    如果lo接口被墙,会发生ping/telnet/ssh本机(本机域名、localhost和127.0.0.1)不通的情况,会给调试带来一些麻烦。

    二、为什么要设置RELATED、ESTABLISHED状态检测?

    相对于纯IP过滤,状态防火墙更加智能,效率更高。这个比较适合FTP服务器。有关iptables的状态机制,可参阅这篇文章:http://os.51cto.com/art/201108/285209.htm

    http://os.51cto.com/art/201111/301918.htm

    在我们的Web服务器上,系统的默认策略是INPUT为DROP,OUTPUT;FORWARD链为ACCEPT,DROP则设置得比较宽松,因为我们知道出去的数据包比较安全。

    准备工作

    为了验证脚本的通用性,我特地查看了服务器的内核及iptables版本:

    # uname -a
    Linux ud50041 2.6.9-34.ELsmp #1 SMP Fri Feb 24 16:54:53 EST 2006 i686 i686 i386 GNU/Linux
    # iptables -V
    iptables v1.2.11
    # lsb_release -a
    LSB Version: :core-3.0-ia32:core-3.0-noarch:graphics-3.0-ia32:graphics-3.0-noarch
    Distributor ID: RedHatEnterpriseAS
    Description: Red Hat Enterprise Linux AS release 4 (Nahant Update 3)
    Release: 4
    Codename: NahantUpdate3

    大家可以发现,这台服务器的系统、内核和iptables版本是比较老的。本文中介绍的脚本涉及到recent安全模块,这对系统内核有要求(recent模块在主机防护脚本中也经常用到)。因此,如果大家要采用iptables作为主机防火墙时,建议用CentOS 5.6 x86_64或更高级版本,不然系统会有如下提示错误信息:

    iptables: Unknown error 18446744073709551615
    iptables:Invalid argument

    在tail -f /var/log/messages时会有如下出错提示:

    ip_tables: connlimit match: invalid size 32 != 16
    ip_tables: connlimit match: invalid size 32 != 24

    另外,在生产环境下进行iptables脚本的调试之前,强烈建议编写crontab任务,每5分钟关闭一次iptables脚本,防止操作失误而将自己的SSH客户端锁在外面:

    */5 * * * * root /etc/init.d/iptables stop

    准备工作就是这些,下面是iptables脚本内容。

    脚本内容

    #!/bin/sh
    #
    # This script will be executed *after* all the other init scripts.
    # You can put your own initialization stuff in here if you don't
    # want to do the full Sys V style init stuff.

    touch /var/lock/subsys/local

    #启动memcached
    /usr/local/bin/memcached -d -m 1024 -u root -p 11211 -c 256 -P /tmp/memcached.pid


    #配置防火墙
    /sbin/iptables -F
    /sbin/iptables -X
    /sbin/iptables -Z

    /sbin/modprobe ip_tables
    /sbin/modprobe iptable_nat
    /sbin/modprobe ip_nat_ftp
    #/sbin/modprobe ip_conntrack

    /sbin/iptables -P INPUT DROP
    /sbin/iptables -P FORWARD ACCEPT
    /sbin/iptables -P OUTPUT ACCEPT


    #每秒钟最多允许100个新连接
    /sbin/iptables -A INPUT -f -m limit --limit 100/sec --limit-burst 100 -j ACCEPT
    #防止ping洪水攻击,限制每秒的ping包不超过10个
    /sbin/iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 10 -j ACCEPT
    #防止各种端口扫描,将SYN及ACK SYN限制为每秒钟不超过200个,免得把数务器带宽耗尽了
    /sbin/iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 20/sec --limit-burst 200 -j ACCEPT
    #放开指定主机的访问,比如是入侵检测的主机IP
    #/sbin/iptables -A INPUT -s 122.70.x.x -j ACCEPT
    #回路数据当然需要放开了
    /sbin/iptables -A INPUT -i lo -j ACCEPT
    /sbin/iptables -A OUTPUT -o lo -j ACCEPT
    #自已发的自己可以收
    /sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    #开放80与22端口,不解释
    /sbin/iptables -A INPUT -p tcp -m multiport --dport 80,22 -j ACCEPT

    保存脚本文件后用

    # sh iptables.sh

    执行脚本。运行脚本之后最好检查一下:

    # iptables -nv -L

    脚本说明

    由于此Web服务器是置于负载均衡器后面,所以我们要允许数据源地址为负载均衡器的数据包通过:

    iptables -A INPUT -s 122.70.x.x -j ACCEPT

    如果配置了Nagios等监控系统的话在这里也要加上,如果监控和LB都没做的话,这行可以不用。

    另外,我的许多基于LNMP的小网站上面也部署了此脚本,由于Web服务和MySQL数据库同时安装在一台机器上,所以没有开放3306端口。

    在本脚本中,我们配置了一些安全措施,以防止外部的ping和SYN洪水攻击,并且考虑到外部的疯狂端口扫描软件可能会影响服务器的入口带宽,所以在这里也做了限制:

    iptables -A INPUT -p tcp --syn -m limit --limit 100/s --limit-burst 100 -j  ACCEPT

    上面的命令每秒钟最多允许100个新连接。请注意这里的新连接指的是state为New的数据包,在后面我们也配置了允许状态为ESTABLISHED和RELATED的数据通过;另外,100这个阀值则要根据服务器的实际情况来调整,如果是并发量不大的服务器这个数值就要调小,如果是访问量非常大且并发数不小的服务器,这个值则还需要调大。

    iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s –limit-burst 10 -j ACCEPT

    这是为了防止ping洪水攻击,限制每秒的ping包不超过10个。

    iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 20/sec --limit-burst 200 -j ACCEPT

    上面的命令防止各种端口扫描,将SYN及ACK SYN限制为每秒钟不超过200个,免得把数务器带宽耗尽了。

    后续加固工作

    iptables防火墙运行后,运行nmap工具进行扫描:

    # nmap -P0 -sS 211.143.6.x
    Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2009-03-29 16:21 CST
    Interesting ports on 211.143.6.X:
    Not shown: 1668 closed ports
    PORT     STATE SERVICE
    22/tcp   open   ssh
    25/tcp   open   smtp
    80/tcp   open   http
    110/tcp   open   pop3
    111/tcp   open   rpcbind
    143/tcp   open   imap
    443/tcp   open   https
    465/tcp   open   smtps
    587/tcp   open   submission
    993/tcp   open   imaps
    995/tcp   open   pop3s
    1014/tcp  open   unknown

    在这里,我们发现一个1014端被某个进程打开了,用lsof -i:1014查看发现是rpc.statd打开的,这服务每次用的端口都不一样啊!本来想置之不理的,但是如果rpc.statd不能正确处理SIGPID信号,远程攻击者可利用这个漏洞关闭进程,进行拒绝服务攻击,所以还是得想办法解决掉。我们发现rpc.statd是由服务nfslock开启的,进一步查询得知它是一个可选的进程,它允许NFS客户端在服务器上对文件加锁。这个进程对应于nfslock服务,于是我们关掉了此服务:

    service nfslock stop
    chkconfig nfslock off

    最后想说的是,如果没有硬件防火墙保护的话,请尽量在每一台有公网IP的机器上部署iptables防火墙吧!

  • 相关阅读:
    HTTP状态详解
    表锁和行锁
    memcache 加载(对象)所遇到的问题。资源
    php 数据导出csv 注意问题。
    文件不存在的话创建文件 文件上传所遇到的问题、
    获取文件的后缀名。phpinfo
    手机访问pc网站自动跳转手机端网站代码
    计算机网络学习-20180826
    计算机网络学习-20180811
    集线器和交换机的区别
  • 原文地址:https://www.cnblogs.com/littlehb/p/2356396.html
Copyright © 2020-2023  润新知