一、服务器防火墙为什么必须自己把控
云厂商虽然有安全组,但它是"机房外围"的过滤,无法覆盖主机内部的应用端口、本机回环和细化到进程的规则。真正的纵深防御,要在系统层面再设一道防火墙。Linux 上两套主流方案:传统 iptables(直接操作 netfilter 规则表)和更上层的 firewalld(RHEL 7+ 默认,把 iptables 管理得面向"区域 zone"和"服务 service",支持动态重载)。Ubuntu/Debian 默认也装 iptables 或 nftables。掌握它们,你才能真正做到"该开的端口才开,不该开的全封"。
二、iptables 的链与规则:一分钟建立直觉
iptables 用"表 + 链 + 规则",最常见的 filter 表有INPUT、OUTPUT、FORWARD 三条链,规则从上到下匹配,命中即决定 DROP/ACCEPT。看当前规则:
sudo iptables -L -n -v sudo iptables -t nat -L -n # NAT 表,端口/地址转发
这是一套"默认拒绝 + 白名单放行"的稳健起点(注意先别在远程环境一次性锁死自己):
# 允许已建立连接及回环 sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT sudo iptables -A INPUT -i lo -j ACCEPT # 开放 SSH、HTTP、HTTPS sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 默认丢弃其它入站 sudo iptables -P INPUT DROP
三、iptables 常用运维命令
# 追加/删除/插入规则(删除需与规则完全一致或用行号) sudo iptables -A INPUT ... # 追加到末尾 sudo iptables -I INPUT 1 ... # 插入到第 1 位 sudo iptables -D INPUT 5 # 删除第 5 行 sudo iptables -L -n --line-numbers # 带行号查看 # 端口转发示例:把本机 8080 转发到 127.0.0.1:9000 sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 127.0.0.1:9000 # 命令行即时生效但重启丢失,需保存 sudo service iptables save # RHEL 系 sudo iptables-save > /etc/iptables/rules.v4 # Debian/Ubuntu 手动保存
关键坑:iptables 规则即时生效但非持久化,写完后必须保存,否则重启就没了。对远程服务器改 POSTROUTING/默认策略时,一定要保留当前 SSH 连接或先加一条-I INPUT -p tcp --dport 22 -j ACCEPT,否则把自己拒之门外。
四、firewalld:面向区域的现代方案
firewalld 把网络按"区域"分组(public、trusted、internal…),通过 "rich rules" 和服务白名单来管理,改动可立即生效且无需中断连接:
# 查看默认区域与当前规则 sudo firewall-cmd --get-default-zone sudo firewall-cmd --list-all # 永久 + 立即开放/移除某个服务 sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --remove-service=http sudo firewall-cmd --reload # 让 --permanent 生效 # 开放指定端口(Tcp 例)与重载 sudo firewall-cmd --permanent --add-port=3306/tcp sudo firewall-cmd --reload # 禁止某 IP sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=1.2.3.4 reject' # 指定端口转发 sudo firewall-cmd --permanent --add-forward-port=port=8080:proto=tcp:toport=9000 sudo firewall-cmd --reload
firewalld 用 xml 保存规则到 /usr/lib/firewalld 与 /etc/firewalld,后者优先且改动用 --reload(热加载)或 --complete-reload(完全重读)。默认区域若为 public,未显式放行的端口通常都会被挡,恰好符合"默认闭合"的安全姿态。
五、iptables 与 firewalld 的取舍与共存
RHEL 系默认 firewalld 底层仍走 nftables/iptables,二者直接用规则文件会打架,应在两者间选其一为主。判断当前启用:systemctl status firewalld。混用时常见问题:用 iptables -A 加的规则被 firewalld 的全局策略覆盖或顺序冲突,导致"明明 ACCEPT 了还是不通"。稳妥做法是:firewalld 平台一律走 firewall-cmd;纯 iptables 平台(或 Ubuntu)则统一 iptables。不要一会用 iptables 一会用 firewalld 去管理同一套规则。
六、排错:为什么端口还是不通
"防火墙没放行,但连不上"要按层次排查:
# 1. 服务本身在监听吗 sudo ss -tlnp | grep :80 # 2. 防火墙是否放行 sudo iptables -L -n | grep :80 sudo firewall-cmd --list-all | grep 80 # 3. 内核 netfilter 是否被第三方(如 fail2ban、Docker、云安全组)额外拦截 sudo iptables -L -n # Docker 会自建链,可能影响端口 # 4. 云厂商安全组/防火墙如果较严,也要在控制台放行端口
按"服务监听 → 系统防火墙 → 叠加工具链 → 云安全组"自下而上逐个排除,90% 的端口不通问题都能定位。
写在最后
防火墙是服务器安全的第一道也是最后一道闸。核心不是记命令,而是建立"默认拒绝、按需放行"的观念。实践建议:保留 SSH 端口前提下,先把 INPUT 默认策略收紧;用白名单放行 Web、数据库等确定需要的端口;规则改动即时生效必须记得持久化保存;在 iptables/firewalld 中选择一套为主,避免规则互相打架。配合 fail2ban、SSH 密钥等前面讲过的措施,你的服务器就能把暴露面压到最低。




