linux防火墙讲解

目录

安全管理

一、SELinux安全上下文

[1、SELinux 简介](#1、SELinux 简介)

2、基础操作命令

[1. 查看SELinux状态](#1. 查看SELinux状态)

[2. 切换工作模式*](#2. 切换工作模式*)

[3、安全上下文(Security Context)](#3、安全上下文(Security Context))

[1. 查看上下文*](#1. 查看上下文*)

[2. 修改上下文](#2. 修改上下文)

chcon命令

[semanage 命令](#semanage 命令)

4、SELinux布尔值(Booleans)

5、日志分析与故障排除

[1. 查看SELinux日志](#1. 查看SELinux日志)

[2. 生成解决方案建议](#2. 生成解决方案建议)

6、常见问题与解决方案

场景1:Web服务器无法访问文件

场景2:服务无法绑定非标准端口

7、注意事项

8、练习与测试

二、Linux防火墙-Firewalld

[1、 概述](#1、 概述)

[2、 Linux防火墙](#2、 Linux防火墙)

防火墙结构

firewalld防火墙

区域分类

区域功能

firewall-cmd命令用法

[3、 课后实验](#3、 课后实验)

实验拓扑

实验拓扑

实验要求

[**注意 : 该实验只需要配置指定策略即可,不用验证!!!**](#注意 : 该实验只需要配置指定策略即可,不用验证!!!)

三、Linux防火墙-Iptables

[1、 Iptables概述](#1、 Iptables概述)

[2、 Iptables 组成](#2、 Iptables 组成)

表(Table)

链(Chain)

链表对应关系

数据包过滤的匹配流程

规则匹配策略

[3、 Iptables防火墙配置](#3、 Iptables防火墙配置)

iptables命令

常用管理选项

常用控制类型

匹配条件

命令操作

添加新的规则

查看规则

删除规则

清空规则

修改规则

[4、 规则的匹配](#4、 规则的匹配)

1、通用匹配

2、隐含匹配

协议端口匹配

[tcp标记匹配 [了解]](#tcp标记匹配 [了解])

ICMP类型匹配

3、显式匹配

多端口匹配

ip范围匹配

mac地址匹配【了解】

状态匹配【了解】

常见的连接状态

5、Iptables配置NAT地址转换

[1、 配置SNAT](#1、 配置SNAT)

应用场景

模拟实验环境

转换为固定公网ip

转换为非固定的公网ip(动态)

2、配置DNAT

应用场景

模拟实验环境

转换为私网ip

6、iptables防火墙策略的备份和恢复

实验

实验拓扑

网络规划

实验要求

8、实验具体步骤:

一、环境准备(虚拟机基础配置)

[1. 禁用 firewalld 并安装 iptables](#1. 禁用 firewalld 并安装 iptables)

[2. 配置网卡与 IP 转发(同 firewalld 方案)](#2. 配置网卡与 IP 转发(同 firewalld 方案))

[二、实验功能实现(防火墙 sf1 配置)](#二、实验功能实现(防火墙 sf1 配置))

[1. 需求 1:pc1 通过 SNAT 访问外网,但无法 ping 内网网关](#1. 需求 1:pc1 通过 SNAT 访问外网,但无法 ping 内网网关)

[2. 需求 2:服务器 s1 通过 DNAT 发布服务到外网](#2. 需求 2:服务器 s1 通过 DNAT 发布服务到外网)

[3. 需求 3:pc2 可访问 s1 服务,但无法 ping/ssh 连接](#3. 需求 3:pc2 可访问 s1 服务,但无法 ping/ssh 连接)

三、验证步骤

四、关键配置分析

五、故障排查命令


安全管理

一、SELinux安全上下文

1、SELinux 简介

  1. 是什么? SELinux(Security-Enhanced Linux)是Linux内核的**强制访问控制(MAC)**安全子系统,提供更细粒度的权限控制,防止进程或用户越权操作。

  2. 核心思想

  • 最小权限原则:进程/用户只能访问其明确需要的资源。

  • 基于标签的访问控制:所有资源(文件、端口、进程)被赋予安全上下文(Security Context)。

  1. 工作模式(*)

    模式 描述
    Enforcing 强制执行策略,拒绝非法操作并记录日志。
    Permissive 仅记录违规操作,不阻止(用于调试)。
    Disabled 完全关闭SELinux(需重启生效)。

2、基础操作命令

1. 查看SELinux状态
复制代码
getenforce# 查看当前模式
sestatus# 详细状态(模式/策略类型)
2. 切换工作模式*
复制代码
setenforce 0# 切换到Permissive模式
setenforce 1# 切换到Enforcing模式

注意:setenforce仅临时生效,永久修改需编辑 /etc/selinux/config 文件。


3、安全上下文(Security Context)

1. 查看上下文*
复制代码
ls -Z /var/www/html # 查看文件/目录的上下文
ps -Z -C httpd# 查看进程的上下文
2. 修改上下文
chcon命令
选项 说明 示例消息
-t, --type TYPE 设置安全上下文的类型部分 已将 file.txt 的类型更改为 httpd_sys_content_t
-u, --user USER 设置安全上下文的用户部分 已将 file.txt 的用户更改为 system_u
-r, --role ROLE 设置安全上下文的角色部分 已将 file.txt 的角色更改为 object_r
--reference=FILE 使用指定文件的安全上下文 已从 ref_file 复制上下文到 target_file
-R, --recursive 递归处理文件和目录 已递归更改 dir/ 及其内容的上下文
-h, --help 显示帮助信息 显示帮助菜单
-v, --verbose 显示操作详情 正在更改 file.txt 的安全上下文
--version 显示版本信息 chcon (GNU coreutils) 8.32

选项使用案例

  1. 设置文件类型 将 /var/www/html/index.html 的上下文类型设为 httpd_sys_content_t:

    复制代码
    sudo chcon -t httpd_sys_content_t /var/www/html/index.html
  2. 设置用户部分 将 /etc/nginx/nginx.conf 的用户部分设为 system_u:

    复制代码
    sudo chcon -u system_u /etc/nginx/nginx.conf
  3. 设置角色部分 将 /home/user/file.txt 的角色部分设为 object_r:

    复制代码
    sudo chcon -r object_r /home/user/file.txt
  4. 参照文件上下文 将 file2 的上下文设置为与 file1 一致:

    复制代码
    sudo chcon --reference=file1 file2
  5. 递归操作目录 递归修改 /var/www/html/ 目录下所有文件的上下文类型:

    复制代码
    sudo chcon -R -t httpd_sys_content_t /var/www/html/
  6. 显示帮助信息

    复制代码
    chcon --help
  7. 显示版本信息

    复制代码
    chcon --version
  8. 详细模式操作 启用详细输出,修改 ~/.ssh/config 的上下文类型:

    复制代码
    sudo chcon -v -t ssh_home_t ~/.ssh/config

说明

  • 实际执行时,若未添加 -v 参数,chcon 默认不输出成功信息,仅在出错时显示错误。

  • 使用 -v 参数可查看操作详情(如上述表格中的"示例消息")。

复制代码
chcon -t httpd_sys_content_t /var/www/html/index.html # 临时修改文件类型
restorecon -v /var/www/html/index.html # 恢复默认上下文

semanage 命令
子命令/选项 用途说明 常用选项 示例消息/操作
semanage login 管理SELinux用户与Linux账户的映射关系 -a (添加)、-d (删除)、-m (修改) 将用户 user1 映射到 SELinux 用户 staff_u
semanage user 管理SELinux用户及其角色和权限 -a、-d、-R (角色)、-L (限制) 创建新SELinux用户 web_user 并分配角色 httpd_role
semanage port 管理网络端口与SELinux类型的绑定关系 -a、-d、-t (类型)、-p (协议) 将TCP端口 8080 绑定到 http_port_t 类型
semanage interface 管理网络接口与SELinux类型的绑定关系 -a、-d、-t 将接口 eth1 绑定到 netif_t 类型
semanage module 管理SELinux策略模块(启用/禁用) -a、-d、-e (启用)、-D (禁用) 启用策略模块 my_custom_module
semanage fcontext 管理文件/目录的默认SELinux上下文规则 -a、-d、-t、-s (范围) 添加规则:/webapps(/.*)? 的上下文类型为 httpd_sys_content_t
semanage boolean 管理SELinux布尔值(开关策略功能) -1 (查看)、--on、--off 启用布尔值 httpd_can_network_connect
semanage dontaudit 管理dontaudit规则(是否记录特定访问拒绝事件) --on、--off 关闭对 sshd 的 dontaudit 规则
-h / --help 显示帮助信息 - 显示子命令的帮助菜单
-v / --verbose 显示详细操作信息 - 显示添加端口 8080 的详细过程
-n / --noheading 输出时隐藏列标题 - 仅显示端口列表数据,无标题行

选项使用案例

  1. 管理端口绑定

将TCP端口 8080 标记为HTTP服务端口:

复制代码
sudo semanage port -a -t http_port_t -p tcp 8080

说明:允许Apache等HTTP服务使用8080端口。


  1. 管理文件上下文规则

为自定义Web目录 /opt/webapps 设置默认上下文:

复制代码
sudo semanage fcontext -a -t httpd_sys_content_t "/opt/webapps(/.*)?"
sudo restorecon -Rv /opt/webapps

说明:添加规则后需运行 restorecon 立即生效。


  1. 管理SELinux用户映射

将Linux用户 dev_user 映射到SELinux用户 user_u:

复制代码
sudo semanage login -a -s user_u dev_user

说明:限制用户 dev_user 的SELinux权限。


  1. 启用布尔值

允许HTTP服务访问网络:

复制代码
sudo semanage boolean --on httpd_can_network_connect

说明:无需重启服务,立即生效。


  1. 管理策略模块

禁用自定义策略模块 mymodule:

复制代码
sudo semanage module -D mymodule

说明:禁用后相关规则不再生效。


  1. 查看当前端口绑定

列出所有HTTP相关端口:

复制代码
semanage port -l | grep http_port_t

输出示例

复制代码
http_port_t    tcp    80, 443, 8080

  1. 删除文件上下文规则

移除对 /tmp/custom_dir 的上下文规则:

复制代码
sudo semanage fcontext -d "/tmp/custom_dir(/.*)?"

注意事项

  • 权限要求:大多数操作需 sudo 或 root 权限。

  • 持久化存储:semanage 修改的规则会保存到策略库(默认路径 /etc/selinux/targeted),重启后仍有效。

  • 结合工具使用:修改文件上下文后,需运行 restorecon 或重启服务使更改生效。

4、SELinux布尔值(Booleans)

SELinux策略通过布尔值动态调整权限控制(例如允许Apache访问用户家目录)。

复制代码
getsebool -a | grep httpd# 查看所有与Apache相关的布尔值
setsebool -P httpd_enable_homedirs=on # 启用布尔值(-P永久生效)

5、日志分析与故障排除

1. 查看SELinux日志
复制代码
tail -f /var/log/audit/audit.log # 直接查看原始日志
ausearch -m AVC -ts recent# 使用工具过滤日志
2. 生成解决方案建议
复制代码
grep "avc: denied" /var/log/audit/audit.log | audit2allow -M mypolicy
semodule -i mypolicy.pp# 编译并加载自定义策略

6、常见问题与解决方案

场景1:Web服务器无法访问文件
  • 现象:Apache返回403错误,但文件权限正常。

  • 解决

    1. 检查文件上下文:ls -Z /var/www/html

    2. 修复上下文:restorecon -Rv /var/www/html

场景2:服务无法绑定非标准端口
  • 现象:Nginx无法监听8080端口。

  • 解决

    复制代码
    semanage port -a -t http_port_t -p tcp 8080# 添加端口到SELinux策略

7、注意事项

  1. 不要随意禁用SELinux:优先使用Permissive模式调试。

  2. 谨慎使用chcon:错误修改上下文可能导致系统不稳定。

  3. 备份策略:修改策略前备份 /etc/selinux 目录。


8、练习与测试

  1. 将SELinux切换为Permissive模式,测试服务异常是否由SELinux引起。

  2. 使用audit2why分析日志,生成解决方案并应用。

  3. 为FTP服务配置允许上传文件到自定义目录。


推荐工具

  • sealert:生成更友好的日志分析报告。

  • semanage:管理SELinux策略(需安装policycoreutils-python-utils)。

二、Linux防火墙-Firewalld

1、 概述

按表现形式划分:

软件防火墙: 集成在系统内部,Linux系统: iptables、firewalld、ufw; windows系统下: windows defender

硬件防火墙: 华为防火墙、思科防火墙、奇安信防火墙、深信服防火墙等

按技术划分:

包过滤防火墙: 检查数据包的源IP、目的IP、源端口、目的端口、TCP的syn控制位

七层防火墙:除了上述检查外,还会检查数据内容

防火墙的作用:

阻止来自网络外部的攻击、进行流量控制

2、 Linux防火墙

防火墙结构

用户态:

iptables: 使用iptables命令对防火墙规则进行管理,必须深度理解网络技术和四表五链,对于初学者或者网络技术不达标的人员不友好

**firewalld:**使用firewall-cmd命令对防火墙进行管理,采用的是区域划分的形式。不需要连接底层的四表五链,对于初学者比较友好

ufw: 使用ufw命令对防火墙进行管理,命令简单易懂。

内核态:

四表: 从内核->用户的顺序: raw -> mangle -> nat -> filter

五链: input、output、forward、prerouting、postrouting

firewalld防火墙
区域分类

九大区域: block、dmz、drop、external、home、internal、public、trusted、work

区域功能

public:公共区域,默认区域

复制代码
public (active)
target: default #区域类型规则
icmp-block-inversion: no
interfaces: ens33 #属于该区域的接口
sources:#来源
services: dhcpv6-client ssh #放行服务的名称
ports:#放行端口号
protocols:#放行协议
masquerade: no#NAT地址转换
forward-ports:#转发端口
source-ports:#源端口
icmp-blocks:#ICMP的阻塞类型,ping的阻塞
rich rules:#富规则

home: 家庭区域

复制代码
home
target: default
icmp-block-inversion: no
interfaces: 
sources: 
services: dhcpv6-client mdns samba-client ssh
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules:

work: 工作区域

复制代码
work
target: default
icmp-block-inversion: no
interfaces: 
sources: 
services: dhcpv6-client ssh
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules: 

trusted: 完全信任区域

复制代码
trusted
target: ACCEPT#不采用默认规则,放行一切
icmp-block-inversion: no
interfaces: 
sources: 
services: 
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules: 

internal: 内部区域 (连接内部网络)

复制代码
internal
target: default
icmp-block-inversion: no
interfaces: 
sources: 
services: dhcpv6-client mdns samba-client ssh
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules: 

external: 外部区域 (连接外部网络,例如: internet网络)

复制代码
ternal
target: default
icmp-block-inversion: no
interfaces: 
sources: 
services: ssh
ports: 
protocols: 
masquerade: yes#默认进行NAT地址转换
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules: 

dmz: 非军事化管理区域(内部的服务器放于该区域)

复制代码
dmz
target: default
icmp-block-inversion: no
interfaces: 
sources: 
services: ssh
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules:

drop: 丢弃区域(丢弃一切流量,不给出任何回应)

复制代码
drop
target: DROP
icmp-block-inversion: no
interfaces: 
sources: 
services: 
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules:

block: 阻塞区域 (拒绝任何流量,但给出回应)

复制代码
block
target: %%REJECT%%
icmp-block-inversion: no
interfaces: 
sources: 
services: 
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules:
firewall-cmd命令用法

关键字:

复制代码
--list-*
--get-*
--set-*
--add-*
--remove-*
--change-*
--zone=

命令分类:

查看:

复制代码
#查看所有区域的详细信息
[root@localhost ~]# firewall-cmd --list-all-zones 
#查看指定区域的详细信息
[root@localhost ~]# firewall-cmd --list-all --zone=public 
#查看指定区域的放行服务
[root@localhost ~]# firewall-cmd --list-services --zone=public 
#查看指定区域的放行端口
[root@localhost ~]# firewall-cmd --list-ports --zone=public 
#查看指定区域包含的网络接口
[root@localhost ~]# firewall-cmd --list-interfaces --zone=public 
#查看指定区域的放心协议
[root@localhost ~]# firewall-cmd --list-protocols --zone=public
#查看指定区域的ICMP阻塞类型
[root@localhost ~]# firewall-cmd --list-icmp-blocks --zone=public
#查看指定区域的放行源地址
[root@localhost ~]# firewall-cmd --list-sources --zone=public
#查看指定区域的源端口
[root@localhost ~]# firewall-cmd --list-source-ports --zone=public
#查看指定区域的富规则
[root@localhost ~]# firewall-cmd --list-rich-rules --zone=public 
#查看指定区域的转发端口
[root@localhost ~]# firewall-cmd --list-forward-ports --zone=public 
#查看firewalld支持的服务类型
[root@localhost ~]# firewall-cmd --get-services
#查看firewalld的默认区域
[root@localhost ~]# firewall-cmd--get-default-zone
#查看firewalld支持的ICMP的阻塞类型
[root@localhost ~]# firewall-cmd--get-icmptypes 
#查看firewalld所有的活动区域
[root@localhost ~]# firewall-cmd --get-active-zones
#查看指定网络接口所属区域
[root@localhost ~]# firewall-cmd --get-zone-of-interface=ens33
#查看所有区域名称
[root@localhost ~]# firewall-cmd --get-zones

添加:

复制代码
#添加指定服务到指定区域
[root@localhost ~]# firewall-cmd --add-service=http --zone=public 
success
#添加端口到指定区域
[root@localhost ~]# firewall-cmd --add-port=80/tcp --zone=public 
success
#添加指定协议到指定区域
[root@localhost ~]# firewall-cmd --add-protocol=ah --zone=public 
success
#添加ICMP阻塞类型到指定区域
[root@localhost ~]# firewall-cmd --add-icmp-block=echo-request --zone=public 
success
#windows端验证
C:\Users\zzh>ping 192.168.115.129
​
正在 Ping 192.168.115.129 具有 32 字节的数据:
来自 192.168.115.129 的回复: 无法访问目标主机。
来自 192.168.115.129 的回复: 无法访问目标主机。
来自 192.168.115.129 的回复: 无法访问目标主机。
#添加指定网络接口到指定区域
[root@localhost ~]# firewall-cmd --add-interface=ens33 --zone=work 
success
#添加指定区域的放行源地址
[root@localhost ~]# firewall-cmd --add-source=192.168.1.0/24 --zone=work 
success
#添加指定区域的放行源端口
[root@localhost ~]# firewall-cmd --add-source-port=999/tcp --zone=work 
success
#添加转发端口到指定区域
[root@localhost ~]# firewall-cmd --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=192.168.115.115 --zone=work 
success
#添加地址转换功能到指定区域
[root@localhost ~]# firewall-cmd --add-masquerade --zone=work 
success
#验证添加
[root@localhost ~]# firewall-cmd --list-all --zone=public 

修改:

复制代码
#修改默认区域
[root@localhost ~]# firewall-cmd --set-default-zone=work
success
#修改网络接口所属区域
[root@localhost ~]# firewall-cmd --change-interface=ens33 --zone=internal 
success
[root@localhost ~]# firewall-cmd --change-zone=ens33 --zone=external 
success
#追加指定区域的放行源地址
[root@localhost ~]# firewall-cmd --change-source=192.168.2.0/24 --zone=work 
success

删除:

复制代码
#删除指定服务到指定区域
[root@localhost ~]# firewall-cmd --remove-service=http --zone=public 
success
#删除端口到指定区域
[root@localhost ~]# firewall-cmd --remove-port=80/tcp --zone=public 
success
#删除指定协议到指定区域
[root@localhost ~]# firewall-cmd --remove-protocol=ah --zone=public 
success
#删除ICMP阻塞类型到指定区域
[root@localhost ~]# firewall-cmd --remove-icmp-block=echo-request --zone=public 
success
#删除指定网络接口到指定区域
[root@localhost ~]# firewall-cmd --remove-interface=ens33 --zone=work 
success
#删除指定区域的放行源地址
[root@localhost ~]# firewall-cmd --remove-source=192.168.1.0/24 --zone=work 
success
#删除指定区域的放行源端口
[root@localhost ~]# firewall-cmd --remove-source-port=999/tcp --zone=work 
success
#删除转发端口到指定区域
[root@localhost ~]# firewall-cmd --remove-forward-port=port=8080:proto=tcp:toport=80:toremover=192.168.115.115 --zone=work 
success
#删除地址转换功能到指定区域
[root@localhost ~]# firewall-cmd --remove-masquerade --zone=work 
success
#验证删除
[root@localhost ~]# firewall-cmd --list-all --zone=public 

保存规则:

复制代码
#逐行规则保存
[root@localhost ~]# firewall-cmd --remove-masquerade --zone=work --permanent
#一次性保存所有规则
[root@localhost zones]# firewall-cmd --runtime-to-permanent
success
#保存的规则存储路径
/etc/firewalld/zones

案例:

禁止外部主机ping本机

复制代码
#本机IP:192.168.115.129 ens33 NAT
#外部IP:192.168.115.128
#防火墙配置
[root@localhost ~]# firewall-cmd --add-interface=ens33 --zone=work 
success
[root@localhost ~]# firewall-cmd --add-icmp-block=echo-request --zone=work 
success
#验证
[root@localhost ~]# ping -c 4 192.168.115.129
PING 192.168.115.129 (192.168.115.129) 56(84) bytes of data.
From 192.168.115.129 icmp_seq=1 Destination Host Prohibited
From 192.168.115.129 icmp_seq=2 Destination Host Prohibited
From 192.168.115.129 icmp_seq=3 Destination Host Prohibited
From 192.168.115.129 icmp_seq=4 Destination Host Prohibited
​
--- 192.168.115.129 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3001ms

允许外部主机访问本机的http服务

复制代码
#本机IP:192.168.80.128 ens34 vmnet3
#外部IP:192.168.80.129
#######环境配置 开始#########
##本机安装httpd服务
#改变SElinux的规则
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum install -y httpd
##启动httpd服务
[root@localhost ~]# systemctl start httpd
##修改httpd服务的监听IP
[root@localhost ~]# vim /etc/httpd/conf/httpd.conf
Listen 192.168.80.128:80
##重启httpd服务
[root@localhost ~]# systemctl restart httpd
##验证服务监听状态
[root@localhost ~]# netstat -naptu | grep :80
tcp00 192.168.80.128:800.0.0.0:* LISTEN5884/httpd 
#######环境配置 结束#########
#防火墙配置
[root@localhost ~]# firewall-cmd --change-interface=ens34 --zone=dmz
success
##客户端验证访问##
[root@localhost ~]# curl 192.168.80.128
curl: (7) Failed connect to 192.168.80.128:80; 拒绝连接
##发现无法访问###
#服务端查看dmz区域信息
[root@localhost ~]# firewall-cmd --list-all --zone=dmz
dmz (active)
target: default
icmp-block-inversion: no
interfaces: ens34
sources: 
services: ssh
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules: 
#发现没有放心http服务
#配置dmz区域http服务放行策略
[root@localhost ~]# firewall-cmd --add-service=http --zone=dmz 
success
dmz (active)
target: default
icmp-block-inversion: no
interfaces: ens34
sources: 
services: http ssh
ports: 
protocols: 
masquerade: no
forward-ports: 
source-ports: 
icmp-blocks: 
rich rules:

允许外部主机访问本机的某个端口号

复制代码
#前置环境如上
#防火墙配置
[root@localhost ~]# firewall-cmd --add-port=801/tcp --zone=dmz 
success
#放行服务的本质实际上是放行了该服务的默认端口号!!!
#假如服务改变了监听端口号,只需放行对应的端口号即可!!!
#客户端验证
[root@localhost ~]# curl 192.168.80.128:801​

三、Linux防火墙-Iptables

1、 Iptables概述

Iptables 是一个用户空间程序,可以用于设置和管理 Linux 操作系统的内核级防火墙。它通过表、链和规则组成,可以灵活地根据不同的需求进行配置。

iptables 具有以下特点:

  • Iptables 作为内核级别的防火墙,具有高效、稳定、安全等优点。

  • Iptables 的表、链、规则结构非常灵活,可适应各种不同的网络环境和应用场景。

  • Iptables 相对于其他防火墙工具而言比较容易学习和掌握,并且拓展性非常强。

2、 Iptables 组成

Iptables 的核心是由表(table)、链(chain)和规则(rule)三部分组成的。

表(Table)

在 iptables 中,表是一个规则的集合,每个表都包含若干个链和一些相关的规则。常用的五种 table 如下:

  • raw表:确定是否对该数据包进行状态跟踪。包含两个规则链,OUTPUT、PREROUTING。

  • mangle表:修改数据包内容,用来做流量整形的,给数据包设置标记。包含五个规则链,INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING。

  • nat表:负责网络地址转换,用来修改数据包中的源、目标IP地址或端口。包含三个规则链,OUTPUT、PREROUTING、POSTROUTING。

  • filter表:负责过滤数据包,确定是否放行该数据包(过滤)。包含三个规则链,INPUT、FORWARD、OUTPUT。

表之间的优先级

数据包到达防火墙时,规则表之间的优先顺序 ​ raw > mangle > nat > filter

链(Chain)

在 iptables 中,链是一个规则的集合,每个链都包含一些相关联的规则。

  • INPUT链: 当接收到防火墙本机地址的数据包(入站)时,应用此链中的规则。

  • OUTPUT链: 当防火墙本机向外发送数据包(出站)时,应用此链中的规则。

  • FORWARD链: 当接收到需要通过防火墙发送给其他地址的数据包(转发)时,应用此链中的规则。

  • PREROUTING链: 在对数据包作路由选择之前,应用此链中的规则,用来修改目的地址,如DNAT。

  • POSTROUTING链: 在对数据包作路由选择之后,应用此链中的规则,用来修改源地址,如SNAT,端口映射等。

链表对应关系
数据包过滤的匹配流程
  • 入站

入站数据包从A网络发到B网络,首先发到防火墙,先后顺序经过有PREROUTING链的三个表(raw、mangle、nat),如果都是放通状态的会经过路由选择,然后根据目的地址一层一层往上送,经过有INPUT的两个表(mangle、filter),一直送到应用程序。

  • 转发

目的地不是本机,数据包先从A网络过滤,经过PREROUTING链,看是否是自己的目的地址,如果是外网到内网需要用nat转换成内网IP,找到内网用户,经过FORWARD链进行过滤,允许放通的到达POSTROUING链,再把内网地址转换成公网,这样数据包才能回去;如果是内网往外网发顺序就是反过来。

  • 出站

从本机的应用程序发出来, 经过路由选择,让路由知道从哪里发,先后顺序经过有OUTPUT链的四个表(raw、mangle、nat、filter),都放通后到达POSTROUING链的两个表(mangle、nat),如果没有什么转换地址,就出站。

  • 总结

当一个数据包进入网卡时,数据包首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去。

如果数据包是进入本机的,数据包就会沿着图向上移动,到达INPUT链。数据包到达INPUT链后, 任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包经过OUTPUT链,然后发送出去。

如果数据包是要转发出去的,且内核允许转发,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出。

规则匹配策略

3、 Iptables防火墙配置

iptables命令

语法 iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 控制类型]

注意:链名必须大写;控制类型必须大写

选项 作用
-t 指定表名(raw、mangle、nat、filter)
-j 指定控制类型
常用管理选项
选项 作用
-A (--append) 在指定链的末尾追加一条新的规则
-I (--insert) 在指定链的开头插入一条新的规则;未指定序号时默认作为第一条规则
-R (--replace) 修改、替换指定链中的某一条规则,可指定规则序号或具体内容
-P (--policy) 设置指定链的默认策略
-D (--delete) 删除指定链中的某一条规则,可指定规则序号或具体内容
-F (--flush) 清空指定链中的所有规则;若未指定链名,则清空表中的所有链
-L (--list) 列出指定链中所有的规则;若未指定链名,则列出表中的所有链
-n (--numeric) (搭配-L使用)使用数字形式显示输出结果,如显示IP地址而不是主机名
-v (搭配-L使用)显示详细信息,包括每条规则的匹配包数量和匹配字节数
--line-numbers (搭配-L使用)查看规则时,显示规则的序号
常用控制类型
控制类型 作用
ACCEPT 允许数据包通过
DROP 直接丢弃数据包,不给出任何回应消息
REJECT 拒绝数据包通过,会给数据发送端一个响应信息
SNAT 修改数据包的源地址
DNAT 修改数据包的目的地址
MASQUERADE 伪装成---个非固定公网IP地址
LOG 在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则。(没有真正处理数据包)
匹配条件
匹配条件 说明
-p 指定要匹配的数据包的协议类型
-s 指定要匹配的数据包的源IP地址
-d 指定要匹配的数据包的目的IP地址
-i 指定数据包进入本机的网络接口
-o 指定数据包离开本机做使用的网络接口
--sport 指定源端口号
--dport 指定目的端口号
命令操作
添加新的规则
复制代码
##-A 在filter表的INPUT链末行添加拒绝icmp的规则
[root@localhost ~]# iptables -t filter -A INPUT -p icmp -j REJECT
​
##-I 不指定行,是在指定链首行插入规则(允许tcp 22端口)
[root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT
​
##-I 指定行,是在指定链的指定行上插入规则
[root@localhost ~]# iptables -t filter -I INPUT 2 -p tcp --dport 22 -j ACCEPT
查看规则
复制代码
##查看指定表的规则(不加链名显示所有链的所有规则)
[root@localhost ~]# iptables -t filter -L
​
##-nL 以数字形式显示
[root@localhost ~]# iptables -t filter -nL
​
##-nvL 以数字形式显示,并显示详细信息
[root@localhost ~]# iptables -t filter -nvL
​
##--line-numbers 显示规则序号(指定链名,就显示指定链的规则)
[root@localhost ~]# iptables -t filter -nvL INPUT --line-numbers
编号  包数量 大小  规则      协议选项 入站网卡 出站网卡源地址               目的地址                条件
num pkts bytes target prot opt in out source destination 
12 168 ACCEPT icmp --** 192.168.1.2500.0.0.0/0 
29 844 REJECT icmp --** 0.0.0.0/00.0.0.0/0reject-with icmp-port-unreachable
392041 ACCEPT tcp--** 192.168.1.2500.0.0.0/0tcp dpt:22
4346 24461 ACCEPT tcp--** 192.168.1.2520.0.0.0/0tcp dpt:22
5 312548 REJECT tcp--** 0.0.0.0/00.0.0.0/0tcp dpt:22 reject-with icmp-port-unreachable
​
删除规则

注意

若规则列表中有多条相同的规则时,按内容匹配只删除的序号最小的一条

按号码匹配删除时,确保规则号码小于等于已有规则数,否则报错 按内容匹配删数时,确保规则存在,否则报错

复制代码
##根据规则序号删
[root@localhost ~]# iptables -D INPUT 3
​
##根据规则内容删(相当于操作一遍创建指定规则的步骤加上-D选项删除)
[root@localhost ~]#iptables -D INPUT -p icmp -j REJECT
​
##有相同的规则会删除第一个
[root@localhost ~]#iptables -nL
​
[root@localhost ~]#iptables -D INPUT -p tcp --dport 22 -j ACCEPT
清空规则

注意

-F仅仅是清空链中的规则,并不影响-Р设置的默认规则,默认规则需要手动进行修改

-P设置了默认规则为DROP后,使用-F一定要小心,因为iptables的修改是立刻生效的! 防止把允许远程连接的相关规则清除后导致无法远程连接主机,此情况如果没有保存规则可重启主机解决

如果不写表名和链名,默认清空filter表中所有链里的所有规则

复制代码
##清空指定链中所有规则
[root@localhost ~]# iptables -F OUTPUT
##不指定链名默认清空所有规则
[root@localhost ~]# iptables -F
修改规则
复制代码
##-R 修改已有的规则
[root@localhost ~]# iptables -t filter -R INPUT 1 -p icmp -j ACCEPT
​
##-P 修改默认策略(修改为丢弃转发数据包)
[root@localhost ~]# iptables -P FORWARD DROP

4、 规则的匹配

1、通用匹配
复制代码
可直接使用,不依赖其他条件或扩展包括网络协议、IP地址、网络接口等条件。
类型 选项
协议匹配 -p 协议名
地址匹配 -s 源地址 -d 目的地址(可以是IP、网段、域名、空(代表任何地址))
接口匹配 -i 入站网卡 -o 出站网卡
复制代码
##(使用!取反)不是icmp协议的其他数据包全部接受
##虽然不是icmp包都接受,但是没有指定icmp包的规则,所以icmp包默认还是接受的
[root@localhost ~]# iptables -A INPUT ! -p icmp -j ACCEPT
​
##将指定主机192.168.116.20的数据包丢弃
[root@localhost ~]# iptables -A INPUT -s 192.168.116.20 -j DROP
​
##拒绝指定网段的数据包从ens33网卡进入
[root@localhost ~]# iptables -I INPUT -i ens33 -s 192.168.110.0/24 -j REJECT​
2、隐含匹配

某些条件,如端口、TCP标记、ICMP类型,隐含要求以特定的协议匹配作为前提。

协议端口匹配
复制代码
--sport 和 --dsport 必须配合 -p 指定协议使用!!!

详细用法

类型 作用
--sport 1000 匹配源端口是1000的数据包
--sport 1000:3000 匹配源端口是1000-3000的数据包
--dport :3000 匹配目标端口是3000及以下的数据包
--dport 1000: 匹配目标端口是1000及以上的数据包
复制代码
##允许tcp的20和21端口通过(即允许ftp数据包)
[root@localhost ~]# iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT
​
##丢弃192.168.11.0网段转发的tcp 24000到24500 端口的数据包
[root@localhost ~]# iptables -I FORWARD -d 192.168.11.0/24 -p tcp --dport 24000:24500 -j DROP
tcp标记匹配 [了解]
复制代码
--tcp-flags 配合 -p tcp 使用,指定tcp标记(SYN、ACK、RST、URG、PSH、FIN)
复制代码
##丢弃SYN请求包,允许其他指定的数据包
[root@localhost ~]# iptables -A INPUT -p tcp --tcp-flags SYN,RST,ACK SYN -j ACCEPT
​
##SYN,RST,ACK SYN前面指定包范围,空格后再指定
##表明前面指定的里面,除了这空格后面的SYN,其他都放行
​
##tcp三次握手第一次接受SYN,拒绝其他,第二次发送SYN和ACK
[root@localhost ~]# iptables -I INPUT -p tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSHSYN -j REJECT
[root@localhost ~]# iptables -I OUTPUT -p tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECT
ICMP类型匹配
复制代码
--icmp-type 配合 -p icmp 使用,指定icmp类型(字符串或数字代码)
icmp类型可用iptables -p icmp -h 查看帮助信息
类型 含义
Echo-Request(代码为8) 请求
Echo-Reply (代码为0) 回显
Destination-Unreachable(代码为3) 目标不可达
复制代码
##丢弃icmp请求包(使别人不能ping通本机,但本机默认情况可以ping通别人)
[root@localhost ~]# iptables -A INPUT -p icmp --icmp-type 8 -j DROP
​
##丢弃icmp回显包(本机发送ping请求,但是别人回显的包被本机丢弃,默认情况下本机不能ping通别人)
[root@localhost ~]# iptables -A INPUT -p icmp --icmp-type 0 -j DROP
​
##当ping不通时,允许显示目标不可达
[root@localhost ~]# iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT
3、显式匹配
复制代码
要求以 -m (扩展模块)的形式明确指出类型,包括多端口、MAC地址、IP范围、数据包状态等条件。
多端口匹配
复制代码
-m multiport --sport 源端口列表
-m multiport --dport 目的端口列表
复制代码
##允许tcp的20,21,22,53端口
[root@localhost ~]# iptables -A INPUT -p tcp -m multiport --dport 20,21,22,53 -j ACCEPT
Chain INPUT (policy ACCEPT)
target prot opt source destination 
ACCEPT tcp--0.0.0.0/00.0.0.0/0multiport dports 20,21,22,53
##允许udp的53,67,68端口
[root@localhost ~]# iptables -A INPUT -p udp -m multiport --dport 53,67,68 -j ACCEPT
ip范围匹配
复制代码
-m iprange --src-range 源IP范围
-m iprange --dst-range 目的IP范围
复制代码
##禁止转发源ip范围是192.168.10.100-192.168.10.200的udp数据包
[root@localhost ~]# iptables -A FORWARD -p udp -m iprange --src-range 192.168.10.100-192.168.10.200 -j DROP
Chain FORWARD (policy ACCEPT)
target prot opt source destination 
DROP udp--0.0.0.0/00.0.0.0/0source IP range 192.168.1.1-192.168.1.10 
##禁止发送目的ip范围是192.168.10.100-192.168.10.200的udp数据包
[root@localhost ~]# iptables -A INPUT -p udp -m iprange --dst-range 192.168.10.100-192.168.10.200 -j DROP
​
mac地址匹配
复制代码
-m mac --mac-source 源MAC地址
状态匹配
复制代码
-m state --state 连接状态
常见的连接状态
状态 含义
NEW 本机要连接目标主机,在目标主机上看到的第一个想要连接的包
ESTABLISHED 本机已与目标主机进行通信,判断标准只要目标主机回应了第一个包,就进入该状态
RELATED 本机已与目标主机进行通信,目标主机发起新的链接方式,一般与ESTABLISHED配合使用
INVALID 无效的封包,例如数据破损的封包状态
复制代码
##第一个包我只看22端口的包(-p tcp是隐含匹配,可以省略-m tcp)
[root@localhost ~]# iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
​
##允许放通tcp和udp的这些端口号
[root@localhost ~]# iptables -A INPUT -p tcp -m multiport --dport 443,80,22,21,20,53 -j ACCEPT
[root@localhost ~]# iptables -A INPUT -p udp -m multiport --dport 53 -j ACCEPT
​
##使已建立连接的包以及该链接相关的包允许通过
[root@localhost ~]# iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
​
##默认策略设为drop,以上所有配置就成了一个tcp相关包的白名单,通过第一步的检测后允许相关包通过
[root@localhost ~]# iptables -P INPUT DROP

5、Iptables配置NAT地址转换

1、 配置SNAT
应用场景
复制代码
局域网主机共享转换的公网ip接入internet公网(内 --> 外)
模拟实验环境
复制代码
私网客户端一台、网关服务器一台(设置iptables防火墙)、外网web服务端(有httpd服务)
三台都需要关闭默认防火墙firewalld和selinux
准备私网客户端:设置网卡网段为192.168.1.0/24;ip设为192.168.1.1;网关设为192.168.1.254。
准备网关服务器:一个网卡设为192.168.1.0/24网段,并设置ip为192.168.1.254;另一个网卡设为10.0.0.0/8网段,并设置ip为10.0.0.100;添加路由转发功能;下载 iptables-services 并开始iptables之后做防护墙策略。
准备外网web服务端:设置网卡网段为10.0.0.0/8;ip设为10.0.0.1;下载并开启httpd服务。
转换为固定公网ip
复制代码
iptables -t nat -A POSTROUTING -s 源网段 -o 出站网卡 -j SNAT --to 转换的公网地址
iptables -t nat -A POSTROUTING -s 源网段 -o 出站网卡 -j SNAT --to-source 转换的公网地址范围(如10.0.0.1-10.0.0.10)
注:每一个做转换的公网ip,一般可以支持内网100~200台主机。
复制代码
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ens33 -j SNAT --to 10.0.0.100
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ens33 -j SNAT --to-source 10.0.0.1 10.0.0.10
转换为非固定的公网ip(动态)
复制代码
iptables -t nat -A POSTROUTING -s 源网段 -o 出站网卡 -j MASQUERADE
复制代码
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE
2、配置DNAT
应用场景
复制代码
在internet公网中发布位于企业局域网的服务器(外 --> 内)
模拟实验环境
复制代码
私网客户端一台(有httpd服务)、网关服务器一台(设置iptables防火墙)、外网web服务端
三台都需要关闭默认防火墙firewalld和selinux
可参考上个模拟场景,再为私网主机增设httpd服务使之成为私网web服务端,将原来的外网主机当做客户端。
为私网主机添加httpd服务并启用
转换为私网ip
复制代码
 iptables -t nat -A PREROUTING -i 连接外部网络的接口名称 -d 外部接口IP地址 -p tcp --dport 发布的端口号 -j DNAT --to-destination 服务器内部网络地址:服务实际端口号
复制代码
[root@localhost ~]# iptables -t nat -A PREROUTING -i ens33 -d 10.0.0.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2

6、iptables防火墙策略的备份和恢复

iptables的配置存放在/etc/sysconfig/iptables 文件中,我们对iptables所做的策略修改,虽然会立刻生效,但是并没有保存下来,当我们重启iptables防火墙时,会读取配置文件中设置的策略,我们之前修改过的策略便失效了。所以需要对修改的iptables策略进行备份和恢复。

复制代码
iptables-save > 备份文件 将修改的iptables策略导入到备份文件中
iptables-restore < /opt/iptables.bak 将备份文件中的策略还原到配置文件中
systemctl restart iptables.service 重启服务生效
复制代码
##查看配置文件中的默认策略
[root@localhost opt]#cat /etc/sysconfig/iptables-config
​
##使用iptables -nL查看修改过的策略
[root@localhost opt]#iptables -nL
​
##对自定义的iptables策略做备份(将命令导入一个备份文件iptables.bak)
[root@localhost opt]# iptables-save > /opt/iptables.bak
[root@localhost opt]# cd /opt
[root@localhost opt]# cat iptables.bak
​
##重启服务(用作模拟未保留修改的策略),再查看发现策略又恢复成了配置文件中的默认策略
[root@localhost opt]# systemctl restart iptables.service
​
[root@localhost opt]# iptables -nL
​
##将备份文件中的策略恢复到配置文件中,再重启服务就还原成功了
[root@localhost opt]# iptables-restore < /opt/iptables.bak
​
[root@localhost opt]# systemctl restart iptables.service
​
[root@localhost opt]# iptables -nL
​

实验

实验拓扑
网络规划
  • 内部PC1位于内网区域,地址段为: 192.168.1.0/24,pc1地址为:192.168.1.1/24,网关地址为:192.168.1.254/24

  • 服务器S1位于服务器区域,地址段为: 192.168.2.0/24,pc1地址为:192.168.2.1/24,网关地址为:192.168.2.254/24

  • PC2位于互联网区域,模拟外部互联网,地址段为:10.0.0.0/8,pc2地址为:10.0.0.1/8

  • Linux防火墙的三块网卡为别连接不同的网络区域,地址分别为 :ens33 192.168.1.254/24;ens34 10.0.0.100/8;ens35 192.168.2.254/24

实验要求
  • 内部网络中的pc1采用SNAT访问外部互联网,但是无法ping到内部网关。

  • 内部网络服务器s1通过DNAT发布服务到互联网。

  • 互联网主机pc2能够访问DMZ(s1)区域的服务器,但是不能够进行ping和ssh连接。

8、实验具体步骤:

一、环境准备(虚拟机基础配置)

1. 禁用 firewalld 并安装 iptables
复制代码
# 禁用 firewalld 并安装 iptables-services
systemctl stop firewalld
systemctl disable firewalld
yum install -y iptables-services
systemctl enable --now iptables
2. 配置网卡与 IP 转发(同 firewalld 方案)

确保防火墙 sf1 的三块网卡(ens33/ens34/`ens37)配置正确,并开启 IP 转发:

复制代码
# 开启 IP 转发
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-ipforward.conf
sysctl -p /etc/sysctl.d/99-ipforward.conf

二、实验功能实现(防火墙 sf1 配置)

1. 需求 1:pc1 通过 SNAT 访问外网,但无法 ping 内网网关
复制代码
# 清空现有规则并设置默认策略
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP  # 默认拒绝所有转发流量
​
# SNAT 配置:pc1 访问外网时源 IP 转换为防火墙外网口 IP
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ens34 -j SNAT --to-source 10.0.0.100
​
# 拒绝 pc1 ping 内网网关(192.168.1.254)
iptables -A INPUT -s 192.168.1.0/24 -d 192.168.1.254 -p icmp --icmp-type echo-request -j DROP
2. 需求 2:服务器 s1 通过 DNAT 发布服务到外网
复制代码
# DNAT 配置:外网访问防火墙 80 端口转发到 s1 的 80 端口
iptables -t nat -A PREROUTING -d 10.0.0.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.2.1:80
​
# 允许转发 HTTP 流量(从 ens34 到 ens35)
iptables -A FORWARD -i ens34 -o ens35 -d 192.168.2.1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -i ens35 -o ens34 -s 192.168.2.1 -p tcp --sport 80 -j ACCEPT
3. 需求 3:pc2 可访问 s1 服务,但无法 ping/ssh 连接
复制代码
# 允许 pc2 访问 s1 的 HTTP 服务
iptables -A FORWARD -i ens34 -o ens35 -s 10.0.0.0/8 -d 192.168.2.1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -i ens35 -o ens34 -s 192.168.2.1 -d 10.0.0.0/8 -p tcp --sport 80 -j ACCEPT
​
# 拒绝 pc2 ping s1
iptables -A FORWARD -i ens34 -o ens35 -s 10.0.0.0/8 -d 192.168.2.0/24 -p icmp --icmp-type echo-request -j DROP
​
# 拒绝 pc2 ssh 连接 s1
iptables -A FORWARD -i ens34 -o ens35 -s 10.0.0.0/8 -d 192.168.2.0/24 -p tcp --dport 22 -j DROP

三、验证步骤

  1. 验证 SNAT 与 ping 限制

    复制代码
    # 在 pc1 上测试
    ping 10.0.0.1       # 应能 ping 通 pc2
    ping 192.168.1.254  # 应无法 ping 通网关
    curl 10.0.0.1       # 若 pc2 开启 HTTP 服务,应能访问
    复制代码
    [root@localhost network-scripts]# systemctl stop firewalld.service 
    [root@localhost network-scripts]# ping 10.0.0.1
    PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
    From 192.168.1.254 icmp_seq=1 Destination Host Unreachable
    From 192.168.1.254 icmp_seq=2 Destination Host Unreachable
    From 192.168.1.254 icmp_seq=3 Destination Host Unreachable
    From 192.168.1.254 icmp_seq=4 Destination Host Unreachable
    ^C
    --- 10.0.0.1 ping statistics ---
    5 packets transmitted, 0 received, +4 errors, 100% packet loss, time 4088ms
    pipe 4
    [root@localhost network-scripts]# ping 192.168.1.254
    PING 192.168.1.254 (192.168.1.254) 56(84) bytes of data.
    64 bytes from 192.168.1.254: icmp_seq=1 ttl=64 time=0.417 ms
    64 bytes from 192.168.1.254: icmp_seq=2 ttl=64 time=0.333 ms
    64 bytes from 192.168.1.254: icmp_seq=3 ttl=64 time=0.294 ms
    64 bytes from 192.168.1.254: icmp_seq=4 ttl=64 time=0.276 ms
    ^C
    --- 192.168.1.254 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3101ms
    rtt min/avg/max/mdev = 0.276/0.330/0.417/0.054 ms
    [root@localhost network-scripts]# curl 10.0.0.1
    [root@localhost network-scripts]# curl 10.0.0.1
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    ​
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
      <head>
        <title>Test Page for the Nginx HTTP Server on Roc
    ​
  2. 验证 DNAT 发布

    复制代码
    # 在 pc2 上测试
    curl http://10.0.0.100  # 应返回 s、1 的 HTTP 页面内容
    复制代码
    [root@localhost ~]# curl http://10.0.0.100
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    ​
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
      <head>
        <title>Test Page for the Nginx HTTP Server on Rocky Linux</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <style type="text/css">
          /*<![CDATA[*/
          body {
            background-color: #fff;
    ​
  3. 验证 pc2 访问限制

    复制代码
    # 在 pc2 上测试
    ping 192.168.2.1   # 应无法 ping 通 s1
    ssh 192.168.2.1    # 应无法建立 SSH 连接
    curl http://10.0.0.100  # 应能正常访问 HTTP 服务
复制代码
root@localhost ~]# ping 192.168.2.1
connect: 网络不可达
[root@localhost ~]# ssh 192.168.2.1 
ssh: connect to host 192.168.2.1 port 22: Network is unreachable
root@localhost ~]# curl 10.0.0.100
111
​
​

四、关键配置分析

功能 iptables 核心规则 说明
SNAT 上网 POSTROUTING 链的 SNAT 规则 改写源 IP,使内网主机可访问外网
ping 限制 INPUT 链拒绝特定 ICMP 类型 阻止内网主机 ping 防火墙网关
DNAT 发布服务 PREROUTING 链的 DNAT 规则 将外网请求转发到内网服务器
pc2 访问限制 FORWARD 链的精准过滤 仅放行 HTTP 流量,拒绝 ICMP 和 SSH

五、故障排查命令

复制代码
# 查看当前 iptables 规则
iptables -L -n -v
iptables -t nat -L -n -v
​
# 查看网络连接状态
netstat -tulpn
​
# 检查数据包计数(验证规则是否生效)
iptable-n -v -x
复制代码
防火墙配置:
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:61:3a:30 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 192.168.1.254/24 brd 192.168.1.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe61:3a30/64 scope link 
       valid_lft forever preferred_lft forever
3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:61:3a:3a brd ff:ff:ff:ff:ff:ff
    altname enp2s2
    inet 10.0.0.100/8 brd 10.255.255.255 scope global noprefixroute ens34
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe61:3a3a/64 scope link 
       valid_lft forever preferred_lft forever
4: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:61:3a:44 brd ff:ff:ff:ff:ff:ff
    altname enp2s5
    inet 192.168.2.254/24 brd 192.168.2.255 scope global noprefixroute ens37
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe61:3a44/64 scope link 
       valid_lft forever preferred_lft forever
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:3f:34:5d brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# iptables -F
[root@localhost ~]# iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
​
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
​
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@localhost ~]# iptables -P INPUT ACCEPT
[root@localhost ~]# iptables -P OUTPUT ACCEPT
[root@localhost ~]# iptables -P FORWARD DROP
[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ens34 -j SNAT --to-source 10.0.0.100
[root@localhost ~]# iptables -A INPUT -s 192.168.1.0/24 -d 192.168.1.254 -p icmp --icmp-type echo-request -j DROP
[root@localhost ~]# iptables -t nat -A PREROUTING -d 10.0.0.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.2.1:80
[root@localhost ~]# iptables -A FORWARD -i ens34 -o ens35 -d 192.168.2.1 -p tcp --dport 80 -j ACCEPT
[root@localhost ~]# iptables -A FORWARD -i ens35 -o ens34 -s 192.168.2.1 -p tcp --sport 80 -j ACCEPT
[root@localhost ~]# iptables -A FORWARD -i ens34 -o ens35 -s 10.0.0.0/8 -d 192.168.2.1 -p tcp --dport 80 -j ACCEPT
[root@localhost ~]# iptables -A FORWARD -i ens35 -o ens34 -s 192.168.2.1 -d 10.0.0.0/8 -p tcp --sport 80 -j ACCEPT
[root@localhost ~]# iptables -A FORWARD -i ens34 -o ens35 -s 10.0.0.0/8 -d 192.168.2.0/24 -p icmp --icmp-type echo-request -j DROP
[root@localhost ~]# iptables -A FORWARD -i ens34 -o ens35 -s 10.0.0.0/8 -d 192.168.2.0/24 -p tcp --dport 22 -j DROP
​
[root@localhost ~]# iptables -L -n -v
Chain INPUT (policy ACCEPT 109 packets, 16120 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   76 11521 LIBVIRT_INP  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
​
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 LIBVIRT_FWX  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWI  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 LIBVIRT_FWO  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
​
Chain OUTPUT (policy ACCEPT 90 packets, 8812 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   51  3973 LIBVIRT_OUT  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
​
Chain LIBVIRT_INP (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
    0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67
​
Chain LIBVIRT_OUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:53
    0     0 ACCEPT     tcp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            tcp dpt:53
    0     0 ACCEPT     udp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            udp dpt:68
    0     0 ACCEPT     tcp  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            tcp dpt:68
​
Chain LIBVIRT_FWO (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  virbr0 *       192.168.122.0/24     0.0.0.0/0           
    0     0 REJECT     all  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
​
Chain LIBVIRT_FWI (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
    0     0 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
​
Chain LIBVIRT_FWX (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  virbr0 virbr0  0.0.0.0/0            0.0.0.0/0           
​
相关推荐
小艺E6 分钟前
硬核算力时代:裸金属服务器如何重塑企业级云基建?
运维·服务器
deeper_wind6 分钟前
Rsync+sersync实现数据实时同步(小白的“升级打怪”成长之路)
linux·运维·网络
tHaNkS71327 分钟前
嵌入式秋招面经八股(三)
linux·服务器·网络
天上掉下来个程小白34 分钟前
Apache ECharts-01.介绍
前端·javascript·spring boot·apache·苍穹外卖
帝恩思科技1 小时前
SSL证书怎么配置到服务器上 ?
服务器·网络协议·ssl
时空自由民.1 小时前
linux Unix Socket 介绍
linux·运维·unix
IT小馋猫2 小时前
从源码到生产:Apache 2.4.57 自动化安装实战指南(附脚本)
linux·服务器·网络·网络安全
Rancemy2 小时前
Redis02
运维·服务器·redis·腾讯云
conkl2 小时前
Linux 并发编程:从线程池到单例模式的深度实践
linux·运维·服务器·阿里云·单例模式·云计算
王富贵QAQ2 小时前
SSH带外管理和Rsync+sersync实现数据实时同步
linux·服务器·ssh