内网穿透
Published:
内网穿透的解决方式一般有两种:
- 借助有公网IP的服务器当跳板,客户端与内网的服务器进行连接
- 借助有公网IP的服务器,将客户端和内网服务器打洞,之后客户端与内网服务器直接通信 一般来说,遇到的问题主要和防火墙有关,可以参考如何解决防火墙的问题。
对于Easy防火墙(只要有出包,不管入包是哪里发来的,都可以进),通常打洞比较简单;
对于Hard防火墙(入包必须是出包目的地对应的ip,其它ip进不来),一般需要借助公网IP服务器当跳板了
这篇文章记录的解决方案有两种:
FRP
这个方案部署起来比较简单,参考相关教程,把FRP server部署在有公网IP的服务器上,把FRP client部署在内网的机器上,即可将公网IP对应端口映射到内网机器的对应端口上。 但是这个方案存在问题是FRP流量容易被校园网防火墙查封,服务很容易挂掉,详见:
目前没有很好的解决方案
Tailscale
这个方案直接部署更简单,按照官网指引把每个设备下载一下tailscale即可互联了,而且不会被校园网防火墙查封。但是默认官方的公共服务器都在境外(最近的是香港),如果打洞不成功的话走官方跳板服务器通信延迟都是100ms起步。
优化方法是自建中继服务器,tailscale使用的中继服务器叫DERP,我们在自己的国内云服务器上部署私有的DERP服务器做跳板可大大降低访问时延。
自建DERP服务器部署方法可以参考:
- https://icloudnative.io/posts/custom-derp-servers/
- 自建derp中继节点
- https://tailscale.com/kb/1118/custom-derp-servers#run-a-derp-server-from-source
值得注意的是,由于DERP服务器只能用ssl通信,当你的域名没有备案时,云服务厂商可能会查封相应的端口,导致客户端连接DERP服务器超时,报错类似这样:
http: TLS handshake erro from (客户端ip+端口): write tcp (服务器ip+端口)->(客户端ip+端口): write: connection reset by peer
流量会被墙,握手都一直失败
这种情况建议DERP服务器使用纯IP,我参考了这个docker镜像部署: https://hub.docker.com/r/yangchuansheng/ip_derper
使用如下命令即可:
sudo docker run --restart always
--name derper_ip -p 443:443 (https端口)
-p 3478:3478/udp
-v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
-e DERP_ADDR=:443
--net host
-d yangchuansheng/ip_derper
值得注意的是,记得在云服务器控制台放行对应的 https端口,3478端口,41641端口(用来打洞的,不放行这个端口无法打洞)
然后在tailscale网站上修改控制规则,在Access Controls里添加规则如下:
"derpMap": {
// OmitDefaultRegions true的话就忽略官方给的服务器,只用自己私有的
"OmitDefaultRegions": false,
"Regions": {
"901": {
"RegionID": 901, // 901 三个地方保持一致,900开始,多个节点可以往后+1
"RegionCode": "GZ",
"RegionName": "GuangZhou",
"Nodes": [
{
"Name": "Aliyun_GuangZhou_1",
"RegionID": 901,
"HostName": "ip", //域名没备案前只能用纯ip
"IPv4": "ip",
"StunOnly": false,
"DERPPort": https端口,
"InsecureForTests": true,
},
],
},
},
},
部署完后基本就OK了,如果想自己搭建控制服务器还可以部署一个headscale,可以参考https://icloudnative.io/posts/how-to-set-up-or-migrate-headscale
完成后测试输入命令:
tailscale netcheck
tailscale ping xxx(你内网的机器)
看到你部署的DERP服务器后,再ping一下内网机器看看能否ping通过,走的是不是自建的节点。