由于我家的网络只有ipv6,没有公网ipv4,导致两个问题:
- ipv4网络下,无法访问家里的服务。
- 常用端口(80,443)被屏蔽了,要访问的话,必须带上端口号,例如:example.com:9527
cloudflare tunnel很好地解决了这两个问题,有了它我们甚至不需要公网ipv4或ipv6,可以把它理解为免费的打洞工具frp。唯一的缺点是速度可能不够理想,我家里的网络,单连接只有几百k/s,多连接可以跑满上行带宽2M/s,公司的网络单连接也能跑满上行带宽。可以把cloudflare作为备用,在无法使用ipv6的情况下,也至少能低速访问自己的服务。
安装
前置条件
- 一台已连接互联网的linux服务器(不需要公网ip)
- cloudflare账户,虽然cloudflare tunnel套餐是免费的,但可能需要绑卡
- 一些基础的linux知识
如果对下面的内容有疑惑,欢迎提问
准备
首先需要有一个域名,并把它的DNS迁到cloudflare,因为我的域名就是在cloudflare买的,所以这里没有教程,不赘述。随后进入Cloudflare Zero Trust控制面板,初次使用需要选择Plan,选择Free Plan,白嫖就完事了。
服务器安装cloudflared
在linux服务器上安装cloudflared,我的系统是manjaro,直接yay -S cloudflared
就欧了,安装成功后,在命令行执行cloudflared
应该就有输出。
配置与转发
在服务器上配置tunnel,有两种配置方式,一种是通过cloudflare控制台,另一种是通过命令行。我使用的是命令行,写脚本比较方便,有如下几步(以下示例使用yunyuyuan作为服务器的用户名,example.com作为域名):
创建tunnel
# 登录cloudflare cloudflared tunnel login # 创建一个tunnel,名字自定,这里用my-tunnel cloudflared tunnel create my-tunnel
然后, 执行
cloudflared tunnel list
显示my-tunnel的ID:~ $ cloudflared tunnel list ID NAME CREATED CONNECTIONS xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx my-tunnel 2023-01-08T02:26:41Z 2xLAX, 2xSJC
编写配置文件,
vim ~/.cloudflared/config.yml
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx credentials-file: /home/yunyuyuan/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json ingress: # ssh - hostname: ssh.example.com service: ssh://localhost # vnc远程桌面,端口5900 - hostname: vnc.example.com service: tcp://localhost:5900 # 其他http服务 - hostname: file.example.com service: http://localhost:9527 - hostname: speed-test.example.com service: http://localhost:9898 # 如果都没有匹配,则返回404,这句不能少 - service: http_status:404
写一个脚本,自动更新DNS以及运行tunnel,
vim ~/tunnel-sh.sh
# update cloudflare DNS record /usr/bin/cloudflared tunnel route dns my-tunnel ssh.example.com /usr/bin/cloudflared tunnel route dns my-tunnel vnc.example.com /usr/bin/cloudflared tunnel route dns my-tunnel file.example.com /usr/bin/cloudflared tunnel route dns my-tunnel speed-test.example.com # run tunnel /usr/bin/cloudflared tunnel run my-tunnel
开机自启
新建一个service,
sudo vim /etc/systemd/system/cloudflared-tunnel.service
[Unit] Description=cloudflared tunnel Wants=network-online.target After=network-online.target StartLimitInterval=300 [Service] User=yunyuyuan ExecStart=sh /home/yunyuyuan/tunnel-sh.sh # 如果启动失败,自动重试,因为开机自启大概率报错网络问题 Restart=always RestartSec=30 [Install] WantedBy=default.target
启动&开机自启
sudo systemctl start cloudflared-tunnel.service sudo systemctl enable cloudflared-tunnel.service
以上完成后,http服务便可以正常使用,访问http://file.example.com/wtf
相当于访问服务器的http://localhost:9527/wtf
。服务端到此已配置完毕。
ssh访问
需要在客户端也安装cloudflared,安装方式和上面一样,我的客户端是Windows,下载cloudflared-windows-amd64.exe文件,然后添加一个ssh配置:
Host ssh.example.com
# 把 D:\tools\cloudflared-windows-amd64.exe 改成你自己的目录
ProxyCommand D:\tools\cloudflared-windows-amd64.exe access ssh --hostname %h
使用ssh yunyuyuan@ssh.example.com
即可ssh登录。
vnc远程桌面
客户端使用vnc远程桌面访问服务器(假设服务器已经开启了vnc server),需要先在客户端的命令行里执行cloudflared access tcp --hostname vnc.example.com --url tcp://localhost:5901
,这个命令把vnc.example.com(对应服务器的tcp://localhost:5900)映射到客户端本地的tcp://localhost:5901。
然后我们用vnc viewer,或者其他vnc软件,使用localhost:5901
登录VNC。
浏览器访问SSH&VNC
浏览器本身不支持ssh和vnc,cloudflare的application提供了ssh和vnc浏览器渲染功能。首先,创建一个application,域名输入vnc.example.com
,在Settings界面选择Browser rendering为VNC:
选择VNC
保存后,访问http://vnc.example.com
,输入密码登陆VNC(我的域名是vnc.yunyuyuan.net):
浏览器上的VNC
SSH同理,域名输入ssh.example.com
,Browser rendering选择SSH,保存后访问http://ssh.example.com
可以看到一个终端界面。
Tips
上面把file.example.com
等4个域名都用在了cloudflare tunnel,如果你的客户端有ipv6,此时不用通过cloudflare tunnel便可访问服务器,则可以新建一个file-direct.example.com
的DNS解析,ip指向服务器的公网ipv6就可以了。
做一个门户界面,把服务的URL都放到上面,切换是否使用代理,显示不同的链接。不代理的url是http://file-direct.example.com:9527
,代理的url是http://file.example.com
:
门户