前言:
一般情况下,我们对于账号的安全是比较随意的,因为在生产环境里,基本都是使用堡垒机这样的带有安全审计功能的工具对各个主机进行监控,管理,并且结合prometheus,zabbix等等其它监控软件,会对主机的一个整体概况有一个直观的感受。
OK,如果堡垒机什么的任意一个点被持有恶意的人攻破,那么,无疑是会引发数据泄露的,因此,我们需要从根源上对主机做安全加固,比如,
- 操作系统内的所有用户的密码设定复杂度,例如,密码长度不低于8位,必须带有大小写和特殊符号至少一个,密码不得设定为常用字,例如,不得设置system,system32 这样的密码,以增加恶意人员的暴力破解难度;
- 限制ssh远程登陆的IP范围,防止恶意的试探性的ssh链接;
- 限制除root用户外的其它普通用户的权限(也就是su 和sudo这些)
- 定期强制更换密码
相信如果有以上这些措施,那么,主机的安全将会得到极大的保证。
OK,下面将就如何做好服务器安全加固做一个简单的介绍。
一,
服务器的初始状态
首先,我们应该清楚,一个裸服务器安装完任意一个操作系统后,如果安装的时候没有定制动作,那么,此服务器是可以使用弱密码的,并且,通常只有一个root用户设置了密码(一般为了省事,root密码通常是一个弱密码),那,ssh服务通常也是开启的,并且默认的ssh链接端口是22,只要是同网段的其它机器都可以通过ssh工具(ssh工具指的是xshell,putty,securtCRT等等运维工具)连接服务器的。
OK,这样的现状无疑是对安全的一个重大挑战,那么,我们应该做一些定制化的动作,来规避这些安全方面的问题。
现有的一个问题是,Linux的版本众多,安全加固的手法和版本密切相关,例如,ubuntu和centos的安全加固可能会有比较大的不同,下面将以Linux内的两大系统ubuntu和centos为例,讲解如何进行服务器的安全加固。
二,
sshd服务的安全加固
1,
修改sshd服务的端口
此方法是Linux操作系统通用的,不管是哪种版本都适用,这么做得目的是防止黑客端口嗅探,例如,将22端口修改为58463,即使黑客通过nmap,medusa,或者其它类嗅探工具检测到了58463,很大概率它也不会知道此端口开放的服务是什么,可能需要其它技术,例如指纹技术才可以确定,无疑的,这么一个小改动会大大的提升sshd服务的安全。
修改方法非常简单,打开/etc/ssh/sshd_config文件
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
##########取消Port的注释,Port的值改为58463
Port 58463
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
重启sshd服务即可,ubuntu一般是service sshd restart centos一般是systemctl restart sshd,重新登陆后,可以看到端口是这样的:
[root@k8s-node1 ~]# netstat -antup |grep sshd
tcp 0 0 192.168.123.12:58463 0.0.0.0:* LISTEN 24630/sshd
2,
sshd限制IP登陆策略
黑白名单策略
linux 服务器通过设置/etc/hosts.allow和/etc/hosts.deny这个两个文件,hosts.allow许可大于hosts.deny可以限制或者允许某个或者某段IP地址远程 SSH 登录服务器,方法比较简单,且设置后立即生效,不需要重启SSHD服务,具体如下:
/etc/hosts.allow添加
sshd:192.168.0.1:allow #允许 192.168.0.1 这个IP地址SSH登录
sshd:192.168.0.:allow #允许192.168.0.1/24这段IP地址的用户登录,多个网段可以以逗号隔开,比如192.168.0.,192.168.1.:allow
/etc/hosts.allow添加
sshd:ALL #允许全部的ssh登录
/etc/hosts.deny添加
sshd:ALL #拒绝全部IP
那么,在实际操作中,一般策略是这样设置的:
口诀大体如下:拒绝所有,放行特定
拒绝策略,这个基本是不变的
/etc/hosts.deny添加
sshd:ALL #拒绝全部IP
放行特定,例如,我的是VMware虚拟机,网络是nat,sshd服务在192.168.123.12这个服务器上,网关是192.168.123.2,那么,接受同网段的其它服务器ssh连接即可:
#
# hosts.allow This file contains access rules which are used to
# allow or deny connections to network services that
# either use the tcp_wrappers library or that have been
# started through a tcp_wrappers-enabled xinetd.
#
# See 'man 5 hosts_options' and 'man 5 hosts_access'
# for information on rule syntax.
# See 'man tcpd' for information on tcp_wrappers
sshd:192.168.123.:allow
如果是使用xshell,那么,客户端IP应该是192.168.123.1,因此,使用精确IP定义:
#
# hosts.allow This file contains access rules which are used to
# allow or deny connections to network services that
# either use the tcp_wrappers library or that have been
# started through a tcp_wrappers-enabled xinetd.
#
# See 'man 5 hosts_options' and 'man 5 hosts_access'
# for information on rule syntax.
# See 'man tcpd' for information on tcp_wrappers
#sshd:192.168.123.:allow #整体网段放行
sshd:192.168.123.1 #单独IP放行
此时,如果要ssh登陆192.168.123.12这台服务器,那么,将只接受宿主机上安装的xshell,其它ssh登陆都会拒绝:
例如,在192.168.123.152上,登陆192.168.123.12,将会失败
root@k8s-node2:~# ssh -v -p 58463 192.168.123.12
OpenSSH_7.6p1 Ubuntu-4ubuntu0.5, OpenSSL 1.0.2n 7 Dec 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to 192.168.123.12 [192.168.123.12] port 58463.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_rsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /root/.ssh/id_ed25519-cert type -1
debug1: Local version string SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.5
ssh_exchange_identification: read: Connection reset by peer
当然了,还一种策略是allow文件内不写,deny内结合/var/log/secure这个安全审计日志,将恶意ssh登陆的IP封禁即可:
例如,封禁192.168.123这个网段,禁止其中所有IP使用ssh服务,此时,如果allow文件内有允许192.168.123网段,allow名单将会生效,deny名单失效。
[root@k8s-node1 ~]# cat /etc/hosts.deny
#
# hosts.deny This file contains access rules which are used to
# deny connections to network services that either use
# the tcp_wrappers library or that have been
# started through a tcp_wrappers-enabled xinetd.
#
# The rules in this file can also be set up in
# /etc/hosts.allow with a 'deny' option instead.
#
# See 'man 5 hosts_options' and 'man 5 hosts_access'
# for information on rule syntax.
# See 'man tcpd' for information on tcp_wrappers
#
#sshd:ALL #拒绝全部IP
sshd:192.168.123.:deny
注:黑白名单一般用于云主机以及在服务器遭遇攻击的时候,进行服务器保护。
三,
Linux的用户登陆策略
这里的用户策略指的是细分普通用户,指定普通用户以及root用户是否可以登陆系统
1,
usermod命令 锁定账号和解除锁定账号
[root@k8s-node1 ~]# usermod -L root ##锁定账号,这里是root,可以替换为其它任意普通账号
[root@k8s-node1 ~]# usermod -U root ##解除锁定账号,这里是root,可以替换为其它任意普通账号
如果是这种锁定账号,那么,ssh登陆的时候,即使密码正确也会拒绝
2,
chsh命令
更改用户的登陆shell
本例仍然是以root用户为例
禁止root登陆
[root@k8s-node1 ~]# chsh -s /sbin/nologin root
Changing shell for root.
Shell changed.
恢复root用户登陆
这里需要注意,我们的可用shell有哪些,需要查询一下:
[root@k8s-node1 ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
选择以上的shell,重新设定一下即可,例如使用sh:
[root@k8s-node1 ~]# chsh -s /bin/sh root
Changing shell for root.
Shell changed.
###xshell登陆后,变成容器一般使用的shell了
WARNING! The remote SSH server rejected X11 forwarding request.
Last login: Wed Mar 1 00:04:12 2023 from 192.168.123.1
-sh-4.2#
####恢复成bash shell
[root@k8s-node1 ~]# chsh -s /usr/bin/bash root
Changing shell for root.
Shell changed.
WARNING! The remote SSH server rejected X11 forwarding request.
Last login: Wed Mar 1 00:07:55 2023 from 192.168.123.1
[root@k8s-node1 ~]#
四,
Linux 用户的密码策略
用户的密码策略具体包括:1,密码的强度 2,密码的时效 ,该策略的实施是借由Linux的内核模块PAM实现。
首先,需要说明的是,密码强度也可以称之为密码的复杂度,具体来说,就是设定密码的时候,密码至少需要几位的字符组成,字符里是否包含大小写字面,是否是常见单词,是否是字符和数字混合的密码,而默认的,例如新安装的操作系统,是没有任何的密码复杂度的,也就是密码没有任何要求,随意的密码都可以设置,这显然是不符合我们对于安全的需求的,因此,我们需要设置密码的复杂度。
附1:密码的等级划分
弱密码:简单的由纯数字或者字母组成的密码,并且密码长度小于6位,通常,我们就可以认为这个是弱密码,例如,支付宝的密码,银行卡的密码(这里说明一下,虽然银行卡密码比较短,但登陆次数有限制,例如,某个银行账户,密码错误3次,账户就锁定很长时间,这无疑给暴力破解增加了很大的难度),或者schoole321这样的由简单的单词加比较少的数字组成的密码,以及system135,admin,admin32,等等这样的由单词和少量数字组成的密码,我们都可以认为这个是弱密码。
强密码:由至少8位的字符,特殊符号和数字混合组成的,字符里有大小写,不包含常用单词,那么,这样的密码我们认为是一个强密码,例如,Ej@l)df1 这样的密码就是一个强密码,当然,这样的密码暴力破解通常是需要至少几个月的时间。
其次,默认的是新安装的操作系统任何密码都永不过期,如果密码不经常重设,那么,暴力破解密码就很有希望。例如,一个操作系统的root密码几年没有变化,那么,一个8位的由大小写和数字组成的密码,通常暴力破解也就是3 4个月的时间(如果字典是比较合适的情况下),如果是12位的强密码,那么,暴力破解的时间是几何增长的,几年十几年都有可能。因此,一个合适的密码强度可以完美的保护重要的服务器(自己泄露那种就没办法了,堡垒通常都是由内部攻克的)。
OK,密码的重要性不在这里废话了,那么,下面就讲述如何通过PAM模块自定义一个合适的密码策略。
附2:PAM模块是Linux内核的安全认证模块,说它是一个函数库也没什么问题,主要就是负责安全认证工作,例如,检查账号的登陆合法性,密码的合理性等等工作都是由这个PAM模块负责。
1 PAM的模块类型
Linux-PAM有四种模块类型,分别代表四种不同的任务,它们是:
- auth模块: 用来对用户的身份进行识别.如:提示用户输入密码,或判断用户是否为root等,主要是认证管理
- account模块: 对帐号的各项属性进行检查.如:是否允许登录,是否达到最大用户数,或是root用户是否允许在这个终端登录等,主要是账号管理
- session模块: 这个模块用来定义用户登录前的,及用户退出后所要进行的操作.如:登录连接信息,用户数据的打开与关闭,挂载文件系统等,主要是会话管理
- password模块: 使用用户信息来更新.如:修改用户密码,设定密码复杂度等等,主要是密码管理
那么,在centos和Debian系列里,分别是/etc/pam.d/system-auth(centos,Redhat)/etc/pam.d/common-password(Debian系列,ubuntu是包含在Debian的)这两个文件里的password模块内实现
在CentOS 7上实现密码复杂度策略设置,主要是由PAM pwquality模块完成
1、备份原有配置文件
cp /etc/pam.d/system-auth /etc/pam.d/system-auth.bak
2、设置复杂度策略
vim /etc/pam.d/system-auth
找到包含pam_pwquality.so模块的行,将原有行注释并修改为如下的新配置,密码长度最少12位,至少包含一个大写字母,一个小写字母,一个数字,一个特殊符号。
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= minlen=12 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 enforce_for_root
- minlen=12 密码最小长度为8个字符。
- lcredit=-1 密码应包含的小写字母的至少一个
- ucredit=-1 密码应包含的大写字母至少一个
- dcredit=-1 将密码包含的数字至少为一个
- ocredit=-1 设置特殊字符的最小数量,例如@,#、! $%等,至少要有一个
- enforce_for_root 确保即使是root用户设置密码,也应强制执行复杂性策略。
Ubunu设置密码规则
- 安装crackilib模块,注意,ubuntu的密码策略主要是由cracklib模块实现
sudo apt-get install libpam-cracklib
修改 /etc/pam.d/common-password文件
添加以下配置信息
# here are the per-package modules (the "Primary" block)
password requisite pam_cracklib.so retry=3 minlen=8 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 enforce_for_root
password [success=1 default=ignore] pam_unix.so obscure use_authtok try_first_pass sha512 remember=5
- retry=3 允许重试次数
- minlen=8 密码最小长度
- difok=3 默认值是1,允许新旧密码中相同的字符数
- ucredit 新密码中至少有1个大写字符
- lcredit=-1 新密码中至少有1个小写字符
- dcredit=-1 新密码中至少有1个数字
- ocredit=-1 新密码中至少有1个特殊字符
- enforce_for_root 此规则对root生效
五,
Linux系统内的密码时效设置和登陆失败策略
密码时效策略是保证按期及时的修改重要用户的密码,防止发生密码泄露,而登陆失败策略则是破坏暴力破解方式的无限登陆,比如,某个用户的密码错误,则一段时间内禁止再次登陆,如果配合密码策略,设置一个强密码,那么,暴力破解的情况是可以完全杜绝的。
1,密码时效策略
编辑 /etc/login.defs 文件,可以设置当前密码的有效期限,具体变量如下所示:
复制代码代码如下:
sudo vi /etc/login.defs
PASSMAXDAYS 150 PASSMINDAYS 0 PASSWARNAGE 7
这些设置要求用户每5个月改变他们的密码,并且会提前7天提醒用户密码快到期了。
如果你想为每个用户设置不同的密码期限,使用 chage 命令。下面的命令可以查看某个用户的密码限期:
复制代码代码如下:
$ sudo chage -l root
默认情况下,用户的密码永不过期。
下面的命令用于修改 xmodulo 用户的密码期限:
复制代码代码如下:
$ sudo chage -E 6/30/2023 -m 5 -M 90 -I 30 -W 14 root
上面的命令将用户root的密码期限设为2023年3月3日。另外,修改密码的最短周期为5天,最长周期为90天。密码过期前14天会发送消息提醒用户,过期后帐号会被锁住30天。
2.,用户登录失败策略
修改 /etc/pam.d/common-auth 文件,添加下面配置
auth required pam_tally2.so deny=3 lock_time=10 unlock_time=3600 even_deny_root root_unlock_time=60
deny=3 允许登录失败次数
lock_time=10 每次登录失败锁定时间,单位 秒
unlock_time=3600 触发登录失败次数后锁定时间 单位 秒
even_deny_root 针对所有用户生效,包括root