CentOS服务器要想真正安全,第一件事就是关掉密码登录,换成SSH密钥认证。这不是什么高级操作,而是每一台生产环境服务器的基本配置。密码登录的风险太大了——暴力破解、字典攻击、撞库,这些手段每天都在发生。而SSH密钥认证用的是非对称加密,公钥放在服务器上,私钥留在你自己手里,没有私钥谁也登不进去。下面我把从生成密钥到配置服务器、禁用密码登录的完整流程一步步讲清楚,包括一些容易踩的坑和进阶技巧。

为什么必须用SSH密钥替代密码登录

密码登录的本质问题在于"你知道的东西"可以被猜到、被窃取、被暴力破解。哪怕你设了一个16位的复杂密码,只要服务器暴露在公网,自动化脚本24小时不停地试,总有一天会被撞上。而且很多人习惯在多台服务器上用同一个密码,一旦一台被破,全部沦陷。

SSH密钥认证完全不同。它基于公钥密码学,你生成一对密钥——一个公钥一个私钥。公钥放到服务器的authorized_keys文件里,私钥保存在本地。登录时服务器用公钥加密一段随机数据发给客户端,客户端用私钥解密后回传,验证通过才放行。这个过程中密码根本不参与传输,暴力破解完全失效。即使有人拿到了你的公钥,没有对应的私钥也无法登录。

生成SSH密钥对的具体操作

在你本地电脑(Linux、macOS或者Windows的PowerShell都行)上执行以下命令生成密钥:

ssh-keygen -t ed25519 -C "your_email@example.com"

这里推荐用ed25519算法而不是传统的RSA。ed25519是目前公认最安全、性能最好的算法,密钥短、速度快、安全性高。如果你的系统比较老不支持ed25519,那就用RSA 4096位:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

执行后会提示你保存密钥的位置,默认是~/.ssh/id_ed25519(或者id_rsa)。建议直接回车用默认路径。然后会让你设一个passphrase(密钥密码),这个强烈建议设一个,相当于给私钥再加一层锁。就算别人偷到了你的私钥文件,没有这个passphrase也用不了。

生成完毕后,你会得到两个文件:私钥id_ed25519(或者id_rsa)和公钥id_ed25519.pub(或者id_rsa.pub)。私钥绝对不能给任何人,公钥才是要放到服务器上的。

把公钥部署到CentOS服务器上

最简单的方法是用ssh-copy-id命令一键部署:

ssh-copy-id -i ~/.ssh/id_ed25519.pub root@你的服务器IP

这条命令会自动把你的公钥追加到服务器的/root/.ssh/authorized_keys文件里,同时自动设置好文件权限。如果你用的不是root用户,就把root换成你的实际用户名。

如果ssh-copy-id不可用(比如某些精简系统没装),可以手动操作。先在本地查看公钥内容:

cat ~/.ssh/id_ed25519.pub

然后登录服务器,执行:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "你的公钥内容粘贴到这里" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

权限设置非常关键。.ssh目录必须是700,authorized_keys文件必须是600,否则SSH会认为不安全直接拒绝密钥认证。这是很多人配置完发现密钥登录不生效的首要原因。

测试密钥登录是否正常工作

在禁用密码登录之前,一定要先测试密钥能不能正常登录。开一个新的终端窗口(不要关掉当前的会话,万一出问题你还能救回来),执行:

ssh -i ~/.ssh/id_ed25519 root@你的服务器IP

如果配置正确,系统会提示你输入密钥的passphrase(如果设了的话),输入后直接登录成功,不需要输入服务器密码。如果提示需要密码或者报错,回头检查公钥是否正确写入、文件权限是否正确、SELinux是否有拦截。

特别提一下SELinux的问题。CentOS默认开启SELinux,有时候它会阻止SSH读取authorized_keys文件。如果你确认配置都对但就是登录不了,可以临时关闭SELinux测试:

setenforce 0

如果关掉后能登录了,说明是SELinux的问题。正确的做法不是永久关闭SELinux,而是修复上下文标签:

restorecon -Rv ~/.ssh

这条命令会把.ssh目录下所有文件的SELinux安全上下文恢复成正确的值。

配置SSH服务端禁用密码登录

确认密钥登录没问题后,就可以关掉密码登录了。编辑SSH配置文件:

sudo vi /etc/ssh/sshd_config

找到以下几个参数,修改或添加:

PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM no

逐个解释一下。PasswordAuthentication no是核心,关掉密码认证。PubkeyAuthentication yes确保密钥认证开启。PermitEmptyPasswords no禁止空密码登录。ChallengeResponseAuthentication no关掉交互式认证(比如键盘交互那种)。UsePAM no在CentOS 7/8上建议关掉,因为PAM模块有时候会绕过SSH本身的认证控制。

如果你不是root用户而是用普通用户登录,还要确认AllowUsers或者AllowGroups参数里包含了你的用户名,或者直接注释掉这些限制。另外,如果你的服务器有多个用户需要用密钥登录,每个用户都需要在自己的~/.ssh/authorized_keys里添加对应的公钥。

修改完配置后重启SSH服务:

sudo systemctl restart sshd

CentOS 7用sshd,CentOS 8/Stream也是sshd。重启后密码登录就彻底失效了,只有持有正确私钥的人才能连上来。

进阶技巧:多密钥管理和密钥轮换

在实际运维中,你可能有多台服务器、多个管理员,或者需要定期更换密钥。这里有几个实用技巧。

第一,用SSH config文件管理多个服务器的密钥。在本地~/.ssh/config里配置:

Host myserver
    HostName 192.168.1.100
    User root
    IdentityFile ~/.ssh/id_ed25519_server1
    Port 22

Host myserver2
    HostName 192.168.1.101
    User admin
    IdentityFile ~/.ssh/id_ed25519_server2
    Port 2222

这样不同服务器用不同密钥,管理起来很清楚。以后直接ssh myserver就行,不用每次指定-i参数。

第二,定期轮换密钥。建议每6到12个月更换一次密钥对。操作很简单:生成新密钥、部署到服务器、测试通过后删除旧公钥。千万不要直接删旧的,万一新的有问题你就锁在外面了。

第三,禁用root远程登录。很多安全规范要求不允许root直接SSH登录,而是用普通用户登录后再sudo提权。如果要这样做,在sshd_config里加:

PermitRootLogin no

然后确保你的普通用户在sudoers里有权限。

常见问题排查清单

配置过程中遇到问题不要慌,按以下顺序排查:

1. 确认公钥内容完整。复制的时候不要多空格、不要换行,公钥是一整行。用cat查看确认。

2. 检查文件权限。.ssh目录700,authorized_keys文件600,私钥文件600。用ls -la ~/.ssh查看。

3. 检查SELinux状态。用getenforce查看,如果是Enforcing,试试restorecon修复或者临时setenforce 0测试。

4. 检查sshd_config语法。修改后可以用sudo sshd -t测试配置文件有没有语法错误。

5. 查看SSH日志。/var/log/secure(CentOS 7)或者journalctl -u sshd(CentOS 8)可以看到详细的认证过程和报错信息。

6. 确认防火墙没挡住。如果你改了SSH端口,记得在firewalld里放行新端口。

关于密钥存储安全的额外建议

私钥是你服务器安全的命脉,丢了或者被偷了后果很严重。几点建议:本地私钥文件设置600权限;不要把私钥放在网盘、代码仓库或者任何联网的地方;如果是多人协作,考虑用SSH证书(SSH Certificate)机制,由一个CA统一签发和管理,方便撤销和审计;笔记本电脑上的私钥可以配合全盘加密使用,防止设备丢失后私钥泄露。

总结一下,CentOS上用SSH密钥替代密码登录,核心就是三步:生成密钥对、部署公钥到服务器、修改sshd_config关闭密码认证。整个过程十分钟就能搞定,但安全性提升是质的飞跃。这是服务器安全加固最基础也最重要的一步,没有任何理由跳过它。做好这一步,你的服务器就已经挡住了绝大多数自动化攻击。