news 2026/10/21 22:04:10

Ubuntu 22.04 SSH 配置与安全加固实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 22.04 SSH 配置与安全加固实战指南

1. 先搞清楚:SSH 不只是"远程登录"那么简单

很多人把 SSH 当成一个普通的远程登录工具,装了就能用,能用就不管。但在 Ubuntu 22.04 上真正把 SSH 配好,尤其是配到"能上生产环境"的程度,其实涉及一整套链路:协议选型、密钥体系、服务配置、登录策略、防火墙配合、暴力破解防护。这个版本默认用的是 OpenSSH 8.9p1,有几个行为变化值得注意,后面会提到。

这篇内容围绕 Ubuntu 22.04 下的 SSH 服务展开,从零开始把安装、密钥登录、安全加固、常见故障排查全部走一遍。适合三类人:一是刚接触 Linux 服务器、想把自己的 VPS 或实验室机器管起来的初学者;二是公司内部运维,需要统一 SSH 安全基线的人;三是自己折腾 NAS、树莓派、HomeLab,想远程管理又不放心裸奔的玩家。无论哪种场景,读完你都能照着操作,至少能把默认状态下的 SSH 提升到"可以长期暴露在公网"的水平。

先说一个基本的认知:SSH 服务端最重要的配置文件是/etc/ssh/sshd_config,几乎所有的安全策略都在这里调整。但配置只是最后一步,前面还有密钥生成、文件权限、防火墙联动这些容易被忽略的环节。很多"明明配置了密钥登录还是失败"或者"改了端口连不上了"的案例,问题都出在配置之外的地方。

2. 安装与服务管理:先把地基打好

2.1 检查是否已有 SSH 服务

Ubuntu 22.04 的桌面版默认没有安装 openssh-server,服务器版则在安装系统时可选。第一步先确认系统里有没有:

systemctl status ssh

如果提示Unit ssh.service could not be found,说明没装。也可以用dpkg -l | grep openssh-server验证包是否安装。

没装的话直接安装:

sudo apt update sudo apt install -y openssh-server

安装完成后,用sudo systemctl status ssh能看到服务状态。正常情况下应该是active (running),监听端口默认是 22。

这里有第一个容易踩的坑:Ubuntu 22.04 下服务的名称是ssh而不是sshd。虽然你执行systemctl status sshd在某些情况下也能有反应,那是因为系统做了兼容处理,但规范做法是用ssh。另外,修改配置后重载服务用的是sudo systemctl restart ssh,不是reload——reload只会让主进程重新读取配置,而某些参数(比如ListenAddress变更)在 reload 时并不会完全生效,保险起见直接 restart。

2.2 防火墙状态检查

很多用户遇到"SSH 连不上"的第一反应是配置错了,但其实新装的 Ubuntu 22.04 默认可能开了 ufw 但没放行 SSH。如果你之前启用过防火墙,重启后 SSH 服务虽然起来了,但外部流量进不来。

检查当前防火墙状态:

sudo ufw status verbose

如果显示Status: active,确认是否有 OpenSSH 或 22 端口的放行规则。没有的话:

sudo ufw allow OpenSSH

这里我建议用服务名而非端口号。ufw 的/etc/ufw/applications.d/openssh-server里定义了这个服务,直接用allow OpenSSH的好处是以后即使改了 SSH 端口,只要配套更新这个服务定义,规则也能同步。不过多数人改端口后懒得动服务定义,所以直接sudo ufw allow 22/tcp也完全可以,看个人习惯。

2.3 确认网络层可达

SSH 服务起没起来,和你能不能连上是两回事。排查链路是:服务状态 -> 本机回环测试 -> 局域网/公网测试。

本机先测:

ssh localhost

如果能通,说明服务本身没问题。再查看监听地址:

sudo ss -tlnp | grep ssh

正常情况下能看到0.0.0.0:22或:::22。如果这里只显示127.0.0.1:22,说明 sshd 只监听了本机回环地址,外部肯定连不进来。这种情况常见于某些安全加固脚本把ListenAddress改坏了,或者系统里存在多个配置文件互相覆盖。

从本机测试到外部测试之间,最好也确认一下 IP 地址:

ip addr show

找到你网卡对应的 IP(通常是eth0或ens33这类),然后在另一台机器上ssh 用户名@IP测试。

3. 核心配置逐项拆解:看懂 sshd_config 再动手

3.1 先备份,再修改

这个习惯我强调过无数次:修改任何系统级配置文件之前,先备份。因为 SSH 配置出问题会导致你远程登录不上,如果服务器不在身边,那可能就得靠机房带外管理或者重启进救援模式,麻烦得很。

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)

这样备份带日期,以后想回滚也知道是哪天的版本。

3.2 端口与监听地址

默认端口 22 是 SSH 的"标准答案",但也是扫描器最优先探测的端口。公网服务器上每天被扫描上千次是很常见的。把端口改成一个不常用的高位端口,能在一定程度上减少被扫描到的概率——注意,只是减少,不是杜绝。真正防暴力破解靠的是密钥认证和 fail2ban。

修改端口:

Port 22022

这里有两个细节:

第一,端口范围建议选 1024 以上的非著名端口。低于 1024 的端口需要 root 权限监听,sshd 启动时确实以 root 身份运行,所以没问题,但没必要去凑那些知名端口。

第二,Port指令可以写多个,sshd 会同时监听多个端口。这在迁移期间很有用:先加一个新端口,确认能连上,再移除旧端口,降低把自己锁在外面的风险。比如:

Port 22 Port 22022

改完后重启服务,用新端口登录确认没问题,再注释掉 22。

监听地址方面,如果服务器有多块网卡,而你只需要在内网使用 SSH,可以限定只监听内网 IP:

ListenAddress 192.168.1.100

这样即使防火墙规则写漏了,外部网络也无法直接访问这个端口。这种"纵深防御"的思路比单纯依赖防火墙更可靠。

3.3 认证方式的优先级设置

sshd 的认证逻辑是这样的:先验证客户端能提供的认证方法,按顺序逐个尝试。AuthenticationMethods参数可以控制必须使用哪些方法的组合。

最常见的安全要求是"必须密钥登录,禁止密码登录"。对应配置:

PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitEmptyPasswords no

等一下,KbdInteractiveAuthentication这个很多人忽略。有些系统上密码认证是通过 keyboard-interactive 方式实现的(比如 PAM 配置导致),只关PasswordAuthentication不够,KbdInteractiveAuthentication也要一起关掉,否则密码登录依然可能成功。

验证当前生效的认证方式:

sudo sshd -T | grep -E 'passwordauthentication|pubkeyauthentication'

sshd -T可以输出最终生效的配置(包括默认值和 Include 进来的其他配置文件的值),排查问题非常好用。

3.4 登录用户限制

允许谁登录、禁止谁登录,也是安全加固的重要部分。

禁止 root 直接登录:

PermitRootLogin no

这个策略的理由很简单:root 用户名是固定的,暴力破解只需要猜密码。而普通用户名还需要先猜出来,安全级别差不少。如果你确实需要 root 权限,正确的做法是用普通用户登录,再sudo -i提权。

只允许特定用户登录:

AllowUsers alice bob

或者反过来,禁止特定用户:

DenyUsers charlie

建议使用AllowUsers白名单模式,管理更清晰。特别是服务器上可能有多个系统账户(比如数据库服务创建的账户),这些账户不需要 SSH 登录,白名单能避免遗漏。

还有一个容易被忽略的:AllowGroups。配合系统用户组来做权限管理更灵活,例如:

AllowGroups ssh-users

然后sudo usermod -aG ssh-users alice,以后新员工加入只需要加组,离职移除组即可,不用改配置。

3.5 会话超时与最大尝试次数

这几个参数虽然不起眼,但对安全性影响不小:

ClientAliveInterval 300 ClientAliveCountMax 2 MaxAuthTries 3 LoginGraceTime 60

ClientAliveInterval表示服务端每隔 300 秒向客户端发送一次存活探测,如果ClientAliveCountMax次探测都没有响应,就断开连接。这样即使你离开座位忘了退出终端,连接也不会一直被占用。对于长时间跑任务的场景,这个值可以调大一点,但别完全关闭。

MaxAuthTries限制的是每次连接中认证尝试的最大次数。默认值是 6,攻击者在一个连接里可以试 6 次密码。改成 3 更合理。

LoginGraceTime是登录超时时间,默认 120 秒。如果你在 60 秒内没完成认证,连接就被断开。这个值不宜设置过小,否则网速慢的时候用户输密码时间不够,会被莫名断开。

4. 密钥认证配置:彻底告别密码

4.1 为什么推荐密钥认证

密码认证最大的问题是:密码本身可以被暴力破解、可以被钓鱼、可以被键盘记录器截获。而密钥认证基于非对称加密,私钥永远保存在本地,不会在网络上传输。即便服务器被攻破,攻击者拿到的也只是公钥,没有私钥就无法登录其他机器。

从运维角度,密钥认证还有一个隐形好处:配合ssh-agent可以实现免密跳板登录。比如你从笔记本登录跳板机,再从跳板机登录内网机器,密钥转发配置好以后,一次认证全程通行,不用每台机器都输密码。

4.2 密钥生成与上传

生成密钥对使用ssh-keygen,这里建议直接用 ed25519 算法。比 RSA 更快、签名更短,安全性在同等位数下更高。RSA 还需要 3072 位以上才够安全,而 ed25519 天生就是强安全的。

ssh-keygen -t ed25519 -C "your_email_or_nickname" -f ~/.ssh/id_ed25519

执行后会提示设置 passphrase(私钥口令)。这个 passphrase 是用来加密私钥文件的,即使私钥文件泄露,没有 passphrase 也无法使用。我建议一定设置,别嫌麻烦。

生成的公钥是~/.ssh/id_ed25519.pub,私钥是~/.ssh/id_ed25519。把公钥内容追加到服务器的~/.ssh/authorized_keys中:

cat ~/.ssh/id_ed25519.pub | ssh username@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

或者更推荐使用ssh-copy-id工具,它会自动处理权限和目录问题:

ssh-copy-id -i ~/.ssh/id_ed25519.pub username@server

这里有个极容易踩的坑:authorized_keys文件权限必须是 600,.ssh目录权限必须是 700。如果权限过宽松(比如 644 或 755),sshd 出于安全考虑会直接忽略这个文件里的密钥,导致登录失败。等下,这个"忽略"不是说报错拒绝,而是表现为:密钥认证不生效,然后退回密码认证。很多人排查半天,最后发现就是权限问题。

4.3 Windows 客户端的密钥配置

如果你是 Windows 用户,OpenSSH 客户端也是内置的。生成密钥的方法一致:

ssh-keygen -t ed25519 -C "your_email" -f "$env:USERPROFILE\.ssh\id_ed25519"

上传公钥同样可以用ssh-copy-id的 PowerShell 等价形式,或者直接读取公钥文件内容追加到服务器上。Windows 自带的 OpenSSH 版本较新,兼容性没问题。

4.4 验证密钥登录并关闭密码

密钥配置完成后,先不要急着关密码认证。用密钥方式登录一次确认无误:

ssh -i ~/.ssh/id_ed25519 username@server

确认能登录后,再修改sshd_config关闭密码登录:

PasswordAuthentication no KbdInteractiveAuthentication no

然后重启服务。重启前务必确认当前连接不会断开——如果你正在用 SSH 连接那台服务器,重启服务不会断掉现有连接,但是如果配置语法有误,服务起不来,你当前的连接虽然还活着,新的连接却进不来了。所以改完配置后,开一个新终端测试连接,确认没问题再关掉旧终端。

5. 安全加固进阶:fail2ban 与防火墙联动

5.1 fail2ban 的作用与安装

密钥认证部署后,密码暴力破解基本被挡住了,但 Fail2ban 仍然建议安装。理由是什么?SSH 服务本身暴露在公网,即使无法通过密码登录,攻击者依然可以发起大量连接试探,消耗系统资源;而且如果系统里还有其他服务(比如 Web 管理面板、邮件服务),fail2ban 也能统一防护。

安装:

sudo apt install -y fail2ban

fail2ban 的配置目录是/etc/fail2ban/,主配置文件是jail.conf。这个文件会被升级覆盖,所以不建议直接改。正确做法是在jail.d/目录下新建一个.local文件,覆盖默认配置:

sudo nano /etc/fail2ban/jail.d/sshd.local

写入:

[sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 5 bantime = 3600

解释一下参数:

  • maxretry = 5:5 次认证失败就触发封禁。
  • bantime = 3600:封禁 1 小时,单位是秒。
  • findtime默认值是 600 秒,也就是在 10 分钟内达到maxretry次数才会封禁。
  • logpath在 Ubuntu 22.04 上是/var/log/auth.log,如果是其他发行版可能是/var/log/secure。

启动服务:

sudo systemctl enable --now fail2ban sudo systemctl status fail2ban

5.2 fail2ban 的封禁查看与手动解封

查看当前封禁的 IP:

sudo fail2ban-client status sshd

输出会显示Currently banned列表。如果误封了自己(比如你连续输错密码),手动解封:

sudo fail2ban-client set sshd unbanip 192.168.1.100

这里有个实践技巧:bantime不要一开始就设置成永久(-1)。因为如果误封,影响会很大。先设置 1 小时,观察一段时间,确认没有误伤,再逐步加大。

5.3 UFW 联动

fail2ban 和 ufw 可以联动:当 fail2ban 判定某个 IP 需要封禁时,自动向 ufw 添加一条 deny 规则。这样不仅 SSH 被拦截,该 IP 对所有开放端口都会失效。

配置方式是在sshd.local中增加:

[sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 5 bantime = 3600 action = ufw

重启 fail2ban 后,封禁会自动通过 ufw 规则实现。查看:

sudo ufw status

你会看到类似DENY 192.168.1.100的规则。

5.4 SSH 相关的高级加固选项

除了 fail2ban,还有几个纵深防御选项值得启用。

TCP Wrappers 在 Ubuntu 22.04 上已经不再推荐(libwrap 支持正在弱化),不用浪费时间。更现代的做法是用 sshd 自身的Match块做条件控制。

比如,对内网和公网来源区别对待:

Match Address 192.168.0.0/16 PasswordAuthentication yes Match Address * PasswordAuthentication no

这段配置的含义是:来自内网 192.168.0.0/16 的连接允许密码登录,其余来源必须密钥认证。这种场景适合公司内部:同事在内网用密码登录方便,外部访问必须走密钥。

另一个容易被忽视的参数是X11Forwarding。如果你不需要通过 SSH 转发图形界面,建议关掉:

X11Forwarding no

减少不必要的攻击面。同理,AllowTcpForwarding如果不需要端口转发,也建议关:

AllowTcpForwarding no

但注意:如果你用 SSH 做隧道(比如访问内网数据库、代理上网),这个必须保持yes。

5.5 关键文件权限一览

SSH 相关的文件权限如果不对,会出现各种莫名其妙的问题。整理一份权限速查表:

路径权限归属
/etc/ssh/sshd_config644root:root
/etc/ssh/目录755root:root
~/.ssh目录700用户:用户
~/.ssh/authorized_keys600用户:用户
~/.ssh/id_ed25519600用户:用户
~/.ssh/id_ed25519.pub644用户:用户

记住一个原则:私钥文件和 authorized_keys 文件必须是当前用户可读写,其他用户无权限。sshd 对权限敏感的检查非常严格,权限不对宁可拒绝认证也不冒险执行。

6. 实操中常见的坑与排查实录

6.1 改端口后连不上怎么办

这是最经典的事故。场景:你改了Port配置,重启服务,发现连接失败。

排查顺序:

第一步,确认服务状态:

sudo systemctl status ssh

服务是active (running)但连接依然失败,继续往下。

第二步,确认端口监听:

sudo ss -tlnp | grep ssh

确认新的端口是否在监听。

第三步,检查防火墙:

sudo ufw status

大概率是这里的问题——新端口没在 ufw 中放行。解决:

sudo ufw allow 22022/tcp

如果你是在云服务器上操作(比如某云厂商的安全组),还需要去控制台放行新端口。云厂商的安全组规则和系统内防火墙是两层独立的,缺一不可。这个顺序很重要:先改防火墙,再重启 SSH 服务,避免服务重启后新端口被墙住。

6.2 公钥认证失败但密码能登录

这个问题的典型场景是:authorized_keys配置正确,密钥也上传了,但登录时依然提示输入密码。

按以下优先级排查:

  1. 检查~/.ssh/authorized_keys是否存在并且内容正确。
  2. 检查文件和目录权限:
    ls -ld ~/.ssh ls -l ~/.ssh/authorized_keys
    必须分别是 700 和 600。
  3. 检查sshd_config中PubkeyAuthentication是否为yes。
  4. 检查AuthorizedKeysFile路径是否正确,默认值是.ssh/authorized_keys。如果你用了一个自定义路径,比如/etc/ssh/authorized_keys/%u,需要确认那个目录也存在且权限正确。
  5. 查看系统日志:
    sudo tail -n 30 /var/log/auth.log
    日志里会显示Failed publickey for ...、Authentication refused等关键信息。

补充一个冷知识:如果你登录时看到sign_and_send_pubkey: no mutual signature supported,说明客户端和服务端支持的签名算法不匹配。比如服务端配置了PubkeyAcceptedAlgorithms限制了算法类型,而客户端生成的密钥类型不在白名单里。检查sshd -T | grep pubkeyacceptedalgorithms确认。

6.3 连接非常慢,要卡好几秒才让输密码

这种情况通常是 DNS 反向解析导致的。sshd 默认会尝试对客户端 IP 做反向 DNS 解析,如果 DNS 不通,会等超时。

解决方式,在sshd_config中:

UseDNS no

同时建议关闭 GSSAPI 认证(如果不用 Kerberos 环境):

GSSAPIAuthentication no

这两个选项改完后,连接速度会有明显改善。特别是内网环境里没有 DNS 解析条件的机器,效果立竿见影。

6.4 多台服务器批量配置的技巧

如果你有十几台服务器都要做同样的 SSH 加固,一台台操作效率太低。可以写一个简单的脚本配合ssh-copy-id批量处理。比如将公钥批量复制到多台机器:

for host in server1 server2 server3; do ssh-copy-id -i ~/.ssh/id_ed25519.pub "$host" done

再配合 Ansible 或纯 bash 脚本统一修改sshd_config。需要注意:批量操作前先在测试环境验证一遍配置模板,避免因为某台机器环境差异导致批量事故。

6.5 误改配置导致远程连接彻底断了怎么办

最坏的情况:你改坏了sshd_config,服务重启失败,远程连接断开,而且手上没有其他登录方式。这时候只能靠带外管理(比如云厂商的 VNC 控制台、物理机的 iLO/IPMI)进入系统。提前想好这个应急预案是运维的基本素养。

如果把配置改坏了,但服务还没重启,可以先执行sudo sshd -t检查配置语法。这个命令不启动服务,只解析配置。即使当前 sshd 服务已经挂掉,只要你能通过某种方式进入系统(哪怕是救援模式),都能用它定位错误。

7. 一些值得分享的实操心得

最后说几点长期运维下来积累的经验。

配置 SSH 服务一定要养成"先验证、再收尾"的习惯。每次改动配置,都先在新开的终端里测试连接正常,才认为改动成功。这个习惯帮我躲过了很多次把自己锁在门外的尴尬。特别是改端口、改认证方式、加AllowUsers这类操作,宁可多花半分钟开个新终端,也别赌"肯定没问题"。

关于安全策略的粒度,不需要把所有的配置项都调到最严格。比如PermitRootLogin no和密钥登录是必须的,MaxAuthTries 3合理,但有些参数(比如ClientAliveInterval调成 30 秒)反而会影响正常使用。安全配置的目标是"够用且不伤体验",不是越严越好。

公钥的私钥文件建议定期检查。如果你发现某台机器的私钥可能泄露了(比如笔记本丢了、同步了不该同步的目录),立即从所有服务器的authorized_keys中删除对应的公钥,并重新生成一对。不要抱着"应该没人发现"的侥幸心理。

Ubuntu 22.04 的 OpenSSH 默认禁用了 ssh-dss 算法,也默认移除了对 RSA SHA-1 签名的支持。如果你有一些老设备(比如很老的嵌入式设备)需要连接这台服务器,可能需要在sshd_config中显式配置兼容性参数。但除非确有必要,建议优先升级老设备上的 SSH 客户端,而不是降低服务端的安全标准。

SSH 配置看起来参数多,其实核心逻辑很简单:管住谁能进、怎么进、进来了能做什么。把这三点想清楚,配置就有章法了。我在实际配置中始终遵循这个思路推进,虽然过程中踩过改端口忘开防火墙、密钥权限不对导致认证失败、改配置没备份回滚困难这些坑,但每一次趟过去,后面的运维都轻松不少。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 21:59:36

项目标题不完整?补齐这些信息,才能写出高质量技术博文

好的,我明白了。在开始之前,我需要确认一下:您提供的项目标题似乎不完整,只有“rea”这个前缀。为了确保我能精准地挖掘标题背后的核心领域与细节,避免偏离方向,请您补充完整的【项目标题】,并尽…

作者头像 李华
网站建设 2026/10/21 21:58:05

如何构建虚拟AI产品经理:从知识库到Roadmap的完整落地指南

1. 先想清楚:你要的是一套“AI 打下手”的方案,还是一个“数字同事” 我见过太多团队把“引入 AI 产品经理”做成了一件很尴尬的事:买了一堆 AI 工具的会员,让产品经理用大模型写 PRD、生成用户故事、做竞品分析。结果呢&#xff…

作者头像 李华
网站建设 2026/10/21 21:56:23

损失函数从原理到实践:梯度行为、选型策略与调试指南

损失函数这东西,每个做深度学习的都绕不开。无论是训练一个图像分类模型,还是调一个目标检测的工程,你最先盯着的就是那张 loss 曲线。它升了你会慌,它降不下来你会焦虑,它变成 NaN 你就知道今晚又得加班了。但很多人对…

作者头像 李华
网站建设 2026/10/21 21:55:52

普通人抓住大模型风口的四大落地路径与实操指南

1. 先泼一盆冷水,再谈风口看到这个标题点进来的人,多半都在琢磨同一件事:大模型是不是真的能让我翻身?我过去一年花了大量时间研究、试用、落地各种大模型应用,先给个明确判断——风口是真的,但大多数人正在…

作者头像 李华
网站建设 2026/10/21 21:54:42

DeepContext:多轮对话意图漂移的LLM安全实时检测方案

多轮对话里的意图漂移,一直是LLM安全检测里最难缠的问题。单个回合看,每句话都干干净净,但把几轮串起来,攻击者的恶意意图就在对话进程中悄然完成了漂移和组装。我做的DeepContext项目,就是用有状态的实时检测机制&…

作者头像 李华
网站建设 2026/10/21 21:53:52

Visionpro多相机视觉检测框架:从标定到融合的完整实现

1. 项目背景与整体体验概览1.1 为什么需要4相机检测框架做机器视觉的朋友应该都有过这种感受:单个相机的视场范围一旦变大,检测精度就跟着缩水。镜头畸变、边缘模糊、分辨率不足,这些问题会直接把你辛辛苦苦调的检测算法按在地上摩擦。我这次…

作者头像 李华