Table of Contents
TCP tunneling is a valuable technique for forwarding connections beyond just web traffic running on HTTP(s). This is particularly useful for forwarding connections like SSH, RDP, or Postgres. Recently, I wanted to use Cloudflare Tunnels to forward TCP connections for my database, allowing me to access my DB from anywhere in the world securely and protected.
Prerequisites
For raw TCP tunneling with Cloudflare Tunnels (CFT), you need the cloudflared
service running on both the target node and all connecting client nodes.
Installation
First, update your package list and install cloudflared
:
sudo apt-get update; sudo apt-get -y install cloudflared
Authentication
Authenticate the server node with the following command and open the link in your browser to complete the authentication:
cloudflared tunnel login
Create a Tunnel
Create a tunnel with a unique identifier:
cloudflared tunnel create TunnelName
Note the UUID of your tunnel.
Configure DNS Route
Configure a DNS route to transport packets from your local forwarder via Cloudflare’s transport network:
cloudflared tunnel route dns <TUNNEL_UUID> <DESIRED_SUBDOMAIN>
Your desired subdomain might be something like database
. You should now have a custom DNS CNAME record aliasing database.<YOUR_DOMAIN>.com
to the tunnel domain.
Configure Cloudflared
Edit the cloudflared
configuration YAML file located at ~/.cloudflared/config.yaml
:
tunnel: <TUNNEL_UUID>
credentials-file: <PATH_TO_TUNNEL_UUID>.json
ingress:
- hostname: <SUBDOMAIN>.<YOURDOMAIN>.com
service: tcp://<PRIVATE_INTERNAL_IP>:<PORT>
# catch all
- service: http_status:404
Start the Tunnel
Start the tunnel with:
cloudflared tunnel run
For more permanent setups, install the cloudflared
service:
sudo cloudflared --config ~/.cloudflared/config.yml service install
Ensure the service is running with:
systemctl status cloudflared
Client Site Configuration or (Remote Site Command)
First, install your package install cloudflared
:
sudo apt-get update; sudo apt-get -y install cloudflared
On the client side, ensure cloudflared
is installed and authenticated. Then, connect to the tunnel:
cloudflared access tcp --hostname <SUBDOMAIN>.<YOURDOMAIN>.com --url 127.0.0.1:<LOCAL_PORT_FORWARD>
his command will take TCP connections sent to localhost:3306
(for example) and push the packets over the tunnel associated with the specified hostname. In my case, with Postgres, I simply connect to the host IP of 127.0.0.1
on port 3306
, and it is forwarded to the MySQL server node.
For more details, refer to the Cloudflare Tunnel documentation.
Excellent blog.