资讯动态

Linux防火墙、SSH与系统日志详解:从原理到落地实战

发布时间:2026/9/17 0:40:21 来源:尧图企业网站定制
Linux 防火墙、SSH、系统日志详解三年运维踩坑后的完整复盘Linux 服务器这三样东西防火墙、SSH、系统日志单拎出来每一项都是基础中的基础但把它们放到一起讲清楚、讲透、讲到能直接落地的还真不多见。这篇文章就是围绕这三板斧展开的覆盖 firewalld 和 iptables 的日常玩法、SSH 免密登录和安全加固的完整流程、系统日志的轮转与防篡改配置最后附上我这些年实际踩过的问题排查记录。无论你是刚接触 Linux 的初学者还是已经被线上服务器折磨过几轮的运维这篇文章都值得花十几分钟看完内容都是可以直接抄作业的。先说一个多数人会忽略的点这三者的关系不是孤立的。防火墙管的是网络出入口SSH 是你登录服务器的手脚系统日志则是事后追溯的唯一依据。任何一个环节配置失误另外两个就一定跟着遭殃。比如你改了防火墙规则忘了放行 22 端口SSH 立刻连不上再比如你 SSH 登录失败但没看日志误判成网段问题结果排查半天才发现是 fail2ban 把 IP 封了。把这些关联想清楚再动手配置会少踩很多坑。1. 防火墙不只是“开端口”那么简单1.1 先搞懂 firewalld 和 iptables 到底什么关系很多人一上来就 firewalld、iptables 混着用改完也分不清到底谁生效这是运维新手常犯的第一个错误。简单讲iptables 是 Linux 内核 netfilter 框架的用户态管理工具firewalld 则是基于 iptables 做了一层动态管理的服务。换句话说firewalld 最终也是通过 iptables 命令把规则写进内核的只不过它把规则按 zone区域做了分类并且支持动态加载不用重启服务。CentOS 7 之后默认用的是 firewalldUbuntu 18.04 之后默认用的是 ufw而这个 ufw 底层同样是 iptables。所以你在 Ubuntu 上折腾 ufw 也好在 CentOS 上折腾 firewall-cmd 也好本质都是间接操作 iptables 规则链。理解这层关系之后就不会再纠结“我改 firewalld 要不要停掉 iptables”这类问题了。实际生产环境中我不建议同时启用 firewalld 和 iptables 服务冲突概率高且排查麻烦。选定一个作为日常管理入口另一个保持 disabled 状态即可。现在通用的做法是CentOS/RHEL 系用 firewalldUbuntu/Debian 系用 ufw底层规则检查统一用 iptables -L -n -v 看命中计数这是最直观的判断方式。1.2 Zone 区域概念与常用命令实战firewalld 的 zone 概念刚接触时会觉得绕我用大白话解释一下每个 zone 就是一套预设的放行策略集合一个网卡接口同一时间只能属于一个 zone。默认情况下所有接口都在 public zone这个 zone 对外的策略是最严格的只放行 SSH 和 DHCP 等少数服务。我举一个最常见的落地例子需要在服务器上放行 8080 端口给 Web 服务firewall-cmd --zonepublic --add-port8080/tcp --permanent firewall-cmd --reload firewall-cmd --zonepublic --list-all这里有个关键点--permanent 表示永久生效不加的话重启后规则就丢了。所以标准操作顺序是先加规则再 reload最后 list-all 确认。我见过不下三次同事忘记加 --permanent重启后服务端口全被拦生产事故就是这么来的。再补充几个高频使用的命令放行服务按服务名firewall-cmd --zonepublic --add-servicehttp --permanent移除端口firewall-cmd --zonepublic --remove-port8080/tcp --permanent查看所有 zonefirewall-cmd --get-zones修改接口默认 zonefirewall-cmd --zoneinternal --change-interfaceeth0 --permanent实际工作中我习惯在 reload 之前先执行 firewall-cmd --check-config 检查一下语法避免因为配置错误导致防火墙服务起不来这也是个保命习惯。1.3 黑名单与出站规则的限制之道防火墙不只是用来放行端口的热词里有人提到“屏蔽某个程序出站联网”这个在 Linux 服务端也常见。比如限制某个用户或某个进程组不能访问外网。firewalld 的 rich rule 可以按照 user、process、port 维度做规则但说实话按进程匹配这块 firewalld 的能力不如 Windows 防火墙图形界面那么直观。Linux 下做进程级出站限制常用的方案是借助 iptables 的 owner 模块按 uid 或 gid 匹配。举个例子禁止 uid 为 1001 的用户访问外网iptables -A OUTPUT -m owner --uid-owner 1001 -j DROP禁止某个固定 IP 访问本机 3306 端口iptables -I INPUT -s 192.168.1.100 -p tcp --dport 3306 -j DROP看到这里你可能会问为什么出站规则比入站规则更难搞因为入站规则是控制别人访问你规则冲突时影响面相对小出站规则是控制你的服务器主动访问别人一旦误封yum 源连不上、外部 API 调不通、ntp 时间同步失败所有依赖外网的服务全部异常。我处理过一个案例服务器上所有 yum 命令都超时排查一圈发现是之前测试出站限制时加了条 INPUT 口的 -j REJECT方向搞反了。所以出站限制的实操建议是先用 -I OUTPUT 插入规则测试确认无误后再加上永久配置如果服务器上有监控系统一定要把关键探测源 IP 加白名单防止自己把自己封死。另外黑白名单不要混用要么全部白名单模式要么全部黑名单模式混着用后期维护很痛苦。1.4 透明模式与旁挂部署的适用场景热词里还提到“透明模式防火墙端口可以配 IP 吗”“防火墙旁挂核心这边配置 vrf 吗”这类问题。这些场景大多是企业级硬件防火墙和 Linux 自带的防火墙不是一回事但既然大家搜到了我就简单理一下概念避免概念混淆。透明模式也叫桥接模式防火墙相当于一个二层设备接口不配 IP直接透明转发流量适合在不改动现有网络架构的情况下串接部署。旁挂模式则是把防火墙挂在核心交换机旁边通过策略路由或 VRF 引流到防火墙做过滤。普通 Linux 服务器的防火墙场景用不上这么重的方案但如果你管理的网络规模大了理解这些部署形态能帮你和网络工程师顺畅沟通。大部分情况下Linux 服务器做边界防火墙用的还是 iptables 的 NAT 和 FORWARD 链路这属于另一套玩法以后有条件单独写一篇。2. SSH 安全与免密登录从原理到实战2.1 SSH 密钥认证的工作原理SSH 登录方式分两种密码登录和密钥登录。密码登录简单但存在暴力破解风险密钥登录更安全但配置不当也容易出问题。密钥认证的原理可以这样理解服务器上存放的是公钥客户端保留的是私钥。客户端发起连接时服务器生成一个随机挑战值客户端用私钥签名后返回服务器用公钥验签验证通过就放行。私钥永远不会在网络中传输安全性有保障。用一个生活化的类比公钥就像一把锁私钥是唯一的钥匙。你把锁公钥放到服务器上自己留着钥匙私钥。别人就算拿到那把锁没有钥匙也进不了门。这比密码登录强在密码会通过网络传输一旦被中间人抓到就泄露了而密钥认证整个过程私钥不出本地。所以这也是为什么企业里批量管理服务器时几乎清一色要求配置密钥登录一是安全二是方便免密脚本化操作。2.2 免密登录完整配置流程下面给出一套我常用的免密登录配置流程以从本地 macOS/Linux 客户端连接远程 CentOS 服务器为例第一步在本地生成密钥对我推荐用 ed25519 算法比传统的 RSA 更安全且密钥长度更短ssh-keygen -t ed25519 -C 你的备注信息 -f ~/.ssh/id_ed25519如果服务器端 SSH 版本较老不支持 ed25519再改用ssh-keygen -t rsa -b 4096 -C 你的备注信息 -f ~/.ssh/id_rsa第二步将公钥拷贝到服务器ssh-copy-id -i ~/.ssh/id_ed25519.pub 用户名服务器IP如果 ssh-copy-id 不可用也可以手动追加cat ~/.ssh/id_ed25519.pub | ssh 用户名服务器IP mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys这里有个容易踩的坑公钥追加到 authorized_keys 之后一定要检查文件和目录权限。服务器端 ~/.ssh 目录权限必须是 700authorized_keys 文件必须是 600。如果权限过宽比如 authorized_keys 是 644sshd 出于安全考虑会直接拒绝使用这个文件日志里会报 “Permissions too open”。我见过很多配置完免密失败的情况八成都是这个原因。第三步测试连接ssh 用户名服务器IP如果配置成功不需要输密码直接进入服务器。如果失败保持 ssh -v 方式连接看输出信息里的 debug 内容定位问题。2.3 安全加固如何让 SSH 更难被攻破免密配置完成后服务器端还应该做一轮安全加固。这里给出我线上环境的推荐配置修改 /etc/ssh/sshd_configPort 2222 # 修改默认端口降低被扫描概率 PermitRootLogin no # 禁止 root 直接登录 PasswordAuthentication no # 禁止密码登录只允许密钥 PubkeyAuthentication yes # 开启密钥认证 MaxAuthTries 3 # 最大认证尝试次数 AllowUsers alice bob # 白名单用户修改完成后重启服务systemctl restart sshd注意一点修改端口前千万不要关掉当前 SSH 连接否则规则一错你就会被关在门外。正确的顺序是先把新端口配置好验证能用新端口登录再关掉旧连接。另外修改 sshd_config 后建议先执行 sshd -t 检查语法确认无误后再重启服务。关于修改端口这件事有争议有人说改了也没用扫描器全端口扫一遍就发现了。但我的实际经验是改端口能挡掉 90% 以上的无差别扫描攻击因为大部分脚本攻击只扫 22 端口。对于有一定暴露面的公网服务器改端口加密钥登录加 fail2ban 三道防线基本可以保证 SSH 入口安全性。配置密钥登录还有个细节就是不同服务器使用不同私钥。我在本地用 ~/.ssh/config 管理多台服务器连接配置Host prod-server HostName 192.168.1.10 User alice Port 2222 IdentityFile ~/.ssh/id_ed25519_prod Host dev-server HostName 192.168.1.20 User bob Port 22 IdentityFile ~/.ssh/id_ed25519_dev配置好之后直接 ssh prod-server 就能连接再也不用记 IP、端口、用户名和私钥路径强烈推荐。2.4 常见 SSH 连接问题排查热词里有“Ubuntu ssh 无法连接”“crt 软件 ssh 登陆交换机提示密钥”这类问题。根据我的经验SSH 连不上先按以下顺序排查先看服务状态systemctl status sshd再看端口监听ss -tlnp | grep ssh如果系统是 Ubuntu注意一个特殊点Ubuntu 默认不装 openssh-server需要手动安装sudo apt update sudo apt install openssh-server -y另外Ubuntu 20.04 和 22.04 的 sshd 服务名可能是 ssh而不是 sshdsystemctl status ssh客户端如果是 CRT 这类工具提示密钥问题大概率是服务器返回的主机密钥和客户端 known_hosts 里记录的不一致。这种情况通常发生在服务器重装系统后解决方式是客户端删除该 IP 对应的 known_hosts 记录ssh-keygen -R 服务器IP然后再重新连接会重新提示确认主机指纹输入 yes 即可。3. 系统日志看得见的痕迹与看不见的坑3.1 日志体系全景rsyslog 与 journald 的分工合作Linux 系统日志体系主流有两套传统的 rsyslog 和 systemd 自带的 journald。很多人分不清两者各自负责什么我来理一下。rsyslog 负责把各种程序产生的日志按设施facility和级别priority写入 /var/log 下的文本文件比如 /var/log/messages系统总日志、/var/log/secure认证安全日志、/var/log/cron计划任务日志。journald 则是 systemd 统一收集所有服务的标准输出和错误日志通过 journalctl 查看保存的是二进制格式。生产线上的经典坑是业务容器或服务直接往 stdout 打日志你在 /var/log/messages 里找不到但这不代表日志丢了它都在 journald 里。查看最近 10 分钟某个服务的日志可以这样journalctl --since 10 minutes ago -u nginx.service查看某个进程按 PID的日志journalctl _PID12345journald 和 rsyslog 的核心关系是journald 负责采集rsyslog 负责落盘。生产环境我建议两者配合开启journald 保证日志不丢rsyslog 把关键日志落到文件方便 grep 和分析。3.2 日志轮转防止磁盘被日志撑爆日志如果不做轮转磁盘被写满是早晚的事。rsyslog 的日志轮转由 logrotate 管理配置文件在 /etc/logrotate.conf 和 /etc/logrotate.d/ 目录下。一个典型的 nginx 日志轮转配置长这样/var/log/nginx/*.log { daily rotate 7 compress delaycompress missingok notifempty create 0640 nginx adm sharedscripts postrotate [ -f /var/run/nginx.pid ] kill -USR1 cat /var/run/nginx.pid endscript }解释下关键参数daily每天轮转一次也可以用 weekly/monthlyrotate 7保留 7 个归档日志更早的删除compress归档后压缩成 gz减少磁盘占用delaycompress延迟压缩保证最近一个日志还能被正常读取missingok日志文件不存在时不报错notifempty日志为空不轮转postrotate轮转后执行的命令通常是通知应用重新打开日志文件线上服务器经常会碰到业务日志量很大按天轮转还是太大可以改成按大小轮转size 200M即日志文件超过 200M 就触发轮转。我自己的服务器上统一配置 size 500M配合 rotate 14等于是最近 7GB 日志可回溯既能排查问题又不至于占用太多磁盘。3.3 日志只能追加用 immutable 属性锁住日志文件热词里有一条“保证系统日志只能追加”这个需求大多是为了日志合规和防篡改。Linux 下实现只追加效果最常用的命令是 chattr 的 a 标识。给 /var/log/messages 加上只追加属性chattr a /var/log/messages查看属性lsattr /var/log/messages输出应该包含一个 a 标识表示 append-only。这样一来任何进程都无法删除或修改已有内容只能追加新内容即使 root 用户也改不了。如果哪天需要解除这个限制chattr -a /var/log/messages这里补充一个容易忽略的点chattr a 只对文件内容保护如果你希望连文件删除操作都禁止可以用 iimmutable属性。但日志场景一般不用 i因为 logrotate 轮转时需要重命名或删除旧日志文件i 会让轮转直接失败。所以日志防篡改的推荐组合是对正在写的日志文件用 a对归档压缩后的旧日志用 i 或者干脆不做额外保护。如果希望整个目录都只能追加可以在目录上设置 a但要注意这会连带目录下的新建文件也继承属性实际使用时小心验证。另一个容易踩的坑是有些保险起见的人会对整个 /var/log 目录递归设置 a这种做法会导致系统服务在创建新日志文件时遇到权限问题反而引发故障。正确做法是精确到单个关键日志文件比如 /var/log/secure、/var/log/messages 这类审计需求高的文件。3.4 journald 的日志限制与清理策略journald 如果不做限制默认会占用系统分区一定比例的空间。服务器跑久了/var/log/journal 目录越来越大查一下才知道占了多少journalctl --disk-usage如果发现占得太多可以设置 journald 的内存和磁盘上限修改 /etc/systemd/journald.confSystemMaxUse500M SystemMaxFileSize50M RuntimeMaxUse200M MaxRetentionSec2week改完重启服务systemctl restart systemd-journald需要立即清理旧的 journal 日志时可以用journalctl --vacuum-size200M journalctl --vacuum-time1week这两个命令分别按大小和时间清理不会影响当前正在记录的日志。4. 高频故障排查速查表与避坑技巧4.1 防火墙挡了 SSH 怎么办这条放在第一位因为这是所有人最容易踩的坑。场景通常是你为了加固安全给防火墙加了规则加了之后 SSH 直接断开且永远连不上因为你把自己所在网段的 IP 也一起拦了。处理办法只有一个如果有物理控制台或云厂商的 VNC通过控制台登录服务器然后执行firewall-cmd --zonepublic --add-rich-rulerule familyipv4 source address你的IP/32 port port22 protocoltcp accept --permanent firewall-cmd --reload这里强调一个原则所有涉及远程防火墙规则的修改务必先加入口白名单再改规则。就好比你要在房间里装防盗门先把钥匙拿在手里再动手别把自己反锁在门外。如果是 iptables 场景可以直接清空规则恢复 SSHiptables -F但 iptables -F 会同时清空所有规则如果机器本身有 NAT 等需求别乱来先 -L 看清楚再决定。4.2 authorized_keys 权限问题导致免密失效客户端配置免密登录后有时候连接时仍然提示输入密码加 -v 参数查看输出会在 debug 里看到Authentication refused: bad ownership or modes for /home/user/.ssh/authorized_keys原因就是服务器端文件权限过宽。SSH 为了保证安全要求私钥文件、authorized_keys 文件必须只能被当前用户拥有且不能被组内其他用户写入。修正方法chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R $(whoami):$(whoami) ~/.ssh这个问题的典型特征是你在本机测试没问题换一台机器或者换一个用户登录就失败大概率都是权限问题。我在 Windows 上用 Git Bash 做免密时也经常踩这个坑因为 Windows 的文件系统权限模型和 Unix 不一样粘贴公钥的操作容易把文件权限搞乱。4.3 WSL 中删除文件后空间不释放热词里有一条“wsl linux 删除文件后空间没释放”这其实是 WSL 虚拟磁盘文件vhdx的经典问题。Windows 的 WSL2 使用 ext4 文件系统封装在 vhdx 虚拟磁盘里你在 Linux 里删除文件磁盘空间不会立刻归还给 Windows 宿主机因为 vhdx 是动态增长的只在内部保留空洞。解决办法是在 Windows 管理员 PowerShell 中执行wsl --shutdown diskpart # 在 diskpart 中选择对应 vhdx 文件后执行 compact vdisk或者简单点直接用 wsl --manage 发行版名 --set-sparse true 开启自动精简。这个配置我试过开启后删除文件的空间回收机制会友好很多不需要频繁手动清理。不过这里要提醒一下先把 Linux 里的日志、缓存、旧内核都清理干净再做 vhdx 压缩否则压缩虽然执行了但实际回收不了多少空间。WSL 里旧内核常常躺在 /usr/src 下占几个 G记得一并清理。4.4 SSH 连接慢的排查方向SSH 连接时要等好几秒才能进入输入密码界面这个问题在任何 Linux 发行版都可能遇到。最常见原因是 sshd 在做反向 DNS 解析局域网内没有配置 DNS 服务器或者 DNS 解析超时整个连接过程就被卡住了。修改 /etc/ssh/sshd_configUseDNS no GSSAPIAuthentication no重启 sshd 之后连接速度会明显改善。我在内网环境实测过开启 UseDNS 时连接耗时 3-5 秒关闭后回到 1 秒以内。另一处可能导致慢的地方是客户端如果你设置了多个 IdentityFile客户端会逐个尝试也会增加延迟。4.5 日志文件被删除但空间不释放这个场景很有代表性。你 rm 掉了一个大日志文件df -h 一看磁盘还是满的。原因是有进程仍然持有该文件的文件句柄文件内容还没有真正释放。排查办法是找到持有句柄的进程lsof | grep deleted输出会列出被删除但仍被占用的文件及对应 PID。确认后重启相关进程或直接 kill 掉空间就会释放。这个坑在 Java 应用日志、Nginx 日志上经常出现很多运维新手第一次遇到会以为删不掉或者误判为磁盘故障。日常避免办法是轮转日志时尽量使用 logrotate而不是手动 rmlogrotate 轮转设计的初衷就是解决文件句柄和应用重开日志的问题。如果你确实需要手动清空日志别用 rm直接 /var/log/some.log用重定向清空文件内容比删除文件更安全不会弄丢文件句柄。4.6 常见问题速查表我把上面所有踩坑场景整理成一个速查表出问题时对照排查现象可能原因排查命令解决办法SSH 连接被拒绝防火墙未放行或 sshd 未启动systemctl status sshd; ss -tlnp放行端口或启动 sshd免密登录失败权限过宽/authorized_keys 内容错误ssh -v 查看 debugchmod 600 权限重新追加公钥磁盘被日志写满无 logrotate 或轮转策略不合理df -h; du -sh /var/log配置 logrotate 轮转压缩日志被人为删除无防篡改保护lsattr /var/log/messageschattr a 设置只追加防火墙规则改动后失联把自己 IP 封了控制台登录检查临时放行白名单再改规则删除日志文件空间不释放进程持有文件句柄lsofgrep deleted5. 落地方案一套组合配置示例把前面说的内容串在一起给出一套适合中小型 Linux 服务器的组合配置示例。这套配置我部署在多个生产环境中整体稳定性很好。防火墙侧CentOS 系统上先切换到默认拒绝策略firewall-cmd --set-default-zonepublic firewall-cmd --zonepublic --remove-servicessh --permanent firewall-cmd --zonepublic --add-rich-rulerule familyipv4 source address10.0.0.0/8 port port22 protocoltcp accept --permanent firewall-cmd --zonepublic --add-servicehttp --permanent firewall-cmd --zonepublic --add-servicehttps --permanent firewall-cmd --reload这样配置的效果是22 端口只允许内网 10.0.0.0/8 访问公网只能访问 80/443其他端口全部关闭。SSH 侧/etc/ssh/sshd_config 重点参数Port 22 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes MaxAuthTries 3 AllowUsers alice bob日志侧既设置 rsyslog 落盘也开 journald 持久化mkdir -p /var/log/journal systemd-tmpfiles --create --prefix /var/log/journal然后按前面介绍的方式设置 journald 空间上限再对 /var/log/messages 和 /var/log/secure 执行chattr a /var/log/messages chattr a /var/log/secure最后配置 logrotate把系统自带的关键日志轮转策略统一加上 size 限制和压缩。这套组合跑下来我观察到最明显的变化是暴力破解日志几乎归零。因为 PasswordAuthentication 已经关闭扫描器发现没有密码登录途径后会自动跳过。防火墙侧由于端口收敛暴露面也大大缩小iptables 的命中计数里能看到大量尝试连接被 REJECT这就是安全策略在起作用的最直接证据。根据我个人的实际经验这三块配置一定要做好配套的备份。我通常把 /etc/firewalld/、/etc/ssh/sshd_config、/etc/logrotate.d/ 和 /etc/systemd/journald.conf 打包备份到一个固定目录每周定时同步到异地存储。一旦哪次手滑改了配置导致故障直接回滚备份比临时回忆哪些参数改过要省事得多。这边再多提醒一句用 chattr a 对日志文件做防篡改之前一定要先确认 logrotate 的执行用户有权限处理这些文件否则轮转会报错日志越积越大直到磁盘爆掉。这算是我踩过最隐蔽的坑之一希望你看完能少走这段弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价