SSH 远程管理
第一节 SSH 简介
1.1 什么是 SSH
SSH 为 Secure Shell 的缩写,是一种用于远程登录和文件传输的加密协议 。它工作在应用层 ,基于传输层 TCP(默认 22 端口)。
只要记住一句:SSH 把"明文传输的 telnet"变成了"加密传输"。
1.2 基础信息
| 项目 | 内容 |
|---|---|
| 默认端口 | 22 |
| Linux 守护进程 | sshd |
| 安装服务 | OpenSSH |
| 服务端主程序 | /usr/sbin/sshd |
| 客户端主程序 | /usr/bin/ssh |
| 服务端配置 | /etc/ssh/sshd_config |
| 客户端配置 | /etc/ssh/ssh_config |
bash
# 确认是否安装
rpm -qa | grep openssh
dnf install -y openssh-server openssh-clients
# 确认服务状态
systemctl status sshd
ss -lntp | grep :22
第二节 SSH 原理
2.1 对称加密
采用单钥密码系统,同一个密钥既用于加密也用于解密。
- 优点:快,适合加密大量数据
- 缺点:密钥怎么安全地交给对方?这就是"密钥分发问题"
- 代表算法:AES、ChaCha20
2.2 非对称加密
又名"公开密钥加密算法",需要一对密钥:
- 公钥(public key):可以公开
- 私钥(private key):只有自己持有
核心特性:
text
公钥加密 → 只有私钥能解
私钥签名 → 只有公钥能验
- 优点:解决了密钥分发问题
- 缺点:慢,比对称加密慢几个数量级
- 代表算法:RSA、ECDSA、Ed25519
2.3 SSH 为什么两种都用(★ 核心)
很多人背了两种算法,却说不清 SSH 到底用哪种。答案是:两种都用,各管一段。
| 阶段 | 用什么 | 为什么 |
|---|---|---|
| 建立连接时 | 非对称加密 | 安全地协商出会话密钥,不需要提前共享密码 |
| 传输数据时 | 对称加密 | 速度快,适合大流量 |
一句话:
非对称负责"安全地把钥匙交给你",对称负责"拿到钥匙后高效地传数据"。
2.4 完整的连接建立过程
text
① TCP 三次握手,连上 22 端口
② 协议版本协商
客户端:SSH-2.0-OpenSSH_8.0
服务端:SSH-2.0-OpenSSH_8.7
③ 算法协商
双方各自列出支持的加密算法,选出一个都支持的
④ 密钥交换(KEX)
通过 Diffie-Hellman 算法,双方各自算出【同一个会话密钥】
★ 注意:这个密钥从来没有在网络上传输过
⑤ 服务端出示主机公钥
客户端校验:这个公钥和我记过的一致吗?(known_hosts)
★ 这一步防的是"中间人攻击"
⑥ 用户身份认证(二选一)
· 密码认证:在【已加密的通道】里传密码
· 公钥认证:客户端用私钥签名,服务端用公钥验签
⑦ 认证通过,建立会话
之后所有数据都用【对称加密】传输
2.5 两种用户认证方式
| 密码认证 | 公钥认证 | |
|---|---|---|
| 原理 | 把密码放进加密通道里传 | 客户端用私钥签名,服务端用公钥验签 |
| 私钥会传输吗 | --- | 不会,只传签名 |
| 安全性 | 中(可能被暴力破解) | 高 |
| 便利性 | 要输密码 | 免密登录 |
| 生产推荐 | 关掉 | 推荐 |
第三节 SSH 配置文件
3.1 服务端配置:/etc/ssh/sshd_config
| 参数 | 常见值 | 说明 |
|---|---|---|
Port |
22 |
监听端口 |
ListenAddress |
0.0.0.0 |
监听的 IP |
HostKey |
/etc/ssh/ssh_host_ed25519_key |
服务端主机私钥位置 |
LogLevel |
INFO |
日志等级 |
SyslogFacility |
AUTH |
日志记录 SSH 登录情况 |
GSSAPIAuthentication |
yes |
GSSAPI(Kerberos)认证 |
PermitRootLogin |
yes / no |
是否允许 root 直接登录 |
PubkeyAuthentication |
yes |
是否启用公钥认证 |
AuthorizedKeysFile |
.ssh/authorized_keys |
公钥保存位置(相对用户家目录) |
PasswordAuthentication |
yes / no |
是否允许密码认证 |
PermitEmptyPasswords |
no |
是否允许空密码 |
UsePAM |
yes |
是否使用 PAM 做认证/会话管理 |
MaxAuthTries |
6 |
最大认证尝试次数 |
关于 GSSAPIAuthentication(常见坑)
在没有 Kerberos/DNS 的实验环境里,这个选项会让登录卡好几秒。
bash
# 服务端
GSSAPIAuthentication no # /etc/ssh/sshd_config
# 客户端
GSSAPIAuthentication no # /etc/ssh/ssh_config
两个文件里都有这一项,两边都关掉才彻底不卡。
关于已过时的参数
| 旧参数 | 说明 |
|---|---|
Protocol 2 |
OpenSSH 7.6+ 已删除,不用再写 |
ServerKeyBits 1024 |
已移除,且 1024 位过弱 |
ssh_host_dsa_key |
DSA 在 7.0+ 默认禁用,用 ed25519 或 rsa |
改完配置必须重启服务:
bash
sshd -t # ★ 先检查语法,避免把自己锁在外面
systemctl restart sshd
3.2 客户端配置:/etc/ssh/ssh_config
客户端配置管的是"我怎么连别人",常见内容:
text
Host myserver
HostName 192.168.44.2
User root
Port 2222
IdentityFile ~/.ssh/id_ed25519
配好之后,直接 ssh myserver 就能连。
| 参数 | 作用 |
|---|---|
Host |
别名,供 ssh 别名 使用 |
HostName |
真实 IP 或域名 |
User |
默认登录用户名 |
Port |
默认端口 |
IdentityFile |
指定私钥文件 |
StrictHostKeyChecking |
是否严格校验主机公钥(实验环境可设 no,生产不要) |
ServerAliveInterval |
多少秒发一次心跳,防断线 |
TCPKeepAlive |
是否用 TCP 层保活 |
生产建议 :加
ServerAliveInterval 60,避免长时间不操作被防火墙断开。
3.3 认证相关文件一览
| 文件 | 位置 | 作用 |
|---|---|---|
| 私钥 | ~/.ssh/id_ed25519 |
自己的私钥,权限必须 600 |
| 公钥 | ~/.ssh/id_ed25519.pub |
自己的公钥,可以公开 |
| 授权公钥 | ~/.ssh/authorized_keys |
允许登录这台机器的公钥列表 |
| 已知主机 | ~/.ssh/known_hosts |
记录连过的主机公钥 |
| 服务端主机密钥 | /etc/ssh/ssh_host_* |
服务端身份,重装后会变 |
第四节 常用 SSH 命令
4.1 ssh 远程登录
bash
ssh 用户名@IP
ssh root@192.168.44.2
ssh -p 2222 root@192.168.44.2 # 指定端口
ssh -i ~/.ssh/id_ed25519 root@IP # 指定私钥
客户端是通用的:Windows(PowerShell/termius)、macOS 终端、Linux 都能用同样的命令连 Linux 服务器。
4.2 常用参数
| 参数 | 作用 |
|---|---|
-p |
指定端口 |
-i |
指定私钥文件 |
-v / -vv / -vvv |
调试模式,卡在哪一步一目了然 |
-o |
临时指定配置项,如 -o StrictHostKeyChecking=no |
-N |
不执行远程命令(只做转发) |
-f |
后台运行 |
-T |
不分配伪终端 |
-L / -R / -D |
端口转发 |
4.3 scp 文件传输
bash
# 下载:远程 → 本地
scp root@192.168.44.2:/root/test.txt .
scp -r root@192.168.44.2:/root/logs ./logs
# 上传:本地 → 远程
scp /root/123 root@192.168.44.2:/root/
scp -r /root/123 root@192.168.44.2:/root/
例子逐项拆解:
bash
scp -r localfile.txt username@192.168.0.1:/home/username/
| 部分 | 含义 |
|---|---|
scp |
命令 |
-r |
递归(传目录) |
localfile.txt |
本地文件路径 |
username |
服务器账号 |
192.168.0.1 |
服务器 IP |
/home/username/ |
目标目录 |
版本提醒 :OpenSSH 9.0 起,
scp默认改用 SFTP 协议传输。连很老的服务器如果报错,可以加-O强制用旧协议。
大文件建议用rsync:支持断点续传和增量同步,比scp更适合重复同步场景。
4.4 sftp 交互式传输
bash
sftp root@192.168.4.2
| 命令 | 作用 |
|---|---|
ls |
查看服务器端文件 |
cd |
切换服务器端目录 |
pwd |
显示服务器端当前目录 |
lls |
查看本地文件 |
lcd |
切换本地目录 |
get |
下载 |
put |
上传 |
mkdir / rm |
在服务器端建目录 / 删文件 |
bye / exit |
退出 |
记忆法:带
l前缀的是本地(local),不带的是远端。
4.5 免密登录(公钥认证)
第一步:生成密钥对
bash
ssh-keygen -t ed25519 -C "your_email@example.com"
# 一路回车即可,默认保存到 ~/.ssh/
第二步:把公钥传到目标机器
bash
ssh-copy-id root@192.168.44.2
# 或者手动:ssh root@IP "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" < ~/.ssh/id_ed25519.pub
第三步:验证
bash
ssh root@192.168.44.2 # 不再提示输入密码
★ 权限必须正确,否则免密一定失败
bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
| 路径 | 要求权限 |
|---|---|
~/.ssh |
700 |
~/.ssh/authorized_keys |
600 |
~/.ssh/id_*(私钥) |
600 |
| 用户家目录 | 不能对组或其他用户可写 |
报错
Authentication refused: bad ownership or modes就是这个原因。
4.6 known_hosts 与首次连接
第一次连接某台主机时,会看到:
text
The authenticity of host '192.168.44.2' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxx...
Are you sure you want to continue connecting (yes/no)?
输入 yes 后,对方的主机公钥会被写入 ~/.ssh/known_hosts。
重装系统或换机器后,会报这个错:
text
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
不是被攻击,而是主机密钥变了。清除旧记录:
bash
ssh-keygen -R 192.168.44.2
4.7 端口转发(运维高频)
| 类型 | 命令 | 场景 |
|---|---|---|
| 本地转发 | ssh -L 8080:127.0.0.1:80 user@跳板机 |
通过跳板访问内网服务 |
| 远程转发 | ssh -R 8080:127.0.0.1:80 user@公网机 |
把内网服务暴露到公网 |
| 动态转发 | ssh -D 1080 user@跳板机 |
建一个 SOCKS 代理 |
bash
# 本地转发:访问本机 8080,等于访问跳板机能看到的 127.0.0.1:80
ssh -N -f -L 8080:127.0.0.1:80 root@192.168.44.2
-N:不执行远程命令-f:后台运行
第五节 运维必备
5.1 服务管理
bash
systemctl status sshd
systemctl restart sshd
ss -lntp | grep :22
journalctl -u sshd -f
tail -f /var/log/secure # Rocky/CentOS 的 SSH 日志
5.2 修改端口的完整步骤(★ 最容易漏 SELinux)
bash
# 1) 改配置
vim /etc/ssh/sshd_config
Port 2222
# 2) 防火墙放行
firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --reload
# 3) SELinux 放行(Rocky/CentOS 必做!)
semanage port -a -t ssh_port_t -p tcp 2222
# 4) 检查语法再重启
sshd -t
systemctl restart sshd
# 5) 新开一个窗口验证,确认能连再关掉旧连接
ssh -p 2222 root@IP
semanage不是默认安装的 :dnf install -y policycoreutils-python-utils漏了这步的表现是:端口在监听、防火墙也放行了,就是连不上。
5.3 连接不上怎么排查
bash
# 客户端:看卡在哪一步
ssh -vvv root@192.168.44.2
# 服务端:服务在跑吗
systemctl status sshd
ss -lntp | grep sshd
# 服务端:日志说了什么
journalctl -u sshd --since "10 minutes ago"
tail -50 /var/log/secure
# 网络层排查
ping 192.168.44.2
nc -vz 192.168.44.2 22
| 现象 | 大概率原因 |
|---|---|
Connection refused |
sshd 没起 / 端口不对 / 防火墙 REJECT |
Connection timed out |
防火墙 DROP / 网络不通 |
Permission denied (publickey) |
公钥没传对 / 权限不对 |
卡在 pledge 或几秒无响应 |
GSSAPI 没关 / DNS 反解慢 |
REMOTE HOST IDENTIFICATION HAS CHANGED |
主机密钥变了,ssh-keygen -R |
5.4 安全加固清单
| 加固项 | 配置 | 说明 |
|---|---|---|
| 禁用 root 直接登录 | PermitRootLogin no |
用普通用户登录后 sudo |
| 禁用密码认证 | PasswordAuthentication no |
只留公钥登录 |
| 限制尝试次数 | MaxAuthTries 3 |
降低暴力破解空间 |
| 限制可登录用户 | AllowUsers ops |
白名单 |
| 空闲超时 | ClientAliveInterval 300 + ClientAliveCountMax 2 |
10 分钟无操作断开 |
| 改端口 | Port 2222 |
只减少扫描噪音,不是真正的安全措施 |
| 防暴力破解 | fail2ban | 多次失败自动封 IP |
面试点 :"改端口能提升安全性吗?" → 只能减少自动化扫描的噪音 ,扫描器照样能全端口扫出来。真正的安全靠密钥认证 + 禁用 root + 最小权限。
第六节 易错点
- 客户端配置和服务端配置不是一回事 :
PermitRootLogin、PasswordAuthentication这些只能写在sshd_config。 - 改完
sshd_config一定要systemctl restart sshd,而且要先sshd -t检查语法,否则可能把自己锁在外面。 - 改端口必须同时处理防火墙和 SELinux,漏一个就连不上。
- 公钥免密登录失败,九成是权限问题 (
.ssh700、authorized_keys600)。 known_hosts里记录的是主机公钥,不是你的公钥;重装系统后必然变化。scp -r的-r是递归,传目录必须加。- 私钥绝对不能外传 ,
authorized_keys里放的永远是.pub文件。 - GSSAPI 没关会导致登录慢,服务端和客户端都要检查。
第七节 SSH 连接工具
| 工具 | 平台 | 说明 |
|---|---|---|
| PuTTY | Windows | 老牌免费工具,支持 SSH、Telnet、串口 |
| SecureCRT | Windows / macOS | 商业软件,多标签、会话管理强 |
| Xshell | Windows | 商业软件,国内使用广泛 |
| Mac 自带终端 | macOS | 系统自带,直接用 ssh 命令 |
第八节 密钥对登录
本节和 4.5 是同一件事。 4.5 用
ssh-keygen -t ed25519+ssh-copy-id,更短更稳;本节是传统的手工步骤,对照着看即可。
密钥对验证:既安全又方便。
步骤 1:生成并上传公钥
Client 客户端:
bash
ssh-keygen -t rsa
Server 服务端:把公钥上传到服务器
bash
cat id_rsa.pub >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
步骤 2:修改服务端 SSH 配置文件
bash
vim /etc/ssh/sshd_config
text
PubkeyAuthentication yes # 是否使用公钥验证
AuthorizedKeysFile .ssh/authorized_keys # 公钥保存位置
PasswordAuthentication no # 禁止使用密码验证登录
步骤 3:重启 SSH 服务
bash
systemctl restart sshd