给树莓派分配一个域名

ping一些网站的时候发现,同一域名可以解析到多个IP地址。
因此想给树莓派分配一个域名,当我在校园网环境访问时解析到校园网IP,直接访问树莓派;当我在其它网络环境访问时解析到阿里云服务器,通过阿里云上的内网穿透服务去访问树莓派。
注:CloudXNS将于2019年7月16日0时起,停止免费客户的服务,仅保留24000元/年的VIP服务。

前提:校园网环境

在寝室里电脑连接有线网会分配到一个公网IP地址,虽然在校园网范围之外无法访问,但是在校园网内的其它设备都可以根据这个IP地址访问电脑上的服务,这个IP也不会经常变化。

第一次尝试:DNS轮询

简单地在自己域名的DNS解析设置里给一个二级域名添加了两条A记录,一条是校园网分配到的IP,另一条是阿里云服务器的IP。在校园网环境下多次尝试后发现,浏览器请求的IP是随机的,并不会始终去访问当前最近的校园网IP。

以“一个域名 多个ip”为关键字进行搜索,发现在V2EX的这个帖子里提到了“DNS 轮询”机制,上面的尝试就属于DNS轮询,维基百科上对其有简单的介绍:Round-robin DNS

大致含义:给一个域名指定多个记录时,DNS查询的结果会是多个记录值,它们的相对顺序是轮换的。如图:

round-robin

而浏览器选择IP地址的规则并没有标准,可能会直接选第一个,连接超时了再换下一个,也可能会对其重新排序,选择最近的地址。因此DNS轮询并不能满足我的要求,继续寻找其它方法。

第二次尝试:页面跳转

DNS轮询不行的话,那么可不可以在访问到的页面上再进行一次跳转?跳转方法想了下面几种:

可是以上几种方法都需要在自己的服务器上创建单独的跳转页面,远不如DNS直接解析到不同的IP地址优雅,于是再次寻找DNS解析相关的内容。

第三次尝试:DNS智能解析

搜索之后,又找到了“DNS智能解析”这一方法,即利用EDNS协议,根据来源IP返回不同的解析结果,阿里云腾讯云都支持智能解析,也都有自己的收费标准。免费且可以自定义线路的最终只找到了CloudXNS

感觉这名字有点熟悉,好像之前出过什么问题。到网上一查,果然,刚开始时CloudXNS不需要实名认证,被强制要求实名制之后,只通过微信通知了一下用户,然后就立即停止了域名解析服务,导致一大批用户的域名解析出现故障,自己提供的实名认证通道还出现了各种问题。

但是免费且可以自定义线路的只找到这一家,实名认证要求上传身份证正反面和手持身份证照片,有点恶心。找了一段时间没找到其它合适的DNS服务商之后就只能尝试CloudXNS了。

添加完域名解析,按校园网IP地址范围设置私有线路后,发现校园网的无线网还有问题,虽然的确在校园网IP范围内,但总是解析不到树莓派的校园网IP,只能获取到阿里云服务器的IP。

查找CloudXNS文档,发现如何配置私有线路文档中明确说明私有线路需要填写的IP段是DNS出口IP,而不是访问者的IP地址所处公网IP段。

根据其提供的本地DNS优化诊断工具进行查询,发现校园网无线网络走的是移动,检测到的DNS也是移动的DNS,按如何收集本地DNS出口IP的说明使用whois命令查询移动DNS所属IP段,填写到私有线路中,终于成功解析。
(搜索过程中发现了网易DNS检测工具,比CloudXNS提供的工具速度快很多)

树莓派与服务器:frp内网穿透

使用frp进行内网穿透,在阿里云服务器下载linux_amd64版本release,树莓派下载linux_arm64版本release(我的树莓派上运行的Arch Linux ARM aarch64),配置树莓派22端口穿透到阿里云8022,80到8080,443到8443。

使用certbot申请ssl证书,注意选择手动配置,这样可以通过在DNS设置里给域名增加TXT类型的记录进行验证:
sudo certbot certonly --manual --preferred-challenges dns
手动部署完证书后在校园网环境下就可以通过http://whoisnian.xyz或者https://whoisnian.xyz访问树莓派了。

服务器上此时应该可以通过http://whoisnian.xyz:8080或者https://whoisnian.xyz:8443进行访问。但由于未备案,http请求都被拦截,访问时强制显示未备案提醒页面。很久之前是可以在443端口使用https访问绕过备案的,这正是我申请ssl证书的原因。

apache设置443端口反向代理8443,但是在本地浏览器里输入https://whoisnian.xyz却仍然无法访问,提示连接被重置,从本地curl提示SSL_ERROR_SYSCALL。怀疑是反向代理配置有问题,调整了半天,没有任何效果。
同样的配置,试着换了一个端口,用8444去反向代理8443,https://whoisnian.xyz:8444可以成功访问,因此怀疑是阿里云对443端口也做出了检测。

打开Wireshark,监听无线网卡,抓包:

wireshark_ali_443

3和4是从本地发出DNS查询并得到结果的过程,5、6、7三条根据SYN和ACK标志可知是TCP连接建立时的三次握手,8是本地向服务器发出TLS握手信号。9和11就很奇怪了,服务器发出了RST信号要重置TCP连接。重新打开Wireshark,随便访问一个https网站,观察其TLS握手过程,服务器正常收到Client Hello后应该回复TCP或TLS包的,这个RST很有可能是阿里云检测到443端口上的TLS握手过程时发出的,强制中断了TCP连接。

用443绕过备案行不通,那就只能指定端口了。为了在浏览器输入同一地址可以自动根据DNS解析结果访问树莓派或者用来做内网穿透的阿里云,我在树莓派上也打开了8443端口,之后只需要访问https://whoisnian.xyz:8443即可。

最终效果

whoisnian.xyz域名通过CloudXNS的私有线路进行智能解析,将校园网来源的请求解析到树莓派校园网IP上,将其它来源的请求解析到阿里云服务器上,树莓派利用frp进行内网穿透,阿里云使用其它端口的TLS访问绕过备案,使得不同来源请求的访问效果相同。