使用cloudflare tunnel打洞,随时随地访问内网服务

9,615 阅读4分钟

由于我家的网络只有ipv6,没有公网ipv4,导致两个问题:

  • ipv4网络下,无法访问家里的服务。

  • 常用端口(80,443)被屏蔽了,要访问的话,必须带上端口号,例如:example.com:9527

    cloudflare tunnel很好地解决了这两个问题,我们甚至不需要公网ipv4或ipv6,可以把它理解为免费的frp,唯一的缺点是速度不够理想,可以把cloudflare作为备用,在无法使用ipv6的情况下,也至少能低速访问自己的服务。

安装

前置条件

  • 一台已连接互联网的linux服务器(不需要公网ip)
  • cloudflare账户,虽然cloudflare tunnel套餐是免费的,但可能需要绑卡
  • 一些基础的linux知识,如果对下面的内容有疑惑,欢迎提问

准备

首先需要有一个域名,并把它的DNS迁到cloudflare,这里不赘述。随后进入Cloudflare Zero Trust控制面板,初次使用需要选择Plan,选择Free Plan,白嫖就完事了。

服务器安装cloudflared

需要在服务器上安装cloudflared,我的系统是manjaro,直接yay -S cloudflared就欧了,安装成功后,在命令行执行cloudflared应该就有输出。

配置与转发

在服务器上配置tunnel,有两种配置方式,一种是通过cloudflare控制台,另一种是通过命令行。我使用的是命令行,写脚本比较方便,有如下几步(以下示例使用yunyuyuan作为用户名,example.com作为域名):

  1. 创建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
    
  2. 编写配置文件,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
    
  3. 写一个脚本,自动更新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
    
  4. 开机自启

    新建一个service,sudo vim /etc/systemd/system/cloudflared-tunnel.service

    [Unit]
    Description=cloudflared tunnel
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    User=yunyuyuan
    ExecStart=sh /home/yunyuyuan/tunnel-sh.sh
    
    [Install]
    WantedBy=default.target
    

    启动&开机自启

    sudo systemctl start cloudflared-tunnel.service
    sudo systemctl enable cloudflared-tunnel.service
    

以上完成后,http服务便可以正常使用,访问http://file.example.com/wtf相当于访问服务器的http://localhost:5885/wtf。服务端到此已配置完毕。

ssh访问

需要在客户端也安装cloudflared,安装方式和上面一样,我的客户端是Windows,下载一个.msi文件安装,命令行执行install命令就行了。然后#添加一个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[70% x ] 保存后,访问http://vnc.example.com,输入密码登陆VNC: 浏览器上的VNC SSH同理,域名输入ssh.example.comBrowser rendering选择SSH,保存后访问http://ssh.example.com可以看到一个终端界面。

Tips

上面把file.example.com等4个域名都用在了cloudflare tunnel,如果你有ipv6,想要不通过cloudflare tunnel访问服务器,则可以新建一个_file.example.com的DNS解析,ip指向服务器的公网ipv6就可以了。
可以做一个门户界面,把服务都放到上面,切换是否使用代理,显示不同的链接,不代理的url是http://_file.example.com:9527,代理的url是http://file.example.com门户

原文地址:blog.yunyuyuan.net/articles/58…