20 个 OpenSSH 服务器最佳安全实践
OpenSSH是 SSH 协议的实现。建议使用 OpenSSH 进行远程登录、备份、通过 scp 或 sftp 进行远程文件传输等。SSH 非常适合保持两个网络和系统之间交换的数据的机密性和完整性。但是,主要优势是通过使用公钥加密进行服务器身份验证。不时有关于 OpenSSH 零日漏洞的传言。本页介绍如何保护在 Linux 或类 Unix 系统上运行的 OpenSSH 服务器以提高 sshd 安全性。
OpenSSH 默认设置
- TCP 端口 — 22
- 服务器配置文件 – sshd_config(位于/etc/ssh/)
- 客户端配置文件 – ssh_config(位于/etc/ssh/)
- 用户私钥/公钥和客户端配置 –$HOME/.ssh/目录
1. 使用基于 SSH 公钥的登录
OpenSSH 服务器支持各种身份验证。建议您使用基于公钥的身份验证。首先,在本地台式机/笔记本电脑上使用以下 ssh-keygen 命令创建密钥对:
DSA 和 RSA 1024 位或更低的 ssh 密钥被认为是弱密钥。请避免使用它们。当 ssh 客户端的向后兼容性受到关注时,会选择 RSA 密钥而不是 ECDSA 密钥。所有 ssh 密钥都是 ED25519 或 RSA。请勿使用任何其他类型。
$ ssh-keygen -t key_type -b bits -C "comment"
$ ssh-keygen -t ed25519 -C "Login to production cluster at xyz corp"
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_aws_$(date +%Y-%m-%d) -C "AWS key for abc corp clients"
接下来,使用 ssh-copy-id 命令安装公钥:
当提示时提供用户密码。验证基于 ssh 密钥的登录是否适合您:
有关 ssh 公钥身份验证的更多信息,请参阅:
$ ssh-copy-id -i /path/to/public-key-file user@host
$ ssh-copy-id user@remote-server-ip-or-dns-name
$ ssh-copy-id vivek@rhel7-aws-server
$ ssh vivek@rhel7-aws-server
- keychain:为备份脚本设置安全无密码 SSH 访问
- sshpass:登录 SSH 服务器/使用 Shell 脚本提供 SSH 密码
- 如何在 Linux / Unix 系统上设置 SSH 密钥
- 如何使用 Ansible DevOPS 工具将 ssh 公钥上传为 authorized_key
- Linux/Unix 服务器上基于 SSH 公钥的身份验证
2.禁用root用户登录
在禁用 root 用户登录之前,请确保普通用户可以以 root 身份登录。例如,允许 vivek 用户使用 sudo 命令以 root 身份登录。
如何在 Debian/Ubuntu 上将 vivek 用户添加到 sudo 组
允许组 sudo 的成员执行任何命令。将用户 vivek 添加到 sudo 组:使用id 命令
$ sudo adduser vivek sudo
验证组成员身份
$ id vivek
如何在 CentOS/RHEL 服务器上将 vivek 用户添加到 sudo 组
允许 wheel 组中的人员在 CentOS/RHEL 和 Fedora Linux 服务器上运行所有命令。使用 usermod 命令将名为 vivek 的用户添加到 wheel 组:
$ sudo usermod -aG wheel vivek
$ id vivek
测试 sudo 访问并禁用 ssh 的 root 登录
测试它并确保用户 vivek 可以以 root 身份登录或以 root 身份运行命令:
确认后,通过将以下行添加到 sshd_config 来禁用 root 登录:
$ sudo -i
$ sudo /etc/init.d/sshd status
$ sudo systemctl status httpd
PermitRootLogin no ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no
有关更多信息,请参阅“如何在 Linux 上禁用 ssh 密码登录以提高安全性”。
3. 禁用基于密码的登录
必须禁用所有基于密码的登录。仅允许基于公钥的登录。在 sshd_config 文件中添加以下内容:
AuthenticationMethods publickey PubkeyAuthentication yes
CentOS 6.x/RHEL 6.x 上旧版本的 SSHD 用户应使用以下设置:
PubkeyAuthentication yes
4.限制用户的 ssh 访问
默认情况下,所有系统用户都可以使用其密码或公钥通过 SSH 登录。有时,您会创建 UNIX / Linux 用户帐户用于 FTP 或电子邮件。但是,这些用户可以使用 ssh 登录系统。他们将拥有对系统工具的完全访问权限,包括编译器和脚本语言(如 Perl、Python),这些工具可以打开网络端口并执行许多其他奇特的操作。仅允许 root、vivek 和 jerry 用户通过 SSH 使用系统,将以下内容添加到 sshd_config:
AllowUsers vivek jerry
或者,您可以允许所有用户通过 SSH 登录但仅拒绝少数用户,在 sshd_config 中添加以下行:
DenyUsers root saroj anjali foo
您还可以配置 Linux PAM允许或拒绝通过 sshd 服务器登录。您可以允许组名列表访问或拒绝访问 ssh。
5. 禁用空密码
您需要明确禁止使用空密码的帐户进行远程登录,请使用以下行更新 sshd_config:
PermitEmptyPasswords no
6. 为 ssh 用户/密钥使用强密码和密码短语
再怎么强调使用强用户密码和密钥密码短语的重要性也不为过。暴力攻击之所以有效,是因为用户会使用基于字典的密码。您可以强制用户避免使用字典攻击的密码,并使用john the ripper 工具找出现有的弱密码。以下是随机密码生成器示例(放入您的 ~/.bashrc 中):
genpasswd() { local l=$1 [ "$l" == "" ] && l=20 tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs }
运行:
$ genpasswd 16
输出:
uw8CnDVMwC6vOKgW
7.防火墙 SSH TCP 端口 # 22
您需要通过更新 iptables/ufw/firewall-cmd 或 pf 防火墙配置来防火墙 ssh TCP 端口 # 22。通常,OpenSSH 服务器必须仅接受来自您的 LAN 或其他远程 WAN 站点的连接。有关更多信息,请参阅 ufw命令或iptables 命令示例。
Netfilter(Iptables)配置
更新/etc/sysconfig/iptables(Redhat 和朋友特定文件)以仅接受来自 192.168.1.0/24 和 202.54.1.5/29 的连接,输入:
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 22 -j ACCEPT -A RH-Firewall-1-INPUT -s 202.54.1.5/29 -m state --state NEW -p tcp --dport 22 -j ACCEPT
如果您已使用 IPv6 双栈 sshd,请编辑 /etc/sysconfig/ip6tables(Redhat 和相关特定文件),输入:
-A RH-Firewall-1-INPUT -s ipv6network::/ipv6mask -m tcp -p tcp --dport 22 -j ACCEPT
将 ipv6network::/ipv6mask 替换为实际的 IPv6 范围。
适用于 Debian/Ubuntu Linux 的 UFW
UFW 是 Uncomplicated Firewall 的缩写。它用于管理 Linux 防火墙,旨在为用户提供易于使用的界面。使用以下命令仅接受来自 202.54.1.5/29 的端口 22:
$ sudo ufw allow from 202.54.1.5/29 to any port 22
阅读“ Linux:25 个适用于新系统管理员的 Iptables Netfilter 防火墙示例”了解更多信息。
*BSD PF 防火墙配置
如果您使用 PF 防火墙,请按如下方式更新 /etc/pf.conf:
pass in on $ext_if inet proto tcp from {192.168.1.0/24, 202.54.1.5/29} to $ssh_server_ip port ssh flags S/SA synproxy state
8. 修改SSH端口并限制IP绑定
默认情况下,SSH 会监听系统上所有可用的接口和 IP 地址。限制 ssh 端口绑定并更改 ssh 端口(许多暴力破解脚本仅尝试连接到 TCP 端口 #22)。要绑定到 192.168.1.5 和 202.54.1.5 IP 和端口 300,请在 sshd_config 中添加或更正以下行:
Port 300
ListenAddress 192.168.1.5
ListenAddress 202.54.1.5
当您想要接受来自动态 WAN IP 地址的连接时,更好的方法是使用主动方法脚本(例如 fail2ban 或 deniedhosts)。
9. 使用 TCP 包装器(可选)
TCP Wrapper 是一个基于主机的网络 ACL 系统,用于过滤对 Internet 的网络访问。OpenSSH 确实支持 TCP 包装器。只需按如下方式更新您的 /etc/hosts.allow 文件,即可仅允许来自 192.168.1.2 和 172.16.23.12 IP 地址的 SSH:
sshd : 192.168.1.2 172.16.23.12
请参阅有关在 Linux / Mac OS X 和类 UNIX 操作系统下设置和使用 TCP 包装器的常见问题解答。
10. 阻止 SSH 破解者/暴力攻击
暴力破解是一种使用单个或分布式计算机网络尝试大量可能性(用户和密码组合)来破解加密方案的方法。要防止针对 SSH 的暴力破解攻击,请使用以下软件:
- DenyHosts是一款基于 Python 的 SSH 服务器安全工具。它旨在通过监控身份验证日志中的无效登录尝试并阻止原始 IP 地址来防止对 SSH 服务器的暴力攻击。
- 解释如何在 RHEL / Fedora 和 CentOS Linux 下设置DenyHosts 。
- Fail2ban是一个类似的程序,可以防止针对 SSH 的暴力攻击。
- sshguard使用 pf 保护主机免受针对 ssh 和其他服务的暴力攻击。
- security/sshblock阻止滥用 SSH 登录尝试。
- IPQ BDB 过滤器可以被视为 fail2ban lite。
11. 对 TCP 端口 #22 的传入流量进行速率限制(可选)
netfilter 和 pf 都提供了速率限制选项,对端口 #22 上的传入连接执行简单的限制。
Iptables 示例
以下示例将丢弃在 60 秒内对端口 22 进行超过 5 次连接尝试的传入连接:
#!/bin/bash inet_if=eth1 ssh_port=22 $IPT -I INPUT -p tcp --dport ${ssh_port} -i ${inet_if} -m state --state NEW -m recent --set $IPT -I INPUT -p tcp --dport ${ssh_port} -i ${inet_if} -m state --state NEW -m recent --update --seconds 60 --hitcount 5 -j DROP
从您的 iptables 脚本调用上述脚本。另一个配置选项:
$IPT -A INPUT -i ${inet_if} -p tcp --dport ${ssh_port} -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT $IPT -A INPUT -i ${inet_if} -p tcp --dport ${ssh_port} -m state --state ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o ${inet_if} -p tcp --sport ${ssh_port} -m state --state ESTABLISHED -j ACCEPT # another one line example # $IPT -A INPUT -i ${inet_if} -m state --state NEW,ESTABLISHED,RELATED -p tcp --dport 22 -m limit --limit 5/minute --limit-burst 5-j ACCEPT
请参阅“如何在 Ubuntu Linux 上使用 ufw 限制 SSH(TCP 端口 22)连接”了解更多信息,并参阅 iptables 手册页了解更多详细信息。
*BSD PF 示例
以下内容将限制每个源的最大连接数为 20,并将 5 秒内连接数限制为 15。如果有人违反我们的规则,则将其添加到我们的 abusive_ips 表中并阻止其进行任何进一步的连接。最后,flush 关键字会终止匹配规则创建的所有状态,这些状态源自超出这些限制的主机。
sshd_server_ip="202.54.1.5" table <abusive_ips> persist block in quick from <abusive_ips> pass in on $ext_if proto tcp to $sshd_server_ip port ssh flags S/SA keep state (max-src-conn 20, max-src-conn-rate 15/5, overload <abusive_ips> flush)
12. 使用端口敲击(可选)
端口敲击是一种通过在一组预先指定的关闭端口上生成连接尝试来从外部打开防火墙端口的方法。一旦收到正确的连接尝试序列,防火墙规则就会动态修改,以允许发送连接尝试的主机连接到特定端口。使用 iptables 的 ssh 端口敲击示例:
$IPT -N stage1 $IPT -A stage1 -m recent --remove --name knock $IPT -A stage1 -p tcp --dport 3456 -m recent --set --name knock2 $IPT -N stage2 $IPT -A stage2 -m recent --remove --name knock2 $IPT -A stage2 -p tcp --dport 2345 -m recent --set --name heaven $IPT -N door $IPT -A door -m recent --rcheck --seconds 5 --name knock2 -j stage2 $IPT -A door -m recent --rcheck --seconds 5 --name knock -j stage1 $IPT -A door -p tcp --dport 1234 -m recent --set --name knock $IPT -A INPUT -m --state ESTABLISHED,RELATED -j ACCEPT $IPT -A INPUT -p tcp --dport 22 -m recent --rcheck --seconds 5 --name heaven -j ACCEPT $IPT -A INPUT -p tcp --syn -j door
更多信息请参阅:
13. 配置空闲注销超时间隔
用户可以通过 ssh 登录服务器,您可以设置空闲超时间隔以避免无人值守的 ssh 会话。打开 sshd_config 并确保配置了以下值:
您正在设置空闲超时间隔(以秒为单位)(300 秒 == 5 分钟)。此间隔过后,空闲用户将被自动踢出(读作已注销)。有关更多详细信息,请参阅如何在一段时间不活动后自动注销 BASH / TCSH / SSH 用户。
ClientAliveInterval 300
ClientAliveCountMax 0
14. 为 ssh 用户启用警告横幅
通过使用以下行更新 sshd_config 来设置警告横幅:
Banner /etc/issue
示例 /etc/issue 文件:
---------------------------------------------------------------------------------------------- You are accessing a XYZ Government (XYZG) Information System (IS) that is provided for authorized use only. By using this IS (which includes any device attached to this IS), you consent to the following conditions: + The XYZG routinely intercepts and monitors communications on this IS for purposes including, but not limited to, penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM), law enforcement (LE), and counterintelligence (CI) investigations. + At any time, the XYZG may inspect and seize data stored on this IS. + Communications using, or data stored on, this IS are not private, are subject to routine monitoring, interception, and search, and may be disclosed or used for any XYZG authorized purpose. + This IS includes security measures (e.g., authentication and access controls) to protect XYZG interests--not for your personal benefit or privacy. + Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching or monitoring of the content of privileged communications, or work product, related to personal representation or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work product are private and confidential. See User Agreement for details. ----------------------------------------------------------------------------------------------
以上是标准示例,具体用户协议和法律声明详情请咨询您的法律团队。
15. 禁用.rhosts 文件(验证)
不要读取用户的 ~/.rhosts 和 ~/.shosts 文件。使用以下设置更新 sshd_config:
IgnoreRhosts yes
SSH 可以模拟过时的 rsh 命令的行为,只需禁用通过 RSH 进行的不安全访问即可。
16. 禁用基于主机的身份验证(验证)
要禁用基于主机的身份验证,请使用以下选项更新 sshd_config:
HostbasedAuthentication no
17. 修补 OpenSSH 和操作系统
建议您使用yum、apt-get、freebsd-update等工具来使系统保持最新的安全补丁:
18. Chroot OpenSSH(将用户锁定在其主目录中)
By default users are allowed to browse the server directories such as /etc/, /bin and so on. You can protect ssh, using os based chroot or use special tools such as rssh. With the release of OpenSSH 4.8p1 or 4.9p1, you no longer have to rely on third-party hacks such as rssh or complicated chroot(1) setups to lock users to their home directories. See this blog post about new ChrootDirectory directive to lock down users to their home directories.
19. Disable OpenSSH server on client computer
Workstations and laptop can work without OpenSSH server. If you do not provide the remote login and file transfer capabilities of SSH, disable and remove the SSHD server. CentOS / RHEL users can disable and remove openssh-server with the yum command:
$ sudo yum erase openssh-server
Debian / Ubuntu Linux user can disable and remove the same with the apt command/apt-get command:
$ sudo apt-get remove openssh-server
You may need to update your iptables script to remove ssh exception rule. Under CentOS / RHEL / Fedora edit the files /etc/sysconfig/iptables and /etc/sysconfig/ip6tables. Once done restart iptables service:
# service iptables restart
# service ip6tables restart
20. Bonus tips from Mozilla
If you are using OpenSSH version 6.7+ or newer try following settings:
#################[ WARNING ]######################## # Do not use any setting blindly. Read sshd_config # # man page. You must understand cryptography to # # tweak following settings. Otherwise use defaults # #################################################### # 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 # Specifies the available KEX (Key Exchange) algorithms. KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 # Specifies the ciphers allowed Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr #Specifies the available MAC (message authentication code) algorithms MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-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 # Log sftp level file access (read/write/etc.) that would not be easily logged otherwise. Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO
You can grab list of cipher and alog supported by your OpenSSH server using the following commands:
$ ssh -Q cipher
$ ssh -Q cipher-auth
$ ssh -Q mac
$ ssh -Q kex
$ ssh -Q key
How do I test sshd_config file and restart/reload my SSH server?
To check the validity of the configuration file and sanity of the keys for any errors before restarting sshd, run:
$ sudo sshd -t
Extended test mode:
$ sudo sshd -T
Finally restart sshd on a Linux or Unix like systems as per your distro version:
$ sudo systemctl start ssh #Debian/Ubuntu
$ sudo systemctl restart sshd.service #RHEL &co
$ doas /etc/rc.d/sshd restart #OpenBSD
$ sudo service sshd restart #FreeBSD
How to audit SSH server and client config on Linux/Unix
ssh-audit is a tool for ssh server and client auditing. See my page about ssh-audit installation and configruration on your Linux or Unix box.
Summing up
If you have a technique or handy software not mentioned here, please share in the comments below to help your fellow readers keep their OpenSSH based server secure. Other susggesions:
- Tighter SSH security with 2FA – Multi-Factor authentication can be enabled with OATH Toolkit or DuoSecurity.
- Use keychain based authentication – keychain is a special bash script designed to make key-based authentication incredibly convenient and flexible. It offers various security benefits over passphrase-free keys
- The official OpenSSH project home page.
- Read man pages using the man command/help command:
$ man 8 sshd
$ man 1 ssh
$ man 1 ssh-add
$ man 1 ssh-agent
$ man 5 sshd_config
- Top 20 OpenSSH Server Best Security Practices
- 如何在 Linux / Unix 系统上设置 SSH 密钥
- Linux / Unix 用户的 OpenSSH 配置文件示例
- 审计 Linux/Unix 上的 SSH 服务器和客户端配置
- 如何在 FreeBSD 上安装和升级 OpenSSH 服务器
- Ubuntu Linux 安装 OpenSSH 服务器
- 在 Alpine Linux 上安装 OpenSSH 服务器(包括 Docker)
- Debian Linux 安装 OpenSSH SSHD 服务器
- 配置 OpenSSH 以监听 IPv6 地址
- OpenSSH 服务器连接在几分钟不活动后断开
- 在 OpenSSH 身份验证之前显示横幅/消息
- 强制 OpenSSH(sshd)仅监听选定的多个 IP 地址
- OpenSSH 使用 ssh-keygen 命令更改密码
- 重复使用 SSH 连接以通过多路复用加速远程登录过程
- 重新启动 SSHD 服务器之前检查语法错误
- 更改 Linux 或 Unix 服务器上的 ssh 端口
- OpenSSH 拒绝或限制用户和组的访问
- Linux OpenSSH 服务器拒绝 root 用户访问/登录
- 在 Linux 上禁用 ssh 密码登录以提高安全性
- SSH ProxyCommand 示例:通过一台主机到达服务器
- OpenSSH 多路复用器可加速 OpenSSH 连接
- 在远程 Linux / UNIX 服务器中安装 / 附加 SSH 密钥 Authorized_keys
- 使用 ssh-copy-id 与监听不同端口的 OpenSSH 服务器配合使用