您好,登錄后才能下訂單哦!
IPv6的NAT原理是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
在億萬互聯網用戶享受著Internet帶來便利的同時,IPv4地址即將耗盡的問題卻早在20年前就被網絡專家們意識到了,并采取了措施延緩IPv4的消耗,這項措施就是NAT(網絡地址轉換)技術。NAT主要作用在于節約IP地址,而非所謂的增加IP的方向性以及隱藏私有IP,且IPv4的NAT打破了互聯網本身的“互聯”特性,使得一部分IP地址不再雙向可達,NAT為無方向的IP協議增加了一個方向,特別是stateful的NAT類型。此時,IPv6時代已逐漸到來。
而IPv6的標準中不建議使用NAT,這是何緣由呢?我們已知IPv6地址數量巨大,只要在地球上,都可為螞蟻配置IP設備,因此IPv4的一些修補手段將不再需要,為了保持協議本身以及相關標準的純潔性,在IPv6中幾乎不再建議使用NAT。雖然不再建議使用,但在某些必要情況下,還是可能需要實現IPv6的NAT。在RFC6296的標題是IPv6-to-IPv6 Network Prefix Translation中,描述了IPv6下的NAT的實現要點,給出了一個合理的建議,既保持了IP的無方向性,又可以滿足NAT的語義,這就是IPv6之NAT stateless的緣由。
IPv6地址有將近128個可隨意調配的位,其龐大的地址空間,一般的單位都會被分配到一個擁有很大量地址的網段,此網段擁有足夠多的地址來和內網主機進行映射,即可用于映射的IP地址池容量巨大,且既然不想再使用非IP層的信息來保持信息,又要保持映射,那就要用純IP層的信息,這樣對上層影響最小。對于IPv6而言,NAT利用checksum算法來保持流標識信息,絲毫不管這個checksum是誰的checksum,因為它根本就不改變數據包的checksum...
接下來給大家講解一下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。
既然IPv6的NAT機制“自動”為一個連接選擇了一個IP地址,那么當返回包到來的時候,如何把地址轉換為原地址呢?IPv6的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上,就是一種實現。
關于IPv6的NAT原理是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。