Recently, I set up several web services on a Raspberry Pi, but they can only be used locally and cannot be accessed through the Internet. So I tried using Cloudflare Tunnel for intranet penetration. Here, I will record my operation process.
My hardware configuration
Raspberry Pi 4B+ with Ubuntu system
Install cloudflared#
To set up a Cloudflare tunnel on Raspberry Pi, we will rely on a software called "Cloudflared", which creates and maintains secure tunnels between the local network and the Cloudflare network. There are two installation methods.
Method 1: Use the Cloudflare repository#
- Get the GPG key for the Cloudflared repository
curl -L https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-archive-keyring.gpg >/dev/null
- Add the Cloudflared repository to the software sources
echo "deb [signed-by=/usr/share/keyrings/cloudflare-archive-keyring.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
- Update the package cache and install
cloudflared
:
sudo apt update
sudo apt install cloudflared
Method 2: Use the official deb package directly#
Download the latest deb package from the Release page on Github and install it using dpkg
:
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb && sudo dpkg -i cloudflared-linux-arm64.deb
Note: For Raspberry Pi 4B, install the arm64
version.
Configure the account#
Execute the following command in the command line and follow the prompts for account verification:
cloudflared tunnel login
Create a tunnel#
Execute the following command to create a tunnel:
cloudflared tunnel create <tunnel-name>
After running the above command, you will see a message similar to the following:
Tunnel credentials written to /home/pi/.cloudflared/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.
Created tunnel pimytunnel with id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
At this step, a UUID for the tunnel, a credential file, and a subdomain .cfargotunnel.com
are generated. The UUID and credential file will be used in the configuration file later, so be sure to remember the UUID and the path of the credential file (which will be mentioned later).
You can also use the following command to verify if the tunnel is created successfully:
cloudflared tunnel list
Detailed tunnel configuration#
There are 3 default paths for the configuration file:
~/.cloudflared
/etc/cloudflared
/usr/local/etc/cloudflared
Here, we will use the current user's directory, ~/.cloudflared
. We create a configuration file named config.yml
in that directory and fill in the configuration information generated when creating the tunnel:
tunnel: <Tunnel-UUID>
credentials-file: /home/pi/.cloudflared/<Tunnel-UUID>.json
ingress:
- hostname: test.example.com
service: http://localhost:80
- hostname: example.com
service: https://localhost:8000
- service: http_status:404
Then, configure the hostname and port of your own web service according to the format of the configuration file. Each rule generally includes hostname
and service
parts. Note the last line - service: http_status:404
. We can see that there is no hostname part, which is not an error but a special rule of cloudflared
. It is mainly used to match all traffic and is necessary.
This is related to the matching rules of cloudflared
. When cloudflared
receives an incoming request, it evaluates each ingress rule from top to bottom to find the rule that matches the request. Rules can match the hostname or path of the incoming request, or both. If no rule matches, the last rule will be matched.
Route intranet service traffic#
Use the following command to assign a CNAME record to redirect traffic to your tunnel subdomain.
cloudflared tunnel route dns <UUID or NAME> <hostname>
# example
cloudflared tunnel route dns pi test.example.com
Run the tunnel#
Execute the following command to connect cloudflared to the Cloudflare network. Cloudflared will retrieve the configuration file from the default location, ~/.cloudflared/config.yml
.
cloudflared tunnel run <UUID or NAME>
If your configuration file is not in the default path, you can use the --config
option to run the tunnel:
cloudflared tunnel --config /path/your-config-file.yaml run <UUID or NAME>
Check tunnel parameters#
At this point, the tunnel configuration is complete. You can execute the following command to get information about the tunnel you just created:
cloudflared tunnel info
Here are some other commonly used commands:
Functions | Commands |
---|---|
Create tunnel | cloudflared tunnel run <NAME> |
Tunnel list | cloudflared tunnel list |
Stop tunnel | cloudflared tunnel stop <NAME> |
Restart tunnel | cloudflared tunnel restart <NAME> |
Delete tunnel | cloudflared tunnel delete <NAME> |
Force delete tunnel | cloudflared tunnel delete -f <NAME> |
Show tunnel info | cloudflared tunnel info <NAME> |
Run the tunnel as a service#
Install the Tunnel as a system service, allowing the Tunnel to run as a startup daemon automatically. By default, the Tunnel expects to find the configuration file in the default directory ~/.cloudflared/config.yml
. However, to run the Tunnel as a service, we need to move the config.yml file to ~/etc/cloudflared/
.
Use the mv
command to move the configuration file:
sudo mv /home/pi/.cloudflared/config.yml /etc/cloudflared/
Then, execute the following command to install the service:
sudo cloudflared service install
Start the service:
systemctl start cloudflared
Check the service status:
systemctl status cloudflared
Pitfalls#
Encountered a problem when starting the tunnel service:
failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB).
Solution:
sudo sysctl -w net.core.rmem_max=2500000
References#
https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/
https://github.com/quic-go/quic-go/wiki/UDP-Receive-Buffer-Size