IPv6的NAT原理以及MAP66

1.引

IPv6的标准中不建议使用NAT,个中缘由何在?这是一个问题,正如我很早之前解释的那样,IPv4的NAT打破了互联网本身的“互联”特性,使得一部分IP地址不再双向可达,NAT为无方向的IP协议增加了一个方向,特别是stateful的NAT类型。然而IPv4的NAT旨在节约IP地址,而非所谓的增加IP的方向性以及隐藏私有IP,这些只是一种难以摆脱的副作用罢了。
        IPv6的时代已经到来,只要不扩展到外太空,地球上的蚂蚁都可以使用IP设备了。IPv4的一些修补手段将不再需要,为了保持协议本身以及相关标准的纯洁性,IPv6几乎不再提起NAT。虽然不再提起,并不是说“你已不是你”,实现IPv6的NAT还是可能的,并且在某些情形下还是必要的。

2.相关的RFC

RFC6296的标题是IPv6-to-IPv6 Network Prefix Translation,描述了IPv6下的NAT的实现要点,给出了一个合理的建议,既保持了IP的无方向性,又可以满足NAT的语义,这就是IPv6之NAT stateless的缘由,你不能再指望像IPv4的NAT那样只需要配置一条rule,然后反方向的rule动态生成,IPv6情况下,两个方向的rule都需要你自己手工来配置。

3.IPv6子网和NAT的关系

IP地址可以划分为几个段,包括网络前缀,子网标识,主机标识,这在IPv4和IPv6中没有什么不同。IPv4的NAT为了节约IP地址,也就是说,可供映射的IP地址pool中的地址小于或者远远小于其内部主机的数量,因此很有可能多个内部主机被映射成了同一个外部IP地址,这如何来区分它们,因此不得不引入诸如第四层协议,端口等信息了,也就是我们熟知的五元组信息,因此IPv4的NAT实现大多数都是基于五元组流的,这样就保证了内核保持的NAT信息项的唯一性,同时也引入了很多副作用。
        IPv6地址持有将近128位可随意调配的位,鉴于地址空间的庞大,一般的单位都会被分配到一个拥有很大量地址的网段,此网段拥有足够多的地址来和内网主机进行一一映射,也就是说可用于映射的IP地址pool容量巨大无比,关键是这个一一映射如何来保持,既然不想再使用非IP层的信息来保持信息,那就要用纯IP层的信息了,这样对上层影响最小。对于IPv4,经典NAT使用了五元组来保持流标识信息,而对于IPv6,则更加绝妙,它利用(而不是使用)了checksum的算法,丝毫不管这个checksum是谁的checksum,因为它根本就不改变数据包的checksum...

4.IPv6和链路层的关系

IP标识一台主机,而MAC标识一个网络接口,它们其实是一对多的关系,然而现实中,一个IP往往会和一块网卡相关联,其中一个缘由就是可以自动生成链路层的路由信息。这是很方便的,然而对于IPv4,地址是自己配置或者通过DHCP来分配的,管理过程十分复杂,一不小心就会有地址冲突,不得不依靠ARP广播/RARP等技术来检测,之所以出现这种状况,一则因为分层理念太教条,谁说IP和链路层就不能有关联,谁说IP标示主机就不能关联网卡;二则因为IPv4地址空间太小,而MAC地址长度一般都会超过IP地址,虽然满足了RFC标准上的一对多的关系,但是使用起来很不方便。
        IPv6解决了这个问题,使得地址冲突问题减缓以致几乎消失。我们知道,MAC地址标示了一块物理设备,是看得见摸得着的,有时你摸一下还会碰到静电,MAC地址和你的身份证号码一样不会重复,IPv6将MAC地址映射到IPv6地址解决了IP地址冲突的大问题,同时这对于NAT也是有益的,这会影响到地址的自动转换,每一个不会重复的内部地址转换为一个不会重复的外部地址,这一切都要归功于IPv6的地址空间的巨大,可以随意杂耍。

5.checksum无关性和自动转换

这个很好解释,小学毕业就应该能理解。考虑
a+b+c+d=X
其中X就是checksum,我们把a,b当成源IP地址的两部分,c,d当成目的IP地址的两部分,我们作源地址转换,将a和b都改变,比如a改变成了A,试问将b改成多少才能保持checksum的值X不变,这其实很简单,就是一个简单的一元一次方程求解的问题。IPv6的建议NAT实现也是这个原理,只不过上面的一元一次方程是实数域的,而这个是计算机布尔数域。既然可以不触动第四层的checksum值,那么NAT对第四层协议的影响也就减小了,虽然它还是解决不了诸如ESP/AH等穿越NAT的问题。
        基于以上算法,IPv6在做NAT的时候,在给定的子网网段内,可以自动生成一个新的IP地址供映射之用,从算法本身来看,冲突的可能性非常之小致于0,上述的做法对于IPv4几乎是不可能的,因为IPv4地址空间太小了,每个单位保有的地址池容量也有限,你不能指望一个算法为你生成一个IP地址,因为这种生成的地址要不根本就不属于自己,地址冲突,要么就是重复,和其它的映射冲突。
        既然IPv6的NAT机制“自动”为一个连接选择了一个IP地址,那么当返回包到来的时候,如何来把地址转换回原来的呢?我们知道,IPv6的NAT已经不再使用五元组来维护NAT映射信息,也不在内核维护这种信息,那么“转换回去”这件事就要完全靠算法本身了,恰恰就是算法本身能将转换后的地址再转回原来的,其依据就是本小节最开始处给出的一元一次方程解的唯一性,在IPv6的NAT实现中,算法只针对IP地址中16位的地址信息进行自动生成,而其它的则需要手工显式配置,由于内网IPv6地址可以使用MAC地址映射成唯一的地址,由于一元一次方程解的唯一性,那么转换后的地址也是唯一的,将这一切反过来,最后还是能映射回原始的IP地址的。
        如果抛开地址转换这一说,仅仅考虑算法本身,那还是可以给出一个实际可以运行的代码的,该代码使用了计算checksum的算法:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//以下2个函数就是计算校验码的,具体的原理请参见RFC1071/RFC1624/RFC1141
static inline u_int16_t add16(
    u_int16_t a,
    u_int16_t b)
{
    a += b;
    return a + (a < b);
}

static inline u_int16_t csum16(const u_int16_t *buf, int len)
{
    u_int16_t csum = 0;
    while(len--) csum = add16(csum, *buf++);
    return csum;
}

int main(int argc, char **argv)
{

    u_int16_t buf[18] = {0};
    int i = 0;
    memcpy(buf, "efghhijk", 8);
    memcpy(buf+4, "12345678", 8);
    memcpy(buf+8, "xxyywert", 8);
    memcpy(buf+12, "zxcvkljh", 8);
    //正确做法是打印16进制数据,此处为了简单,打印了字符串
    printf("原始数据:%s  长度:%d\n", (char*)buf, strlen((char*)buf));
    printf("原始数据的校验码:%X\n", csum16(buf, 16));    

    u_int16_t tip[3] = {0};
    memcpy(tip, "#$!%", 4);
    u_int16_t tip_sum = csum16(tip, 2);
    printf("\nNAT规则: efghhijk1234/12 -〉efghhijk#$!%/12\n\n");
    printf("固定从第9个字节开始修改4个字节为:%s 其校验码为:%X\n", (char*)tip, tip_sum);

    //定位固定修改后的动态修改的初始地址,注意,我们仅仅修改16位信息
    u_int16_t* pcsum = buf + 4+2;  

    //计算动态修改的值
    *pcsum = ~add16(
        add16(
            ~(*pcsum),
            ~csum16(buf+4, 2)
        ),
        tip_sum
    );
    printf("动态修改的值为:%X\n", *pcsum);
    memcpy(buf+4, tip, 4); //完成修改

    printf("当前数据:%s  长度:%d\n", buf, strlen((char*)buf));
    printf("当前校验码:%X\n", csum16(buf, 16));
    printf("-------------以下是还原操作-------------\n");
    printf("\n反向NAT规则: efghhijk#$!%/12 -〉efghhijk1234/12\n\n");

    u_int16_t tip2[3] = {0};
        memcpy(tip2, "1234", 4);
    printf("我们只需要记住原始数据被固定修改前的:%s\n", tip2);

    u_int16_t tip_sum2 = csum16(tip2, 2);

    u_int16_t* pcsum2 = buf+6;

    *pcsum2 = ~add16(
        add16(
            ~(*pcsum2),
            ~csum16(buf+4, 2)
        ),
        tip_sum2
    );
    //还原
    memcpy(buf+4, tip2, 4);

    printf("原始数据:%s\n", (char *)buf);
    printf("原始校验码:%X\n", csum16(buf, 16));    

}

运行结果如下:

结果斐然。把以上的原理套用在IPv6的NAT上,就是一种实现。

6.Linux上的MAP66

如果有一个点子,总会有人实现它,何况如果不仅仅是一个点子而是一个标准,那么实现它就更是情理之中了。Linux是一个大熔炉,更是一个实验场,一些草案的最新进展总是会体现了Linux上,IPv6的NAT也不例外。MAP66是一个基本遵循RFC6296建议的Linux实现,编译安装很简单,详见其README,想试一下吗?很简单,和IPv4的iptables一样:
1.配置正向的转换规则,将源地址fdca:ffee:babe::/64网段的地址转换为2008:db8:1::/64网段的地址
ip6tables -t mangle -A POSTROUTING -s fdca:ffee:babe::/64 -o eth2 -j MAP66--src-to 2008:db8:1::/64

可以看出,没有显式指定任何具体地址,类似IPv4的MASQUERADE和IPv4的IP Pool,原理详见第5节。
2.配置反向包的转换规则,将正向包被转换过的地址再转换回去
ip6tables -t mangle -A PREROUTING -d 2008:db8:1::/64 -i eth2 -j MAP66 --dst-to fdca:ffee:babe::/64

可以看出,也没有显式指定任何具体的地址,更值得一提的是,内核并不维护任何关于NAT映射的信息,因此MAP66也不再依赖ip(6)_conntrack。

如果使能上述两条规则,ping一下对端地址,tcpdump抓包的结果如下:

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/ksiwnhiwhs/p/10390569.html

时间: 2024-11-13 18:48:09

IPv6的NAT原理以及MAP66的相关文章

[daily][network] NAT原理(转)

写在转发之前: 一直以来,我一直有一个疑惑,SNAT的时候,如果两个内网主机恰巧使用了相同的源端口号该怎么办呢? 我自己猜测的方法是改掉一个端口号,把端口一起映射(当然还有另一个设想,就是把包同时广播给两个主机,但这会引发安全问题,给黑客留下方便,pass).然后问题来了,如果某一种特定的服务,双方约定了各自的端口号,对端服务会检查源端口又该怎么办呢? 在这篇文章中提及了这个问题,并给出了我解答,他的解答是,这是NAT存在的固有缺陷.所以一个成熟的开发者,要考虑这个世界上好多人都没有公网IP,要

NAT原理与NAT穿越

最近在看东西的时候发现很多网络程序中都需要NAT穿越,特意在此总结一下. 先做一个约定: 内网A中有:A1(192.168.0.8).A2(192.168.0.9)两用户 网关X1(一个NAT设备)有公网IP 1.2.3.4 内网B中有:B1(192.168.1.8).B2(192.168.1.9)两用户, 网关Y1(一个NAT设备)有公网IP 1.2.3.5 公网服务器:C (6.7.8.9) D (6.7.8.10) NAT原理 网络地址转换(NAT,Network Address Tran

NAT原理简介和virtualbox当中的NAT实现

NAT原理简介 NAT英文全称是“Network Address Translation”,中文意思是“网络地址转换”,它是一个IETF(Internet Engineering Task Force, Internet工程任务组)标准,允许一个整体机构以一个公用IP(Internet Protocol)地址出现在Internet上.顾名思义,它是一种把内部私有网络地址(IP地址)翻译成合法网络IP地址的技术.如图: 简单地说,NAT就是在局域网内部网络中使用内部地址,而当内部节点要与外部网络进

网络知识--网络地址转换NAT原理及其作用

1 概述 1.1 简介 NAT英文全称是"Network Address Translation",中文意思是"网络地址转换",它是一个IETF(Internet Engineering Task Force, Internet工程任务组)标准,允许一个整体机构以一个公用IP(Internet Protocol)地址出现在Internet上.顾名思义,它是一种把内部私有网络地址(IP地址)翻译成合法网络IP地址的技术.因此我们可以认为,NAT在一定程度上,能够有效的

VMware NAT原理深度解析总结,可解决一切vmware网络配置问题

问题概述:VMware虚拟机中安装Centos6.6使用vmnet8网卡做NAT模式上网,dhcp正常使用,但是如果使用static IP就会出现无法上网的情况. 先讲一讲NAT的原理:即内网用户通过网络地址转换,由出口设备(一般指路由器)使用网络地址转换,将源地址转换为出口IP地址,代理内网用户访问外网资源:出口设备自身维护一张对应表,当访问返回结果后,再根据对应表送给对应的内网用户,这个过程也称作源地址转换:如果是外网用户,需要访问内网的一台服务器或者主机,可以在出口设备开端口映射,将目的地

UDP穿越NAT原理(p2p)

转载自:http://blog.csdn.net/ldd909/article/details/5979967 论坛上经常有对P2P原理的讨论,但是讨论归讨论,很少有实质的东西产生(源代码).在这里我就用自己实现的一个源代码来说明UDP穿越NAT的原理. 首先先介绍一些基本概念: NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够地址重用.NAT分为两大类,基本的NAT和NAPT(Network

NAT原理

在局域网中,我们是如何通过路由器访问外网的?这里就涉及到了NAT转换. 私网ip指只能在内部网络中使用的ip,公网ip是全球唯一的ip,在私有ip中,分为以下几类: A类:10.0.0.0-10.255.255.255 B类:172.16.0.0-172.31.255.255 C类:192.168.0.0-192.168.255.255 内网机器要访问外网需要进行地址转换,将内网ip转换成外网ip,我们成为NAT转换,NAT转换又分为以下几种: 静态NAT(Static NAT) 动态地址NAT

Linux netfilter 学习笔记 之十一 ip层netfilter的NAT模块初始化以及NAT原理

1.NAT的原理 NAT会修改数据包的ip层的源或者目的ip地址.在实际应用中,NAT 主要用于实现私有网络访问公共网络的功能. 1.1 SNAT 源目的地址转换,即对ip数据包的源ip地址进行转换操作,典型的应用即是网关,网关的lan侧会下挂至少两台设备,而这两台设备的ip地址都是lan侧地址,而lan侧设备又要访问公网,这就需要SNAT大展身手了,通过将lan侧发送的ip数据包的源ip地址转换成公网地址即可以访问公网了. 1.2 DNAT 目的地址转换主要是将ip数据包的目的ip地址进行修改

网络地址转换NAT原理解析

1 概述 1.1 简介 NAT英文全称是“Network Address Translation”,中文意思是“网络地址转换”,它是一个IETF(Internet Engineering Task Force, Internet工程任务组)标准,允许一个整体机构以一个公用IP(Internet Protocol)地址出现在Internet上.顾名思义,它是一种把内部私有网络地址(IP地址)翻译成合法网络IP地址的技术.因此我们可以认为,NAT在一定程度上,能够有效的解决公网地址不足的问题. 1.