当前位置: 代码网 > 服务器>服务器>Linux > Linux利用iptables与firewalld实现端口访问控制的实战指南

Linux利用iptables与firewalld实现端口访问控制的实战指南

2026年02月06日 Linux 我要评论
前言在linux服务器安全体系中,端口访问控制是基础而关键的一环。无论是保护数据库、web服务还是api接口,正确的黑白名单配置都能有效防止未授权访问。然而,从简单的iptables命令到复杂的doc

前言

在linux服务器安全体系中,端口访问控制是基础而关键的一环。无论是保护数据库、web服务还是api接口,正确的黑白名单配置都能有效防止未授权访问。然而,从简单的iptables命令到复杂的docker环境集成,许多管理员在实践中会遇到各种“坑”。本文将系统性地讲解端口访问控制的原理、实践和排错方法。

一、核心概念:理解防火墙的工作方式

1.1 iptables三层过滤体系

iptables工作在linux内核网络栈,通过表和链的层级结构过滤数据包:

数据包 → 原始表(prerouting) → 过滤表(forward) → 网络地址转换表(postrouting)
                        ↓
                   过滤表(input/output)

对于端口访问控制,我们主要操作过滤表的input链,它决定了哪些外部连接可以访问本机服务。

1.2 规则的匹配原则

这是最容易被误解的部分,请务必记住:

iptables规则从上到下顺序匹配,一旦匹配成功就立即执行对应动作,后续规则不再检查。

这就像公司的门禁系统:如果第一条规则说“拒绝所有人进入”,那么后面再说“允许张三进入”就毫无意义了。

二、iptables实战:从入门到精通

2.1 基础命令速查

# 查看规则(显示编号便于管理)
iptables -l input -n --line-numbers

# 追加规则到链末尾
iptables -a input -p tcp --dport 22 -j accept

# 插入规则到链开头
iptables -i input -p tcp --dport 22 -j accept

# 插入到指定位置(如第3条规则前)
iptables -i input 3 -p tcp --dport 22 -j accept

# 删除指定规则
iptables -d input 3

# 清空所有规则
iptables -f input

2.2 典型白名单配置

让我们通过一个mysql防护的完整案例来理解:

#!/bin/bash
# mysql_whitelist.sh - mysql端口安全加固脚本

port=3306
whitelist=("192.168.1.100" "192.168.1.101" "10.0.0.50")

echo "正在配置mysql端口($port)白名单..."

# 步骤1:备份当前规则
iptables-save > /etc/iptables.backup.$(date +%y%m%d_%h%m%s)

# 步骤2:清除旧规则(避免重复)
iptables -d input -p tcp --dport $port -j drop 2>/dev/null || true
for ip in "${whitelist[@]}"; do
    iptables -d input -p tcp --dport $port -s $ip -j accept 2>/dev/null || true
done

# 步骤3:按正确顺序添加规则
# 3.1 允许本地回环(必须)
iptables -i input -i lo -j accept

# 3.2 允许已建立的连接(防止断开当前会话)
iptables -i input -m state --state established,related -j accept

# 3.3 添加白名单ip
for ip in "${whitelist[@]}"; do
    iptables -a input -p tcp --dport $port -s $ip -j accept
    echo "  ✓ 允许ip: $ip"
done

# 3.4 拒绝其他所有访问(这条规则必须最后添加!)
iptables -a input -p tcp --dport $port -j drop
echo "  ✗ 拒绝其他所有ip访问"

# 步骤4:保存配置
iptables-save > /etc/sysconfig/iptables

# 步骤5:验证配置
echo -e "\n验证规则顺序:"
iptables -l input -n --line-numbers | grep -e "(dpt:$port|policy)"

关键点:注意accept规则在drop规则之前,这是保证白名单生效的前提。

2.3 经典错误案例解析

场景:管理员想先禁止所有访问,再开放特定ip,结果白名单失效。

# ❌ 错误做法(常见陷阱)
iptables -a input -p tcp --dport 3306 -j drop      # 规则1:拒绝所有
iptables -a input -p tcp --dport 3306 -s 192.168.1.100 -j accept  # 规则2:允许特定ip(永远不会执行!)

# ✅ 正确做法
iptables -a input -p tcp --dport 3306 -s 192.168.1.100 -j accept  # 规则1:允许特定ip
iptables -a input -p tcp --dport 3306 -j drop      # 规则2:拒绝其他

诊断技巧

# 查看规则匹配计数器,如果accept规则计数为0,说明从未匹配
iptables -l input -n -v

三、docker环境的特殊挑战

当容器技术遇上防火墙,情况变得复杂。docker默认会修改iptables规则,这可能导致你的配置失效。

3.1 docker的网络管理机制

docker启动时默认会:

  1. 创建dockerdocker-userdocker-isolation等自定义链
  2. forward链中插入跳转规则
  3. 为端口映射创建nat规则
# 查看docker创建的链
iptables -l -n | grep -i docker

# 典型输出示例:
# chain docker (1 references)
# chain docker-isolation (1 references)
# chain docker-user (1 references)

3.2 方案一:使用docker-user链(推荐)

docker 19.03+ 版本引入了docker-user链,专门用于用户自定义规则,且不会被docker覆盖。

#!/bin/bash
# docker_whitelist.sh - docker容器端口白名单

container_port=80
host_port=8080
whitelist=("192.168.1.100" "192.168.1.0/24")

echo "配置docker容器端口白名单..."
echo "容器端口: $container_port, 主机端口: $host_port"

# 清空docker-user链(注意:不影响其他docker规则)
iptables -f docker-user

# 添加基础规则
iptables -a docker-user -i lo -j accept
iptables -a docker-user -m state --state established,related -j accept

# 添加白名单
for ip in "${whitelist[@]}"; do
    iptables -a docker-user -p tcp --dport $host_port -s $ip -j accept
    echo "  ✓ 允许 $ip 访问端口 $host_port"
done

# 拒绝其他所有访问
iptables -a docker-user -p tcp --dport $host_port -j drop
echo "  ✗ 拒绝其他ip访问"

# 查看结果
echo -e "\n当前docker-user链规则:"
iptables -l docker-user -n --line-numbers

3.3 方案二:直接管理input链(无docker链时)

如果系统没有docker链(可能因为docker配置或版本原因),可以像管理普通服务一样操作:

# 检查是否有docker链
if ! iptables -l -n | grep -q "chain docker"; then
    echo "系统无docker链,直接配置input链"
    
    # 允许特定ip访问docker映射的端口
    iptables -a input -p tcp --dport 8080 -s 192.168.1.100 -j accept
    iptables -a input -p tcp --dport 8080 -s 192.168.1.0/24 -j accept
    
    # 拒绝其他
    iptables -a input -p tcp --dport 8080 -j drop
fi

3.4 方案三:docker原生限制(简单场景)

对于简单的ip限制,可以在运行容器时直接指定:

# 只允许特定ip访问
docker run -d \
  --name myapp \
  -p 192.168.1.100:8080:80 \
  nginx

# 允许多个ip访问
docker run -d \
  --name myapp \
  -p 192.168.1.100:8080:80 \
  -p 192.168.1.101:8080:80 \
  nginx

四、firewalld:现代化的防火墙管理

对于需要动态管理规则的环境,firewalld提供了更友好的接口。

4.1 firewalld核心概念

  • zone(区域):预定义的信任级别(public、home、internal等)
  • rich rule(富规则):功能强大的规则语法
  • 运行时配置:支持动态修改,无需重启服务

4.2 常用命令示例

# 查看当前配置
firewall-cmd --get-default-zone
firewall-cmd --list-all

# 添加富规则(永久生效)
firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.100"
  port port="3306" protocol="tcp"
  accept'

# 允许多个ip
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="22" protocol="tcp" accept'

# 添加黑名单
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10" reject'

# 重新加载(不中断现有连接)
firewall-cmd --reload

4.3 与docker集成

# 方法1:直接允许端口访问
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port port="8080" protocol="tcp" accept'

# 方法2:使用端口转发(更灵活)
firewall-cmd --permanent --add-rich-rule='
  rule family="ipv4"
  source address="192.168.1.100"
  forward-port port="8080" protocol="tcp" to-port="80"'

五、高级优化技巧

5.1 使用ipset管理大量ip

当白名单包含成百上千个ip时,使用ipset可以显著提升性能:

# 创建ipset集合
ipset create mysql_whitelist hash:ip

# 批量添加ip
for ip in {1..100}; do
    ipset add mysql_whitelist 192.168.1.$ip
done

# 添加网段
ipset add mysql_whitelist 10.0.0.0/24

# 在iptables中使用
iptables -a input -p tcp --dport 3306 -m set --match-set mysql_whitelist src -j accept

# 保存配置
ipset save > /etc/ipset.conf

5.2 自动化管理脚本

#!/bin/bash
# firewall_manager.sh - 智能防火墙管理

set -euo pipefail

readonly log_file="/var/log/firewall_manager.log"
readonly backup_dir="/etc/iptables/backup"

log() {
    echo "[$(date '+%y-%m-%d %h:%m:%s')] $*" | tee -a "$log_file"
}

backup_rules() {
    mkdir -p "$backup_dir"
    local backup_file="$backup_dir/iptables_$(date +%y%m%d_%h%m%s).rules"
    iptables-save > "$backup_file"
    log "规则已备份到: $backup_file"
}

whitelist_port() {
    local port=$1
    shift
    local ips=("$@")
    
    log "开始配置端口 $port 白名单"
    backup_rules
    
    # 清理旧规则
    iptables -d input -p tcp --dport "$port" -j drop 2>/dev/null || true
    
    # 添加新规则
    for ip in "${ips[@]}"; do
        if ! iptables -c input -p tcp --dport "$port" -s "$ip" -j accept 2>/dev/null; then
            iptables -a input -p tcp --dport "$port" -s "$ip" -j accept
            log "添加白名单: $ip -> 端口 $port"
        fi
    done
    
    # 添加拒绝规则(确保在最后)
    iptables -a input -p tcp --dport "$port" -j drop
    
    # 保存
    iptables-save > /etc/sysconfig/iptables
    log "配置完成"
}

# 使用示例
whitelist_port 3306 "192.168.1.100" "192.168.1.101" "10.0.0.50"

六、故障排查与恢复

6.1 诊断工具箱

# 1. 检查规则顺序和匹配计数
iptables -l input -n -v --line-numbers

# 2. 实时监控规则匹配
watch -n 1 'iptables -l input -n -v | grep :3306'

# 3. 测试连接并观察计数变化
timeout 5 nc -zv 服务器ip 3306 && echo "连接成功" || echo "连接失败"

# 4. 查看详细日志(如果有log规则)
iptables -a input -p tcp --dport 3306 -j log --log-prefix "[iptables-deny] "
tail -f /var/log/messages | grep iptables-deny

# 5. 检查docker相关规则
iptables -t nat -l -n
iptables -l forward -n -v

6.2 紧急恢复方案

如果配置错误导致自己被锁定,可以通过以下方式恢复:

方案a:通过服务器控制台

# 清空所有规则(谨慎使用)
iptables -f
iptables -p input accept

# 或者只恢复ssh访问
iptables -i input -p tcp --dport 22 -j accept

方案b:使用预置的恢复脚本

#!/bin/bash
# emergency_recovery.sh - 防火墙紧急恢复

# 创建恢复标记
touch /tmp/firewall_recovery_mode

# 设置宽松策略
iptables -p input accept
iptables -p forward accept
iptables -p output accept

# 清空所有规则
iptables -f
iptables -t nat -f
iptables -t mangle -f

# 允许基本服务
iptables -a input -i lo -j accept
iptables -a input -p tcp --dport 22 -j accept
iptables -a input -m state --state established,related -j accept

echo "紧急恢复完成,请重新配置防火墙"

6.3 常见问题解答

q1:为什么添加了accept规则还是无法访问?
a:检查规则顺序,确保accept在drop之前;检查默认策略;确认端口监听正常。

q2:docker容器规则重启后丢失?
a:docker重启会重建规则,将自定义规则放在docker-user链中。

q3:如何让iptables规则永久生效?

# centos/rhel
iptables-save > /etc/sysconfig/iptables
systemctl enable iptables

# debian/ubuntu
iptables-save > /etc/iptables/rules.v4
apt-get install iptables-persistent

q4:如何管理大量端口和ip?
a:使用配置管理工具(ansible/saltstack)或编写管理脚本,避免手动操作。

七、最佳实践总结

7.1 安全原则

  1. 最小权限原则:只开放必要的端口给必要的ip
  2. 默认拒绝策略:设置iptables -p input drop,显式允许
  3. 分层防护:结合网络层、主机层、应用层防护
  4. 变更管理:任何规则变更前备份、测试、记录

7.2 操作规范

  1. 使用版本控制:将iptables规则纳入git管理
  2. 注释说明:为复杂规则添加注释
iptables -a input -p tcp --dport 3306 -s 10.0.0.50 -j accept -m comment --comment "允许dba服务器访问mysql"
  1. 定期审计:每月检查一次规则,清理无效条目
  2. 监控告警:设置规则变更告警和异常访问告警

7.3 配置示例模板

#!/bin/bash
# production_firewall_template.sh - 生产环境防火墙模板

set -e

# 备份
backup_rules() {
    iptables-save > /etc/iptables/backup/prod_$(date +%s).rules
}

# 初始化
init_firewall() {
    # 设置默认策略
    iptables -p input drop
    iptables -p forward drop
    iptables -p output accept
    
    # 基础规则
    iptables -a input -i lo -j accept
    iptables -a input -m state --state established,related -j accept
    
    # icmp(根据需要)
    iptables -a input -p icmp --icmp-type echo-request -j accept
}

# 服务规则
setup_services() {
    # ssh(限制ip段)
    iptables -a input -p tcp --dport 22 -s 192.168.1.0/24 -j accept
    iptables -a input -p tcp --dport 22 -s 10.0.0.0/8 -j accept
    
    # web服务
    iptables -a input -p tcp --dport 80 -j accept
    iptables -a input -p tcp --dport 443 -j accept
    
    # 数据库(严格白名单)
    local db_ips=("192.168.1.100" "192.168.1.101")
    for ip in "${db_ips[@]}"; do
        iptables -a input -p tcp --dport 3306 -s "$ip" -j accept
    done
    iptables -a input -p tcp --dport 3306 -j drop
}

# 执行
backup_rules
init_firewall
setup_services

# 保存
iptables-save > /etc/sysconfig/iptables
echo "防火墙配置完成"

结语

端口访问控制是linux系统安全的基石,但也是一把双刃剑。配置得当,它能有效阻挡攻击;配置失误,可能导致服务中断。掌握iptables和firewalld的核心原理,遵循最佳实践,结合自动化工具,你就能构建既安全又可靠的防火墙体系。

记住:测试、备份、渐进式变更是防火墙管理的三大黄金法则。每次变更前问自己三个问题:

  1. 这个规则真的必要吗?
  2. 会不会阻断正常业务?
  3. 如果出问题,如何快速恢复?

安全之路,始于足下。从正确配置第一个端口白名单开始,逐步构建完善的防御体系。

以上就是linux端口访问控制iptables与firewalld的实战指南的详细内容,更多关于linux端口访问控制iptables与firewalld的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com