SSH 与日志 — CodeRoadMapSSH 与日志
这一课你将能做到
- 配置 SSH 密钥登录服务器,禁用密码登录,把被暴力破解的风险降到零
- 用 scp/rsync 在本地与服务器之间安全传输文件和目录
- 通过 /var/log/auth.log、journalctl、Spring Boot 应用日志定位「谁在什么时间登录/操作/报错」
为什么要学
SSH 是你进入服务器的唯一大门,也是黑客扫描器 24 小时撞库的头号目标。任何一台有公网 IP 的服务器,放行 SSH 密码登录后,/var/log/auth.log 里几小时内就会出现来自世界各地的暴力破解记录。密钥登录 + 禁用密码 + 改默认端口是服务器安全的最低配置。
日志则是事后追责与问题定位的唯一证据链:谁登录过(auth.log)、服务为什么挂(journalctl)、接口为什么 500(应用日志)。本站后端上线第一天,这三类日志就要全部跑通。
先建立图像
SSH 密钥认证的原理(非对称加密):
本地电脑 服务器
┌──────────────┐ ┌──────────────────┐
│ 私钥 id_ed25519│ 证明身份 │ 公钥存在: │
│ (绝不外泄, │ ───────────→ │ ~/.ssh/ │
│ 可加密码短语) │ 挑战-应答 │ authorized_keys │
└──────────────┘ └──────────────────┘
过程:服务器发一段随机数据 → 本地用私钥签名 →
服务器用公钥验证签名 → 通过则登录。
私钥永远不离开你的电脑,网络上抓不到密码。
三类核心日志:
/var/log/auth.log → 谁登录了、sudo 了、失败了(Ubuntu)
journalctl -u ssh → SSH 服务本身的运行日志
/var/log/myapp/*.log → Spring Boot 业务日志(自己配置的)
跟着做
步骤 1:生成密钥对(在本地电脑执行)
# Windows 用 PowerShell 或 Git Bash;Mac/Linux 直接用终端
ssh-keygen -t ed25519 -C "leebf@codeforge"
# 一路回车:默认存到 ~/.ssh/id_ed25519(私钥)和 id_ed25519.pub(公钥)
# 建议设置密码短语(passphrase),私钥丢了也不致立刻沦陷
ls ~/.ssh/
# id_ed25519 id_ed25519.pub
ed25519 是新一代算法,比 RSA 更短更快更安全。老系统不支持时用 ssh-keygen -t rsa -b 4096。
步骤 2:把公钥部署到服务器
# 方法一:一键部署(需要暂时还能用密码登录)
ssh-copy-id ubuntu@你的服务器IP
# 方法二:手动(云服务器控制台粘贴公钥的场景)
cat ~/.ssh/id_ed25519.pub
# 复制输出,登录服务器后:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA... leebf@codeforge" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
权限是硬要求:.ssh 必须 700,authorized_keys 必须 600,否则 sshd 出于安全拒绝读取。
步骤 3:验证登录并加固 SSH 服务
# 先验证密钥能登录(新窗口验证,别关当前会话!)
ssh ubuntu@服务器IP
# 确认无误后,修改服务端配置
sudo nano /etc/ssh/sshd_config
关键配置项:
PasswordAuthentication no # 禁用密码登录(防暴力破解)
PermitRootLogin no # 禁止 root 直接登录
Port 2222 # 改默认端口(减少扫描噪音,可选)
MaxAuthTries 3 # 最多试错 3 次
# 检查配置语法再重启(写错会把自己锁外面)
sudo sshd -t
sudo systemctl restart ssh
# 防火墙放行新端口(如果改了端口)
sudo ufw allow 2222/tcp
黄金纪律:改 sshd 配置时保留一个已登录的会话不关,新会话验证能连后再退出旧会话。
步骤 4:免密传输文件——scp 与 rsync
# scp:上传/下载单个文件
scp ./codeforge.jar ubuntu@服务器IP:/opt/codeforge/
scp ubuntu@服务器IP:/var/log/myapp/error.log ./ # 下载日志到本地分析
scp -P 2222 ... # 改过端口要加 -P(大写)
# rsync:传目录、增量同步(部署静态资源、备份首选)
sudo apt install -y rsync
rsync -avz --progress ./dist/ ubuntu@服务器IP:/var/www/html/
# a=归档(保留权限时间) v=显示过程 z=传输压缩
# rsync 的杀手级特性:增量——只传变化的文件,第二次执行秒完
rsync -avz --delete ./dist/ ubuntu@服务器IP:/var/www/html/
# --delete 让目标目录和源完全一致(多余文件删除,慎用)
步骤 5:审计登录日志——auth.log
# 谁登录成功了
sudo grep "Accepted" /var/log/auth.log | tail -20
# Oct 7 10:01:22 server sshd[1234]: Accepted publickey for ubuntu from 1.2.3.4
# 谁在暴力破解(失败记录)
sudo grep "Failed password" /var/log/auth.log | tail -10
# 统计爆破源 IP 排行(文本处理课的组合拳)
sudo grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head
# 谁用了 sudo(操作审计)
sudo grep "sudo:" /var/log/auth.log | grep COMMAND | tail -10
# 实时盯登录(安全巡检)
sudo tail -f /var/log/auth.log
步骤 6:SSH 服务与应用日志
# SSH 服务本身的日志(启动失败、配置错误看这)
sudo journalctl -u ssh -n 50 --no-pager
# Spring Boot 应用日志(本站配置在 /var/log/codeforge/)
tail -f /var/log/codeforge/app.log | grep --line-buffered ERROR
# 系统级日志总入口
sudo journalctl -p err -b --no-pager # 本次启动以来的所有错误
步骤 7:防爆破加固——fail2ban
sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
# 查看 SSH 防护状态
sudo fail2ban-client status sshd
# Status: Currently banned: 3 Total banned: 128
# 默认策略:5 次失败封禁 10 分钟。黑名单 IP 会被 iptables 直接丢弃。
步骤 8:SSH 使用技巧提效
# 本地 ~/.ssh/config 配置别名,告别记 IP
nano ~/.ssh/config
Host codeforge
HostName 服务器IP
User ubuntu
Port 2222
IdentityFile ~/.ssh/id_ed25519
ssh codeforge # 一条命令直达
scp app.jar codeforge:/opt/ # 传输同样用别名
# 保持连接不断(避免因网络空闲被踢)
# ~/.ssh/config 中加:
# ServerAliveInterval 60
# 在服务器上执行单条命令不登录
ssh codeforge "systemctl status codeforge --no-pager"
讲清楚要点
- 密钥认证的本质是挑战-应答:私钥签名、公钥验证,密码不经过网络传输,中间人无法嗅探。这是它比密码登录安全的根本原因。
- .ssh 目录权限错了密钥直接失效:目录 700、authorized_keys 600、所有者必须是自己。
ssh -v 能看到 bad ownership or modes 的明确报错。
- 加固三件套有先后顺序:先部署密钥并验证 → 再禁用密码登录 → 最后改端口/禁 root。顺序反了会把自己锁在服务器外。
- scp 的端口参数是大写 -P,ssh 是小写 -p:经典易混点,写错报连接失败。
- rsync 的尾斜杠语义:
rsync -a src/ dst/ 同步 src 里的内容;rsync -a src dst/ 会把 src 目录本身放进 dst。差一个斜杠结果完全不同。
- auth.log 是安全审计的源泉:登录成功(Accepted)、失败(Failed)、sudo 操作全在里面。等保合规、入侵排查都以它为准。
- fail2ban 是密码时代的守门员:即使禁用了密码登录,装它也能封掉扫描器,减少日志噪音和攻击面。
你可能会懵的地方
-
密钥登录还要不要密码短语(passphrase)?
建议要。passphrase 保护的是私钥文件本身——笔记本丢了,没有短语的私钥等于大门钥匙直接送人。配合 ssh-agent 只需开机输一次。
-
为什么 ssh-copy-id 还是需要密码?
它的工作方式是「先用密码登录上去,替你追加公钥」。这是最后一次用密码,之后就禁用了。
-
云服务器控制台也能配密钥,和 ssh-copy-id 一样吗?
原理相同,都是往 authorized_keys 写公钥。控制台方式适合初始化,ssh-copy-id 适合给已有服务器加新同事。
-
改了 SSH 端口就安全了吗?
只是减少噪音(扫描器默认扫 22)。真正的安全靠密钥认证 + 禁用密码。改端口属于锦上添花,不是核心防线。
-
服务器之间能互相 SSH 吗?
能,但不要在服务器 A 上存能登录服务器 B 的私钥(一台沦陷全线沦陷)。用 ProxyJump(ssh -J 跳板机 目标机)做堡垒机跳转是规范做法。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 公钥私钥搞反,把私钥传到服务器 | 私钥泄露 = 身份被盗 | 只传 .pub 公钥;私钥永不出本机 |
| chmod 777 ~/.ssh | sshd 拒绝认证,报权限不安全 | 目录 700、文件 600 |
| 禁密码前没验证密钥能登 | 把自己锁在门外 | 新窗口验证密钥登录成功后再改配置 |
scp -p 2222 | scp 的端口参数是大写 -P | scp -P 2222 |
| rsync 源路径漏写尾斜杠 | 多套一层目录,部署路径全错 | rsync -avz src/ dst/ 记牢斜杠语义 |
| 改完 sshd_config 直接关终端 | 配置错误无人发现,重启后失联 | 保留旧会话 → sshd -t → 新窗口验证 |
卡点急救
-
现象:密钥登录报 Permission denied (publickey)
按序排查:ssh -v 看细节 → 服务器端 ls -la ~/.ssh 查权限和所有者 → 确认公钥内容完整无换行混入 → sudo tail -f /var/log/auth.log 边登录边看拒绝原因。
-
现象:sshd 重启失败,SSH 连不上服务器
配置文件语法错误。云服务器用控制台的 VNC/救援模式登录 → sudo sshd -t 看报错行 → 修复后 systemctl restart ssh。预防:改配置时保留旧会话。
-
现象:scp 传输大文件中途断掉前功尽弃
scp 不支持断点续传。改用 rsync -avzP --partial(--partial 保留已传部分,重跑续传)。
面试常问
-
SSH 密钥登录的原理?为什么比密码安全?
基于非对称加密的挑战-应答:服务器发随机挑战,客户端用私钥签名,服务器用公钥验证。私钥永不传输,网络上无密码可嗅探;没有私钥的攻击者无法伪造签名,暴力破解失去意义。配合禁用密码登录,可免疫撞库攻击。
-
如何查看服务器是否被暴力破解过?
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head 看失败源 IP 排行;grep "Accepted" /var/log/auth.log 核查成功登录记录里有没有陌生 IP。加固手段:密钥登录、fail2ban、改端口、安全组限源 IP。
-
scp 和 rsync 的区别?
scp 是全量拷贝,简单直接,适合单文件;rsync 是增量同步(按校验和只传差异),支持断点续传(--partial)、删除同步(--delete)、压缩传输(-z),适合目录部署和定期备份。生产部署脚本一律用 rsync。
自测三问
- 禁用密码登录前必须完成哪两步验证?漏了会怎样?
- 如何统计 auth.log 里暴力破解次数最多的 5 个 IP?
- 部署前端静态资源到
/var/www/html/,要求只传变化的文件、目标目录多余文件删除,写出完整 rsync 命令。
小结一句话
SSH 安全四件事——密钥登录、禁密码、fail2ban、auth.log 常审计;文件传输记牢 scp 传单文件、rsync 增量传目录。
延伸