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 &