《TCP/IP详解 卷一》第7章 防火墙和NAT
7.1 引言
NAT通常改变源IP和源端口,不改变目的IP和目的端口。
7.2 防火墙
常用防火墙:
包过滤防火墙(packet-filter firewall)
代理防火墙(proxy firewall)
代理防火墙作用:
1. 通过代理服务来代替内网的终端与外网通信。
2. 进行数据包分析,实现ACL访问控制。
7.2.1 包过滤防火墙
包过滤防火墙分为:
无状态防火墙:单独处理每一个数据包。
有状态防火墙:
记录所有经过报文的连接状态。包括源IP、目标IP、端口号、连接状态(如TCP)、分片信息等。
检测这些状态信息来判断是否允许通过。
7.2.2 代理防火墙
本质是应用层网关(ALG)。
作用:通过代理防火墙实现监控流量,访问控制,日志记录等。
常见代理防火墙:
HTTP代理防火墙。
SOCKS代理防火墙。
HTTP代理防火墙:
外网客户端通过HTTP代理防火墙访问内网Web资源,不直接与Web服务器通信。
Web代理还提供Web缓存功能,降低访问延迟。
SOCKS代理防火墙:
SOCKS:Socket Secure
优点:在客户端与服务器之间建立安全的、匿名的连接。
比HTTP代理更灵活,SOCKS能代理几乎所有流量。
支持认证,如用户名/密码认证。未经授权用户无法使用代理。
7.3 网络地址转换
即NAT。
如果应用层载荷内有IP地址或端口信息,此时NAT转换比较麻烦,如FTP,SIP协议。这需要ALG解决。
FTP和SIP数据连接需要使用动态端口,ALG可解决端口映射问题。
鼓励开发NAT友好的应用协议。
NAPT:网络地址端口转换,即IP源地址+源端口一起转换。
TCP三次握手时,当收到首次SYN包,就生成NAT映射表。收到第三次FIN的ACK后删除NAT映射表。
7.3.1 传统NAT:基本NAT和NAPT
基本NAT:只重写IP地址,但没有减少IP地址需求。
NAPT:使用IP地址+传输层标识符一起转换。
传输层标识:如TCP端口,UDP端口,ICMP查询标识符。
ICMP查询标识符:用于匹配ICMP请求和响应。
NAT与TCP:
路由器收到内网发送的SYN报文时,对SYN报文进行NAT转换,并建立NAT映射表。
路由器收到FIN报文时删除NAT映射表。
NAT和UDP:
收到第一个UDP报文时,对报文进行NAT转换,并建立NAT映射表。
当数据包从内网传输到外网经过NAT就刷新NAT映射表。超时未刷新就清除NAT映射条目。
难点:除了第一个分片,其他分片没有端口信息,所以需要NAT特殊处理甚至虚拟重组分片。
所以,IP分片和IP不分片在穿越NAT时吞吐速率有较大差距。显然不分片速率更高。
而TCP分段后每个TCP段都包含TCP头部,其中包含源目端口信息,因此NAT通常不需要重组TCP分段。CPU负荷小。
NAT和SCTP:
NAT和ICMP:
ICMP有两类报文:信息类,出错类。
出错类:包含引起错误的IP数据包副本,当ICMP出错报文通过NAT时,可根据实际需要是否改写出错报文中IP地址。
信息类:大多数报文类型是查询/响应或C/S模型,使用IP地址+ICMP查询ID共同建立映射。
总结:ICMP报文在NAT转换时,会结合ICMP报文中源目IP地址,ICMP序列号,ICMP查询ID等信息来建立NAT映射表,以区分内网不同主机。
NAT和隧道数据包:
如果隧道数据需要进行NAT,NAT不仅修改IP包头,还需修改隧道内部包头和载荷。
如果有更多层的隧道封装,NAT工作更复杂。
NAT和组播:
NAT也可支持组播,少见,用IGMP代理来增强NAT,到外部数据目的IP地址和端口不会被修改。
NAT和IPv6:
坚决抵制在IPv6中使用NAT。
7.3.2 地址和端口转换行为
NAT地址池:有几个可用的外部IP地址可供NAT转换。
7.3.3 过滤行为
若没有建立NAT映射,就无法转发从外网到内网的流量。
只有内部主机主动向外网发送了报文,创建了映射,才允许外网传入的流量。
这起到一定过滤效果。
7.3.4 位于NAT之后的服务器
从外网经NAT访问内网服务器时,需要主动在NAT路由器上做端口映射/端口转发。
7.3.5 NAT夹发和NAT环回
目前网络需求多样化,我们应当结合实际网络需求,定制NAT配置。
而NAT环回和NAT夹发只是两种典型NAT配置,一般通常用iptables实现。
NAT环回举例:
1. 当内网主机A访问NAT设备公网IP地址时,NAT设备将请求转发给主机B。这样主机A可访问主机B的服务。
2. 内网主机访问NAT设备公网IP地址时,NAT设备将流量转发回到NAT路由器本身,以便内部主机访问路由器web服务。
NAT夹发举例:
内网主机访问NAT设备公网IP地址时,NAT设备将流量转发到外网,而返回给内部主机或NAT路由器。
7.3.6 NAT编辑器
当应用层协议包含端口,IP地址等低层信息时,NAT会变得复杂。如SIP协议,P2P(BitTorrent)。
NAT编辑器:
不仅改写IP头的IP地址和TCP/UDP头中的端口号,还修改应用层载荷中包含的IP端口信息。
如果NAT改变了包的应用载荷大小,还更改序列号。
7.3.7 服务提供者NAT和服务提供者IPv6转换
服务提供者NAT:将NAT从客户端移动到ISP端。
7.4 NAT穿越
NAT穿透解决的问题:
因为源IP被NAT转换,导致内网主机IP对外网不可见,造成通信障碍。
对等P2P网络因为NAT设备限制,无法直接通信。
NAT设备导致实时通信应用连接不稳定或高延迟。
NAT设备导致VPN连接失败。
NAT穿越技术常见方法:(后续会详细介绍)
STUN:STUN客户端向STUN服务器请求NAT后公网IP和端口,并确定NAT类型。
TURN:TURN服务器作为中间人,帮助两个客户端建立直接连接,并转发数据流量。
ICE:一种综合NAT穿越技术,结合STUN、TURN和其他协议。通过候选地址、检测网络类型和可用的传输协议等方式,寻找最佳通信路径,实现NAT穿越。
UPnP:向NAT路由器请求打开或关闭某端口,路由器对该端口报文不进行NAT转换,以允许设备直接通信。
7.4.1 针孔和打孔
针孔:
含义:NAT设备的一种工作模式。即NAT在转发数据时临时打开的端口或临时建立的NAT地址映射。
作用:仅允许特定数据流穿过NAT设备,而不是简单将所有数据流都转发到内网。
打孔工作原理:
NAT设备根据特定规则识别需打孔数据流。规则通常基于源IP地址、目标IP、端口等。
当内网主机向外网发送数据时,NAT设备动态为此数据流创建一个NAT映射,并NAT转换该数据流。
NAT设备只允许与该映射相关数据通过,而拒绝未授权数据通过。
一旦数据流完成或超时,动态映射将自动删除,防止潜在安全威胁。
打洞:
含义:一种网络穿透技术。用于两个不同私网主机之间直接通信,而不需要中间服务器转发。
打洞流程举例:
寻找公共节点:两个不同私网主机先尝试连接到一个公共服务器。
交换信息:当两个主机通过公共服务器交换各自私有IP和端口等信息。
建立映射:它们会向各自NAT设备发送数据,使NAT设备为这些数据包创建映射,并允许从外网中 的对等方直接发送数据包到对应私有IP和端口。
保持连接:一旦NAT映射建立成功,两个主机就以通过各自NAT设备直接建立通信连接,而不需经过中间服务器转发。
7.4.2 单边的自地址确定
自地址确定:内网主机使用一系列方法得到其NAT公网IP。
单边的自地址确定:不需要外部服务器或其他设备帮助,即可确定内网主机NAT转换后的公网IP。
7.4.3 NAT的会话穿越工具
NAT穿越:在NAT环境中,使不同私网主机直接建立通信,而不需要中间服务器转发。
STUN:Session Traversal Utilities for NAT
应用层C/S协议,用于确定内网经过NAT设备转换后的公网IP和端口,并通过心跳信息维持当前NAT绑定。
STUN功能包括:
发现NAT类型:内网STUN客户端向STUN服务器发送请求,以确定客户端网络NAT类型。有助于应用程序根据不同NAT类型采取相应策略。
获取公网IP地址和端口:客户端向STUN服务器发送请求,以获得公网IP和端口。
维持NAT映射:客户端定期向STUN服务器发送请求,使设备保持NAT映射关系,避免因为NAT映射超时导致通信中断。
STUN使用场景:对等网络P2P和实时应用。
STUN客户端和STUN服务器之间含有多个NAT设备时,不适合使用STUN,而是使用TURN。
STUN应用层协议可通过UDP、TCP封装。
使用互联网已知STUN服务器足够。

Linux上stun相关实现:
libstun
pjnath:C语言编写的网络穿透库,包括了STUN、TURN和ICE等功能。
7.4.4 利用NAT中继的穿越
TURN:Traversal Using Relays around NAT
适用场景:如两个内网设备位于不同NAT设备后,无法直接建立对等P2P连接,可通过使用TURN中继服务器中转数据流。
TURN服务器:位于公网的服务器,充当中继。两个内网设备都将数据发到TURN服务器,TURN服务器转发给对方设备。
缺点:TURN服务器虽然解决了NAT穿越问题,但增加了网络延迟。
STUN和TURN对比:
STUN:用于发现NAT后的公网IP和NAT类型,帮助建立对等P2P连接,不提供中继服务。
TURN: 当直接对等连接无法建立时,通过TURN中继服务器中转数据流。
7.4.5 交互连接建立
ICE是STUN和TURN的结合,当STUN建立P2P连接失败时,使用TURN。
7.5 配置包过滤防火墙和NAT
7.5.1防火墙规则
每个规则包含:匹配条件,动作(action)
匹配条件:报文的字段(源目IP、源目端口、ICMP类型),方向(direction)
iptables支持:无状态包过滤,有状态包过滤,NAT,NAPT
有状态包过滤:基于连接状态进行过滤,可检查包的状态(如NEW、ESTABLISHED、RELATED、INVALID)来确定是否允许或拒绝包通过。
举例:允许建立新连接的数据包:
iptables -A INPUT -m state --state NEW -j ACCEPT
iptables动作(target,action):可用于执行用户自定义链,或标准ACCEPT,DROP,QUEUE,RETURN
QUEUE:将数据包提交给一个用户程序处理。
iptables -A INPUT -j NFQUEUE --queue-num 23
应用进程通过libnetfilter_queue库函数读取queue-num 23的报文即可。
RETURN:回到之前的链中继续。
7.5.2 NAT 规则
Windows中NAT:互联网连接共享(Internet Connection Sharing, ICS)
Linux中NAT实现:
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE
masquerade:伪装,NAT转换会自动使用eth1的IP作为源IP。
7.5.3 与NAT和防火墙的直接交互:UPnP、NAT-PMP和PCP
NAT-PMP:NAT端口映射协议。
UPnP:通用即插即用。
UPnP作用:
动态创建端口映射,允许从Internet访问局域网内的服务器。
设备自动发现、设备描述,操作指令。比如手机远程控制空调。
Linux实现:
MiniUPnP开源软件包。
7.6 IPv4/IPv6共存和过渡中的NAT
7.7 与防火墙和NAT相关的攻击
当一个IP数据报被分片时,只有第一个分片包含端口,而其他分片没有。
因为许多老式防火墙没有能力处理IP分片。
解决方法:找到第一个分片(如果有的话),这需要一个有状态防火墙,但可能会资源耗尽攻击。
7.8 总结
代理防火墙:一种应用层网关ALG。每个应用都需要在防火墙上有自己的代理处理程序,以便修改其中载荷。
对于NAT后的内网服务器,需在NAT上主动配置端口转发,以允许外网流量的主动访问。
路由器收到报文后,一般先路由表查找,再NAT。
如果先NAT,后查找路由表,后果:
路由表查找不准确。
连接追踪可能无法正确识别或跟踪连接的状态。
安全问题,未授权报文可能被错误转发到网络中。
相关文章:
《TCP/IP详解 卷一》第7章 防火墙和NAT
7.1 引言 NAT通常改变源IP和源端口,不改变目的IP和目的端口。 7.2 防火墙 常用防火墙: 包过滤防火墙(packet-filter firewall) 代理防火墙(proxy firewall) 代理防火墙作用: 1. 通过代理服务…...
访问raw.githubusercontent.com失败问题的处理
1 问题 GitHub上的项目的有些资源是放在raw.githubusercontent.com上的,通常我们在安装某些软件的时候会从该地址下载资源,直接访问的话经常容易失败。 # 安装operator kubectl apply -f https://raw.githubusercontent.com/oceanbase/ob-operator/2.1…...
Elasticsearch的基本安装教程,Elasticsearch+SpringBoot实现简单的增删改查功能
Elasticsearch 是一个开源的分布式搜索和分析引擎,最初由 Elastic 公司开发。它是基于 Apache Lucene 的搜索引擎构建的,提供了强大的搜索和分析功能,并支持实时数据检索和分析。 Elasticsearch 被设计用来处理大规模的数据集,它具有以下几个主要特点: 分布式架构: Elast…...
【Git教程】(五)分支 —— 并行式开发,分支相关操作(创建、切换、删除)~
Git教程 分支 1️⃣ 并行式开发2️⃣ 修复旧版本中的 bug3️⃣ 分支4️⃣ 当前活跃分支5️⃣ 重置分支指针6️⃣ 删除分支7️⃣ 清理提交对象🌾 总结 对于版本提交为什么不能依次进行,以便形成一条直线型的提交历史记录,我们认为有 以下两个…...
Maven管理项目,本地仓库有对应的jar包,但还是报找不到
文章目录 业务场景错误提示分析过程解决办法 业务场景 settings.xml种配置了私服,但是有些依赖私服上没有,通过同事拷贝过来的。但是用maven打包时报红了。 错误提示 Idea Maven错误:was cached in the local repository, resolution will…...
手写JavaScript中的Promise.all方法(JS中Promise.all的执行过程)
简介: Promise.all是JavaScript中一种用于处理多个Promise对象的方法,该方法接收一个数组作为参数,并返回一个新的Promise对象。 这个新的对象会在所有Promise对象都成功解析后解析,解析的结果是一个数组,包含了所有P…...
IP设置教程
Win 7 固定Ip设定 https://jingyan.baidu.com/article/4b07be3cbc8e7348b380f31d.html Win 10 固定Ip设定 Win10 固定IP地址方法_win10设置固定ip地址怎么设置-CSDN博客 Win 11 固定Ip设定 https://jingyan.baidu.com/article/cb5d6105be5354415c2fe0d3.html TP-LINK…...
【Azure 架构师学习笔记】-Azure Synapse -- Link for SQL 实时数据加载
本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Synapse】系列。 前言 Azure Synapse Link for SQL 可以提供从SQL Server或者Azure SQL中接近实时的数据加载。通过这个技术,使用SQL Server/Azure SQL中的新数据能够几乎实时地传送到Synapse(…...
k8s(5)
目录 使用Kubeadm安装k8s集群: 初始化操作: 每台主从节点: 升级内核: 所有节点安装docker : 所有节点安装kubeadm,kubelet和kubectl: 修改了 kubeadm-config.yaml,将其传输给…...
【服务器数据恢复】ext3文件系统下硬盘坏道掉线的数据恢复案例
服务器数据恢复环境: 一台IBM某型号服务器上有16块FC硬盘组建RAID阵列。上层linux操作系统,ext3文件系统,部署有oracle数据库。 服务器故障&检测: 服务器上跑的业务突然崩溃,管理员发现服务器上有2块磁盘的指示灯…...
Sentinel 动态规则扩展
一、规则 Sentinel 的理念是开发者只需要关注资源的定义,当资源定义成功后可以动态增加各种流控降级规则。Sentinel 提供两种方式修改规则: 通过 API 直接修改 (loadRules)通过 DataSource 适配不同数据源修改 手动通过 API 修改比较直观,…...
UE5 UE4 自定义插件自动开启关联插件(plugin enable)
在我们自己编写UE4、UE5的插件时,常常需要开启相关联的插件进行功能编写。 例如:UE4/5 批量进行贴图Texture压缩、修改饱和度_ue4批量修改纹理大小-CSDN博客 而让插件使用者每次使用时,依次进行开启其他相关联插件确实有些麻烦。 如何只需要…...
Android摄像头横屏的时候_人脸预览横向显示_问题解决---Android原生开发工作笔记164
在Android系统的平板中发现一个问题,我们做的一个Android程序,横屏的时候,摄像头在上面, 然后这个时候程序中的一个人脸预览页面,横向手持平板,摄像头在上面,但是这个时候预览的摄像头画面却是很像头像朝左,也是横过来的. private int getCameraOrientation(int cameraId) {Ca…...
网络安全防御保护 Day6
深度检测技术 DFI(深度包检测技术):主要针对完整的数据包(数据包分片,分段需要重组),之后对 数据包的内容进行识别。 DPI(深度流检测技术):一种基于流量…...
自动驾驶消息传输机制-LCM
需要用到LCM消息通讯,遂研究下。 这里写目录标题 1 LCM简介2. LCM源码分析3 LCM C教程与实例3.1 安装配置及介绍3.2 创建类型定义3.3 初始化LCM3.4 发布publish一个消息3.5 订阅和接收一个消息3.6 LCM进程间通讯3.7 注意事项?3.7.1 当数据结构定义的是数…...
架构设计实践:熟悉架构设计方法论,并动手绘制架构设计图
文章目录 一、架构设计要素1、架构设计目标2、架构设计模式(1)分而治之(2)迭代式设计 3、架构设计的输入(1)概览(2)功能需求 - WH分析法(3)质量 - “怎么”分…...
【推荐算法系列十六】:协同过滤
文章目录 参考原理基于邻域的协同过滤算法基于用户的协同过滤(User-Based Collaborative Filtering)基于内容的协同过滤 基于模型的协同过滤算法 扩展优缺点 参考 推荐系统之神经协同过滤 原理 基于邻域的协同过滤算法 基于邻域的协同过滤算法又包括…...
linux动态库加载相关
linux下动态库搜索规则 (1)编译目标代码时指定的动态库搜索路径,也就是RPATH; (2)环境变量LD_LIBRARY_PATH指定的动态库搜索路径; (3)配置文件/etc/ld.so.conf中指定的动态库搜索路径;配置完毕后需运行ldconfig命令生效; (4)默…...
python 基础绘图函数 实例
简介 在 Python 中,有许多用于绘图的库。以下是一些常用的 Python 绘图库及其基本绘图函数的简要介绍: Matplotlib: matplotlib.pyplot.plot(x, y): 绘制线图。matplotlib.pyplot.scatter(x, y): 绘制散点图。matplotlib.pyplot.bar(x, height): 绘制条…...
28. 找出字符串中第一个匹配项的下标(力扣LeetCode)
文章目录 28. 找出字符串中第一个匹配项的下标题目描述暴力KMP算法 28. 找出字符串中第一个匹配项的下标 题目描述 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
字符串哈希+KMP
P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...
