怎样在CentOS上使用iptables自动封IP

2016年2月26日 | 分类: 【技术】, 【项目】

linux上用iptables自动封ip的bash脚本,这个还是有一定效果的。

CentOS 内置了一个非常强劲的防火墙,统称为 iptables,但更正确的名称是 iptables/netfilter。iptables 是一个用户空间的模块。作为用户,你在命令行就是通过它将防火墙规则放进缺省的表里。netfilter 是一个核心模块,它内置于内核中,进行实际的过滤。iptables 有很多前端图像界面可以让用户新增或定义规则,但它们很多时不及使用命令行般有灵活性,而且限制用户了解实际发生的事情。

参考资料:《linux上用iptables自动封ip的bash脚本》
参考资料:《在 Redhat / CentOS Linux 中安装 iptables 防火墙》
参考资料:《linux下IPTABLES配置详解》
参考资料:《IPTables》

1. 安先装iptables

2. 下面的脚本保存为drop_ips.sh

#!/bin/bash                        
     
    ###########################################
    # 封锁ip 用iptables                 
    # usage:                            
    # 
    # create date 2010-11-11            
    # update date 2010-11-12            
    ###########################################
     
     
    # 定义端口                          
    CHK_PORT="80 25" 
     
    # 定义输出文件                      
    IPTABLE_OUTPUT=/tmp/ip_drop_tables  
    # 定义输出文件备份  
    IPTABLE_OUTPUT_BAK=/tmp/ip_drop_tables.bak  
     
    # 扫描ip的 间隔时间  
    SCAN_HTTP_IP_TIMEOUT=20  
     
    # 处理ip的间隔时间  
    HANDLE_IP_TIMEOUT=120  
     
    # 连接数量最大限制  
    MAX_CONNECT_IP_NUM=100  
     
    # 排除在外的ip  
    ACCEPT_IP="203.95.110.2" 
     
    # 已经封锁的ip   
    DROP_IP_RECORD_FILE=/tmp/drop_ip_record  
     
    #################################################################  
    #定义方法  
    #################################################################  
    # 输出ip到文件  
    output_ip_table()  
    {  
            # 拿到端口号  
            port_num=$1  
            # 查此端口上的连接ip 输出到指定的目录  
            #echo "start scan ......"  
            netstat -na --tcp| grep ESTABLISHED | awk '{ if ( index($4,":"'"$port_num"'"") ) print $5}' | awk -F ':' '{print $1}' | sort  >> $IPTABLE_OUTPUT  
            #echo "scan end ......"  
    }  
     
     
    # 把需要观测端口列出                                 
    check_port()  
    {  
            for port_td in $CHK_PORT  
            do 
            # echo "port : "$port_td  
                # 扫描此端口  
            output_ip_table $port_td  
        done  
    }  
     
     
    # 封杀ip  
    drop_ip_from_table()  
    {  
        iptables -I INPUT -s "$1" -j DROP  
    }  
     
    # 排除ip  
    accept_ip()  
    {  
        for access_ip in $ACCEPT_IP  
        do 
            iptables -I INPUT -s "$access_ip" -j ACCEPT  
        done  
    }  
     
    # 提取需要的ip  
    get_iptable()  
    {  
        # 如果已经存在就删除  
        if [ -e $IPTABLE_OUTPUT_BAK ] ; then  
            rm -rf $IPTABLE_OUTPUT_BAK  
        fi  
        # copy 一份出去   
        cp $IPTABLE_OUTPUT $IPTABLE_OUTPUT_BAK  
        # 排序 数组  
        declare -a ip_array_org=($(cat ${IPTABLE_OUTPUT_BAK} | sort))  
        # 循环  
        # 比对用的ip 初始化  
        tmp_ip=0.0.0.0  
        let "tmp_ip_count=1" 
        for tmp_element in "${ip_array_org[@]}" 
        do            
            # 初始化 没有特殊设置为排除ip  
            is_not_set_accept="true" 
            # 初始化 是否已封杀了  
            is_not_drop="true" 
            # 如果相等  
            if [ "$tmp_ip" = "$tmp_element" ] ; then   
                let "tmp_ip_count+=1" 
            else              
                # 打印  
                echo "ip: $tmp_ip count: $tmp_ip_count"   
                # 如果大于某个数字 就封杀  
                if (( $tmp_ip_count >= $MAX_CONNECT_IP_NUM )) ; then  
                    # 如果没有记录就封杀  
                    if  cat /tmp/drop_ip_record | grep "$tmp_ip" > /dev/null   ; then  
                        echo "this ip $tmp_ip has been mask !" 
                        is_not_drop="false" 
                    else      
                        # 循环 需要排除ip  
                            for tmp_access_ip in $ACCEPT_IP  
                        do 
                            # 如果排除ip里有 就去封锁此ip  
                            if [ "$tmp_access_ip" = "$tmp_ip" ] ; then   
                                echo "this ip $tmp_ip was mark to accept !" 
                                is_not_set_accept="false" 
                            fi  
                        done   
                    fi  
                    if [ $is_not_set_accept = "true" ] && [ $is_not_drop = "true"] ; then  
                        echo "add a new ip to drop : $tmp_ip" 
                        drop_ip_from_table $tmp_ip  
                        # 记录ip  
                        echo "$tmp_ip" >> $DROP_IP_RECORD_FILE  
                    fi  
                fi  
                # 归零  
                let "tmp_ip_count=1" 
                tmp_ip=$tmp_element  
            fi  
        done  
        # 全部处理完了 删除原件  
        rm -rf $IPTABLE_OUTPUT  
        # 排除ip  
        # accept_ip  
          
    }  
     
    # 扫描ip  
    scan_http_access_ip()  
    {  
        # 获取当前时间作为开始时间  
        start_time=`date +%s`  
            # 循环开始    
        while true 
        do 
            # 开始检查 扫描ip  
            check_port  
            # 线程停止  
            sleep $SCAN_HTTP_IP_TIMEOUT  
            # 获取当前时间  
            cur_time=`date +%s`  
            # 时间差  
            let "time_out=$cur_time-$start_time" 
            echo "time_out : "$time_out  
            # 超过2分钟  
            if (( $time_out >= $HANDLE_IP_TIMEOUT )) ; then  
                # 整理一次ip表  
                echo " times up"              
                get_iptable           
                # 重置开始时间  
                start_time=`date +%s`  
            fi  
        done      
    }  
     
    # 程序执行入口  
    main_app()  
    {  
        # 定时扫描ip  
        scan_http_access_ip  
    }  
     
    main_app 

然后执行下面的脚本,让其自动在后台运行

sh ~/scripts/drop_ips.sh &