Nova Kwok's Awesome Blog

Use Cloudflare Argo Tunnel (cloudflared) to accelerate and protect your website.

这篇文章有简体中文版本,在 使用 Cloudflare Argo Tunnel(cloudflared) 来加速和保护你的网站

This article was last updated on March 1, 2024, and includes the updated deployment and installation methods for the new version of cloudflared.

Yes, this is an article documenting the usage of cloudflared and sharing some thoughts. Regarding the usage of Cloudflare’s Argo Tunnel, you can find it in the article titled “Cloudflare Argo Tunnel Experiment: Finally, I Can Host a Website with a Raspberry Pi”. Cloudflare Argo Tunnel provides a lightweight daemon program called cloudflared, which can be installed on your own machine to establish a connection with Cloudflare and provide web services. In Cloudflare’s words:

With Tunnel, users can create a private link from their origin server directly to Cloudflare without a publicly routable IP address. Instead, this private connection is established by running a lightweight daemon, cloudflared, on your origin, which creates a secure, outbound-only connection. This means that only traffic that routes through Cloudflare can reach your origin.

Typically, when setting up a website and joining Cloudflare, there are several typical steps involved:

  1. Rent a server and run your app on it (e.g., listening on 127.0.0.1:8080).
  2. Configure Caddy/Nginx to listen on a specific domain and reverse proxy to the app’s port.
  3. Configure a domain on Cloudflare to point to your server’s IP and enable CDN (to protect the origin server’s IP).
  4. (Optional) Set up complex rules on the server/Nginx to prevent discovery of your origin server’s IP by tools scanning IPs/TLS certificates (which could lead to DDoS attacks).

There are many complexities involved in the above steps, and you might end up setting up various firewall rules only to realize that your application is directly exposed on <server_public_IP>:8080 due to a hole created by Docker on your machine (as mentioned in the article “Why Isn’t My UFW Working? How to Block Non-Cloudflare Access When Using Docker”).

To address such issues, you can use Cloudflare Argo Tunnel, which works as follows:

  1. Your server doesn’t even need a public IP.
  2. Your app continues to run on a local port (e.g., listening on 127.0.0.1:8080).
  3. You can set up a firewall anywhere and block all inbound traffic to the server except for SSH.
  4. Run the Argo Tunnel program (cloudflared) and configure it with the local app’s port. Argo Tunnel will generate a domain for you based on your requirements.
  5. Access the app directly using the domain provided by Argo Tunnel.

Doesn’t this sound similar to Tor’s Hidden Service?

Practical cloudflared

Systemd + Package Manager Installation (Default for Cloudflared Panel)

As of now (March 1, 2024), the installation and deployment of cloudflared have been integrated into the “Zero Trust” dashboard by Cloudflare.

If you want to create a new tunnel, you can directly create it here. After creation, you will be provided with the Systemd + binary installation method:

You can change the name later, so no worries.

In this example, the installation method is shown in the last screenshot:

curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && 

sudo dpkg -i cloudflared.deb && 

sudo cloudflared service install eyJhIjoi.....JMSJ9

Note that eyJhIjoi.....JMSJ9 is the token for the tunnel. If you prefer not to use this one-click installation method or if you want to have multiple different services on the same machine using different tunnels, you can record this token and deploy it using a Docker container.

Docker Container Deployment

For example, if you have a containerized service listening on port 8080, you can expose it separately using cloudflared by following these steps:

version: '3'

services:
  some_service:
    image: ghcr.io/n0vad3v/some_service:latest
    restart: always

  cloudflared:
    image: cloudflare/cloudflared
    restart: always
    command: --no-autoupdate tunnel run
    environment:
      - TUNNEL_TOKEN=eyJhIjoi.....JMSJ9

Since services within a Docker Compose network can communicate with each other using service names, in the above example, the service name is set as some_service. You can configure it accordingly on the Tunnel page:

After that, your service will be successfully exposed to the outside world.

Manual Installation (Old Method)

Updated on March 1, 2024: This is the old installation method, and it may not be necessary anymore.

As a documentation piece, let’s see how to perform the above operations (assuming you already have a Cloudflare account and have added a domain).

First, we need to download cloudflared. Since it is a binary, we can download it and run it directly:

wget https://github.com/cloudflare/cloudflared/releases/download/2022.3.4/cloudflared-linux-amd64
chmod +x cloudflared-linux-amd64
mv cloudflared-linux-amd64 /usr/bin/cloudflared

Log in to cloudflared locally. It will provide a URL, and you need to access it using a browser to select a domain:

cloudflared tunnel login

Cloudflare will create a cert.pem file in your ~/.cloudflared directory.

Next, create a tunnel (e.g., knat-tunnel):

cloudflared tunnel create knat-tunnel

This will output some information about the tunnel ID (e.g., xxxxxxx-5b0e-xxxx-8034-xxxxxxx). Make sure to record this information as it will be used later.

Create a domain for the tunnel. For example, I used tunnel.knat.network:

cloudflared tunnel route dns knat-tunnel tunnel.knat.network

Finally, create a configuration file (e.g., ~/.cloudflared/knat.yml) with the following content:

url: http://localhost:8080
tunnel: xxxxxxx-5b0e-xxxx-8034-xxxxxxx
credentials-file: /root/.cloudflared/xxxxxxx-5b0e-xxxx-8034-xxxxxxx.json

Start the tunnel:

cloudflared tunnel --config ~/.cloudflared/knat.yml run

This will display some debug information, including the Cloudflare nodes to which it is connected:

022-03-26T06:52:31Z INF Starting tunnel tunnelID=xxxxxxx-5b0e-xxxx-8034-xxxxxxx
2022-03-26T06:52:31Z INF Version 2022.3.4
...
2022-03-26T06:52:31Z INF Generated Connector ID: 624aa020-a90a-4bef-91da-330c74edb02f
2022-03-26T06:52:31Z INF Initial protocol http2
2022-03-26T06:52:31Z INF Starting metrics server on 127.0.0.1:44143/metrics
2022-03-26T06:52:33Z INF Connection 34504363-646c-46a2-973d-bd112943c58f registered connIndex=0 location=KIX
2022-03-26T06:52:34Z INF Connection 7a3ec8f7-482c-4fe5-93c4-69d1177ca457 registered connIndex=1 location=NRT
2022-03-26T06:52:35Z INF Connection 7d571bdb-96d2-49d3-b8bf-14754aa6cf8b registered connIndex=2 location=KIX
2022-03-26T06:52:36Z INF Connection 473e30ae-e98b-4da1-8768-12bf5304c7ab registered connIndex=3 location=NRT

Now, when you start a local service listening on 127.0.0.1:8080, you can access it directly using the provided domain.

If you want to create a tunnel on another machine, you can simply copy the ~/.cloudflared/ directory without the need to log in again.

Speed Test

Many people have already performed tests while creating tunnels, but the motivation behind this article is to test the speed. We know that Cloudflare defaults to routing traffic to the nearest origin server. In my previous article, “Simulating Argo Using an Anycast Network Behind Cloudflare”, I described the following:

If these two conclusions are difficult to understand, let’s consider the following scenario: Suppose my blog is located in France (let’s assume it resolves to origin.nova.moe), and you are a visitor from mainland China. Considering the current network environment:

By using Argo Tunnel, since the origin traffic goes through various public network tunnels of Cloudflare, it can reduce detours and, in some cases, improve speed. In simple terms, the speed should be faster. Cloudflare’s official promotional image illustrates this:

This applies to Argo Tunnel as well. To demonstrate this, I conducted a test with the following conditions:

  1. A server in Helsinki with a nominal bandwidth of 300 Mbps.
  2. A server in Japan with a nominal bandwidth of 200 Mbps.
  3. Latency between the two servers is 233 ms.
  4. When directly connected using iperf3, the speed is around 60 Mbps.
  5. Cloudflare’s caching strategy is set to “Bypass” (no caching).
  6. without-tunnel.knat.network is directly resolved to the server in Helsinki, with Cloudflare CDN enabled.
  7. tunnel.knat.network is the tunnel created using cloudflared on the server in Helsinki.
  8. A dummy file was generated: fallocate -l 1G CoronaVac.img.
  9. The file was downloaded using wget on the server in Japan.

Let’s directly look at the conclusions. When connected directly, the speed is as follows (average speed: 4.97 MB/s):

○ wget https://without-tunnel.knat.network/CoronaVac.img
--2022-03-26 15:07:39--  https://without-tunnel.knat.network/CoronaVac.img
Resolving without-tunnel.knat.network (without-tunnel.knat.network)... 2606:4700:3037::6815:2403, 2606:4700:3033::ac43:b694, 172.67.182.148, ...
Connecting to without-tunnel.knat.network (without-tunnel.knat.network)|2606:4700:3037::6815:2403|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1073741824 (1.0G) [application/octet-stream]
Saving to: ‘CoronaVac.img’

CoronaVac.img                           100%[==============================================================================>]   1.00G  5.37MB/s    in 3m 26s  

2022-03-26 15:11:06 (4.97 MB/s) - ‘CoronaVac.img’ saved [1073741824/1073741824]

When using Argo Tunnel, the speed is as follows (average speed: 13.6 MB/s):

○ wget https://tunnel.knat.network/CoronaVac.img
--2022-03-26 15:12:39--  https://tunnel.knat.network/CoronaVac.img
Resolving tunnel.knat.network (tunnel.knat.network)... 2606:4700:3037::6815:2403, 2606:4700:3033::ac43:b694, 172.67.182.148, ...
Connecting to tunnel.knat.network (tunnel.knat.network)|2606:4700:3037::6815:2403|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1073741824 (1.0G) [application/octet-stream]
Saving to: ‘CoronaVac.img’

CoronaVac.img                           100%[==============================================================================>]   1.00G  14.8MB/s    in 75s     

2022-03-26 15:13:56 (13.6 MB/s) - ‘CoronaVac.img’ saved [1073741824/1073741824]

The speed increased fourfold.

Moreover, this service is even free:

In the past, Argo Tunnel has been priced based on bandwidth consumption as part of Argo Smart Routing, Cloudflare’s traffic acceleration feature. Starting today, we’re excited to announce that any organization can use the secure, outbound-only connection feature of the product at no cost.

——A Boring Announcement: Free Tunnels for Everyone

https://blog.cloudflare.com/tunnel-for-everyone/

Some Additional Thoughts

Many of our infrastructure services are provided by US companies, or we heavily rely on products from US companies. The developer-friendly clouds we are familiar with (such as Vultr, Digital Ocean, Linode), major public clouds (AWS, GCP, Azure), major CDN providers (Cloudflare, Akamai, Fastly), commonly used technologies like Docker/Kubernetes, and the two major front-end frameworks (React, Angular) are all products of US companies.

As a result, it becomes quite challenging to have services that are completely hosted in the EU and owned by EU companies.

Sometimes I wonder: When these companies introduce exciting and hard-to-replace products (such as S3 or Lambda), what are we doing? What products do we have that are truly driving progress in certain areas of the internet? Even if it’s just a small improvement…

(Or perhaps we are still busy creating scenarios, empowering industries, providing leverage, and assisting in Southeast Asian expansion?)

This brings to mind a statement from Cloudflare’s blog:

At Cloudflare, our mission is to help build a better Internet.

I hope this documentation and test can inspire some people in their business. That’s all.

#English #Cloudflare