使用Cloudflare Tunnel转发任意端口
date
Dec 10, 2023
slug
use-cloudflared-tunnel-proxy-any-port
status
Published
tags
Tech
Devops
Cloudflare
summary
实现在只有IPV4单栈网络环境访问家里IPV6单栈服务器,无需自备中转服务器
type
Post
背景
我的家里使用的是移动宽带,由于众所周知(IP不够)的原因移动只给IPV6,并且没有申请IPV4的可能性,但是我在家里的Exsi server上部署了很多的服务,例如NAS,相册,电影点播服务,以及开发用的一些环境(ssh/mysql/mq)
首先如果访问者也有IPV6那就不用说了,DDNS解析一个域名直接连接就可以了。
问题
那如果我们的访问者只有IPV4呢?我们如何实现在只有IPV4的网络环境访问家里的服务器呢?
网上一搜就有一大把的ugly方案,例如ngrok,frp,zerotier,这些方案我都曾经尝试过,在我看来一点都不完美。
我的方案是基于Cloudflare 提供的Zerotrust,Cloudflare Tunnel 通过在本地网络运行的一个 Cloudflare 守护程序,与 Cloudflare 云端通信,将云端请求数据转发到本地网络的 IP + 端口。
前置条件
- 拥有一个域名
- 将域名 DNS 解析托管到 CF
- 内网有一台服务器(也可以是PC or 路由器),用于运行本地与 cloudflare 通信的 cloudflared 程序
- 一张境内双币信用卡(仅需要添加付款方式,服务是免费的,free tier足够大部分人使用)
Web服务
如果我们是需要暴露一个HTTP服务出来,那么很简单,这种教程网上太多了。
- 打开 Cloudflare Zero Trust 工作台面板
- 创建 Cloudflare Zero Trust ,选择免费计划。需要提供付款方式,使用境内的双币卡即可
- 完成后,在 Access Tunnels 中,创建一个 Tunnel。
- 选择 Cloudflared 部署方式。
- Tunnel 需要通过 Cloudflared 来建立云端与本地网络的通道,这里推荐选择 Docker 部署Cloudflared 守护进程以使用 Tunnel 功能。
- 配置域名和转发URL
- 为你的域名配置一个子域名(Subdomain),Path 留空,URL 处填写内网服务的IP加端口号。注意 Type 处建议使用 HTTP,因为 Cloudflare 会自动为你提供 HTTPS,因此此处的转发目标可以是 HTTP 服务端口
接着访问刚刚配置的三级域名,例如 https://app.example.com(你没看错,cloudflare 已经自动为域名提供了 https 证书)就可以访问到内网的非公端口号服务了。
一个 Tunnel 中可以添加多条三级域名来跳转到不同的内网服务,在 Tunnel 页面的 Public Hostname 中新增即可。
更细节的操作步骤,以及如果不想将服务暴露给所有人,Cloudflare还贴心的帮你提供了一套安全完善的认证机制,你可以参考少数派提供的教程,这不是我这篇文章想要讲的重点内容。
任意TCP服务
网上轻易能找到的教程就是前半部分了,这种内容只能暴露HTTP服务以及通过网页访问SSH和VNC服务,而我想讲的重点是,如果我们想要连接到我的开发环境的非HTTP服务呢?任意一个TCP端口,可能是一个RDP协议的端口,也可能是MySQL的服务,前面那部分教程是无法帮你转发非HTTP服务的,网上的教程大家抄来抄去,很少有人讲这部分。
话不多说,直接开始,这里我们以内网的MySQL和SSH服务举个栗子。
SSH
- 还是需要按照Web服务的第五步在 Tunnel 页面的 Public Hostname 中新增一条记录,协议按需选择,我这里选的SSH,也可以选TCP
- 现在是在访问的电脑上操作,执行登录命令,这个时候浏览器会自动打开一个网址用于oauth授权。
- 在客户端修改 ~/.ssh/config 文件, 通过ProxyCommand 来调用 cloudflared 创建一个隧道,在这之前你可能需要先登录一下
- 最后
ssh home
即可。
RDP(以及任意TCP端口)
跟上面的SSH相同的步骤,在 Tunnel 页面的 Public Hostname 中新增一个域名,只是不再需要修改ssh config,直接通过命令启动端口代理
实际上只要我们成功地转发了SSH,即可通过SSH建立隧道来转发更多的端口,不再需要这样单独配置,如果没有SSH服务当我没说,按照这个方法配置也行。
新更新 NAT打洞
这部分更新在这篇文章写完之后一年,一个偶然的机会我测试之后发现我家的移动宽带NAT居然是NAT1 FullClone,我在Github上找到了Natter这个项目,具体使用方法可以参考项目自带的ReadMe,如果看完有问题可以加到官方的TG Channel,非常活跃,有问必答。
据我实测,正常情况下打洞成功之后,随机分发的端口可以使用7天左右,连接超时被关闭之后,Natter会自动重新连接并获得一个新的随机端口。