开门见山地说,只要你在跑 Linux 服务器,SSH 基本就是每天都要打交道的工具。Ubuntu 22.04 的默认安装里通常带有 SSH 客户端,但服务端不一定装好,更别谈开箱即用的安全配置。很多人装上 openssh-server 能连上就以为完工了,等到服务器被扫、被爆破、被塞进挖矿脚本,才回头补安全策略,这种体验我太熟悉了。这篇文章不是简单教你敲几条 systemctl 命令,而是把 Ubuntu 22.04 里从安装、启用、加固到日常排障的完整链路讲清楚,重点放在“安全远程访问”这六个字上。内容覆盖密钥认证、禁止 root 直接登录、用 AllowGroups 精确控制可登录用户、防火墙配合、VSCode Remote-SSH 连接等真实场景,新手可以照抄,有基础的朋友也能查漏补缺。
1. SSH 的核心作用,以及 Ubuntu 22.04 里哪些默认行为要先搞清楚
1.1 SSH 解决的到底是什么问题
服务器通常放在机房、云平台或者家里某个角落,你不可能每次都跑到屏幕前敲键盘。SSH(Secure Shell)的价值就是在不安全的网络上建立一条加密通道,让你远程登录、执行命令、传文件都像是坐在本机前操作一样。换个生活化的类比:你家的门锁原本只能从里面插钥匙,SSH 相当于给这扇门装了一个远程遥控锁,钥匙是加密后的身份凭证,别人即使看到你在门外按密码,也无法复制出这把钥匙。
在 Ubuntu 22.04 上,系统自带的 OpenSSH 分为客户端和服务端两个部分。客户端用来连接别人,服务端用来被别人连。很多人用 ssh user@host 能连到别的机器,就以为本机也“开了 SSH”,这是个常见的误区。本机默认不一定安装了 openssh-server,所以我下面把服务端的安装和启动单独拎出来讲。
1.2 22.04 的配置方式相比老版本有什么要注意的地方
Ubuntu 22.04 的 SSH 主配置文件仍然是 /etc/ssh/sshd_config,但有个容易被忽略的关键细节:这个文件底部默认带着一行 Include /etc/ssh/sshd_config.d/*.conf。也就是说,系统会读取 sshd_config.d 目录下所有以 .conf 结尾的文件,并把它们的配置合并进来。官方建议自定义配置放在这个目录里新建独立文件,而不是直接改动主配置,好处是升级系统时不容易被覆盖,排查时也一目了然。
但这里有个隐藏的坑:如果你用的是云服务器镜像,/etc/ssh/sshd_config.d/ 里可能已经存在 cloud-init 生成的配置(比如 50-cloud-init.conf)。这些文件里的某项设置可能和你的预期冲突,修改后明明保存了却不生效,多半就是被后读取的同名配置顶掉了。判断规则是:sshd 按顺序读取配置,同一条指令以先到先得的第一条为准,后面的会被忽略。所以自定义文件名建议用 99- 开头,比如 99-hardening.conf,确保排在最后,这样遇到同名的旧配置时可以保证你的策略生效。
还有一个 Ubuntu 22.04 相关的特性:如果云平台的初始化工具修改过 SSH 配置,重启后你的改动可能会被复原。虽然这种情况主要出现在云镜像里,但本地虚拟机安装时也可能遇到残留的 cloud-init 包,如果你发现自己改的 sshd 配置总是莫名其妙丢失,可以执行 sudo cloud-init clean 或者干脆卸载 cloud-init,这个后面排查章节会再提。
1.3 动手前的准备清单
在开始配置之前,先花两分钟确认几件事,能避免后边把自己锁在门外:
- 你有一个非 root 的 sudo 用户,并且知道密码。
- 当前机器的 IP 地址固定(DHCP 分配的地址重启后可能变化,如果是虚拟机建议在路由器里做地址保留,或者用 netplan 配静态 IP)。
- 你当前用什么方式访问这台机器:如果是物理机,确保你能走到它面前操作;如果是云服务器,确保厂商控制台的 VNC 或者网页终端可用,这是最后一条保命通道。
- 系统时间要准确,密钥认证和日志排查都依赖时间一致性,时间差太远可能导致连接异常。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 安装、启用 SSH 服务端,并完成第一次连接验证
2.1 安装 openssh-server,为什么还要顺带确认客户端
登录到 Ubuntu 22.04 后,先执行系统更新。
bash复制sudo apt update && sudo apt upgrade -y
然后安装 SSH 服务端。
bash复制sudo apt install -y openssh-server openssh-client
大部分 Ubuntu 22.04 的最小安装已经带有 OpenSSH 客户端,但这里再装一次也无妨。客户端和服务端是两个独立包,openssh-client 提供 ssh、scp、sftp 等命令,openssh-server 才提供 sshd 服务。如果你只打算让别人连这台机器,那么只装 server 也够;但通常运维人员会在这台机器上再连别的服务器,所以两个都装更实用。
安装完成后,OpenSSH 服务端会自动启动吗?在 Ubuntu 22.04 上,openssh-server 安装后会自动创建 systemd 服务 ssh.service,但启动状态取决于安装包的行为。别猜,直接查看:
bash复制systemctl status ssh
如果显示 active (running),说明已经起来了。如果没起来,手动启动并设置开机自启:
bash复制sudo systemctl enable --now ssh
注意这里服务名是 ssh,不是 sshd。Ubuntu 的 Debian 系列风格里,systemd 服务名叫 ssh,不要下意识敲成 sudo systemctl start sshd 然后报错。
2.2 确认端口监听,以及如何找到自己的 IP
服务启动后,用 ss 命令确认端口监听状态:
bash复制sudo ss -tlnp | grep ssh
正常你会看到类似这样的输出:
text复制LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))
这说明 sshd 已经在所有 IPv4 地址的 22 端口上监听。如果没有看到输出,要么服务没起来,要么端口被其他配置改过。
接着确认本机 IP:
bash复制ip -4 addr show | grep -E "inet " | grep -v 127.0.0.1
或者用更直观的方式:
bash复制hostname -I
记下地址,然后从另一台机器发起第一次连接:
bash复制ssh yourname@192.168.1.100
第一次连接时,客户端会提示确认远程主机的指纹,输入 yes 即可。这一步之所以存在,是为了防止中间人攻击,指纹相当于远程服务器的“身份证号”。建议在台式机、手机终端和云控制台等多渠道备份这个指纹,如果某天指纹变了,能帮你快速判断是否有人从中作梗,还是机器重装过系统。
2.3 修改主机名和静态 IP,省去后顾之忧
关于主机名:默认的主机名可能叫 ubuntu,如果你手里有多台服务器,建议改成有辨识度的名字,否则登录后你可能分不清自己在哪台机器上。
bash复制sudo hostnamectl set-hostname web-prod-01
修改 IP 推荐使用 netplan 配置。Ubuntu 22.04 的 netplan 配置文件在 /etc/netplan/ 下,通常是 01-network-manager-all.yaml 或 00-installer-config.yaml,不同安装方式可能不同。把 DHCP 改成静态 IP 的常见示例:
yaml复制network:
version: 2
ethernets:
enp0s3:
dhcp4: false
addresses:
- 192.168.1.100/24
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses:
- 223.5.5.5
- 1.1.1.1
改完执行 sudo netplan apply 使配置生效。
这段看起来和 SSH 没什么直接关系,但它直接影响远程访问的稳定性。如果你的服务器 IP 重启后就变了,那后面配置的密钥、免密登录、防火墙规则全部打折扣。网络配置是 SSH 可靠性的地基,强烈建议先解决。
3. 安全加固:别让 22 端口裸奔在网络上
3.1 修改默认端口,防的还是批量扫描
默认的 22 端口是扫描器最喜欢的入口,每天有无数的自动化脚本在全网扫这个端口,试图用弱密码爆破。把端口改成高位端口(如 2222、16022 等),不能阻止所有攻击,但是能有效过滤掉大量不加思考的扫描流量,这是很基础的成本博弈。
在 /etc/ssh/sshd_config.d/99-hardening.conf 中添加:
text复制Port 16022
AddressFamily inet
然后校验配置:
bash复制sudo sshd -t
如果语法无误,重新加载:
bash复制sudo systemctl reload ssh
注意,改端口后,你要先在当前会话里验证新端口能连上,再彻底关闭旧会话。云服务器场景下,还要先去控制台安全组放行新端口,否则你会在外面眼睁睁看着端口不通,却又无法从内网访问回来解围。
3.2 禁止 root 直接登录
Linux 服务器的 root 是最高权限账户,通过 SSH 直接允许 root 登录等于给爆破者一个明确的最终目标。即便你设置了很强的 root 密码,也完全没必要冒这个风险。日常运维的正确姿势是:普通用户 + sudo 提权。
继续在 99-hardening.conf 中添加:
text复制PermitRootLogin no
这个设置配合 sudo 机制使用,日常操作都用普通账号,需要管理员权限时再 sudo,这样在审计日志中还能看到是谁在什么时间执行了什么命令。如果你真的需要用 root 权限执行一系列操作,也一样可以通过 sudo 完成,不一定要切换到 root 本身。
3.3 启用密钥认证,这是整个安全策略的核心
密码认证最大的风险在于弱口令和暴力破解。无论你的密码多复杂,只要是通过网络传输认证信息,就存在被中间人截获的隐患,当然 SSH 本身就是加密传输的,但密码字典爆破仍然是最常见的攻击路径。密钥认证则不同,它基于非对称加密:公钥放在服务器上,私钥只保存在你的本地设备中,服务器用公钥验证你的身份,整个过程私钥不出本地。
在我的实际使用中,密钥认证一旦配置好,使用体验是质的提升。不用再反复敲密码,也不怕密码泄露,配合 ssh-agent 还能实现更灵活的多服务器访问。我会在下一节专门讲如何生成和部署密钥。
3.4 通过 AllowGroups 精确控制谁能登录
如果你管理着多台服务器、多个账号,难免会担心某些闲置账号被利用。Ubuntu 22.04 的机制和 RHEL/CentOS 有点不同,默认不存在 wheel 组,管理员组叫 sudo。你要让哪些组能 SSH 登录,直接在配置里写清楚即可。
text复制AllowGroups sudo
这意味着只有 sudo 组的成员才能通过 SSH 登录。如果你有一个专门的运维组,可以这样:
bash复制sudo groupadd ops
sudo usermod -aG ops yourname
然后在配置里写:
text复制AllowGroups sudo ops
如果你希望限制某个具体用户能登录,那么用:
text复制AllowUsers yourname admin
AllowUsers 和 AllowGroups 都适用于所有用户,包括 root,所以要时刻记住当前登录用户是否在被允许的范围内。配置前最好保持一个已连接的终端窗口不要关闭,万一保存配置把自己拒之门外,还可以用这个窗口把配置改回来。
3.5 设置空闲超时和登录尝试次数
为了应对长时间挂机会话和暴力尝试,我习惯再加两条:
text复制ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
解释一下这几项的含义:
ClientAliveInterval 300:每 300 秒向客户端发送一次心跳检测,如果客户端没有响应,服务端会开始计次。ClientAliveCountMax 2:连续 2 次心跳无响应后,服务端断开连接。MaxAuthTries 3:每次连接最多允许 3 次认证尝试,超过则断开。
前两条的作用是避免出现大量半开连接占用服务器资源。很多人觉得只要自己不主动断开,SSH 挂着也没事,实际上网络环境变化后,TCP 连接可能已经处于假死状态,服务器却还在为它维护会话。心跳机制能让这种无效连接被及时回收。
3.6 防火墙放行规则与云平台安全组双层检查
如果你启用了 UFW,要把 SSH 服务放行。Ubuntu 22.04 默认可能没有启用 UFW,检查状态:
bash复制sudo ufw status
如果显示 inactive,可以先启用再放行。但注意启用 UFW 本身有风险,如果你是通过 SSH 远程配置,一旦防火墙规则把当前连接阻断,你就被关在门外了。所以正确的顺序是先放行再启用:
bash复制sudo ufw allow 16022/tcp
sudo ufw enable
sudo ufw status verbose
如果你用默认 22 端口,也可以直接 sudo ufw allow OpenSSH,UFW 内置了 OpenSSH 服务的规则。
更大的坑在云服务器控制台。云厂商通常有一层独立于系统防火墙的安全组,系统里的 ufw 规则即使正确,安全组不放行一样连不上。反之,如果你改了 SSH 端口,只改系统防火墙却忘了安全组,也会导致新端口外部不可达。我在多次配置中总结出的流程是:先改安全组放行新端口,再配置系统防火墙,最后才改 sshd_config。改完之后立刻新开一个终端测试,而不是在旧会话里等待。
4. 密钥认证与免密登录:从“能用”到“好用”
4.1 生成密钥对:选 ED25519 还是 RSA
现代 OpenSSH 版本已经默认支持 ED25519 算法,它的优势是密钥短、生成快、安全性强,推荐作为首选。
在本地机器(不是服务器)上生成:
bash复制ssh-keygen -t ed25519 -C "yourname@laptop"
如果你使用的是公司统一的跳板机,或者需要和某些老旧的自动化系统兼容,可能只能用 RSA。那就生成 4096 位的密钥:
bash复制ssh-keygen -t rsa -b 4096 -C "yourname@laptop"
生成过程中会询问保存路径和 passphrase。直接按回车会存到默认路径 ~/.ssh/id_ed25519,不建议修改路径,否则后续工具容易找不到。passphrase 选项建议设置一个,它相当于本地私钥的二次密码。即使私钥文件被别人拷走,没有 passphrase 也无法使用。如果担心使用麻烦,可以配合 ssh-agent 把私钥加载到内存中,只需每次开机输入一次 passphrase。
4.2 把公钥部署到服务器
生成后,本地目录会出现 id_ed25519(私钥)和 id_ed25519.pub(公钥)。公钥才是可以公开的内容,服务器上存放的就是它。使用 ssh-copy-id 是最省事的方法:
bash复制ssh-copy-id -i ~/.ssh/id_ed25519.pub yourname@192.168.1.100
执行后会要求输入一次密码,随后公钥会自动追加到服务器上你的家目录下的 ~/.ssh/authorized_keys 文件中。如果你的服务器 SSH 端口不是默认 22:
bash复制ssh-copy-id -p 16022 -i ~/.ssh/id_ed25519.pub yourname@192.168.1.100
没有 ssh-copy-id 命令时(比如 Windows 原生 PowerShell 环境),可以手动执行:
bash复制cat ~/.ssh/id_ed25519.pub | ssh -p 16022 yourname@192.168.1.100 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
我见过很多人因为少了 mkdir -p ~/.ssh 而失败,第一次 ssh 登录时家目录下可能还没有 .ssh 目录,公钥根本写不进去。另外 chmod 这几步不能省略,权限过宽会导致 sshd 拒绝读取 authorized_keys。
4.3 验证密钥登录,再决定何时关闭密码登录
确认公钥部署成功后,换一个终端,用密钥方式试连:
bash复制ssh -p 16022 yourname@192.168.1.100
如果一切正常,你不会被提示输入密码,直接进入服务器。这时候才可以在 99-hardening.conf 里关闭密码登录:
text复制PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
先校验语法再重启服务:
bash复制sudo sshd -t
sudo systemctl reload ssh
关键建议:关密码登录前,务必保持一个已经通过密钥登录成功的会话窗口不关闭。一旦新配置导致你无法登录,你还能用这个窗口紧急回滚配置。我在生产环境里吃过亏,改了配置顺手 reload,结果因为公钥权限不对,新连接全被拒绝,幸好旧会话没断,否则只能去机房了。
4.4 私钥与目录的权限问题,这是新手最容易踩的坑
使用密钥认证时,权限问题占故障原因的八成。服务端和客户端两边的权限都要检查:
服务端(服务器上):
| 路径 | 推荐权限 | 说明 |
|---|---|---|
~/.ssh 目录 |
700 | 仅属主可读写执行 |
~/.ssh/authorized_keys |
600 | 仅属主可读写 |
客户端(本地电脑上):
| 路径 | 推荐权限 | 说明 |
|---|---|---|
~/.ssh 目录 |
700 | 防止其他用户读取配置 |
~/.ssh/id_ed25519 私钥 |
600 | 私钥权限绝不能开放 |
~/.ssh/id_ed25519.pub 公钥 |
644 | 公钥可以公开 |
修复命令:
bash复制chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
如果服务器上的 .ssh 目录属于 root 或者其他用户,也会报错。解决办法是:
bash复制sudo chown -R yourname:yourname ~/.ssh
远程执行时特别容易犯的错是用了 sudo 来执行重定向,结果 authorized_keys 的所有者变成 root,导致普通用户无法读取公钥,连接直接被拒。
4.5 ssh-agent 与多服务器密钥管理
当你手上有几台服务器,私钥又设置了 passphrase,每次连接都输 passphrase 会让人抓狂。解决办法是用 ssh-agent 把私钥加载到内存。
bash复制eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
输入一次 passphrase 后,agent 会在会话期间记住解密后的私钥。macOS 用户可以执行 ssh-add --apple-use-keychain ~/.ssh/id_ed25519 把 passphrase 写入系统钥匙串。Windows 用户可以开启服务里的 OpenSSH Authentication Agent,然后执行 ssh-add。
使用 ssh-agent 还有一个好处:配合 ssh -A 或者 config 里的 ForwardAgent yes 可以在跳板机上继续往后跳转,不用在中间机器上放私钥。不过要谨慎使用 agent forwarding,因为如果跳板机被攻破,攻击者可能借助你的 agent 继续访问你的其他机器。我在自己不信任的跳板机上会保持关闭。
4.6 用 config 文件管理多台服务器
服务器超过两台之后,每次敲 ssh -p 16022 yourname@192.168.1.100 太长了。在本地 ~/.ssh/config 中配置别名是标准做法:
text复制Host web-prod
HostName 192.168.1.100
Port 16022
User yourname
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 60
Host db-bak
HostName 10.0.0.5
Port 22
User backupuser
IdentityFile ~/.ssh/id_ed25519_rsa
配置完成后,连接只需要:
bash复制ssh web-prod
scp 传文件也一样:
bash复制scp ./app.tar.gz web-prod:/home/yourname/
config 文件里的规则按第一个匹配项生效,所以把最常用的主机写在前面。ServerAliveInterval 60 是本机维护心跳,可以避免长时间无操作后连接被网络设备切断,和服务端那个类似。
5. 远程开发场景:VSCode Remote-SSH 直连服务器写代码
5.1 为什么远程开发离不开 SSH
很多在实际项目中跑代码的人,发现开发环境和生产环境越来越难保持一致。你本地是 macOS,服务器是 Ubuntu 22.04,本地装 Python 3.12,服务器上装的是 3.10,跑起来行为不一致的问题现场排查非常费劲。VSCode Remote-SSH 解决的就是这个问题:本地编辑器只是一个前端,真正的代码逻辑、解释器、编译环境全部跑在服务器上,你在本地打字,代码在服务器上运行,文件系统直接读写服务器空间。
这种模式对于需要和 Linux 环境交互的 C/C++、Python、ROS 等项目尤其合适。前面提到的热搜里有“vscode远程服务器配置”,很多初学者卡在第一步:VSCode 提示连不上服务器。这里的关键往往是——服务器上的 SSH 本身就只允许密钥登录了,但 VSCode 没有找到对应的私钥文件,或者配置文件里没有写 IdentityFile。
5.2 本机安装 VSCode 与 Remote-SSH 插件
本机安装 VSCode 就不再赘述,装好后在扩展市场搜索 Remote - SSH,安装微软官方的那个插件。连接前先在命令行里确认:
bash复制ssh web-prod
能免密登录成功,再切到 VSCode。
按下 Ctrl+Shift+P,输入:
text复制Remote-SSH: Connect to Host
选择你在 config 里配置的别名(比如 web-prod),VSCode 会在新窗口打开远程连接。首次连接时它会在服务器端自动下载并释放 ~/.vscode-server 目录,这个过程可能需要等待一两分钟,取决于服务器带宽。
如果遇到连接失败,先检查服务器上 ~/.vscode-server 目录是否存在,很可能上次连接中断导致残留文件损坏。解决办法:
bash复制rm -rf ~/.vscode-server
然后重新连接。这招我用了很多次,几乎能解决 VSCode Remote-SSH 大部分莫名其妙的首次连接问题。
5.3 配置 Remote-SSH 使用正确的私钥和端口
如果服务器端口和密钥不是默认的,VSCode 也可能读不到。最好的办法是在 ~/.ssh/config 里明确写出:
text复制Host dev-ubuntu
HostName 192.168.1.100
Port 16022
User yourname
IdentityFile ~/.ssh/id_ed25519
这样 VSCode 的 Remote-SSH 会自动复用本机的 SSH 配置和 agent,不需要在插件设置里重复配置。如果你在 Windows 上用的私钥路径是 C:\Users\you\.ssh\id_ed25519,config 里写法是:
text复制IdentityFile ~/.ssh/id_ed25519
~ 会自动展开成当前用户目录,跨平台方便。
连接成功后,左下角会显示绿色状态条“SSH: dev-ubuntu”。打开终端菜单,默认就是远程服务器上的 bash。直接 sudo apt install 也好、跑训练脚本也好,全部在服务器上执行,体验和在本机几乎没区别。
6. 常见故障现象与排查思路
6.1 Connection refused:到底是谁拒绝了你的连接
这个错误信息非常常见,通常意味着到达了服务器,但没有进程在目标端口监听。
排查顺序:
- 检查 sshd 是否在运行:
bash复制systemctl status ssh
- 检查端口监听情况:
bash复制sudo ss -tlnp | grep ssh
-
确认你是否连对了端口。如果修改过 sshd_config 里的 Port,但连接时还写 22,肯定会出现 refused。
-
查看系统防火墙:
bash复制sudo ufw status
- 云服务器不要忘记检查安全组。本地明明在监听,但从外部怎么都连不上,绝大多数情况是安全组没有放行对应端口。
6.2 Permission denied 和登录失败
看到 Permission denied (publickey,password) 时,先区分是密码阶段失败还是密钥阶段失败。加 -v 参数能看到详细过程:
bash复制ssh -v -p 16022 yourname@192.168.1.100
如果输出里能看到 Offering public key,但服务器一直不接受,大概率是公钥没对上或者权限问题。上服务器查看认证日志是关键:
bash复制sudo tail -f /var/log/auth.log
再发起一次连接,观察新增日志。如果看到 Authentication refused: bad ownership or modes,立刻能定位到权限问题。如果看到 User yourname not allowed because account is locked,则要检查是否用 AllowUsers 或 AllowGroups 把用户过滤了。
6.3 Host key verification failed:警告提示不代表不能修复
有时候服务器重装系统后,你用原来的 IP 去连接,会报:
text复制WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
这是因为本地 known_hosts 里保存的服务器指纹和现在的指纹不一致,SSH 出于防中间人攻击的考虑主动拒绝连接。如果是自己的机器重装,可以放心清理旧指纹:
bash复制ssh-keygen -R 192.168.1.100
如果你改了端口,需要这样写:
bash复制ssh-keygen -R '[192.168.1.100]:16022'
然后重新连接并确认新指纹。这里提醒一句:清理之前最好通过厂商控制台或者其他渠道确认这台机器确实重装过,如果机器没有重装而指纹变了,那你要警惕是否有中间人。
6.4 登录速度很慢,卡了好几秒才提示密码
登录时手输密码或者密钥验证前总是卡顿,基本是 DNS 反向解析的问题。在 sshd_config 中可以设置:
text复制UseDNS no
GSSAPIAuthentication no
建议在 99-hardening.conf 中直接加上,然后 reload。这样能显著减少登录时的等待时间。对于内网环境,通常立刻能感受到区别。
6.5 MaxAuthTries 导致的异常断连
如果你设置了 MaxAuthTries 3,但自动化脚本、VSCode 或某些 SSH 客户端可能会在连接时自动尝试多种密钥和认证方式,超过尝试次数后服务器直接断开。你会看到:
text复制Connection closed by 192.168.1.100 port 16022
解决方案是把这个值调整到 5 到 6,或者排查客户端是否配置了过多的 IdentityFile。如果是 VSCode,可以在连接前通过命令行确认 ssh -vvv 的认证过程不会超过限制。
6.6 关于 reload 和 restart 的选择
修改 sshd 配置后,很多人习惯用 systemctl restart ssh,但这有一个风险:restart 会先停止服务再启动,期间所有现有连接都会断开。如果你当前是通过 SSH 连接的,操作一执行,马上会掉线,如果新配置有语法错误,服务可能无法启动,你就彻底被关在门外了。
稳妥顺序是:
- 修改配置。
- 执行
sudo sshd -t检查语法。 - 执行
sudo systemctl reload ssh,ssh 会在不中断现有会话的情况下重新加载配置。 - 新开一个终端测试新配置,确认没问题后再关闭旧会话。
如果确认语法错误导致 sshd 无法启动,而当前会话已经断开,那就真的只能靠物理访问或者云控制台救援了。我见过太多同事在这一步被卡住,所以每次都要强调:改配置前先留一条后路。
7. 日常运维中的一个小建议
最后补一点实践经验:把刚才手动做的配置用脚本固化下来。Ubuntu 22.04 的服务器一旦多起来,重复配置很容易漏项。我习惯在 /etc/ssh/sshd_config.d/99-hardening.conf 统一维护:
text复制Port 16022
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 5
ClientAliveInterval 300
ClientAliveCountMax 2
AllowGroups sudo
UseDNS no
GSSAPIAuthentication no
每次新装完系统,直接把这个文件复制过去,执行 sudo sshd -t && sudo systemctl reload ssh,再配合 ssh-copy-id 部署公钥,基本 10 分钟内交付一台可以安全远程访问的机器。
我在实际配置中积累的另一个心得是:不要把安全配置做成一锤子买卖。间隔半年左右检查一次 /var/log/auth.log,看看有没有异常 IP 尝试记录,确认一下系统中还有没有不必要的账号可以被 AllowGroups 排除,更新一下服务器补丁。SSH 的安全不是某一个参数决定的,而是一个完善的纪律问题。把默认配置调好,把管理流程走顺,你在 Ubuntu 22.04 上的远程访问体验会非常让人放心,这也是为什么我说“安全远程访问”不是一句口号,而是每一个细节都在服务一个目标:让不该进来的人进不来,让该进来的人用得顺手。
