以下内容转载自为什么我在公司里访问不了家里的电脑?,整理部分格式

概要

  • 需要解决的问题:内网如何访问外网外网如何访问内网

  • 方案:NAT (Network Address Translation)内网穿透

NAT

概述

  • 类型,简单介绍,以后用到其他了再研究

  • 假设,家里分配的公网IP20.20.20.20,家里电脑分配的内网IP192.168.30.5,将要访问的公网IP30.30.30.30,如下图

  • 分为私有IP发送数据私有IP接受数据两个部分,分别使用SNATDNAT

SNAT-发送

  • 准备发送数据包的时候,电脑内核协议栈就会构造一个IP数据包

  • IP数据包报头里的发送端IP地址填的就是192.168.30.5接收端IP地址就是30.30.30.30。将数据包发到NAT路由器中

  • 此时NAT路由器会将IP数据包里的源IP地址修改一下,私有IP地址192.168.30.5改写为公网IP地址20.20.20.20,即SNAT (Source Network Address Translation),源地址转换

  • 并且还会在NAT路由器内部留下一条 192.168.30.5 -> 20.20.20.20的映射记录,这个信息会在后面用到

  • 之后IP数据包经过公网里各个路由器的转发,发到了接收端30.30.30.30,到这里发送流程结束

DNAT-接收

  • 如果接收端处理完数据了,需要发一个响应给你的电脑,那就需要将发送端IP地址填上自己的30.30.30.30,将接收端地址填为你的公网IP地址20.20.20.20,发往NAT路由器
  • NAT路由器收到公网来的消息之后,会检查下自己之前留下的映射信息,发现之前留下了这么一条 192.168.30.5 -> 20.20.20.20记录,就会将这个数据包的目的IP地址修改一下,变成内网IP地址192.168.30.5, 这也叫DNATDestination Network Address Translation,目的地址转换)
  • 之后将其转发给你的电脑上

总结

  • 通过SNATDNAT可以实现内网访问外网资源
  • 疑问
    • 如果有多台设备,NAT路由器改如何填表?=>NAPT
    • 外网如何访问内网?=>内网穿透

NAPT

概述

  • NAPT:Network Address Port Transfer , 即网络地址端口转换
  • 有传输层TCP/UDP时:采用IP + 端口形式
  • 无传输层TCP/UDP时,如ping使用ICMP:采用IP + 标识符形式
    • ping报文头里有个Identifier的信息,它其实指的是放出ping命令的进程id
  • 假设,发送端IP地址填的就是192.168.30.5,发送端口是5000接收端IP地址就是30.30.30.30,接收端口是3000

发送

  • NAT路由器会将IP数据包里的IP地址和端口号修改一下,从192.168.30.5:5000改写成20.20.20.20:6000端口号的映射是随机的
  • 并且还会在NAT路由器内部留下一条 192.168.30.5:5000 -> 20.20.20.20:6000的映射记录
  • 之后数据包经过公网里各个路由器的转发,发到了接收端30.30.30.30:3000,到这里发送流程结束

接收

  • 接收端响应时,就会在数据包里填入发送端地址是30.30.30.30:3000,将接收端20.20.20.20:6000,发往NAT路由器
  • NAT路由器发现下自己之前留下过这么一条 192.168.30.5:5000 -> 20.20.20.20:6000的记录,就会将这个数据包的目的IP地址和端口修改一下,变回原来的192.168.30.5:5000
  • 之后将其转发给你的电脑上

内网穿透

  • 使用了NAT上网的话,前提得内网机器主动请求公网IP,这样NAT才能将内网的IP端口转成外网**IP端口**

  • 反过来公网的机器想主动请求内网机器,就会被拦在NAT路由器上,此时由于NAT路由器并没有任何相关的IP端口的映射记录,因此也就不会转发数据给内网里的任何一台机器

  • 解决:通过再加一层实现,即在公网上加一台服务器x,并暴露一个访问域名,再让内网的服务主动连接服务器x,这样NAT路由器上就有对应的映射关系。接着,所有人都去访问服务器x,服务器x将数据转发给内网机器,再原路返回响应,这样数据就都通了。这就是所谓的内网穿透

  • 内网穿透步骤,可查看内网穿透

不同内网通讯

通过服务器建立连接

  • 两个内网的QQ是如何通讯的?
  • 两个在内网的客户端登录QQ时都会主动向公网的聊天服务器建立连接,这时两方的NAT路由器中都会记录有相应的映射关系
  • 当在其中一个QQ上发送消息时,数据会先到服务器,再通过服务器转发到另外一个客户端上。反过来也一样,通过这个方式让两台内网的机子进行数据传输

直连 (P2P)

  • 假设A和B两个局域网内的机子,A内网对应的NAT设备叫NAT_A,B内网里的NAT设备叫NAT_B,和一个第三方服务器server

  • 流程

    • step1和2: A主动去连server,此时A对应的NAT_A就会留下A的内网地址和外网地址的映射关系,server也拿到了A对应的外网IP地址和端口

    • step3和4: B的操作和A一样,主动连第三方server,NAT_B内留下B的内网地址和外网地址的映射关系,然后server也拿到了B对应的外网IP地址和端口

    • step5和step6以及step7: 此时server发消息给A,让A主动发UDP消息到B的外网IP地址和端口。此时NAT_B收到这个A的UDP数据包时,这时候根据NAT_B的设置不同,导致这时候有可能NAT_B能直接转发数据到B,那此时A和B就通了。但也有可能不通,直接丢包,不过丢包没关系,这个操作的目的是给NAT_A上留下有关B的映射关系

    • step8和step9以及step10: 跟step5一样熟悉的配方,此时server再发消息给B,让B主动发UDP消息到A的外网IP地址和端口。NAT_B上也留下了关于A到映射关系,这时候由于之前NAT_A上有过关于B的映射关系,此时NAT_A就能正常接受B的数据包,并将其转发给A。到这里A和B就能正常进行数据通信了。这就是所谓的NAT打洞

    • step11: 注意,之前我们都是用的UDP数据包,目的只是为了在两个局域网的NAT上打个洞出来,实际上大部分应用用的都是TCP连接,所以,这时候我们还需要在A主动向B发起TCP连接。到此,我们就完成了两端之间的通信