关于

树莓派B+是14年买回来的,本来想通过其学习linux,却一直在角落堆灰。这次拿出来一是想配置一下ssh,想搭建一个家庭24*7服务器,不料由于各种原因困难重重。本科计算机网络知识大部分停留在理论阶段,刚好借此机会,通过配置树莓派学习一些远程控制的概念、方法以及涉及的网络知识。

本文主要涉及知识有:NAT,DHCP,DDNS,内网穿透,跨越NAT的P2P打洞等,最终实现在外网连接NAT后的树莓派并用ssh登陆系统。

参考资料

  1. 内网穿透、远程控制、端口映射,八种方法汇总:链接
  2. nat123服务安装教程:链接
  3. 聊聊什么是公网IP 内网穿透 端口映射:链接
  4. ngrok Github Repo:链接
  5. frp Github Repo:链接
  6. 内网穿透工具的原理与开发实战:链接
  7. P2P中的NAT穿越方案:链接

关于远程控制

想要远程控制一台电脑,一个是利用ssh登录电脑,或者用远程桌面登陆。一个是CLI界面,一个是GUI界面。本质上来说,就是需要设计一种协议,在服务端和客户端之间进行通讯,而他们的区别则是通讯协议不同,使用的安全加密手段不同。下面的简介大部分来在Wikipedia介绍页面。

SSH

Secure Shell是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中创建安全隧道来实现SSH客户端与服务器之间的连接。虽然任何网络服务都可以通过SSH实现安全传输,SSH最常见的用途是远程登录系统,人们通常利用SSH来传输命令行界面和远程执行命令。使用频率最高的场合类Unix系统,但是Windows操作系统也能有限度地使用SSH。

远程桌面

有很多公司都设计了远程桌面的软件,使用的通讯手段、加密手段各不相同。这里主要考虑使用下面两种最常用的远程桌面协议。

VNC(Virtual Network Computing),为一种使用RFB协议的显示屏画面分享及远程操作软件。此软件借由网络,可发送键盘与鼠标的动作及即时的显示屏画面。

RDP(Remote Desktop Protocol),是一个多通道(multi-channel)的协议,让用户连上提供微软终端机服务的电脑(服务器端或称“远程电脑”)。服务端电脑方面,则监听送到TCP 3389的数据。

相关的网络知识

理论上,上面所提及的远程控制方法,只需要开相应的端口,然后根据机器在互联网中的IP地址与端口号进行通信即可。然而,由于ISP无法保证为每一个宽带用户提供全球唯一的公网IPv4地址,所以这又涉及到很多其他的网络知识,在这一部分详细描述。

NAT 网络地址转换

在本科计算机网络课程中,已经详细讨论过该技术。NAT网络地址转换主要是为了解决IPv4地址短缺用于保留IP地址的一种手段。其思路也非常简单。利用路由器作为内网和公网的划分,将内网与外网进行映射,并负责这两者的信息传递。映射方法有很多种,包括基本网络地址转换与网络地址端口转换(NAPT)。现在常用的是后面的一种,如下图所示:

穿越NAT来见你-树莓派远程控制-编程知识网

路由器负责将内网的IP与端口号映射到公网的IP与端口号,并以该IP与端口号与外网进行通讯,并作为中间桥梁控制其间的数据传输。那么路由器怎么分配内网IP,以及ISP如何分配一个IPv4地址?利用的便是DHCP协议,下一小节描述。

DHCP 动态主机设置协议

在本科计算机网络课程中,DHCP也同样被详细讨论过。DHCP是一个局域网的网络协议,使用UDP协议工作,主要用于内部网络或网络服务供应商自动分配IP地址给用户,同时也可以作为内部网络管理员作为对所有电脑作中央管理的手段。

其原理其实很简单,通过广播、协议标识号,经过DHCP发现,提供,请求,确认的流程给一个新链接入网络的设备分配IP。

所以,目前为止,我们知道路由器内网的IP并不是公网可以访问的IPv4地址,甚至路由器的wan口接着的也是运营商提供的私网IP(可以通过查路由器设置与访问外网的IP进行对比可知)。下面讨论如何在这种情况下将内网的服务暴露到公网上:

  1. 先讨论的第一种情况是如果ISP比较良心,给了公网IP,那么将内网的端口暴露到公网就比较简单了。直接在路由器上设置一下端口映射,将内网IP与端口映射到公网IP的一个端口上。当外界需要访问内网端口的服务时,只需要向公网IP对应的端口发起请求即可。
  2. 第二种情况是,ISP虽然不给静态IP,但是给的动态IP是公网IP,而不是自己内网的IP。这种情况下依然可以做端口映射,但是由于IP地址不固定,所以需要通过方法来告知连接者IP到底是多少。解决这个问题最暴力的一种随时监听IP并发送邮件/信息来告知连接者真实IP。另外一种则是DDNS技术,这种技术比较简单,不单独做一小节描述,该技术就是首先获得一个域名,并要求内网设备每隔一段时间对于DDNS服务器发起请求,DNS服务器将请求的IP记录下来并且刷新相关域名的解析记录。最终可以通过该域名找到当前的IP地址。
  3. 最后一种情况就比较糟糕了,家庭路由器上面一层连接的是ISP的另一层路由器,甚至有层层链接。这种情况下,在自己的路由器上设置映射是没有作用的。这种时候就需要内网穿透的技术了。该技术在下一小节描述。

内网穿透

内网穿透的技术说起来也不是很难理解,对于在NAT之后的节点来说,其不是能主动访问公网端口,而是不能反过来有效的被公网访问。内网穿透的主要思路就是利用这一点,让在NAT之后的节点主动访问一个拥有公网IP地址的服务器,并由中间服务器搭桥,打通经过该服务器从其他主机到NAT之后节点的隧道。

已经停止更新的ngrok便是完成这样工作的开源项目,下面便是ngrok说明文档里面的配图。

穿越NAT来见你-树莓派远程控制-编程知识网

”I want to expose a local server behind a NAT or firewall to the internet.”

利用参考文献6的例子详细解释内网穿透的原理:

假设拥有公网IP的中间服务器的IPv4地址为23.23.23.23,NAT之后节点的IP为192.168.1.2。现在需要将该NAT之后节点的80HTTP服务器暴露出去。在正式提供内网穿透之前,需要完成以下两点准备工作:

  • 首先按照如下参数配置中间服务器:公网主机先监听80端口,同时其他任意一个端口,监听这个端口是用于让内网服务器主动连接进来打通一个隧道。
  • 接着内网再主动向公网主机的指定端口发起一个请求,这样内网就成功与公网主机建立了一个连接通道。

准备工作结束后,就可以利用中间服务器进行内网穿透了:

  1. 客户端主动连接公网的80端口,即23.23.23.23:80
  2. 公网接收到连接请求之后,将请求通过先前建立好的隧道转发到内网主机
  3. 内网主机接收到来自隧道的数据包后,再连接内网主机自身的80端口
  4. 连接成功之后将数据包原封不动地转发数据包给80端口
  5. 待HTTP服务器程序处理完这个数据包,生成了响应报文之后再转发到隧道端口
  6. 隧道端口将响应报文发送给中间公网服务器
  7. 中间服务器将该报文转发到公网的80端口
  8. 然后返回给最开始请求公网服务器80端口的客户端

同样该技术除了可以访问隐藏在NAT之后的节点,同样可以穿透防火墙。由于防火墙只拦截了入站没有拦截出站,所以可以让防火墙内的服务器主动连接到一个公网服务器打通隧道,并通过该隧道最终链接到本地的其他端口。

总的来说,内网穿透技术可以适用于所有能够连通公网的机器,提供了一个通用的打通内网的方式。

国内提供这种服务器的有花生壳和nat123。

然而! 这样很明显的问题是,对于每一次内容的传输,都需要服务器做代理!!!这对于服务器流量与传输延迟都是非常非常不理想的。能否将服务器只当一个握手工具,当两边接上头了后直接P2P做全端口映射?

穿越NAT来见你

新华三有一篇技术博客专门分享穿越NAT的P2P的方法,见参考文献7。这里主要讲一下穿越NAT的P2P端口映射的思路。用H3C讲述此技术的一张图,描述非同一网段,两端均在NAT后的P2P技术:

穿越NAT来见你-树莓派远程控制-编程知识网

客户端A,B均在NAT之后,现在需要他们两P2P通讯。

  1. 客户端A,B均向服务器发送连接请求,并带上自己的内网地址。
  2. 服务器获得<内网地址:端口,外网地址:端口>二元组,并分别将A,B的二元组发给B,A
  3. A,B分别尝试向内网地址与端口,外网地址与端口发送UDP包。当A发送的数据包已经经过NAT,并记录了相应的表项,且B发送的数据包同样也通过了NAT,记录了相应的表项,UDP数据包就可以正确的被接受与翻译。此时便可等效的为对方发送UDP数据包了。这个过程就是打洞过程。
  4. 一旦应用程序确认已经可以通过往对方的外网地址发送数据包的方式让数据包到达NAT后面的目的应用程序,程序会自动停止继续发送用于“打洞”的数据包,转而开始真正的P2P数据传输。

国内提供这个服务的还是花生壳和nat123,由于p2p连通之后也就没他们什么事了,所以一般这个服务都是不怎么要钱的。

实际上手,利用ssh登陆树莓派

基本思路

首先,ssh端口会默认占用22端口,如果树莓派拥有一个外网IP,那么开启ssh服务后,直接访问该IP22端口,即可利用ssh登陆树莓派。但是我们家的网是刚才讨论的第三种情况,需要利用内网穿透技术。下面小节使用的nat123提供的服务。

Step 1 路由器静态分配内网IP

不仅仅外部ISP是动态分配IP的,路由器的内部同样也是动态分配IP的,然而为了不用每次都到路由器查询设备分配的IP,可以设置路由器DHCP静态IP分配,保证树莓配在该内网上分配的IP是固定的。(根据MAC地址来确定的)。如在小米路由器中,设置DHCP静态IP分配设置如下:

穿越NAT来见你-树莓派远程控制-编程知识网

Step 2 局域网内部直连

先通过局域网对刚才配置的IP进行测试。树莓派中安装的ssh服务器的配置文件没有修改,就使用的默认的22端口,且刚才在路由器做了内网DHCP静态IP分配为192.168.31.216,故通过局域网ssh到树莓派的地址是:192.168.31.216:22

穿越NAT来见你-树莓派远程控制-编程知识网

可以直接通过同一网段的电脑连接上局域网地址的树莓派。

Step 3 内网穿透 nat123

由于国家规定要实名制,刚好网站想捞一笔,需要支付宝支付实名认证。为了实验乖乖掏出8块钱充了服务币后准备开始配置。有VPS的孩子可以利用参考文献4,5的那两个开源软件自己搭建内网穿透服务器。

首先根据官方文档安装nat123的客户端并开启,这对应内网打穿的NAT内节点连接服务器的步骤。这时服务器分配的端口是随机分配的。

穿越NAT来见你-树莓派远程控制-编程知识网

然后登陆nat123进行端口映射设置:

穿越NAT来见你-树莓派远程控制-编程知识网

而后直接通过该外网域名与端口连接ssh服务即可:

在macOS的终端上登陆

穿越NAT来见你-树莓派远程控制-编程知识网

在iOS上使用Termius登陆SSH

穿越NAT来见你-树莓派远程控制-编程知识网

VNC远程桌面

当手边没有显示器时,利用VNC远程桌面连接树莓派现实图形界面是一个不错的选择。就是考虑到继续用内网穿透技术来远程访问速度会非常慢,故这里只测试局域网同一网段下的连接。

在树莓派上安装VNCserver,并运行,即可通过局域网与VNC的端口来连接远程桌面:

macOS端 VNC Viwer

穿越NAT来见你-树莓派远程控制-编程知识网