SSH 连接 — Windows 11 到服务器 从零搭建指南
定位:Windows 11 环境通过 SSH 连接远程 Linux 服务器的完整步骤。适用场景:部署代码、执行远程命令、管理服务。
前置条件
| 项目 | 说明 |
|---|---|
| 操作系统 | Windows 11(已预装 OpenSSH 客户端) |
| 服务器 | CentOS / Ubuntu / Debian 等 Linux |
| 账户 | 服务器有 root 或普通用户账号及密码 |
| 网络 | 服务器 22 端口已开放(防火墙/安全组) |
一、检查本地 SSH 环境
Windows 11 自带 OpenSSH 客户端,无需额外安装。
# 验证 SSH 命令是否可用
ssh -V
期望输出类似:OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2
可以在 CMD、PowerShell 或 Git Bash 中执行上述命令。本文推荐的终端是 Git Bash(与 Linux 命令一致),也可用 PowerShell。
二、生成密钥对(推荐 ed25519)
密钥策略:按项目/服务器独立生成,不建议共用
| 策略 | 说明 | 推荐度 |
|---|---|---|
| 每项目独立密钥 ✅ | 每个项目/服务器生成单独的密钥对,各自命名 | 强烈推荐 |
| 全局共用一把密钥 | 所有服务器使用同一对密钥 | 不推荐 |
推荐独立密钥的原因:
- 隔离风险:某台服务器被入侵,只需吊销该服务器的公钥,不影响其他服务器
- 权限管理:为特定项目配置密钥时可以精准控制,无需担心"有密钥的人能访问所有服务器"
- 审计追溯:通过公钥注释(
-C参数)能一眼看出密钥用途 - 轮换灵活:单个项目升级或废弃时单独更换密钥,不影响其他项目
命名约定
~/.ssh/id_ed25519_{项目名或服务器别名}
示例:
| 项目 | 生成命令 |
|---|---|
| broker 项目 | ssh-keygen -t ed25519 -C "broker-server" -f ~/.ssh/id_ed25519_broker |
| news 项目 | ssh-keygen -t ed25519 -C "news-server" -f ~/.ssh/id_ed25519_news |
| 临时测试机 | ssh-keygen -t ed25519 -C "test-server" -f ~/.ssh/id_ed25519_test |
具体步骤
# 以 broker 项目为例
ssh-keygen -t ed25519 -C "broker-server" -f ~/.ssh/id_ed25519_broker
参数说明:
- -t ed25519 — 密钥类型,比 RSA 更安全且速度更快
- -C "broker-server" — 注释标记,标注此密钥的用途,方便日后识别
- -f ~/.ssh/id_ed25519_broker — 密钥文件存放路径,按项目名命名不冲突
执行后交互:
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase): ← 直接回车(不设密码)
Enter same passphrase again: ← 直接回车
不设 passphrase,否则每次连接都要输入密码,无法实现自动化。
生成后的文件:
| 文件 | 说明 | 安全要求 |
|------|------|----------|
| ~/.ssh/id_ed25519_broker | 私钥,保存在本地 | 绝对不可泄露 |
| ~/.ssh/id_ed25519_broker.pub | 公钥,上传到服务器 | 可公开 |
常见疑问:一台电脑最多能管理多少把密钥?没有限制。Config 文件通过
IdentityFile指定具体用哪把,连接时不会混淆。
三、上传公钥到服务器
3.1 打印公钥内容
cat ~/.ssh/id_ed25519_server.pub
输出类似:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... my-server
复制这整行内容(含 ssh-ed25519 开头到末尾)。
3.2 上传到服务器(方式一:ssh-copy-id)
若服务器已允许密码登录,一行命令完成上传:
ssh-copy-id -i ~/.ssh/id_ed25519_server.pub root@服务器IP
输入服务器密码后,公钥自动追加到服务器的 ~/.ssh/authorized_keys。
注意:Windows 11 可能不预装
ssh-copy-id。如果提示命令不存在,使用方法二。
3.3 上传到服务器(方式二:手动写入)
先用密码登录服务器:
ssh root@服务器IP
在服务器上执行:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... my-server" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit
把
echo后面的公钥内容替换为你第 3.1 步复制的值。
3.4 上传到服务器(方式三:paramiko — 适合需要程序化操作时)
如果 Windows 环境下有 Python,可通过 paramiko 在无 ssh-copy-id 的情况下写入:
python -c "
import paramiko
pubkey = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... my-server'
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect('服务器IP', username='root', password='你的密码', timeout=15)
c.exec_command('mkdir -p ~/.ssh && chmod 700 ~/.ssh')
c.exec_command('printf \"%s\\n\" \"{}\" >> ~/.ssh/authorized_keys'.format(pubkey))
c.exec_command('chmod 600 ~/.ssh/authorized_keys')
c.exec_command('sort -u ~/.ssh/authorized_keys -o ~/.ssh/authorized_keys')
c.close()
print('公钥上传完成')
"
需要安装 paramiko:
pip install paramiko
四、创建 SSH Config 文件(别名配置)
配置别名后,ssh my-server 即可连接,无需记忆 IP 和用户名。
创建(或编辑)~/.ssh/config 文件:
Host my-server
HostName 服务器IP
User root
IdentityFile ~/.ssh/id_ed25519_server
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
字段说明:
| 字段 | 值 | 作用 |
|---|---|---|
Host |
自定义别名 | 连接时用 ssh 别名 |
HostName |
服务器IP或域名 | 目标服务器地址 |
User |
root 或普通用户 | 登录用户名 |
IdentityFile |
~/.ssh/id_ed25519_server |
指定私钥文件 |
IdentitiesOnly |
yes |
只使用指定密钥,不自动尝试其他密钥 |
ServerAliveInterval |
30 |
每 30 秒发心跳包,防连接断开 |
ServerAliveCountMax |
3 |
连续 3 次心跳无响应断开连接 |
Windows 避坑:不要添加
ControlMaster/ControlPath。Git Bash 的 OpenSSH 对 Unix socket 支持不完整,可能导致mux_client_request_session: read from master failed错误。
五、测试连接
ssh my-server "echo '连接成功' && hostname && uptime"
预期输出(无需输入密码):
连接成功
服务器主机名
12:34:56 up 10 days, 3:21, ...
如果仍然提示输入密码,检查:
1. 公钥是否已正确写入服务器的 ~/.ssh/authorized_keys
2. 服务器的 sshd 配置是否启用了密钥认证
# 在服务器上检查 sshd 配置
grep PubkeyAuthentication /etc/ssh/sshd_config
# 应输出:PubkeyAuthentication yes
六、日常使用方式
| 场景 | 命令 |
|---|---|
| 单条命令 | ssh my-server "命令" |
| 多条命令 | ssh my-server "cd /path && git pull && systemctl restart xxx" |
| 交互式登录 | ssh my-server |
| 端口转发(本地→远程) | ssh -L 3307:localhost:3306 my-server |
| 端口转发(远程→本地) | ssh -R 8080:localhost:8080 my-server |
| 文件上传 | scp local.file my-server:/remote/path/ |
| 文件下载 | scp my-server:/remote/file ./local/ |
七、常见问题
7.1 连接超时
ssh: connect to host 服务器IP port 22: Connection timed out
排查步骤:
1. 检查服务器安全组/防火墙是否放行了 22 端口
2. 检查服务器是否运行了 SSH 服务:systemctl status sshd
3. 从其他设备尝试连接,确认是否是本地网络问题
7.2 Host key verification failed
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
原因:服务器重装后主机密钥变化,与本地 known_hosts 记录的指纹不一致。
解决:清除旧的服务器指纹
ssh-keygen -R 服务器IP
7.3 Permission denied (publickey)
原因:密钥认证失败。
排查步骤:
1. 确认 ~/.ssh/authorized_keys 权限为 600,~/.ssh 权限为 700
2. 确认公钥内容完整写入(无折行、无多余空格)
3. 启动详细日志模式排查
ssh -vvv my-server
7.4 Windows 特有的问题
| 问题 | 原因 | 解决 |
|---|---|---|
sshpass 不存在 |
Git Bash 不含此工具 | 改用 SSH Key 或 paramiko |
ControlMaster 报错 |
Windows OpenSSH 不支持 Unix socket | 从 config 中删除 ControlMaster / ControlPath |
| 中文乱码 | 服务器编码与终端不一致 | ssh my-server "LANG=zh_CN.UTF-8 命令" 或修改终端编码 |
| 连接间歇断开 | 网络不稳定 | 配置 ServerAliveInterval 30 |
八、安全注意事项
- 私钥绝不外传:
~/.ssh/id_ed25519_server是证明身份的凭据,不要提交到 Git、发送给他人、存放在公开位置 - 禁用密码登录(可选但在生产环境推荐):配置密钥认证确认可用后,在服务器上
PasswordAuthentication no - 使用非 root 用户:日常操作使用普通用户 + sudo,减少风险
- 定期轮换密钥:更换服务器或怀疑泄露时,重新生成密钥并更新
authorized_keys