Linux安全加固实操:SSH防护、防火墙配置与日志审计
干了这么多年 Linux 运维我见过太多“裸奔”的服务器SSH 跑在默认 22 端口、root 密码简单得离谱、防火墙该开的不该开的全开着、日志几个月没人翻。说实话每次看到这种状况我都后背发凉因为中招往往不是运气问题而是时间问题。Linux 网络安全这个事说大可以很大说小其实也小主要是把基本功做扎实。这篇文章我从一个运维老兵的角度把 Linux 系统在网络层面最容易挨打的点挨个梳理一遍同时给出一套自己能直接抄作业的加固流程包括账号管理、SSH 防护、防火墙配置、日志审计、异常流量排查这些核心环节。不管你是刚接手第一台服务器的新手还是在公司扛着几十台机器运维压力的老手我相信这篇文章里都有能用得上的东西。1. 先搞明白这台机器容易挨什么打攻击面梳理1.1 第一步永远是画一张“暴露面”地图很多人拿到一台服务器就开始装环境装完就上线跑业务但从来没问过一个问题这台机器到底对外开了什么口子我习惯在接手任何一台 Linux 机器时先执行一条命令ss -tlnp这条命令会列出当前所有处于监听状态的 TCP 端口以及对应的进程。看到的输出会让你意外很多时候你以为是“干净”的机器实际上跑着一些你都快忘了的服务。比如某个实验用的后端服务端口 8080 还开着MongoDB 的 27017 还裸露在公网Redis 默认配置允许任意来源访问。拿到端口列表以后再对照防火墙规则看一遍确认这些端口到底是只在内网可见还是真的暴露到了公网。如果你手头有扫描工具也可以从一台外部机器对自己做一次合法扫描来交叉验证。这里的重点是搞清楚你网络边界上开了哪些口子才能知道该堵哪里。除了端口还有几个地方容易被忽略网卡上是不是绑定了多余的 IP会不会有某个服务监听在 0.0.0.0 上导致内网服务被公网直接访问。这些都要在画暴露面地图的时候一并检查。画完地图建议整理成一张简单的表每一行是一个服务、端口、协议、是否需要对公网开放、负责人是谁。别小看这张表它是后面做防火墙策略、安全审计的重要依据。1.2 常见攻击路径和我踩过的坑暴露面清楚了接下来要站在攻击者的角度想如果你是坏人你会从哪个口子进来我这些年实际处理过的攻击事件归纳下来无非下面几条路。第一条也是频率最高的是 SSH 暴力破解。只要服务器把 22 端口暴露在公网扫描器几乎是全天候在尝试账号密码。我之前检查过一台机器的登录日志一天之内就有上万条失败记录来源 IP 遍布全球其中很多是同一个僵尸网络在扫。这类爆破不一定每一次都能成功但只要你的密码稍微弱一点字典跑一遍就进去了。第二条路径是对暴露的高危端口直接攻击。比如 Redis、Docker API、Elasticsearch 这类服务如果配置不当且直接暴露在公网就成了攻击者的“提款机”。曾经有同事的 Redis 没设密码也没绑定内网地址结果被写入 SSH 公钥直接登录到了服务器。这个案例我印象极其深刻所以之后凡是有这类服务的机器我都强行要求先做访问控制再上线。第三条路径是漏洞利用。Web 应用层的问题不在 Linux 系统本身但系统层面的服务也经常有漏洞比如 OpenSSH 的一些历史 CVE、内核权限提升漏洞、Web 服务器中间件漏洞。这类问题比较考验日常更新的纪律性不更新就是在赌。第四条路径是供应链污染。从第三方源下载软件包的时候如果源被污染或者中间被人动手脚装上去的东西本身就是个后门。在国内环境里很多人习惯直接改镜像源但改完之后从来不校验签名这也是个隐患。理解了这些路径后面的加固动作才有针对性。安全不是做一步看一步而是从攻击者的整个链条上堵住每一个环节。2. 从账号和 SSH 开始加固最便宜也最有效2.1 SSH 登录防护堵住最常被敲门的那扇门SSH 是 Linux 服务器最常用的远程管理入口也是最常被爆破的服务。加固 SSH优先级一定是最高的而且成本极低。先说最彻底的一步禁止 root 用户直接远程登录。root 是所有攻击者最想要的目标账号因为只要拿到 root整台机器就完全沦陷。禁止 root 远程登录之后攻击者必须先破解一个普通用户再通过后续手段提权难度和可追溯性都会好很多。接着是把密码登录关掉只保留密钥登录。密钥登录使用的是非对称加密私钥只保存在你本地暴力破解基本无从下手。我在生产环境里已经全面禁用密码登录只留下密钥这个口子。配置在 /etc/ssh/sshd_config 文件里核心内容如下# 禁止 root 直接远程登录 PermitRootLogin no # 只允许密钥认证 PasswordAuthentication no PubkeyAuthentication yes # 如果启用了 PAM也要确保它不会重新放开密码认证 UsePAM yes # 设定空密码用户禁止登录 PermitEmptyPasswords no改完之后先用sshd -t检查语法再执行systemctl restart sshd。这里必须提醒一句改 SSH 配置前一定确保当前已经成功登录且密钥有效或者你有带外管理权限。否则一旦密码认证被关掉而密钥又没配好你可能会进不了机器。我见过不止一次有人先改了配置重启 sshd才发现密钥根本没用结果把自己锁在门外。另一个常见疑问是“要不要改 SSH 端口”。改端口本质上只是减少被扫到的概率不是安全手段但确实能显著减少日志里那些无聊的爆破尝试。我一般会把 SSH 端口改成一个高位端口再配合 Fail2ban 做动态封禁。注意改端口的时候同样要先放行新端口、测试通过后再停掉旧端口否则机器就真连不上了。2.2 最小权限普通用户加 sudo 白名单关闭 root 远程登录之后意味着日常管理和操作都要通过普通用户完成。这引出一个问题普通用户的权限怎么控制才能既不耽误干活又不至于失控我的原则是做最小授权。日常工作一律用普通用户登录只有在必要时才通过 sudo 提权。sudo 也不是全命令放行而是尽量细化到具体的命令白名单。sudo 的配置存放在 /etc/sudoers 文件推荐用visudo命令编辑因为它会在保存前做语法检查。常见的做法是把运维用户加入 wheel 组这样他们在需要时可以执行 sudo 命令。但是对于更敏感的机器我会单独配置命令白名单比如# 允许某用户执行 systemctl 管理服务但禁止修改 sudoers Cmnd_Alias SERVICE_MGMT /usr/bin/systemctl list-units, /usr/bin/systemctl status user1 ALL(ALL) NOPASSWD: SERVICE_MGMT每一步提权操作审计日志里都会留下记录谁在什么时间以什么身份执行了命令后续都能追溯。账号这块还有一个很容易被忽略的安全点检查有没有多余的、权限过大的账号。定期看一下 /etc/passwd 文件排查有没有 UID 为 0 的用户。UID 0 意味着超级用户权限普通用户如果 UID 0他就拥有了和 root 一样的能力。这条命令我每次巡检必跑awk -F: $3 0 {print $1 : $3} /etc/passwd正常情况结果里应该只有 root 一行。如果多出任何其他账号几乎可以断定是被入侵了。另外长期不用的僵尸账号要及时禁用用usermod -L锁定账号或者删除。密码策略也值得看一眼虽然现在密钥登录是主流但系统里总有一些服务账号还在用密码给它们设一个合理的最小修改周期和复杂度要求能减少一部分风险。3. 防火墙层级的门神从 iptables 到 nftables3.1 为什么别再裸配 iptablesLinux 网络安全的另一个重头戏是防火墙。早年大家习惯直接操作 iptables但说实话手写 iptables 规则维护起来很痛苦几条链的顺序稍微一乱可能就连不上机器了。我自己踩过这种坑特别是在规则很多的时候排查问题就是地狱模式。iptables 是内核 netfilter 框架的传统前端语法是分成 INPUT、OUTPUT、FORWARD 几条静态链来配置的规则顺序极其敏感一条 ACCEPT 放错位置在 DROP 后面效果就完全不对了。这些年我强烈建议新部署的机器直接用 nftables也就是新一代的 netfilter 前端框架。它的语法更接近人类的阅读习惯支持规则集原子替换还允许你像写脚本一样把规则组织成表格和链理解和维护成本都低很多。如果你不想手写规则发行版自带的 firewalld 其实也够用。它把 nftables 包装成更友好的命令用 zone 的概念来管理不同信任级别的网络区域。对于绝大多数业务场景firewalld 是绰绰有余的。我通常在快速部署的服务器上用防火墙管理命令在需要精细控制流量模型的核心机器上直接写 nftables 配置文件。3.2 一套可落地的 nftables 配置模板下面给一个我自己常用的 nftables 配置模板思路很简单默认策略就是丢弃入站流量只放行明确需要的服务。这跟很多人习惯的“默认全放有问题再堵”正好相反但只有默认拒绝才能真正兜底。配置文件在 /etc/nftables.conf基础内容大概长这样#!/usr/sbin/nft -f flush ruleset table inet filter { chain input { type filter hook input priority filter; policy drop; # 放行回环接口 iif lo accept # 放行已建立连接和关联连接这是关键 ct state established,related accept # 放行 ICMP但可以加一点速率限制 ip protocol icmp icmp type echo-request limit rate 5/second accept # 放行 SSH 服务端口这里假设是 2222 tcp dport 2222 accept # 放行 Web 服务 tcp dport { 80, 443 } accept # 来自内网网段的流量放行 ip saddr 192.168.0.0/16 accept } chain output { type filter hook output priority filter; policy accept; } chain forward { type filter hook forward priority filter; policy drop; } }这段配置的含义是默认丢弃所有从外部进入的新连接但允许回环、已经建立的连接、以及指定的服务端口。这里重点解释两个细节。第一个是ct state established,related accept这一条。没有它你会发现很多正常的响应包回不去因为 TCP 连接是双向的入站请求进来之后出站的响应属于 established 状态必须在入站方向放行。漏掉这条是新手最容易犯的错表现为“服务明明在监听但就是连不上”。第二个是 ICMP 速率限制。很多人为了防 ping 直接禁掉所有 ICMP但这样做其实会给排障带来麻烦因为网络连通性测试都做不了。更合理的做法是限制频率既能防止被用来做流量放大攻击又保留了排障手段。加载配置前先确认本机已经有一条可用的放行规则最好是从另一个会话或者另一台机器测试访问。用nft list ruleset查看当前规则用nft -f /etc/nftables.conf重新加载。 我每次改防火墙都严格遵守一个原则先开新窗口测试还能不能连上确认没问题再关掉旧窗口。不要给自己留“裸奔”的窗口期。另外如果机器上还跑着 DockerDocker 会在 iptables 里动态插入自己的 DNAT 规则firewalld 的规则经常被它绕过。这是一个老话题了我的建议是尽量把对外暴露的容器端口控制在明确范围内并且保证宿主机的防火墙策略仍然生效不要让 Docker 自己把端口全部映射到公网。4. 监控和审计看出问题、抓住证据4.1 日志是案发现场加固做得再好也不可能 100% 拦截所有攻击。所以在防御之外监控和审计是另一根拐杖。Linux 系统日志是排查安全问题的最佳起点。多数发行版把系统日志放在 /var/log/和网络、登录相关的关键日志主要是这几个/var/log/messages系统整体事件包含网络、服务状态等/var/log/secure登录认证记录SSH 爆破的案发现场/var/log/cron定时任务执行日志排查后门时会用到/var/log/firewalld 或 nftables 相关日志防火墙拦截记录如果你的系统使用 systemd那么journalctl可以把很多分散的日志统一检索。我常用的几条是# 看最近 1 小时的所有日志 journalctl --since 1 hour ago # 只看 SSH 服务的日志 journalctl -u sshd # 看所有失败的登录尝试 journalctl | grep Failed password不过要提醒一句journald 的日志默认存在内存环形缓冲区里重启后很大概率会丢失。生产环境建议把持久化打开在 /etc/systemd/journald.conf 里设置Storagepersistent。日志量大的机器别忘了做日志轮转否则/var/log会被一波日志打爆磁盘满了以后服务会莫名挂掉。默认的 logrotate 配置一般够用但如果你加大过日志级别最好检查一下轮转策略和时间间隔。4.2 Fail2ban 和 tcpdump防与查日志看多了以后人不可能 24 小时盯着屏幕所以自动化封禁工具就很有必要。Fail2ban 的基本逻辑是去读日志文件统计匹配规则的失败次数超过阈值就把来源 IP 加入防火墙封禁名单过一段时间再自动解除。Fail2ban 的配置一般写在 /etc/fail2ban/jail.local 里覆盖默认配置。我常用的一个 SSH 防护配置类似这样[sshd] enabled true port 2222 filter sshd logpath /var/log/secure maxretry 5 bantime 3600 findtime 600这几个参数的意义是在 10 分钟内findtime600同一来源 IP 的失败次数达到 5 次maxretry5就封禁 3600 秒bantime3600。数值可以根据业务情况调整但不要设得太极端比如 1 次失败就封几个小时反而有可能把正常用户误伤。除了防爆破日常排障也离不开抓包工具。tcpdump 是服务器上排查网络流量最直接的工具它能把网卡上跑的原始数据包dump出来基于协议、端口、IP 做过滤分析。比如你想确认某个端口到底有没有外部流量进来tcpdump -i eth0 -n tcp port 8080 -c 100这条命令抓取网卡 eth0 上端口 8080 的 TCP 流量-c 100表示抓 100 个包就自动停止。如果你想在发现外发流量异常时快速确认是不是被植入挖矿程序可以按目的 IP 维度看连接数netstat -an | awk {print $5} | cut -d: -f1 | sort | uniq -c | sort -rn | head -20把抓到的数据和系统日志结合起来看很快就能定位异常连接的目标地址、对应进程、以及进程启动方式。5. 常见故障与排查经验速查表5.1 加固完连不上服务器救回访问的几条路这个话题很尴尬但必须写因为几乎每个人都至少经历一次改完防火墙或者 SSH 配置回车一敲连接断了然后心里一凉。最优先的救援通道是带外管理比如云控制台里的 VNC、救援模式。如果你用的是物理机那就只能靠 IPMI 或者串口。这类途径不受操作系统网络栈影响可以用来临时改配置。如果带外也用不了还有一个办法是趁防火墙规则还没持久化直接重启机器。因为有些发行版的 nftables/iptables 规则没有使用 systemd 服务自动加载重启后会回到空规则状态这样你就有机会重新登录了。不过我强烈建议不要依赖这个办法因为如果规则已经写成持久化配置重启后照样加载。关键还是预防不要在生产环境高峰时段改防火墙改之前先在本地保存一份已知良好的配置永远保留一个“后门”窗口。现在我连远程服务器都是开两个SSH会话一个专门用来改另一个只用来保底测试改完确认新会话能连接了才断开保底的那一个。5.2 被暴力破解后的处置流程如果你的 SSH 爆破已经成功了也就是说日志里能看到“Accepted password”的记录来源 IP 又不是你自己那这台机器基本可以判定失陷。这时候最忌讳的是手忙脚乱地乱删文件应该按流程来。第一步先隔离。把机器的外网访问断掉或者至少在防火墙上把可疑来源 IP 封掉。已经建立的异常会话也要强制踢掉用pkill -9 -u处理可疑账号或者直接结束相关进程。第二步收集证据。保存 /var/log/secure、/var/log/messages、/var/log/wtmp、/var/log/btmp 这些日志的副本先不要清理方便后面溯源。同时把当前所有登录会话列出来查清楚哪些账号是新添加的。第三步清点后门。检查 cron 任务是否被写入异常脚本、/etc/rc.local 是否有可疑启动项、/root/.ssh/authorized_keys 里有没有多出来的公钥、/etc/passwd 里有没有新用户、有没有 UID 为 0 的账号。这五项我称之为“后门必查五项”。第四步重置所有凭据。包括 root 密码、普通用户密码、SSH 密钥、应用系统里的各种 token 和密钥。即使你只怀疑某个账号被攻破也建议全部重置因为你不知道攻击者到底掌握了多少信息。最后一步才是恢复服务。把已知的漏洞补上、确认加固项都已生效再逐步开放网络。遭受过入侵的机器我心里是不太愿意继续信任的。如果有条件重建我会更倾向于重装系统再恢复业务数据而不是在原系统上反复修补。5.3 主观判断“有点不对劲”外发流量异常排查思路很多时候你突然觉得机器变慢了、带宽占用异常、CPU 飙高但本地各项业务都看着正常这时候十有八九是外发流量出了问题。外发流量异常最常见的两个原因一是被植入挖矿程序二是被当成跳板攻击别人。排查可以从三个维度并行。先看进程维度用top按 CPU 排序找到占用高的进程。挖矿程序一般会伪装成看起来很正常的进程名比如 kworker、systemd-update所以要留意进程的实际路径是不是在 /tmp、/var/tmp、/dev/shm 这种可疑目录。再看网络维度用netstat -an看有没有大量连接指向同一批外部 IP。挖矿进程一般会连接矿池地址特征比较明显。把可疑 IP 和进程 PID 对应起来一步定位是哪个程序在发起连接。最后看持久化维度因为即使你杀掉进程如果它被写成定时任务或者守护进程重启后还会复活。所以必须查 cron、systemd timer、rc.local把它的自动启动链路全部断掉才能彻底清理。日常运维里给外网出口流量监控做个基线也很有用。比如正常情况下这台机器每天的产生流量是多少某天突然多了几十倍那肯定有问题。大部分云厂商的控制台自带流量监控做告警阈值并不难。这一步值得做因为很多安全事件被发现往往不是因为你主动看到了攻击而是因为某个异常指标突破了你的心理底线。自动化的告警会帮很大忙。我现在会定期写一个巡检脚本把所有登录失败次数、开放端口、磁盘日志占用、最新可疑登录记录汇总成一份报告发到工作群。看起来是很枯燥的重复劳动但真出事的时候这些东西能让你比别人早一步动手。安全工作的价值往往就体现在这些不起眼的坚持里。我自己这些年最大的体会就是别追求什么花哨的安全方案先把基础项做好比什么都强。一个默认拒绝的防火墙、一套只走密钥的 SSH、一条能用的监控告警这三样就能挡住绝大多数的自动化攻击。剩下的时间拿来关注业务本身而不是天天盯着安全日志焦虑。