您的位置:首页 > 运维架构 > Linux

20 个 OpenSSH 最佳安全实践 | Linux 中国

2018-03-01 11:24 866 查看
OpenSSH 是 SSH 协议的一个实现。一般通过 scp 或 sftp 用于远程登录、备份、远程文件传输等功能。SSH能够完美保障两个网络或系统间数据传输的保密性和完整性。尽管如此,它最大的优势是使用公匙加密来进行服务器验证。时不时会出现关于 OpenSSH 零日漏洞的传言[1]。本文将描述如何设置你的 Linux 或类 Unix 系统以提高 sshd 的安全性。OpenSSH 默认设置◈ TCP 端口 - 22◈ OpenSSH 服务配置文件 - sshd_config (位于 /etc/ssh/)1、 基于公匙的登录OpenSSH 服务支持各种验证方式。推荐使用公匙加密验证。首先,使用以下 ssh-keygen命令在本地电脑上创建密匙对:1024 位或低于它的 DSA 和 RSA 加密是很弱的,请不要使用。当考虑 ssh 客户端向后兼容性的时候,请使用 RSA密匙代替 ECDSA 密匙。所有的 ssh 密钥要么使用 ED25519 ,要么使用 RSA,不要使用其它类型。1.  $ ssh-keygen -t key_type-b bits -C "comment"示例:1.  $ ssh-keygen -t ed25519-C "Login to production cluster at xyzcorp"2.  或3.  $ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_aws_$(date+%Y-%m-%d) -C "AWS key forabc corp clients"下一步,使用 ssh-copy-id 命令安装公匙:1.  $ ssh-copy-id -i /path/to/public-key-fileuser@host2.  或3.  $ ssh-copy-id user@remote-server-ip-or-dns-name示例:1.  $ ssh-copy-id vivek@rhel7-aws-server提示输入用户名和密码的时候,确认基于 ssh 公匙的登录是否工作:1.  $ sshvivek@rhel7-aws-serverOpenSSH 服务安全最佳实践更多有关 ssh 公匙的信息,参照以下文章:◈ 为备份脚本设置无密码安全登录[2]◈ sshpass:使用脚本密码登录 SSH 服务器[3]◈ 如何为一个 Linux/类 Unix 系统设置SSH 登录密匙[4]◈ 如何使用 Ansible 工具上传 ssh 登录授权公匙[5]2、 禁用 root 用户登录禁用 root 用户登录前,确认普通用户可以以 root 身份登录。例如,允许用户 vivek 使用 sudo 命令以 root 身份登录。在 Debian/Ubuntu 系统中如何将用户 vivek 添加到 sudo 组中允许 sudo 组中的用户执行任何命令。 将用户 vivek 添加到 sudo 组中[6]:1.  $ sudo adduser vivek sudo使用 id 命令[7] 验证用户组。1.  $ id vivek在 CentOS/RHEL 系统中如何将用户 vivek 添加到 sudo 组中在 CentOS/RHEL 和 Fedora 系统中允许 wheel 组中的用户执行所有的命令。使用 usermod 命令将用户 vivek 添加到wheel 组中:1.  $ sudousermod -aG wheel vivek2.  $ id vivek测试 sudo 权限并禁用 ssh root 登录测试并确保用户 vivek 可以以 root 身份登录执行以下命令:1.  $ sudo -i2.  $ sudo /etc/init.d/sshd status3.  $ sudosystemctl status httpd添加以下内容到 sshd_config 文件中来禁用 root 登录:1.  PermitRootLoginno2.  ChallengeResponseAuthenticationno3.  PasswordAuthenticationno4.  UsePAMno更多信息参见“如何通过禁用 Linux 的 ssh 密码登录来增强系统安全[8]” 。3、 禁用密码登录所有的密码登录都应该禁用,仅留下公匙登录。添加以下内容到 sshd_config 文件中:1.  AuthenticationMethods publickey2.  PubkeyAuthenticationyesCentOS 6.x/RHEL 6.x 系统中老版本的 sshd 用户可以使用以下设置:1.  PubkeyAuthenticationyes4、 限制用户的 ssh 访问默认状态下,所有的系统用户都可以使用密码或公匙登录。但是有些时候需要为 FTP 或者 email 服务创建 UNIX/Linux 用户。然而,这些用户也可以使用 ssh 登录系统。他们将获得访问系统工具的完整权限,包括编译器和诸如 Perl、Python(可以打开网络端口干很多疯狂的事情)等的脚本语言。通过添加以下内容到 sshd_config 文件中来仅允许用户 root、vivek和 jerry 通过 SSH 登录系统:1.  AllowUsers vivek jerry当然,你也可以添加以下内容到 sshd_config 文件中来达到仅拒绝一部分用户通过 SSH 登录系统的效果。1.  DenyUsers root saroj anjali foo你也可以通过配置Linux PAM[9] 来禁用或允许用户通过 sshd 登录。也可以允许或禁止一个用户组列表[10]通过 ssh 登录系统。5、 禁用空密码你需要明确禁止空密码账户远程登录系统,更新 sshd_config 文件的以下内容:1.  PermitEmptyPasswordsno6、 为ssh 用户或者密匙使用强密码为密匙使用强密码和短语的重要性再怎么强调都不过分。暴力破解可以起作用就是因为用户使用了基于字典的密码。你可以强制用户避开字典密码[11]并使用约翰的开膛手工具[12]来检测弱密码。以下是一个随机密码生成器(放到你的 ~/.bashrc 下):1.  genpasswd() {2.      locall=$13.      [ "$l" == "" ] && l=204.      tr -dcA-Za-z0-9_ < /dev/urandom| head -c ${l} | xargs5.  }运行:1.  genpasswd 16输出:1.  uw8CnDVMwC6vOKgW◈ 使用 mkpasswd / makepasswd / pwgen 生成随机密码[13]◈ Linux / UNIX: 生成密码[14]◈ Linux 随机密码生成命令[15]7、 为SSH 的 22端口配置防火墙你需要更新 iptables/ufw/firewall-cmd 或 pf 防火墙配置来为 ssh的 TCP 端口 22 配置防火墙。一般来说,OpenSSH 服务应该仅允许本地或者其他的远端地址访问。Netfilter(Iptables) 配置更新 /etc/sysconfig/iptables (Redhat 和其派生系统特有文件) [16] 实现仅接受来自于 192.168.1.0/24 和 202.54.1.5/29 的连接,输入:1.  -A RH-Firewall-1-INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 22 -jACCEPT2.  -A RH-Firewall-1-INPUT -s 202.54.1.5/29 -m state --state NEW -p tcp --dport 22 -jACCEPT如果同时使用 IPv6 的话,可以编辑 /etc/sysconfig/ip6tables (Redhat 和其派生系统特有文件),输入:1.  -A RH-Firewall-1-INPUT -s ipv6network::/ipv6mask -m tcp -p tcp --dport 22 -j ACCEPT将 ipv6network::/ipv6mask 替换为实际的 IPv6 网段。Debian/Ubuntu Linux 下的 UFWUFW 是 Uncomplicated FireWall 的首字母缩写,主要用来管理 Linux 防火墙[17],目的是提供一种用户友好的界面。输入以下命令使得系统仅允许网段 202.54.1.5/29 接入端口 22[18]:1.  $ sudo ufw allow from202.54.1.5/29 to any port 22更多信息请参见 “Linux:菜鸟管理员的 25 个 Iptables Netfilter 命令[19]”。*BSD PF 防火墙配置如果使用 PF 防火墙 /etc/pf.conf[20] 配置如下:1.  passin 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 state8、 修改 SSH 端口和绑定 IPssh 默认监听系统中所有可用的网卡。修改并绑定 ssh 端口有助于避免暴力脚本的连接(许多暴力脚本只尝试端口 22)。更新文件 sshd_config 的以下内容来绑定端口 300 到IP 192.168.1.5 和 202.54.1.5:1.  Port3002.  ListenAddress192.168.1.53.  ListenAddress202.54.1.5当需要接受动态广域网地址的连接时,使用主动脚本是个不错的选择,比如 fail2ban 或 denyhosts。9、 使用 TCP wrappers (可选的)TCP wrapper 是一个基于主机的访问控制系统,用来过滤来自互联网的网络访问。OpenSSH 支持 TCP wrappers。只需要更新文件 /etc/hosts.allow 中的以下内容就可以使得 SSH 只接受来自于 192.168.1.2 和 172.16.23.12 的连接:1.  sshd : 192.168.1.2172.16.23.12在 Linux/Mac OS X 和类 UNIX 系统中参见 TCP wrappers 设置和使用的常见问题[21]。10、 阻止 SSH 破解或暴力攻击暴力破解是一种在单一或者分布式网络中使用大量(用户名和密码的)组合来尝试连接一个加密系统的方法。可以使用以下软件来应对暴力攻击:◈ DenyHosts[22] 是一个基于 Python SSH 安全工具。该工具通过监控授权日志中的非法登录日志并封禁原始 IP 的方式来应对暴力攻击。◈ RHEL / Fedora 和CentOS Linux 下如何设置 DenyHosts[23]。◈ Fail2ban[24] 是另一个类似的用来预防针对 SSH 攻击的工具。◈ sshguard[25] 是一个使用 pf 来预防针对 SSH 和其他服务攻击的工具。◈ security/sshblock[26] 阻止滥用 SSH 尝试登录。◈ IPQ BDB filter[27] 可以看做是 fail2ban 的一个简化版。11、 限制 TCP 端口 22 的传入速率(可选的)netfilter 和 pf 都提供速率限制选项可以对端口 22 的传入速率进行简单的限制。Iptables 示例以下脚本将会阻止 60 秒内尝试登录 5 次以上的客户端的连入。1.  #!/bin/bash2.  inet_if=eth13.  ssh_port=224.  $IPT -I INPUT -p tcp --dport ${ssh_port} -i${inet_if} -m state --state NEW -m recent --set5.  $IPT -I INPUT -p tcp --dport ${ssh_port} -i${inet_if} -m state --state NEW -m recent --update --seconds 60 --hitcount 5在你的 iptables 脚本中调用以上脚本。其他配置选项:1.  $IPT -A INPUT -i ${inet_if} -p tcp --dport${ssh_port} -m state --state NEW -m limit --limit 3/min--limit-burst 3 -j ACCEPT2.  $IPT -A INPUT -i ${inet_if} -p tcp --dport${ssh_port} -m state --state ESTABLISHED -j ACCEPT3.  $IPT -A OUTPUT -o ${inet_if} -p tcp --sport${ssh_port} -m state --state ESTABLISHED -j ACCEPT4.  # another one line example5.  # $IPT -A INPUT -i ${inet_if} -m state --stateNEW,ESTABLISHED,RELATED -p tcp --dport 22 -mlimit --limit 5/minute --limit-burst 5-j ACCEPT其他细节参见 iptables 用户手册。*BSD PF 示例以下脚本将限制每个客户端的连入数量为 20,并且 5 秒内的连接不超过 15 个。如果客户端触发此规则,则将其加入 abusive_ips 表并限制该客户端连入。最后 flush 关键词杀死所有触发规则的客户端的连接。1.  sshd_server_ip = "202.54.1.5"2.  table <abusive_ips> persist3.  block inquick from <abusive_ips>4.  passin on $ext_if proto tcp to $sshd_server_ipport ssh flags S/SA keep state (max-src-conn 20, max-src-conn-rate 15/5, overload<abusive_ips> flush) 12、 使用端口敲门(可选的)端口敲门[28]是通过在一组预先指定的封闭端口上生成连接尝试,以便从外部打开防火墙上的端口的方法。一旦指定的端口连接顺序被触发,防火墙规则就被动态修改以允许发送连接的主机连入指定的端口。以下是一个使用 iptables 实现的端口敲门的示例:1.  $IPT -N stage12.  $IPT -A stage1 -m recent --remove --nameknock3.  $IPT -A stage1 -p tcp --dport 3456 -m recent --set --name knock24.   5.  $IPT -N stage26.  $IPT -A stage2 -m recent --remove --nameknock27.  $IPT -A stage2 -p tcp --dport 2345 -m recent --set --name heaven8.   9.  $IPT -N door10.$IPT -A door -m recent --rcheck --seconds 5 --name knock2 -j stage211.$IPT -A door -m recent --rcheck --seconds 5 --name knock -j stage112.$IPT -A door -p tcp --dport 1234 -m recent --set --name knock13. 14.$IPT -A INPUT -m --stateESTABLISHED,RELATED -j ACCEPT15.$IPT -A INPUT -p tcp --dport 22 -m recent --rcheck --seconds 5 --name heaven -jACCEPT16.$IPT -A INPUT -p tcp --syn -j door更多信息请参见:Debian / Ubuntu: 使用 Knockd and Iptables 设置端口敲门[29]13、 配置空闲超时注销时长用户可以通过 ssh 连入服务器,可以配置一个超时时间间隔来避免无人值守的 ssh 会话。 打开 sshd_config 并确保配置以下值:1.  ClientAliveInterval3002.  ClientAliveCountMax0以秒为单位设置一个空闲超时时间(300秒 = 5分钟)。一旦空闲时间超过这个值,空闲用户就会被踢出会话。更多细节参见如何自动注销空闲超时的 BASH / TCSH/ SSH 用户[30]。14、 为ssh 用户启用警示标语更新 sshd_config 文件如下行来设置用户的警示标语:1.  Banner /etc/issue`/etc/issue 示例文件:1.  ----------------------------------------------------------------------------------------------2.  You are accessing a XYZ Government(XYZG) InformationSystem (IS) that is provided for authorized useonly.3.  Byusingthis IS (which includesany device attached to this IS), you consent to the followingconditions:4.   5.  + The XYZG routinelyintercepts and monitors communications on this IS for purposes including, but not limited to,6.  penetration testing, COMSEC monitoring,network operations and defense, personnel misconduct (PM),7.  law enforcement (LE), and counterintelligence (CI) investigations.8.   9.  + At any time, the XYZG may inspect andseize data stored on this IS.10. 11.+ Communicationsusing, or data stored on, this ISare notprivate, are subject to routine monitoring,12.interception, andsearch, and may be disclosed orused for any XYZG authorized purpose.13. 14.+ This IS includessecurity measures (e.g., authentication andaccess controls) to protect XYZG interests--not15.for your personal benefit orprivacy.16. 17.+ Notwithstanding the above, usingthis IS does notconstitute consent to PM, LE or CI investigative searching18.or monitoring of the content of privileged communications, or work product, related to personal representation19.or services by attorneys, psychotherapists, orclergy, and their assistants. Suchcommunications and work20.product are privateand confidential. SeeUserAgreementfor details.21.----------------------------------------------------------------------------------------------以上是一个标准的示例,更多的用户协议和法律细节请咨询你的律师团队。15、 禁用 .rhosts 文件(需核实)禁止读取用户的 ~/.rhosts 和 ~/.shosts 文件。更新 sshd_config 文件中的以下内容:1.  IgnoreRhostsyesSSH 可以模拟过时的 rsh 命令,所以应该禁用不安全的 RSH 连接。16、 禁用基于主机的授权(需核实)禁用基于主机的授权,更新 sshd_config 文件的以下选项:1.  HostbasedAuthenticationno17、 为OpenSSH 和操作系统打补丁推荐你使用类似 yum[31]、apt-get[32] 和 freebsd-update[33] 等工具保持系统安装了最新的安全补丁。18、Chroot OpenSSH (将用户锁定在主目录)默认设置下用户可以浏览诸如 /etc、/bin 等目录。可以使用 chroot 或者其他专有工具如 rssh[34] 来保护 ssh 连接。从版本4.8p1 或 4.9p1 起,OpenSSH 不再需要依赖诸如 rssh 或复杂的 chroot(1) 等第三方工具来将用户锁定在主目录中。可以使用新的 ChrootDirectory 指令将用户锁定在其主目录,参见这篇博文[35]。19. 禁用客户端的 OpenSSH 服务工作站和笔记本不需要 OpenSSH 服务。如果不需要提供 ssh远程登录和文件传输功能的话,可以禁用 sshd 服务。CentOS/ RHEL 用户可以使用 yum 命令[31] 禁用或删除 openssh-server:1.  $ sudoyum erase openssh-serverDebian / Ubuntu 用户可以使用 apt 命令[36]/apt-get 命令[32] 删除 openssh-server:1.  $ sudoapt-get remove openssh-server有可能需要更新 iptables 脚本来移除 ssh 的例外规则。CentOS / RHEL / Fedora 系统可以编辑文件 /etc/sysconfig/iptables 和 /etc/sysconfig/ip6tables。最后重启 iptables[37] 服务:1.  # service iptables restart2.  # service ip6tables restart20. 来自Mozilla 的额外提示如果使用 6.7+ 版本的 OpenSSH,可以尝试下以下设置[38]:1.  #################[ WARNING]########################2.  #Donotuse any setting blindly. Readsshd_config #3.  #man page. Youmust understand cryptography to    #4.  # tweak following settings. Otherwiseuse defaults #5.  ####################################################6.   7.  #SupportedHostKey algorithms byorder of preference.8.  HostKey /etc/ssh/ssh_host_ed25519_key9.  HostKey /etc/ssh/ssh_host_rsa_key10.HostKey /etc/ssh/ssh_host_ecdsa_key11. 12.#Specifies the available KEX (KeyExchange) algorithms.13.KexAlgorithmscurve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha25614. 15.#Specifies the ciphers allowed16.Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr17. 18.#Specifies theavailable MAC (message authentication code) algorithms19.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.com20. 21.#LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audittrack of which key was using to log in.22.LogLevel VERBOSE23. 24.# Log sftp level file access(read/write/etc.) that would not be easily logged otherwise.25.Subsystem sftp /usr/lib/ssh/sftp-server -fAUTHPRIV -l INFO使用以下命令获取 OpenSSH 支持的加密方法:1.  $ ssh -Q cipher2.  $ ssh -Q cipher-auth3.  $ ssh -Q mac4.  $ ssh -Q kex5.  $ ssh -Q keyOpenSSH安全教程查询密码和算法选择如何测试 sshd_config 文件并重启/重新加载 SSH 服务?在重启 sshd 前检查配置文件的有效性和密匙的完整性,运行:1.  $ sudosshd -t扩展测试模式:1.  $ sudosshd -T最后,根据系统的的版本重启Linux 或类 Unix 系统中的 sshd 服务[39]:1.  $ [sudosystemctl start ssh][38] ##Debian/UbuntLinux##2.  $ [sudosystemctl restart sshd.service][39] ##CentOS/RHEL/FedoraLinux##3.  $ doas /etc/rc.d/sshdrestart ##OpenBSD##4.  $ sudo service sshd restart ##FreeBSD##其他建议☉ 使用 2FA 加强 SSH 的安全性[40] - 可以使用 OATH Toolkit[41] 或 DuoSecurity[42] 启用多重身份验证。☉ 基于密匙链的身份验证[2] - 密匙链是一个 bash 脚本,可以使得基于密匙的验证非常的灵活方便。相对于无密码密匙,它提供更好的安全性。更多信息◈ OpenSSH 官方[43] 项目。◈ 用户手册: sshd(8)、ssh(1)、ssh-add(1)、ssh-agent(1)。如果知道这里没用提及的方便的软件或者技术,请在下面的评论中分享,以帮助读者保持 OpenSSH 的安全。关于作者作者是 nixCraft 的创始人,一个经验丰富的系统管理员和Linux/Unix 脚本培训师。他曾与全球客户合作,领域涉及 IT,教育,国防和空间研究以及非营利部门等多个行业。请在 Twitter[44]、Facebook[45]、Google+[46] 上关注他。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: