之前搬主题有介绍利用系统的自带防火墙手动封IP的教程,有的人觉得很麻烦,这里搬主题再分享一下在CentOS上使用iptables自动封IP及配合ipset自动封IP教程。如果利用好的话,实际是功能很强大的。Linux上用iptables自动封ip的bash脚本,这个还是有一定效果的。CentOS 内置了一个非常强劲的防火墙,统称为 iptables,但更正确的名称是 iptables/netfilter。iptables 是一个用户空间的模块。作为用户,你在命令行就是通过它将防火墙规则放进缺省的表里。netfilter 是一个核心模块,它内置于内核中,进行实际的过滤。iptables 有很多前端图像界面可以让用户新增或定义规则,但它们很多时不及使用命令行般有灵活性,而且限制用户了解实际发生的事情。1. 安先装iptables这里搬主题就不多描述了,如果是CentOS 6的话,自带iptables防火墙,如果是CentOS 7的话,那还需要卸掉原有防火墙,然后安装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 &以上是封少量的IP的教程,但是大家知道,iptables封掉少量ip处理是没什么问题的,但是当有大量ip攻击的时候性能就跟不上了,iptables是O(N)的性能。而ipset就像一个集合,把需要封闭的ip地址放入这个集合中,ipset 是O(1)的性能,用的hash方式所以特别快。之前搬主题也介绍了【WordPress设置CDN被CC攻击设置防火墙封IP防护图文教程】一、软件及安装 1、iptables(一般Linux都已经安装好的) 2、ipset:ubuntu:apt-get install ipset二、ipset的使用1、查看ip集的列表信息ipset list2、创建ip集ipset create XXXX hash:ip maxelem 100000 timeout 3600XXXX:ip集的名字hash:ip :为指定类型,还有其他好些类型,比如hash:net,hash:net,net等,具体可以man ipset100000:为最大保存ip的数量 timeout: 为封闭ip的默认时间,这个参数可以不写,这样就永不解封,除非手动解封3、增加ip地址到ip集ipset add xxxx 1.1.1.1增加网段ipset add xxxx 1.1.1.0/244、删除指定的ip或网段ipset del xxxx 1.1.1.1
ipset del xxxx 1.1.1.0/245、保存ip集到文件ipset save xxxx>ipset_list.txt6、还原ip集ipset restore /tmp/ips
grep ${DATE} ${FILES}|grep -i passwd|awk -F'|' '{print $3}'|sort -n|uniq>/tmp/ippwd
NUM=`awk '{print $1}' /tmp/ips`
IP=`awk '{print $2}' /tmp/ips`
IP2=`cat /tmp/ippwd`
threshold=1000
if [[ $NUM -gt $threshold ]];then
/sbin/ipset -! add forbidip $IP timeout 3600
fi
if [ -s /tmp/ippwd ];then
for i in $IP2
do
/sbin/ipset -! add forbidip $i
done
fi4、脚本自动运行在crontab中添加此脚本的自动运行*/1 * * * * bash /path/to/script.sh
THE END