本节书摘来自华章计算机《高性能Linux服务器构建实战:系统安全、故障排查、自动化运维与集群架构》一书中的第1章,第1.2节,作者:高俊峰著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.2 远程访问和认证安全
1.2.1 远程登录取消telnet而采用SSH方式
telnet是一种古老的远程登录认证服务,它在网络上用明文传送口令和数据,因此别有用心的人就会非常容易截获这些口令和数据。而且,telnet服务程序的安全验证方式也极其脆弱,攻击者可以轻松将虚假信息传送给服务器。现在远程登录基本抛弃了telnet这种方式,取而代之的是通过SSH服务远程登录服务器。
关于SSH在前面已经做过一些简单的介绍,它是由客户端和服务器端的软件组成的,在客户端可以使用的软件有SecureCRT、putty、Xshell等,而在服务器端运行的是一个sshd服务。通过使用SSH,可以加密所有传输的数据,而且能够防止DNS和IP欺骗。使用SSH的另外一个好处就是:传输的数据是经过压缩的,所以可以加快网络传输速度。
下面重点介绍下如何配置服务器端的sshd服务,以保证服务器远程连接的安全。
sshd服务对应的主配置文件是/etc/ssh/sshd_config,下面重点介绍下此文件关于安全方面的几个配置。先打开主配置文件:
[root@localhost ~]# vi /etc/ssh/sshd_config
主配置文件中各个配置选项的含义如下:
Port 22,“Port”用来设置sshd监听的端口,为了安全起见,建议更改默认的22端口,选择5位以上的陌生数字端口。
Protocol 2,设置使用的SSH协议的版本为SSH1或SSH2,SSH1版本有缺陷和漏洞,因此这里选择Protocol 2即可。
ListenAddress 0.0.0.0,“ListenAddress”用来设置sshd服务器绑定的IP地址。
HostKey /etc/ssh/ssh_host_dsa_key,“HostKey”用来设置服务器密匙文件的路径。
KeyRegenerationInterval 1h,“KeyRegenerationInterval”用来设置在多少秒之后系统自动重新生成服务器的密匙(如果使用密匙)。重新生成密匙是为了防止利用盗用的密匙解密被截获的信息)。
ServerKeyBits 1024,“ServerKeyBits”用来定义服务器密匙的长度。
SyslogFacility AUTHPRIV,“SyslogFacility”用来设定在记录来自sshd的消息的时候,是否给出“facility code”。
LogLevel INFO,“LogLevel”用来记录sshd日志消息的级别。
LoginGraceTime 2m,“LoginGraceTime”用来设置如果用户登录失败,在切断连接前服务器需要等待的时间,以秒为单位。
PermitRootLogin no,“PermitRootLogin”用来设置超级用户root能不能用SSH登录。root远程登录Linux是很危险的,因此在远程SSH登录Linux系统时,建议将这个选项设置为“no”。
StrictModes yes,“StrictModes”用来设置SSH在接收登录请求之前是否检查用户根目录和rhosts文件的权限和所有权。建议将此选项设置为“yes”。
RSAAuthentication no,“RSAAuthentication”用来设置是否开启RSA密钥验证,只针对SSH1,如果采用RSA密钥登录方式时,开启此选项。
PubkeyAuthentication yes,“PubkeyAuthentication”用来设置是否开启公钥验证,如果采用公钥验证方式登录时,开启此选项。
AuthorizedKeysFile .ssh/authorized_keys,“AuthorizedKeysFile”用来设置公钥验证文件的路径,与PubkeyAuthentication配合使用。
IgnoreUserKnownHosts no,“IgnoreUserKnownHosts”用来设置SSH在进行RhostsRSAAuthentication安全验证时是否忽略用户的“$HOME/.ssh/known_hosts”文件。
IgnoreRhosts yes,“IgnoreRhosts”用来设置验证的时候是否使用“~/.rhosts”和“~/.shosts”文件。
PasswordAuthentication yes,“PasswordAuthentication”用来设置是否开启密码验证机制,如果使用密码登录系统,应该设置为“yes”。
PermitEmptyPasswords no,“PermitEmptyPasswords”用来设置是否允许用口令为空的账号登录系统,必须选择“no”。
ChallengeResponseAuthentication no,禁用s/key密码。
UsePAM no,不通过PAM验证。
X11Forwarding yes,“X11Forwarding”用来设置是否允许X11转发。
PrintMotd yes,“PrintMotd”用来设置sshd是否在用户登录的时候显示“/etc/motd”中的信息,可以在/etc/motd中加入警告信息,以震慑攻击者。
PrintLastLog no,是否显示上次登录信息,设置为“no”表示不显示。
Compression yes,是否压缩命令,建议选择“yes”。
TCPKeepAlive yes ,选择“yes”防止死连接。
UseDNS no,是否使用DNS反向解析,这里选择“no”。
MaxStartups 5,设置同时允许几个尚未登入的联机,当用户连上SSH但是尚未输入密码的时候就是所谓的联机,在这个联机中,为了保护主机,需要设定最大值,预设最多10个联机画面,而已经建立联机的不计算在这10个当中,其实设置5个已经够用了,这个设置可以防止对服务器进行恶意连接。
MaxAuthTries 3,设置最大失败尝试登录次数为3,合理设置此值,可以防止攻击者穷举登录服务器。
AllowUsers <用户名>,指定允许通过远程访问的用户,多个用户以空格分隔。
AllowGroups <组名>,指定允许通过远程访问的用户组,多个用户组以空格分隔,当很多用户都需要通过SSH登录系统时,可将这些用户加入到一个用户组中。
DenyUsers <用户名>,指定禁止通过远程访问的用户,多个用户以空格分隔。
DenyGroups <组名>,指定禁止通过远程访问的用户组,多个用户组以空格分隔。
1.2.2 合理使用shell历史命令记录功能
在Linux下可通过history命令查看用户所有的历史操作记录,同时shell命令操作记录默认保存在用户目录下的.bash_history文件中,通过这个文件可以查询shell命令的执行历史,有助于运维人员进行系统审计和问题排查,同时,在服务器遭受黑客攻击后,也可以通过这个命令或文件查询黑客登录服务器所执行的历史命令操作。但是有时候黑客在入侵服务器后为了毁灭痕迹,可能会删除.bash_history文件,这就需要合理保护或备份.bash_history文件。下面介绍下history日志文件的安全配置方法。
默认的history命令只能查看用户历史操作记录,并不能区分每个用户操作命令的时间,这点对于排查问题十分不便,不过可以通过下面的方法(加入四行内容)让history命令自动记录所有shell命令的执行时间,编辑/etc/bashrc文件:
HISTFILESIZE=4000
HISTSIZE=4000
HISTTIMEFORMAT='%F %T'
export HISTTIMEFORMAT
其中,HISTFILESIZE定义了在.bash_history文件中保存命令的记录总数,默认值是1000,这里设置为4000;HISTSIZE定义了history命令输出的记录总数;HISTTIMEFORMAT定义时间显示格式,这里的格式与date命令后的“+"%F %T"”是一致的;HISTTIMEFORMAT作为history的时间变量将值传递给history命令。
通过这样的设置后,执行history命令,就会显示每条历史命令的详细执行时间,例如:
[root@server ~]# history
247 2013-10-05 17:16:28 vi /etc/bashrc
248 2013-10-05 17:16:28 top
249 2013-10-05 17:04:18 vmstat
250 2013-10-05 17:04:24 ps -ef
251 2013-10-05 17:16:29 ls -al
252 2013-10-05 17:16:32 lsattr
253 2013-10-05 17:17:16 vi /etc/profile
254 2013-10-05 17:19:32 date +"%F %T"
255 2013-10-05 17:21:06 lsof
256 2013-10-05 17:21:21 history
为了确保服务器的安全,保留shell命令的执行历史是非常有用的一条技巧。虽然shell有历史功能,但是这个功能并非针对审计目的而设计,因此很容易被黑客篡改或丢失。下面再介绍一种方法,可以实现详细记录登录过系统的用户、IP地址、shell命令以及详细操作时间等,并将这些信息以文件的形式保存在一个安全的地方,以供系统审计和故障排查。
将下面这段代码添加到/etc/profile文件中,即可实现上述功能。
#history
USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`
HISTDIR=/usr/share/.history
if [ -z $USER_IP ]
then
USER_IP=`hostname`
fi
if [ ! -d $HISTDIR ]
then
mkdir -p $HISTDIR
chmod 777 $HISTDIR
fi
if [ ! -d $HISTDIR/${LOGNAME} ]
then
mkdir -p $HISTDIR/${LOGNAME}
chmod 300 $HISTDIR/${LOGNAME}
fi
export HISTSIZE=4000
DT=`date +%Y%m%d_%H%M%S`
export HISTFILE="$HISTDIR/${LOGNAME}/${USER_IP}.history.$DT"
export HISTTIMEFORMAT="[%Y.%m.%d %H:%M:%S]"
chmod 600 $HISTDIR/${LOGNAME}/*.history* 2>/dev/null
这段代码将每个用户的shell命令执行历史以文件的形式保存在/usr/share/.history目录中,每个用户一个文件夹,并且文件夹下的每个文件以IP地址加shell命令操作时间的格式命名。下面是user01用户执行shell命令的历史记录文件,基本效果如下:
[root@server user01]# pwd
/usr/share/.history/user01
[root@server user01]# ls -al
-rw------- 1 user01 wheel 56 Jul 6 17:07 192.168.12.12.history.20130706_164512
-rw------- 1 user01 wheel 43 Jul 6 17:42 192.168.12.12.history.20130706_172800
-rw------- 1 user01 wheel 22 Jul 7 12:05 192.168.12.19.history.20130707_111123
-rw------- 1 user01 wheel 22 Jul 8 13:41 192.168.12.20.history.20130708_120053
-rw------- 1 user01 wheel 22 Jul 1 15:28 192.168.12.186.history.20130701_150941
-rw------- 1 user01 wheel 22 Jul 2 19:47 192.168.12.163.history.20130702_193645
-rw------- 1 user01 wheel 22 Jul 3 12:38 192.168.12.19.history.20130703_120948
-rw------- 1 user01 wheel 22 Jul 3 19:14 192.168.12.134.history.20130703_183150
保存历史命令的文件夹目录要尽量隐蔽,避免被黑客发现后删除。
1.2.3 启用tcp_wrappers防火墙
tcp_wrappers是一个用来分析TCP/IP封包的软件,类似的IP封包软件还有iptables。Linux默认安装了tcp_wrappers。作为一个安全的系统,Linux本身有两层安全防火墙,通过IP过滤机制的iptables实现第一层防护。iptables防火墙通过直观地监视系统的运行状况,阻挡网络中的一些恶意攻击,保护整个系统正常运行,免遭攻击和破坏。如果通过了第一层防护,那么下一层防护就是tcp_wrappers了。通过tcp_wrappers可以实现对系统中提供的某些服务的开放与关闭、允许与禁止,从而更有效地保证系统安全运行。
tcp_wrappers的使用很简单,仅仅有两个配置文件:/etc/hosts.allow和/etc/hosts.deny。
(1)查看系统是否安装了tcp_wrappers
[root@localhost ~]# rpm -q tcp_wrappers
tcp_wrappers-7.6-57.el6.x86_64
或者
[root@localhost ~]# rpm -qa | grep tcp
tcp_wrappers-7.6-57.el6.x86_64
tcp_wrappers-libs-7.6-57.el6.x86_64
tcpdump-4.0.0-3.20090921gitdf3cb4.2.el6.x86_64
如果有上面类似的输出,表示系统已经安装了tcp_wrappers模块。如果没有显示,可能没有安装,可以从Linux系统安装盘找到对应的RPM包进行安装。
(2)tcp_wrappers防火墙的局限性
Linux系统中的某个服务是否可以使用tcp_wrappers防火墙,取决于该服务是否应用了libwrapped库文件,如果应用了就可以使用tcp_wrappers防火墙。系统中默认的一些服务,如:sshd、portmap、sendmail、xinetd、vsftpd、tcpd等都可以使用tcp_wrappers防火墙。
(3) tcp_wrappers设定的规则
tcp_wrappers防火墙的实现是通过/etc/hosts.allow和/etc/hosts.deny两个文件来完成的,首先看一下设定的格式:
service:host(s) [:action]
主要参数含义如下:
service:代表服务名,例如sshd、vsftpd、sendmail等。
host(s):主机名或者IP地址,可以有多个,例如192.168.12.0、www.ixdba.net。
action:动作,符合条件后所采取的动作。
配置文件中常用的关键字有:
ALL:所有服务或者所有IP。
ALL EXCEPT:从所有的服务或者所有IP中除去指定的。
例如:
ALL:ALL EXCEPT 192.168.12.189
表示除了192.168.12.189这台机器,任何机器执行所有服务时或被允许或被拒绝。
了解了设定语法后,下面就可以对服务进行访问限定。
例如,互联网上一台Linux服务器,实现的目标是:仅仅允许222.61.58.88、61.186.232.58以及域名www.ixdba.net通过SSH服务远程登录系统,下面介绍具体的设置过程。
首先设定允许登录的计算机,即配置/etc/hosts.allow文件,设置很简单,只要修改/etc/hosts.allow(如果没有此文件,请自行建立)这个文件,即只需将下面规则加入/etc/hosts.allow即可。
sshd: 222.61.58.88
sshd: 61.186.232.58
sshd: www.ixdba.net
接着设置不允许登录的机器,也就是配置/etc/hosts.deny文件。
一般情况下,Linux会首先判断/etc/hosts.allow这个文件,如果远程登录的计算机满足文件/etc/hosts.allow设定,就不会再使用/etc/hosts.deny文件;相反,如果不满足hosts.allow文件设定的规则,就会使用hosts.deny文件,如果满足hosts.deny的规则,此主机就被限制为不可访问Linux服务器,如果也不满足hosts.deny的设定,此主机默认是可以访问Linux服务器的。因此,在设定好/etc/hosts.allow文件访问规则之后,只需设置/etc/hosts.deny为“所有计算机都不能登录状态”:
sshd:ALL
这样,一个简单的tcp_wrappers防火墙就设置完毕了。