ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SSH密钥登录实战:从原理到配置,彻底禁用密码提升服务器安全

2026/8/3 7:37:56 拓冰建站 浏览量
SSH密钥登录实战:从原理到配置,彻底禁用密码提升服务器安全 1. 项目概述为什么“改端口”只是隔靴搔痒每次看到有朋友在服务器安全配置清单里第一条就是“修改SSH默认端口22”我就忍不住想说兄弟这招真的过时了。这就像你家防盗门你把锁眼从正中间挪到了侧面以为小偷就找不到了。实际上任何一个稍微有点耐心的攻击者用端口扫描工具比如nmap几分钟就能把你的新端口扫出来。真正的安全核心在于“钥匙”本身——你是用一把全世界可能有几亿把的“密码钥匙”还是用一把全世界独一无二、几乎无法复制的“物理密钥”这就是SSH密钥登录与密码登录的本质区别。我这个在运维和开发一线摸爬滚打了十多年的老鸟处理过无数次因为弱密码或密码泄露导致的服务器入侵事件。从挖矿脚本、勒索病毒到数据被清空惨痛的教训告诉我禁用密码全面转向密钥登录是服务器安全入门的“第一道铁闸”。这个项目就是带你一步步在Ubuntu和CentOS这两大主流Linux发行版上完成从“密码改端口”的脆弱防御到“密钥登录完全禁用密码”的钢铁防线升级。无论你是刚买了云服务器的个人开发者还是需要规范团队服务器访问的运维负责人这份指南都能让你获得立竿见影的安全提升。2. 核心原理与方案选型密钥 vs 密码降维打击在深入实操之前我们必须搞清楚为什么密钥登录是近乎“降维打击”的安全方案。这不仅仅是“更安全”三个字能概括的。2.1 密码登录的“阿喀琉斯之踵”密码登录本质上是一个“你知道什么”What you know的验证模型。它的脆弱性根植于几个无法回避的弱点可暴力破解无论你的密码多复杂只要它长度有限、字符集有限理论上都可以通过穷举暴力破解或基于字典的碰撞尝试出来。攻击者利用自动化工具可以以每秒成千上万次的速度进行登录尝试。可被窃听与重放在非绝对安全的网络环境中密码在传输过程中有被截获的风险。虽然SSH协议本身加密了传输内容但中间人攻击MITM在特定条件下仍有可能发生。人为因素弱密码、密码复用、密码泄露通过社工、数据库撞库等是安全链条中最薄弱的一环。一个团队成员的不慎就可能导致整个堡垒失守。你可能会说“我设置了fail2ban失败几次就封IP”这确实有效但它属于“事后补救”和“增加攻击成本”。一个分布式的、IP池庞大的僵尸网络完全可以绕过这种限制。2.2 非对称加密SSH密钥登录的基石SSH密钥登录采用的是“你拥有什么”What you have的验证模型其核心是非对称加密Asymmetric Cryptography。你需要生成一对密钥私钥 (Private Key)相当于你的“主钥匙”或“印章”必须绝对私密地保存在你的本地电脑上绝不能通过网络传输或分享给他人。它用于生成数字签名。公钥 (Public Key)相当于“公开的锁芯”或“印章的印模”。你可以把它放到任何需要访问的服务器上。它用于验证私钥生成的签名。其工作流程可以类比为一种特殊的“锁和钥匙”挑战当你的客户端比如ssh命令或VSCode的Remote-SSH插件尝试连接服务器时服务器会生成一个随机的“挑战”字符串。签名客户端用本地的私钥对这个“挑战”进行加密即签名然后将签名发送回服务器。验证服务器用事先存储在你家目录下的公钥去尝试解密即验证这个签名。如果解密成功并且得到的原始“挑战”字符串与服务器发出的完全一致则证明客户端拥有对应的私钥认证通过。这个过程的美妙之处在于无法逆向推导即使攻击者截获了传输中的签名或者拿到了服务器上的公钥他也几乎不可能反向推导出你的私钥基于数学难题如大数分解。无需传输秘密你的私钥从未离开过你的本地机器从根本上杜绝了在传输中被窃取的风险。抵抗暴力破解私钥通常是一个非常长如RSA 4096位的随机数据块其可能的组合数量是一个天文数字使得暴力破解在现有计算能力下完全不现实。因此我们的方案选型非常明确在个人电脑上生成高强度密钥对将公钥部署到服务器并彻底关闭密码登录通道。对于团队协作则采用每个成员独立生成密钥由管理员将其公钥添加到服务器相应用户的~/.ssh/authorized_keys文件中的模式。注意私钥是你的命根子。务必做好备份例如使用加密的U盘或密码管理器并设置强密码短语Passphrase来加密私钥文件本身实现“双因子认证”你拥有的私钥你知道的密码短语。3. 完整实操流程从零构建密钥登录体系下面我将以同时覆盖Ubuntu以22.04 LTS为例和CentOS以7.x为例的视角演示完整的配置过程。假设你已有一台全新安装的服务器并通过密码登录用户为root或具有sudo权限的普通用户。3.1 第一步在本地客户端生成SSH密钥对这是所有操作的起点。在你的个人电脑Windows/macOS/Linux上操作。1. 打开终端或PowerShell/Git Bash2. 生成密钥对我们使用ssh-keygen命令并推荐使用更安全、性能更好的Ed25519算法。如果你需要兼容一些老旧的系统可以使用RSA 4096位。# 推荐使用Ed25519算法 ssh-keygen -t ed25519 -C your_emailexample.com -f ~/.ssh/id_ed25519_my_server # 或使用兼容性更好的RSA 4096位 ssh-keygen -t rsa -b 4096 -C your_emailexample.com -f ~/.ssh/id_rsa_my_server-t指定密钥类型ed25519或rsa。-b指定密钥长度仅对RSA有效4096位是当前的安全标准。-C添加一个注释通常用邮箱便于识别密钥所有者。-f指定生成的私钥文件名和路径。这里我使用了带服务器标识的文件名便于管理多台服务器。如果不指定-f默认会生成~/.ssh/id_ed25519或~/.ssh/id_rsa并覆盖已存在的同名文件。3. 设置密钥密码短语Passphrase命令执行后会提示你输入保存密钥的文件路径已通过-f指定然后会两次提示你输入密码短语。Enter passphrase (empty for no passphrase): Enter same passphrase again:强烈建议设置一个强密码短语这为你的私钥文件增加了一层加密保护。即使私钥文件不慎泄露攻击者没有密码短语也无法使用它。如果直接回车则表示不设置密码短语不推荐。操作完成后你会在~/.ssh/目录下看到两个新文件id_ed25519_my_server这是你的私钥权限必须是600仅所有者可读可写。id_ed25519_my_server.pub这是你的公钥内容是一长串以算法名开头的文本。4. 可选启动ssh-agent并添加私钥如果你设置了密码短语每次使用密钥登录时都需要输入可能会有些麻烦。ssh-agent是一个在后台运行的程序可以帮你安全地缓存已解密的私钥在一段时间内无需重复输入密码短语。# 启动ssh-agent如果尚未运行 eval $(ssh-agent -s) # 将私钥添加到agent ssh-add ~/.ssh/id_ed25519_my_server系统会提示你输入一次密码短语之后在当前终端会话期间再使用该密钥连接就无需输入了。你可以将ssh-add命令和ssh-agent的启动配置到你的shell配置文件如~/.bashrc或~/.zshrc中实现自动加载。3.2 第二步将公钥部署到远程服务器现在我们需要把上一步生成的公钥内容放到服务器的对应用户目录下。方法A使用ssh-copy-id命令最简便如果你的本地系统支持这个命令macOS和大多数Linux发行版都有这是首选。ssh-copy-id -i ~/.ssh/id_ed25519_my_server.pub usernameyour_server_ip-i指定公钥文件路径。username你在服务器上的用户名如root或ubuntu等。your_server_ip你的服务器IP地址。执行后会提示你输入对应用户的密码这是最后一次使用密码登录。成功后公钥就会被自动追加到服务器上~/.ssh/authorized_keys文件的末尾。方法B手动复制通用方法如果ssh-copy-id不可用如某些Windows环境可以手动操作。查看并复制公钥内容cat ~/.ssh/id_ed25519_my_server.pub全选并复制终端中输出的整行内容从ssh-ed25519 AAA...开始到注释结束。登录服务器确保目标用户的家目录下存在.ssh文件夹且权限正确ssh usernameyour_server_ip # 输入密码登录后 mkdir -p ~/.ssh chmod 700 ~/.ssh将公钥写入authorized_keys文件echo “你刚才复制的公钥内容” ~/.ssh/authorized_keys设置authorized_keys文件权限chmod 600 ~/.ssh/authorized_keys这个600权限至关重要权限过大会导致SSH服务器出于安全考虑拒绝使用该文件。3.3 第三步测试密钥登录在关闭密码之前务必先测试密钥登录是否成功。从你的本地机器使用-i参数指定私钥文件进行连接ssh -i ~/.ssh/id_ed25519_my_server usernameyour_server_ip如果设置了密码短语此时会提示你输入。如果一切配置正确你将无需输入服务器用户密码即可登录。测试成功的关键标志登录过程没有出现usernameyour_server_ip‘s password:这个提示。如果出现了说明密钥认证未生效请返回检查公钥是否复制正确、文件权限是否正确服务器上.ssh目录为700authorized_keys文件为600。3.4 第四步配置SSH服务端强化安全并禁用密码密钥登录测试成功后我们就可以放心地“关上密码这扇门”了。我们需要修改SSH服务端的配置文件/etc/ssh/sshd_config。1. 备份原始配置文件好习惯sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak2. 编辑SSH服务端配置使用你熟悉的编辑器如vim或nanosudo vim /etc/ssh/sshd_config找到并修改以下关键参数。请注意有些参数可能被注释以#开头你需要取消注释并修改其值。# 1. 禁止root用户直接登录强烈建议先用普通用户sudo # 将 PermitRootLogin 设置为 no PermitRootLogin no # 2. 强制使用密钥认证禁用密码认证 # 将 PasswordAuthentication 设置为 no PasswordAuthentication no # 将 PubkeyAuthentication 设置为 yes (通常默认就是yes) PubkeyAuthentication yes # 3. 禁用其他不安全的认证方式 # 确保以下参数为 no ChallengeResponseAuthentication no UsePAM no # 注意在Ubuntu 22.04及更高版本或某些CentOS配置中UsePAM可能需要保持为yes以支持其他功能如果禁用后出现问题请改回yes。最关键是PasswordAuthentication为no。 # 4. 可选但推荐修改默认端口 # 取消 Port 的注释并将22改为一个1024-65535之间的非知名端口例如 2345 Port 2345 # 注意修改端口后防火墙必须放行新端口且后续连接命令需加 -p 2345 参数。 # 5. 可选限制登录用户 # 在文件末尾添加只允许特定用户登录例如只允许用户 deploy 和 admin 登录 AllowUsers deploy admin # 6. 重要确保密钥文件路径设置正确 AuthorizedKeysFile .ssh/authorized_keys3. 检查配置文件语法修改后使用以下命令检查配置文件是否有语法错误sudo sshd -t如果没有任何输出表示语法正确。如果有错误它会提示你哪一行有问题。4. 重启SSH服务使配置生效这是最关键且危险的一步你必须确保当前的SSH会话不会因为配置错误而中断。最佳实践是保持当前通过密钥登录的SSH会话窗口不要关闭。打开另一个终端窗口同样使用密钥登录到服务器。在新的会话中执行重启命令# Ubuntu/Debian 系统 sudo systemctl restart ssh # 或 sudo service ssh restart # CentOS/RHEL 7/8 系统 sudo systemctl restart sshd # 或 sudo service sshd restart重启后立即在新的终端窗口尝试建立第三个SSH连接以验证新配置是否工作。例如如果你修改了端口ssh -i ~/.ssh/id_ed25519_my_server -p 2345 usernameyour_server_ip只有确认新的连接成功后你才可以安全地关闭最初的测试会话。致命警告切勿在唯一的SSH连接会话中重启SSH服务。如果配置有误例如误禁用密钥认证你会立刻被踢出并永远无法连接只能通过云服务商的控制台VNC或物理接触服务器来修复。保持一个“逃生会话”是铁律。3.5 第五步配置防火墙如果修改了端口如果你修改了SSH默认端口第4步中的可选操作必须更新防火墙规则放行新的端口并考虑是否关闭旧端口22的访问。对于UFWUbuntu常用sudo ufw allow 2345/tcp # 允许新端口 sudo ufw deny 22/tcp # 拒绝旧端口可选但推荐 sudo ufw reload对于FirewalldCentOS 7/8常用sudo firewall-cmd --permanent --add-port2345/tcp # 添加新端口 sudo firewall-cmd --permanent --remove-servicessh # 移除默认的ssh服务即端口22 sudo firewall-cmd --reload对于iptables通用# 允许新端口 sudo iptables -A INPUT -p tcp --dport 2345 -j ACCEPT # 保存规则根据系统不同 sudo iptables-save | sudo tee /etc/sysconfig/iptables # 或使用 iptables-persistent 等工具4. 高级配置与多服务器管理当你需要管理多台服务器或多个密钥时合理的本地配置能极大提升效率。4.1 本地SSH客户端配置~/.ssh/config在你的本地~/.ssh/目录下创建或编辑config文件可以为不同的服务器设置别名和默认参数。Host myserver1 # 自定义别名方便记忆 HostName 192.168.1.100 # 服务器真实IP或域名 Port 2345 # 端口号如果修改过 User ubuntu # 登录用户名 IdentityFile ~/.ssh/id_ed25519_myserver1 # 指定使用的私钥 IdentitiesOnly yes # 只使用指定的密钥避免尝试其他密钥 Host myserver2 HostName example.com User centos IdentityFile ~/.ssh/id_rsa_myserver2 Host github.com # 为Git服务配置 User git IdentityFile ~/.ssh/id_ed25519_github配置完成后连接服务器只需ssh myserver1SSH会自动使用配置文件中指定的所有参数无需再输入-i、-p、username等。4.2 为服务器上的不同用户添加密钥如果需要让多个用户都能通过密钥登录同一台服务器或者为一个用户添加多个公钥例如你和你的同事只需将各自的公钥内容逐行追加到相应用户家目录下的~/.ssh/authorized_keys文件中即可。4.3 密钥的备份与恢复私钥丢失意味着永久失去访问权限。备份策略加密备份将~/.ssh/目录下的私钥文件如id_ed25519_*复制到加密的U盘、硬盘或使用gpg加密后存储到云盘。密码管理器一些高级密码管理器支持安全地存储SSH私钥。恢复恢复时将备份的私钥文件放回本地~/.ssh/目录并确保权限为600。将对应的公钥重新部署到服务器。5. 故障排查与常见问题实录即使按照步骤操作也可能会遇到问题。这里记录了我踩过的坑和解决方案。5.1 密钥登录失败依然提示输入密码这是最常见的问题。请按以下清单逐项检查问题点检查命令在服务器上执行正确设置/现象1. 文件权限ls -la ~/.ssh/.ssh目录权限应为700(drwx------)authorized_keys文件权限应为600(-rw-------)。权限不对会导致SSH出于安全考虑直接忽略密钥。2. 公钥内容cat ~/.ssh/authorized_keys确认公钥内容完整、没有多余空格或换行且与本地公钥文件内容完全一致。可以手动vim编辑删除旧内容重新粘贴一次。3. SELinuxCentOSgetenforce如果返回EnforcingSELinux可能会阻止非标准目录或权限的访问。尝试临时禁用测试sudo setenforce 0。如果解决问题需要为.ssh目录添加正确的SELinux上下文sudo restorecon -Rv ~/.ssh。4. 用户家目录权限ls -ld ~用户家目录的权限不能过于开放如drwxrwxrwx。通常应为755(drwxr-xr-x) 或700。过宽的权限也会导致SSH拒绝密钥认证。5. SSH服务配置sudo grep -E “^(PasswordAuthenticationPubkeyAuthentication)” /etc/ssh/sshd_config6. 连接命令ssh -v -i /path/to/key userhost使用-v详细模式连接观察输出日志。通常会明确提示失败原因如“Permission denied (publickey)”并指出它尝试了哪些密钥文件。5.2 修改端口后无法连接防火墙未放行这是首要原因。确保新端口已在服务器防火墙ufw/firewalld/iptables中正确添加并启用。连接命令未指定端口如果修改了端口连接时必须用-p参数指定例如ssh -p 2345 userhost或在~/.ssh/config中配置Port。SSH服务监听错误端口检查SSH服务是否真的在监听新端口sudo netstat -tlnp | grep sshd。确保输出中包含你设置的端口号如:2345。5.3 禁用密码后如何临时恢复密码登录如果你把自己锁在外面了而你有服务器控制台访问权限如云厂商的VNC/Web终端通过控制台登录服务器。编辑/etc/ssh/sshd_config将PasswordAuthentication临时改为yes。重启SSH服务sudo systemctl restart sshd。用密码登录后立即检查并修复你的密钥配置然后记得再把密码登录关掉。5.4 使用VSCode Remote-SSH或Cursor等编辑器连接这些编辑器底层也使用SSH协议。配置好本地的~/.ssh/config文件后在它们的远程连接窗口中直接输入你配置的Host别名如myserver1即可它们会自动读取配置。如果连接失败检查编辑器是否使用了自带的SSH还是系统SSH。通常可以在设置中指定系统SSH的路径C:\Windows\System32\OpenSSH\ssh.exeon Windows,/usr/bin/sshon Linux/macOS。5.5 服务器上.ssh目录及文件权限参考表为了彻底避免权限问题记住这个“金科玉律”文件/目录推荐权限命令用户家目录 (~)755(drwxr-xr-x) 或700(drwx------)chmod 755 ~或chmod 700 ~.ssh目录700(drwx------)chmod 700 ~/.sshauthorized_keys文件600(-rw-------)chmod 600 ~/.ssh/authorized_keys私钥文件 (本地)600(-rw-------)chmod 600 ~/.ssh/id_ed25519公钥文件 (本地)644(-rw-r--r--)chmod 644 ~/.ssh/id_ed25519.pubconfig文件 (本地)600或644chmod 600 ~/.ssh/config最后关于“禁用空密码”和“限制身份验证最大尝试次数”这类需求它们确实是安全加固的一部分通常通过修改/etc/ssh/sshd_config中的PermitEmptyPasswords no和MaxAuthTries 3来实现。但在彻底禁用密码认证PasswordAuthentication no之后这些针对密码的防护措施实际上已经不再起作用了因为密码认证的通道已经被完全关闭。我们的方案是在更根本的层面上解决了问题。当然在混合环境仍需保留部分密码登录下这些参数依然有价值。但对于追求极致安全的个人服务器或生产环境我的建议始终是生成强密钥彻底关密码。这套组合拳打下来你的服务器SSH入口安全性已经超越了90%的默认配置机器。