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 &