虚拟化容器,大数据,DBA,中间件,监控。

linux自动屏蔽IP

08 10月
作者:admin|分类:系统运维

linux自动屏蔽IP

服务器遭受SYN_RECV攻击时,也许下边的小工具Firewall.sh能派上用场。

内容如下:

====================================================================
#!/bin/sh
# this program is used to check tcp/ip connections
# and block those ip with excessive connections

# my version
myver="1.0RC1"

# wake up every 120s if last check found abuse client
wakeup_time_min=120

# wake up every 300s if last check found no abuse client
wakeup_time_max=300

# rule timeout 3600s
rule_timeout=3600

# check port list
portlist="80"

# max established connection per ip
max_active_conn=8

# iptables chain name
iptables_chain_name="RH-Lokkit-0-50-INPUT"

# log facility
log_facility="local0"

# Block policy
ipchains_block_policy="DENY"
iptables_block_policy="REJECT"

# myself
myself=`basename $0`

mylogger_info()
{
logger -p $log_facility.info -t $myself $@ 2>/dev/null
}

mylogger_debug()
{
logger -p $log_facility.debug -t $myself $@ 2>/dev/null
}

mylogger_notice()
{
logger -p $log_facility.notice -t $myself $@ 2>/dev/null
}

dotimeout()
{
mylogger_info "reset firewall when timeout arrives"
case "$firewall" in
ipchains)
    /etc/init.d/ipchains restart 1>/dev/null 2>/dev/null
    if [ $? = 0 ] ; then
       mylogger_info "ipchains restarted"
    else
       mylogger_notice "ipchains restart failed"
    fi
    ;;
iptables)
    /etc/init.d/iptables restart 1>/dev/null 2>/dev/null
    if [ $? = 0 ] ; then
       mylogger_info "iptables restarted"
    else
       mylogger_notice "iptables restart failed"
    fi
    ;;
*)
    mylogger_notice "neither ipchains nor iptables"
    ;;
esac
  
}

blockclient()
{
if [ -z "$1" ] || [ -z "$2" ]; then
   mylogger_notice "blockclient() missing client or port to block"
   return
fi
local ip port

ip=$1
port=$2

case "$firewall" in
ipchains)
    mylogger_notice "blocking $1 to $2 via ipchains"
found=`ipchains -nL | egrep "^$ipchains_block_policy.*[[:space:]]+$ip[[:space:]]+.*[[:space:]]+/->[[:space:]]+$port"`
if [ -z "$found" ] ; then
cmd="ipchains -I input 1 -p tcp -s $ip -d 0/0 $port -j $ipchains_block_policy 1>/dev/null 2>/dev/null"
mylogger_debug "cmd: $cmd"
`ipchains -I input 1 -p tcp -s $ip -d 0/0 $port -j $ipchains_block_policy 1>/dev/null 2>/dev/null`
if [ $? != 0 ] ; then
mylogger_notice "$cmd call failed"
return
fi
new_block=1
ever_block=1
else
mylogger_info "$ip already blocked to $port"
fi
    ;;
iptables)
    mylogger_notice "blocking $1 to $2 via iptables"
found=`iptables -nL | egrep "^$iptables_block_policy.*[[:space:]]+$ip[[:space:]]+.*[[:space:]]+dpt:$port[[:space:]]+"`
if [ -z "$found" ] ; then
cmd="iptables -I $iptables_chain_name 1 -p tcp -m tcp -s $ip --dport $port -j $iptables_block_policy 1>/dev/null 2>/dev/null"
mylogger_debug "cmd: $cmd"
`iptables -I $iptables_chain_name 1 -p tcp -m tcp -s $ip --dport $port -j $iptables_block_policy 1>/dev/null 2>/dev/null`
if [ $? != 0 ] ; then
mylogger_notice "$cmd call failed"
return
fi
new_block=1
ever_block=1
else
mylogger_info "$ip already blocked to $port"
fi
    ;;
*)
    mylogger_notice "neither ipchains nor iptables"
    ;;
esac
}

restartservice()
{
local service
if [ -z "$1" ] ; then
mylogger_notice "no port given to see which service to be restart"
return
fi

case "$1" in
80)
    service="httpd"
    ;;
25)
    service="postfix"
    ;;
110)
    service="courier-pop3d"
    ;;
21)
    service="muddleftpd"
    ;;
53)
    service="named"
    ;;
3306)
    service="mysqld"
    ;;
esac
if [ ! -z "$service" ] ; then
/etc/init.d/$service restart 1>/dev/null 2>/dev/null
if [ $? = 0 ] ; then
    mylogger_notice "$service restarted"
else
    mylogger_notice "$service restart failed"
fi
fi
}

docheckport()
{
mylogger_info "do check port $1"
local port last_client count client total_count

if [ -z "$1" ] ; then
mylogger_notice "docheckport() port not given"
return
fi

port=$1

clientlist=`netstat -an --tcp| grep ESTABLISHED | awk "{ if ( index(//$4,/":$port/") ) print //$5}" | awk -F ':' '{print $1}'|sort`
if [ $? != 0 ] ; then
mylogger_notice "netstat call failed"
return
fi
#echo $clientlist
# reset new_block
new_block=0
count=0
total_count=0
last_client=""
for client in $clientlist
do
#echo "client is $client"
if [ -z "$last_client" ] ; then
    count=$((count+1))
    total_count=$((total_count+1))
    last_client=$client
else
    if [ "$client" = "$last_client" ] ; then
      count=$((count+1))
      total_count=$((total_count+1))
    else
      mylogger_debug "$last_client $count connections"
      if [ $count -ge $max_active_conn ] ; then
         mylogger_notice "client $last_client connection $count >= $max_active_conn"
         blockclient $last_client $port
      fi
      count=1
      total_count=$((total_count+1))
      last_client=$client
    fi
fi
done
# check the last client
if [ ! -z "$client" ] ; then
count=$((count+1))
total_count=$((total_count+1))
mylogger_debug "$client $count connections"
if [ $count -ge $max_active_conn ] ; then
    mylogger_notice "client $client connection $count >= $max_active_conn"
    blockclient $client $port
fi
fi
mylogger_info "total connections on port $port: $total_count"

if [ $new_block = 1 ] ; then
restartservice $port
fi
}

docheckall()
{
# reset wakeup_time
wakeup_time=$wakeup_time_max
for port in $portlist
do
docheckport $port
if [ $new_block = 1 ] ; then
    # set wakeup_time shorter cause we found some abuse client
    wakeup_time=$wakeup_time_min
fi
done
}

if [ -z "$firewall" ] && [ -f /etc/sysconfig/ipchains ] ; then
firewall="ipchains"
fi

if [ -z "$firewall" ] && [ -f /etc/sysconfig/iptables ] ; then
firewall="iptables"
fi

if [ -z "$firewall" ] ; then
echo "Error: This machine does not have ipchains or iptables firewall support"
exit 1
fi

mylogger_info "firewall.sh v$myver starting"
mylogger_info "Firewall is:           $firewall"
mylogger_info "Port protected:        $portlist"
mylogger_info "Max connection per ip: $max_active_conn"
mylogger_info "Min time to check:     $wakeup_time_min""s"
mylogger_info "Max time to check:     $wakeup_time_max""s"
mylogger_info "Timeout circle:        $rule_timeout""s"
mylogger_info "Output is logged to:   $log_facility"

# if new ip blocked at this check run?
new_block=0
# if new ip blocked at this timeout run?
ever_block=0
# reset wakeup_time
wakeup_time=$wakeup_time_max

lasttime=`date +%s`

while [ 1 ]
do
curtime=`date +%s`
timediff=$((curtime-lasttime))
#echo "timediff: $timediff"
if [ $timediff -ge $rule_timeout ] && [ $ever_block = 1 ] ; then
lasttime=$curtime
ever_block=0
dotimeout
fi
docheckall
mylogger_info "sleep for $wakeup_time""s"
sleep $wakeup_time
done
====================================================================

帮助说明:firewall.sh 1.0b

1. 说明
firewall.sh是一个shell脚本程序,每隔一段时间检查tcp连接的统计信息,如果来自某个ip对某个端口的活动连接超过规定的最大数量,
则自动将该IP对该端口的访问屏蔽,并重新启动相应的服务。再每隔一段时间,会重设防火墙到初始状态。
该程序可以同时保护多个端口

2. 安装
tar zxf firewall-1.0b.tar.gz
cd firewall-1.0b
install -m 700 firewall.sh /usr/prima/sbin/firewall.sh

3. 配置
主要配置项目如下:
# 最小检查周期,缺省为120秒
wakeup_time_min=120

# 最大检查周期,缺省为300秒
wakeup_time_max=600

# 重设防火墙状态的时间,缺省为3600秒
rule_timeout=3600

# 保护的端口列表,缺省为80和25,支持的其他端口包括21(ftp), 110(pop3), 53(named), 3306(mysql)
# 一般的网络攻击都是针对80和25,又以80居多
portlist="80 25"

# 每个ip可占用的最大活动(Established)连接数
max_active_conn=8

# iptables防火墙规则链名称,必须和/etc/sysconfig/iptables中一致
# 如果用的是ipchains,可以忽略此项
iptables_chain_name="RH-Lokkit-0-50-INPUT"

# 日志输出目标
log_facility="local0"

**** 关于检查周期 ****
程序定义了两个检查周期,如果上次检查中屏蔽了某个IP,则程序会更频繁地检查连接情况,反之则等待更长时间。通过检查周期
的动态调整,可以有效调度在遭受攻击和正常状态下程序的运行次数。

**** ipchains vs iptables ****
目前该程序支持ipchains和iptables两种软件防火墙,使用何种是由程序启动时自动检测的。如果/etc/sysconfig/ipchains和
/etc/sysconfig/iptables都没有检测到,则报错退出。

**** 日志输出 ****
程序的输出信息记录在系统日志中,目标是local0。如果没有特殊配置,可以在/var/log/messages中看到。建议在/etc/syslog.conf
中加入一条:
local0.*                        /var/log/firewall.log
然后重新启动syslog
/etc/init.d/syslog restart
这样,可以将firewall.sh输出的日志单独记到文件/var/log/firewall.log里。

4. 运行
/usr/prima/sbin/firewall.sh &

范例输出:
*** firewall.sh v1.0b ValueOf.com***
Firewall is:           ipchains
Port protected:        80 25
Max connection per ip: 8
Min time to check:     120s
Max time to check:     300s
Timeout circle:        3600s
Output is logged to:   local0

察看/var/log/firewall.log,可以看到:
Oct 16 14:08:55 server firewall.sh: do check port 80                            // 检查80端口
Oct 16 14:08:55 server firewall.sh: 192.168.0.60 2 connections                  // 有两个来自192.168.0.60的连接
Oct 16 14:08:55 server firewall.sh: total connections on port 80: 2             // 80端口总共2个连接
Oct 16 14:08:55 server firewall.sh: do check port 25                            // 检查25端口
Oct 16 14:08:55 server firewall.sh: total connections on port 25: 0             // 25端口没有连接
Oct 16 14:08:55 server firewall.sh: sleep for 300s                              // 等待300秒

5. 停止
先用ps命令察看firewall.sh进程的进程号,然后用kill命令将其终止,如
# ps auxww|grep firewall.sh
root     27932 0.0 0.5 2312 1060 pts/2    S    12:38   0:00 /bin/sh /usr/prima/sbin/firewall.sh
root     27967 0.0 0.3 1732 592 pts/2    S    12:39   0:00 grep firewall.sh
第一行即firewall.sh的进程,用kill命令:
# kill 27932
[1]    Terminated                    /usr/prima/sbin/firewall.sh
即将其终止


浏览2765 评论0
返回
目录
返回
首页
zabbix1.8详细安装过程。 通过脚本自动屏蔽非法IP