Skip to content
firewalld
  • 白名单
bash
### 默认拒绝所有,只允许明确的

# 默认策略:拒绝所有入站,只允许出站
sudo firewall-cmd --set-default-zone=drop  # 或 block

# 然后明确允许需要的服务
sudo firewall-cmd --add-service=http
sudo firewall-cmd --add-service=https
sudo firewall-cmd --add-service=ssh

# 或者使用富规则允许特定IP
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" accept'

# ✅ 更安全:未知的连接默认被拒绝
# ✅ 需要明确配置每个允许的服务/IP
# ✅ 适合服务器、生产环境
  • 黑名单
bash
### 默认允许所有,只拒绝明确的

# 默认策略:允许所有入站
sudo firewall-cmd --set-default-zone=public  # 默认允许

# 然后明确拒绝不需要的或恶意的
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.0.5" reject'
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" drop'

# 或者禁用某些端口
sudo firewall-cmd --remove-port=135-139/tcp
  • zone
bash
firewall-cmd --get-zones
## 网络接口和服务分配到不同的zone上,会对应不同的默认规则和策略
zone默认规则适用场景
drop丢弃所有传入流量最高安全级别,适用于不信任的网络(如公共 Wi-Fi),丢弃所有未经请求的入站流量。
block拒绝所有传入流量(返回 ICMP 拒绝消息)类似 drop,但会通知发送方连接被拒绝。适用于需要明确拒绝流量的场景。
public仅允许显式放行的传入流量默认 zone,适用于公共网络(如咖啡馆、机场),仅开放必要的服务(如 HTTP/SSH)。
external仅允许指定传入流量,默认启用伪装(NAT)用于外部网络(如路由器防火墙),保护内部网络,通常允许 SSH 和伪装(IPv4 地址转换)。
internal允许大部分传入流量(信任内部用户)用于内部网络(如企业内网),允许 SSH、DHCP、Samba 等服务,信任内部设备。
dmz仅允许指定传入流量用于隔离区(如暴露给外网的服务器),限制流量到特定服务(如 Web 服务器)。
work允许部分传入流量(信任工作环境)适用于工作场所,允许 SSH、DHCP、文件共享等,但限制高危服务。
home允许较多传入流量(信任家庭网络)家庭网络环境,允许打印机共享、DLNA、SSH 等,比 internal 更宽松。
trusted允许所有流量(完全信任)最高信任级别(如 VPN 或内部测试网络),无任何限制,慎用。

  • 说明
  1. 主机上的每个网络接口(ip a)只能绑定到一个zone上
  2. 匹配顺序:先检查 来源 IP 绑定的 zone,再检查 接口 绑定的 zone, 最后回退到 默认 zone(通常是 public)
  3. 所有 zone 默认允许出站流量,但入站流量根据 zone 规则控制

  • direct rules

    1. 基本语法
    bash
    ## 允许指定 IP 访问端口
    sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 10 -s 192.168.1.100 -p tcp --dport 80 -j ACCEPT
    ## 拒绝指定 IP 访问端口
    sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 10 -s 192.168.1.100 -p tcp --dport 22 -j DROP
    ## 设置优先级(数字越小优先级越高)
  • rich-rule

    1. 基本语法
    bash
    rule [family="ipv4|ipv6"] [source address="ip/MASK" mac="MAC地址"|destination address="IP/MASK"] [service name="服务名"|port port="端口号"|protocol value="协议名"] [log prefix="前缀文本" level="info"] [audit] [action] [other_options]
    1. 示例:
    bash
    ## 允许特定IP访问指定服务
    firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" accept'  
    
    
    ## 拒绝某网段的 ICMP 并记录日志
    firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.2.0/24" protocol value="icmp" log prefix="ICMP BLOCK: " level="warning" reject'  
    
    ## 限速http请求
    firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="80" protocol="tcp" limit value="10/minute" accept'  
    
    ## 端口转发(公网 8080 → 内网 80)
    firewall-cmd --zone=external --add-rich-rule='rule family="ipv4" forward-port port="8080" protocol="tcp" to-port="80" to-addr="192.168.1.2"'  
    
    ## 临时生效指定时长(30秒)
    firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.5" service name="http" accept' --timeout=30  
    
    ## 端口转发
    ## echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
    ## sudo sysctl -p
    ## 网卡接口绑定
    ##   外部接口(eth0)绑定到 external zone(默认启用伪装 masquerade)。
    firewall-cmd --zone=external --change-interface=eth0 --permanent
    
    ##   内部接口(如 eth1)绑定到 internal zone。
    firewall-cmd --zone=internal --change-interface=eth1 --permanent
    
    ## 使用 forward-port 参数实现 DNAT:
    sudo firewall-cmd --zone=external --add-rich-rule='rule family="ipv4" forward-port port="8080" protocol="tcp" to-port="80" to-addr="192.168.1.100"' --permanent
    
    ## 允许 192.168.1.0/24 通过防火墙访问外网,并启用 SNAT
    firewall-cmd --zone=external --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" masquerade' --permanent
    
    ## 规则清空并还原到默认设置
    firewall-cmd --complete-reload

  • 创建 zone 进行管理

    1. 基本语法
    bash
    # 1. 创建新 zone
    sudo firewall-cmd --permanent --new-zone=trusted_access
    
    # 2. 设置默认规则(默认拒绝)
    sudo firewall-cmd --permanent --zone=trusted_access --set-target=REJECT
    
    # 3. 添加允许的 IP
    sudo firewall-cmd --permanent --zone=trusted_access --add-source=192.168.1.100
    
    # 4. 开放端口给这个 zone
    sudo firewall-cmd --permanent --zone=trusted_access --add-port=8080/tcp
    
    # 5. 重载配置
    sudo firewall-cmd --reload
  • IPSET示例

    • 主要字段
    字段说明
    nameipset 名称,用于引用
    typeipset 类型,决定存储结构和匹配方式
    options创建时的额外参数(如最大条目、超时、范围等)
    entriesipset 内部存储的 IP / 网段 / MAC 条目
    • firewalld 支持的 ipset 类型及用途
    type用途适用 option
    hash:ip单个 IPmaxelem, hashsize, timeout, family
    hash:net网段 (CIDR)maxelem, hashsize, timeout, family
    hash:macMAC 地址maxelem, hashsize
    hash:ip,portIP + 端口组合maxelem, hashsize
    hash:net,port网段 + 端口maxelem, hashsize
    hash:ip,port,ip源 IP + 端口 + 目标 IPmaxelem, hashsize
    hash:ip,port,net源 IP + 端口 + 目标网段maxelem, hashsize
    bitmap:ip连续 IP 范围range, maxelem
    • options 只能在创建 ipset 时设置,多 option 用逗号分隔
    Option说明适用类型
    maxelem=N最大条目数hash 系列
    hashsize=N哈希表初始大小hash 系列
    timeout=N每条 entry 有效时间(秒)hash:ip, hash:net
    family=inet / inet6IPv4 / IPv6hash:ip, hash:net
    range=IP1-IP2连续 IP 范围bitmap:ip
    • 创建使用
    bash
    ##### firewalld ipset使用示例
    ## firewall-cmd --set-default-zone=drop
    # 1. 新建ipset
    IPSET_NAME=whitelist
    firewall-cmd --permanent --new-ipset=${IPSET_NAME} --type=hash:ip
    # 2. 查看ipset: IPSET_NAME
    firewall-cmd --permanent --info-ipset=${IPSET_NAME}
    # 3. 将指定ip加入: IPSET_NAME
    firewall-cmd --permanent --ipset=${IPSET_NAME} --add-entry=192.168.165.89
    # 4. 将指定ip段加入: IPSET_NAME
    firewall-cmd --permanent --ipset=${IPSET_NAME} --add-entry=192.168.165.0/24
    # 5. 指定端口放行 IPSET_NAME
    firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source ipset='whitelist' port protocol='tcp' port=8080 accept"
    
    # 6. 列出 rich rules
    firewall-cmd --permanent --list-rich-rules
    # 7. 从 IPSET_NAME 移除 指定ip
    firewall-cmd --permanent --ipset=${IPSET_NAME} --remove-entry=192.168.165.89
    # 8. 从 IPSET_NAME 移除 指定ip段
    firewall-cmd --permanent --ipset=${IPSET_NAME} --remove-entry=192.168.165.0/24
    # 9. 清空 IPSET_NAME
    firewall-cmd --permanent --ipset=${IPSET_NAME} --flush
    # 10. 删除 IPSET_NAME 
    firewall-cmd --permanent --delete-ipset=${IPSET_NAME}
    # 11. 列出存在的ipset
    firewall-cmd --permanent --get-ipsets
    • 一些示例
    bash
    ### 创建IPSET
    # 创建 ipset(永久生效)
    sudo firewall-cmd --permanent --new-ipset=blacklist --type=hash:ip
    sudo firewall-cmd --permanent --new-ipset=whitelist --type=hash:net
    sudo firewall-cmd --permanent --new-ipset=countries --type=hash:net
    # 创建带选项的 ipset
    sudo firewall-cmd --permanent --new-ipset=blocklist \
        --type=hash:ip \
        --option=timeout=3600 \
        --option=family=inet
    # 查看可用的 ipset 类型
    sudo firewall-cmd --get-ipset-types
    # hash:ip, hash:net, hash:ip,port 等
    
    ### 添加IP到IPSET
    # 添加单个 IP
    sudo firewall-cmd --permanent --ipset=blacklist --add-entry=192.168.1.100
    # 添加 IP 网段
    sudo firewall-cmd --permanent --ipset=whitelist --add-entry=192.168.1.0/24
    # 添加多个 IP(从文件读取)
    sudo firewall-cmd --permanent --ipset=blacklist --add-entries-from-file=/path/to/ip_list.txt
    # 文件格式(每行一个IP)
    # 192.168.1.100
    # 10.0.0.50
    # 172.16.0.0/16
    
    ### 从IPSET移除IP
    # 删除单个 IP
    sudo firewall-cmd --permanent --ipset=blacklist --remove-entry=192.168.1.100
    # 清空 ipset
    sudo firewall-cmd --permanent --ipset=blacklist --remove-entries-from-file=/path/to/ip_list.txt
    
    ### 基于rich rule的IPSET
    # 拒绝黑名单 IP 访问所有端口
    sudo firewall-cmd --permanent --add-rich-rule='rule source ipset=blacklist drop'
    # 允许白名单 IP 访问 SSH
    sudo firewall-cmd --permanent --add-rich-rule='rule source ipset=whitelist port port=22 protocol=tcp accept'
    # 拒绝黑名单访问特定端口
    sudo firewall-cmd --permanent --add-rich-rule='rule source ipset=blacklist port port=80 protocol=tcp reject'
    
    ### 结合 zone 使用
    # 创建自定义 zone
    sudo firewall-cmd --permanent --new-zone=restricted
    # 将 ipset 添加到 zone
    sudo firewall-cmd --permanent --zone=restricted --add-source=ipset:blacklist
    # 设置 zone 默认行为
    sudo firewall-cmd --permanent --zone=restricted --set-target=DROP
    
    ### 阻止恶意IP
    # 1. 创建恶意 IP 列表
    sudo firewall-cmd --permanent --new-ipset=bad_ips --type=hash:ip
    # 2. 添加恶意 IP
    sudo firewall-cmd --permanent --ipset=bad_ips --add-entry=10.0.0.100
    sudo firewall-cmd --permanent --ipset=bad_ips --add-entry=172.16.0.50
    # 3. 阻止这些 IP
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source ipset="bad_ips" drop'
    # 4. 重载配置
    sudo firewall-cmd --reload

  • 特别说明
    1. 调试建议:先用 --timeout 测试临时规则,避免配置错误导致访问中断
    bash
    firewall-cmd --zone=external --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" masquerade' --timeout 30

  • 脚本示例
bash
#!/bin/bash

CMD="/usr/bin/firewall-cmd"
ZONE_NAME="tmpz"
INTERFACE="ens192"          # 替换为你的实际网卡名
WHITELIST_IPS=("192.168.1.100" "192.168.165.88")  # 你允许访问的 IP

# 创建自定义 zone(如果不存在)
if ! $CMD --get-zones | grep -qw "$ZONE_NAME"; then
    echo "创建 zone: $ZONE_NAME"
    $CMD --permanent --new-zone=$ZONE_NAME
fi

# 清空 zone 的所有现有规则(确保纯净)
echo "清空 zone: $ZONE_NAME 的所有规则"
RICH_RULES=$($CMD --permanent --list-rich-rules --zone $ZONE_NAME)
if [[ -n "$RICH_RULES" ]]; then
    echo "清除已有 rich-rules:"
    while IFS= read -r rule; do
        echo "删除规则: $rule"
        $CMD --permanent --zone=$ZONE_NAME --remove-rich-rule="$rule"
    done <<< "$RICH_RULES"
else
    echo "没有需要删除的 rich-rule"
fi
$CMD --permanent --zone=$ZONE_NAME --remove-interface=$INTERFACE

# 添加 rich-rule 白名单 IP
for ip in "${WHITELIST_IPS[@]}"; do
    echo "添加白名单 IP: $ip"
    $CMD --permanent --zone=$ZONE_NAME \
        --add-rich-rule="rule family='ipv4' source address='$ip' accept"
done

# 默认拒绝其他访问
echo "设置默认策略为拒绝"
$CMD --permanent --zone=$ZONE_NAME --set-target=DROP

# 绑定网卡到新 zone
echo "绑定网卡 $INTERFACE 到 zone $ZONE_NAME"
$CMD --permanent --zone=$ZONE_NAME --add-interface=$INTERFACE

# 应用更改
echo "重新加载 firewalld"
$CMD --reload

# 验证
echo "验证规则"
$CMD --zone=$ZONE_NAME --list-all

  • iptables示例
bash
#!/bin/bash
set -e

## 清空规则
iptables -F
iptables -X

## 设置白名单
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT


iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -p tcp --dport 1122 -j ACCEPT
iptables -A INPUT -p tcp --dport 6666 -j ACCEPT
iptables -A INPUT -p tcp --dport 8000 -j ACCEPT
iptables -A INPUT -p tcp --dport 8877 -j ACCEPT

iptables save

欢迎来到 Laazua 的站点