Skip to content

🛡️ firewalld(CentOS/RHEL 防火墙)

什么是 firewalld?

firewalld 引入了**"区域"(Zone)**的概念——想象你的服务器在不同场合有不同的"面孔":在家(trusted 区域)什么都允许,在咖啡厅(public 区域)只开必要端口,在公司(work 区域)开放办公需要的服务。

区域(Zones)

区域名默认行为适用场景
drop丢弃所有入站最高安全级别
block拒绝所有入站(返回 ICMP 拒绝)类似 drop,但会通知对方
public默认区域,只允许选中的服务公网服务器
external启用伪装(MASQUERADE)路由器/网关
work允许常见办公服务办公网络
home信任大部分入站家庭网络
trusted允许所有入站完全信任的网络

基本管理

bash
# 启动和开机自启
sudo systemctl start firewalld
sudo systemctl enable firewalld

# 查看状态
sudo firewall-cmd --state
running

# 查看默认区域
sudo firewall-cmd --get-default-zone
public

# 查看所有区域
sudo firewall-cmd --get-zones
block dmz drop external home internal public trusted work

# 查看当前区域的规则
sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  rich rules:

# 查看所有区域的规则
sudo firewall-cmd --list-all-zones

服务和端口管理

bash
# 查看可用服务列表
sudo firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula
bacula-client bitcoin bitcoin-rpc ... ssh dhcpv6-client
http https mysql postgresql redis ...

# 添加服务(运行时生效)
sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https

# 添加端口
sudo firewall-cmd --add-port=8080/tcp
sudo firewall-cmd --add-port=3000-4000/tcp    # 端口范围

# 永久添加(重启后仍然生效)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8080/tcp

# 重新加载使永久规则生效
sudo firewall-cmd --reload

# 移除服务/端口
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --permanent --remove-port=8080/tcp

# 查看当前生效的规则(运行时)
sudo firewall-cmd --list-services
dhcpv6-client http https ssh

sudo firewall-cmd --list-ports
8080/tcp

⚠️ 注意: ⚠️ 运行时 vs 永久:--add-service只在当前会话生效(重启后消失)。加上--permanent才会永久保存。加了--permanent后需要--reload才生效。

Rich Rules(富规则)

富规则是 firewalld 的高级语法,能做更精细的控制。

bash
# 只允许特定 IP 访问 SSH
sudo firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.100"
  port protocol="tcp" port="22"
  accept'

# 限制连接速率(每分钟最多 10 个新 SSH 连接)
sudo firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  port protocol="tcp" port="22"
  accept
  limit value="10/m"'

# 拒绝特定 IP
sudo firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  source address="10.0.0.50"
  drop'

# 允许特定网段访问 MySQL
sudo firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.0/24"
  port protocol="tcp" port="3306"
  accept'

# 查看所有富规则
sudo firewall-cmd --list-rich-rules

# 删除富规则
sudo firewall-cmd --permanent --remove-rich-rule='
  rule family="ipv4"
  source address="10.0.0.50"
  drop'

sudo firewall-cmd --reload

Direct Rules(直接规则)

bash
# 直接插入 iptables 规则(firewalld 的后门)
sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 \
  -p tcp --dport 9090 -j ACCEPT

# 查看直接规则
sudo firewall-cmd --direct --get-all-rules

# 永久化
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 \
  -p tcp --dport 9090 -j ACCEPT
sudo firewall-cmd --reload

📝 备注: 📝 什么时候用 Direct Rules?当 firewalld 的富规则无法满足你的需求时(比如复杂的 iptables 规则),可以用 direct 规则直接操作底层 iptables。

区域绑定

bash
# 把网卡绑定到区域
sudo firewall-cmd --permanent --zone=public --change-interface=eth0

# 把 IP 绑定到区域
sudo firewall-cmd --permanent --zone=trusted --add-source=192.168.1.100

# 查看接口对应的区域
sudo firewall-cmd --get-active-zones
public
  interfaces: eth0 eth1