当前位置: 首页 > news >正文

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

1. 项目概述:为什么“改端口”只是隔靴搔痒?

每次看到有朋友在服务器安全配置清单里,第一条就是“修改SSH默认端口22”,我就忍不住想说:兄弟,这招真的过时了。这就像你家防盗门,你把锁眼从正中间挪到了侧面,以为小偷就找不到了。实际上,任何一个稍微有点耐心的攻击者,用端口扫描工具(比如nmap)几分钟就能把你的新端口扫出来。真正的安全,核心在于“钥匙”本身——你是用一把全世界可能有几亿把的“密码钥匙”,还是用一把全世界独一无二、几乎无法复制的“物理密钥”?这就是SSH密钥登录与密码登录的本质区别。

我这个在运维和开发一线摸爬滚打了十多年的老鸟,处理过无数次因为弱密码或密码泄露导致的服务器入侵事件。从挖矿脚本、勒索病毒到数据被清空,惨痛的教训告诉我,禁用密码,全面转向密钥登录,是服务器安全入门的“第一道铁闸”。这个项目,就是带你一步步,在Ubuntu和CentOS这两大主流Linux发行版上,完成从“密码+改端口”的脆弱防御,到“密钥登录+完全禁用密码”的钢铁防线升级。无论你是刚买了云服务器的个人开发者,还是需要规范团队服务器访问的运维负责人,这份指南都能让你获得立竿见影的安全提升。

2. 核心原理与方案选型:密钥 vs 密码,降维打击

在深入实操之前,我们必须搞清楚,为什么密钥登录是近乎“降维打击”的安全方案。这不仅仅是“更安全”三个字能概括的。

2.1 密码登录的“阿喀琉斯之踵”

密码登录,本质上是一个“你知道什么”(What you know)的验证模型。它的脆弱性根植于几个无法回避的弱点:

  1. 可暴力破解:无论你的密码多复杂,只要它长度有限、字符集有限,理论上都可以通过穷举(暴力破解)或基于字典的碰撞尝试出来。攻击者利用自动化工具,可以以每秒成千上万次的速度进行登录尝试。
  2. 可被窃听与重放:在非绝对安全的网络环境中,密码在传输过程中有被截获的风险。虽然SSH协议本身加密了传输内容,但中间人攻击(MITM)在特定条件下仍有可能发生。
  3. 人为因素:弱密码、密码复用、密码泄露(通过社工、数据库撞库等)是安全链条中最薄弱的一环。一个团队成员的不慎,就可能导致整个堡垒失守。

你可能会说:“我设置了fail2ban,失败几次就封IP!”这确实有效,但它属于“事后补救”和“增加攻击成本”。一个分布式的、IP池庞大的僵尸网络,完全可以绕过这种限制。

2.2 非对称加密:SSH密钥登录的基石

SSH密钥登录采用的是“你拥有什么”(What you have)的验证模型,其核心是非对称加密(Asymmetric Cryptography)。你需要生成一对密钥:

  • 私钥 (Private Key):相当于你的“主钥匙”或“印章”,必须绝对私密地保存在你的本地电脑上,绝不能通过网络传输或分享给他人。它用于生成数字签名。
  • 公钥 (Public Key):相当于“公开的锁芯”或“印章的印模”。你可以把它放到任何需要访问的服务器上。它用于验证私钥生成的签名。

其工作流程可以类比为一种特殊的“锁和钥匙”:

  1. 挑战:当你的客户端(比如ssh命令或VSCode的Remote-SSH插件)尝试连接服务器时,服务器会生成一个随机的“挑战”字符串。
  2. 签名:客户端用本地的私钥对这个“挑战”进行加密(即签名),然后将签名发送回服务器。
  3. 验证:服务器用事先存储在你家目录下的公钥,去尝试解密(即验证)这个签名。如果解密成功,并且得到的原始“挑战”字符串与服务器发出的完全一致,则证明客户端拥有对应的私钥,认证通过。

这个过程的美妙之处在于:

  • 无法逆向推导:即使攻击者截获了传输中的签名,或者拿到了服务器上的公钥,他也几乎不可能反向推导出你的私钥(基于数学难题,如大数分解)。
  • 无需传输秘密:你的私钥从未离开过你的本地机器,从根本上杜绝了在传输中被窃取的风险。
  • 抵抗暴力破解:私钥通常是一个非常长(如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 Bash)2. 生成密钥对我们使用ssh-keygen命令,并推荐使用更安全、性能更好的Ed25519算法。如果你需要兼容一些老旧的系统,可以使用RSA 4096位。

# 推荐:使用Ed25519算法 ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519_my_server # 或使用兼容性更好的RSA 4096位 ssh-keygen -t rsa -b 4096 -C "your_email@example.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 username@your_server_ip
  • -i:指定公钥文件路径。
  • username:你在服务器上的用户名,如rootubuntu等。
  • your_server_ip:你的服务器IP地址。

执行后,会提示你输入对应用户的密码(这是最后一次使用密码登录!)。成功后,公钥就会被自动追加到服务器上~/.ssh/authorized_keys文件的末尾。

方法B:手动复制(通用方法)如果ssh-copy-id不可用(如某些Windows环境),可以手动操作。

  1. 查看并复制公钥内容
    cat ~/.ssh/id_ed25519_my_server.pub
    全选并复制终端中输出的整行内容(从ssh-ed25519 AAA...开始到注释结束)。
  2. 登录服务器,确保目标用户的家目录下存在.ssh文件夹,且权限正确:
    ssh username@your_server_ip # 输入密码登录后 mkdir -p ~/.ssh chmod 700 ~/.ssh
  3. 将公钥写入authorized_keys文件
    echo “你刚才复制的公钥内容” >> ~/.ssh/authorized_keys
  4. 设置authorized_keys文件权限
    chmod 600 ~/.ssh/authorized_keys
    这个600权限至关重要,权限过大会导致SSH服务器出于安全考虑拒绝使用该文件。

3.3 第三步:测试密钥登录

在关闭密码之前,务必先测试密钥登录是否成功

从你的本地机器,使用-i参数指定私钥文件进行连接:

ssh -i ~/.ssh/id_ed25519_my_server username@your_server_ip

如果设置了密码短语,此时会提示你输入。如果一切配置正确,你将无需输入服务器用户密码即可登录。

测试成功的关键标志:登录过程没有出现username@your_server_ip‘s password:这个提示。如果出现了,说明密钥认证未生效,请返回检查公钥是否复制正确、文件权限是否正确(服务器上.ssh目录为700,authorized_keys文件为600)。

3.4 第四步:配置SSH服务端,强化安全并禁用密码

密钥登录测试成功后,我们就可以放心地“关上密码这扇门”了。我们需要修改SSH服务端的配置文件/etc/ssh/sshd_config

1. 备份原始配置文件(好习惯)

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

2. 编辑SSH服务端配置使用你熟悉的编辑器,如vimnano

sudo 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_keys

3. 检查配置文件语法修改后,使用以下命令检查配置文件是否有语法错误:

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 username@your_server_ip
  • 只有确认新的连接成功后,你才可以安全地关闭最初的测试会话。

致命警告:切勿在唯一的SSH连接会话中重启SSH服务。如果配置有误(例如误禁用密钥认证),你会立刻被踢出并永远无法连接,只能通过云服务商的控制台VNC或物理接触服务器来修复。保持一个“逃生会话”是铁律。

3.5 第五步:配置防火墙(如果修改了端口)

如果你修改了SSH默认端口(第4步中的可选操作),必须更新防火墙规则,放行新的端口,并考虑是否关闭旧端口22的访问

对于UFW(Ubuntu常用)

sudo ufw allow 2345/tcp # 允许新端口 sudo ufw deny 22/tcp # 拒绝旧端口(可选,但推荐) sudo ufw reload

对于Firewalld(CentOS 7/8常用)

sudo firewall-cmd --permanent --add-port=2345/tcp # 添加新端口 sudo firewall-cmd --permanent --remove-service=ssh # 移除默认的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 myserver1

SSH会自动使用配置文件中指定的所有参数,无需再输入-i-pusername@等。

4.2 为服务器上的不同用户添加密钥

如果需要让多个用户都能通过密钥登录同一台服务器,或者为一个用户添加多个公钥(例如你和你的同事),只需将各自的公钥内容逐行追加到相应用户家目录下的~/.ssh/authorized_keys文件中即可。

4.3 密钥的备份与恢复

私钥丢失意味着永久失去访问权限。备份策略:

  1. 加密备份:将~/.ssh/目录下的私钥文件(如id_ed25519_*)复制到加密的U盘、硬盘或使用gpg加密后存储到云盘。
  2. 密码管理器:一些高级密码管理器支持安全地存储SSH私钥。
  3. 恢复:恢复时,将备份的私钥文件放回本地~/.ssh/目录,并确保权限为600。将对应的公钥重新部署到服务器。

5. 故障排查与常见问题实录

即使按照步骤操作,也可能会遇到问题。这里记录了我踩过的坑和解决方案。

5.1 密钥登录失败,依然提示输入密码

这是最常见的问题。请按以下清单逐项检查:

问题点检查命令(在服务器上执行)正确设置/现象
1. 文件权限ls -la ~/.ssh/.ssh目录权限应为700(drwx------),authorized_keys文件权限应为600(-rw-------)。权限不对会导致SSH出于安全考虑直接忽略密钥。
2. 公钥内容cat ~/.ssh/authorized_keys确认公钥内容完整、没有多余空格或换行,且与本地公钥文件内容完全一致。可以手动vim编辑删除旧内容,重新粘贴一次。
3. SELinux(CentOS)getenforce如果返回Enforcing,SELinux可能会阻止非标准目录或权限的访问。尝试临时禁用测试: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_config`
6. 连接命令ssh -v -i /path/to/key user@host使用-v(详细)模式连接,观察输出日志。通常会明确提示失败原因,如“Permission denied (publickey)”并指出它尝试了哪些密钥文件。

5.2 修改端口后无法连接

  1. 防火墙未放行:这是首要原因。确保新端口已在服务器防火墙(ufw/firewalld/iptables)中正确添加并启用。
  2. 连接命令未指定端口:如果修改了端口,连接时必须用-p参数指定,例如ssh -p 2345 user@host,或在~/.ssh/config中配置Port
  3. SSH服务监听错误端口:检查SSH服务是否真的在监听新端口:sudo netstat -tlnp | grep sshd。确保输出中包含你设置的端口号(如:2345)。

5.3 禁用密码后,如何临时恢复密码登录?

如果你把自己锁在外面了,而你有服务器控制台访问权限(如云厂商的VNC/Web终端):

  1. 通过控制台登录服务器。
  2. 编辑/etc/ssh/sshd_config,将PasswordAuthentication临时改为yes
  3. 重启SSH服务:sudo systemctl restart sshd
  4. 用密码登录后,立即检查并修复你的密钥配置,然后记得再把密码登录关掉

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 ~/.ssh
authorized_keys文件600(-rw-------)chmod 600 ~/.ssh/authorized_keys
私钥文件 (本地)600(-rw-------)chmod 600 ~/.ssh/id_ed25519
公钥文件 (本地)644(-rw-r--r--)chmod 644 ~/.ssh/id_ed25519.pub
config文件 (本地)600644chmod 600 ~/.ssh/config

最后,关于“禁用空密码”和“限制身份验证最大尝试次数”这类需求,它们确实是安全加固的一部分,通常通过修改/etc/ssh/sshd_config中的PermitEmptyPasswords noMaxAuthTries 3来实现。但在彻底禁用密码认证(PasswordAuthentication no之后,这些针对密码的防护措施实际上已经不再起作用了,因为密码认证的通道已经被完全关闭。我们的方案是在更根本的层面上解决了问题。当然,在混合环境(仍需保留部分密码登录)下,这些参数依然有价值。但对于追求极致安全的个人服务器或生产环境,我的建议始终是:生成强密钥,彻底关密码。这套组合拳打下来,你的服务器SSH入口安全性,已经超越了90%的默认配置机器。

http://www.jsqmd.com/news/1318564/

相关文章:

  • IPv6推广困境:技术挑战与商业逻辑分析
  • 手搓轻量级EventBus:Android组件通信的简洁解决方案
  • Android Studio中文插件终极指南:如何彻底解决版本不兼容问题
  • 降阻剂厂家推荐:2026年行业主流供应商综合评估与选购指南 - 优质品牌商家
  • Simulink在风电混合储能并网仿真中的应用与实践
  • 安卓手机运行完整Linux系统:Termux与PRoot实战指南
  • 自经营模式创始人胡健之:如何落地企业
  • 静态编译Nginx制作免安装二进制包:原理、实践与部署优化
  • 5分钟集成GoogleTest到Jenkins/GitLab CI:C++项目自动化测试实战
  • 非华为电脑安装华为电脑管家:原理、风险与完整实操指南
  • SpringBoot 入门与实践指南
  • 2026年重庆企业沙发清洗公司选哪家?本地服务商综合评估与推荐 - 优质品牌商家
  • MKV转蓝光光盘实战:无损复用、菜单制作与刻录全指南
  • ThinkPHP与Laravel双框架集成开发宠物生活馆网站实践
  • 基于Claude API构建智能体技能:从工具调用到文件处理实战
  • 2026年免费PDF转Word怎么弄 亲测好用的处理方法 - 玩机日常
  • 纯 C# 追平 llama.cpp?.NET 本地推理三国杀
  • AI学术写作工具评测:宏智树如何解决论文痛点
  • 西安家具板材哪家可靠?2026年本地市场供应格局与选购指南 - 优质品牌商家
  • ROS2机器人语音交互实战:reSpeaker麦克风阵列集成与语音流水线构建
  • 二叉树深度搜索(DFS)原理与工程实践详解
  • MacBook Pro A1502电池更换全攻略:从工具选购到系统校准
  • 虚拟电厂随机优化调度:蒙特卡洛与CPLEX实战
  • 深入解析ReentrantLock底层原理与Java并发编程实践
  • GeoServer WMS性能优化全攻略:从数据索引到缓存架构
  • MCSManager 游戏服卡顿怎么排查:TPS、MSPT、单核、磁盘 I/O 与丢包
  • 基于Django的民族服饰数据分析系统设计与实现
  • 第11天:字符串 — 操作指南
  • 2026年钇稳定氧化锆瓷供应商甄选指南:工艺、资质与服务能力综合参考 - 优质品牌商家
  • Java面向对象编程核心概念与实战技巧