SSH 完整工作流程:从安装、密钥认证到 Config、隧道与排错
SSH 用久了很容易只记住一句 ssh user@ip,真正遇到密钥、跳板机、端口转发、VS Code 或 Permission denied 时又开始逐个搜索。
这篇文章不只给命令,而是把 SSH 当成一条完整链路来理解:
客户端 OpenSSH
│
├── 读取 ~/.ssh/config
├── 校验服务器 Host Key
├── 使用密码 / 用户私钥认证
│
▼
网络:IP / 域名 / 端口 / NAT / 防火墙 / 跳板机
│
▼
服务端 sshd
├── Host Key:证明“服务器是谁”
├── authorized_keys:决定“谁能登录”
└── Shell / SFTP / 端口转发
如果这几个层次分清楚,大部分 SSH 问题都能按层定位,而不是靠反复改配置碰运气。
本文以 Windows 11 作为常见客户端、Ubuntu/Debian 作为常见服务器,同时给出 Linux/macOS 客户端命令。命令中的 IP、域名、用户名和端口均为示例,请替换为自己的实际值。
一、先弄清 SSH 里到底有哪些东西
OpenSSH 常见命令可以先记成下面这张表:
| 命令 | 作用 |
|---|---|
ssh |
登录远程主机、执行远程命令、建立隧道 |
sshd |
SSH 服务端守护进程 |
ssh-keygen |
生成和管理用户密钥、Host Key、指纹 |
ssh-agent |
在本机内存中管理已解锁的私钥 |
ssh-add |
把私钥加入 ssh-agent |
ssh-keyscan |
获取远程主机公开的 Host Key |
scp |
通过 SSH/SFTP 复制文件 |
sftp |
通过 SSH 进行交互式文件传输 |
还要区分三类经常被混淆的文件:
客户端用户私钥:~/.ssh/id_ed25519_xxx
客户端用户公钥:~/.ssh/id_ed25519_xxx.pub
服务端授权列表:~/.ssh/authorized_keys
客户端主机记录:~/.ssh/known_hosts
服务端 Host Key:/etc/ssh/ssh_host_*_key
最重要的一条:用户私钥永远留在可信客户端,不需要上传到服务器。
二、确认客户端是否已经有 OpenSSH
Windows 11
PowerShell:
ssh -V
where.exe ssh
Windows 10 1809 及之后的 Windows 可以把 OpenSSH Client/Server 作为系统可选功能安装。大多数 Windows 11 机器已经具备客户端;如果 ssh 不存在,可在“设置 → 系统 → 可选功能”中安装 OpenSSH Client。
也可以用管理员 PowerShell 查看状态:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
Linux / macOS
ssh -V
command -v ssh
Ubuntu/Debian 如未安装客户端:
sudo apt update
sudo apt install -y openssh-client
macOS 通常已自带 OpenSSH 客户端。
三、在 Linux 服务器安装并启动 sshd
Ubuntu/Debian:
sudo apt update
sudo apt install -y openssh-server
sudo systemctl enable --now ssh
检查服务:
systemctl status ssh --no-pager
ss -lntp | grep ':22'
RHEL / Rocky / AlmaLinux / Fedora 常见写法:
sudo dnf install -y openssh-server
sudo systemctl enable --now sshd
systemctl status sshd --no-pager
此时最基础的连接形式是:
ssh user@192.0.2.10
如果 SSH 不在 22 端口:
ssh -p 2222 user@192.0.2.10
云服务器还要同时检查云厂商的安全组/防火墙规则。sshd 正在监听,并不代表公网一定能访问到它。
四、第一次连接最容易忽略的 Host Key
第一次连接新服务器时通常会看到:
The authenticity of host 'server.example.com' can't be established.
ED25519 key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no/[fingerprint])?
这里验证的是服务器身份,不是你的用户登录密钥。
最好先通过云厂商控制台、服务器本地终端或其他可信通道查看服务端 Ed25519 Host Key 指纹:
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
确认客户端看到的 SHA256:... 与服务器一致,再输入:
yes
记录随后会写入客户端:
~/.ssh/known_hosts
以后同一主机的 Host Key 突然发生变化,SSH 会主动警告。这可能只是系统重装或容器重建,也可能意味着 DNS/IP 指向异常或中间人攻击,所以不要一看到报错就无脑删除 known_hosts。
确认服务器确实重建并核对新指纹后,才清理旧记录:
ssh-keygen -R server.example.com
非 22 端口的记录有时需要写成:
ssh-keygen -R '[server.example.com]:2222'
五、生成一把专用用户密钥
现在开始解决“客户端如何证明自己有权登录服务器”。
对现代 OpenSSH 环境,个人服务器一般优先使用 Ed25519:
Windows PowerShell
ssh-keygen -t ed25519 -f "$env:USERPROFILE\.ssh\id_ed25519_lab" -C "windows-lab"
Linux / macOS
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_lab -C "laptop-lab"
会生成:
id_ed25519_lab # 私钥:只能留在可信客户端
id_ed25519_lab.pub # 公钥:可以放到服务器
建议给私钥设置一个口令(passphrase),而不是为了所谓“免密登录”直接留空。真正方便的做法是:
私钥有口令
+
ssh-agent 记住已解锁私钥
=
日常连接不反复输入,同时私钥文件泄露后的风险更低
RSA 仍然有兼容性用途。如果必须连接老设备,可按设备支持情况另建 RSA 密钥,而不是把一个老 RSA 私钥复用到所有服务器。
六、把公钥安装到服务器
Linux/macOS 客户端最方便的是:
ssh-copy-id -i ~/.ssh/id_ed25519_lab.pub user@server.example.com
如果端口不是 22:
ssh-copy-id -i ~/.ssh/id_ed25519_lab.pub -p 2222 user@server.example.com
Windows 默认没有 ssh-copy-id,可以先查看公钥:
Get-Content "$env:USERPROFILE\.ssh\id_ed25519_lab.pub"
然后通过云控制台或现有密码登录,把这一整行公钥追加到服务器:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
也可以在已经能够密码登录的 Unix 服务器上,从 Windows PowerShell 直接管道追加:
Get-Content "$env:USERPROFILE\.ssh\id_ed25519_lab.pub" | ssh user@server.example.com "umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys"
完成后先新开一个终端测试密钥登录,原来的服务器会话暂时不要关闭:
ssh -i "$env:USERPROFILE\.ssh\id_ed25519_lab" user@server.example.com
只有这个新会话确认能正常登录后,再考虑关闭服务端密码认证。这样即使配置写错,也不至于立刻把自己锁在服务器外面。
七、用 ssh-agent 管理有口令的私钥
Windows 11
Windows 的 ssh-agent 服务默认可能没有启动。先用管理员 PowerShell执行:
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
Get-Service ssh-agent
然后回到普通 PowerShell 加载私钥:
ssh-add "$env:USERPROFILE\.ssh\id_ed25519_lab"
ssh-add -l
第一次执行 ssh-add 时输入私钥口令。后续 ssh 可以让 agent 代为完成签名,不必每次重新输入。
删除某一把密钥:
ssh-add -d "$env:USERPROFILE\.ssh\id_ed25519_lab"
清空 agent:
ssh-add -D
Linux / macOS
很多桌面环境已经自动管理 agent。手动启动时可以:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_lab
ssh-add -l
不要把“私钥没有口令”当成 ssh-agent 的替代品。两者解决的是不同问题:前者取消私钥本地保护,后者是在可信会话中暂存已解锁密钥。
八、真正应该长期使用的是 ~/.ssh/config
命令越来越长时,不要每天这样连:
ssh -p 2222 -i C:\Users\me\.ssh\id_ed25519_lab ubuntu@203.0.113.10
编辑客户端配置:
Windows:
C:\Users\你的用户名\.ssh\config
Linux/macOS:
~/.ssh/config
写入:
Host lab
HostName 203.0.113.10
User ubuntu
Port 2222
IdentityFile ~/.ssh/id_ed25519_lab
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
以后只需要:
ssh lab
几个关键字段:
| 配置 | 含义 |
|---|---|
Host |
本地别名,不必是真实域名 |
HostName |
真正连接的 IP 或域名 |
User |
远端用户名 |
Port |
SSH 服务端口 |
IdentityFile |
指定用户私钥 |
IdentitiesOnly yes |
只尝试显式配置的身份,避免 agent 中密钥太多 |
ServerAliveInterval |
定期发送 SSH 层保活消息 |
ServerAliveCountMax |
连续多少次无响应后断开 |
OpenSSH 客户端读取配置时,命令行参数优先于用户 ~/.ssh/config,用户配置又优先于系统配置;同一参数通常使用最先得到的值。因此更具体的 Host 一般写在前面,Host * 默认项放后面。
想知道最终到底应用了什么配置,不要靠猜:
ssh -G lab
Windows PowerShell 过滤关键项:
ssh -G lab | Select-String 'hostname|user|port|identityfile|proxyjump|proxycommand'
这个命令对排查“明明改了 config 为什么不生效”特别有用。
九、SSH 的常用连接方式
1. 交互式 Shell
ssh lab
2. 远程执行一条命令
ssh lab 'hostname; whoami; uptime'
3. 不分配伪终端
脚本或纯命令执行通常不需要 TTY:
ssh lab 'systemctl is-active nginx'
某些命令确实需要终端环境时,再显式使用:
ssh -t lab 'top'
十、文件传输:scp、sftp、rsync 怎么选
scp:一次性复制最方便
上传文件:
scp ./demo.zip lab:~/
下载文件:
scp lab:~/result.log ./
递归复制目录:
scp -r ./project lab:~/project
现代 OpenSSH 的 scp 默认使用 SFTP 协议传输,但命令行习惯仍然保留 scp 形式。
sftp:交互式管理远程文件
sftp lab
常用命令:
pwd 查看远程目录
lpwd 查看本地目录
ls 列远程文件
lls 列本地文件
get file 下载
put file 上传
mkdir dir 创建远程目录
exit 退出
rsync:大量文件和增量同步更适合
Linux/macOS 或 WSL 中,如果两端都有 rsync:
rsync -azP ./project/ lab:~/project/
rsync 更适合经常同步代码、数据集或备份,不需要每次把整个目录重传。
十一、VS Code Remote - SSH
如果命令行已经可以:
ssh lab
那么 VS Code Remote - SSH 通常不需要再维护另一套服务器参数,它直接读取 OpenSSH 的 ~/.ssh/config。
安装微软的 Remote - SSH 扩展后:
F1 / Ctrl+Shift+P
→ Remote-SSH: Connect to Host...
→ lab
如果 VS Code 失败,第一步仍然应该回到终端执行:
ssh -vvv lab
先证明底层 OpenSSH 能连接,再处理 VS Code 自己的 Server 安装、代理或远端环境问题。
十二、服务端安全加固:先验证密钥,再关闭密码
Ubuntu 支持直接编辑:
/etc/ssh/sshd_config
也支持使用:
/etc/ssh/sshd_config.d/*.conf
如果系统已经通过 cloud-init、镜像厂商或其他配置片段设置过同一选项,要先检查实际加载顺序。OpenSSH 对大量配置项采用“先得到的值生效”的规则,因此不要想当然地认为文件名 99-xxx.conf 一定能覆盖前面的设置。
先看配置语法:
sudo sshd -t
再查看最终有效配置:
sudo sshd -T | grep -Ei 'passwordauthentication|pubkeyauthentication|permitrootlogin|port|listenaddress'
确认公钥登录已经成功后,常见的安全基线可以是:
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
如果业务根本不需要 root 直接 SSH,进一步使用:
PermitRootLogin no
修改后不要直接关闭当前 SSH 会话。先检查:
sudo sshd -t
无输出通常表示语法通过,然后重载/重启:
Ubuntu/Debian:
sudo systemctl restart ssh
RHEL 系:
sudo systemctl restart sshd
保持旧会话不动,再从另一个终端执行:
ssh lab
只有新连接也成功,才算本轮配置真正安全落地。
十三、本地端口转发:访问“只在远端本机开放”的服务
假设远端 PostgreSQL 只监听:
127.0.0.1:5432
本地执行:
ssh -N -L 127.0.0.1:15432:127.0.0.1:5432 lab
链路是:
本机 127.0.0.1:15432
│
│ SSH 加密连接
▼
远端 SSH Server
│
▼
远端 127.0.0.1:5432
之后本地数据库客户端直接连接:
127.0.0.1:15432
这里显式绑定 127.0.0.1,避免把转发端口意外暴露给局域网其他设备。
更适合长期使用的 config:
Host lab-db
HostName 203.0.113.10
User ubuntu
IdentityFile ~/.ssh/id_ed25519_lab
LocalForward 127.0.0.1:15432 127.0.0.1:5432
ExitOnForwardFailure yes
只建立隧道、不打开 Shell:
ssh -N lab-db
十四、远程端口转发:把“本地服务”送到远端
假设你的本机运行开发服务:
127.0.0.1:3000
希望远端服务器自己的 127.0.0.1:8080 能访问它:
ssh -N -R 127.0.0.1:8080:127.0.0.1:3000 lab
链路是:
远端 127.0.0.1:8080 → SSH → 本机 127.0.0.1:3000
如果想让远端其他机器也访问这个反向端口,会涉及 GatewayPorts、监听地址以及服务端防火墙,暴露范围明显扩大。除非明确知道自己在做什么,否则优先保持 127.0.0.1。
十五、动态转发:把 SSH 当 SOCKS 代理
本地建立 SOCKS5 代理:
ssh -N -D 127.0.0.1:1080 lab
然后把支持 SOCKS5 的应用指向:
127.0.0.1:1080
应用的 TCP 流量会经过 SSH 到远端,再由远端访问目标地址。
这适合临时调试、访问远端网络中的 Web 服务等场景,但它不是 VPN,也不会自动接管系统全部流量。
十六、跳板机 ProxyJump:访问内网服务器
典型结构:
本机
│
▼
bastion.example.com 公网跳板机
│
▼
10.0.0.20 内网服务器
命令行可以直接:
ssh -J bastion.example.com user@10.0.0.20
更推荐写进 config:
Host bastion
HostName bastion.example.com
User ubuntu
IdentityFile ~/.ssh/id_ed25519_bastion
IdentitiesOnly yes
Host internal
HostName 10.0.0.20
User dev
IdentityFile ~/.ssh/id_ed25519_internal
IdentitiesOnly yes
ProxyJump bastion
以后:
ssh internal
scp ./file internal:~/
VS Code Remote - SSH 也可以直接使用 internal。
不要为了跳板机默认开启 Agent Forwarding
ProxyJump 并不等于 ForwardAgent yes。通常客户端可以通过跳板机建立传输通道,然后直接向目标服务器完成认证,不需要把本地 agent 暴露给跳板机。
所以不要在全局配置里随手写:
Host *
ForwardAgent yes
只有确实需要并且信任中间主机时,再对具体主机启用 agent forwarding。
十七、ProxyCommand:SSH 不一定要直接连目标端口
很多特殊网络方案会让 ssh.exe 把底层字节流交给另一个程序,例如 Cloudflare Access、HTTP CONNECT 代理或其他隧道客户端。
典型结构:
Host tunnel-host
HostName ssh.example.com
User root
IdentityFile ~/.ssh/id_ed25519_tunnel
IdentitiesOnly yes
ProxyCommand cloudflared access ssh --hostname %h
这时 SSH 的认证、Host Key、scp、sftp 等上层逻辑仍然由 OpenSSH 处理,只是“怎么到达远端 sshd”改成了 ProxyCommand。
因此排错时必须把问题区分成:
ProxyCommand 是否能建链
↓
能否看到 SSH Banner / 完成握手
↓
Host Key 是否通过
↓
用户公钥认证是否通过
不要把“网络隧道已经连通”和“SSH 用户已经认证成功”当成同一件事。
十八、系统化排错:先确定失败在哪一层
SSH 最有价值的排错命令是:
ssh -vvv lab
调试时建议按下面顺序判断。
1. 客户端配置有没有读对
ssh -G lab
重点看:
hostname
user
port
identityfile
proxyjump
proxycommand
2. DNS/IP/端口能不能到达
Windows PowerShell:
Resolve-DnsName server.example.com
Test-NetConnection server.example.com -Port 22
Linux/macOS:
getent hosts server.example.com 2>/dev/null || nslookup server.example.com
nc -vz server.example.com 22
如果这里就是超时,先查路由、安全组、防火墙、NAT、端口映射或代理,不要先折腾用户密钥。
3. 服务端 sshd 是否真的在监听
服务器控制台:
systemctl status ssh --no-pager 2>/dev/null || systemctl status sshd --no-pager
ss -lntp | grep -E ':22|:2222'
sudo sshd -t
Ubuntu 日志:
sudo journalctl -u ssh -n 100 --no-pager
RHEL 系常用:
sudo journalctl -u sshd -n 100 --no-pager
4. 已握手,但出现 Permission denied (publickey)
这说明网络和 SSH 协议层通常已经通了,重点查用户认证:
whoami
ls -ld ~ ~/.ssh
ls -l ~/.ssh/authorized_keys
常见 Unix 权限:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
客户端确认自己到底在试哪把密钥:
ssh -vvv lab
或者直接强制:
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_lab user@server.example.com
5. Too many authentication failures
这通常不是“密码输错太多”,而是本地 agent 里装了很多密钥,服务器在正确密钥出现前已经达到认证尝试上限。
解决:
Host lab
IdentityFile ~/.ssh/id_ed25519_lab
IdentitiesOnly yes
6. Connection refused
通常表示已经到达目标主机,但目标端口没有服务监听,常见原因:
sshd没启动;- 端口写错;
- sshd 只监听了其他地址;
- 防火墙明确拒绝连接。
7. Connection timed out
更偏向网络路径问题:
- 公网 IP/域名错误;
- 云安全组没有放行;
- 路由器没有端口映射;
- NAT 后主机不可直接入站;
- 出入口防火墙丢弃数据包;
- 网络封锁了目标端口。
8. REMOTE HOST IDENTIFICATION HAS CHANGED
先问自己:服务器是否刚重装、容器是否重建、IP 是否重新分配、域名是否改了后端?
在服务端可信控制台重新查看指纹:
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
确认变化合理后再删除客户端旧记录:
ssh-keygen -R server.example.com
然后重新连接并核对新指纹。
9. SSH 连几分钟就断
先区分是 NAT/防火墙空闲超时,还是远端服务主动断开。
客户端可以配置:
Host lab
ServerAliveInterval 30
ServerAliveCountMax 3
这里是 SSH 协议层保活,不等于 TCPKeepAlive,也不是让失联服务器“永不掉线”。
十九、Windows 也可以作为 SSH Server
Windows 11/Windows Server 可以安装 OpenSSH Server。管理员 PowerShell 先查看:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
如未安装:
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
启动并设为自动:
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
Get-Service sshd
Windows OpenSSH Server 的主配置通常位于:
C:\ProgramData\ssh\sshd_config
Host Key 也保存在 C:\ProgramData\ssh。Windows 的 authorized_keys 与 ACL 规则和 Unix 不完全相同,尤其管理员账户默认配置可能使用:
C:\ProgramData\ssh\administrators_authorized_keys
因此把 Windows 当服务端时,建议按 Microsoft 当前 OpenSSH 文档处理 ACL,不要直接照抄 Linux 的 chmod 600 思路。
另外确认 Windows 防火墙存在 OpenSSH Server 的 TCP/22 入站规则。如果服务器需要经过公网访问,还要继续检查上游 NAT、云安全组或路由器端口映射。
二十、一套推荐的日常 SSH 配置
下面是个人电脑管理多台 Linux 服务器时比较稳妥的起点:
Host lab
HostName 203.0.113.10
User ubuntu
Port 22
IdentityFile ~/.ssh/id_ed25519_lab
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
Host bastion
HostName bastion.example.com
User ubuntu
IdentityFile ~/.ssh/id_ed25519_bastion
IdentitiesOnly yes
Host internal
HostName 10.0.0.20
User dev
IdentityFile ~/.ssh/id_ed25519_internal
IdentitiesOnly yes
ProxyJump bastion
Host *
HashKnownHosts yes
这里没有默认开启 ForwardAgent,也没有关闭 Host Key 检查,更没有把所有主机强行绑定到同一把私钥。
二十一、从零到稳定使用的完整操作顺序
第一次配置一台新服务器,可以直接照下面顺序走:
1. 客户端确认 ssh -V
2. 服务端安装并启动 openssh-server
3. 确认 sshd 监听地址和端口
4. 确认网络/安全组/防火墙可达
5. 第一次连接时核对服务器 Host Key 指纹
6. 为这台服务器生成独立 Ed25519 用户密钥
7. 给私钥设置 passphrase
8. 把 .pub 公钥加入远端 authorized_keys
9. 新开终端验证公钥登录
10. 配置 ssh-agent
11. 把长命令整理进 ~/.ssh/config
12. 用 ssh -G 检查最终客户端配置
13. 确认密钥登录稳定后,再关闭服务端密码认证
14. 服务端每次改配置先 sshd -t
15. 保留旧连接,新开第二个连接验证
16. VS Code/scp/sftp 全部复用同一个 Host 别名
17. 需要访问内网时使用 ProxyJump
18. 需要访问远端本地服务时使用 -L
19. 需要反向暴露本地服务时谨慎使用 -R
20. 需要 SOCKS 代理时使用 -D
21. 出错先 ssh -vvv,再按网络→握手→Host Key→用户认证分层定位
这比“能连上就算配置完成”更接近一套长期可维护的 SSH 工作流。
二十二、不要做的几件事
- 不要上传用户私钥到服务器。 服务器只需要你的公钥。
- 不要为了免输密码就默认创建无口令私钥。 优先使用 passphrase + ssh-agent。
- 不要第一次连接任何服务器都无脑输入
yes。 至少对重要机器核对 Host Key 指纹。 - 不要在公钥登录还没验证时先关闭密码认证。 这是最常见的自锁服务器方式之一。
- 不要全局
ForwardAgent yes。 只在确有需要的可信主机上使用。 - 不要全局关闭
StrictHostKeyChecking。 这样等于主动放弃服务器身份校验的重要防线。 - 不要把端口转发默认绑定
0.0.0.0。 本机使用时优先显式绑定127.0.0.1。 - 不要把
Connection timed out当成密钥问题。 连 TCP 都没建立时,用户密钥根本还没有登场。 - 不要看到 Host Key changed 就直接
ssh-keygen -R。 先确认服务器为什么变了。 - 不要一把长期私钥打天下。 重要设备、服务器或用途分开建密钥,撤销时更干净。
二十三、常用命令速查
| 需求 | 命令 |
|---|---|
| 普通登录 | ssh lab |
| 指定端口 | ssh -p 2222 user@host |
| 指定私钥 | ssh -i ~/.ssh/id_ed25519_lab user@host |
| 查看最终配置 | ssh -G lab |
| 详细调试 | ssh -vvv lab |
| 执行远程命令 | ssh lab 'hostname; uptime' |
| 生成 Ed25519 密钥 | ssh-keygen -t ed25519 |
| 查看公钥指纹 | ssh-keygen -lf key.pub |
| 从 known_hosts 删除旧记录 | ssh-keygen -R host |
| 查看 agent 密钥 | ssh-add -l |
| 上传文件 | scp file lab:~/ |
| 下载文件 | scp lab:~/file ./ |
| SFTP | sftp lab |
| 本地转发 | ssh -N -L 127.0.0.1:15432:127.0.0.1:5432 lab |
| 远程转发 | ssh -N -R 127.0.0.1:8080:127.0.0.1:3000 lab |
| SOCKS5 动态转发 | ssh -N -D 127.0.0.1:1080 lab |
| 跳板机 | ssh -J bastion target |
| 检查服务端配置语法 | sudo sshd -t |
| 查看服务端有效配置 | sudo sshd -T |
二十四、官方资料与版本边界
本文于 2026-08-09 按当前 OpenSSH、Ubuntu 与 Microsoft 官方资料重新核对。OpenSSH 的具体默认算法、Windows 可选功能状态以及发行版默认配置都可能随着版本变化,因此涉及安全策略或默认值时,优先查看当前系统自己的 ssh -V、ssh -G、sshd -T 和官方文档。
- OpenSSH ssh(1) 手册
- OpenSSH ssh_config(5) 手册
- OpenSSH sshd_config(5) 手册
- OpenSSH ssh-keygen(1) 手册
- Ubuntu OpenSSH Server 官方文档
- Microsoft:OpenSSH for Windows 概述
- Microsoft:OpenSSH 密钥管理
- Microsoft:开始使用 OpenSSH Server
总结
一套可靠的 SSH 工作流,核心不是记住更多命令,而是始终知道当前在处理哪一层:
网络可达性
↓
SSH 协议握手
↓
服务器 Host Key 身份校验
↓
用户认证(私钥 / 公钥)
↓
Shell、文件传输、VS Code、端口转发与跳板机
日常使用时,把主机参数统一收进 ~/.ssh/config,用独立密钥配合 ssh-agent,重要主机认真核对 Host Key;服务端先验证公钥登录,再关闭密码认证。出现故障时从 ssh -G 和 ssh -vvv 开始,按网络、握手、主机身份、用户认证逐层排查。
掌握这条主线以后,scp、SFTP、VS Code Remote - SSH、ProxyJump、ProxyCommand、Cloudflare Tunnel 以及 -L/-R/-D 端口转发,本质上都只是同一套 OpenSSH 工作流在不同网络场景下的扩展。