OpenSSH 服务器的 20 个最佳实践
OpenSSH 是 SSH 协议的开源实现。 OpenSSH 可进行远程登录、备份、通过 scp 或 sftp 进行远程文件传输等等。 SSH 最完美的确保两个网络和系统之间交换数据的机密性和完整性。其主要的优点是通过使用公共密钥加密进行服务器身份验证。然而,不时有传闻关于 OpenSSH 零日漏洞。这里我们列出一些重要的事情,你需要作出调整来提高 OpenSSH 服务器的安全性。
默认配置文件和端口
- /etc/ssh/sshd_config - OpenSSH 服务器配置文件
- /etc/ssh/ssh_config - OpenSSH 客户端配置文件
- ~/.ssh/ - 用户独立的 ssh 配置目录
- ~/.ssh/authorized_keys or ~/.ssh/authorized_keys - 公钥 (RSA or DSA)
- /etc/nologin - 如果该文件存在,则只允许 root 帐号登录
- /etc/hosts.allow and /etc/hosts.deny : 访问控制定义
- SSH 默认端口 : TCP 22
#1: 禁用 OpenSSH 服务
一些工作站或者是笔记本是无需 OpenSSH 服务的,你不需要提供远程登录和文件传输,那么就禁用 SSHD 服务吧。CentOS/RHEL/Fedora Linux 用户可通过 yum 命令来禁用并删除 openssh-server 服务:
# chkconfig sshd off # yum erase openssh-serverDebian / Ubuntu Linux 用户可通过 apt-get 命令来处理:
# apt-get remove openssh-server你还需要更新 iptables 脚本来移除 ssh 例外规则,在 CentOS / RHEL / Fedora 下可编辑 /etc/sysconfig/iptables 和 /etc/sysconfig/ip6tables. 搞定后重启 iptables 服务即可:
# service iptables restart # service ip6tables restart
#2: 只使用 SSH Protocol 2
SSH 协议版本 1 有很多漏洞和安全问题,应该避免使用 SSH-1,可通过在 sshd_config 文件中配置如下信息来启用 SSH-2:
Protocol 2
#3: 限制用户访问 SSH
默认所有系统用户都可以通过 SSH 登录,只需要用密码或者公钥即可。有时候你创建某个用户只是为了使用邮件或者是 FTP,但是这些用户也可以通过 ssh 登录,登录后就可以访问很多的系统工具,包括编译器和脚本语言,可打开网络端口以及做很多其他的事情。我们可以通过 sshd_config 文件中的 AllowUsers 和 DenyUsers 来设置可访问 SSH 服务的用户名单。
下面配置只允许 root, vivek 和 jerry 三个帐号使用 SSH 服务
AllowUsers root vivek jerry
你也可以设置哪些用户不能访问 SSH:
DenyUsers saroj anjali foo
你也可以 配置 Linux PAM 来允许或者拒绝通过 sshd 服务器登录,你也可以对一个分组进行设置是否可以访问 ssh (详情)
#4: 配置空闲登出的超时间隔
用户通过 ssh 登录到服务器后,如果长时间没有任何动作的话,可通过设置空闲超时时间来让登录的用户自动登出,以避免一些不必要的 ssh 会话连接。打开 sshd_config 文件查看并编辑如下配置:
ClientAliveInterval 300 ClientAliveCountMax 0
这里我们设置了 300 秒(5分钟),一旦用户在 5 分钟内没有动作则会自动被踢出。请看 如何自动登出 BASH / TCSH / SSH 以了解更多无活动状态自动登出的详情。
#5: 禁用 .rhosts 文件
不读取用户命令下的 ~/.rhosts 和 ~/.shosts 文件,只需在 sshd_config 中使用如下设置:
IgnoreRhosts yes
SSH 可模拟过时的 rsh 命令的行为,需要禁用通过 RSH 的非安全登录。
#6: 禁用基于主机的认证
在 sshd_config 中使用如下配置:
HostbasedAuthentication no
#7: 禁止 root 帐号通过 SSH 登录
没必要让 root 帐号可通过 ssh 登录,可通过正常用户登录后然后执行 su 或者 sudo 来执行 root 权限的操作,可在 sshd_config 中使用如下配置来禁用 root 帐号登录:
PermitRootLogin no
关于这个问题,Bob 给出了很棒的说明:
Saying "don't login as root" is h******t. It stems from the days when people sniffed the first packets of sessions so logging in as yourself and su-ing decreased the chance an attacker would see the root pw, and decreast the chance you got spoofed as to your telnet host target, You'd get your password spoofed but not root's pw. Gimme a break. this is 2005 - We have ssh, used properly it's secure. used improperly none of this 1989 will make a damn bit of difference. -Bob
#8: 启用警告的 Banner
可以在 sshd_config 中通过如下配置来启用通过 ssh 登录后的警告信息:
Banner /etc/issue
下面是 /etc/issue 文件的示例内容:
---------------------------------------------------------------------------------------------- 欢迎访问 open 服务器,请不要乱来!!! ----------------------------------------------------------------------------------------------
#8: 防火墙处理 SSH 端口 # 22
你需要在防火墙规则中打开 22 端口,除非你的服务器只允许通过局域网访问:
Netfilter (Iptables) 配置
编辑 /etc/sysconfig/iptables (红帽系列 Linux) 以允许来自 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 ,编辑 /etc/sysconfig/ip6tables (Redhat and friends specific file):
-A RH-Firewall-1-INPUT -s ipv6network::/ipv6mask -m tcp -p tcp --dport 22 -j ACCEPT
用实际的 IPv6 范围替换其中的 ipv6network::/ipv6mask
*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
#9: 修改 SSH 端口和限制 IP 绑定
默认 SSH 绑定到所有网卡的所有 IP,端口号是 22,建议只绑定到需要的网卡 IP ,并修改默认的端口。可通过 ssh_config 配置文件中使用如下配置信息将端口修改为 300:
Port 300 ListenAddress 192.168.1.5 ListenAddress 202.54.1.5
还有一个更好的方法是使用积极主动的脚本,诸如 fail2ban 或者是 denyhosts
#10: 使用强的 SSH 密码
使用强而复杂的密码是多么重要的一件事。蛮力攻击之所以有效,是因为你使用基于字典的密码。你可以强制要求用户不能使用基于字典的密码,并通过使用 john the ripper tool 来找出已有的弱密码,下面是一个随机密码生成器的示例:(放在你的 ~/.bashrc):
genpasswd() { local l=$1 [ "$l" == "" ] && l=20 tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs }运行:
genpasswd 16
输出:uw8CnDVMwC6vOKgW
#11: 使用基于公钥的认证
使用公/私钥配对,并对私钥提供密码保护,详情请看使用基于 RSA 和 DSA key 的认证。绝对不要使用密码短语免费密钥(密码键更少)登录。
#12: 使用 Keychain 认证
keychain 是一个特别的 bash 脚本,用于方便灵活的生成基于密钥认证,提供多种安全措施,详情请看 keychain software.
#13: Chroot SSHD (将用户锁定在他的主目录下)
默认用户允许浏览服务器上的目录,如 /etc、/bin 等,我们可使用 chroot 或者是 special tools such as rssh 来保护 ssh。而 OpenSSH 4.8p1 和 4.9p1 让你不再依赖第三方的工具(如rssh和组合 chroot)来将用户锁定在他的主目录下,详情请看 blog post 关于如何使用 ChrootDirectory 指令。
#14: 使用 TCP Wrappers
TCP Wrapper 是一个基于主机地址的网络 ACL 系统,用来过滤网络地址访问互联网。OpenSSH 支持 TCP Wrappers。只需要更新你的 /etc/hosts.allow 文件只允许通过 192.168.1.2 172.16.23.12 访问 sshd:
sshd : 192.168.1.2 172.16.23.12
详情请看 FAQ about setting and using TCP wrappers
#15: 禁用空密码
你应该禁止帐号使用空密码进行远程登录,在 sshd_config 使用如下配置即可:
PermitEmptyPasswords no
#16: 阻止 SSH 破解 (蛮力破解攻击)
蛮力破解是一种试图通过大量使用单一或分布式计算机网络来战胜一个加密方案。为了阻止这种方法,可结合使用如下软件:
- DenyHosts 是Python语言写的一个程序,它会分析SSHD的日志文件,当发现重复的攻击时就会记录IP到/etc/hosts.deny文 件,从而达到自动屏蔽IP的功能。
- 解释如何在 RHEL、Fedora 和 CentOS 系统下安装 DenyHosts
- Fail2ban 是一个 IP 自动屏蔽工具
- security/sshguard-pf 在 pf 中防止暴力破解
- security/sshguard-ipfw 在 ipfw 中防止暴力破解
- security/sshguard-ipfilter 在 ipfilter 中防止暴力破解
- security/sshblock block abusive SSH login attempts.
- security/sshit checks for SSH/FTP bruteforce and blocks given IPs.
- BlockHosts Automatic blocking of abusive IP hosts.
- Blacklist Get rid of those bruteforce attempts.
- Brute Force Detection A modular shell script for parsing application logs and checking for authentication failures. It does this using a rules system where application specific options are stored including regular expressions for each unique auth format.
- IPQ BDB filter May be considered as a fail2ban lite.
#17: 限制 22 端口连接的速率
netfilter 和 pf 都提供了连接速率限制选项
Iptables 示例
下面配置禁止在一分钟内 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
另外的配置选项:
$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
更多的配置详情请看 iptables 的 man 页。
*BSD PF 示例
以下将限制的最大连接数到20,每个源速率限制连接数,在一个5秒的跨度15。如果有人打破我们的规则将它们添加到我们的阻止的ip表和阻止他们做任何进一步的连接。
sshd_server_ip="202.54.1.5" tablepersist block in quick from 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 flush)
#18: 使用端口碰撞技术(Port Knocking)
端口碰撞技术 是一个方法的外部开放端口防火墙通过生成一个连接请求在一组预先指定关闭端口。一旦一个正确的顺序连接尝试接收,防火墙规则是动态修改为允许主机将连接尝试连接在特定端口(s)。
使用 iptables 配置端口碰撞的示例:
$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 doo
两个软件:
- fwknop 是一个结合端口碰撞和被动操作系统识别技术的实现
- Multiple-port knocking 仅限于 Netfilter/IPtables 的实现
#19: 使用日志分析器
可通过 logwatch or logcheck 来阅读日志,这些工具可以让你轻松的浏览日志。通过指定时间来给出日志的报告。首先要确保在 sshd_config 中将日志级别 LogLevel 设置为 INFO 或者 DEBUG:
LogLevel INFO
#20: 对 OpenSSH 和操作系统打补丁
推荐你使用诸如 yum, apt-get, freebsd-update 工具来保持系统的即时获取最新的安全补丁。
其他选项
为了隐藏 openssh 版本,你可更新源码然后再次编译 openssh ,并确保在 sshd_config 中使用如下配置:
# Turn on privilege separation UsePrivilegeSeparation yes # Prevent the use of insecure home directory and key file permissions StrictModes yes # Turn on reverse name checking VerifyReverseMapping yes # Do you need port forwarding? AllowTcpForwarding no X11Forwarding no # Specifies whether password authentication is allowed. The default is yes. PasswordAuthentication no
在重启 openssh-server 之前先用如下命令验证配置是否正确:
# /usr/sbin/sshd -t
使用 two-factor 或者 three-factor (or more) 认证来加强 OpenSSH 的安全。