学习NAT协议,在家中架设服务器

背景

好久没写博客了,也许是因为前段时间大作业写的报告内容太多,有点厌倦了,坚持果然是件难事。

寒假放假在家想和朋友联机玩《Minecraft》,但苦于没有服务器可以用,于是便尝试自己开一个私服。因为学过计算机网络的知识,我知道自己的PC在路由器LAN口的内网下,于是便考虑了很多种方法来使自己能被公网的其他用户发现。顺便还研究了一下组网的原理。

理论部分

NAT协议

全称Network Address Translation。

众所周知,IPv4地址由32bit组成,也就是说,IPv4最多能给2^32次方个设备提供逻辑地址,这其中还不包括事先约定好的主机环回地址127.0.0.1,私有地址、广播地址等等,所以目前IPv4地址已经枯竭,目前我们所用的个人上网设备大都没有真正意义的公网地址。为了解决IPv4地址枯竭的问题,NAT协议被提出。

没有特别说明,本文的IP都指IPv4地址

私有地址(私有IP)

国际上为IP又划分了三个地址段,用于局域网内为设备分配IP地址。也就是说,公网下存在若干的局域网,每个局域网的网关LAN口下就可以使用这些私有地址,私有地址在局域网内不可以重复,但是在公网的不同局域网中可以重复。

NAT示意图

RFC1918定义了私有IP地址范围:

A: 10.0.0.0~10.255.255.255 即10.0.0.0/8

B:172.16.0.0~172.31.255.255即172.16.0.0/12

C:192.168.0.0~192.168.255.255 即192.168.0.0/16

NAT协议的工作原理

如上图所示,使用私有地址后,个人的上网设备不需要时时刻刻占用公网IP也可以上网。例如,路由器获得了3个公网IP(X1,X2,X3),局域网内有5台上网设备,当某台设备(私有地址为A1)需要上网时,路由器就会从地址池中选择一个公网地址(X2),建立一个二元组(A1,X2)在映射表中,此后从A1地址发出来的数据报都会利用路由器转化后以X2地址的身份发出,同样,路由器收到发给X2的数据报时都会转发给A1,这样这台设备就可以正常上网。

但是这样有个问题,就是如果这个局域网的5台设备都要上网时,公网IP不够的问题还是没有被解决。于是,更节省的**NAPT(Network Address Port Translation)**就被提出。现今用的大部分NAT协议,其实就是NAPT协议,只是习惯上仍归类为NAT。

NAPT协议的工作原理

NAT协议是建立起一个从私网IP到公网IP的映射,而NAPT如其名,将端口也进行了映射。当路由器收到一个从内网设备A1端口P1发出的数据报时,路由器会建立一个四元组(A1,P1,X1,P1’),其中X1为路由器的公网地址,P1‘为路由器未使用的端口号。这样,只要从(A1,P1)端口发出的数据报都会由路由器的(X1,P1’),发向外网,反之亦然,于是A1就可以上网。由于一台上网设备可能需要使用多个端口,所以NAPT需要维护的映射表数量较大,但这有个好处,就是路由器只需要被分配一个公网IP可以令其局域网内的设备都可以上网,大大节省了IP资源。

NAPT示意图

由于涉及到修改端口号,所以NAPT必须与更高层的协议如TCP配合,否则上层数据会出现问题,比如说修改端口号时,TCP头部校验和不对,需要由路由器修改。在一定程度上说,我认为NAPT协议破坏了OSI七层模型层间的独立性。

映射的分类

NA(P)T协议的映射方案分许两种种,其中包括对称型NAT,锥形NAT;锥形NAT又可以分为完全锥形、IP限制锥形、端口限制锥形。以上提到的完全锥形NAT、IP限制型NAT,端口限制型NAT,对称型NAT,映射要求逐次变严格。具体的可以看文章底部的B站链接。

“大内网”

实际上,我国的运营商(专业上叫服务提供商ISP)为了更大程度地借阅公网IP资源,采用了”大内网“的策略,说白了就是套娃。将你的网关(路由器、光猫)再置于一个”大内网”,也就是说,看似你可以正常上网,但是你压根就没有属于自己的公网IP。

实践部分

NAT协议确实节省了IP地址资源,但是这也带来一个问题,就是现在的个人网络设备都没有公网IP,这就意味着个人设备无法直接被其他外网用户主动访问(虽然确实起到一定防火墙作用)。为了能够被其他公网用户访问,需要用一种叫做**端口映射(端口转发)**的技术。

端口映射

因为内网中的设备被网关所隐蔽,所以外网用户无法直接访问内网设备,但是我们可以事先在网关上维护好映射表,让外网发往路由器P2端口的数据报都被转发到A1的P1端口,这样就可以让内网设备的某个应用向外网提供服务了。

请注意,我在这段文字中的都说的是“外网”而非“公网”,因为正如上文所说,大部分人都处于“大内网“下,也就是说数据报还要经过ISP的网关才能到达家中的网关。而普通人是没有ISP的网关的配置权限的,这就意味着简单的端口映射是行不通的。就算可以配置ISP网关,经过两层端口映射后延迟也会变得难以接受。

天无绝人之路

但是,我们是可以通过联系ISP客服来获得公网IP的,给家中网关分配公网IP后,我们的数据报就不需要进过运营商的网关了。但是,配置好我的路由器后,我发现还是不能上网,检查后发现我仍然不是用公网IP上网的,经过检查我家网络的拓扑结构后,我发现我家网络的拓扑结构如下图:

myhouse1

由于我家的宽带拨号是在光猫上完成的,所以获得公网IP的实际上是我的光猫,而光猫下面一共连接了4个路由器,只设置一层的端口映射是不够的。经过思考后我想出来下面几种解决办法:

1.在光猫上也设置一个端口映射,但是两层的端口映射可能会让延迟打折扣,所以这个方案不适合作为首选。

2.将光猫配置为桥接模式。这种情况下光猫只负责光电信号的转化,拨号由路由器完成,于是路由器就可以获得公网IP。但是宽带拨号只能在一个设备上完成,我的路由器A拨号后,其他三台就无法联网。当然,可以配置其他三台路由器为有线中继或无线中继模式来实现上网,但这样会让路由器A负担过大,并且网络健壮性会下降。同时这种方案会让网络维护难度增大,一是光猫变桥接后,如果网络出问题ISP无法远程配置我家的光猫,需要安排师傅上门,二是我维护网络时需要同时配置四台路由器,过于麻烦。

3.直接将我所用的路由器A设置为中继,中继光猫的信号,这样,我家的网络拓扑结构可以逻辑上表示为下图:

这种方式下,路由器只是作为一个信号中继器的作用,实际上的数据报都由光猫处理。我只需要在光猫上配置端口映射,就可以实现向公网提供服务了!

为了配置光猫信息,需要获得光猫的超级管理员密码,这需要一定手段。并且运营商为了防止用户私自搭设服务器,(似乎)将光猫的80、8080等常用端口都封了,如果想要架设WEB服务器可能需要另外的端口。

image-20221226155500696

化动为静

内网-DHCP

为了免去因为DHCP租约到期后要重新配置端口映射的麻烦,需要在PC上将DHCP关闭,手动为其设置一个私有IP。

公网-dDNS

个人用户获得的公网IP是动态变化的,只要重启一次光猫就会改变(即使不手动重启,运营商也会隔段时间重启一次),这就给我们带来很大的不便利——每次要访问我们的主机时,都要确定一下公网IP是否改变。为了解决这一问题,可以使用dDNS(Dynamic Domain Name Server),使用域名动态解析我们的公网IP,也就是当我们公网IP改变时,会更改DNS解析的内容,我这里使用花生壳(电信网关只支持花生壳)。

扩展

还有STUN、TURN等方法可以达到内网穿透的效果,其中STUN是通过服务器获取自己的公网IP和端口号,从而自行与公网上的目标建立连接;而TURN是通过一个中间的服务器来交换数据报,知名的樱花内网穿透就是利用这个原理来完成通信的。

结语

最后就是用这个办法与好基友成功联机,延迟比使用内网穿透降低了不少,几乎感受不到延迟。想到Minecraft开服我就回忆起初中那段玩MC的时光,当时没有钱,也没有支付宝、微信支付这种手段,只能和朋友买Q币卡,然后上淘宝用Q币卡租服务器。当时对计算机知识了解得太少了,被各种配置搞的晕头转向的,不过想想许多计算机知识或许都是MC带给我的。

参考地址

知乎:NAT协议是怎样工作的

BiliBili:B站最详细内网穿透原理,看了包懂,全是干货!

阿里云:STUN, TURN, ICE介绍


学习NAT协议,在家中架设服务器
http://zhouhf.top/2022/12/26/学习NAT协议,在家中架设服务器/
作者
周洪锋
发布于
2022年12月26日
许可协议