为了方便使用,一般服务器都会通过配置远程访问来保证随时配置服务器,但是不正确的远程访问配置会对系统产生安全隐患,产生被入侵的风险。
使用安全的登录认证方式
现代服务器环境往往需要用户远程登录,而远程登录本身就具有一定的安全风险————中间人攻击。
在早期,telnet是一种常用的登录方式,但它过于古老,而且使用明文传输,这使得对其的攻击代价十分之小,极易遭到拦截与伪造。现代远程登录已经基本抛弃了telnet,而是通过SSH服务远程登录服务器。
SSH会加密所有的传输数据,并且可以防御DNS和IP欺骗,经过SSH压缩的数据也可以提高远程访问的传输效率。
SSH在服务端运行的是sshd服务,sshd服务对应的主配置文件是/etc/ssh/sshd_config
。
使用强密码
很多时候,为了方便记忆,用户往往会使用一些简单的密码。例如自己的生日、某个时间点或者一些其他内容,但这些密码其实安全性很低,在撞库攻击下很容易就受到攻破。所以建议使用随机生成的高位强密码,并周期性更换。
Linux系统自带的openssl就可以生成一串强密码供用户使用,建议使用32位以上的强密码,这样可以有效的防止撞库攻击。
如生成一串十六位的密码:
$ openssl rand -base64 16
WjzyDqedkWf3e5A3tJw/c=
使用密钥认证
使用强密码认证仍存在一定的风险,如管理员忘记或遗失密码,甚至泄露密码。而密钥认证则是一种更加安全的认证方式,因为其将密钥文件存储在客户端与服务器中,不必输入密码就可以进行登录,避免了密码泄露的风险。
这里以Xshell6为例,讲解通过密钥认证方式远程登录Linux服务器的实现方法。
- 首先打开Xshell,选择“工具-新建用户密钥生成向导”,进入密钥生成窗口。选择密钥类型为RSA,长度建议至少为1024位。点击下一步
- 等待密钥生成,生成完毕后直接点击下一步。
- 输入密钥信息,以及密钥密码,点击下一步。
- 点击“保存为文件”,将pub后缀的公钥保存到本地,完成。
- 此时私钥已经被Xshell保存在本地了,通过“工具-用户密钥管理者”可以查看生成的密钥。
- 到目前为止,已经成功的生成密钥,并将公钥与私钥都保存在了本地,接下来我们需要设置用户使用SSH2协议,如,将user01设置为使用SSH2登录
$ mkdir /home/user01/.ssh
$ chmod 700 /home/user01/.ssh
然后将公钥上传到服务器,并且导入密钥,在将公钥上传后,使用以下命令将公钥导入到服务器,并修改公钥文件的权限:
$ ssh-keygen && cat /上传公钥的路径/id_rsa_2048.pub >> /home/user01/.ssh/authorized_keys
$ chmod 600 /home/user01/.ssh/authorized_keys
- 为了服务器的安全,我们还需要将SSH2修改为只能接受PublicKey认证的方式来验证用户:
$ vim /etc/ssh/sshd_config
##修改以下配置:
Protocol 2 #仅允许使用SSH2
PubkeyAuthentication yes #启用PublicKey认证
AuthorizedKeyFile .ssh/authorized_keys #PublicKey文件路径
PasswordAuthentication no #不使用口令认证
最后重启sshd服务:
$ systemctl restart sshd
- 接下来就可以使用密钥方式来登录服务器了,在Xshell的会话属性中,将用户身份认证方式改为PublicKey方式,并且选择用户密钥就可以使用密钥方式登陆服务器。
shell命令日志
用户在shell中的操作记录会被保存在用户目录下的.bash_history
文件中,通过这个文件可以查询shell命令的执行历史,有助于进行系统审计与问题排查。
并且,在遭受到黑客攻击后,也可以通过这个文件查询黑客登录服务器所执行的历史命令操作,但是黑客在攻击会为了毁灭痕迹而删除.bash_history
文件,所以我们要对该文件进行保护。
默认的.bash_history并不会区分不同用户操作命令与执行时间,我们可以通过以下方式来让history命令记录所有的shell命令的执行时间,编辑/etc/bashrc
文件:
HISTFILESIZE=4000 #定义保存命令的总数
HISTSIZE=4000 #定义输出的命令总数
HISTTIMEFORMAT='%F %T' #定义时间格式
export HISTTIMEFORMAT #传递变量
然后可以利用以下方法来实现详细记录登陆过系统的用户、IP地址、shell命令以及详细操作时间,并将这些信息以文件方式保存在一个安全的目录,
将以下代码添加到/etc/profile文件中:
#history
USER_IP='who -u am i 2>/dev/null| awk '{print SNF}'|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.SDT"
export HISTTIMEFORMAT="[%Y.%m.%d %H:%M:%S]"
chmod 600 $HISTDIR/${LOGNAME}/*.history* 2>/dev/null
tcp_wrappers防火墙
tcp_wrappers是Linux中用于分析TCP/IP数据包的软件,类似的如iptables
,与iptables不同的是,iptables通过监视系统运行状态阻挡恶意攻击。而tcp_wrappers
可以实现对系统中提供某些服务的控制。
tcp_wrappers有一个TCP的守护进程叫作tcpd。以ssh为例,每当有ssh的连接请求时,tcpd即会截获请求,先读取系统管理员所设置的访问控制文件,符合要求,则会把这次连接原封不动的转给真正的ssh进程,由ssh完成后续工作;如果这次连接发起的ip不符合访问控制文件中的设置,则会中断连接请求,拒绝提供ssh服务。
但tcp_wrappers仍存在有一定的局限性,Linux中的一个服务是否可以使用tcp_wrappers,取决于服务是否应用了libwrapped库文件,系统中默认的一些服务,如sshd、portmap、sendmail、xinetd、vsftpd、tcpd等都可以使用tcp_wrappers。
我们可以通过以下命令来检查系统中是否安装有tcp_wrappers
:
$ rpm -q tcp_wrappers
如果输出有关tcp_warppers的信息,则说明系统中已经安装了tcp_warppers。
tcp_wrappers有两个配置文件:/etc/hosts.allow
和/etc/hosts.deny
,
Linux对配置文件的执行是顺序的,先读取/etc/hosts.allow
,一旦满足就应用,而抛弃后面的配置,所以可以只设定/etc/hosts.allow
文件,然后在/etc/hosts.deny
中设置为所有计算机都不能登陆。
配置文件准从如下语法:
service:host(s) [:action]
其中,
- service:服务名,如sshd、vsftpd、sednmail等
- host(s):主机名或IP地址,可以有多个。
- action:动作,符合条件后采取的动作。
常见关键字有: - ALL:所有服务或所有IP。
- ALL EXCEPT:除指定的以外所有的服务或IP。
例如:
ALL:ALL EXCEPT 192.168.123.8
表示除192.168.123.8以外的请求都会被允许或拒绝,取决于以上内容写在哪个配置文件里。
附录
/etc/ssh/sshd_config文件内容
文本 | 作用 |
---|---|
Port 22 | 用来设置sshd监听的接口,建议修改为5位数字以上的陌生数字端口 |
Protocol 2 | 设置使用的SSH协议版本为SSH1或SSH2,SSH1存在漏洞,建议不变 |
ListenAddress 0.0.0.0 | 用于设置sshd服务器绑定的IP地址 |
HostKey /etc/ssh/ssh_host_dsa_key | 用于设置服务器密钥文件的位置 |
KeyRegenerationInterval 1h | 用于设置生成密钥的周期。可以防止入侵者利用盗取的密钥 |
ServerKeyBits 1024 | 用于定义密钥长度 |
SyslogFacility AUTHPRIV | 用于设置在记录来自sshd的消息时,是否给出facility code |
LogLevel INFO | 用于设置log文件的消息级别 |
LoginGraceTime 2m | 如果用户登录失败,在切断链接前。服务器需要等待的时间。 |
PermitRootLogin no | 是否允许root用户登录,建议设置为no |
StrictModes yes | 用于设置SSH在接受登陆请求之前是否检查用户根目录和rhosts文件的权限和属主。建议设置为yes |
RSAAuthentication no | 设置是否开启RSA密钥认证,只针对SSH1,使用RSA密钥登录时,需要开启 |
PubkeyAuthentication yes | 设置是否使用公钥验证,使用公钥验证时,需要开启 |
authorizedKeyFile .ssh/authorized_key | 用于设置公钥文件路径,与PubkeyAuthenticatio 配合使用 |
IgnoreUserKnownHosts no | 用于设置SSH在进行RSAAuthentication 安全认证时忽略用户的$HOME/.ssh/known_hosts 文件 |
IgnoreRhosts yes | 用于设置验证时是否使用~/.rhosts 和~/.shosts 文件。 |
PassWordAuthentication yes | 用于设置是否开启密码验证 |
PermitEmptyPasswds no | 用于设置是否允许用空密码登录系统,必须为no |
ChallengeResponseAuthenthtication no | 禁用s/key 密码 |
UsePAM no | 是否使用PAM认证 |
X11Forwarding yes | 用于设置是否允许X11转发 |
PrintMotd yes | 用于设置是否显示欢迎登录信息,建议加入警告信息以震慑攻击者 |
PrintLastLog no | 是否显示上次登录信息 |
Compression yes | 是否压缩命令 |
TCPKeepAlive yes | 是否防止死链接,通过心跳包的方式来进行连接 |
UseDNS no | 是否使用DNS反向解析 |
MaxStartups | 允许几个尚未登陆的连接,已建立的连接不算入其中。设置为5个可以防止对服务器进行恶意连接 |
MaxAuthTries 3 | 设置最大失败尝试登陆次数,合理设置可以防御撞库攻击 |
AllowUser <用户名> | 指定用户允许通过远程登录访问,多个用户以空格分隔 |
AllowGroups <组名> | 指定用户组允许通过远程登录访问,多个用户组以空格分隔 |
DenyUsers <用户名> | 指定用户禁止通过远程登录访问,多个用户以空格分隔 |
DenyGroups <组名> | 指定用户组禁止通过远程登录访问,多个用户组以空格分隔 |