Linux防火墙

网络安全技术基础

 

目前主流的网络安全产品(技术)包括以下几类

入侵检测系统 IDS

IDS:Intrusion Detection Systems (入侵检测系统)

其特点是不阻断任何网络访问,而是依照一定的安全策略,通过软,硬件,对网络,系统的运行状况进 行监控,尽可能发现各种攻击企图,攻击行为或攻击结果,以保证网络系统资源的机密性,完整性和可用性。

本质上,IDS 是监听设备(系统),不用直接接入网络链路,网络流量也不用经过IDS。所以IDS一般以 旁路部署的形入接入系统,然后在网络上收集它所关心的报文即可。对于收集到的报文数据,IDS会进行 清洗统计,并与内置的规则进行比对和分析,从而得出哪些网络数据是入侵和攻击。

根据模型和部署方式不同,IDS 可分为基于主机的IDS,基于网络的IDS,以及新一代的分布式IDS。

基于主机的IDS

在每个要保护的主机上运行一个代理程序,一般只能检测该主机上发生的入侵。主要部署在重要的系统服务器,工作站上。IDS代理程序监控操作系统或系统事件级别的可疑活动(如尝试登录等)。在使用时 需要清楚的定义哪些是不合法的活动,然后根据这些定义的规则来做检测。

基于网络的IDS

该类系统一般被动地在网络上监听整个网段上的信息流,通过捕获网络数据包,进行分析,能够检测该 网络段上发生的网络入侵。

分布式IDS

一般由多个部件组成,分布在网络的各个部分,每个部件完成相应功能,分别进行数据采集、数据分析 等。通过中心的控制部件,进行数据汇总、分析、产生入侵警报等。在这种 "分布式IDS(入侵检测系统)” 的结构下,不仅可以检测到针对单独主机的入侵,同时也可以检测到针对该网段上的主机的入侵。

 

入侵防御系统 IPS

IPS: Intrusion Prevention System (入侵防御系统)

IPS 以串行的方式接入系统,IPS系统可以深度感知并检测经流的数据报文,可以根据预先设定的安全策 略,对流经的每个报文进行深度检测(包括协议分析跟踪、特征匹配、流量统计分析、事件关联分析等),如果发现藏匿于其中的网络攻击,可以根据该攻击的威胁级别立即采取措施,这些措施包括中断 连接,丢弃报文,隔离文件,向管理员告警等。

 

IPS可以分为 主机入侵防御系统,网络入侵防御系统,无线入侵防御系统等几类。

主机 IPS

主机IPS部署在终端主机节点上,主要用来保护单台主机,主机IPS与网络IPS结合使用效果更佳,对于能 够规避网络IPS的威胁,主机IPS可以看是防御系统的最后一道防线。

网络 IPS

网络IPS一般部署在系统的战略位置上,所有进出的流量和报文,都要经由网络IPS,其作用在整个网络 上。

无线 IPS

此类的入侵防御系统可以扫描无线网络,进行寻找未经授权的访问,并可以将未授权的设备移出网络。

 

防火墙 FW

FW:Firewal

防火墙系统是在内部网络和外部网络之间,专用网络与公共网络之间,可信网络和不可信网络之间建立 屏障。它是一种隔离技术,是在两个网络通讯时执行的一种访问控制尺度,它能允许经你 “同意”的个人 和数据进入你的网络,同时将你 “不同意” 的个人和数据拒之门外,最大限度的阻止非法的流量和数据进 入系统或网络。同时防火墙也可以根据规则禁止本地网络向外发送数据报文,以及根据规则转发网络流 量等。

防火墙以串行的方式接入系统,所有流入流出的网络报文都要经由防火墙。

根据工作模式不同,防火墙可以分为 网络层防火墙,应用层防火墙等。

 

防水墙 WW

WW:Waterwall

与防火墙相对,防水墙是一种防止内部信息泄漏的安全产品。它利用透明加解密,身份认证,访问控制 和审计跟踪等技术手段,对涉密信息,重要业务数据和技术专利等敏感信息的存储,传播和处理过程, 实施安全保护;最大限度地防止敏感信息泄漏、被破坏和违规外传,并完整记录涉及敏感信息的操作日志,以便日后审计。

 

防火墙的分类

 

按照保护范围来划分

可以分为主机防火墙和网络防火墙。

 

主机防火墙

主机防火墙对单个主机进行防护,运行在终端主机上,主机防火墙可以阻止未授权的程序和数据出入计 算机,Windows和Linux 系统都有自带的主机防火墙。

 

网络防火墙

网络防火墙部署在整个系统的主线网路上,对整个系统的出入数据进行过滤。

 

按实现方式划分

可以分为硬件防火墙和软件防火墙

 

硬件防火墙

硬件防火墙以独立硬件设备的形式提供服务,独立供电,独立部署,其软件是单独运行在硬件里面的, 所有硬件资源都只给防火墙这一个程序使用。

常见的硬件防火墙生产厂商有 华为,天融信,启明星辰,绿盟,深信服等。

 

软件防火墙

没有独立硬件,一般以应用程序的形式提供,运行于通用硬件平台,寄生于操作系统中,是通过纯软件 的方式提供服务

 

按网络协议划分

可以分为网络层防火墙和应用层防火墙

网络层防火墙工作在OSI七层模型中的网络层,又称包过滤防火墙。

应用层防火墙工作在OSI七层模型中的应用层,又称网关防火墙或代理服务器防火墙。

 

网络层防火墙

网络层防火墙对流经的数据包中的源地址,目标地址,端口号及协议等内容做出分析,依据事先设定好 的过滤规则,对数据包作出不同的处理(包括拒绝,丢弃,放行,转发等)。这些过滤规则,被称为访问控制列表(ACL)。

网络层防火墙只能根据数据包头部的协议端口号等进行过滤,无法过滤应用层的具体数据

 

应用层防火墙

应用层网只针对特别的网络应用服务协议来确定数据过滤逻辑。应用层网关防火墙是内部网和外部网的隔离点,它部署在主链路上,将系统分为两部份,起到内外部网络通讯时的中间转接作用

 

Linux 防火墙基础知识

 

netfilter 基础

netfilter/iptables 项目由 Rusty Russe 创建于1998年,并于 1999 年建立了 Netfilter Core team,并在 此后负责维护此项目,同时也于2000年3月合并进了 linux 2.3.x 版本的 linux 内核

从 Linux 2.4.x 版本的内核开始,netfilter 就正式成为了新一代的 Linux 防火墙机制,是Linux内核的一 个子系统。Netfilter采用模块化设计,具有良好的可扩充性,提供扩展网络服务的结构化底层框架。 Netfilter与IP协议栈是无缝契合,并允许对数据包进行过滤、地址转换、处理等操作

netfilter/iptables 有三部分组成,分别是netfilter 框架/iptables(内核空间)/iptables 命令行工具(用户空间)。

 

内核中netfilter相关的模块

[root@ubuntu24 ~]# grep -i netfilter /boot/config-6.8.0-45-generic
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_BRIDGE_NETFILTER=m
# Core Netfilter Configuration
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_EGRESS=y
CONFIG_NETFILTER_SKIP_EGRESS=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_FAMILY_BRIDGE=y
CONFIG_NETFILTER_FAMILY_ARP=y
CONFIG_NETFILTER_BPF_LINK=y
CONFIG_NETFILTER_NETLINK_HOOK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NETFILTER_NETLINK_OSF=m
CONFIG_NETFILTER_CONNCOUNT=m
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
....

防火墙工具

对于防火墙工具,建议只用一个,多个工具共存可能会有冲突

 

iptables

由软件包iptables提供的命令行工具,工作在用户空间,用来编写规则,写好的规则被送往netfilter,告 诉内核如何去处理信息包。

 

firewalld

redhat 系列的发行版中,从CentOS 7 版本开始,引入了新的前端管理工具。

 

nftables

此软件是 CentOS 8的新特性,Nftables 最初在法国巴黎的 Netfilter Workshop 2008 上发表,后由 netfilter核心团队成员和项目负责人Patrick McHardy 于2009年3月发布。并于2013年末合并到Linux内 核中,自2014年开始,己经在 3.13版本以以后的版本的内核中可用。

它重用了 netfilter框架的许多部份,例如连接跟踪和NAT功能。它还保留了命名法和基本iptables设计的 几个部份,例如表,链和规则。就像iptables一样,充当链的容器,并且链包含单独的规则,这些规则 可以执行操作,例如丢弃数据包,移至下一个规则或跳至新链

从用户角度来看,nftables添加了名为 nft 的新工具,该工具是iptables及其衍生指令 (ip6tables, arptables,ebtables)的超集,替代了iptables 及其衍生指令的中的所有工具。从体系结构的角度来看, 它还替换了内核中处理数据包过滤规则集运行时评估的那些部分

 

 

netfilter 工作原理

netfilter 在内核中某些位置放置了五个勾子函数(hook function),分别是 INPUT,OUTPUT, FORWARD,PREROUTING,POSTROUTING,管理员可以通过配置工具配置规则,让这五个函数按照自 定义的规则进行工作,达到防火墙的功能。

305efed7698948c98d105f5f8d3649c6.png

特别说明

从 Linux kernel 4.2 版以后,netfilter 在prerouting 前加了一个 ingress 勾子函数。可以使用这个新的 入口挂钩来过滤来自第2层的流量,这个新挂钩比预路由要早,基本上是 tc 命令(流量控制工具)的替 代品

 

三种报文流向

数据走向具体过程
流入本机PREROUTING --> INPUT --> 用户空间进程
流出本机用户空间进程 --> OUTPUT --> POSTROUTING
从本机转发PREROUTING --> FORWARD --> POSTROUTING

 

iptables 的组成

netfilter 在内核中设置了五个勾子函数,管理员在用户空间,通过程序设置过滤规则,内核中的勾子函数根据预设的规则进行工作,达到对流经的数据包进行过滤,拒绝,转发等功能

iptables中有五个链(chain)对应内核中的五个勾子函数。除此之外,iptables中还有五个表 (table),一起来配合工作

 

iptables 中的链

类型备注
内置链对应内核中的每一个勾子函数 (INPUT,OUTPUT,FORWARD,PREROUTING, POSTROUTING)
自定义链用于对内置链进行扩展或补充,可实现更灵活的规则组织管理机制;只有Hook钩子调用自定义链时,才会生效

 

iptables 中的表

表名备注
filter过滤规则表,根据预定义的规则过滤符合条件的数据包,默认表
natnetwork address translation 地址转换规则表
mangle修改数据标记位规则表
raw关闭启用的连接跟踪机制,加快封包穿越防火墙速度
security用于强制访问控制(MAC)网络规则,由Linux安全模块(如SELinux)实现,很少使用

 

表的优先级(从高到低)

security --> raw --> mangle --> nat --> filter

 

链和表的对应关系(不是每个链都能支持五个表)

可支持的链
rawPREROUTING,OUTPUT
manglePREROUTING,POSTROUTING,INPUT,OUTPUT,FORWARD
natPREROUTING,POSTROUTING,INPUT,OUTPUT
filterINPUT,FORWARD,OUTPUT

 

数据包过滤匹配流程

201397eef36f4f62a18e75ea429d0c91.png

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

  • 如果数据包是进入本机的,则会进入INPUT链,然后交由本机的应用程序处理;

  • 如果数据包是要转发的,且内核允许转发,则数据包在PREROUTING链之后到达FORWARD链,再经由POSTROUTING链输出

  • 本机的应用程序往外发送数据包,会先进入OUTPUT链,然后到达POSTROUTING链输出

 

  • 数据流入:PREROUTING --> INPUT

  • 数据流出:OUTPUT --> POSTROUTING

  • 数据转发:PREROUTING --> FORWARD --> POSTROUTING

 

 

iptables

 

前置工作

在 ubuntu 中,在用iptables命令设置防火墙之前,先关闭自带的 ufw 服务,因为 ufw 服务中也有一套 自定义的规则,如果在开启 ufw 服务的情况下再用 iptables 设置或删除规则,容易发生冲突。

在 redhat 系中要先停用 firewalld 服务

#ubuntu中
[root@ubuntu24 ~]# systemctl disable --now ufw
Synchronizing state of ufw.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install disable ufw
Removed "/etc/systemd/system/multi-user.target.wants/ufw.service".

#Rocky 中
[root@Rocky-9 ~]# systemctl disable --now firewalld.service
Removed "/etc/systemd/system/multi-user.target.wants/firewalld.service".
Removed "/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service".

iptables 命令组成

 

iptables 完整命令由四部份组成

iptables Table Chain Rule

#通过 iptables 命令,在某个表,某个链上设置一个过滤规则

字段说明

字段说明
iptables命令
Table具体要操作的表,用 -t 指定,raw|mangle|nat|filter,默认filter
Chain具体要操作的链,PREROUTING|INPUT|FORWARD|OUTPUT|POSTROUTING
Rule具体规则,由匹配条件和目标组成,如果满足条件,就执行目标中的规则,目标用 -j 指定

 

完整格式示例

iptables -t filter -A INPUT -s 192.168.0.1 -j DROP

iptables 命令格式

iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X [chain]
iptables [-t table] -P chain target
iptables [-t table] -E old-chain-name new-chain-name

rule-specification = [matches...] [target]
match = -m matchname [per-match-options]
target = -j targetname [per-target-options]

#指定表
-t|--table table #指定表raw|mangle|nat|filter,如果不显式指定,默认是filter


#操作链
-N|--new-chain chain 			#添加自定义新链
-X|--delete-chain [chain] 		#删除自定义链(要求链中没有规则)
-P|--policy chain target 		#设置默认策略,对filter表中的链而言,其默认策略有ACCEPT|DROP
-E|--rename-chain old-chain new-chain #重命名自定义链,引用计数不为0的自定义链不能被重命名
-L|--list [chain] 				#列出链上的所有规则
-S|--list-rules [chain] 		#列出链上的的有规则
-F|--flush [chain] 				#清空链上的所有规则,默认是所有链
-Z|--zero [chain [rulenum]] 	#置0,清空计数器,默认操作所有链上的所有规则


#操作具体规则
-A|--append chain rule-specification 			#往链上追加规则
-I|--insert chain [rulenum] rule-specification 	#往链上插入规则,可以指定编号,默认插入到最前面(第一条)
-C|--check chain rule-specification 			#检查链上的规则是否正确
-D|--delete chain rule-specification 			#删除链上的规则 
-D|--delete chain rulenum 						#根据编号删除链上的规则
-R|--replace chain rulenum rule-specification 	#根据链上的规则编号,使用新的规则替换原有规则


#其它选项
-h|--help 		#显示帮助
-V|--version 	#显示版本
-v|--verbose 	#显示详细信息
-n|--numeric 	#以数字形式显示IP和端口,默认显示主机名和协议名
--line-numbers 	#显示每条规则编号

示例

#查看规则
#默认filter表
[root@ubuntu24 ~]# iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

#指定filter表
[root@ubuntu24 ~]# iptables -t filter -vS
-P INPUT ACCEPT -c 0 0
-P FORWARD ACCEPT -c 0 0
-P OUTPUT ACCEPT -c 0 0

#指定filter表,INPUT链
[root@ubuntu24 ~]# iptables -t filter -vS INPUT
-P INPUT ACCEPT -c 0 0

#新增规则
#在INPUT 链的 filter 表上设置过滤规则,将来自 10.0.0.152 的数据包丢弃掉
[root@ubuntu24 ~]# iptables -t filter -A INPUT -s 10.0.0.152 -j DROP
[root@ubuntu24 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       all  --  10.0.0.152           anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

#查看详细信息
[root@ubuntu24 ~]# iptables -vL
Chain INPUT (policy ACCEPT 28 packets, 1668 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       all  --  any    any     10.0.0.152           anywhere

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@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 41 packets, 5870 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       0    --  *      *       10.0.0.152           0.0.0.0/0

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
 
#在最前面插入一条放行物理机IP的规则
[root@ubuntu24 ~]# iptables -t filter -I INPUT -s 10.0.0.1 -j ACCEPT


#删除 iptables 规则
#查看规则编号
[root@ubuntu24 ~]# iptables -t filter -vnL INPUT --line-numbers
Chain INPUT (policy ACCEPT 191 packets, 28455 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1      114  9992 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
2        0     0 DROP       0    --  *      *       10.0.0.152           0.0.0.0/0

#删除第2条规则,根据规则编号删除
[root@ubuntu24 ~]# iptables -t filter -D INPUT 2
#删除第一条,根据命令来删除
[root@ubuntu24 ~]# iptables -t filter -D INPUT -s 10.0.0.1 -j ACCEPT

#规则替换
[root@ubuntu24 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  10.0.0.151           anywhere             reject-with icmp-port-unreachable
#将10.0.0.151 更改为 10.0.0.0/24 整个网段
[root@ubuntu24 ~]# iptables -t filter -R INPUT 1 -s 10.0.0.0/24 -j REJECT

#由于物理机IP也被拒绝自己也会掉线
#需要插入一条规则去放行物理机IP,要用-I 
#这种情况下,ACCEPT规则一定要写在前面,如果放在REJECT 就不会匹配到ACCEPT

#清空统计数据
# 查看
[root@ubuntu24 ~]# iptables -vnL INPUT
Chain INPUT (policy ACCEPT 575 packets, 80374 bytes)
 pkts bytes target     prot opt in     out     source               destination
  134 27116 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
   69  4065 REJECT     0    --  *      *       10.0.0.0/24          0.0.0.0/0            reject-with icmp-port-unreachable
   
#清空INPUT链上的第一条规则统计数据 
[root@ubuntu24 ~]# iptables -t filter -Z INPUT 1

[root@ubuntu24 ~]# iptables -vnL INPUT
Chain INPUT (policy ACCEPT 575 packets, 80374 bytes)
 pkts bytes target     prot opt in     out     source               destination
    7   405 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
   69  4065 REJECT     0    --  *      *       10.0.0.0/24          0.0.0.0/0            reject-with icmp-port-unreachable
   
   
#每个表中都有默认规则
#修改默认规则
[root@ubuntu24 ~]# iptables -P FORWARD DROP

输出内容说明

字段说明
pkts在当前规则中,被命中的数据包数量
bytes在当前规则中,被命中的总流量大小
target动作,目标,DROP 表示丢弃
prot具体协议
opt选项
in数据从哪个网络设备进来
out数据从哪个网络设备上出去
source源,可以是主机IP,网段,anywhere 表示不受限
destination目标,可以是主机IP,网段,anywherer 表示不受限

 

iptables 防火墙中的规则,在生效时会按照顺序,从上往下生效,当前一条规则命中后,不再继续往下 匹配

如果多条规则里面,匹配条件中有交集,或者有包含关系,则这些规则,要注意前后顺序,范围小的, 需要精确匹配的,要往前放范围大的,往后放,负责兜底的,放在最后

如果多条规则里面,匹配条件没有交集,彼此不会互相影响,则无所谓前后顺序,但是从效率上来讲, 更容易命中的要放在前面

 

 

iptables 匹配条件

iptables 中的匹配条件分为基本匹配和扩展匹配两种,当一条 iptables 规则中有多个匹配条件时,默认 是 “与” ,即要同时满足

匹配条件-基本匹配

[!] -s|--source address[/mask][,...] 		#匹配源IP地址或网段
[!] -d|--destination address[/mask][,...] 	#匹配目标IP地址或网段
[!] -p|--protocol protocol 					#匹配具体协议,可以使用协议号或协议名,具体见 /etc/protocols
[!] -i|--in-interface name 					#匹配报文流入接口,只用于数据流入 
[!] -o|--out-interface name 				#匹配报文流出接口,只用于数据流出
#示例
#规则取反
[root@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 17 packets, 1484 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1315 81273 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    3   252 REJECT     0    --  *      *       10.0.0.157           0.0.0.0/0            reject-with icmp-port-unreachable

#从 10.0.0.157 来的数据包被拒绝
[root@ubuntu24 ~]# ping 10.0.0.161
PING 10.0.0.161 (10.0.0.161) 56(84) bytes of data.
From 10.0.0.161 icmp_seq=1 Destination Port Unreachable
From 10.0.0.161 icmp_seq=2 Destination Port Unreachable
From 10.0.0.161 icmp_seq=3 Destination Port Unreachable

#设置取反规则,除了 10.0.0.150 来的数据,其它都拒绝
[root@ubuntu24 ~]# iptables -t filter -R INPUT 2 ! -s 10.0.0.157 -j REJECT

[root@ubuntu24 ~]# ping 10.0.0.161
PING 10.0.0.161 (10.0.0.161) 56(84) bytes of data.
64 bytes from 10.0.0.161: icmp_seq=1 ttl=64 time=0.610 ms
64 bytes from 10.0.0.161: icmp_seq=2 ttl=64 time=0.434 ms
64 bytes from 10.0.0.161: icmp_seq=3 ttl=64 time=0.811 ms


#根据协议过滤
#拒绝来自157IP上的ICMP协议
[root@ubuntu24 ~]# iptables -t filter -A INPUT -s 10.0.0.157 -p icmp -j REJECT
[root@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 558 packets, 49035 bytes)
 pkts bytes target     prot opt in     out     source               destination
   25  1468 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    2   168 REJECT     1    --  *      *       10.0.0.157           0.0.0.0/0            reject-with icmp-port-unreachable
[root@ubuntu24 ~]# ping 10.0.0.161
PING 10.0.0.161 (10.0.0.161) 56(84) bytes of data.
From 10.0.0.161 icmp_seq=1 Destination Port Unreachable

#扔掉目标为161的IP上的ICMP协议
[root@ubuntu24 ~]# iptables -t filter -A INPUT -d 10.0.0.161 -p icmp -j DROP
[root@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 558 packets, 49035 bytes)
 pkts bytes target     prot opt in     out     source               destination
  500 29893 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    3   252 DROP       1    --  *      *       0.0.0.0/0            10.0.0.161
        
[root@ubuntu24 ~]# ping 10.0.0.161
PING 10.0.0.161 (10.0.0.161) 56(84) bytes of data.

#没有任何回应

匹配条件-扩展匹配

扩展匹配条件需要加载扩展模块才能使用

 

查看扩展模块

[root@ubuntu24 ~]# dpkg -L iptables | grep libxt_.*.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_AUDIT.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CHECKSUM.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CLASSIFY.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CONNMARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CONNSECMARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_CT.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_DSCP.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_HMARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_IDLETIMER.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_LED.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_LOG.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_MARK.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_NAT.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_NFLOG.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_NFQUEUE.so
....

扩展匹配条件分为隐式扩展和显示扩展两种

 

隐式扩展

iptables 在使用 -p 选项指明了特定的协议时,无需再用 -m 选项指明扩展模块的扩展机制,不需要手动 加载扩展模块,不需要用 -m 显式指定的扩展,即隐式扩展。

tcp,upd,icmp 这三个协议是可以用 -m 指定的模块,但同时,也可以在基本匹配里面用 -p 来指定这 几个协议

[root@ubuntu24 ~]# dpkg -L iptables | grep tcp.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so

[root@ubuntu24 ~]# dpkg -L iptables | grep udp.so
/usr/lib/x86_64-linux-gnu/xtables/libxt_udp.so

[root@ubuntu24 ~]# dpkg -L iptables | grep icmp.so
/usr/lib/x86_64-linux-gnu/xtables/libipt_icmp.so

tcp 协议的扩展选项

[!] --source-port|--sport port[:port] 			#匹配报文源端口,可为端口连续范围
[!] --destination-port|--dport port[:port] 		#匹配报文目标端口,可为连续范围
[!] --tcp-flags mask comp 						#mask 需检查的标志位列表,用逗号分隔,例如 SYN,ACK,FIN,RST
												#comp 在mask列表中必须为1的标志位列表,无指定则必须为0,用逗号分隔tcp协议的扩展选项
--tcp-flags SYN,ACK,FIN,RST SYN 				#检查SYN,ACK,FIN,RST四个标志位,其中SYN值为1,其它值为0,表示第一次握手
--tcp-flags SYN,ACK,FIN,RST SYN,ACK 			#第二次握手

[!] --syn 										#第一次握手的简单写法

#用tcp 协议和目标端口拒绝ssh服务
#拒绝来自于157的,其目标IP是161,目标端口是 21 到 23 的数据
[root@ubuntu24 ~]# iptables -t filter -A INPUT -s 10.0.0.157 -d 10.0.0.161 -p tcp --dport 21:23 -j REJECT
[root@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 559 packets, 49111 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1512 91031 ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    0     0 REJECT     6    --  *      *       10.0.0.157           10.0.0.161           tcp dpts:21:23 reject-with icmp-port-unreachable

upd 协议的扩展选项

[!] --source-port|--sport port[:port] #匹配报文的源端口或端口范围
[!] --destination-port|--dport port[:port] #匹配报文的目标端口或端口范围

icmp 协议的扩展选项

[!] --icmp-type {type[/code]|typename}
0/0|echo-reply 		#icmp应答
8/0|echo-request 	#icmp请求

显式扩展及相关模块

显示扩展即必须使用 -m 选项指明要调用的扩展模块名称,需要手动加载扩展模块

-m matchname [per-match-options]

multiport 扩展

以离散方式定义多端口匹配,最多指定15个端口

[!] --source-ports|--sports port[,port|,port:port]... 		#指定多个源端口
[!] --destination-ports|--dports port[,port|,port:port]... 	#指定多个目标端口
[!] --ports port[,port|,port:port]... 						#多个源或目标端口	

#在一条规则中指定两个端口
[root@ubuntu24 ~]# iptables -t filter -A INPUT -s 10.0.0.157 -d 10.0.0.161 -p tcp -m multiport --dports 22,80 -j REJECT
[root@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 559 packets, 49111 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1822  109K ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    0     0 REJECT     6    --  *      *       10.0.0.157           10.0.0.161           multiport dports 22,80 reject-with icmp-port-unreachable

iprange 扩展

指明连续的(但一般不是整个网络)ip地址范围

[!] --src-range from[-to] #源IP地址范围
[!] --dst-range from[-to] #目标IP地址范围

#拒绝 10.0.0.9-10.0.0.99 这91个IP		#libxt_iprange.so用于实现IP地址范围的匹配功能
[root@ubuntu24 ~]# iptables -t filter -A INPUT -m iprange --src-range 10.0.0.9-10.0.0.99 -j DROP
[root@ubuntu24 ~]# iptables -nvL
Chain INPUT (policy ACCEPT 561 packets, 49289 bytes)
 pkts bytes target     prot opt in     out     source               destination
 2082  124K ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    0     0 DROP       0    --  *      *       0.0.0.0/0            0.0.0.0/0            source IP range 10.0.0.9-10.0.0.99

mac 扩展

mac 模块可以指明源MAC地址,适用于:PREROUTING, FORWARD,INPUT chains

[!] --mac-source XX:XX:XX:XX:XX:XX

#拒绝 mac 地址为 00:0c:29:f3:44:9a 的主机
[root@ubuntu24 ~]# iptables -t filter -A IvnL
Chain INPUT (policy ACCEPT 561 packets, 49289 bytes)
 pkts bytes target     prot opt in     out     source               destination
 2391  143K ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
    3   252 REJECT     0    --  *      *       0.0.0.0/0            10.0.0.161           MAC 00:0c:29:1e:65:08 reject-with icmp-port-unreachable
    
[root@ubuntu24 ~]# ping 10.0.0.161
PING 10.0.0.161 (10.0.0.161) 56(84) bytes of data.
From 10.0.0.161 icmp_seq=1 Destination Port Unreachable
From 10.0.0.161 icmp_seq=2 Destination Port Unreachable

string 扩展

对报文中的应用层数据做字符串模式匹配检测

--algo {bm|kmp} 	#过滤算法 Boyer-Moore|Knuth-Pratt-Morris,在Rocky8.6中bm算法配合nginx有问题
--from offset 		#开始偏移量,一般用来跳过包头,只检查具体内容,这样能提高效率
--to offset 		#结束偏移量

[!] --string pattern #具体要匹配的字符串
[!] --hex-string pattern #具体要匹配的字符串,16进制格式


#示例
[root@ubuntu24 html]# curl 10.0.0.161/bd.html
baidu
[root@ubuntu24 html]# curl 10.0.0.161/gg.html
google

#设置出口规则,在返回的数据包中,跳过前62字节的报文头,如果内容中出现 google,则拒绝返回
[root@ubuntu ~]# iptables -t filter -A OUTPUT -m string --algo kmp --from 62 --string "google" -j REJECT

[root@ubuntu24 html]# iptables -vnL OUTPUT
Chain OUTPUT (policy ACCEPT 26 packets, 2760 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            STRING match  "google" ALGO name kmp FROM 62 reject-with icmp-port-unreachable

#再次测试
[root@ubuntu24 ~]# curl 10.0.0.161/bd.html
baidu

#google 无法返回
[root@ubuntu24 ~]# curl 10.0.0.161/gg.html
^C

#区分大小写,大写不会被命中
[root@ubuntu24 ~]# curl 10.0.0.161/GG.html
GOOgle

time 扩展

根据将报文到达的时间与指定的时间范围进行匹配,此扩展中默认使用UTC时间,所以使用时,要根据当前时区进行计算。

此扩展在CentOS8中有问题

--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]] #开始生效时间
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] #结束生效时间
--timestart hh:mm[:ss] #开始生效时间
--timestop hh:mm[:ss] #结束生效时间

[!] --monthdays day[,day...] #指定几号,1-31 
[!] --weekdays day[,day...] #指定星期几,可以写Mon|Tue|Wed|Thu|Fri|Sat|Sun,也可以写1|2|3|4|5|6|7
--contiguous
--kerneltz #内核时区,此选项不建议使用,CentOS7版本以上系统默认UTC

#示例
#Rocky8.6配置报错
[root@rocky ~]# iptables -t filter -A INPUT -m time --timestart 01:00 --timestop 
14:00 -s 10.0.0.150 -j REJECT
Warning: Extension time revision 0 not supported, missing kernel module?
iptables v1.8.4 (nf_tables): RULE_APPEND failed (No such file or directory): 
rule in chain INPUT

#在ubuntu中设置
[root@ubuntu24 html]# iptables -t filter -A INPUT -m time --timestart 1:00 --timestop 14:00 -s 10.0.0.157 -j REJECT
[root@ubuntu24 html]# iptables -vnL
Chain INPUT (policy ACCEPT 739 packets, 88669 bytes)
 pkts bytes target     prot opt in     out     source               destination
 4418  263K ACCEPT     0    --  *      *       10.0.0.1             0.0.0.0/0
   31  2604 REJECT     0    --  *      *       10.0.0.157           0.0.0.0/0            TIME from 01:00:00 to 14:00:00 UTC reject-with icmp-port-unreachable

[root@ubuntu24 ~]# ping 10.0.0.161
PING 10.0.0.161 (10.0.0.161) 56(84) bytes of data.
From 10.0.0.161 icmp_seq=1 Destination Port Unreachable
From 10.0.0.161 icmp_seq=2 Destination Port Unreachable
From 10.0.0.161 icmp_seq=3 Destination Port Unreachable
From 10.0.0.161 icmp_seq=4 Destination Port Unreachable
From 10.0.0.161 icmp_seq=5 Destination Port Unreachable

#先暂停掉ntp服务
[root@ubuntu24 html]# timedatectl set-ntp 0
[root@ubuntu24 html]# date -s "+20 hour"

[root@ubuntu24 ~]# ping 10.0.0.161
From 10.0.0.161 icmp_seq=11 Destination Port Unreachable
From 10.0.0.161 icmp_seq=12 Destination Port Unreachable
From 10.0.0.161 icmp_seq=13 Destination Port Unreachable
64 bytes from 10.0.0.161: icmp_seq=14 ttl=64 time=0.399 ms
64 bytes from 10.0.0.161: icmp_seq=15 ttl=64 time=0.389 ms
64 bytes from 10.0.0.161: icmp_seq=16 ttl=64 time=0.363 ms

connlimit 扩展

根据每客户端IP做并发连接数数量匹配,可防止 Dos(Denial of Service,拒绝服务)攻击

--connlimit-upto N #连接的数量小于等于N时匹配
--connlimit-above N #连接的数量大于N时匹配


#示例
#在另一台机上安装压测工具
[root@ubuntu24 ~]# apt install apache2-utils

[root@ubuntu24 ~]# ab -n 100000 -c 1000 http://10.0.0.161/
-n N #总共发起多少个请求,默认一个
-c N #每次请求并发数,默认一个

#在161主机上查看连接
[root@ubuntu24 ~]# ss -nt

#如果并发连接数超过10个,则拒绝连接
[root@ubuntu24 ~]# iptables -t filter -A INPUT -m connlimit --connlimit-above 10 -j REJECT

#已经没有办法发起连接
[root@ubuntu24 ~]# ab -n 100000 -c 1000 http://10.0.0.161/
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 10.0.0.161 (be patient)
apr_socket_recv: Connection refused (111)
Total of 1 requests completed

limit 扩展

基于收发报文的速率做匹配 , 令牌桶过滤器。

connlimit 扩展是限制单个客户端对服务器的并发连接数,limit 扩展是限制服务器上所有的连接数。

--limit-burst number #前多少个包不限制
--limit [/second|/minute|/hour|/day] #在一个时间区间内能接收的连接数

#示例
#添加 icmp 放行规则,前10个不处理,后面每分钟放行20个
[root@ubuntu24 ~]# iptables -t filter -A INPUT -p icmp --icmp-type 8 -m limit --limit 20/minute --limit-burst 10 -j ACCEPT
#兜底的拒绝规则
[root@ubuntu24 ~]# iptables -t filter -A INPUT -p icmp -j REJECT

[root@ubuntu24 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 652 packets, 39685 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     1    --  *      *       0.0.0.0/0            0.0.0.0/0            icmptype 8 limit: avg 20/min burst 10
    0     0 REJECT     1    --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

state 扩展

state 扩展,可以根据 "连接追踪机制" 去检查连接的状态,比较耗费资源

[!] --state state

state 扩展的状态

状态类型说明
NEW新发出请求;连接追踪信息库中不存在此连接的相关信息条目,因此,将其识别 为第一次发出的请求
ESTABLISHEDNEW状态之后,连接追踪信息库中为其建立的条目失效之前期间内所进行的通 信状态
RELATED新发起的但与已有连接相关联的连接,如:ftp协议中的数据连接与命令连接之 间的关系
INVALID无效的连接,如flag标记不正确
UNTRACKED未进行追踪的连接,如:raw表中关闭追踪

连接追踪机制需要内核选项支持,rocky中开启了此功能,所以此处我们在 rocky 中进行测试

[root@Rocky-9 ~]# cat /usr/lib/modules/5.14.0-427.28.1.el9_4.x86_64/config | grep CONFIG_NF_CONNTRACK_PROCFS
CONFIG_NF_CONNTRACK_PROCFS=y

#当前还没有启用
[root@Rocky-9 ~]# lsmod | grep nf_conntrack

#启用连接跟踪机制后,会自动生成此文件
[root@Rocky-9 ~]# cat /proc/net/nf_conntrack
cat: /proc/net/nf_conntrack: No such file or directory

#只要系统中某处要使用到连接追踪机制,连接追踪机制相关模块会自动加载

#示例
#拒绝新连接
#先建立连接,再设置防火墙规则
64 bytes from 10.0.0.153: icmp_seq=4 ttl=64 time=0.405 ms
64 bytes from 10.0.0.153: icmp_seq=5 ttl=64 time=0.296 ms
64 bytes from 10.0.0.153: icmp_seq=6 ttl=64 time=0.671 ms
64 bytes from 10.0.0.153: icmp_seq=7 ttl=64 time=0.911 ms
64 bytes from 10.0.0.153: icmp_seq=8 ttl=64 time=1.16 ms
64 bytes from 10.0.0.153: icmp_seq=9 ttl=64 time=0.822 ms

[root@Rocky-9 ~]# iptables -t filter -A INPUT -m state --state ESTABLISHED -j ACCEPT
[root@Rocky-9 ~]# iptables -t filter -A INPUT -m state --state NEW -j REJECT

#己连接的客户端可以继续通信

#新的客户端拒绝连接
[root@ubuntu24 ~]# ping 10.0.0.153
PING 10.0.0.153 (10.0.0.153) 56(84) bytes of data.
From 10.0.0.153 icmp_seq=1 Destination Port Unreachable
From 10.0.0.153 icmp_seq=2 Destination Port Unreachable

#启用连接跟踪机制之后,连接状态是记录在文件中的
[root@Rocky-9 ~]# cat /proc/net/nf_conntrack
ipv4     2 tcp      6 299 ESTABLISHED src=10.0.0.153 dst=10.0.0.1 sport=22 dport=2587 src=10.0.0.1 dst=10.0.0.153 sport=2587 dport=22 [ASSURED] mark=0 zone=0 use=2
ipv4     2 icmp     1 29 src=10.0.0.157 dst=10.0.0.153 type=8 code=0 id=14954 src=10.0.0.153 dst=10.0.0.157 type=0 code=0 id=14954 mark=0 zone=0 use=2

#nf_conntrack 文件内容说明
ipv4 	#第一列 网络层协议名称
2 		#第二列 网络层协议号
icmp 	#第三列 传输层协议名称
1 		#第四列 传输层协议号
29 		#第五列 无后续包进入时无效的秒数,即老化时间
ESTABLISHED #第六列 该连接的连接状态,不是所有协议都有此列值
 		#后续都是k=v 格式的连接参数和选项
 		
 		
#nf_conntrack文件中能记录多少内容,取决于配置
[root@Rocky-9 ~]# cat /proc/sys/net/netfilter/nf_conntrack_max
65536

相关内核参数

参数说明
/proc/sys/net/netfilter/nf_conntrack_max连接追踪功能所能够容纳的最大连接数量,修改 此处,下一项也会改变
/proc/sys/net/nf_conntrack_max连接追踪功能所能够容纳的最大连接数量,修改 此处,上一项也会改变
/proc/sys/net/netfilter/nf_conntrack_count己追踪的连接数量
/proc/sys/net/netfilter/time不同协议超时时长,单位为秒,超时后会踢出己 监控的队列

 

target

-j targetname [per-target-options]
target说明
ACCEPT允许通过,命中此规则后,不再对比当前链的其它规则,进入下一个链
DROP丢弃,命中此规则后,该连接直接中断,发送方收不到任何回应
REJECT拒绝,命中此规则后,该连接直接中断,发送方能收到拒绝回应
RETURN返回,在当前链中不再继续匹配,返回到主链,一般用于自定义规则链中
LOG记录日志,将被命中的数据记录在日志中
SNAT源IP地址转换
DNAT目标IP地址转换
REDIRECT本机端口转换
MASQUERADE源IP地址动态转换
自定义
--log-level level #日志级别
debug|info|notice|warning|error|crit|alert|emerg
--log-prefix prefix #日志前缀,用于区别不同的日志,最多29个字符

规则优化最佳实践

  • 安全放行所有入站和出站的状态为ESTABLISHED状态连接,建议放在第一条,效率更高

  • 谨慎放行入站的新请求

  • 有特殊目的限制访问功能,要在放行规则之前加以拒绝

  • 同类规则(访问同一应用,比如:http ),匹配范围小的放在前面,用于特殊处理

  • 不同类的规则(访问不同应用,一个是http,另一个是mysql ),匹配范围大的放在前面,效率更高

  • 应该将那些可由一条规则能够描述的多个规则合并为一条,减少规则数量,提高检查效率

  • 设置默认策略,建议白名单(只放行特定连接)

  • 默认规则(iptables -P)是 ACCEPT,不建议修改,容易出现 “自杀” 现象

  • 规则的最后定义规则做为默认策略,推荐使用,放在最后一条

 

iptables 规则保存

使用iptables 命令定义的规则,手动删除之前,其生效期限为 kernel 存活期限,当系统重启之后,定义的规则会消失。

 

持久化保存规则

[root@Rocky-9 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   28  1684 ACCEPT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            state ESTABLISHED
    0     0 REJECT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW reject-with icmp-port-unreachable
#在标准输出中显示
[root@Rocky-9 ~]# iptables-save
# Generated by iptables-save v1.8.10 (nf_tables) on Thu Sep 26 10:46:33 2024
*filter
:INPUT ACCEPT [4:336]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED -j ACCEPT
-A INPUT -m state --state NEW -j REJECT --reject-with icmp-port-unreachable
COMMIT
# Completed on Thu Sep 26 10:46:33 2024

#导出到文件
[root@Rocky-9 ~]# iptables-save > iptables.rule

#清空规则
[root@Rocky-9 ~]# iptables -F
#导入
#加载保存的规则
[root@Rocky-9 ~]# iptables-restore  < ./iptables.rule

[root@Rocky-9 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   28  1684 ACCEPT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            state ESTABLISHED
    0     0 REJECT     0    --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW reject-with icmp-port-unreachable

iptables-restore 命令

iptables-restore命令是将保存在文件中的防火墙规则导入到系统中

iptables-restore [option] [file]

#常用选项
-h #显示帮助
-t #测试
-n #保留原有规则

开机自动加载规则

[root@rocky ~]# vim /etc/rc.d/rc.local

#增加如下行
iptables-restore < /root/iptables.rule
#保存后给文件增加执行权限
[root@rocky ~]# chmod a+x /etc/rc.d/rc.local

网络防火墙

 

NAT 网络转换原理

NAT

NAT:(Network Address Translation) 网络地址转换

局域网中的主机都是分配的私有IP地址,这些IP地址在互联网上是不可达的,局域网中的主机,在与互 联网通讯时,要经过网络地址转换,去到互联网时,变成公网IP地址对外发送数据。服务器返回数据 时,也是返回到这个公网地址,再经由网络地址转换返回给局域网中的主机。

一个局域网中的主机,想要访问互联网,在出口处,应该有一个公网可达的IP地址,应该能将局域网中 的IP地址通过NAT转换成公网IP。

NAT的分类

NAT说明备注
SNATSource NAT源地址转换,修改请求报文中的源IP地址
DNATDestination NAT目标地址转换,修改响应报文中的目标IP地址
PNATPort NAT端口转换,IP地址和端口都进行转换

 

iptables 中的 NAT

在 iptables 中的基于 nat 表来实现 SNAT 和 DNAT

左边 10.0.0.0/24 网段的主机用来模拟内网环境,需要配置路由指向

192.168.10.0/24 网段不需要配置路由,右边用来模拟互联网环境,让其与防火墙主机之间没有路由表

640736420fd543e5a5e328c7e5690be2.png

#修改10.0.0.150 主机的网关,指向 10.0.0.123
[root@ubuntu24 ~]# route add default gw 10.0.0.123 dev eth0
[root@ubuntu24 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.123      0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
#防火墙主机只保留同网段的网关
[root@ubuntu24 sites-enabled]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1

#确认开启 ip_forward功能
[root@ubuntu24 sites-enabled]# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 1
...

#如果没有开启的话
[root@ubuntu24 sites-enabled]# echo 1 > /proc/sys/net/ipv4/ip_forward
#192.168.10.150主机
#关闭防火墙
[root@ubuntu ~]# systemctl disable --now ufw.service 
Synchronizing state of ufw.service with SysV service script with 
/lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable ufw
Removed /etc/systemd/system/multi-user.target.wants/ufw.service.

#开启nginx 服务
[root@ubuntu22:~]# systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2024-09-26 05:35:03 UTC; 1h 15min ago
       Docs: man:nginx(8)
   Main PID: 1012 (nginx)
      Tasks: 3 (limit: 2176)
     Memory: 9.1M
        CPU: 71ms
     CGroup: /system.slice/nginx.service
             ├─1012 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─1014 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
             └─1015 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
             
             
#在本机测试web服务
[root@ubuntu22:~]# curl 192.168.10.150
<h2>this page from 192.168.10.150<h2>


#在防火墙主机测试web服务
[root@ubuntu24 sites-enabled]# curl 192.168.10.150
<h2>this page from 192.168.10.150<h2>

#查看日志信息
[root@ubuntu22:~]# tail /var/log/nginx/access.log
192.168.10.150 - - [26/Sep/2024:06:51:34 +0000] "GET / HTTP/1.1" 200 38 "-" "curl/7.81.0"
192.168.10.123 - - [26/Sep/2024:06:52:10 +0000] "GET / HTTP/1.1" 200 38 "-" "curl/8.5.0"
#在10.0.0.150主机上测试
#可以ping通防火墙
[root@ubuntu24 ~]# ping 10.0.0.123
PING 10.0.0.123 (10.0.0.123) 56(84) bytes of data.
64 bytes from 10.0.0.123: icmp_seq=1 ttl=64 time=0.746 ms

[root@ubuntu24 ~]# ping  192.168.10.123
PING 192.168.10.123 (192.168.10.123) 56(84) bytes of data.
64 bytes from 192.168.10.123: icmp_seq=1 ttl=64 time=0.962 ms

#但ping 不同目标机器
[root@ubuntu24 ~]# ping 192.168.10.150
PING 192.168.10.150 (192.168.10.150) 56(84) bytes of data.
^C
--- 192.168.10.150 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1023ms

SNAT 实现源IP地址转换

SNAT:Source NAT,源地址转换,基于nat表,工作在 POSTROUTING 链上。

具体是指将经过当前主机转发的请求报文的源IP地址转换成根据防火墙规则指定的IP地址。

iptables -t nat -A POSTROUTING -s LocalNet ! -d LocalNet -j SNAT --to-source
ExtIP [--random]

--to-source [ipaddr[-ipaddr]][:port[-port]] #转换成指定IP,或指定范围内的IP,端口可选
--random #端口映射基于hash算法随机化
#在防火墙主机上添加规则,如果源IP是 10.0.0.0/24网段的IP,则出去的时候,替换成192.168.10.123
[root@ubuntu24 sites-enabled]# iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j SNAT --to-source 192.168.10.123
[root@ubuntu24 sites-enabled]# iptables -t nat -L POSTROUTING
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       all  --  10.0.0.0/24         !10.0.0.0/24          to:192.168.10.123

#测试,10.0.0.150 主机可以到达 192.168.10.150
[root@ubuntu24 ~]# ping 192.168.10.150
PING 192.168.10.150 (192.168.10.150) 56(84) bytes of data.
64 bytes from 192.168.10.150: icmp_seq=1 ttl=63 time=2.08 ms
64 bytes from 192.168.10.150: icmp_seq=2 ttl=63 time=1.22 ms
64 bytes from 192.168.10.150: icmp_seq=3 ttl=63 time=0.590 ms

#在 192.168.10.150主机上抓PING包
#所有的PING包都来自于 192.168.10.123,而并非是 10.0.0.150
[root@ubuntu22:~]# tcpdump icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), snapshot length 262144 bytes
07:05:40.371030 IP 192.168.10.123 > 192.168.10.150: ICMP echo request, id 15740, seq 1, length 64
07:05:40.371055 IP 192.168.10.150 > 192.168.10.123: ICMP echo reply, id 15740, seq 1, length 64
07:05:41.372536 IP 192.168.10.123 > 192.168.10.150: ICMP echo request, id 15740, seq 2, length 64
07:05:41.372574 IP 192.168.10.150 > 192.168.10.123: ICMP echo reply, id 15740, seq 2, length 64

#web服务测试
[root@ubuntu24 ~]# curl 192.168.10.150
<h2>this page from 192.168.10.150<h2>

#查看192.168.10.150的日志
[root@ubuntu22:~]# tail -f /var/log/nginx/access.log
192.168.10.150 - - [26/Sep/2024:06:51:34 +0000] "GET / HTTP/1.1" 200 38 "-" "curl/7.81.0"
192.168.10.123 - - [26/Sep/2024:06:52:55 +0000] "GET / HTTP/1.1" 200 38 "-" "curl/8.5.0"
192.168.10.123 - - [26/Sep/2024:07:07:24 +0000] "GET / HTTP/1.1" 200 38 "-" "curl/8.5.0"

MASQUERADE 实现源IP地址转换

如果我们内网的出口设备上有固定IP,则直接指定 --to-source IP 没有任何问题,但是如果是使用拨号上 网,出口网络设备上的IP地址会发生变化,这种情况下,我们的出口IP不能写成固定的

这种场景下,我们需要使用 MASQUERADE 进行地址转换,MASOUERADE 可以从主机网卡上自动获取 IP地址当作出口IP地址

iptables -t nat -A POSTROUTING -s LocalNET ! -d LocalNet -j MASQUERADE [--toports port[-port]] [--random]

--to-ports port[-port] #指定端口
--random #端口映射基于hash算法随机化
#清空防火墙主机规则
#用 MASQUERADE 设置SNAT转发
[root@ubuntu24 sites-enabled]# iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
[root@ubuntu24 sites-enabled]# iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 1 packets, 132 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  0    --  *      *       10.0.0.0/24         !10.0.0.0/24
      
#测试,10.0.0.150 主机可以到达 192.168.10.150
[root@ubuntu24 ~]# ping 192.168.10.150
PING 192.168.10.150 (192.168.10.150) 56(84) bytes of data.
64 bytes from 192.168.10.150: icmp_seq=1 ttl=63 time=2.78 ms
64 bytes from 192.168.10.150: icmp_seq=2 ttl=63 time=0.902 ms

#在 192.168.10.150主机上抓PING包
#所有的PING包都来自于 192.168.10.123
[root@ubuntu22:~]# tcpdump icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), snapshot length 262144 bytes
07:13:36.690200 IP 192.168.10.123 > 192.168.10.150: ICMP echo request, id 15745, seq 5, length 64
07:13:36.690225 IP 192.168.10.150 > 192.168.10.123: ICMP echo reply, id 15745, seq 5, length 64

#防火墙主机IP发生变化,192.168.10.123 > 192.168.10.150,192.168.10.123也会发生变化

DNAT 实现目标IP地址转换

在内网环境中,使用私有IP地址的设备要与互联网进行通讯时,需要借助出口设备将原内网IP地址转换 成公网可达的IP地址再进行通讯。

在内网环境中,只有在出口设备上才有一个(或数个)公网可达的IP,所以在互联网上,是不能路由至内网 主机的。如果要让内网主机上的服务在公网上可见,我们需要使用 DNT 实现目标IP地址转换。

DNAT:Destination NAT,目标地址转换,基于nat表,工作在 PREROUTING 链上

iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp|icmp --dport PORT -j DNAT --todestination InterSeverIP[:PORT]

-d ExtIP #指公网可达的IP地址,必须是固定IP
--to-destination [ipaddr[-ipaddr]][:port[-port]] #转换成指定IP,或指定范围内的IP,端口可选
#在 192.168.10.150上查看
[root@ubuntu22:~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 ens33
#清空防火墙主机规则
#在防火墙主机上设置DNAT转发规则,在使 192.168.10.150 访问 192.168.10.123 的 web 服务时,服务时将请求转发到 10.0.0.150上
[root@ubuntu24 sites-enabled]# iptables -t nat -A PREROUTING -d 192.168.10.123 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.150:80

[root@ubuntu24 sites-enabled]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 14 packets, 1632 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DNAT       6    --  *      *       0.0.0.0/0            192.168.10.123       tcp dpt:80 to:10.0.0.150:80
    
#测试
[root@ubuntu22:html]# curl 192.168.10.123
<h2>this page from 10.0.0.150<h2>

DNAT 只能将一条请求规则重定向到一台后端主机,无法实现负载均衡功能

早期 iptables 中有一条规则重定向到多台后端主机的功能,后来被 lvs 取代

防火墙主机上看不到80和8080的端口监听,因为这里看到的是应用程序在监听的端口,而防火墙是在内核中实现的

 

REDIRECT 实现本机端口转换

REDIRECT:重定向,通过定义规则,将收到的数据包转发至同一主机的不同端口

REDIRECT 功能无需开启内核 ip_forward 转发

iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport PORT -j REDIRECT --to-ports PORT

--to-ports #新的端口
#修改nginx配置,监听81端口
[root@ubuntu24 ~]# vim /etc/nginx/sites-enabled/default
include /etc/nginx/conf.d/*.conf;
server {
 listen       81 default_server;
 listen       [::]:81 default_server;

#重启服务
[root@ubuntu24 ~]# systemctl restart nginx

#测试, 在10.0.0.123 上访问 10.0.0.150 的 web服务

[root@ubuntu24 ~]# curl 10.0.0.150
curl: (7) Failed to connect to 10.0.0.150 port 80 after 1 ms: Connection refused

#在10.0.0.150上添加REDIRECT规则,将80端口的请求转发到81端口
[root@ubuntu24 html]# iptables -t nat -A PREROUTING -d 10.0.0.150 -p tcp --dport 80 -j REDIRECT --to-ports 81
[root@ubuntu24 html]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   6    --  *      *       0.0.0.0/0            10.0.0.150           tcp dpt:80 redir ports 81
    
[root@ubuntu24 sites-enabled]# curl 10.0.0.150
<h2>this page from 10.0.0.150<h2>

iptables 中的自定义链

iptables 中除了系统自带的五个链之外,还可以自定义链,来实现将规则进行分组,重复调用的目的。

自定义链添加规则之后,要作为系统链的 target 与之关联,才能起到作用

#添加自定义链
[root@ubuntu ~]# iptables -t filter -N web_chain

#查看
[root@ubuntu ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
Chain FORWARD (policy DROP)
target     prot opt source               destination         
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
Chain web_chain (0 references)
target     prot opt source               destination 

#修改
[root@ubuntu ~]# iptables -t filter -E web_chain WEB_CHAIN

#向自定链中添加规则
[root@ubuntu ~]# iptables -t filter -A WEB_CHAIN -p tcp -m multiport --dports 80,443 -j ACCEPT

#查看
[root@ubuntu24 sites-enabled]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain WEB_CHAIN (0 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             multiport dports http,https
    
    
#自定义链必须关联到系统链上才能使用
[root@ubuntu ~]# iptables -t filter -A INPUT -s 10.0.0.1 -j WEB_CHAIN
#再次查看
[root@ubuntu24 sites-enabled]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
WEB_CHAIN  all  --  10.0.0.1             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain WEB_CHAIN (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             multiport dports http,https

在使用单独的自定义链的情况下,如果需要修改,则只需要修改链上的具体规则,而不用修改自定义链 与系统链的关联关系

自定义链中的规则进行复用

清空规则,并不会删除自定义链

[root@ubuntu24 sites-enabled]# iptables -t filter -F
[root@ubuntu24 sites-enabled]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain WEB_CHAIN (0 references)
target     prot opt source               destination

#删除自定义链
[root@ubuntu ~]# iptables -t filter -X WEB_CHAIN

firewalld

 

firewalld 介绍

firewalld 是 CentOS 7.0 新推出的管理 netfilter 的用户空间软件工具,也被 ubuntu18.04 版以上所支 持 (apt install firewalld)

firewalld 是配置和监控防火墙规则的系统守护进程,可以实现 iptables,ip6tables,ebtables 的功 能。

firewalld 服务由 firewalld 包提供。

firewalld 中有多个系统自带的 Zone,每个zone都对应不同的防火墙规则,使用不同的 Zone,就表示 使用不同的防火墙规则,每个Zone的具体规则可以进行修改,也可以自定义Zone。

firewalld 中自带的 Zone

Zone说明
block拒绝所有
dmz拒绝除和传出流量相关的,以及ssh预定义服务之外的其它所有传入流量
drop拒绝除和传出流量相关的所有传入流量(甚至不以ICMP错误进行回应)
external拒绝除和传出流量相关的,以及ssh预定义服务之外的其它所有传入流量,属于 external zone的传出ipv4流量的源地址将被伪装为传出网卡的地址
home拒绝除和传出流量相关的,以及ssh,mdsn,ipp-client,samba-client,dhcpv6-client预 定义服务之外其它所有传入流量
internal和home相同
public拒绝除和传出流量相关的,以及ssh,dhcpv6-client预定义服务之外的其它所有传入 流量,新加的网卡默认属于public zone
trusted允许所有流量
work拒绝除和传出流量相关的,以及ssh,ipp-client,dhcpv6-client预定义服务之外的其它 所有传入流量

firewalld 三种配置方法

  • firewall-config 图形工具:需要安装 firewall-config 包

  • firewall-cmd 命令行工具:来自于 firewalld 包,默认己安装

  • /etc/firewalld/* 配置文件:一般不直接修改配置文件来管理firewalld

#安装
[root@c7 ~]# yum install -y firewall-config
#要依赖本地主机的图形化软件
[root@c7 ~]# firewall-config

firewall-cmd 工具

firewall-cmd 是 firewalld 服务的命令行编辑工具

firewall-cmd [OPTIONS...]

#常用选项
--state     		#查看服务运行状态     
--reload         	#重载,修改后只是在当前运行环境下生效,如果想还原回去之前的配置,可以使用此选项
--complete-reload 	#完全重载
--runtime-to-permanent #将当前运行状态的配置永久保存
--check-config 		#检查规则配置是否出错
--get-log-denied 	#显示日记记录规则
--set-log-denied= 	#设置日志记录规则 all|unicast|broadcast|multicast|off
--permanent 		#设置永久生效规则时加上此项,如果没有此项,则更改的都是临时生效规则

--get-default-zone 		#显示默认使用的 zone
--set-default-zone= 	#设置默认zone
--get-active-zones   	#显示当前使用中的 zone及对应的设备
--get-zones         	#显示可用的 zone
--get-services       	#显示所有己定义的 services,每一个 services 对应一个或多个端口规则,多个 service 组成 zone
--get-icmptypes 		#显示icmp协议类型
--get-zone-of-interface= #显示指定设备的 zone
--list-all-zones 		#列出每个zone中的所有规则
--new-zone= 			#添加一个新的zone
--new-zone-from-file= 	#从指定文件中读取规则,添加新zone
--delete-zone= 			#删除指定zone
--zone= 				#指定zone,配合其它选项
--info-zone= 			#查看指定zone运行情况

--new-service= 			#添加一个新的 service
--new-service-from-file= #从文件中添加一个新的 serivce 
--list-services 		#显示所有 service
--delete-service= 		#删除 service
--info-service= 		#输出 info 相关信息
--change-interface= #指定要修改的设备,与其它项一起配合使用


#查看默认Zone中的所有内容
[root@rocky86 ~]# firewall-cmd --list-all
block (active)
 target: %%REJECT%% 	#目标
 icmp-block-inversion: no #决定 icmp-blocks
 interfaces: eth0 eth1 	#生效的网络设备
 sources: 				#来源,IP或MAC
 services: http ssh 	#放行的服务
 ports: 				#允许的目标端口,即本地开放的端口
 protocols: 			#允许通过的协议
 forward: no 			#允许转发的端口
 masquerade: no 		#是否允许伪装(yes/no),可改写来源IP地址及mac地址
 forward-ports: 		#允许转发的端口
 source-ports: 			#允许的源端口
 icmp-blocks: 			#ICMP类型,配合 icmp-block-inversion=no/yes一起使用
 rich rules: 			#富规则

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值