在上一节中,我们介绍了iptables和netfilter的基本关系,在这里我们会进一步介绍现有的NAT以及Linux中大多已实现的MASQUERADE实现原理。

1. NAT类型介绍

  常用的NAT类型主要有Full Cone NAT(全锥型), Restricted NAT(限制型锥型), Port Restricted NAT(端口限制型锥型), Symmetric NAT(对称型)四种。

  四种类型的主要区别在于对外界访问内部IP的控制力度。为方便解释,我们使用如下的用语来说明四种NAT类型的不同之处。

用语定义

  1. 内部Tuple:指内部主机的私有地址和端口号所构成的二元组,即内部主机所发送报文的源地址、端口所构成的二元组
  2. 外部Tuple:指内部Tuple经过NAT的源地址/端口转换之后,所获得的外部地址、端口所构成的二元组,即外部主机收到经NAT转换之后的报文时,它所看到的该报文的源地址(通常是NAT设备的地址)和源端口
  3. 目标Tuple:指外部主机的地址、端口所构成的二元组,即内部主机所发送报文的目标地址、端口所构成的二元组

详细释义

  1. Full Cone NAT:所有来自同一 个内部Tuple X的请求均被NAT转换至同一个外部Tuple Y,而不管这些请求是不是属于同一个应用或者是多个应用的。除此之外,当X-Y的转换关系建立之后,任意外部主机均可随时将Y中的地址和端口作为目标地址 和目标端口,向内部主机发送UDP报文,由于对外部请求的来源无任何限制,因此这种方式虽然足够简单,但却不那么安全

  2. Restricted Cone NAT: 它是Full Cone的受限版本:所有来自同一个内部Tuple X的请求均被NAT转换至同一个外部Tuple Y,这与Full Cone相同,但不同的是,只有当内部主机曾经发送过报文给外部主机(假设其IP地址为Z)后,外部主机才能以Y中的信息作为目标地址和目标端口,向内部 主机发送UDP请求报文,这意味着,NAT设备只向内转发(目标地址/端口转换)那些来自于当前已知的外部主机的UDP报文,从而保障了外部请求来源的安 全性

  3. Port Restricted Cone NAT:它是Restricted Cone NAT的进一步受限版。只有当内部主机曾经发送过报文给外部主机(假设其IP地址为Z且端口为P)之后,外部主机才能以Y中的信息作为目标地址和目标端 口,向内部主机发送UDP报文,同时,其请求报文的源端口必须为P,这一要求进一步强化了对外部报文请求来源的限制,从而较Restrictd Cone更具安全性

  4. Symmetric NAT:这是一种比所有Cone NAT都要更为灵活的转换方式:在Cone NAT中,内部主机的内部Tuple与外部Tuple的转换映射关系是独立于内部主机所发出的UDP报文中的目标地址及端口的,即与目标Tuple无关; 在Symmetric NAT中,目标Tuple则成为了NAT设备建立转换关系的一个重要考量:只有来自于同一个内部Tuple 、且针对同一目标Tuple的请求才被NAT转换至同一个外部Tuple,否则的话,NAT将为之分配一个新的外部Tuple;打个比方,当内部主机以相 同的内部Tuple对2个不同的目标Tuple发送UDP报文时,此时NAT将会为内部主机分配两个不同的外部Tuple,并且建立起两个不同的内、外部 Tuple转换关系。与此同时,只有接收到了内部主机所发送的数据包的外部主机才能向内部主机返回UDP报文,这里对外部返回报文来源的限制是与Port Restricted Cone一致的。不难看出,如果说Full Cone是要求最宽松NAT UDP转换方式,那么,Symmetric NAT则是要求最严格的NAT方式,其不仅体现在转换关系的建立上,而且还体现在对外部报文来源的限制方面。

2. Masquerade 用户空间的实现

  在Netfilter中,不同NAT的实现在内核中进行。而通常情况下,Linux系统自带的NAT类型多为端口限制型锥型NAT或者对称型。对此,我们参照着内核和用户层的源码进行说明。这里之所以说为端口限制型锥型NAT或对称型NAT是因为系统自带的MASQUERADE部分模块根据配置命令行的不同可以实现上述两种不同类型的NAT。由上一篇,大家应该都知道了iptables和Netfilter的关系,这里我们先看看在用户层,Iptables命令中关于MASQUERADE的实现。

  源码名libipt_MASQUERADE.c,位置的话不同版本的linux系统可能不大一样。该部分主要是实现对配置masquerade命令的解析以及注册,注册之后即可激活内核空间中的masquerade相应钩子函数实现masquerade功能。关于钩子函数和内核中masquerade的实现,在下一讲中将会简单介绍。

  首先看一下该源码的大体框架。

  由图可见,该部分主要由help, opts, init, parse_ports, parse, final_check, print, save, masq, _init组成。按
各个函数、结构的名称大致可以猜测到该函数做的是什么功能,之后实现其他几种NAT均需要模仿该模块完成。

  首先需要介绍的是masq。源码如下

static struct iptables_target masq = {NULL,.name= "MASQUERADE",.version= IPTABLES_VERSION,.size= IPT_ALIGN(sizeof(struct ip_nat_multi_range)),.userspacesize= IPT_ALIGN(sizeof(struct ip_nat_multi_range)),.help= &help,.init= &init,.parse= &parse,.final_check= &final_check,.print= &print,.save= &save,.extra_opts= opts};

  该部分是整个MASQUERADE的注册,给定了该结构体的各个元素(名称、版本、函数实现等)。所有其他的iptables命令行参数均以此形式添加,注意这里的名字必须和内核中注册的钩子函数一致才可生效。关于为何这样写即可成功注册并与内核中的相应钩子函数配对,需要研究相关源码才可了解,在此无法简单概括,后面会单独写一篇进行讲解。

  help部分即命令行常用的帮助部分,在MASQUERADE中,实现如下。

/* Function which prints out usage message. */
static void
help(void)
{printf("MASQUERADE v%s options:\n"" --to-ports <port>[-<port>]\n""Port (range) to map to.\n"" --random\n""Randomize source port.\n""\n",IPTABLES_VERSION);}

  这里我们可以很清晰的了解iptables中MASQUERADE如何配置。之前所说的MASQUERADE可以配置两种不同类型的NAT也来源于此,提供的–random功能即为对称型NAT,其他两种形式命令行则为端口限制型锥形NAT的配置。其实这里的help是为使用该命令行的人提供的功能。当你添加了这个程序到Netiflter中,在命令行输入iptables -t nat -h即可自动出现该帮助菜单。

  opts是对用户输入做出控制的结构体,和上文中提供的功能对应,代码如下。

static struct option opts[] = {{"to-ports", 1, 0, '1'},{"random", 0, 0, '2'},{0 }};

  parse函数是对用户输入命令行的解析,主要用于判断是否正确输入命令,并做了详细的异常处理机制(其实也就是打印提示错误),代码如下,其中已对关键位置做注释说明。

/* Function which parses command options; returns true if itate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,const struct ipt_entry *entry,struct ipt_entry_target **target)
{int portok;struct ip_nat_multi_range *mr= (struct ip_nat_multi_range *)(*target)->data;/* 协议检测 */if (entry->ip.proto == IPPROTO_TCP|| entry->ip.proto == IPPROTO_UDP|| entry->ip.proto == IPPROTO_ICMP)portok = 1;elseportok = 0;/* 输入1个参数则需要检查端口,输入2个即random类型不需要检测,直接给标记为赋值 */     switch (c) {case '1':if (!portok)exit_error(PARAMETER_PROBLEM,"Need TCP or UDP with port specification");if (check_inverse(optarg, &invert, NULL, 0))exit_error(PARAMETER_PROBLEM,"Unexpected `!' after --to-ports");parse_ports(optarg, mr);return 1;case '2':mr->range[0].flags |=  IP_NAT_RANGE_PROTO_RANDOM;/*添加标记,该标记使得此类型转化为对称型NAT*/return 1;default:return 0;}}

  parse中调用的parse_port代码如下,同样在代码中注释说明。

/* Parses ports */
static void
parse_ports(const char *arg, struct ip_nat_multi_range *mr)
{const char *dash;int port;/*标记位赋值*/mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;port = atoi(arg);if (port <= 0 || port > 65535)exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", arg);/*这里允许不输入范围,即限定仅使用某个端口,dash = 0*/dash = strchr(arg, '-');if (!dash) {    mr->range[0].min.tcp.port= mr->range[0].max.tcp.port= htons(port);  } else {int maxport;maxport = atoi(dash + 1);if (maxport == 0 || maxport > 65535)exit_error(PARAMETER_PROBLEM,"Port `%s' not valid\n", dash+1);if (maxport < port)/* People are stupid.  Present reader excepted. */exit_error(PARAMETER_PROBLEM,"Port range `%s' funky\n", arg);mr->range[0].min.tcp.port = htons(port);mr->range[0].max.tcp.port = htons(maxport);}}

  其余都是很容易弄懂的一些函数,比如print即为打印出当前配置,save为保存配置,在此不做过多的介绍,有问题的可以联系我。

  本篇结束。


欢迎关注本人公众号,公众号会更新一些不一样的内容,相信一定会有所收获。

Netfilter学习之NAT类型动态配置(二)NAT类型介绍及MASQUERADE用户层的实现相关推荐

  1. typescript学习笔记1-tsconfig.json配置和变量类型声明

    一,tsconfig.json {// 编译器选项"compilerOptions": {/* 基本选项 */"target": "es5" ...

  2. kafka原理_Kafka动态配置实现原理解析

    总 第19篇 2019年 第15篇 一.问题导读Apache Kafka在全球各个领域各大公司获得广泛使用,得益于它强大的功能和不断完善的生态.其中Kafka动态配置是一个比较高频好用的功能,下面我们 ...

  3. ASA防火墙之NAT的实例配置

    ASA防火墙之NAT的实例配置 关于nat的知识点我们在讲路由器的时候已经讲述过了,具体为啥配置NAT技术这里不再讲述,本篇讲述的关于ASA防火墙的各个NAT配置实例的分析,包括static NAT. ...

  4. php+读取配置里的值,ThinkPHP 读取配置信息与动态配置(C方法)

    ThinkPHP C 方法 C 方法是 ThinkPHP 内置的特殊方法,用于在操作和模板里读取配置文件里的配置信息或者动态配置参数.语法如下: C( para_name, value ) 参数说明 ...

  5. Kubernetes 1.6新特性系列 | 动态配置和存储类

    导读: Dynamic Provisioning的目标是完全自动化存储资源的生命周期管理,让用户无需过多的关注存储的管理,可以按需求自动动态创建和调整存储资源.StorageClass本质上是底层存储 ...

  6. Linux下Netfilter创建自己的Hook,让数据包可以发送到用户层,然后统计节点负载信息

    Linux下Netfilter创建自己的Hook函数,让数据包可以发送到用户层,然后统计节点的负载信息 写在最前面,我的linux内核版本是4.4.0-31-generic,版本是Ubuntu 16. ...

  7. NAT的类型与配置(学习笔记)

    一.NAT的类型 1.静态NAT 静态NAT是指在路由器中,将内网IP地址固定地转换为外网IP地址,通常应用在允许外网用户访问内网服务器的场景中. 2.动态NAT 动态NAT指将一个内部IP地址转换为 ...

  8. 操作篇 了解学习NAT实验(关于静态NAT、动态NAT、EasyIP、端口映射的配置方法))

    文章目录 前言 NAT工作原理 NAT分类 一:实验环境 1.1:实验原理 1.2实验目的 1.3华为NAT实验拓扑图 二:实验过程 配置SW1 配置AR1: 配置AR2: 前言 随着Internet ...

  9. 华为静态NAT、动态NAT、NAPT、Easy NAT配置实例

    一.NAT的四种类型 1,静态NAT(服务器地址转换) 静态NAT实现了私有地址和公有地址的一对一转换,一个公网地址对应一个私网地址 2,动态NAT 动态NAT基于地址池来实现私有地址和公有地址的转换 ...

  10. 配置静态NAT和配置动态NAT

    配置静态NAT 随着接入Internet的计算机数量的不断猛增,IP地址资源也就愈加显得捉襟见肘.事实上,除了中国教育和科研计算机网(CERNET)外,一般用户几乎申请不到整段的C类IP地址.在其他I ...

最新文章

  1. 【pyQuery】抓取startup news首页
  2. leetcode 82. 删除排序链表中的重复元素 II
  3. 【中级软考】什么是McCabe测量法(McCabe复杂性度量、环路度量。计算有向弧数、结点数、强连通分量个数)
  4. selenium定位输入框_[Selenium 粗浅笔记] 用Selenium填写表单
  5. ROS的学习(十九)用rosserial创建一个subscriber
  6. ffmpeg (四):ffmpeg, ffplay, ffprobe用法
  7. IE各浏览器HACK
  8. python 初级笔记
  9. iText5实现Java生成PDF文件完整版
  10. 计算机的储存容量1kb等于多少byte,1kb等于多少mb
  11. CodeWarrior for S12(X) V5.1 Special详细安装过程
  12. 常见的网站功能需求及解决方案
  13. 手把手写深度学习(16):用CILP预训练模型搭建图文检索系统/以图搜图/关键词检索系统
  14. dlna 电脑连r1_电脑上dlna功能怎么用?
  15. Ganymed SSH-2(ch.ethz.ssh2)
  16. 百度语音合成Rest API使用
  17. 高一被清华姚班录取,高三委拒谷歌 offer,一个重度网瘾少年到理论计算机科学家的蜕变!...
  18. Amazon SQS 消息相关接口测试用例
  19. Android定制个性化字体
  20. JAVA 特约商户进件对接

热门文章

  1. 记录一次idea因为虚拟内存不足而闪退的经历
  2. 送给女朋友的圣诞节电子贺卡源代码,圣诞节快乐代码
  3. 2019年 年终总结
  4. 区块链开发之智能合约设计模式
  5. 时间固定效应和个体固定效应的选择_【十分钟计量经济学】面板数据选择固定效应还是随机效应...
  6. 魔兽世界怀旧服最新服务器开发时间,魔兽世界怀旧服明日开放,开服第一天“大部队”能升到多少级?...
  7. CC2530看门狗定时器实现1秒定时
  8. 清音驱腐启鸿蒙,中华成语千句文解释.doc
  9. html蒙版代码是什么意思,图层蒙版是什么意思
  10. 配置 PO SLD步骤