deserts |
2008-01-26 02:12 |
另存为 firewall.sh 给执行的权限 xyCcd= -mdPqVIJn: #!/bin/sh F<<H [,%0 # this program is used to check tcp/ip connections l),13"?C( # and block those ip with excessive connections 2_DtzY:= 'B:De"_(N # my version *#9kFz- myver="1.0RC1" $)a5;--W }i~ j"m # wake up every 120s if last check found abuse client /'+JP4mK wakeup_time_min=120 780MSFV8 7-B'G/PS/ # wake up every 300s if last check found no abuse client k( ^ b wakeup_time_max=300 +6E<+-N .v8=zi:7Y # rule timeout 3600s }Ec"& rule_timeout=3600 '*.};t~;"d ~qxc!k!w4 # check port list t')I c6.?i portlist="80" .6(i5K
.l'QCW9 # max established connection per ip `buTP?]4. max_active_conn=8 Dn!V)T |mX8fRh # iptables chain name 94/}@<d-= iptables_chain_name="RH-Lokkit-0-50-INPUT" rbWFq|(_ ;W:Q}[ # log facility RmCR"~ log_facility="local0" )E|Bb=% IHfqW? # Block policy sk/Mh8z ipchains_block_policy="DENY" dD!SgK [Jv iptables_block_policy="REJECT" c Ix(;[U BC+qeocg # myself !Zx>)V6. myself=`basename $0` % *hBrjbj .d,Zx mylogger_info() p`0Tpgi { co|0s+%PBq logger -p $log_facility.info -t $myself $@ 2>/dev/null #{a <{HX } zyE yZc? fk_i~K mylogger_debug() ^
T S\x/P { yo=d"*E4^ logger -p $log_facility.debug -t $myself $@ 2>/dev/null
%G*D0pE } oj, 'AU!xG6OQ mylogger_notice() %|~UNP$ { *BV .zbGm logger -p $log_facility.notice -t $myself $@ 2>/dev/null S3r\)5%; } el<nY"
c 'lF|F+8 dotimeout() 62q-7nV { - K{ID$!p mylogger_info "reset firewall when timeout arrives" B^Q#@[T case "$firewall" in (`N/1}vk ipchains) \GN5Sy]r /etc/init.d/ipchains restart 1>/dev/null 2>/dev/null VI4d/2e if [ $? = 0 ] ; then RL%{VE mylogger_info "ipchains restarted" @9L9c else ^/,s$dj mylogger_notice "ipchains restart failed" )8_0 d) fi fHiCuF ;; DRnXo-Aaj iptables) B sAglem /etc/init.d/iptables restart 1>/dev/null 2>/dev/null 6m]L{ buP if [ $? = 0 ] ; then
>Y:ouN~< mylogger_info "iptables restarted" !dGgLU_ else _i&\G}mrC mylogger_notice "iptables restart failed" TCYnErqk fi er_aol e ;; rtI4W *) /[IK[ mylogger_notice "neither ipchains nor iptables" FR&RIFy ;; zAH+{4lC+ esac gyPF!"!5dq Zqao4 } ,Ubnz 1osI~oNZ blockclient() BdceINI { XDn$=`2 if [ -z "$1" ] || [ -z "$2" ]; then @cx!m mylogger_notice "blockclient() missing client or port to block" au8)G_A return H;^6%HV1 fi \+,jM6l}- local ip port v4&*iT N9i>81tY ip=$1 /A>/
]2( port=$2 X9P-fF?0 FGZOn5U6'
case "$firewall" in kqyY:J ipchains) ]t,ppFC# mylogger_notice "blocking $1 to $2 via ipchains" rlds-j'' found=`ipchains -nL | egrep "^$ipchains_block_policy.*[[:space:]]+$ip[[:space:]]+.*[[:space:]]+\->[[:space:]]+$port"` q[+];
if [ -z "$found" ] ; then IE|$>q0Z cmd="ipchains -I input 1 -p tcp -s $ip -d 0/0 $port -j $ipchains_block_policy 1>/dev/null 2>/dev/null" ^v,^.>P mylogger_debug "cmd: $cmd" FNUue `ipchains -I input 1 -p tcp -s $ip -d 0/0 $port -j $ipchains_block_policy 1>/dev/null 2>/dev/null` j3FDGDrg if [ $? != 0 ] ; then U zc`,iV$ mylogger_notice "$cmd call failed" FuD$jsEw return E;+3VJ+F" fi 'a0$74f z new_block=1 < B'BlqTS ever_block=1 d9E:LZy else _xbVAI4 mylogger_info "$ip already blocked to $port" S3 &L fi kQYX[e7n ;; 0"ZRJl<)[I iptables) ,3x3&c mylogger_notice "blocking $1 to $2 via iptables" @k6>&PS found=`iptables -nL | egrep "^$iptables_block_policy.*[[:space:]]+$ip[[:space:]]+.*[[:space:]]+dpt:$port[[:space:]]+"` :V
8 \^ if [ -z "$found" ] ; then EKgTRRW 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" }VyDX14j mylogger_debug "cmd: $cmd" aj1Zi3h `iptables -I $iptables_chain_name 1 -p tcp -m tcp -s $ip --dport $port -j $iptables_block_policy 1>/dev/null 2>/dev/null` L g-Sxz}P! if [ $? != 0 ] ; then X+iUT mylogger_notice "$cmd call failed" @<l7"y;\ return ZMoN fi \= i>}Sg new_block=1 8M
!If ever_block=1 .
]P@{T||Y else rtC.!].;% mylogger_info "$ip already blocked to $port" tvavI9 fi *GD?d2.6j ;; jo/-'Lf{? *) )nQA) uz mylogger_notice "neither ipchains nor iptables" |h4aJv ;; X
J.bK esac $SA8
$!: } N"@aisi) xXQDHc-Ba restartservice() 9+_SG/@ { iW9G0Ay local service 0"3l2Eo if [ -z "$1" ] ; then 73
ix4C mylogger_notice "no port given to see which service to be restart" :>+}|(v return ]Vuq)# fi rzsAnLxo h0_od/D1r case "$1" in krnxM7y 80) 3+ JkV\
AF service="httpd" xJlf}LEyF ;; _=S4H 25) _[SW8 9zk service="postfix" {$5?[KD ;; mO%F {' 110) ^--kcTiR% service="courier-pop3d" =n7QL QU ;; ,aq0Q<}~lc 21) D;nm~O%
service="muddleftpd" KsVN<eR{ ;; )"KKBil0 53) \%[sv@P9s service="named" /zV&ebN] ;; {^(h*zxn 3306) 7\.{O$Q service="mysqld" 0Ez(;4]3 ;; x6N)T4J( esac wX/0.aZ | if [ ! -z "$service" ] ; then Es]:-TR /etc/init.d/$service restart 1>/dev/null 2>/dev/null :yFUlO: if [ $? = 0 ] ; then L/*D5k%J mylogger_notice "$service restarted" f
N_8HP6& else I.dS-)Y mylogger_notice "$service restart failed" [8%R*} fi q#C;iK4 fi tleWJR8oc } j; TXZ`|( W*.j=?)\[ docheckport() G1tua"Px { "Sb<"$: mylogger_info "do check port $1" y\?NB:=% local port last_client count client total_count IEmjWw4 aWS_z6[t#6 if [ -z "$1" ] ; then |X47&Y mylogger_notice "docheckport() port not given" W6^YFN return Gov]^?^D- fi ;)Fc@OXN> Ci9]#)"c port=$1 ,II-:&H 2H,n"-9+ clientlist=`netstat -an --tcp| grep ESTABLISHED | awk "{ if ( index(\\$4,\":$port\") ) print \\$5}" | awk -F ':' '{print $1}'|sort` WJU[+|J if [ $? != 0 ] ; then IRG -H!FV mylogger_notice "netstat call failed" iy-~CPNB_ return Xte"tf9(C fi K#;EjR4H #echo $clientlist 01w}8a( # reset new_block p >h&SD?b new_block=0 M$Or|HTG count=0 +'V ,z total_count=0 *f-8egt- last_client="" }. t8Cy9G for client in $clientlist 8~|tl, do w%?6s 3 #echo "client is $client" v5A8"&Jr if [ -z "$last_client" ] ; then hZtJ LY count=$((count+1)) >Pwu> total_count=$((total_count+1)) i%#
<Hi7 last_client=$client ~{$5JIpCm else m\eYm;RVj if [ "$client" = "$last_client" ] ; then 3:MAdh[w count=$((count+1)) Yq0j w&v
total_count=$((total_count+1)) dkAY%z two else a&C}'e" mylogger_debug "$last_client $count connections" JW9U&Bj{ if [ $count -ge $max_active_conn ] ; then &BE'~G mylogger_notice "client $last_client connection $count >= $max_active_conn" ?bw1zYP blockclient $last_client $port f0ME$:2 fi |m>{<
: count=1 |#J!oBS! total_count=$((total_count+1)) 8omk4 ; last_client=$client 7thB1cOJ fi w;
]~2$ fi q %hxU.h done @Rs3i;"W # check the last client vJ
fj1 f if [ ! -z "$client" ] ; then o 4cqLMu count=$((count+1)) dZ{yNh.] total_count=$((total_count+1)) W8Aii'Q8C/ mylogger_debug "$client $count connections" a9niXy}a( if [ $count -ge $max_active_conn ] ; then }1?
2 mylogger_notice "client $client connection $count >= $max_active_conn" +?y9EZB% blockclient $client $port s* UO!bH a fi a6 epew!2 fi t`eUD>\ mylogger_info "total connections on port $port: $total_count" <p\iB'y m6YDyQC
if [ $new_block = 1 ] ; then `uLH3sr restartservice $port /><+[\q4LM fi *WK0dn } r0fEW9wL /d-d8n docheckall() WJF#+)P:Y { V7q-Pfh!y # reset wakeup_time ]}HuK# wakeup_time=$wakeup_time_max AD4Ot5 for port in $portlist ^E= w3g& do _NkbB"+L docheckport $port mQqv{1 if [ $new_block = 1 ] ; then f]37Xl%I # set wakeup_time shorter cause we found some abuse client %VmHw~xyF: wakeup_time=$wakeup_time_min zpM%L:S fi 3|9
U`@ done K6nGC } 1:VbbOu->V bj`mQMC if [ -z "$firewall" ] && [ -f /etc/sysconfig/ipchains ] ; then
+c-?1j firewall="ipchains" Y1Sfhs) fi p`}'-A|@ Ql.abU if [ -z "$firewall" ] && [ -f /etc/sysconfig/iptables ] ; then XLxr@1 firewall="iptables" VdetY\ fi )[d>?%vfd 2c4x=% if [ -z "$firewall" ] ; then 4 g}'/ echo "Error: This machine does not have ipchains or iptables firewall support" E"[h20`\/ exit 1 K6X}d,g fi }Rx`uRx\ %?WR9}KU0 mylogger_info "firewall.sh v$myver ValueOf.com starting" v(vJ[_&% mylogger_info "Firewall is: $firewall" \C eP.,< mylogger_info "Port protected: $portlist" ne(zGJd mylogger_info "Max connection per ip: $max_active_conn" D<:J6W7] mylogger_info "Min time to check: $wakeup_time_min""s" ]H_|E mylogger_info "Max time to check: $wakeup_time_max""s" ;R
x
Rap mylogger_info "Timeout circle: $rule_timeout""s" SB#Y^! mylogger_info "Output is logged to: $log_facility" V.U9Q{y" 1*o=I-nOa # if new ip blocked at this check run? {ICW"Rlcs new_block=0 M7JQw/,xs # if new ip blocked at this timeout run? ,2C
{X+t ever_block=0 4>I >y@^ # reset wakeup_time yv2N5IQ>{V wakeup_time=$wakeup_time_max |>U:Pb( 01^+HEbm lasttime=`date +%s` eK)R=M@i 8\H*Z2yF+ while [ 1 ] AZgeu$:7p< do ].e4a;pt curtime=`date +%s` &?)?
w-$p timediff=$((curtime-lasttime)) bB->7.GXu #echo "timediff: $timediff" H/?@UJ5m if [ $timediff -ge $rule_timeout ] && [ $ever_block = 1 ] ; then -)Zp" lasttime=$curtime V@C8HTg
ever_block=0 ^/V>^9CZ dotimeout bCbp JZ fi 9>I&Z8J$M docheckall 7kDqgod^A mylogger_info "sleep for $wakeup_time""s" )A1u uW ( sleep $wakeup_time d(X/N2~g done pcrarj ^S%xaA9 B}U:c] ]o<&Q52 | 1. 说明 :Q-QY)hH firewall.sh是一个shell脚本程序,每隔一段时间检查tcp连接的统计信息,如果来自某个ip对某个端口的活动连接超过规定的最大数量, Ww&r 则自动将该IP对该端口的访问屏蔽,并重新启动相应的服务。再每隔一段时间,会重设防火墙到初始状态。 e\7AtlW" 该程序可以同时保护多个端口 1&.q#,EMn( f]C`]qg 2. 安装 KKcajN tar zxf firewall-1.0b.tar.gz WM8])}<
L cd firewall-1.0b ?;xL]~Q~1 install -m 700 firewall.sh /usr/prima/sbin/firewall.sh Mc@_[q!xY?
/Y#Q<=X 3. 配置 ya'Ma<4 主要配置项目如下: Xf%vfAf # 最小检查周期,缺省为120秒 y)K!l:X wakeup_time_min=120 5I>a|I!j @=NTr # 最大检查周期,缺省为300秒 m8,jV R wakeup_time_max=600 >v'@p [O@U@bD9 # 重设防火墙状态的时间,缺省为3600秒 Q>g-xe 1 rule_timeout=3600 dthtWnB@ Sah!|9 # 保护的端口列表,缺省为80和25,支持的其他端口包括21(ftp), 110(pop3), 53(named), 3306(mysql) .Mxt
F\ # 一般的网络攻击都是针对80和25,又以80居多 A)80qx:
portlist="80 25" rKkFflOVO Pah*, # 每个ip可占用的最大活动(Established)连接数 ,X)/ T!ff max_active_conn=8 IO{iQ-Mg Z\S'HNU # iptables防火墙规则链名称,必须和/etc/sysconfig/iptables中一致 =6d'/D#J # 如果用的是ipchains,可以忽略此项 Z
jn![ iptables_chain_name="RH-Lokkit-0-50-INPUT" Ij?Qs{V %*^s%NI # 日志输出目标 j)mi~i*U log_facility="local0" "Z#MR`;&29 iUq{c+h
**** 关于检查周期 **** ,!bcm 程序定义了两个检查周期,如果上次检查中屏蔽了某个IP,则程序会更频繁地检查连接情况,反之则等待更长时间。通过检查周期 hY/i)T{ 的动态调整,可以有效调度在遭受攻击和正常状态下程序的运行次数。 g+QNIM> fiQ/ &]|5 **** ipchains vs iptables **** 2>vn'sXdj 目前该程序支持ipchains和iptables两种软件防火墙,使用何种是由程序启动时自动检测的。如果/etc/sysconfig/ipchains和 6)1xjE# /etc/sysconfig/iptables都没有检测到,则报错退出。 P,bis7X. v03^ **** 日志输出 **** i|N(=Z
= 程序的输出信息记录在系统日志中,目标是local0。如果没有特殊配置,可以在/var/log/messages中看到。建议在/etc/syslog.conf S~\u]j^%y 中加入一条: ~-
BIUZ; local0.* /var/log/firewall.log I{7Hz{ 然后重新启动syslog gx=2]~O1( /etc/init.d/syslog restart WZf}1.Mh* 这样,可以将firewall.sh输出的日志单独记到文件/var/log/firewall.log里。
fYzZW bX`VIFc 4. 运行 84y#L[ /usr/prima/sbin/firewall.sh & TN.&FDqC9 fHacVjJ 范例输出: YvPs
*** firewall.sh v1.0b ValueOf.com*** \q:PU6q Firewall is: ipchains g({dD; Port protected: 80 25 f/]g@/` Max connection per ip: 8 sRSy++FRF Min time to check: 120s ~MW_=6U Max time to check: 300s vDVE#Nm_ Timeout circle: 3600s LYp=o8JW| Output is logged to: local0 Z{
b($po `KJBQK 察看/var/log/firewall.log,可以看到: KHt.g`1:R Oct 16 14:08:55 server firewall.sh: do check port 80 // 检查80端口 3&7$N#v Oct 16 14:08:55 server firewall.sh: 192.168.0.60 2 connections // 有两个来自192.168.0.60的连接 UU2=W Oct 16 14:08:55 server firewall.sh: total connections on port 80: 2 // 80端口总共2个连接 M;F&Ix Oct 16 14:08:55 server firewall.sh: do check port 25 // 检查25端口 Auf2JH~ Oct 16 14:08:55 server firewall.sh: total connections on port 25: 0 // 25端口没有连接 F<N{ x^ Oct 16 14:08:55 server firewall.sh: sleep for 300s // 等待300秒 Wo~#R tJ@5E^'4 5. 停止 yXL]uh#b 先用ps命令察看firewall.sh进程的进程号,然后用kill命令将其终止,如 mLL?n) # ps auxww|grep firewall.sh psZ #^@>mJ root 27932 0.0 0.5 2312 1060 pts/2 S 12:38 0:00 /bin/sh /usr/prima/sbin/firewall.sh j?'It`s root 27967 0.0 0.3 1732 592 pts/2 S 12:39 0:00 grep firewall.sh Hm55R 第一行即firewall.sh的进程,用kill命令: |HMpVT-;j # kill 27932 ({#M*=&" [1] Terminated /usr/prima/sbin/firewall.sh 1VC:o]$ 即将其终止 |
|