ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux服务器安全加固:从SSH认证到iptables时间窗规则

Linux服务器安全加固:从SSH认证到iptables时间窗规则

如果你有一台公网可达的Linux服务器,或者只是把实验室的主机暴露到办公网里,22端口迟早会被扫描器盯上。这个IP只要在公网上露头,几分钟内就会出现针对SSH的口令尝试,这是常态,不是运气问题。你给出的这条iptables规则片段,关键词就在-m time这一节:它想用“时间窗”来限制SSH入口的访问,让非业务时段根本不给握手机会。这个思路很对,很多人却卡在规则参数、时区和持久化上。

顺着这条命令聊开,我会把Linux系统安全拆成六个维度来展开:入口认证、网络访问控制、主动封禁、系统基线、文件保护、日志审计。每一块都会给可直接落地的配置和操作步骤,也会把这些年实际操作中踩过的坑一并讲清楚。这篇文章适合刚从“能跑就行”迈向“不想被黑”的开发者、小团队运维,以及所有自己搭服务器的人。

1. 先想清楚:Linux系统安全到底该从哪几个方面做

1.1 攻击者视角下的入侵路径

每当有人问我“Linux系统怎么防攻击”,我都会先让他站到攻击者的角度重新看一遍自己的服务器。

攻击者的路径其实非常固定:先做全端口扫描,找出哪些端口开放了;一旦发现22端口开放,立刻开始SSH暴力破解;如果密码弱,几分钟就能进去;进去之后第一件事就是提权、留后门、清理日志;再往后就是横向移动,拿你这台机器当跳板去碰同网段的其他机器。这套流程已经被各种自动化脚本跑了几百万遍,几乎不需要人工干预。

所以“安全”并不是某一个命令、某一条iptables规则能解决的问题,而是一条完整的防御链。链条上有任何一个环节是空的,攻击者就会从那里钻进来。常见的情况是:有人把SSH密码改得很复杂,却没有关root密码登录;有人把22端口改了,却忽略了其他服务的弱口令;有人装了一堆fail2ban,却忘了系统补丁几个月没打。

1.2 分层防御:从外网边界到数据兜底

理解了攻击路径,防御思路就清晰了。我们把整个系统从外到内看成几道防线,每一道防线负责拦截一类问题。

防线层级典型防护手段主要防什么
网络边界iptables/nftables规则、时间窗、访问来源白名单端口扫描、非授权访问
入口认证SSH密钥、禁止root、口令策略、二次验证暴力破解、弱口令撞库
主动封禁fail2ban、ipset、日志联动脚本高频扫描、持续爆破
系统基线最小化服务、系统补丁、内核参数漏洞利用、服务暴露
文件与进程权限清理、不可变属性、完整性校验篡改文件、植入后门
日志审计syslog、auditd、集中日志掩盖痕迹、恶意操作追溯

这份表格就是整篇文章的地图。后面每一章都是在给这张地图补充能直接使用的配置细节。需要注意的是,分层防御的意思不是把每一层都做满,而是每一层都要有,哪怕某一层很薄,也比没有强。比如网络层规则就两条,也比完全裸奔好一百倍。

1.3 这套思路的适用边界

这套方案主要针对的是中小规模的Linux服务器:个人网站、小团队的自建系统、实验室环境,这些场景的威胁模型是“自动化脚本扫描”和“无差别攻击”,而不是有组织的高级威胁。如果面对的是有明确目标、投入大量资源的高水平攻击者,那需要的远不止这些,还要包括流量检测、蜜罐、值守团队等东西。

另外,安全加固一定要考虑可用性。把服务器锁到连自己都进不去,那不是安全,是事故。所以我在后面的每个小节里都会强调“先保住自己的逃生通道”。这可能是整篇文章最实用的经验之一:任何一次加固操作,都必须在明确“如果失败了我怎么还原”的前提下进行。

2. 入口防线:SSH认证和用户白名单加固

2.1 22端口为何成为爆破灾区

SSH之所以是重灾区,原因很简单:它默认监听在22端口,而且绝大多数服务器都开着它。对攻击者来说,根本不需要猜端口,直接扫22就行。你去看服务器上的/var/log/auth.log或者journalctl -u sshd,里面几乎每天都有大量Failed password记录,大部分来自世界各地不同IP的扫描程序。

这些爆破并不可怕,真正可怕的是“密码”本身。很多人沿用简单密码,比如123456、admin、root这类,扫描器通常拿着一个集成了几万条常见口令的字典,一轮跑下来命中率不低。所以第一件要做的事,不是换端口,而是把“密码登录”这条路直接堵上。

2.2 密钥认证替换密码登录的落地步骤

用SSH密钥替代密码登录,是目前性价比最高的入口加固手段。操作并不复杂,我直接给完整流程。

首先在本地机器(不是服务器)生成密钥对:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 -C "你的备注名称"

参数解释一下:-t ed25519指定密钥算法,Ed25519是目前推荐的现代算法,安全性和性能都优于老式的RSA 2048;-a 100表示做100次KDF迭代,提高私钥的抗暴力破解能力。如果工具不支持Ed25519,退一步用ssh-keygen -t rsa -b 4096也可以,但Ed25519是更好的选择。

然后把公钥传到服务器上:

ssh-copy-id -i ~/.ssh/id_ed25519.pub 用户名@服务器IP

执行这条命令需要输入一次服务器密码,它会自动把公钥写入服务器的~/.ssh/authorized_keys。接下来测试一下纯密钥登录是否成功,确认能登进去之后,再执行后面的密码禁用操作。

2.3 sshd_config 关键参数修改清单

SSH服务的主配置在/etc/ssh/sshd_config。修改之前先备份:cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.日期。然后按下面的清单逐项确认。

参数推荐设置原因
PermitRootLoginno禁止root直接登录,避免root被爆破
PasswordAuthenticationno禁用密码登录,彻底断绝字典爆破
PubkeyAuthenticationyes启用密钥认证,默认就是yes
MaxAuthTries3限制单次连接最大认证尝试次数
ClientAliveInterval300每300秒探测一次客户端状态
ClientAliveCountMax2连续2次无响应就断开连接
AllowUsers指定用户名只允许白名单用户登录,其余一律拒绝
Protocol2只允许SSH 2协议
X11Forwardingno不用图形转发就关闭它
UseDNSno关闭反向DNS查询,加快登录速度并避免DNS故障影响

重点是PermitRootLogin no和PasswordAuthentication no这两项。前者让你日常必须用普通用户登录,再用sudo执行管理操作;后者直接消灭“密码被字典命中”这个可能性。修改完配置后,先做语法检查,再重载服务:

sshd -t systemctl reload sshd

注意我用的是reload而不是restart。reload会平滑重载配置并保留现有SSH会话,restart会断开当前所有连接。如果是远程操作,一次不合时宜的restart可能让你直接失去入口。

2.4 二次验证与最小权限

如果这台机器上跑着重要业务,建议再把二次验证加上。使用基于时间的一次性口令(TOTP)方案,登录时除了密钥,还要输入手机上动态验证码。相关工具主流发行版都有现成软件包,服务端启用后不会太复杂。启用之前一定先确认:手机应用已经绑定成功并生成正确验证码,再修改sshd_config开启认证,否则你有概率把自己锁在门外。

最小权限是另一个容易被忽略的点。日常维护时一律不要用root直接敲命令,而是用一个普通用户配合sudo。在/etc/sudoers.d/下给用户配置权限,尽量只授权需要的命令,而不是笼统给ALL。比如一个用户只需要重启某个服务,那就只授权那一条命令。这样即使某个用户被攻破,攻击者拿到的权限也是受限的。细节就是:visudo检查语法,不会的不要自己手工改/etc/sudoers。

3. 网络访问控制:拆解那条iptables时间窗规则

3.1 逐段看懂标题里的命令

你这条规则片段是-a input -p tcp -m tcp --dport 22 -m time --timest。

我先说一个实战中常见的坑:iptables命令行参数是区分大小写的。如果在命令行上直接执行,追加规则应该写成大写-A INPUT,链名也是大写INPUT。原文里的-a input是小写,严格来说直接敲进去会报错。这种大小写错误在博客文章、聊天记录里非常常见,抄的时候一定要看清楚。

拆开来看,每个片段的意思如下:

  • -m time --timest...:调用time时间匹配模块,配合--timestart和--timestop限定时间段。后面timest明显是参数被截断了,正常应该是--timestart。
  • -p tcp -m tcp --dport 22:匹配TCP协议、目标端口为22的封包。
  • 整条规则的意图就是:只在指定时间段内,允许外部访问SSH端口。

这条命令的思想是对的。但单独一条规则没法用,原因是iptables默认不是“白名单制”。即使你加入了时间窗规则,其他时间依然可以通过其他规则或者默认策略放行22端口。必须配合默认策略和兜底DROP规则。

3.2 拼出一条完整可用的时间窗规则

我直接把常用的完整规则组贴出来,这套规则适合“工作日业务时间开放SSH,其他时间关闭SSH”的场景:

# 默认策略:入站和转发丢弃,出站放行 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # 放行回环接口 iptables -A INPUT -i lo -j ACCEPT # 放行已建立连接和关联连接,这是保命规则 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 时间窗内放行SSH iptables -A INPUT -p tcp -m tcp --dport 22 -m time \ --timestart 09:00:00 --timestop 21:00:00 \ --weekdays Mon,Tue,Wed,Thu,Fri \ --kerneltz -j ACCEPT # 时间窗外,对SSH端口直接丢弃 iptables -A INPUT -p tcp --dport 22 -j DROP

这里有几个关键点。--weekdays可以限制一周内的指定日期;--kerneltz告诉模块使用系统本地时区,否则它会按UTC计算,中国时区会整整偏差8小时。这一点后面单开一节详细说,因为这是最容易翻车的地方。

如果你需要更精准的窗口,还可以用--datestart和--datestop指定绝对日期,用来做“某一段时间临时封锁”或者“假期封禁”非常方便。

3.3 规则顺序与默认策略怎么配合

iptables的规则是从上往下逐条匹配的,命中即停止。所以规则顺序直接决定行为。

最典型的错误是把-A INPUT -p tcp --dport 22 -j DROP放在ESTABLISHED,RELATED规则前面,然后发现服务器上所有已有的SSH连接全部断开。为什么?因为回包不属于ESTABLISHED吗?不对,实际上回包是ESTABLISHED,但DDOS? 我们理一下:你本地SSH客户端连接服务器22端口,从服务器角度来看,进入方向是目的端口22的SYN包,属于NEW状态;而响应出去的SYN-ACK是ESTABLISHED,RELATED?不完全是。实际上SSH连接是TCP,服务器收到SYN后回复SYN-ACK,这属于连接跟踪中的ESTABLISHED的一部分。如果DROP规则在ESTABLISHED之前,连服务器的回包都可能不会被特殊处理?其实对于已建立的连接,因为服务器首次收到SYN时就已经建立连接,后续双向包都是ESTABLISHED,所以对于已建立的SSH连接,入站包目的端口是随机高端口而不是22,所以22端口的DROP不会影响现有SSH连接。但如果你把默认策略改成INPUT DROP,且没有放行ESTABLISHED,RELATED,现有SSH连接也会断,因为服务器要回复客户端,但回复是OUTPUT方向,默认OUTPUT ACCEPT,所以没问题;但是客户端发来的后续入站数据包不是ESTABLISHED?它属于ESTABLISHED状态,如果INPUT DROP且没有放行ESTABLISHED,客户端发来的数据包会被丢弃,连接体验马上就会中断。这就是为什么ESTABLISHED,RELATED是保命规则。无论如何,-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT放在最前面是必须的。

另外,默认策略INPUT DROP请谨慎使用。如果是在远程机器上第一次配置防火墙,建议先不要直接改默认策略,而是把规则一条条加好,用iptables -L -n -v确认,最后再切默认策略。或者使用iptables-apply这个工具:它会加载规则并等待用户确认,超时或确认失败会自动恢复原规则,避免远程操作时把自己锁在外面。

3.4 让规则重启不丢失

iptables规则的实质是内核netfilter框架里的一组运行时配置,重启机器就没了。所以保存规则和配置规则同样重要。

不同发行版有不同做法。RHEL/CentOS系较老的版本有service iptables save,会自动写入/etc/sysconfig/iptables;Debian/Ubuntu系可以安装iptables-persistent,安装时或之后执行netfilter-persistent save保存。但如果你用的是容器、精简系统或者只是想更可控,我建议直接用最原始的方案:

iptables-save > /etc/iptables.rules

然后在开机启动时恢复:

iptables-restore < /etc/iptables.rules

可以用systemd服务或者/etc/rc.local来执行。最简单的做法是在systemd里加一个oneshot服务,但大多数场景下iptables-persistent已经够用。需要留意的是:如果你修改了规则,一定要重新执行一次保存,否则重启后又回到旧规则,排查起来非常令人崩溃。

3.5 最容易翻车的时区问题

time模块默认按UTC处理时间。如果你在国内,本地时间是晚上10点,UTC时间却是下午2点,差8小时。很多人配置了--timestart 09:00 --timestop 18:00,结果早上发现9点了SSH还不能连,晚上却一直开着,就是时区没设置。

解决办法就是加--kerneltz参数,让模块直接使用内核时间,也就是系统当前设置好的本地时区。在多数现代发行版上,--kerneltz是可用且推荐的;如果你的内核或iptables版本不支持,就用--localtz。加了参数之后,规则会严格按照服务器本地时间生效。

还有一个隐藏坑:如果服务器系统时间本身不准,时间窗规则也会错乱。所以要让系统时间保持自动同步。使用systemd的发行版一般自带systemd-timesyncd,也可以装NTP工具。不管用哪个,保证date命令输出的本地时间准确,是一切时间相关规则生效的基础。

4. 主动防御:fail2ban、手动封禁与入口隐藏

4.1 fail2ban 如何自动拉黑攻击IP

时间窗规则能挡住非工作时间的扫描,但工作时间内的暴力破解还是要靠fail2ban这类主动防御工具。它的工作机制不复杂:监听SSH日志文件,用正则表达式识别登录失败的记录,统计每个来源IP在指定时间窗口内的失败次数,一旦超过阈值,就调用系统防火墙把该IP封禁一段时间。

配置起来很简单。安装好之后,在/etc/fail2ban/jail.local里写:

[sshd] enabled = true filter = sshd logpath = /var/log/auth.log backend = systemd maxretry = 5 findtime = 10m bantime = 1h

如果发行版使用systemd日志,logpath可以换成journalctl方式,配置里用backend = systemd即可。参数含义:findtime=10m表示只看10分钟内的记录,maxretry=5表示同一IP失败5次就触发,bantime=1h表示封禁1小时。

启动之后用fail2ban-client status sshd查看封禁状态,能看到当前被拉黑的IP列表。如果某个IP被误伤,用fail2ban-client set sshd unbanip 具体IP即可解除。这里有个小经验:bantime建议设置成-1表示永久封禁,但对于动态IP环境不推荐,因为DHCP用户可能共用IP,一旦被封会影响正常用户访问。1到24小时是比较平衡的选择。

4.2 不用工具也能写封禁脚本

有时候环境不允许装第三方软件,或者你想完全掌控封禁逻辑,也可以自己写一个脚本。核心思路就是从SSH日志里提取失败IP,统计次数,超过阈值就交给iptables封掉。

下面是一个简单的命令链,可以快速列出最近10分钟内失败次数最多的IP:

journalctl -u sshd --since "10 minutes ago" | grep "Failed password" | grep -oE "from [0-9.]+" | awk '{print $2}' | sort | uniq -c | sort -nr

如果某个IP的次数超过你的阈值,可以手动封禁:

iptables -I INPUT -s 该IP -j DROP

封禁之后记得重新保存规则集,否则重启失效。对于大量IP批量封禁的场景,iptables一条条加效率太低,我建议用ipset,先建一个集合,再在INPUT链上引用这个集合,之后只需往集合里加IP即可:

ipset create brute-force iphash iptables -I INPUT -m set --match-set brute-force src -j DROP ipset add brute-force 1.2.3.4

脚本化的完整版比这复杂,要考虑日志轮转、白名单、封禁时间过期自动解封等。如果暂时没有精力维护,老老实实用fail2ban就好,它已经把这些逻辑都处理得很成熟。

4.3 高敏感机器还可以做入口隐藏

对安全级别要求高的机器,还可以考虑“入口隐藏”,也就是把SSH端口藏起来,不让外部扫描器直接发现。扫描器扫到22端口开放会觉得“这有一台机器,尝试破解一下”;扫不到22端口,大概率直接跳过。

入口隐藏比较实用的是“端口敲门”思路:正常情况下,iptables对22端口的所有入站访问都直接DROP;当客户端按特定顺序尝试连接一组端口后,服务器才临时放行该来源IP的22端口访问。iptables自带的recent模块就可以实现,不用装额外服务。

思路如下:访问端口7000登记为“第一步”,访问端口7001登记为“第二步”,然后才允许22端口。这中间还要配合时间限制,避免敲门信号被重放。

但这种方案有代价:所有合法用户都要先执行敲门动作,增加了使用复杂度;recent模块在UDP和TCP混合场景下还有各种边界情况。我的建议是:除非这台机器对外完全不提供服务、只有管理员自己访问,否则优先采用“业务时间窗口+来源IP白名单”,而不是端口敲门。

4.4 主动防御的边界在哪里

一定要清醒:fail2ban、ipset封禁这些手段,本质是“降低攻击速度”,而不是“阻断攻击”。攻击者可以用分布式IP绕过封禁,也可以在你睡眠时间慢慢磨。它们能帮你挡住绝大多数无差别爆破,但挡不住想进的人。

所以主动防御必须和入口认证配合使用。如果你允许密码登录,就算有fail2ban,攻击者也可能在封禁窗口内试出正确密码;如果你把密码登录关了、只用密钥,就算被爆破,对方没有私钥也进不来。我见过不少配置看起来“拉满了”,但开了密码登录,最后仍然被攻破的案例。主次不能颠倒。

5. 系统基线加固:服务、内核与文件三件事

5.1 服务和端口最小化

很多人用的系统是通用发行版,装完自带一堆服务:打印服务、蓝牙服务、各种不需要的守护进程。一台服务器上跑的服务越多,攻击面越大。

检查当前系统有哪些服务是开机启动的:

systemctl list-unit-files --state=enabled

把不认识的、确定用不到的逐一禁用:

systemctl disable --now 服务名

然后看看当前监听端口,确认哪些是对外开放的:

ss -tuln

ss -tuln输出中,0.0.0.0和::表示监听在所有网卡上,127.0.0.1表示只监听本机回环。如果有服务没必要对外监听,就去改它的配置,让它只绑定在回环地址上。例如数据库、缓存这类服务,永远不要监听在公网接口上。这条基线能直接影响你被攻击的概率:监听端口越少,扫描器看到的缝隙就越少。

5.2 内核网络参数与漏洞修复

系统补丁是最容易被忽略但性价比极高的环节。内核漏洞、OpenSSL漏洞、SSH服务的漏洞,一旦有了公开POC,互联网上立刻就会出现扫描脚本。建议保持系统包定期更新:

# Debian系 apt update && apt upgrade # RHEL系 yum update

注意生产环境升级前先做备份或快照,内核升级后一般需要重启才生效,把重启窗口安排在业务低峰期。

内核网络参数建议按需收紧,编辑/etc/sysctl.conf并执行sysctl -p生效:

# 关闭IP转发,防止被当作跳板 net.ipv4.ip_forward = 0 # 关闭ICMP重定向 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 # 忽略广播ping,减少被探测的可能 net.ipv4.icmp_echo_ignore_broadcasts = 1 # 开启反向路径过滤,防止源地址伪造 net.ipv4.conf.all.rp_filter = 1

这些参数的调整不会影响绝大多数正常业务,但能有效减少一部分网络攻击面。修改sysctl同样需要谨慎,有些参数(比如ip_forward)如果服务器本身要做路由转发,就不能直接关掉。逐项确认是否影响现有业务再应用。

5.3 关键文件的权限与不可变保护

文件篡改是攻击者留后门最常用的一步。检查几个关键文件的权限:

ls -l /etc/passwd /etc/shadow /etc/ssh/sshd_config

正常情况下,/etc/passwd对普通用户可读,/etc/shadow只有root可读。如果发现有异常权限,立刻chmod修正。

对变更非常少的文件,可以用chattr +i设置不可变属性。设置之后,即使是root也无法修改、删除、重命名该文件。通常适合锁定的文件包括/etc/passwd、/etc/shadow。但要注意:一旦锁定,后续你想系统性地添加用户、修改密码,必须先用chattr -i解锁,否则操作会报错。对/etc/ssh/sshd_config这类经常调整的文件,我不建议锁,锁了反而给自己添麻烦。

另外,建议建立文件完整性基线。用完整性校验工具记录关键文件的哈希值,定期比对,能在攻击者篡改文件后及时发现。这类工具有的依赖数据库文件,有的可以生成报告发送到远程日志。代价是需要维护基线,并妥善保存初始基线数据,否则攻击者看得到你的基线文件,直接把基线也改了,比对就失去了意义。

5.4 不要一上来就关安全子系统

很多发行版默认带强制访问控制机制,它们会在传统的“用户权限”之外给每个进程、文件打标签,限制进程能访问哪些资源。有些人觉得这东西碍事,装完系统第一件事就是关掉。这是一个非常大的风险决定。

强制访问控制确实是运维新手最头疼的环节之一,因为它经常拦着正常业务不让你跑。但正确的做法不是关掉,而是先切换成宽松模式看日志,找出被拦截的项,针对具体规则做适配,最后再恢复到强制模式。一句话:它可以不“正常工作”,但你不该把它当成敌人。

如果一台机器长期关闭了这套机制,我建议找一个变更窗口,开启强制模式,并准备好回退方案。一旦在强制模式下启动,因为策略主题的拒绝而被干掉的非法访问,恰恰是平时你没注意到的风险点。

6. 常见问题与排查技巧实录

6.1 时间窗规则为何总差8小时

症状:明明配置了9点到18点开放SSH,到了9点还是连不上,晚上反而通了。

排查第一步:看系统时间是否准确。date命令输出本地时间。第二步:查看iptables规则里有没有--kerneltz或--localtz。如果不加,time模块默认使用UTC,你的“9点”在模块内部被理解为UTC的9点,换算成北京时间就是17点。所以“9点没开、傍晚开了”完全符合逻辑。

解决:在时间窗规则中加上--kerneltz,重载规则。然后可以用iptables -L -n -v查看规则命中次数,或者开一个临时端口做对比测试,确认窗口行为符合预期。

6.2 规则全是对的但流量就是不通

常见原因有三个。

第一,规则顺序问题。DROP规则被放在了ACCEPT规则前面,永远轮不到后面的ACCEPT执行。iptables匹配是“先到先得,命中即止”,把宽松的放行规则放在前面,把严格的拒绝规则放在后面。

第二,ESTABLISHED,RELATED没放行。如果默认策略是INPUT DROP,这条缺失会导致所有出站连接的回包进不来,表现为“能主动访问别人,但外部访问你的服务一直超时”。其实本地连接本身也可能出现“SSH连上了但打字回显卡死”的诡异现象。

第三,规则没有持久化。每次重启后规则恢复原状,看起来像“偶尔通偶尔不通”。用iptables-save保存规则到持久化文件,并在开机时恢复。

6.3 重启后防火墙规则被清空

iptables规则存在于内存中,重启即丢失。如果你发现重启后所有规则没了,不是系统出问题,而是没有保存。

解决思路:RHEL系执行service iptables save;Debian系安装iptables-persistent并netfilter-persistent save;或者自己写一个开机恢复脚本。另外,修改规则后养成习惯:测试通过后立刻保存。很多人是在重启之后才想起来“哦我没保存”,但那时候已经晚了。

6.4 SSH配置改错了怎么办

先说预防手段。远程修改SSH配置前,务必先开一个root shell并保持在线,不要关掉当前SSH会话;这次修改后,先开一个新的SSH session验证可以登录,再去关闭旧会话。改完执行sshd -t检查语法,语法通过后systemctl reload sshd。这些动作按顺序执行,能让你大概率不会把自己锁在门外。

如果已经失联了,就需要走“带外”通道:云主机一般有控制台/网页终端,虚拟机可以通过虚拟化管理界面进去,物理机只能靠现场接显示器了。进去后恢复配置备份,或者把sshd_config里改过的项调回来,再systemctl restart sshd。

所以,改配置前备份的文件就是你的救命稻草。我强烈建议备份文件名里带日期,多个历史版本留存,以后排查问题也能对比。

6.5 实战经验速查表

问题可能原因快速处理
SSH时间窗不生效时区差了8小时加--kerneltz,确认系统时间准确
重启后防火墙丢失没保存规则iptables-save持久化,开机恢复
新配置连不上SSHsshd_config有语法错误检查sshd -t,用备份恢复,再reload
fail2ban没有封禁日志路径不对、正则不匹配确认logpath/backend,用fail2ban-client status查看
所有入站连接异常少了ESTABLISHED,RELATED放行把状态放行规则放在最前面
端口扫不到但业务异常服务没监听或防火墙没放行UDP核对ss -tuln与实际规则

这些坑我基本上都亲身踩过一遍。最想强调的一点是:任何加固操作,先想“测试环境验证”、“备份”、“保留逃生通道”这三件事,能过滤掉大多数人为故障。给自己留退路,不是不够专业,恰恰是专业的一部分。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进