首页 / 资讯中心 / 文章详情

Ubuntu 22.04 SSH服务安全配置指南:从密钥登录到fail2ban加固

Ubuntu 22.04 SSH服务安全配置指南:从密钥登录到fail2ban加固 ★ FEATURED ARTICLE
我用Ubuntu 22.04做服务器快三年了前前后后配置过的SSH连接没有上百次也有几十次。这期间踩过的坑——密钥权限不对导致连不上、改了端口忘了云安全组把自己锁在外面、被暴力破解脚本扫到怀疑人生——全都经历过。所以看到SSH服务完全配置指南这个标题我很清楚大家真正需要的是什么不是那种执行几条命令就好了的速成教程而是每一步都讲清楚为什么这样做、出了问题时怎么排查的完整过程。这篇文章我会从最基础的安装开始一路做到安全加固把我在实际运维中验证过、踩过坑、最后稳定运行很久的方案完整分享出来。无论你刚装好一台Ubuntu 22.04想远程登录还是已经在用SSH但觉得心里没底这篇文章都值得你从头看完。1. 为什么说SSH配置跑起来容易跑得安全难很多人的SSH配置经历是这样的装好系统、安装openssh-server、用密码登录一下完事。能用但也就仅此而已了。我在某高校实验室维护服务器的时候接过一个前任留下的系统打开/etc/ssh/sshd_config发现PermitRootLogin竟然是yesPasswordAuthentication也是yes端口还是默认的22。这台机器被暴力破解的日志已经积累了几万条。它显然不是个案互联网上每时每刻都有扫描器在全网扫默认端口配上弱口令的话被入侵只是时间问题。所以我觉得有必要把能用和安全这两件事分开看。这篇文章讲的配置会包含三个层面一是连接层面保证你能稳定、方便地通过SSH远程管理服务器不管是局域网还是公网环境。二是效率层面通过密钥登录、客户端别名配置等手段让你每天的操作不用重复输密码、不用记一堆IP和端口。三是安全层面这是重头戏。禁用root远程登录、禁用密码认证、修改默认端口、设置防火墙、防暴力破解这些措施缺一不可。为什么安全层面这么重要因为SSH是服务器最核心的管理入口一旦它被攻破整台服务器就完全暴露了。而SSH的默认配置在安全设计上相对保守大部分默认值都偏重可用而非安全需要管理员自己动手收紧。安全加固的核心思路其实不复杂。我总结成一句话就是减少暴露面、增加攻击成本、加固身份验证。减少暴露面比如改端口、限制监听地址增加攻击成本比如防暴力破解工具的速率限制加固身份验证比如只用密钥不用密码。后面的所有配置本质上都是围绕这三件事展开的。这个思路明确之后你再看网上的各种加固教程就不会觉得它们是一条条孤立的命令而是能理解每一条命令在整体防御体系中的位置。2. 环境准备从固定IP到SSH服务正常启动先明确一下操作环境。我在本文中的示例统一使用Ubuntu 22.04 LTS刚装好的纯净系统。无论你用的是实体机、虚拟机还是云服务器SSH配置的逻辑都是相通的差异主要在于网络层比如云服务器还涉及安全组。2.1 服务器IP地址的确定与固定SSH是用来远程连接的首先要搞清楚服务器在哪个IP上。如果你在服务器本机上执行ip addr查看当前网卡信息和IP地址。正常情况下你的网卡一般是ens33、eth0或enp1s0下会有一个IPv4地址。如果你是云服务器IP一般是管理控制台里显示的公网IP或弹性IP如果你是企业内网就是网段内分配的静态IP如果你是家庭环境就需要考虑路由器的端口转发。这里有个实际工作中必须提前处理的点尽量给服务器配置固定IP。我见过太多今天能连上、明天连不上的情况查来查去发现是DHCP分配的IP变了。Ubuntu 22.04用的是netplan管理网络配置配置文件在/etc/netplan/目录下如果你需要配置静态IP大致是这样network: version: 2 ethernets: ens33: dhcp4: no addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 223.5.5.5 - 8.8.8.8注意ens33要换成你自己网卡的真实名称IP、网关、DNS也要改成你所在网络的实际情况。配置完成后执行sudo netplan apply然后通过ip addr确认地址是否生效。这一步很多人会跳过觉得反正我每次连之前查一下IP就行。但当你有三五台服务器或者需要配置自动化脚本的时候固定IP的价值立刻就出来了。2.2 安装并启动SSH服务Ubuntu 22.04 Server版默认可能已经装了SSH服务端但Desktop版默认只有SSH客户端没有服务端。确认方式很简单# 查看SSH服务端是否已安装 dpkg -l openssh-server # 如果没有安装执行安装 sudo apt update sudo apt install -y openssh-server安装完成后启动服务并设置开机自启sudo systemctl enable --now ssh注意Ubuntu 22.04中SSH服务的systemd单元名是ssh这和CentOS中叫sshd略有不同。如果你是刚从CentOS迁移过来的同学这一条别搞混了。启动后确认服务状态sudo systemctl status ssh正常情况下会显示active (running)。2.3 防火墙放行与第一次本地连接测试SSH服务默认监听22端口。如果你的系统启用了ufw防火墙Ubuntu默认一般不启用但很多人会开需要先放行SSH端口否则配置好了也连不上# 查看防火墙状态 sudo ufw status # 如果状态是active放行SSH sudo ufw allow ssh # 或者明确放行22端口 sudo ufw allow 22/tcp我的习惯是无论防火墙开没开都把这条命令执行一遍养成顺手放行的习惯防止后续开防火墙的时候把自己锁出去。然后是本地连接测试。很多人会直接拿另一台机器连服务器一旦连不上就开始瞎折腾。我建议先在服务器本机测试一下服务是否正常运行# 在服务器上执行 ssh localhost如果本机能连上说明SSH服务本身没问题剩下的问题就在网络层或客户端配置。如果本机连不上说明服务端配置有误可以优先排查。2.4 客户端连接前的基本准备如果你用的是Windows 10/11系统自带的OpenSSH客户端基本够用。打开PowerShell或终端执行ssh 用户名服务器IP第一次连接会提示确认主机指纹输入yes回车即可。如果你是Mac或Linux操作方式完全一样。如果是初次使用SSH建议先确认服务器上用来登录的用户存在并且知道密码。Ubuntu 22.04安装时创建的那个用户默认是可以登录SSH的对普通场景来说这就够了。但我强烈建议不要在root用户下直接做后面的安全加固而是用一个普通用户配合sudo来操作。这里我想提前说明很多人从头到尾都是在root用户下配置SSH导致后面启用禁止root登录后管理变得别扭。最佳实践是创建一个普通用户赋予它sudo权限用这个用户做日常管理。如果你还没有这样的用户可以用下面命令创建sudo adduser yourname sudo usermod -aG sudo yourname后续所有配置操作都用这个用户来执行。3. 密钥登录把每天输入密码这件事彻底终结密码登录本身没有错但在实际使用中它有两个绕不开的痛点一是容易被暴力破解二是当你管理多台服务器时记住一堆密码本身就是负担。密钥登录可以同时解决这两个问题。3.1 SSH密钥认证的工作原理SSH密钥认证基于非对称加密。简单来说它有一对钥匙一把公钥和一把私钥。公钥可以放在服务器上私钥自己保管。连接时服务器用你的公钥加密一个随机挑战发给客户端客户端用私钥解密后返回给服务器。因为私钥只在你手里所以只有持有匹配私钥的人能通过验证。这个机制类比一下就是公钥是一把锁任何人都能看到这把锁但钥匙只有你有。服务器拿锁来验证你——你能打开锁说明你就是主人。在Ubuntu 22.04上生成密钥对执行ssh-keygen -t ed25519 -C yournameyourhost参数说明-t ed25519指定密钥类型。ed25519是目前推荐的非对称加密算法安全性高、性能好、密钥长度短。-C给密钥加一个注释通常写用户名主机名的格式方便识别。执行后它会问你要保存到哪里默认是~/.ssh/id_ed25519直接回车即可。接着会提示设置私钥的passphrase口令短语我建议一定要设置。关于passphrase很多人觉得麻烦就不设置。但我的看法是私钥文件是明文存储的一旦泄露别人就能直接使用。设置passphrase相当于给私钥再加一道保险即使文件泄露攻击者没有口令也无法解开密钥。以后每次连接时需要输入一次私钥口令配合SSH-Agent工具可以只在会话开始时输一次。3.2 把公钥部署到服务器生成密钥对之后需要把公钥内容追加到服务器的~/.ssh/authorized_keys文件中。有三种做法第一种如果你已经能通过密码登录服务器可以直接用ssh-copy-id命令最推荐ssh-copy-id -i ~/.ssh/id_ed25519.pub 用户名服务器IP它会自动把公钥追加到服务器的authorized_keys并处理好目录权限。第二种手动追加。cat ~/.ssh/id_ed25519.pub | ssh 用户名服务器IP mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys第三种如果服务器上还没有~/.ssh目录用第二种方式的时候顺便就创建了。注意目录权限必须严格~/.ssh目录权限是700authorized_keys文件权限是600。权限过于宽松会导致SSH直接忽略这个文件这是新手最常见的坑之一。3.3 验证密钥登录并关闭密码认证公钥部署完成后在客户端测试ssh 用户名服务器IP如果一切正常会直接登录成功或者提示输入私钥的passphrase不再询问系统用户密码。确认密钥登录没问题之后再关闭密码认证。这一步的先后顺序很重要——必须先确保密钥登录可用再关闭密码登录否则你可能会把自己锁在服务器外面。编辑SSH配置文件sudo vim /etc/ssh/sshd_config找到对应行并修改PasswordAuthentication no PubkeyAuthentication yes我强烈建议在修改完配置后先执行sudo sshd -t检查配置语法确认无误再重启服务sudo sshd -t sudo systemctl restart ssh重启后在当前会话别忙着断开另外开一个终端窗口测试一下能否正常登录。确认没问题再关掉当前窗口。这一条经验来源于我早年的一次惨痛教训当时我只关掉了密码认证却忘了检查密钥权限重启后新窗口直接连不上幸好老会话还在才没有彻底锁死。所以这里也分享给各位任何时候改动SSH配置一定保留至少一个已建立的会话再验证新会话能连接。3.4 用SSH-Client配置管理多台服务器当你管理的服务器超过一台之后最烦的就是记IP、记端口、记用户名。SSH客户端的配置文件可以帮你解决这个问题。在客户端机器的~/.ssh/config下创建配置文件格式如下Host myserver1 HostName 192.168.1.100 User yourname Port 2222 IdentityFile ~/.ssh/id_ed25519 Host myserver2 HostName yourdomain.com User admin Port 22022 IdentityFile ~/.ssh/id_ed25519配置好之后连接时只需要ssh myserver1它会自动读取对应的主机名、用户名、端口和密钥文件。在你管理的人多了之后这个文件的便利性远超预期而且能有效避免不同服务器、不同端口、不同用户名之间的记忆混乱。4. 安全加固实战把默认配置一步步调到生产可用级别如果你只是在自己家里或内网测试环境玩做到密钥登录可能就够了。但只要服务器暴露在公网或者承载了稍微重要一点的业务加固就没有商量余地。这一节的内容是重中之重每一部分我都配了为什么这么做的理由。4.1 修改SSH默认端口简单却有效的第一道障眼法默认22端口是安全扫描器的头号目标。修改端口并不能从根本上提高安全性但它能让绝大多数批量扫描脚本扫描不到你大幅降低被针对性攻击的概率。修改方法编辑/etc/ssh/sshd_configPort 2222端口范围可以从1024到65535。我建议选择一个相对冷门但不影响记忆的端口比如23456或者你自己的某个纪念日数字。注意不要选0-1023之间的特权端口因为那需要更复杂的权限管理。改完端口后如果开启了防火墙还要放行新端口sudo ufw allow 23456/tcp如果你之前放行了22端口建议先保留等确认新端口能正常连接后再删除旧规则sudo ufw delete allow 22/tcp云服务器用户务必记得在云控制台的安全组里同步放行新端口。我在这里栽过跟头——本地防火墙放行了但云安全组没放行结果新端口永远连不上差点以为服务没起来。如果你在改端口后连接超时而不是拒绝连接优先怀疑安全组。4.2 禁止root用户直接SSH登录直接禁止root通过SSH登录是安全基准要求。不管在任何情况下,让root以SSH方式登录都是高风险行为root拥有系统全部权限一旦被突破等于整台服务器直接沦陷。更合理的方式是通过普通用户登录需要提权时再用sudo。在/etc/ssh/sshd_config中设置PermitRootLogin no修改完成后执行sudo sshd -t检查语法然后sudo systemctl restart ssh并用普通用户验证能正常登录。4.3 关闭密码认证把唯一入口换成不可被猜测的密钥前面已经提到过在验证密钥登录可用后关闭密码认证。在加固语境下这一步是杜绝暴力破解的最终手段。即使攻击者知道了你的用户名没有私钥文件也完全无法登录。配置如下PasswordAuthentication no KbdInteractiveAuthentication no注意Ubuntu 22.04默认可能启用了KbdInteractiveAuthentication如果只关PasswordAuthentication某些版本的SSH还是会通过键盘交互方式接受密码登录。首次配置时确认这两行都要设置为no。如果你使用公网服务器做完这一步几乎可以立刻感受到差别——日志里的暴力破解尝试会大幅减少因为密码认证本身已经被禁用攻击者连试密码的机会都没有了。4.4 限制登录用户和会话空闲时间加固到一定程度后可以进一步缩小攻击面。比如只允许特定的用户通过SSH登录AllowUsers yourname otheruser只有列出的用户可以SSH登录其他用户即使有正确密码和密钥也无法进入。这在多人共用的服务器上尤其有用。再比如设置空闲超时时间。很多人习惯开着SSH窗口不关这就给了会话劫持的机会。我习惯设置ClientAliveInterval 300 ClientAliveCountMax 2意思是每300秒向客户端发送一次检查消息连续2次没有收到回应就断开连接。这样闲置超过10分钟后服务器会自动踢掉无响应的空闲会话。4.5 与防火墙配合限制来源IP如果你的服务器只面向固定IP段提供服务比如公司办公网的运维人员可以在防火墙层限制SSH的源IP这比任何软件配置都更直接有效。UFW命令示例sudo ufw allow from 192.168.1.0/24 to any port 23456 proto tcp这行规则只允许192.168.1.0/24这个网段的机器访问SSH端口其他所有IP一律无法触达。在安全设计里这叫网络层白名单和SSH配置的应用层白名单形成了纵深防御。但注意如果你的办公IP不是固定的比如经常切换网络不要轻易加这条规则否则你人在外面就连不上服务器了。我自己吃过这个亏限制完来源IP后出差时手机热点完全连不上只好求助同事帮忙解禁。所以加这条规则前务必确认你的访问场景。4.6 防暴力破解工具fail2ban的安装与配置就算关了密码认证SSH服务的日志里可能还是会有大量Failed password记录——这些是扫描器在撞用户名。fail2ban是一个很好的防护层它会监控日志发现多次失败尝试后自动封禁来源IP并在一段时间内拒绝该IP的所有连接。安装sudo apt install -y fail2banUbuntu 22.04安装后默认会启动服务。它的核心配置在/etc/fail2ban/jail.local如果没有这个文件就新建[DEFAULT] bantime 1h findtime 10m maxretry 5 [sshd] enabled true port ssh,23456参数含义bantime封禁时长1小时。findtime统计窗口10分钟内。maxretry这个窗口内最多允许5次失败超过就封禁。port保护的服务端口或名称。enabled启用该jail。配置完成后sudo systemctl restart fail2ban sudo systemctl status fail2ban验证是否生效sudo fail2ban-client status sshd正常情况下会显示当前被封禁的IP列表。你可以故意用错误密码登录几次再查看状态确认封禁逻辑是否工作。我实际观察过一台公网服务器如果什么都不配置一天可能有几百到上千次扫描尝试配上fail2ban之后前期封禁速度很快后面稳定期每天的尝试量骤降。它是性价比极高的安防投入。4.7 SSH配置文件的最终形态示例把上面各项配置汇总我当前的/etc/ssh/sshd_config关键部分长这样非默认行均有注释说明Port 23456 PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no AllowUsers yourname ClientAliveInterval 300 ClientAliveCountMax 2 MaxAuthTries 3其中MaxAuthTries 3限定单次连接最多尝试3次认证超过直接断开。对于使用密钥登录的我们来说这不会造成困扰但能进一步限制暴力破解的尝试窗口。强调一遍改完任何配置先sudo sshd -t检查语法再sudo systemctl restart ssh然后新开一个终端验证登录成功后再关旧会话。这套习惯能保证你再也不会把自己锁在门外。5. 连不上排查实录把踩过的坑完整走一遍配置完SSH之后遇到连不上的情况几乎是必然的。新手容易慌老手会按顺序排查。下面这两个场景是我自己在实战中踩过、又帮别人排查过很多次的典型问题。5.1 密钥文件权限问题最常见的配置正确但连不上有位一起做项目的同学遇到的情况是这样的密钥配置完ssh-copy-id也跑完了但连接时报Permission denied (publickey)。排查过程我写在这里。先在服务器上查看日志sudo tail -50 /var/log/auth.log日志里通常会有一行关键的提示Authentication refused: bad ownership or modes for directory /home/yourname/.ssh这就是典型的目录或文件权限错误。SSH对~/.ssh目录和authorized_keys文件的权限极其敏感——如果这些位置对其他用户也可写SSH会直接拒绝使用密钥认证。修复命令chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys注意不只是当前用户目录下的.ssh如果你登录的是普通用户普通用户的.ssh目录权限也要检查。还有一个容易忽视的地方服务器上用户的家目录权限也不应过于宽松。如果/home/yourname的权限是777同样会导致认证失败。正常应该是755或700。5.2 新端口连不上但旧端口正常安全组和防火墙双重排查这是个非常典型的高级坑。场景是我把端口改成23456后用新端口连服务器始终超时换回22端口反而正常。这时候SSH服务本身肯定是正常的问题出在端口被网络层挡住了。排查顺序是第一步本地防火墙。在服务器上执行sudo ufw status确认23456/tcp是否有放行规则。如果没有执行放行。第二步云安全组。如果你用的是云服务器登录管理控制台找到安全组或防火墙规则检查入方向规则是否允许TCP端口23456。这一步和本地防火墙是并列的关系——只要有一条拦截连接就通不了。第三步监听地址确认。在服务器上执行sudo ss -tlnp | grep sshd确认服务监听的是0.0.0.0:23456所有接口还是127.0.0.1:23456仅本机。如果是后者说明配置里可能设置了ListenAddress 127.0.0.1需要删掉或改成0.0.0.0。第四步如果你本地网络环境复杂比如公司出口NAT还要确认你没有限制来源IP。我在4.5节提醒过的那条来源IP白名单规则也可能成为排查盲区。以上四步不是瞎猜而是按网络栈从底到顶排查的合理顺序。每次遇到新配置连不上的情况按这个顺序走一遍基本都能找到原因。5.3 如何在已断开的情况下紧急恢复SSH连接写到这里我觉得必须提一下备份通道。再严谨的人也有失手的时候——比如你误删了authorized_keys或者sshd_config写错某个参数导致服务无法启动。我的建议是操作前务必备份关键文件sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak-$(date %F)如果配置改坏了可以用U盘启动盘或服务器的VNC/管理终端云服务器控制台有远程连接功能进入系统把备份文件恢复回来再重启SSH服务。这个备份成本极低但关键时刻能救命。云服务器用户尤其要养成这个习惯——因为你一旦关了密码认证又没保存好密钥自己手里的钥匙丢了后果就是联系客服重置或者走紧急登录通道非常耽误事。5.4 日志是排查的第一语言遇到任何SSH连接问题不要靠猜直接看日志。Ubuntu 22.04的认证日志在/var/log/auth.log。几个高频操作# 查看最近认证相关日志 sudo tail -100 /var/log/auth.log # 实时监控日志一边连接一边观察 sudo tail -f /var/log/auth.log # 查看服务启动错误 sudo journalctl -u ssh --since 5 minutes ago日志里会明确写出拒绝的原因可能是公钥不匹配、权限错误、用户被禁用、来源被防火墙拦截等。排查速度比瞎猜快十倍。6. 配置清单与我的日常使用习惯经过上面的配置你的Ubuntu 22.04服务器SSH应该已经达到了生产可用级别。最后整理一份我实际使用的配置清单以及几个我自己坚持多年的使用习惯。6.1 一份可直接对照的配置清单配置项推荐值作用端口非默认高位端口如23456避开批量扫描PermitRootLoginno禁止root远程登录PubkeyAuthenticationyes启用公钥认证PasswordAuthenticationno关闭密码认证KbdInteractiveAuthenticationno关闭键盘交互认证AllowUsers指定用户名限制可登录用户ClientAliveInterval300空闲检测间隔MaxAuthTries3限制认证尝试次数fail2ban启用sshd保护封禁暴力破解来源IPUFW防火墙只放行必要端口网络层过滤每次都照着这个表格检查一遍基本可以放心把服务器暴露在公网环境中。6.2 客户端机器的私钥管理与备份私钥是你登录服务器的唯一凭证丢了等于钥匙丢了。建议一是给私钥设置passphrase。这是最简单也最有效的保护措施。私钥文件如果没设置passphrase一旦被拷贝走就完全暴露了。设置了的话攻击者拿到文件还要破解口令。二是考虑使用硬件密钥或安全管理工具。如果你管理的机器多推荐把私钥放到独立的密码管理工具里或者系统自带的钥匙串这样既能保证加密存储也能在多台机器之间同步。三是备份私钥要谨慎。私钥的备份不要放在云端、网盘等位置明文存储。合理的做法是加密压缩后存放在安全介质里或者使用密码管理工具统一保管。6.3 定期检查SSH服务和日志其实到了配置稳定的阶段日常要做的事情非常少。我一般会每隔一两周看一次认证日志和fail2ban状态确认没有异常封禁或可疑登录成功记录。# 查看最近登录记录 sudo last # 查看当前登录用户 who # 检查最近认证日志 sudo tail -100 /var/log/auth.log如果这些日志里出现来源不明的登录成功记录需要立刻警觉。6.4 最后想对你说的SSH配置是一件前面做扎实后面零操心的事情。稳定后的服务器我甚至几个月都不会碰一次SSH配置只需在需要登录时输入私钥口令即可。对比早年间密码登录时代的提心吊胆现在的体验舒服太多了。如果你是从零开始配置Ubuntu 22.04服务器就照着这篇文章一步一步来。过程中遇到问题先保留已有会话再检查日志。只要把第4节的安全加固做完整你的服务器就已经比网络上绝大多数默认配置的机器安全了一大截。剩下的就是享受远程管理的便利了。我在实际操作中还有一个小心得配置完成后把这份配置清单保存成一个Markdown文件放在本地每台新服务器我都是照着它快速配置一遍大约十分钟就能完成从装机到加固。随着你管理的机器变多这种标准化流程带来的收益会越来越明显。
阅读完成 · 觉得有帮助?
咨询建站