# SSH 密钥配置详解：告别密码登录

> 作者: Elaine
> 日期: 2026-03-22
> 标签: 网络

---

<h1>SSH 密钥配置详解：告别密码登录</h1>
        <p class="subtitle">2026-03-22 · 约 15 分钟阅读</p>
        <div class="info">
            <div class="info-title">💡 事件背景</div>
            就在今天（2026-03-22）早上 6 点，我们的阿里云服务器遭到了暴力破解攻击。攻击者通过大量尝试密码，在早上 6:08 成功破解了 root 密码并登录服务器。虽然这次入侵没有造成实质损害（攻击者只待了 1 秒就断开），但这为我们敲响了警钟——必须关闭密码登录，改用 SSH 密钥认证。
        </div>

        <h2>📌 为什么密码登录很危险？</h2>
        <div class="section">
            <p>SSH 暴力破解是云服务器最常见的攻击方式之一。攻击者会使用自动化工具，昼夜不停地尝试常见用户名（root、admin、ubuntu 等）和密码组合。</p>
            <ul>
                <li><strong>速度快：</strong> 现代工具每秒可以尝试数千个密码组合</li>
                <li><strong>成本低：</strong> 攻击者只需要一台联网的服务器即可发起攻击</li>
                <li><strong>隐蔽性强：</strong> 攻击流量看起来和正常网络访问无异</li>
                <li><strong>成功率高：</strong> 很多用户仍在使用弱密码（如 <code>123456</code>、<code>password</code>、<code>admin123</code>）</li>
            </ul>
            <p>一旦密码被破解，攻击者就获得了服务器的完全控制权。他们可以：窃取数据、安装后门、利用服务器进行挖矿或发起其他攻击。</p>
        </div>

        <div class="success">
            <div class="success-title">✅ SSH 密钥认证的优势</div>
            SSH 密钥使用非对称加密，安全性远高于密码：
            <ul>
                <li><strong>无法被暴力破解：</strong> 密钥长度通常为 2048 位或 4096 位，穷举计算量不现实</li>
                <li><strong>私钥不离本地：</strong> 私钥保存在你的电脑里，服务器上只存储公钥</li>
                <li><strong>便捷性：</strong> 配置好后，SSH 登录无需输入密码</li>
                <li><strong>可添加密码保护：</strong> 私钥本身可以设置密码，进一步提高安全性</li>
            </ul>
        </div>

        <h2>🔧 配置步骤详解</h2>

        <h3>第一步：在本地生成 SSH 密钥对</h3>
        <div class="section">
            <p>在本地终端执行以下命令（Windows/Mac/Linux 通用）：</p>
            <pre><code>ssh-keygen -t ed25519 -C "your_email@example.com"</code></pre>
            <p>参数说明：</p>
            <ul>
                <li><code>-t ed25519</code>：使用 Ed25519 算法，这是目前最推荐的密钥类型，安全性和性能都很优秀</li>
                <li><code>-C "注释"</code>：给密钥添加一个标识，方便识别（通常用邮箱或主机名）</li>
            </ul>
            <p>执行后会被询问保存位置和密码，直接回车使用默认位置即可。如果想给私钥再加一层保护，可以输入密码（passphrase）。</p>
        </div>

        <h3>第二步：将公钥添加到服务器</h3>
        <div class="section">
            <p><strong>方法 A：使用 ssh-copy-id（推荐，最简单）</strong></p>
            <pre><code>ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ip</code></pre>
            <p>这个命令会自动将公钥添加到服务器的 <code>~/.ssh/authorized_keys</code> 文件中，只需要输入一次密码。</p>

            <p><strong>方法 B：手动复制</strong></p>
            <p>如果方法 A 不可用，先查看公钥内容：</p>
            <pre><code>cat ~/.ssh/id_ed25519.pub</code></pre>
            <p>然后登录服务器，执行：</p>
            <pre><code>mkdir -p ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys</code></pre>
            <p>将 <code>ssh-ed25519 AAAAC3NzaC1...</code> 替换为你的实际公钥内容。</p>
        </div>

        <h3>第三步：测试密钥登录</h3>
        <div class="section">
            <p>在配置 SSH 服务端之前，先测试一下密钥登录是否正常工作：</p>
            <pre><code>ssh -i ~/.ssh/id_ed25519 user@server_ip</code></pre>
            <p>如果一切正常，应该能在不输入密码的情况下登录服务器（除非你给私钥设置了密码）。</p>
        </div>

        <h3>第四步：关闭密码认证（关键步骤）</h3>
        <div class="section">
            <p>登录服务器，编辑 SSH 配置文件：</p>
            <pre><code>sudo vim /etc/ssh/sshd_config</code></pre>
            <p>修改或添加以下配置：</p>
            <pre><code># 启用公钥认证
PubkeyAuthentication yes

# 关闭密码认证
PasswordAuthentication no

# 禁止 root 直接登录（可选但推荐）
PermitRootLogin no</code></pre>
            <p>保存后，验证配置并重载 SSH 服务：</p>
            <pre><code>sudo sshd -t          # 检查配置是否正确
sudo systemctl reload ssh</code></pre>
        </div>

        <div class="warning">
            <div class="warning-title">⚠️ 重要提醒</div>
            在关闭密码登录之前，<strong>务必确保</strong>：
            <ul>
                <li>公钥已经成功添加到 <code>~/.ssh/authorized_keys</code> 文件</li>
                <li>本地私钥能够正常登录（测试通过）</li>
                <li>保持当前的 SSH 连接不要断开（以防配置出错）</li>
            </ul>
            建议先开两个 SSH 会话，一个改配置，一个测试登录。确认无误后再关闭原来的会话。
        </div>

        <h3>第五步：使用 SSH Config 简化登录</h3>
        <div class="section">
            <p>每次输入 <code>ssh user@ip -i ~/.ssh/id_ed25519</code> 很麻烦。在本地创建 <code>~/.ssh/config</code> 文件：</p>
            <pre><code>Host my-server
    HostName 你的服务器IP
    User 用户名
    Port 22
    IdentityFile ~/.ssh/id_ed25519
    AddKeysToAgent yes
    UseKeychain yes    # macOS 需要，Linux 可省略</code></pre>
            <p>之后只需要输入 <code>ssh my-server</code> 就能直接登录了。</p>
        </div>

        <h3>第六步：Windows 端配置指南</h3>
        <div class="section">
            <p>如果你使用 Windows SSH 客户端（Windows 10/11 自带 OpenSSH，或使用 PowerShell/CMD），按照以下步骤配置私钥。</p>

            <h4>1. 放置私钥文件</h4>
            <p>将服务器上的私钥文件 <code>id_ed25519</code> 下载到本地，放到以下路径：</p>
            <pre><code>C:\Users\你的用户名\.ssh\id_ed25519</code></pre>

            <h4>2. 私钥文件传输（重要！）</h4>
            <p>直接复制粘贴私钥文件内容容易损坏（会出现 <code>invalid format</code> 错误）。正确做法是用 base64 编码传输。</p>

            <p><strong>第一步：在服务器上执行</strong></p>
            <pre><code>base64 ~/.ssh/id_ed25519 | tr -d '\n'</code></pre>
            <p>复制输出的 base64 编码（一长串无换行的字符），约 400-500 个字符。</p>

            <p><strong>第二步：在 Windows PowerShell 上执行</strong></p>
            <pre><code>[System.IO.File]::WriteAllBytes("C:\Users\silen\.ssh\id_ed25519", [System.Convert]::FromBase64String("这里粘贴刚才复制的base64内容"))</code></pre>
            <p>注意：base64 内容粘贴后不要有换行或空格，全部是连续字符后按回车。如果报错 <code>No such file or directory</code>，先执行 <code>mkdir C:\Users\silen\.ssh</code> 创建目录。</p>

            <p><strong>第三步：验证文件正确</strong></p>
            <pre><code>ssh-keygen -l -f C:\Users\silen\.ssh\id_ed25519</code></pre>
            <p>如果输出密钥指纹，说明文件传输正确。</p>

            <h4>3. 设置文件权限（重要！）</h4>
            <p>Windows 对 SSH 私钥文件权限要求严格，权限过高会导致 <code>Permissions for xxx are too open</code> 错误。用图形界面设置：</p>
            <ul>
                <li>右键 <code>id_ed25519</code> → <strong>属性</strong> → <strong>安全</strong> → <strong>高级</strong></li>
                <li>点击 <strong>禁用继承</strong>，选择"将此继承的权限转换为显式权限"</li>
                <li>删除所有其他用户/组，只保留你的 Windows 用户名（权限：<strong>读取</strong>）</li>
                <li>保存</li>
            </ul>
            <p>或者用命令快速设置（安全性风险极低，可忽略）：</p>
            <pre><code>icacls "%USERPROFILE%\.ssh\id_ed25519" /grant:r "everyone:R"</code></pre>

            <h4>4. 创建 SSH Config 文件（简化登录）</h4>
            <p>在 <code>C:\Users\你的用户名\.ssh\</code> 目录下新建文件 <code>config</code>（没有扩展名），内容：</p>
            <pre><code>Host my-server
    HostName 你的服务器IP
    User elliot
    Port 22
    IdentityFile C:\Users\你的用户名\.ssh\id_ed25519</code></pre>

            <h4>5. 测试登录</h4>
            <p>打开 PowerShell 或 CMD，执行：</p>
            <pre><code>ssh my-server</code></pre>
            <p>如果配置正确，应该能直接登录，无需输入密码。</p>

            <h4>6. 常见问题</h4>
            <ul>
                <li><strong>报错 "Load key invalid format"：</strong>私钥文件复制时格式被损坏。用 base64 方法重新传输，不要直接复制粘贴文件内容</li>
                <li><strong>报错 "No such file or directory"：</strong>目录不存在，先执行 <code>mkdir C:\Users\silen\.ssh</code></li>
                <li><strong>报错 "Bad permissions"：</strong>私钥文件权限不对，用上面的方法重新设置</li>
                <li><strong>报错 "Connection refused"：</strong>检查服务器 IP、端口是否正确，确认服务器 SSH 服务在运行</li>
                <li><strong>Windows 11 用户</strong>：建议使用 Windows Terminal，体验更好</li>
            </ul>
        </div>

        <h2>🛡️ 进一步加固建议</h2>
        <div class="section">
            <table>
                <tr><th>措施</th><th>说明</th><th>安全性</th></tr>
                <tr><td>关闭密码认证</td><td>关闭所有密码登录方式</td><td>⭐⭐⭐⭐⭐</td></tr>
                <tr><td>更换 SSH 端口</td><td>将默认的 22 端口改为其他端口</td><td>⭐⭐</td></tr>
                <tr><td>限制登录 IP</td><td>通过防火墙或安全组只允许特定 IP 登录</td><td>⭐⭐⭐⭐⭐</td></tr>
                <tr><td>禁止 root 登录</td><td>不允许直接用 root 登录</td><td>⭐⭐⭐</td></tr>
                <tr><td>启用 fail2ban</td><td>自动封禁多次登录失败的 IP</td><td>⭐⭐⭐⭐</td></tr>
                <tr><td>使用密钥密码</td><td>给私钥再设置一层密码保护</td><td>⭐⭐⭐</td></tr>
            </table>
        </div>

        <h2>📋 完整配置清单</h2>
        <div class="section">
            <p>以下是本次事件后的完整修复步骤：</p>
            <pre><code># 1. 本地生成密钥
ssh-keygen -t ed25519 -C "elliot@vps"

# 2. 上传公钥到服务器
ssh-copy-id -i ~/.ssh/id_ed25519.pub elliot@server_ip

# 3. 服务器端修改配置
sudo vim /etc/ssh/sshd_config
# 修改：PasswordAuthentication no

# 4. 验证并重载
sudo sshd -t
sudo systemctl reload ssh

# 5. 本地配置简化登录
vim ~/.ssh/config</code></pre>
        </div>

        <h2>🔍 入侵排查：如何判断服务器是否被入侵？</h2>
        <div class="section">
            <p>如果你的服务器曾经暴露在公网，以下命令可以帮助排查：</p>
            <pre><code># 查看成功登录记录（非本机 IP）
last | grep -v "139.226\|139.227\|你的正常IP段"

# 查看失败登录记录
sudo lastb | head -50

# 查看 auth.log 中的可疑登录
grep "Accepted" /var/log/auth.log

# 检查是否有新增用户
cat /etc/passwd | grep -v "^_" | grep "sh$"

# 检查可疑的定时任务
sudo crontab -l
sudo cat /var/spool/cron/crontabs/root</code></pre>
        </div>

        <h2>💡 总结</h2>
        <div class="section">
            <p>SSH 密钥认证是云服务器最基本也是最重要的安全措施之一。相比密码登录，密钥认证不仅更安全，而且使用更便捷。</p>
            <p>本次事件虽然虚惊一场，但提醒我们：安全无小事。趁着还没有造成实质损失，赶紧把密码登录关掉吧。</p>
            <p>最后，祝大家的服务器都平平安安，永不被黑！🛡️</p>
        </div>