Linux 命令行日课 · 从零到得心应手的每日修行
Day 01:别再被命令行劝退了——Day 01:终端、提示符与文本查看命令 Day 02:文件管理命令——创建、复制、移动、删除与链接 Day 03:求助、编辑与重定向——让 Linux 真正为你工作 Day 04:你的终端其实会"编程"——变量、环境与引号的艺术 Day 05(上):Linux 的"门禁系统"——用户、组与密码管理 Day 05(下):借力打力——su、sudo 提权与文件权限解密 Day 06:文件权限管理实战——从 chmod 到 chattr,把权限"锁"明白 Day 07:进程管理与系统监控——ps、kill、jobs 到 top 全掌握 Day 08:系统服务管理与压力测试——从 systemd 到 stress Day 09:远程登录与安全加固——SSH 从入门到不输密码(本篇) Day 10:即将更新
前八天我们一直在"单机世界"里打转——文件权限、进程管理、系统服务,全是在一台机器上操作。但真实环境里,你面对的不可能是"一台机器"——开发环境、测试服务器、生产服务器,少则三五台,多则成百上千。你不可能抱着显示器和键盘跑到机房一台台插。
这就是 SSH 出场的时候。它给你的感觉就像坐在自己电脑前,手却伸到了千里之外的服务器上——敲命令、传文件、改配置,跟你坐在那台机器面前一模一样。
今天的内容分三块。上半场搞懂 SSH 是怎么保证安全的——加密是怎么回事、第一次连接为什么问你 yes/no、密钥认证比密码强在哪。中半场上手实操——ssh 命令、配置文件、免密登录一条龙。下半场做安全加固——把 SSH 服务端"锁"到滴水不漏,让暴力破解的人连门都摸不着。
一、SSH 是什么——给你和服务器之间拉一根"加密电话线"
1.1 没有 SSH 的时代
在 SSH 出现之前,人们用的是 telnet、rlogin、rsh 这些工具远程连服务器。问题在哪?它们发的一切内容都是明文的——包括你的密码。就像明信片上写银行卡密码,邮递员、分拣员、送信员,谁经手谁看得见。
SSH 全称 Secure Shell,它做的事一句话就能说清:在你和服务器之间建立一个加密隧道,所有数据都走这条隧道,外面的人只能看到乱码。
1.2 SSH 建立连接——五个回合的"安全握手"
SSH 建立连接不是你想象中"一秒钟就连上了"。背后有五步"握手",每一步都在为安全加码:
| ① 版本协商 | 双方说好用什么版本(SSH2) | “你说中文还是英文?”—“英文吧” |
| ② 算法协商 | 商量用哪些加密算法、压缩算法 | “我们用 AES 加密,SHA256 校验” |
| ③ 身份认证 | 服务器和客户端互相"亮身份证" | “你是谁?出示你的密钥” |
| ④ 会话请求 | 客户端说要干什么——开 shell?传文件?端口转发? | “我要远程敲命令,请准备” |
| ⑤ 交互会话 | 正式开始干活 | 你敲命令,服务器执行,结果传回来 |
你平时感知不到这五步,但理解它们很重要——后面配置出问题、连不上、报错,你就知道是哪一步卡住了。
二、加密的故事——公钥私钥到底是怎么回事
这是 SSH 最难理解也最核心的部分。我用一个比喻帮你建立直觉。
2.1 对称加密:一把钥匙
原文 + 🔑 = 密文
密文 + 🔑 = 原文
加密和解密用同一把钥匙。优势是快,劣势是:你怎么把这把钥匙安全地交给对方? 你俩都不在一个地方,给钥匙的过程本身就是"明文传输"——那还不如不加密。
2.2 非对称加密:两把钥匙
🔓 公钥(Public Key)——可以公开发给任何人,用来加密
🔐 私钥(Private Key)——死也要藏在自己手里,用来解密
公钥加密的东西,只有对应的私钥才能解开。 这就解决了对称加密的"怎么给钥匙"的问题——你公开你的公钥,我用它加密数据发给你,路上就算被截获也没人能解开,因为只有你有私钥。

2.3 SSH 的双向加密——双方都有"一对钥匙"
SSH 不是只有服务器有密钥。服务器和客户端各自生成自己的公私钥对,最终形成这样一个格局:
服务器持有:自己的私钥 + 客户端的公钥
客户端持有:自己的私钥 + 服务器的公钥
通信过程:
- 服务器 → 客户端:用客户端公钥加密,客户端收到后用自己私钥解密
- 客户端 → 服务器:用服务器公钥加密,服务器收到后用自己私钥解密
双向都加密,双向都安全。整个过程分四步走:
第一步:服务器准备密钥对。
服务器在 /etc/ssh/ 下存着多个密钥对,比如 ssh_host_ecdsa_key(私钥)和 ssh_host_ecdsa_key.pub(公钥)。每次 sshd 服务启动,自动加载这些密钥。
第二步:客户端第一次连服务器——“这个人我认识吗?”
[zyf@client ~]$ ssh server
The authenticity of host 'server (10.1.8.10)' can't be established.
ECDSA key fingerprint is SHA256:KTP3/4VydNwCIpOUzpd0C5IhvjfirH+y1U8IHIt8ZdM.
Are you sure you want to continue connecting (yes/no)?
这是客户端在问你:“嘿,这个人自称是 server,他的身份证指纹是 KTP3……我从来没见过他。你确认要连吗?”
你输入 yes 后,服务器的公钥被存进 ~/.ssh/known_hosts。下次再连同一台服务器,客户端会比对公钥指纹——一致就放行,不一致就报警(可能有中间人攻击)。
第三步:客户端也用服务器公钥加密自己的公钥,发给服务器。
第四步:双方都有了对方的公钥,加密通信开始。
三、ssh 命令——你的远程遥控器
3.1 基本连接
# 方式一:直接用 IP
ssh 10.1.8.10
# 方式二:用主机名(/etc/hosts 或 DNS 里配好的)
ssh server
# 方式三:指定用户名
ssh zyf@server
ssh -l zyf server # -l 和 @ 等价
3.2 不登录,只执行一条命令
有时候你不想登录进去——只想在远程机器上跑一条命令,结果拿回来就行:
[zyf@client ~]$ ssh zyf@server hostname
zyf@server's password:
server.zyf.cloud
[zyf@client ~]$ # 注意!提示符还是 client,你没离开本机
# 多条命令用引号包起来
[zyf@client ~]$ ssh root@server 'hostname; id'
root@server's password:
server.zyf.cloud
uid=0(root) gid=0(root) groups=0(root)
这个用法在写脚本的时候特别有用——你可以在本机脚本里远程控制上百台服务器,逐个执行检查命令,把结果收集回来。
3.3 其他选项
# -p:指定端口(默认 22)
ssh -p 22 zyf@server
# -i:指定私钥文件
ssh -i /tmp/my_key root@server hostname
四、SSH 客户端配置文件——懒人才是高效的人
每天敲 ssh -p 2222 -i ~/.ssh/special_key zyf@10.1.8.10 你会疯的。配置文件就是帮你把这些参数"固化"下来的。
4.1 两个配置文件
| ~/.ssh/config | 只对你生效 | 高 |
| /etc/ssh/ssh_config | 对所有用户生效 | 低 |
4.2 实战配置
# 创建配置目录(权限必须 700)
[zyf@client ~]$ mkdir -m 700 ~/.ssh
# 写配置
[zyf@client ~]$ vim ~/.ssh/config
Host *
StrictHostKeyChecking no # 不弹 yes/no 确认,直接接受
User root # 默认用 root 登录
PreferredAuthentications password # 默认用密码认证
Host s1
HostName 10.1.8.10
User zyf
Port 1022
Host s2
HostName 10.1.8.11
User zyf
# 权限收紧——必须 600,否则 ssh 拒绝使用
[zyf@client ~]$ chmod 600 ~/.ssh/config
配好之后,ssh s1 就等于 ssh -p 1022 zyf@10.1.8.10。
关键参数说明:
- Host *:匹配一切目标机器。如果你有特殊需求,单独写一个 Host 块覆盖它。
- StrictHostKeyChecking no:跳过"Are you sure you want to continue connecting?"这个交互——脚本里用这个,手动操作时建议保留。
- PreferredAuthentications password:强制用密码认证(后面讲密钥认证时会调这个)。
权限为什么这么严格? 如果你的 config 文件权限是 644(别人可读),SSH 会直接报错:Bad owner or permissions on /home/zyf/.ssh/config。因为别人读到你的配置文件,就可能知道你用什么方式登录哪些机器——安全风险。
五、密钥认证——告别密码,用"身份证"登录
5.1 密码登录的三大槽点
密钥认证解决以上所有问题。它的核心思想是:你手里有一对数学上关联的密钥,服务器只认公钥不认密码。
5.2 密钥认证三步走
第一步:在客户端生成密钥对
[zyf@client ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/zyf/.ssh/id_rsa): # 回车,用默认路径
Enter passphrase (empty for no passphrase): # 回车,不设密码
Enter same passphrase again: # 回车确认
Your identification has been saved in /home/zyf/.ssh/id_rsa.
Your public key has been saved in /home/zyf/.ssh/id_rsa.pub.
生成两个文件:
| ~/.ssh/id_rsa | 私钥 | 当银行卡密码保管 |
| ~/.ssh/id_rsa.pub | 公钥 | 当身份证复印件到处发 |
非交互式生成(脚本里用):ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa_new
第二步:把公钥推送给服务器
[zyf@client ~]$ ssh-copy-id zyf@server
# 输入一次密码(最后一次!)
这个命令做的事很简单:把你的 id_rsa.pub 内容追加到服务器的 ~/.ssh/authorized_keys 文件中。你可以去服务器上验证:
# 客户端的公钥
[zyf@client ~]$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDtFoo/sD... zyf@client
# 服务器上的认证文件——一模一样
[zyf@server ~]$ cat ~/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDtFoo/sD... zyf@client
第三步:验证
[zyf@client ~]$ ssh zyf@server hostname
server.zyf.cloud
# 没弹密码!直接返回了结果
5.3 密钥认证的验证原理
当你用密钥登录时,不是"客户端把私钥发给服务器比对"——私钥永远不出你的机器。真正的过程是:
整个过程私钥没有离开过你的机器,传输的只有挑战码和结果。这就是为什么比密码安全。
5.4 怎么把一把密钥配给多台服务器
# 同一把公钥推给 3 台服务器
ssh-copy-id zyf@server1
ssh-copy-id zyf@server2
ssh-copy-id zyf@server3
# 或者推给 root
ssh-copy-id root@server
一把私钥走天下,所有信任你的服务器都认。
六、排故——密钥配好了还是让输密码
这是 SSH 出问题频率最高的情况。配置完密钥登录,满怀期待地敲下 ssh server——结果还是弹密码。
6.1 90% 的情况:权限不对
SSH 对文件权限有近乎偏执的要求——权限太宽就拒绝工作,因为那意味着"别人可能看到了你的私钥"。
正确的权限表:
| ~/.ssh/ | 700 (drwx——) | chmod 700 ~/.ssh |
| ~/.ssh/id_rsa(私钥) | 600 (-rw——-) | chmod 600 ~/.ssh/id_rsa |
| ~/.ssh/authorized_keys | 600 (-rw——-) | chmod 600 ~/.ssh/authorized_keys |
| 家目录 | 750 或 700,不能是 777 | chmod 750 ~ |
6.2 实战排故
模拟故障:
# 在 server 上故意把 root 家目录改成 777
[root@server ~]# chmod 777 /root
# 客户端尝试密钥登录——失败!
[zyf@client ~]$ ssh root@server hostname
root@server's password:
排查:在 server 上实时盯着日志:
[root@server ~]# tail -f /var/log/secure
Jul 31 16:13:41 server sshd[3693]: Authentication refused: bad ownership or modes for directory /root
日志说得很直白:/root 的权限有问题。修它:
[root@server ~]# chmod 550 /root
再试——恢复正常。出问题先看 /var/log/secure,这是排故第一步。
七、加固 SSH——给你的服务器穿上"防弹衣"
前面的内容让你能连上服务器。这一节让你连上的同时,拦住在外面敲门的攻击者。
SSH 服务端配置文件是 /etc/ssh/sshd_config。注意区分:
| /etc/ssh/sshd_config | SSH 服务端 | systemctl reload sshd |
| ~/.ssh/config 或 /etc/ssh/ssh_config | SSH 客户端 | 下次执行 ssh 自动生效 |
7.1 禁止 root 用密码登录
[root@server ~]# vim /etc/ssh/sshd_config
# 添加:
PermitRootLogin prohibit-password
[root@server ~]# systemctl reload sshd
效果:root 只能密钥登录,不能用密码登录。
为什么?root 账号每个 Linux 都有,用户名不用猜。如果允许密码登录,攻击者只要暴力跑密码字典,迟早有一天能撞进来。prohibit-password 堵住了这个口。
测试:
# 用密码——拒绝
[zyf@client ~]$ ssh -o PreferredAuthentications=password root@server
root@server's password:
Permission denied, please try again.
# 用密钥——OK
[zyf@client ~]$ ssh root@server hostname
server.zyf.cloud
7.2 完全禁止 root 登录(更狠)
[root@server ~]# vim /etc/ssh/sshd_config
# 添加:
PermitRootLogin no
[root@server ~]# systemctl reload sshd
效果:root 不管用什么方式都登不了——密码不行,密钥也不行。
那要用 root 怎么办?先用普通用户登录,再 su – 切换。 这样做的好处不止安全——还有审计。系统日志会留下"zyf 于某时某刻切换成了 root",出了事能追溯到人。如果所有人都用 root 直接登录,根本没记录是谁干的。
[zyf@client ~]$ ssh root@server
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
# 正确姿势:
[zyf@client ~]$ ssh zyf@server
[zyf@server ~]$ su –
Password:
[root@server ~]#
7.3 禁止密码登录(只用密钥)
[root@server ~]# vim /etc/ssh/sshd_config
PasswordAuthentication no
[root@server ~]# systemctl reload sshd
效果:所有人都必须用密钥登录。密码在这个服务器上彻底作废。
测试:
# zyf 没配密钥——直接拒绝,连输入密码的机会都不给
[zyf@client ~]$ ssh -o PreferredAuthentications=password zyf@server
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
# zyf 配了密钥——畅通无阻
[zyf@client ~]$ ssh zyf@server
Last login: Thu May 14 10:35:05 2026
7.4 只允许特定用户登录
[root@server ~]# vim /etc/ssh/sshd_config
AllowUsers zyf
[root@server ~]# systemctl reload sshd
效果:白名单机制。只有 zyf 能 SSH 登录,其他用户(如 laowang)不管用什么方式认证都登不了。
# laowang 配了密钥也没用
[zyf@client ~]$ ssh laowang@server hostname
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
# zyf 正常
[zyf@client ~]$ ssh zyf@server hostname
server.zyf.cloud
7.5 关闭 DNS 反向解析
UseDNS no
不是安全配置,但很实用。默认情况下 SSH 服务器会尝试反向解析客户端的 IP 对应什么域名——如果 DNS 配置不对,连接会卡好几秒。UseDNS no 跳过这一步,登录速度立竿见影。
7.6 一张表总结加固策略
| PermitRootLogin prohibit-password | root 只能密钥登录 | ⭐⭐⭐ |
| PermitRootLogin no | root 完全不能登录 | ⭐⭐⭐⭐ |
| PasswordAuthentication no | 全员密钥登录 | ⭐⭐⭐⭐⭐ |
| AllowUsers zyf bob | 只允许指定用户登录 | ⭐⭐⭐⭐ |
| UseDNS no | 跳过反向 DNS,加快连接 | ⭐⭐⭐ |
生产环境推荐组合:
PermitRootLogin no
PasswordAuthentication no
AllowUsers zyf bob
UseDNS no
开了这四条,攻击者面前就是一道铁门:root 登不了、密码没用、用户名不对的直接拒绝、连接还贼快。
八、核心文件速查表
| id_rsa | 客户端 | 你的私钥 | 你死也要保护好的东西 |
| id_rsa.pub | 客户端 | 你的公钥 | 可以到处发的"身份证" |
| known_hosts | 客户端 | 你信任的服务器公钥列表 | “我连过的服务器花名册” |
| authorized_keys | 服务器 | 被授权登录的客户端公钥列表 | “谁有资格免密进我这扇门” |
| sshd_config | 服务器 | SSH 服务端配置 | “这扇门开多大、谁让进” |
| ~/.ssh/config | 客户端 | SSH 客户端配置 | “去哪些门、用哪把钥匙” |
今日骚操作
# 一条命令:生成密钥 + 推公钥 + 加固服务端 + 免密验证
ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa_new && \\
echo "=== 密钥生成完毕 ===" && \\
ssh-copy-id -i ~/.ssh/id_rsa_new zyf@server && \\
echo "=== 公钥已推送 ===" && \\
ssh -i ~/.ssh/id_rsa_new zyf@server "sudo tee -a /etc/ssh/sshd_config <<< 'PasswordAuthentication no' && sudo systemctl reload sshd" && \\
echo "=== 服务端已禁止密码登录 ===" && \\
ssh -i ~/.ssh/id_rsa_new zyf@server hostname && \\
echo "=== 免密登录验证通过 ===" && \\
echo "=== 现在这台服务器只能用密钥登录了 ==="
拆解:
一条命令串起 ssh-keygen、ssh-copy-id、远程命令执行、sshd_config 配置、systemctl reload 五项技能。给新服务器初始化时,跑这一条就搞定安全基线。
下一篇预告:Day 10 我们进入 Linux 的另一块拼图——存储管理。fdisk 分区、mkfs 格式化、mount 挂载、df/du 看空间,亲手给虚拟机挂一块新硬盘,体验从"一块裸盘"到"能用"的全过程。
今日练习:






