本章目录:
12.11 屏蔽网站访问频繁的IP
1)屏蔽每分钟访问超过200的IP
方法1:以Nginx日志作为测试
1
2
3
4
5
6
7
8
|
DATE=$(
date
+%d/%b/%Y:%H:%M)
ABNORMAL_IP=$(
tail
-n5000 access.log |
grep
$DATE |
awk
'{a[$1]++}END{for(i in a)if(a[i]>100)print i}'
)
#先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。
for
IP
in
$ABNORMAL_IP;
do
if
[ $(iptables -vnL |
grep
-c
"$IP"
) -
eq
0 ];
then
iptables -I INPUT -s $IP -j DROP
fi
done
|
方法2:通过建立连接数
1
2
3
4
5
6
7
|
ABNORMAL_IP=$(
netstat
-an |
awk
'$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}'
)
#gsub是将第五列(客户端IP)的冒号和端口去掉
for
IP
in
$ABNORMAL_IP;
do
if
[ $(iptables -vnL |
grep
-c
"$IP"
) -
eq
0 ];
then
iptables -I INPUT -s $IP -j DROP
fi
done
|
2)屏蔽每分钟SSH暴力破解超过10次的IP
方法1:通过lastb获取登录状态:
1
2
3
4
5
6
7
|
DATE=$(
date
+
"%a %b %e %H:%M"
)
#星期月天时分 %e单数字时显示7,而%d显示07
ABNORMAL_IP=$(lastb |
grep
"$DATE"
|
awk
'{a[$3]++}END{for(i in a)if(a[i]>10)print i}'
)
for
IP
in
$ABNORMAL_IP;
do
if
[ $(iptables -vnL |
grep
-c
"$IP"
) -
eq
0 ];
then
iptables -I INPUT -s $IP -j DROP
fi
done
|
方法2:通过日志获取登录状态
1
2
3
4
5
6
7
8
|
DATE=$(
date
+
"%b %d %H"
)
ABNORMAL_IP=
"$(tail -n10000 /var/log/auth.log |grep "
$DATE
" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')"
for
IP
in
$ABNORMAL_IP;
do
if
[ $(iptables -vnL |
grep
-c
"$IP"
) -
eq
0 ];
then
iptables -A INPUT -s $IP -j DROP
echo
"$(date +"
%F %T
") - iptables -A INPUT -s $IP -j DROP"
>>~
/ssh-login-limit
.log
fi
done
|
12.12 判断输入是否为IP
方法1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
function
check_ip(){
IP=$1
VALID_CHECK=$(
echo
$IP|
awk
-F.
'$1<=255&&$2<=255&&$3<=255&&$4<=255{print "yes"}'
)
if
echo
$IP|
grep
-E
"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
>
/dev/null
;
then
if
[ $VALID_CHECK ==
"yes"
];
then
echo
"$IP available."
else
echo
"$IP not available!"
fi
else
echo
"Format error!"
fi
}
check_ip 192.168.1.1
check_ip 256.1.1.1
|
方法2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
function
check_ip(){
IP=$1
if
[[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]];
then
FIELD1=$(
echo
$IP|
cut
-d. -f1)
FIELD2=$(
echo
$IP|
cut
-d. -f2)
FIELD3=$(
echo
$IP|
cut
-d. -f3)
FIELD4=$(
echo
$IP|
cut
-d. -f4)
if
[ $FIELD1 -
le
255 -a $FIELD2 -
le
255 -a $FIELD3 -
le
255 -a $FIELD4 -
le
255 ];
then
echo
"$IP available."
else
echo
"$IP not available!"
fi
else
echo
"Format error!"
fi
}
check_ip 192.168.1.1
check_ip 256.1.1.1
|
增加版:加个死循环,如果IP可用就退出,不可用提示继续输入,并使用awk判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function
check_ip(){
local
IP=$1
VALID_CHECK=$(
echo
$IP|
awk
-F.
'$1<=255&&$2<=255&&$3<=255&&$4<=255{print "yes"}'
)
if
echo
$IP|
grep
-E
"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
>
/dev/null
;
then
if
[ $VALID_CHECK ==
"yes"
];
then
return
0
else
echo
"$IP not available!"
return
1
fi
else
echo
"Format error! Please input again."
return
1
fi
}
while
true
;
do
read
-p
"Please enter IP: "
IP
check_ip $IP
[ $? -
eq
0 ] &&
break
||
continue
done
|
12.13 判断输入是否为数字
1
2
3
4
5
6
7
8
9
10
11
12
|
方法1:
if
[[ $1 =~ ^[0-9]+$ ]];
then
echo
"Is Number."
else
echo
"No Number."
fi
方法2:
if
[ $1 -gt 0 ] 2>
/dev/null
;
then
echo
"Is Number."
else
echo
"No Number."
fi
|
方法3:
1
2
3
4
5
6
7
8
9
|
echo
$1 |
awk
'{print $0~/^[0-9]+$/?"Is Number.":"No Number."}'
#三目运算符
12.14 找出包含关键字的文件
DIR=$1
KEY=$2
for
FILE
in
$(
find
$DIR -
type
f);
do
if
grep
$KEY $FILE &>
/dev/null
;
then
echo
"--> $FILE"
fi
done
|
12.15 监控目录,将新创建的文件名追加到日志中
需安装inotify-tools软件包。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#!/bin/bash
MON_DIR=
/opt
inotifywait -mq --
format
%f -e create $MON_DIR |\
while
read
files;
do
echo
$files >>
test
.log
done
12.16 多个网卡选择
function
local_nic() {
local
NUM ARRAY_LENGTH
NUM=0
for
NIC_NAME
in
$(
ls
/sys/class/net
|
grep
-vE
"lo|docker0"
);
do
NIC_IP=$(
ifconfig
$NIC_NAME |
awk
-F
'[: ]+'
'/inet addr/{print $4}'
)
if
[ -n
"$NIC_IP"
];
then
NIC_IP_ARRAY[$NUM]=
"$NIC_NAME:$NIC_IP"
#将网卡名和对应IP放到数组
let
NUM++
fi
done
ARRAY_LENGTH=${
#NIC_IP_ARRAY[*]}
if
[ $ARRAY_LENGTH -
eq
1 ];
then
#如果数组里面只有一条记录说明就一个网卡
NIC=${NIC_IP_ARRAY[0]%:*}
return
0
elif
[ $ARRAY_LENGTH -
eq
0 ];
then
#如果没有记录说明没有网卡
echo
"No available network card!"
exit
1
else
#如果有多条记录则提醒输入选择
for
NIC
in
${NIC_IP_ARRAY[*]};
do
echo
$NIC
done
while
true
;
do
read
-p
"Please enter local use to network card name: "
INPUT_NIC_NAME
COUNT=0
for
NIC
in
${NIC_IP_ARRAY[*]};
do
NIC_NAME=${NIC%:*}
if
[ $NIC_NAME ==
"$INPUT_NIC_NAME"
];
then
NIC=${NIC_IP_ARRAY[$COUNT]%:*}
return
0
else
COUNT+=1
fi
done
echo
"Not match! Please input again."
done
fi
}
local_nic
|
如果有只有一个网卡就不选择。
12.17 查看网卡实时流量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#!/bin/bash
# Description: Only CentOS6
traffic_unit_conv() {
local
traffic=$1
if
[ $traffic -gt 1024000 ];
then
printf
"%.1f%s"
"$(($traffic/1024/1024))"
"MB/s"
elif
[ $traffic -lt 1024000 ];
then
printf
"%.1f%s"
"$(($traffic/1024))"
"KB/s"
fi
}
NIC=$1
echo
-e
" In ------ Out"
while
true
;
do
OLD_IN=$(
awk
-F
'[: ]+'
'$0~"'
$NIC
'"{print $3}'
/proc/net/dev
)
OLD_OUT=$(
awk
-F
'[: ]+'
'$0~"'
$NIC
'"{print $11}'
/proc/net/dev
)
sleep
1
NEW_IN=$(
awk
-F
'[: ]+'
'$0~"'
$NIC
'"{print $3}'
/proc/net/dev
)
NEW_OUT=$(
awk
-F
'[: ]+'
'$0~"'
$NIC
'"{print $11}'
/proc/net/dev
)
IN=$(($NEW_IN-$OLD_IN))
OUT=$(($NEW_OUT-$OLD_OUT))
echo
"$(traffic_unit_conv $IN) $(traffic_unit_conv $OUT)"
sleep
1
done
# 也可以通过ficonfig命令获取收发流量
while
true
;
do
OLD_IN=$(
ifconfig
$NIC |
awk
-F
'[: ]+'
'/bytes/{print $4}'
)
OLD_OUT=$(
ifconfig
$NIC |
awk
-F
'[: ]+'
'/bytes/{print $9}'
)
sleep
1
NEW_IN=$(
ifconfig
$NIC |
awk
-F
'[: ]+'
'/bytes/{print $4}'
)
NEW_OUT=$(
ifconfig
$NIC |
awk
-F
'[: ]+'
'/bytes/{print $9}'
)
IN=$(($NEW_IN-$OLD_IN))
OUT=$(($NEW_OUT-$OLD_OUT))
echo
"$(traffic_unit_conv $IN) $(traffic_unit_conv $OUT)"
sleep
1
done
|
12.18 MySQL数据库备份
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#!/bin/bash
DATE=$(
date
+%F_%H-%M-%S)
HOST=192.168.1.120
DB=
test
USER=bak
PASS=123456
MAIL=
"zhangsan@example.com lisi@example.com"
BACKUP_DIR=
/data/db_backup
SQL_FILE=${DB}_full_$DATE.sql
BAK_FILE=${DB}_full_$DATE.zip
cd
$BACKUP_DIR
if
mysqldump -h$HOST -u$USER -p$PASS --single-transaction --routines --triggers -B $DB > $SQL_FILE;
then
zip $BAK_FILE $SQL_FILE &&
rm
-f $SQL_FILE
if
[ ! -s $BAK_FILE ];
then
echo
"$DATE 内容"
| mail -s
"主题"
$MAIL
fi
else
echo
"$DATE 内容"
| mail -s
"主题"
$MAIL
fi
find
$BACKUP_DIR -name
'*.zip'
-ctime +14 -
exec
rm
{} \;
|
12.19 Nginx启动脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#!/bin/bash
# Description: Only support RedHat system
.
/etc/init
.d
/functions
WORD_DIR=
/data/project/nginx1
.10
DAEMON=$WORD_DIR
/sbin/nginx
CONF=$WORD_DIR
/conf/nginx
.conf
NAME=nginx
PID=$(
awk
-F
'[; ]+'
'/^[^#]/{if($0~/pid;/)print $2}'
$CONF)
if
[ -z
"$PID"
];
then
PID=$WORD_DIR
/logs/nginx
.pid
else
PID=$WORD_DIR/$PID
fi
stop() {
$DAEMON -s stop
sleep
1
[ ! -f $PID ] && action
"* Stopping $NAME"
/bin/true
|| action
"* Stopping $NAME"
/bin/false
}
start() {
$DAEMON
sleep
1
[ -f $PID ] && action
"* Starting $NAME"
/bin/true
|| action
"* Starting $NAME"
/bin/false
}
reload() {
$DAEMON -s reload
}
test_config() {
$DAEMON -t
}
case
"$1"
in
start)
if
[ ! -f $PID ];
then
start
else
echo
"$NAME is running..."
exit
0
fi
;;
stop)
if
[ -f $PID ];
then
stop
else
echo
"$NAME not running!"
exit
0
fi
;;
restart)
if
[ ! -f $PID ];
then
echo
"$NAME not running!"
start
else
stop
start
fi
;;
reload)
reload
;;
testconfig)
test_config
;;
status)
[ -f $PID ] &&
echo
"$NAME is running..."
||
echo
"$NAME not running!"
;;
*)
echo
"Usage: $0 {start|stop|restart|reload|testconfig|status}"
exit
3
;;
esac
|
12.20 选择SSH连接主机
写一个配置文件保存被监控主机SSH连接信息,文件内容格式:主机名 IP User Port
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#!/bin/bash
PS3=
"Please input number: "
HOST_FILE=host
while
true
;
do
select
NAME
in
$(
awk
'{print $1}'
$HOST_FILE) quit;
do
[ ${NAME:=empty} ==
"quit"
] &&
exit
0
IP=$(
awk
-
v
NAME=${NAME}
'$1==NAME{print $2}'
$HOST_FILE)
USER=$(
awk
-
v
NAME=${NAME}
'$1==NAME{print $3}'
$HOST_FILE)
PORT=$(
awk
-
v
NAME=${NAME}
'$1==NAME{print $4}'
$HOST_FILE)
if
[ $IP ];
then
echo
"Name: $NAME, IP: $IP"
ssh
-o StrictHostKeyChecking=no -p $PORT -i id_rsa $USER@$IP
# 密钥登录
break
else
echo
"Input error, Please enter again!"
break
fi
done
done
|
本文转自 李振良OK 51CTO博客,原文链接:http://blog.51cto.com/lizhenliang/1929770,如需转载请自行联系原作者