加固SSH服务器的10个基本最佳实践

通过更安全的认证、最小权限访问、防火墙规则、速率限制、更新和日志检查来加固您的SSH服务器。

加固SSH服务器的10个基本最佳实践

安全外壳(SSH)通常是您服务器的前门。如果这扇门接受弱密码、直接root登录或来自整个互联网的流量,攻击者会很快找到它。

本指南为您提供了10个实用的SSH服务器加固步骤,适用于常见Linux发行版上的OpenSSH。在测试每个更改时,请保持一个工作会话打开,以便在防火墙规则或配置编辑阻止新登录时能够恢复。

1. 更改默认SSH端口

默认的SSH端口是22。这是众所周知的,并且不断被寻找易受攻击服务器的自动化机器人扫描。更改默认端口提供了一个简单但有效的隐蔽层。虽然本身不是安全措施,但它显著减少了自动化扫描的噪音,并有助于避免许多机会主义攻击。

要更改端口,请编辑sshd_config文件,通常位于/etc/ssh/sshd_config

sudo nano /etc/ssh/sshd_config

找到Port 22这一行(如果不存在则添加),并将22更改为一个非标准的、未分配的端口号(例如,222249152-65535是用户/动态端口)。

#Port 22
Port 2222

在重启SSH之前,在防火墙中允许新端口。然后在新端口上测试新登录,然后再移除对端口22的访问。

# 对于UFW(简单防火墙):
sudo ufw allow 2222/tcp
sudo ufw reload

# 对于Firewalld:
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

sudo sshd -t
sudo systemctl restart sshd

提示: 在测试配置更改时,始终至少保持一个SSH会话打开。如果您被锁定,可以在活动会话中恢复更改。

2. 禁用root登录

强烈建议不要通过SSH直接以root身份登录。root用户拥有不受限制的权限,使其成为攻击者的主要目标。如果攻击者获得root访问权限,他们将完全控制您的系统。相反,以普通、非特权用户身份登录,然后使用sudo执行管理任务。

sshd_config中,找到PermitRootLogin指令并将其设置为no

PermitRootLogin no

保存并重启SSH服务:

sudo systemctl restart sshd

3. 使用基于密钥的身份验证

基于密码的身份验证容易受到暴力破解攻击和字典攻击,特别是如果用户选择弱密码。SSH基于密钥的身份验证是一种更安全的替代方案。它使用一对加密密钥:存储在服务器上的公钥和存储在本地机器上的私钥。只有拥有匹配私钥的客户端才能进行身份验证。

实施基于密钥的身份验证的步骤(简要):

  1. 在本地机器上生成密钥对:

    ssh-keygen -t ed25519 -C "[email protected]"
    
    • ed25519是一种现代、安全的算法,具有固定的密钥大小。rsa也很常见;如果使用RSA,请生成一个大密钥,例如ssh-keygen -t rsa -b 4096
  2. 将公钥复制到服务器:

    ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your_server_ip
    

    或者,手动将~/.ssh/id_ed25519.pub的内容追加到服务器上您要登录用户的~/.ssh/authorized_keys文件中。

  3. 确保服务器上的权限正确:

    • ~/.ssh目录:700(仅所有者可读写执行)
    • ~/.ssh/authorized_keys文件:600(仅所有者可读写)
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    

4. 禁用密码身份验证

一旦您成功设置并测试了所有必要用户的基于密钥的身份验证,您应该完全禁用密码身份验证。这消除了SSH安全中最薄弱的环节,使暴力破解密码攻击变得不可能。

sshd_config中,将PasswordAuthentication设置为no

PasswordAuthentication no
KbdInteractiveAuthentication no

在某些发行版上,PAM或键盘交互式身份验证仍然可能提示输入密码,除非您也禁用它。在关闭现有会话之前,请使用新的终端进行测试。

保存并重启SSH服务:

sudo systemctl restart sshd

警告: 在验证基于密钥的身份验证对所有需要访问的用户都正常工作之前,切勿禁用密码身份验证。否则,您可能会将自己锁定在服务器之外。

5. 限制用户访问

默认情况下,服务器上的任何用户帐户都可以尝试通过SSH登录。您可以将SSH访问限制为仅特定用户或组,从而最小化攻击面。

sshd_config中使用AllowUsersAllowGroups指令。

要仅允许特定用户(例如,adminuserdevuser):

AllowUsers adminuser devuser

要仅允许特定组的成员(例如,sshusers):

AllowGroups sshusers

提示: 如果您有多个用户,通常最好使用AllowGroups。创建一个专门的SSH访问组,并将授权用户添加到其中。

sudo groupadd sshusers
sudo usermod -aG sshusers adminuser
sudo usermod -aG sshusers devuser

进行更改后,保存并重启SSH。

6. 为SSH密钥使用强密码短语

虽然基于密钥的身份验证很强大,但您的私钥仍然是一个关键资产。如果攻击者获得对您本地机器的访问权限,他们可能会窃取您的私钥。强密码短语会加密您的私钥,要求在使用前解锁它。这增加了一层额外的安全保护,即使私钥落入他人之手,也能保护它。

在生成SSH密钥时(如步骤3),系统会提示您输入密码短语。选择一个长、复杂且易记的密码短语,并且与您使用的任何其他密码不同。

7. 实施连接速率限制(Fail2Ban)

即使使用基于密钥的身份验证,SSH服务器仍然会受到连接尝试的影响。像Fail2Ban这样的工具可以主动监控SSH日志,查找来自同一IP地址的重复失败登录尝试,并使用防火墙规则自动阻止该IP地址一段时间。

安装(例如,Debian/Ubuntu):

sudo apt update
sudo apt install fail2ban

Fail2Ban开箱即用,具有默认的SSH规则,但您可以通过将jail.conf复制到jail.local并编辑来定制其配置。

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

jail.local中,您可以调整[sshd]部分的bantimefindtimemaxretry

[sshd]
enabled = true
port = 2222 # 您的新SSH端口
logpath = %(sshd_log)s
maxretry = 3
bantime = 1h
findtime = 10m

配置更改后重启Fail2Ban

sudo systemctl restart fail2ban

8. 保持SSH服务器软件更新

软件漏洞不断被发现和修补。运行过时的SSH守护程序软件(OpenSSH)意味着您可能暴露于已知的漏洞。定期更新服务器的软件,包括OpenSSH服务器软件包,对于修补安全漏洞至关重要。

# 对于Debian/Ubuntu:
sudo apt update && sudo apt upgrade

# 对于CentOS/RHEL:
sudo yum update
# 或
sudo dnf update

配置您的系统以在适当的情况下自动应用安全更新,或建立手动更新的例行程序。

9. 监控SSH日志以发现可疑活动

即使采取了强大的预防措施,保持警惕也是关键。定期检查SSH身份验证日志,以检测异常模式、失败的登录尝试或未经授权的访问尝试。这有助于您识别潜在的入侵或持续的攻击。

SSH日志通常位于:

  • /var/log/auth.log(Debian/Ubuntu)
  • /var/log/secure(CentOS/RHEL)
  • 使用journalctl(systemd系统):
    sudo journalctl -u sshd -f
    

查找重复的失败身份验证尝试、来自异常IP地址的登录或陌生用户的成功登录。像LogwatchElastic Stack(ELK)这样的工具可以自动化日志分析和警报,适用于较大的环境。

10. 配置防火墙规则以限制访问

防火墙是您的第一道防线。默认情况下,它应该阻止所有传入流量,除了您明确需要暴露的服务。对于SSH,这意味着只允许在您选择的端口(例如,2222)上建立连接,并且理想情况下,只允许来自特定受信任IP地址或网络的连接。

使用UFW(简单防火墙)的示例:

允许来自特定IP地址192.168.1.100的SSH连接到端口2222

sudo ufw allow from 192.168.1.100 to any port 2222

允许来自特定子网192.168.1.0/24的SSH连接:

sudo ufw allow from 192.168.1.0/24 to any port 2222

使用Firewalld(CentOS/RHEL)的示例:

允许来自特定IP地址192.168.1.100的SSH连接到端口2222

sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port=2222 protocol="tcp" accept'
sudo firewall-cmd --reload

警告: 如果您从动态IP地址管理服务器,请谨慎使用严格的防火墙规则。您可能需要允许来自更广泛范围的访问或使用VPN。

额外的加固提示

除了基本的10个要点之外,考虑以下指令以获得更高的安全性:

  • MaxAuthTries:限制每次连接的身份验证尝试次数。默认值为6。降低它(例如,3)可以减少暴力破解的机会。在sshd_config中设置。
    MaxAuthTries 3
    
  • LoginGraceTime:限制用户进行身份验证的时间。默认值为2分钟。降低它(例如,30s)可以减少慢速攻击的窗口。
    LoginGraceTime 30s
    
  • ClientAliveIntervalClientAliveCountMax:防止空闲的SSH会话无限期保持打开状态。ClientAliveInterval每隔X秒发送一个保活消息。如果错过了ClientAliveCountMax次响应,连接将被终止。
    ClientAliveInterval 300
    ClientAliveCountMax 2
    
  • Banner:在身份验证之前显示警告消息。这向潜在的未授权用户提供法律通知。
    Banner /etc/issue.net
    
    创建/etc/issue.net文件,并包含您想要的警告消息。

实际要点

从消除最大风险的更改开始:禁用root登录、要求SSH密钥、限制谁可以连接,并在可能时限制源网络。在关闭当前会话之前,使用sshd -t和新的登录会话测试每个更改。