(九)洞悉linux下的Netfilter&iptables:网络地址转换原理之DNAT

洞悉linux下的Netfilter&iptables 发现不错的讲解linux下的Netfilter&iptables的文章,记录如下: (一)洞悉linux下的Netfilter&iptables:什么是Netfilter?  (二)洞悉linux下的Netfilter&iptables:内核中的ip_tables小觑  (三)洞悉linux下的Netfilter&iptables:内核中的rule,match和target (四) 阅读详情

网络地址转换:NAT

     Netfitler为NAT在内核中维护了一张名为nat的表,用来处理所有和地址映射相关的操作。诸如filter、nat、mangle抑或raw这些在用户空间所认为的“表”的概念,在内核中有的是以模块的形式存在,如filter;有的是以子系统方式存在的,如nat,但它们都具有“表”的性质。因此,内核在处理它们时有很大一部操作都是相同的,例如表的初始化数据、表的注册、钩子函数的注册等等。关于NAT表的初始化模板数据和表的注册流程并不是本文的重点,大家可以对照第四篇博文中filter表的相关分析来研究。本文还是侧重于从整体上对整个NAT子系统的设计思想和原理进行,当然,有时间我还是会简单和大家分析一NAT表的东西。因为最近确实太忙了,本来想着在四月份结束这个系列,无奈一转眼就晃到了五月份,做IT的娃,都不容易啊!

     通过前面的几篇文章我们已经知道,NAT的设计是独立于连接跟踪系统的,即连接跟踪是NAT的基础框架,我们还了解到连接跟踪不会修改数据包,它只是负责维护数据包和其所属的业务会话或数据连接状态的相关信息而已。连接跟踪最终是被iptables模块所使用的,它所定义的那些状态信息如NEW、ESTABLISHED、RELEATED等等,NAT统统不用关心。

     根据前面的hook函数挂载图我们可以清晰的知道,对于那些需要被本机转发的数据包,注册在NF_IP_PRE_ROUTING点的ip_nat_in ()函数完成对其目的地址转换的操作,注册在NF_IP_POST_ROUTING点的ip_nat_out()函数完成源地址转换任务。如果在编译Linux内核源码时打开了CONFIG_IP_NF_NAT_LOCAL选项,则注册在NF_IP_LOCAL_OUT和NF_IP_LOCAL_IN点的hook函数就会工作,最常见的用法的是用NF_IP_LOCAL_OUT点的ip_nat_local_fn()函数来改变本机发出报文的目的地址。至于注册在NF_IP_LOCAL_IN点的ip_nat_fn()函数一般不会起作用,只是当数据包到达该HOOK点后会例行被调用一下。因为,NAT的所有规则只可能被配置到nat表的PREROUTING、POSTROUTING和OUTPUT三个点上,一般也很少有人去修改那些路由给本机的报文的源地址。

         NAT的分类如下图所示:

    相信大家在看iptables用户指南都见过这么一句解释:

    只有每条连接的第一个数据包才会经过nat表,而属于该连接的后续数据包会按照第一个数据包则会按照第一个报所执行的动作进行处理,不再经过nat表。Netfilter为什么要做这个限制?有什么好处?它又是如何实现的?我们在接下来的分析中,将一一和大家探讨这些问题。

    在ip_nat_rule.c文件中定义了nat表的初始化数据模板nat_table,及相应的target实体:SNAT和DNAT,并将其挂在到全局xt[PF_INET].target链表中。关于NAT所注册的几个hook函数,其调用关系我们在前几篇博文中也见过:

 

因此,我们的核心就集中在ip_nat_in()上。也就是说,当我们弄明白了ip_nat_fn()函数,你就差不多已经掌握了nat的精髓。ip_nat_in()函数定义定在ip_nat_standalone.c文件里。连接跟踪作为NAT的基础,而建立在连接跟踪基础上的状态防火墙同样服务于NAT系统。

    关于ip_nat_fn()函数我们还是先梳理整体流程,以便大家对其有一个宏观整体的把握,然后我们再来分析其实现细节。这里需要大家对连接跟踪的状态跃迁有一定了了解。

 

    从流程图可以看出,牵扯到的几个关键函数都土黄色标注出来了。ip_nat_setup_info()函数主要是完成对数据包的连接跟踪记录ip_conntrack对象中相应成员的修改和替换,而manip_pkt()中才是真正对skb里面源/目的地址,端口以及数据包的校验和字段修改的地方。

 

 

目的地址转换:DNAT

         DNAT主要适用于将内部私有地址的服务发布到公网的情形。情形如下:

 

 

    服务器上架设了Web服务,其私有地址是B,代理防火墙服务器有一个公网地址A。想在需要通过A来访问B上的Web服务,此时就需要DNAT出马才行。根据前面的流程图,我们马上杀入内核。

当client通过Internet访问公网地址A时,通过配置在防火墙上的DNAT将其映射到了对于私网内服务器B的访问。接下来我们就分析一下当在client和server的交互过程中架设在防火墙上NAT是如何工作。

还是看一下hook函数在内核中的挂载分布图。

 

    在PREROUTING点当一个skb被连接跟踪过后,那么skb->ctinfo和skb->nfct两个字段均被设置了值。在接下来的分析中,对那些梢枝末节的代码我们都将不予理睬。盗个图:

 

 

这里牵扯到一个变量ip_conntrack_untracked,之前我们见过,但是还没讨论过。该变量定义在ip_conntrack_core.c文件里,并在ip_conntrack_init()函数进行部分初始化:

atomic_set(&ip_conntrack_untracked.ct_general.use, 1);

set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);

同时,在ip_nat_core.c文件里的ip_nat_init()函数中又有如下设置:

ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;

该变量又是何意呢?我们知道iptables维护的其实是四张表,有一张raw不是很常用。该表以-300的优先级在PREROUTING和LOCAL_OUT点注册了ipt_hook函数,其优先级要高于连接跟踪。当每个数据包到达raw表时skb->nfct字段缺省都被设置成了ip_conntrack_untracked,所以当该skb还没被连接踪的话,其skb->nfct就一直是ip_conntrack_untracked。对于没有被连接跟踪处理过的skb是不能进行NAT的,因此遇到这种情况代码中直接返回ACCEPT。

从上面的流程图可以看出,无论是alloc_null_binding_confirmed()、alloc_null_binding()还是ip_nat_rule_find()函数其本质上最终都调用了ip_nat_setup_info()函数。

 

ip_nat_setup_info()函数:

该函数中主要完成了对连接跟踪记录ip_conntrack.status字段的设置,同时根据可能配置在nat表中的DNAT规则对连接跟踪记录里的响应tuple进行修改,最后将该ip_conntrack实例挂载到全局双向链表bysource里。

    在连接跟踪系统里根据skb的源/目的IP分别已经构建生成初始tuple和响应tuple,我们通过一个简单的示意图来回顾一下其流程,并加深对ip_nat_setup_info()函数执行过程的理解。

 

 

在图1中,根据skb的源、目的IP生成了其连接跟踪记录的初始和响应tuple;

在图2中,以初始tuple为输入数据,根据DNAT规则来修改将要被改变的地址。这里是当我们访问目的地址是A的公网地址时,DNAT规则将其改成对私网地址B的访问。然后,计算被DNAT之后的数据包新的响应。最后用新的响应tuple替换ip_conntrack实例中旧的响应tuple,因为数据包的目的地址已经被改变了,所以其响应tuple也必须跟着变。

在图3中,会根据初始tuple计算一个hash值出来,然后以ip_conntrack结构中的nat.info字段会被组织成一个双向链表,将其插入到全局链表bysource里。

最后,将ip_conntrack.status字段的IPS_DST_NAT和IPS_DST_NAT_DONE_BIT位均置为1。

这里必须明确一点:在ip_nat_setup_info()函数中仅仅是对ip_conntrack结构实例中相关字段进行了设置,并没有修改原始数据包skb里的源、目的IP或任何端口。

 

ip_nat_packet()函数的核心是调用manip_pkt()函数:

在manip_pkt()里主要完成对数据包skb结构中源/目的IP和源/目的端口的修改,并且修改了IP字段的校验和。从mainip_pkt()函数中返回就回到了ip_nat_in()函数中(节选):

ret = ip_nat_fn(hooknum, pskb, in, out, okfn);

if (ret != NF_DROP && ret != NF_STOLEN&& daddr != (*pskb)->nh.iph->daddr) {

         dst_release((*pskb)->dst);

         (*pskb)->dst = NULL;

}

return ret;

    正常情况下返回值ret一般都为NF_ACCEPT,因此会执行if条件语句,清除skb原来的路由信息,然后在后面协议栈的ip_rcv_finish()函数中重新计算该数据包的路由。

在数据包即将离开NAT框架时,还有一个名为ip_nat_adjust()的函数。参见hook函数的挂载示意图。该函数主要是对那些执行了NAT的数据包的序列号进行适当的调整。如果调整出错,则丢弃该skb;否则,将skb继续向后传递,即将到达连接跟踪的出口ip_confirm()。至于,ip_confirm()函数的功能说明我们在连接跟踪章节已经深入讨论了,想不起来的童鞋可以回头复习一下连接跟踪的知识点。

 

前面我们仅分析了从client发出的第一个请求报文到server服务器时,防火墙的处理工作。紧接着我们顺着前面的思路继续分析,当server收到该数据包后回应时防火墙的处理情况。

server收到数据包时,该skb的源地址(记为X)从未变化,但目的地址被防火墙从A改成了B。server在响应这个请求时,它发出的回应报文目的地址是X,源地址是自己的私有地址B。大家注意到这个源、目的地址刚好匹配被DNAT之后的那个响应tuple。

当该回应报文到达防火墙后,首先是被连接跟踪系统处理。显而易见,在全局的连接跟踪表ip_conntrack_hash[]中肯定可以找到这个tuple所属的连接跟踪记录ip_conntrack实例。关于状态的变迁参见博文八。

然后,该回应报文到达NAT框架的ip_nat_in()函数,流程和前面一样,但处理方式肯定不同。我们还是先看一下截止到目前为止,这条连接跟踪结构图:

 

 

直接跳到ip_nat_packet()函数里,当netlink通知机制将连接跟踪状态由NEW变为REPLY后,此时dir=1,那么根据初始tuple求出原来的响应tuple:源地址为A,目的之为X。此时,server的响应报文,源地址为私有网段B,目的地址为X。路由寻址是以目的地址为依据,防火墙上有直接到client的路由,所以响应报文是可以被client正确收到的。但是,但可是,蛋炒西红柿,对于UDP来说client收到这样的回复没有任何问题的,但是对于TCPU而言确实不行的。这就引出我们接下来将要讨论的SNAT。

    未完,待续…
[Realtek sdk-3.4.14b]升级iptables以支持IPv6 DHCPV6 NAT6的MASQUERADE属性(原厂默认iptables不支持NAT6) 升级原因 由于原厂自带iptables版本V1.4.4,默认不支持NAT6的MASQUERADE,查看内核默认是可以支持NAT6的MASQUERADE,只需要在内核开启以下配置 CONFIG_NF_NAT_IPV6=y CONFIG_IP6_NF_TARGET_MASQUERADE=y 下载iptables软件包 软件包下载地址 Index of /pub/iptables (netfilter.org)http://ftp.netfilter.org/pub/iptables/... 阅读详情

相关推荐

netfilter 五个钩子点实现SNAT和DNAT的方案

netfilter_queue的安装包所需依赖包,先安装libmnl然后libnfnetlink最后netqueue。在钩子点可以通过return NF_QUEUE对所需数据包进行地址转换

通过iptables实现NAT网络地址转换

内核配置 # # IP: Netfilter Configuration # CONFIG_NF_DEFRAG_IPV4=m CONFIG_NF_CONNTRACK_IPV4=m CONFIG_NF_CONNTRACK_PROC_COMPAT=y CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CON...

camel_in_sand的专栏 1402

VS2103+Intel2013+MSMPI运行Fortran并行程序

VS2103+Intel2013+MSMPI运行Fortran并行程序MSMPI安装新建Fortran90项目编写Fortran并行程序在cmd运行编译完成的执行文件 MSMPI安装 我这里采用的是Microsoft MPI v9.0.1,可以点此下载。下载完成后同时安装msmpisdk.msi、msmpisetup.exe两个文件,安装位置默认即可。 其中msmpisdk.msi的默认安装路径在C:\Program Files (x86)\Microsoft SDKs\MPI,该文件包含了mpi环境所需

weixin_43176703的博客 2937

iptables的内核配置

CONFIG_PACKET - 允许程序直接访问网络设备(译者注:最常用的就是网卡了),象tcpdump 和 snort就要使用这个功能。 严格地说,iptables并不需要CONFIG_PACKET,但是它有很多用处(译者注:其他程序需要),所以就选上了。当然,你不想要,不选就是了。(译者注:建议还是选的为好) CONFIG_NETFILTER - 允许计算机作为网关或防火墙。这个是必需的,因为整篇文章都要用到这个功能。我想你也需要这个,谁叫你学iptables呢:) 当然,你要给网络设备安装正确的

阿Sir问道 3533

用74LS190和555定时器复刻经典交通灯:一个电子工程新手的实战避坑记录

本文记录了使用74LS190和555定时器复刻经典交通灯的实战过程,详细介绍了元件选型、电路搭建与调试的关键步骤。特别分享了555定时器参数设置、74LS190级联技巧以及状态机设计的避坑经验,为电子工程新手提供实用参考。

weixin_42629671的博客 306

C++ 类

本文介绍了C++中类的核心概念和使用方法。

weixin_54859557的博客 1016

Linux下NAT功能的实现

本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性,严禁用于任何商业用途。msn: yfydz_no1@hotmail.com来源: http://yfydz.cublog.cn1. 前言在2.4/2.6内核的Linux中的防火墙代码netfilter中支持源NAT(SNAT)和目的NAT(DNAT),基本可以满足各种类型的NAT需求,本文介

奋起的blog 5631

2025年12月GESP真题及题解(C++一级): 小杨的爱心快递

2025年12月GESP真题及题解(C++一级): 小杨的爱心快递

王老师青少年编程 1648

洞悉linux下的Netfilter&iptables:网络地址转换原理之DNAT

(九)洞悉linux下的Netfilter&iptables:网络地址转换原理之DNAT 2012-05-16 21:12:27 点击打开链接 分类: LINUX 网络地址转换:NAT      Netfitler为NAT在内核中维护了一张名为nat的表,用来处理所有和地址映射相关的操作。诸如filter、nat、mangle抑或raw这些在用户空间所认为的“表”的概念,

hanyingzhong的专栏 936

PCIe 全解析笔记:从协议本质到工程实现

学习 PCIe,最容易陷入的误区是直接跳进协议手册(Base Spec 1300 多页),然后在 TLP 字段、LTSSM 状态、Ordering Rules 中迷失方向。正确的思维路径历史维度:从 PCI 到 PCIe,解决了什么核心矛盾?抽象维度:协议栈分层的真正意图是什么?工程维度:高速串行链路面临哪些物理挑战?协议如何应对?系统维度:作为 CPU 与外设的"动脉",PCIe 如何融入整个计算机体系?带着这四个视角去看每一个细节,知识才能内化为认知。

m0_46644103的博客 261

大数据开发工程师必备面试题与解答

大数据开发岗位一直是互联网行业的热门方向,面试过程中既考察基础知识,也关注实际项目经验和问题解决能力。本文整理了等核心组件相关的高频面试题及参考解答,帮助大家高效准备面试。大数据面试不仅考察基础理论,更看重项目经验与问题解决能力。本文涵盖了等核心知识点及调优思路,希望能帮助你在面试中游刃有余。

X2829352498的博客 302

洞悉linux下的Netfilter&iptables:网络地址转换原理之SNAT

SNAT主要应用于下列场景:     这种情况下,我们只有一个公网地址A,而又有三台主机需要同时上网,这时就需要SNAT了。它的主要作用是将那些由私网发来的数据包skb的源地址改成防火墙的公网地址A,这是因为目的主机在响应源地址为私网地址的数据包时,私网地址不能在网络上路由的缘故。     SNAT仅可以在LOCAL_OUT和POSTROUTING点生效,这也说明了为什么用户空间的ipta

carltraveler的专栏 857

手把手教你使用YOLOv11完成人脸分类识别,YOLOv11人脸识别,解决中文乱码问题,全网最详细教程

手把手教你使用YOLOv11完成人脸分类识别,YOLOv11人脸识别,解决中文乱码问题,全网最详细教程

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 4445

(十)洞悉linux下的Netfilter&iptables:网络地址转换原理之SNAT

源地址转换:SNAT     SNAT主要应用于下列场景:     这种情况下,我们只有一个公网地址A,而又有三台主机需要同时上网,这时就需要SNAT了。它的主要作用是将那些由私网发来的数据包skb的源地址改成防火墙的公网地址A,这是因为目的主机在响应源地址为私网地址的数据包时,私网地址不能在网络上路由的缘故。     SNAT仅可以在LOCAL_OUT和POSTROUTING点生效,这...

逐步前行 293

UG\NX二次开发 获取对象的层、颜色、隐藏状态、线宽、线型、高亮显示状态

获取对象的层、颜色、隐藏状态、线宽、线型、高亮显示状态。

王牌飞行员_里海的博客 1981

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

上一篇: Linux链表list_head/hlist_head/hlist_nulls_head的并发性
下一篇: (十)洞悉linux下的Netfilter&iptables:网络地址转换原理之SNAT
废言Pro
博客等级 码龄16年 1093粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值