Linux登录提示(静态/动态MOTD)
在用户输入口令或使用密钥成功登录后,让服务器自动为我们执行几个简单的操作,如打印提示信息,打印异常信息,执行一个脚本,或者发送邮件等。能够预先提示信息给登录者,让我们在登录机器采取任何操作之前,可以快速的了解这台机器的重要信息。看起来是不是很有意思呢? 也许我们会想,这对于服务器的安全加固并没有直接的影响,而且每次刚刚登录就执行一系列命令、脚本(如收集服务器资源使用情况的信息),似乎也有点多余。因此,如果是在生产环境的Linux服务器并且需要配置登录提示,诸如登录执行命令、脚本等这些操作,我们不必为此写一个复杂的、庞大的脚本,脚本的执行时间很关键,如果你不想在正确输入登录密码后仍需等待几秒或更长的时间,那么,尽可能地把脚本的执行耗时优化到几毫秒,甚至更低。(登录后的提示或操作尽可能简单的、有利的是最好的。如果你想这么做)
在大多数Linux分发版中,可以直接修改/etc/motd文件来定制任何想要的提示信息,修改方法是将需要打印的提示消息文件粘贴到该文件中即可(一些可执行命令或脚本在文件中仅仅被当作是普通字符/文本)。/etc/motd内的文本消息是固定不变,除非我们手动修改它。因此,在/etc/motd中定制的消息是静态MOTD。
如果你使用过Debian/Ubuntu分发版,你可能已经发现,Ubuntu默认就已经有一个动态的MOTD信息提示(通过SSH或本地登录时显示系统当前的一些信息)。在RHEL/CentOS中不可能实现像在Debian/Ubuntu中这样的功能,因为RHEL/CentOS并没有提供与之相关的任何脚本。我们可以通过环境变量文件,如/etc/profile、/etc/bashrc等,将需要执行的命令或脚本添加到这些文件末尾,这样当每次用户登陆时,系统就会读取这些文件,执行文件里定义好的脚本。除此之外,也可以结合使用crontab计划任务,将预先准备好的脚本,如系统监控,异常信息收集通过crontab在后台定期执行,并把收集到的信息重定向写到/etc/motd文件中。在用户登录系统时,就可以显示这些系统监控、异常处理信息了。
在Ubuntu中,提供了一组脚本在目录/etc/update-motd.d/中,在用户登录时,按照脚本名字前缀的数字(00-99)顺序执行,并将这些脚本的输出保存到文件/run/motd.dynamic中,最终用户成功登录后,在登录的屏幕界面中打印出来。输出结果如下图所示
/etc/update-motd.d/脚本列表:
00-header
10-help-text
50-landscape-sysinfo
90-updates-available
91-release-upgrade
98-fsck-at-reboot
98-reboot-required
以上是在Ubuntu 14.04 LTS中默认的提供动态MOTD消息的脚本,这些脚本可以修改,也可以增加自己的脚本。比如替换为自己的定制好的脚本。
下面我给出在RHEL/CentOS中定制MOTD的几个简单操作示例:
打印提示信息,执行一个脚本,或者发送邮件
l 任何用户远程或本地登录后打印提示信息(如提示登录者这是一台重要的服务器,要求登录者谨慎操作)
>> 开启SSH服务打印MOTD消息,配置文件/etc/ssh/sshd_config,确认是否如下配置(默认为yes)
1
|
PrintMotd
yes
|
>> 修改/etc/motd文件,将提示消息粘贴到该文件中
1
2
3
4
5
|
[root@localhost ~]
# cat /etc/motd
***************************************************
* 注意: 这是一台重要的生产服务器,请谨慎操作!! *
* 如需要重启/关闭服务器,请先将NFS卸载 *
***************************************************
|
>> 保存之后,使用SSH登录该服务器,输入正确的账号密码之后,提示如下
当然,仅仅像这样简单的提示远远不够,我们可以根据这台服务器的特征、运行的服务、文件系统信息以及重要的细节信息等打印出来,让其他的IT人员登录该服务器时,在采取任何操作之前,可以快速的掌握这台服务器的重要信息。也可以起到一个警惕的作用。你可以根据自己的情况定制。
l RHEL/CentOS中打印动态MOTD提示
>> 任何用户通过SSH远程登录打印提示如下
>> 创建系统信息收集脚本
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
|
[root@HMing ~]
# vim /usr/src/scripts/system_info.sh
#!/bin/bash
date
=`
date
"+%F %T"
`
head
=
"System information as of: $date"
kernel=`
uname
-r`
hostname
=`
echo
$HOSTNAME`
#Cpu load
load1=`
cat
/proc/loadavg
|
awk
'{print $1}'
`
load5=`
cat
/proc/loadavg
|
awk
'{print $2}'
`
load15=`
cat
/proc/loadavg
|
awk
'{print $3}'
`
#System uptime
uptime=`
cat
/proc/uptime
|
cut
-f1 -d.`
upDays=$((uptime
/60/60/24
))
upHours=$((uptime
/60/60
%24))
upMins=$((uptime
/60
%60))
upSecs=$((uptime%60))
up_lastime=`
date
-d
"$(awk -F. '{print $1}' /proc/uptime) second ago"
+
"%Y-%m-%d %H:%M:%S"
`
#Memory Usage
mem_usage=`
free
-m |
awk
'/Mem:/{total=$2} /buffers\/cache/ {used=$3} END {printf("%3.2f%%",used/total*100)}'
`
swap_usage=`
free
-m |
awk
'/Swap/{printf "%.2f%",$3/$2*100}'
`
#Processes
processes=`
ps
aux |
wc
-l`
#User
users
=`
users
|
wc
-w`
USER=`
whoami
`
#System fs usage
Filesystem=$(
df
-h |
awk
'/^\/dev/{print $6}'
)
#Interfaces
INTERFACES=$(ip -4 ad |
grep
'state '
|
awk
-F
":"
'!/^[0-9]*: ?lo/ {print $2}'
)
echo
echo
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo
"$head"
echo
"----------------------------------------------"
printf
"Kernel Version:\t%s\n"
$kernel
printf
"HostName:\t%s\n"
$
hostname
printf
"System Load:\t%s %s %s\n"
$load1, $load5, $load15
printf
"System Uptime:\t%s "
days
" %s "
hours
" %s "
min
" %s "
sec
"\n"
$upDays $upHours $upMins $upSecs
printf
"Memory Usage:\t%s\t\t\tSwap Usage:\t%s\n"
$mem_usage $swap_usage
printf
"Login Users:\t%s\t\t\tWhoami:\t\t%s\n"
$
users
$USER
printf
"Processes:\t%s\n"
$processes
printf
"\n"
printf
"Filesystem\tUsage\n"
for
f
in
$Filesystem
do
Usage=$(
df
-h |
awk
'{if($NF=="'
''
$f
''
'") print $5}'
)
echo
-e
"$f\t\t$Usage"
done
printf
"\n"
printf
"Interface\tMAC Address\t\tIP Address\n"
for
i
in
$INTERFACES
do
MAC=$(ip ad show dev $i |
grep
"link/ether"
|
awk
'{print $2}'
)
IP=$(ip ad show dev $i |
awk
'/inet / {print $2}'
)
printf
$i
"\t\t"
$MAC
"\t$IP\n"
done
echo
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo
|
>> 给脚本增加执行权限
1
|
[root@HMing ~]
# chmod +x /usr/src/scripts/system_info.sh
|
>> 将脚本的路径名添加到/etc/profile文件末尾
1
2
|
[root@HMing ~]
# tail -1 /etc/profile
/usr/src/scripts/system_info
.sh
|
l 任何用户远程或本地登录后发送邮件信息
>> 演示如下
>> 发送邮件如下
>> 创建一个发送邮件的脚本/usr/src/scripts/my-server-login-mail,如下
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
smtp=smtp.163.com
smtp_auth_user=xxxxxx
smtp_auth_password=xxxxxxxxxx
from=xxxxxxxx@163.com
function
HEAD {
Kernel_version=`
uname
-r`
Login_user=`last -a |
grep
"logged in"
|
wc
-l`
Up_lastime=`
date
-d
"$(awk -F. '{print $1}' /proc/uptime) second ago"
+
"%Y-%m-%d %H:%M:%S"
`
Up_runtime=`
cat
/proc/uptime
|
awk
-F. '{run_days=$1 / 86400;run_hour=($1 % 86400)
/3600
;run_minute=($1 % 3600)
/60
;run_second
=$1 % 60;
printf
(
"%d天%d时%d分%d秒"
,run_days,run_hour,run_minute,run_second)}'`
Last_user=`last |
awk
'(
/pts/
) && (
/-/
){print
"User: "
$1
" - "
"OlineTime: "
$NF
" - "
"IP: "
$3
" - "
"LoginTime: "
$4
" "
$5
" "
$6
" "
$7}
'| head -1 | sed -e '
s/(
//g
' -e '
s/)
//g
'`
echo
-e
""
echo
-e "\
邮件提示: 未知身份来源使用${USER}用户登录系统
-------------------------------------------------------------
System information
主机名: $HOSTNAME
内核版本: $Kernel_version
系统已运行时间: $Up_runtime
上一次重启时间: $Up_lastime
当前登入用户数: $Login_user
上一次登入用户: $Last_user
-------------------------------------------------------------
"
};HEAD >
/tmp/
.loginmail
title=
"主机:`echo $HOSTNAME`登录提示 (`date "
+%F %T
"`)"
body=`
cat
/tmp/
.loginmail`
to=741616710@qq.com
sendEmail -s
"$smtp"
-xu
"${smtp_auth_user}"
-xp
"${smtp_auth_password}"
-f
"$from"
-t
"$to"
-u
"$title"
-m
"$body"
&>
/dev/null
&&
rm
-rf
/tmp/
.loginmail
|
在Linux发送邮件的程序有很多,在这里我用的是sendEmail,你也可以使用其他的发送邮件程序。
>> 将脚本绝对路径名添加到/etc/profile文件末尾
1
2
|
[root@HMing ~]
# tail -1 /etc/profile
/usr/src/scripts/my-server-login-mail
|
结语
动态的MOTD在Ubuntu中是开箱即用的,因为它已经被集成为系统的一个模块,通过pam_motd.so调用。不过,我们可以随时修改系统上预先配置好的脚本,将脚本放到/etc/update-motd.d/目录中,比如收集系统异常信息脚本,在用户登录时,将在第一时间反馈给用户,或者是系统登录记录的实时监控,通过发生邮件给用户,用户可以快速掌握服务器是否存在被入侵的情况。对于RHEL/CentOS发行版,我在文中也给出了几个简单的演示示例,实现动态MOTD。有兴趣同学的可以作为参考。