| deserts |
2008-01-26 02:12 |
另存为 firewall.sh 给执行的权限 "TJ^Z! ..TjEBp #!/bin/sh !|c5@0Wr # this program is used to check tcp/ip connections BniVZCct # and block those ip with excessive connections g(H3arb& }TL"v|ny6; # my version #8OqX*/ myver="1.0RC1" r= aQS5 rWqA)j*!
# wake up every 120s if last check found abuse client $?{zV$r1 wakeup_time_min=120 9ksrr{tW ksp':2d} # wake up every 300s if last check found no abuse client GqxK|G1 wakeup_time_max=300 1*jm9])# P'~3WL4MKs # rule timeout 3600s o]U== rule_timeout=3600 a$:N9&P l}/UriZ0 # check port list i`L66uV portlist="80" ;A!i V| mJ7kOQ-.$ # max established connection per ip ?,C,q5
T\ max_active_conn=8 r
|/9Dn% V485Yn!$( # iptables chain name LJ3UB iptables_chain_name="RH-Lokkit-0-50-INPUT" ')c
u/ wf1DvsJQ
l # log facility {*9i}w|2 log_facility="local0" UUq9UV-h D(|$6J 0 # Block policy WcFZRy-erc ipchains_block_policy="DENY" HfPeR8I%i iptables_block_policy="REJECT" ;@hP*7Lm
H'.eqZM # myself C@i g3fhV myself=`basename $0` QNFrkel ~Y[1Me mylogger_info() dX=^>9hN/ { add-]2` logger -p $log_facility.info -t $myself $@ 2>/dev/null =fPO0Ot; } uItKs u #Uu"olX7 mylogger_debug() RI=B(0A { l M$7/ logger -p $log_facility.debug -t $myself $@ 2>/dev/null 8J0tya"z } =g:\R$lQ ->(B:Cz mylogger_notice() K]l)z* I { 14R))Dz" logger -p $log_facility.notice -t $myself $@ 2>/dev/null .B*)A. } nj[6c K VCS(oN dotimeout() $&!U&uMt { :>k\uW mylogger_info "reset firewall when timeout arrives" X)~-MY*p case "$firewall" in JY,+eD ipchains) 6
FE[snw /etc/init.d/ipchains restart 1>/dev/null 2>/dev/null ]2jnY&a5 if [ $? = 0 ] ; then ]rS+v^@QH mylogger_info "ipchains restarted" yT4|eHl else
|8B[yr.b mylogger_notice "ipchains restart failed" C6`8dn
fi `6/7},"9t ;; /%)J+K) iptables) `PL!>o
a(8 /etc/init.d/iptables restart 1>/dev/null 2>/dev/null \0$?r4A if [ $? = 0 ] ; then LM}si|
mylogger_info "iptables restarted" >\'yj|
U, else _?ym,
@}# mylogger_notice "iptables restart failed" 2+enRR~ fi ll#PCgIm
;; Buo1o&& *) wv<"W@& 9 mylogger_notice "neither ipchains nor iptables" \h-[u% ;; EQ28pAZ esac Gi-tf< Ul=`]@]] } -+L1Hid.7 p"T4;QBxQ blockclient() Q~9:}_@ { `27? f
$, if [ -z "$1" ] || [ -z "$2" ]; then 9u9#&xx mylogger_notice "blockclient() missing client or port to block" /4|qfF3 return h41v}5
!- fi cIgF]My*D@ local ip port yY1&hop M! s&<Bi ip=$1 ,Zdc port=$2 +h
=lAHn& FOZqN K case "$firewall" in wtY#8'^$& ipchains) B *:6U+I mylogger_notice "blocking $1 to $2 via ipchains" xTe?* found=`ipchains -nL | egrep "^$ipchains_block_policy.*[[:space:]]+$ip[[:space:]]+.*[[:space:]]+\->[[:space:]]+$port"` O6`@'N>6P if [ -z "$found" ] ; then -X |G cmd="ipchains -I input 1 -p tcp -s $ip -d 0/0 $port -j $ipchains_block_policy 1>/dev/null 2>/dev/null" 0c]Lm?& mylogger_debug "cmd: $cmd" !_]WUQvV? `ipchains -I input 1 -p tcp -s $ip -d 0/0 $port -j $ipchains_block_policy 1>/dev/null 2>/dev/null` _h5@3>b3r if [ $? != 0 ] ; then t+vn.X+& mylogger_notice "$cmd call failed" W2n%D& PE return W
nVX)o fi VQX#P< new_block=1 iKDGYM ever_block=1 7Npz
{C{I else 8Uc#>Ae'_ mylogger_info "$ip already blocked to $port" N
^)L@6 fi fx9c1h9s ;; MJK L4 G iptables) *s_)E2 mylogger_notice "blocking $1 to $2 via iptables" 9ah,a 4 found=`iptables -nL | egrep "^$iptables_block_policy.*[[:space:]]+$ip[[:space:]]+.*[[:space:]]+dpt:$port[[:space:]]+"`
pO"V9[p] if [ -z "$found" ] ; then '*2
2j ] 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" S9mj/GpL3 mylogger_debug "cmd: $cmd" #.) qQ8*( `iptables -I $iptables_chain_name 1 -p tcp -m tcp -s $ip --dport $port -j $iptables_block_policy 1>/dev/null 2>/dev/null` KaOS!e' if [ $? != 0 ] ; then Y,?rykRj mylogger_notice "$cmd call failed" c,e
0+ return #SQFI;zj fi TC ^EyjD new_block=1 3pm;?6i6 ever_block=1 L7 qim.J else pi+m`O mylogger_info "$ip already blocked to $port" :)bm+xWFF fi 8j8FQ!M ;; !x|Ok'izDL *) Da
aLRMQ= mylogger_notice "neither ipchains nor iptables" M" %w9)@ ;; v dyu =*Y esac _v<EFal } {R]4N]l> "w=.2A:q restartservice() S_aml { eZT923tD local service u9QvcD^'z if [ -z "$1" ] ; then 3-srt^>w* mylogger_notice "no port given to see which service to be restart" {dhG
SM7 return #%Uk}5;- fi vfm|?\ @~xNax&^ case "$1" in /N]?>[<NW 80) C4]vq+ service="httpd" ^. M*pe ;; zuwCN. 25) MW6d- service="postfix"
D`2Iy.|! ;; NAlYfbp 110) >y
&9!G service="courier-pop3d" X~G!{TT_x6 ;; 2mWW0txil 21) e@F9'z4 service="muddleftpd" f)~urGazS ;; Rku9? zf^ 53) EQET:a:g service="named" X~T"n<:a> ;; C2<!
.l 3306) Kzfa4C service="mysqld" " +'E ;; }PTYNidlR esac k,LeBCqGcb if [ ! -z "$service" ] ; then TW8E^k7 /etc/init.d/$service restart 1>/dev/null 2>/dev/null |X,T>{V?y if [ $? = 0 ] ; then za` mylogger_notice "$service restarted" sk.<|-(o else _=Ed>2M)no mylogger_notice "$service restart failed" >gtKyn] fi bwR24>8lP fi V\^3I7F } q$ (@ (iXo\y`z docheckport() T0J"Wr>WY { *,A?lX,9A mylogger_info "do check port $1" s-!Bpr16o0 local port last_client count client total_count F:"<4hiA" NHG+l)y: if [ -z "$1" ] ; then G%_6"s mylogger_notice "docheckport() port not given" Yq-N
k:H| return #05#@v8.f fi 484lB}H >DeG//rv port=$1 !r]elX P~$FgAV clientlist=`netstat -an --tcp| grep ESTABLISHED | awk "{ if ( index(\\$4,\":$port\") ) print \\$5}" | awk -F ':' '{print $1}'|sort` ;O5p>o if [ $? != 0 ] ; then b1Bu5%bt,: mylogger_notice "netstat call failed" m_{OCHS+ return ;`Eie2y{M fi |d\rCq > #echo $clientlist {Hxvt~P # reset new_block HQlhT new_block=0 lX$6U|! count=0 s\A"B#9r total_count=0 8q*MhH>6I last_client="" -S5M>W.Qb{ for client in $clientlist #
~SuL3 do *ILx-D5qr #echo "client is $client"
d1$3~Xl] if [ -z "$last_client" ] ; then VU6nu4 count=$((count+1)) _X5@%/Vz total_count=$((total_count+1)) <>\s#Jf/ last_client=$client pJkaP else vM@2C'
if [ "$client" = "$last_client" ] ; then ?0k(wiF count=$((count+1)) 2K?~)q&t* total_count=$((total_count+1))
j.UQLi&` else pGEYke NU mylogger_debug "$last_client $count connections" ` QC if [ $count -ge $max_active_conn ] ; then $%~-p[)<(P mylogger_notice "client $last_client connection $count >= $max_active_conn" {*WJ"9ujp] blockclient $last_client $port
M ,qX fi t<S]YA~N' count=1 bH+x `]{A total_count=$((total_count+1)) ds@X%L;_ last_client=$client A$*#n8, fi ie4keVlXc fi qFEGV+ done a#H2H`% # check the last client %JmRJpCvR if [ ! -z "$client" ] ; then J[E_n;d1 count=$((count+1)) 3I!xa*u total_count=$((total_count+1)) s|iph~W!L mylogger_debug "$client $count connections" !<9sOvka{ if [ $count -ge $max_active_conn ] ; then #T\Yi|Qs# mylogger_notice "client $client connection $count >= $max_active_conn" QoZ7l]^ blockclient $client $port |Z%I3-z_DS fi @\-i3EhR fi a& >(*PQ mylogger_info "total connections on port $port: $total_count" |,zcrOo] f8]Qn8 if [ $new_block = 1 ] ; then rMDo5Z2 restartservice $port 5rG&Z5 fi ENu`@S='I3 } cd8ZZ8L +<p?i]3CHe docheckall() dc#Db~v}k { Z4S0{:XY # reset wakeup_time X8!=Xjl) wakeup_time=$wakeup_time_max *2M
M for port in $portlist U)oH@/q do )c9]}:W& docheckport $port U3SF'r8 if [ $new_block = 1 ] ; then {0(:7IY, # set wakeup_time shorter cause we found some abuse client S<n3wR"^ wakeup_time=$wakeup_time_min d~L`*"/)[ fi nnBgTtsC] done .E!p } M1._{Jw5
(W~jr-O^ if [ -z "$firewall" ] && [ -f /etc/sysconfig/ipchains ] ; then Q;O\tl firewall="ipchains" 7?6?`no~JJ fi jRz2l`~7# wv,,#P if [ -z "$firewall" ] && [ -f /etc/sysconfig/iptables ] ; then ]+\@
_1<ZI firewall="iptables" 'BT}'qN fi x}TDb0V HgG-r&r!2 if [ -z "$firewall" ] ; then a,Gd\.D echo "Error: This machine does not have ipchains or iptables firewall support" &s!"pEZWck exit 1 Y""-U3;T~ fi 9kPwUAw 9%\<x mylogger_info "firewall.sh v$myver ValueOf.com starting" W>b(hVBE
mylogger_info "Firewall is: $firewall" y:!MWZ mylogger_info "Port protected: $portlist" t1HUp dHY mylogger_info "Max connection per ip: $max_active_conn" 02X ~' To" mylogger_info "Min time to check: $wakeup_time_min""s" i|>K
mylogger_info "Max time to check: $wakeup_time_max""s" ,hK0F3?H> mylogger_info "Timeout circle: $rule_timeout""s" Du>dTi~ mylogger_info "Output is logged to: $log_facility" <!:,(V>F(C Z,o*M#} # if new ip blocked at this check run? ssW+'GD new_block=0 7Z>u|L($m # if new ip blocked at this timeout run? |0(Z)s, ever_block=0 i;^
e6A> # reset wakeup_time
q`09 wakeup_time=$wakeup_time_max wgSA6mQZ KdFQlQaj lasttime=`date +%s` #{(?a.: ?/"@WP9 while [ 1 ] P*/p x4;6 do .hgc1 curtime=`date +%s` :c,\8n timediff=$((curtime-lasttime)) xZFha=# #echo "timediff: $timediff" Js qze'BGY if [ $timediff -ge $rule_timeout ] && [ $ever_block = 1 ] ; then O7j$bxk/^ lasttime=$curtime !.L%kw7z ever_block=0 wpY%"x#-+= dotimeout -]5dD VSO fi mT@UQC
G docheckall IGql^,b mylogger_info "sleep for $wakeup_time""s" a#! Vi93 sleep $wakeup_time /{7x|ay] done IJq$GR ,{itnKJC {^9,Dy_D =0,")aa! 1. 说明 0$&Z_oJ firewall.sh是一个shell脚本程序,每隔一段时间检查tcp连接的统计信息,如果来自某个ip对某个端口的活动连接超过规定的最大数量, /j
-LW1:N 则自动将该IP对该端口的访问屏蔽,并重新启动相应的服务。再每隔一段时间,会重设防火墙到初始状态。 /.05rTpp 该程序可以同时保护多个端口 GfQMdLy\Z ~n]:f7?I 2. 安装
30FYq? tar zxf firewall-1.0b.tar.gz ]S,I}NP cd firewall-1.0b }?*:uf install -m 700 firewall.sh /usr/prima/sbin/firewall.sh |\?-k Ew4DumI 3. 配置 QEUg=*3W= 主要配置项目如下: 3KB)\nF#% # 最小检查周期,缺省为120秒 y+Q!4A wakeup_time_min=120 Fxv~;o# l:Ci'= # 最大检查周期,缺省为300秒 } M'\s wakeup_time_max=600 k>VP<Zm13 CNbrXN # 重设防火墙状态的时间,缺省为3600秒 mg'-]>$ $] rule_timeout=3600 _PNU*E%s< HW.S~eLw* # 保护的端口列表,缺省为80和25,支持的其他端口包括21(ftp), 110(pop3), 53(named), 3306(mysql) A!iH g__/t # 一般的网络攻击都是针对80和25,又以80居多 8Mws?]\/q portlist="80 25" aeSy,: ]3
0
7. # 每个ip可占用的最大活动(Established)连接数 9IMRWtZWT max_active_conn=8 c~RElL 5Odi\SJ& # iptables防火墙规则链名称,必须和/etc/sysconfig/iptables中一致 1Lj\"+. # 如果用的是ipchains,可以忽略此项 ( Y/
DMQ iptables_chain_name="RH-Lokkit-0-50-INPUT" >Cd%tIie* u#J5M # 日志输出目标 PJkMn log_facility="local0" )E6m}?
H5 ;HqK^[1\ **** 关于检查周期 **** .V/TVz!b 程序定义了两个检查周期,如果上次检查中屏蔽了某个IP,则程序会更频繁地检查连接情况,反之则等待更长时间。通过检查周期 K3
]hUe
# 的动态调整,可以有效调度在遭受攻击和正常状态下程序的运行次数。 m}
Yf6:cr 5r
zB"L **** ipchains vs iptables **** LgUaX 目前该程序支持ipchains和iptables两种软件防火墙,使用何种是由程序启动时自动检测的。如果/etc/sysconfig/ipchains和 |":^3 /etc/sysconfig/iptables都没有检测到,则报错退出。 D"A`b{z *vBcT.|, **** 日志输出 **** i"w$D{N 程序的输出信息记录在系统日志中,目标是local0。如果没有特殊配置,可以在/var/log/messages中看到。建议在/etc/syslog.conf t~
U:{g~ 中加入一条: L]HY*e local0.* /var/log/firewall.log h+Dg"j<[ 然后重新启动syslog aYPzN<"% /etc/init.d/syslog restart MHxv@1)K|Y 这样,可以将firewall.sh输出的日志单独记到文件/var/log/firewall.log里。 5[/*UtB
^lf;Lc 4. 运行 R
)?8A\<E /usr/prima/sbin/firewall.sh & xTAC&OCk^[ vRT1tOQ$ 范例输出: _Dk;U*2 *** firewall.sh v1.0b ValueOf.com*** b,318R8+G Firewall is: ipchains }GGFJ" Port protected: 80 25 &+*jTE Max connection per ip: 8 AV&W&$ Min time to check: 120s #~p1\['|M Max time to check: 300s pOS.`rSK Timeout circle: 3600s C@Wm+E~;8 Output is logged to: local0 \".3x
PkE qvYw[D#.
察看/var/log/firewall.log,可以看到: p=7kFv Oct 16 14:08:55 server firewall.sh: do check port 80 // 检查80端口 4H1s"mP< Oct 16 14:08:55 server firewall.sh: 192.168.0.60 2 connections // 有两个来自192.168.0.60的连接 @~a52'\ Oct 16 14:08:55 server firewall.sh: total connections on port 80: 2 // 80端口总共2个连接 J@yy2AZnO Oct 16 14:08:55 server firewall.sh: do check port 25 // 检查25端口 =|?w<qc Oct 16 14:08:55 server firewall.sh: total connections on port 25: 0 // 25端口没有连接 /{qr~7k,oQ Oct 16 14:08:55 server firewall.sh: sleep for 300s // 等待300秒 ^(&:=r.PC wetkmd 5. 停止 l"ih+%S 先用ps命令察看firewall.sh进程的进程号,然后用kill命令将其终止,如 Ye1P5+W( # ps auxww|grep firewall.sh ^M?uv{354 root 27932 0.0 0.5 2312 1060 pts/2 S 12:38 0:00 /bin/sh /usr/prima/sbin/firewall.sh A?6b)B/e? root 27967 0.0 0.3 1732 592 pts/2 S 12:39 0:00 grep firewall.sh q+LjWZ+O 第一行即firewall.sh的进程,用kill命令: M)3h 4yQ # kill 27932 ?rHc%H [1] Terminated /usr/prima/sbin/firewall.sh O`Z>Oon? 即将其终止 |
|