适用:所有 Linux 耗时:约 40 分钟 前置:E4(网络排查)、E1(权限)
SSH 是 Linux 世界里最重要的一个工具——它让你能操作任何一台联网的机器。
这一篇从"连上去"讲到"连得安全、连得省事"。
一、SSH 是什么,一句话
加密的远程命令行。
你的电脑 ──── 加密隧道 ────→ 另一台机器
(客户端) (服务端,跑 sshd)
关键点:全程加密。你在里面敲的东西,中途经过的任何路由器都看不到明文。
这也是为什么 SSH 能替代 telnet/rlogin——那些是明文的,密码在网上裸奔。
二、最简单的连接
ssh 用户名@IP地址
ssh zhangsan@192.168.1.100
ssh root@47.242.169.126
第一次连接会问:
The authenticity of host '192.168.1.100' can't be established.
ED25519 key fingerprint is SHA256:xxxxx.
Are you sure you want to continue connecting (yes/no)?
输 yes 回车。 这是"指纹确认"——防止有人中间人攻击。确认后会记到 ~/.ssh/known_hosts,以后不再问。
如果指纹变了(比如重装了服务器),会警告
REMOTE HOST IDENTIFICATION HAS CHANGED。 可能是重装,也可能是被攻击。 确认是前者的话:ssh-keygen -R 192.168.1.100 # 删掉旧记录不要习惯性
-o StrictHostKeyChecking=no——那等于关掉这层保护。
三、常用参数
| 参数 | 作用 | 例子 |
|---|---|---|
-p 端口 | 指定端口(不是 -P) | ssh -p 2222 user@host |
-i 密钥文件 | 指定私钥 | ssh -i ~/.ssh/mykey user@host |
-v | 详细输出(排障用) | ssh -v user@host |
-N | 不执行命令(只建隧道) | ssh -N -L ... |
-f | 后台运行 | ssh -f -N -L ... |
-L | 本地端口转发 | 见第七节 |
-R | 远程端口转发 | 见第七节 |
端口参数是小写
-p。scp 才是大写-P。这个不一致坑过很多人。
四、密钥登录:不用记密码,还更安全
原理(一句话)
你有一对钥匙:
私钥(id_ed25519) ← 留在自己电脑上,绝不外传
公钥(id_ed25519.pub)← 放到目标机器的 authorized_keys 里
连接时:服务器用公钥出一道题,只有你的私钥能答对 → 证明是你
私钥永远不离开你的机器,所以比密码安全——服务器被攻破,也拿不到你的私钥。
第一步:生成密钥对
ssh-keygen -t ed25519 -C "你的备注"
一路回车(默认路径 ~/.ssh/id_ed25519)。
如果要设密码短语(passphrase):可以设,更安全(私钥被偷了也用不了),但每次用要输。 建议:个人电脑可以不设,笔记本建议设。
-t ed25519是现代推荐(比 RSA 短、快、安全)。老系统可能不支持,那就用-t rsa -b 4096。
生成后:
ls -l ~/.ssh/
# id_ed25519 ← 私钥(权限必须 600,绝不能给别人)
# id_ed25519.pub ← 公钥(可以随便给)
第二步:把公钥放到目标机器
方法 A:一条命令(最简单)
ssh-copy-id 用户名@目标IP
输入一次密码,之后就能免密登录。
方法 B:手动(ssh-copy-id 不可用时)
# 在本地
cat ~/.ssh/id_ed25519.pub
# 复制输出的整行
# 登录目标机器
ssh 用户名@目标IP
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "刚才复制的那一整行" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
权限必须对,否则 SSH 会拒绝使用:
~/.ssh→700~/.ssh/authorized_keys→600
第三步:验证
ssh 用户名@目标IP
# 应该不问密码,直接进去了
五、配置文件:把常用连接存起来
每次敲 ssh -p 2222 zhangsan@192.168.1.100 太累。写进 ~/.ssh/config:
nano ~/.ssh/config
Host myserver
HostName 192.168.1.100
User zhangsan
Port 2222
IdentityFile ~/.ssh/id_ed25519
Host work
HostName 47.242.169.126
User root
IdentityFile ~/.ssh/id_ed25519
之后只要:
ssh myserver
ssh work
这个配置文件值得花五分钟配好。 尤其机器多了以后。
更多有用选项:
Host *
ServerAliveInterval 60 # 每 60 秒发心跳,防止空闲断线
ServerAliveCountMax 3 # 3 次没响应就断开
Compression yes # 压缩传输(慢网络有用)
AddKeysToAgent yes # 自动加载密钥到 agent
六、ssh-agent:密码短语只输一次
如果你给私钥设了密码短语,每次都要输很烦。ssh-agent 能帮你在一个会话里记住。
# 启动 agent(大多数桌面环境已自动启动)
eval "$(ssh-agent -s)"
# 把密钥加进去(输一次密码短语)
ssh-add ~/.ssh/id_ed25519
# 看已加载的
ssh-add -l
之后这个终端里所有 SSH 连接都不用再输。
写进 ~/.bashrc 自动加载(可选):
if [ -z "$SSH_AUTH_SOCK" ]; then
eval "$(ssh-agent -s)" > /dev/null
ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi
七、端口转发:SSH 的隐藏超能力
这是 SSH 最被低估的功能。 能把远程的端口"搬"到本地,或反过来。
场景 1:远程数据库不让公网访问,但你要连
ssh -L 3307:127.0.0.1:3306 zhangsan@服务器IP
意思:把服务器上的 3306 映射到我本地的 3307。
之后本地连 127.0.0.1:3307 就等于连服务器的 MySQL。而 MySQL 依然只监听服务器本地,公网访问不到。
本地 3307 ──加密隧道──→ 服务器 127.0.0.1:3306
场景 2:只建隧道,不开 shell
ssh -N -L 3307:127.0.0.1:3306 zhangsan@服务器IP
-N = 不执行远程命令,只转发。不占一个 shell。
后台运行:
ssh -f -N -L 3307:127.0.0.1:3306 zhangsan@服务器IP
场景 3:让远程机器访问我的服务(-R)
ssh -R 8080:127.0.0.1:8000 zhangsan@服务器IP
意思:把我本地的 8000 暴露到服务器的 8080。
用途:本地开发时,让别人通过服务器访问你的开发环境(做演示、给客户看)。
⚠️
-R默认只绑服务器本地。要让外部访问,服务器sshd_config里需要GatewayPorts yes。 这有安全风险——等于把你的本地服务暴露出去。用完就断。
八、断线了怎么办:tmux / screen
SSH 断线,正在跑的命令会被杀掉。 长任务(编译、下载、备份)会被打断。
解法:在远程机器上跑 tmux,断线后重连还能接上。
# 在远程机器上
sudo apt install tmux
tmux new -s work # 新建会话
# 里面跑你的长任务
# 断线了,重新 ssh 上去
tmux attach -t work # 接回来,任务还在跑
tmux 常用:
| 操作 | 按键 |
|---|---|
| 断开(任务继续跑) | Ctrl + B 然后 d |
| 列出会话 | tmux ls |
| 接回会话 | tmux attach -t 名字 |
| 新建窗口 | Ctrl + B 然后 c |
| 切换窗口 | Ctrl + B 然后 数字 |
原则:任何超过 5 分钟的命令,都放进 tmux 里跑。 这条能省你无数次重来。
九、服务器端的加固(如果你是管理员)
看 SSH 服务状态
systemctl status ssh # Debian 系
systemctl status sshd # RPM 系
注意服务名不一样,这是最容易搞混的。
三个必做的加固
编辑 /etc/ssh/sshd_config:
# 1. 禁止 root 直接登录(改用普通用户 + sudo)
PermitRootLogin no
# 2. 只允许密钥登录,禁用密码
PasswordAuthentication no
PubkeyAuthentication yes
# 3. 改端口(可选,减少扫描噪音)
Port 2222
改完必须验证配置再重启:
sudo sshd -t # 语法检查
sudo systemctl reload ssh # 平滑重载,不断现有连接
⚠️ 最危险的错误:改完配置把自己锁在外面。 安全做法:保持当前 SSH 会话不断开,另开一个窗口测试新连接。新连接能进,再关旧的。 验证失败就改回来——旧会话还在,你还能救。
看谁在尝试登录
sudo lastb # 失败的登录记录
sudo grep "Failed password" /var/log/auth.log | tail -20
sudo journalctl -u ssh -n 50
公网服务器上,你会看到大量暴力破解尝试(每秒几十次都常见)。这就是为什么密码登录必须关。
fail2ban:自动封 IP
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
默认配置就能用(5 次失败封 10 分钟)。但在有些系统上默认配置不生效,需要检查:
sudo fail2ban-client status sshd
sudo iptables -L -n | grep f2b # 看有没有真封
这个坑我踩过:
fail2ban配了banaction = firewallcmd-rich-rules但系统没跑 firewalld → 每次 ban 都报错,IP 一个没封,日志里还显示"Total banned: 14"全是假动作。 正确做法:banaction = iptables-multiport,然后实测封一个测试 IP 看 iptables 里有没有条目。
十、动手:五个练习
练习 1:生成密钥并查看
ssh-keygen -t ed25519 -C "test-key"
ls -l ~/.ssh/
cat ~/.ssh/id_ed25519.pub
注意:id_ed25519(无后缀)是私钥,内容绝对不能贴给任何人。
练习 2:配一个 ssh config 条目
nano ~/.ssh/config
Host test
HostName 127.0.0.1
User 你的用户名
保存后:
ssh test # 连自己(需要 sshd 在跑)
练习 3:验证权限检查
chmod 644 ~/.ssh/id_ed25519 # 故意改错
ssh -v 某主机 2>&1 | grep -i "bad permissions"
会看到警告。改回来:
chmod 600 ~/.ssh/id_ed25519
这个练习让你亲眼看到"权限不对 SSH 就不用"的行为。
练习 4:本地端口转发(有第二台机器时)
ssh -N -L 8080:127.0.0.1:80 用户名@目标IP
# 另开一个终端
curl http://127.0.0.1:8080
练习 5:tmux 断线恢复
# 在远程机器上
tmux new -s test
# 跑一个长命令
ping 8.8.8.8
# Ctrl+B 然后 d (断开)
tmux ls
tmux attach -t test # 接回来,ping 还在跑
十一、验证:你过关了吗
- 会用
ssh 用户@IP连接 - 会用
ssh-keygen生成密钥,知道私钥/公钥的区别 - 会用
ssh-copy-id配免密登录 - 知道
~/.ssh要 700、私钥要 600 - 会写
~/.ssh/config简化连接 - 会用
scp/rsync传文件(见下一篇) - 会用
-L做本地端口转发 - 会用 tmux 让长任务熬过断线
- 知道改 sshd 配置时不能断开当前会话
十二、不行怎么办
Q1:Permission denied (publickey)
三个原因,按顺序查:
# ① 私钥权限太宽
ls -l ~/.ssh/id_ed25519 # 必须是 -rw-------
# ② 公钥没放对
ssh 用户@主机 "cat ~/.ssh/authorized_keys" # 看有没有你的公钥
# ③ 用错了密钥
ssh -v 用户@主机 2>&1 | grep "Offering public key"
Q2:Connection refused
SSH 服务没跑,或端口不对:
# 在目标机器上
systemctl status ssh
ss -ltnp | grep :22
或者防火墙拦了(云服务器还要看安全组)。
Q3:Connection timed out
包没到——网络不通或防火墙丢包。见 E4 网络排查。
Q4:REMOTE HOST IDENTIFICATION HAS CHANGED
指纹变了。先确认是不是重装/换机器,是的话:
ssh-keygen -R 主机IP
Q5:连上了但很卡、经常断 加心跳:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Q6:ssh-copy-id 不存在
手动做(见第四节方法 B),或者用一行命令:
cat ~/.ssh/id_ed25519.pub | ssh 用户@主机 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Q7:改了 sshd_config 后连不上了
如果旧会话还在:改回来,systemctl reload ssh。
如果已经断了:只能通过云控制台的 VNC/串口登录,或者本地控制台。
这就是为什么要"保持旧会话不断开再测试新连接"。
十三、一句话总结
ssh 用户@IP连上去;ssh-keygen+ssh-copy-id免密。
~/.ssh/config存连接;-L做隧道;tmux防断线。服务器端:关密码登录、禁 root、装 fail2ban——但改配置时别断了后路。
← 上一篇 T2|压缩与归档 下一篇 → T4|文件传输:scp / rsync / sftp