原文:imthenachoman/How-To-Secure-A-Linux-Server: An evolving how-to guide for securing a Linux server. (github.com)
确定你的目标
在你确定目标之前,你首先需要建立你的威胁模型。怎么建立威胁模型呢,这里有一些你需要考虑的几个点:
- 物理机访问对你的服务器算是一个威胁吗,比如某人偷摸着摸到你的服务器跟前。不过现在都是云主机,很少有这种情况;
- 你是否会开启额外的端口以允许外界访问你的服务器,个人不推荐开启额外端口访问,能使用域名+反向代理就使用,一个是安全,另一个是访问速度快;
- 个人计算机和服务器文件共享问题,服务器上的一个文件夹挂载到个人电脑上,传文件方便,但是中招可能性会大很多。
选择Linux分支
这一部分旨在教导你如何去选择Linux分支,现在Linux分支有点多,有 Debain系列,小红帽系列,Arch Linux等等,还有国产UOS,Deepin,TencentOS,AliOS,OpenCloudOS等等。
下面可供你选择的原因:
3.你熟悉的操作系统,使用前建议你先熟悉熟悉;
安装Linux
这个章节超出文章讨论范围,主要是每个Linux分支可能不太一样,如果你需要帮助,可以查看Linux分支相关文档或者各类博客等,大概安装步骤如下:
安装后可以根据自己的需要自定义安装Linux,这样一来会对服务器拥有更高的控制能力,二来也不必要安装一些额外的功能。如果你需要安装软件,可以通过ssh连接到服务器中进行必要的安装。
安装准备
- 如果你依赖于额外的端口去访问外界,等系统安装完毕或者系统加固完毕需要禁用端口;
- 如果服务器访问不需要什么硬件,建议你通过SSH协议去直接访问;
- 永远保持系统更新,这是很关键的,不然等过阵子你可能拥有跟不上了,历史欠账太多,更新命令如下:
sudo apt update &&sudo apt upgrade && sudo apt dist-upgrade
- 配置好其他需要的设置项:
- 配置网络
- 配置挂载路径
- 创建用户初始化账户
- 安装核心软件,例如
tree
、man
、ls
- 系统安全故障邮件通知,可以用谷歌邮箱,163邮箱等等,配置到服务器上即可,但一般国内不太配置这个,太麻烦;
- 推荐在开始之前阅读CIS Benchmarks。
其他重要事项
- 指南是以dabian系基础上写的,其他Linux发行分支可能用不了,如果你发现用不了的部分,请联系作者;
- 文件路径和设置也可能略有不同,如果发现有不同点,可以查看相应Linux发行版文档;
- 在完整参考指南前,可以通读一遍,有些示例可能跟你本地服务器上配置不太相同,或者顺序不太一样;
- 不要盲目的复制粘贴,尤其在不了解这个脚本是干啥的之前,一些脚本可能破坏你的服务器。
SSH服务器
重要提醒★★★
在你要改动SSH配置文件之前,建议你开着至少2个SSH终端,这样即使改坏了你也能把它改回来。
感谢Sonnenbrand提供这个小技巧。
SSH公钥/私钥
为什么要用公钥/私钥
连接服务器时,SSH公钥私钥远比密码安全,简单和快速。因为他不需要输入密码,不过也很容易造成密码遗忘,这就是手机要求72小时内必须输入一遍密码,要不然时间久了还真容易忘。
运作原理和流程
深层来讲,公钥/私钥通过验证密钥对是不是匹配来正常验证服务器通信的。
对SSH服务器来说,公钥私钥对是由客户端创建的。你需要去确保密钥对的安全性,尤其是确保私钥的安全。即便公钥是所有人可见的,你也需要保证其安全,因为有些人可能用公钥来尝试连接你的服务器。
当你连接服务器时,SSH协议会来搜寻你的公钥是不是匹配你的客户端,一般来说公钥位置放在
~/.ssh/authorized_keys
文件内。注意这个文件是在你需要登录账号的home文件夹内。当创建好公钥后,你需要把公钥添加到~/.ssh/authorized_keys
内,一个简单的办法是用U盘拷贝,另一个办法是通过ssh-copy-id
来传输公钥,现在都是云时代了,一般用第二种办法,毕竟运营商的物理机你是不可能看到的。创建好公钥后,公钥就放在你的
~/.ssh/authorized_keys
内了。在主机上,SSH使用公钥和私钥去验证你和建立SSH安全连接。建立后服务器会创建一个单独的线程用于与你的电脑通信。深刻来说,SSH协议通信是通过公钥来加密信息,进而发送到你的电脑上,如果你的电脑没有私钥钥,或者私钥不对,那这个信息就不能解密了,然后服务器就连接失败了。公钥私钥相对来说安全性更高,但如果你设置
/etc/ssh/sshd_config
内的配置PasswordAuthentication no
,那你就不能用公钥私钥来登录服务了。在设置好公钥私钥后,你也应该设置一个二次登录密码,不过这样你登录过程就不是全自动的了,要麻烦一些。
ssh-agent
允许你在内存中拥有未加密的私钥一段时间,运行 ssh-add
命令,他会提示你输入你的密码,这样你就不需要每次都输入密码了。根据linux-audit.com/ 上说的,我们下面会使用Ed25519方案;Ed25519方案提供比ECDSA方案和DSA方案更安全,性能也更好。
目标
在你的客户端(个人电脑)上创建你的私钥,在服务器上创建公钥。
如果你之前没有创建聒公钥和私钥,你需要创建他,如果你创建过,就可以忽略这个步骤。
参考文章/文献
- www.ssh.com/ssh/public-…
- help.ubuntu.com/community/S…
- linux-audit.com/using-ed255…
- www.digitalocean.com/community/t…
- wiki.archlinux.org/index.php/S…
- www.ssh.com/ssh/copy-id
man ssh-keygen
man ssh-copy-id
man ssh-add
步骤
ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_ed25519.
Your public key has been saved in /home/user/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:F44D4dr2zoHqgj0i2iVIHQ32uk/Lx4P+raayEAQjlcs user@client
The key's randomart image is:
+--[ED25519 256]--+
|xxxx x |
|o.o +. . |
| o o oo . |
|. E oo . o . |
| o o. o S o |
|... .. o o |
|.+....+ o |
|+.=++o.B.. |
|+..=**=o=. |
+----[SHA256]-----+
如果你设置了passphrase(密码),当你登录服务器时,你需要每次都登录。
2. 添加公钥到服务器中的~/.ssh/id_ed25519.pub
文件内。如果你处在家庭网络,你可能不会遭遇MIM攻击,所以你可以试试用ssh-copy-id
来传输你的公钥。
ssh-copy-id user@server
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub"
The authenticity of host 'host (192.168.1.96)' can't be established.
ECDSA key fingerprint is SHA256:QaDQb/X0XyVlogh87sDXE7MR8YIK7ko4wS5hXjRySJE.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
user@host's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'user@host'"
and check to make sure that only the key(s) you wanted were added.
现在你可以接下来操作了。
创建SSH允许登录组
为什么创建
创建SSH组能让你更快捷的控制服务器,通过以组的形式控制允许登录的账号,我们可以更快捷的添加或者删除SSH许可。
运行原理
下面我们将在/etc/ssh/sshd_config
文件内添加允许SSH登录的账号组。
目标
创建UNIX 账号组来限制账号登录Linux服务器
提示
这是设置/etc/ssh/sshd_config
安全性的先决条件。
使用命令
- man groupadd
- man usermod
操作步骤
sudo groupadd sshusers
sudo usermod -a -G sshusers user1
sudo usermod -a -G sshusers user2
sudo usermod -a -G sshusers ...
通过/etc/ssh/sshd_config
文件来确保安全
重要性
SSH是进入你服务器的门户,所以确保SSH安全尤其重要,尤其是访问外网。
工作原理
SSH服务器默认使用/etc/ssh/sshd_config
配置文件,所以要想服务器安全一点我们可以在这里下一点功夫。
目标
配置SSH文件配置,首先确保你完成了SSH账号组配置。
参考文章
- Mozilla's OpenSSH guidelines for OpenSSH 6.7+ at infosec.mozilla.org/guidelines/…
- linux-audit.com/audit-and-h…
- www.ssh.com/ssh/sshd_co…
- www.techbrown.com/harden-ssh-… (broken; try - web.archive.org/web/2020041…)
- serverfault.com/questions/6…
man sshd_config
操作步骤
/etc/ssh/sshd_config
备份,移除注释,提高文件可读性;sudo cp --archive /etc/ssh/sshd_config /etc/ssh/sshd_config-COPY-$(date +"%Y%m%d%H%M%S")
sudo sed -i -r -e '/^#|^$/ d' /etc/ssh/sshd_config
/etc/ssh/sshd_config
文件,按照下面提示添加或者更改设置。注意:SSH协议重复设置会有问题,例如存在两个相同设置,一个是
ChallengeResponseAuthentication no
,另一个是ChallengeResponseAuthentication yes
,SSH会保留第一个,而忽略第二个。如果你的/etc/ssh/sshd_config
存在这种情况,为避免出现问题,你需要查找你的文件并删除重复设置项。########################################################################################################
# start settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
########################################################################################################
# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Use kernel sandbox mechanisms where possible in unprivileged processes
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
# Note: This setting is deprecated in OpenSSH 7.5 (https://www.openssh.com/txt/release-7.5)
# UsePrivilegeSeparation sandbox
########################################################################################################
# end settings from https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67 as of 2019-01-01
########################################################################################################
# don't let users set environment variables
PermitUserEnvironment no
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp internal-sftp -f AUTHPRIV -l INFO
# only use the newer, more secure protocol
Protocol 2
# disable X11 forwarding as X11 is very insecure
# you really shouldn't be running X on a server anyway
X11Forwarding no
# disable port forwarding
AllowTcpForwarding no
AllowStreamLocalForwarding no
GatewayPorts no
PermitTunnel no
# don't allow login if the account has an empty password
PermitEmptyPasswords no
# ignore .rhosts and .shosts
IgnoreRhosts yes
# verify hostname matches IP
UseDNS yes
Compression no
TCPKeepAlive no
AllowAgentForwarding no
PermitRootLogin no
# don't allow .rhosts or /etc/hosts.equiv
HostbasedAuthentication no
配置如下设置项
设置项 | 合法数值 | 示例 | 描述 | 备注 |
---|---|---|---|---|
AllowGroups | local UNIX group name | AllowGroups sshusers |
group to allow SSH access to | |
ClientAliveCountMax | number | ClientAliveCountMax 0 |
maximum number of client alive messages sent without response | |
ClientAliveInterval | number of seconds | ClientAliveInterval 300 |
timeout in seconds before a response request | |
ListenAddress | space separated list of local addresses |
|
local addresses sshd should listen on |
See Issue #1 for important details. |
LoginGraceTime | number of seconds | LoginGraceTime 30 |
time in seconds before login times-out | |
MaxAuthTries | number | MaxAuthTries 2 |
maximum allowed attempts to login | |
MaxSessions | number | MaxSessions 2 |
maximum number of open sessions | |
MaxStartups | number | MaxStartups 2 |
maximum number of login sessions | |
PasswordAuthentication | yes or no |
PasswordAuthentication no |
if login with a password is allowed | |
Port | any open/available port number | Port 22 |
port that sshd should listen on |
确保没有重复项,下面是检查重复项的语法
awk 'NF && $1!~/^(#|HostKey)/{print $1}' /etc/ssh/sshd_config | sort | uniq -c | grep -v ' 1 '
sudo service sshd restart
sudo sshd -T
port 22
addressfamily any
listenaddress [::]:22
listenaddress 0.0.0.0:22
usepam yes
logingracetime 30
x11displayoffset 10
maxauthtries 2
maxsessions 2
clientaliveinterval 300
clientalivecountmax 0
streamlocalbindmask 0177
permitrootlogin no
ignorerhosts yes
ignoreuserknownhosts no
hostbasedauthentication no
...
subsystem sftp internal-sftp -f AUTHPRIV -l INFO
maxstartups 2:30:2
permittunnel no
ipqos lowdelay throughput
rekeylimit 0 0
permitopen any
删除短Diffie-Hellman密钥
为什么这么做
根据Mozilla针对OpenSSH 6.7+的OpenSSH指南,“所有使用的Diffie-Hellman模块应至少为3072位长”。
Diffie-Hellman算法针对SSH连接建立。
目标
移除少于3072比特长度的Diffie-Hellman密钥。
参考文章
- Mozilla's OpenSSH guidelines for OpenSSH 6.7+ at infosec.mozilla.org/guidelines/…
- infosec.mozilla.org/guidelines/…
man moduli
操作步骤
sudo cp --archive /etc/ssh/moduli /etc/ssh/moduli-COPY-$(date +"%Y%m%d%H%M%S")
sudo awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.tmp
sudo mv /etc/ssh/moduli.tmp /etc/ssh/moduli
2FA/MFA认证
虽然前面的措施很完善了,但黑客还是可以尝试登录你的服务器。Fail2ban 工具能监控谁登录你的服务器并干掉多次尝试登录的人,另外,添加两因素认证也很棒,国内用两因素认证的人不多,主要是做技术的和国外用的多,常见的两因素认证有OnePass,Google Auth和MicroSoft Auth等,国内的话我推荐使用微软的这款,因为能备份数据。
使用两因素认证后,用户登录需要两方面的认证,一个是需要密码,另一个是由两因素认证器生成的6位数随机密码,随机密码会存在30秒,之后刷新。
什么情况下不考虑
如果你感觉这个是在麻烦,你可以不考虑,哈哈哈哈哈,原文是这么说的:
Many folks might find the experience cumbersome or annoying. And, access to your system is dependent on the accompanying authenticator app that generates the code.
工作原理
在Linux中,PAM用于安全认证。PAM有四个部分,你可以试试读读en.wikipedia.org/wiki/Linux_…,第二部分讨论的就是认证。
当你用终端登录Linux服务器时,你的登录请求会发送到PAM认证任务中,然后PAM会验证你的密码。你可以自定义使用规则。例如,你可以设置一组规则可以直接从终端登录服务器,设置另一组规则通过SSH协议登录服务器。
本节将更改通过SSH登录时的身份验证规则,使其需要密码和6位代码。
我们将使用谷歌libpam-google-authenticator PAM 模块去创建和验证TOTP验证码。你可以读取下面的文章去了解TOTP的工作原理。
- fastmail.blog/2016/07/22/…
- jemurai.com/2018/10/11/…
然后我们需要做的是设置服务器SSH PAM,让用户登录的时候带着他们的Token,不然登录不了。PAM第一步会验证密码,第二步验证5位数Token,如果都对了,才会允许用户登录。
目标
设置SSH连接的两因素认证。在操作前,你需要确保你的两因素认证器好不好使。指南中使用google-authenticator-libpam。
参考文章
- github.com/google/goog…
- en.wikipedia.org/wiki/Linux_…
- en.wikipedia.org/wiki/Time-b…
- fastmail.blog/2016/07/22/…
- jemurai.com/2018/10/11/…
操作步骤
sudo apt install libpam-google-authenticator
google-authenticator
。google-authenticator
Do you want authentication tokens to be time-based (y/n) y
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@host%3Fsecret%3DR4ZWX34FQKZROVX7AGLJ64684Y%26issuer%3Dhost
...
Your new secret key is: R3NVX3FFQKZROVX7AGLJUGGESY
Your verification code is 751419
Your emergency scratch codes are:
12345678
90123456
78901234
56789012
34567890
Do you want me to update your "/home/user/.google_authenticator" file (y/n) y
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
By default, tokens are good for 30 seconds. In order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with
poor time synchronization, you can increase the window from its default
size of +-1min (window size of 3) to about +-4min (window size of
17 acceptable tokens).
Do you want to do so? (y/n) y
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y
注意这个不要用管理员运行。
3. 创建PAM SSH配置备份。
sudo cp --archive /etc/pam.d/sshd /etc/pam.d/sshd-COPY-$(date +"%Y%m%d%H%M%S")
/etc/pam.d/sshd
:auth required pam_google_authenticator.so nullok
可以参考这里来看nullok是什么意思。here (github.com)
一键命令:
echo -e "\nauth required pam_google_authenticator.so nullok # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/pam.d/sshd
/etc/ssh/sshd_config
:ChallengeResponseAuthentication yes
一键命令
sudo sed -i -r -e "s/^(challengeresponseauthentication .*)$/# \1 # commented by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")/I" /etc/ssh/sshd_config
echo -e "\nChallengeResponseAuthentication yes # added by $(whoami) on $(date +"%Y-%m-%d @ %H:%M:%S")" | sudo tee -a /etc/ssh/sshd_config
sudo service sshd restart