- Opening up a port on a home network isn’t the greatest idea. It is a security risk, a hole waiting for a hacker/bot to sneak in using a known vulnerability.
- Many ISP‘s and routers prevent you from opening up ports 80 and 443.
- Another challenge you will face is setting up a dynamic DNS.
- Finally, when your domain is pointing to your home IP address it is very easy to determine your home location.
This is where Cloudflare’s tunnel comes in. It builds a tunnel to cloudflares network. Now all request to your domain get directed through this tunnel to your web-server. all without opening any ports! and your domain simply points to cloudflare.
- Assumes you already have a domain name configured to use Cloudflare’s DNS service. This is a totally free service.
- Assumes you already have a Linux server with Nginx and Let’s Encrypt.
First we will get cloudflared installed as a package to get everything going. Then we will transfer it over to a service that automatically runs on boot in the background and establishes a tunnel.
$ wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb $ sudo dkpg -i cloudflared-linux-arm64.deb
*Note this link is for a raspberry pi, for other binaries see here.
This will create a folder in the home directory
Next, we need to authenticate with Cloudflare.
$ cloudflared tunnel login
This will generate a URL which will take you to login into your dashboard on Cloudflare.
$ cloudflared tunnel create <NAME>
Replace <NAME> with any name of your choice.
Running this command will:
- Create a tunnel by establishing a persistent relationship between the name you provide and a UUID for your tunnel. At this point, no connection is active within the tunnel yet.
- Generate a tunnel credentials file in the default
Confirm that the tunnel has been successfully created by running:
$ cloudflared tunnel list
Now, create a configuration file in your
.cloudflared directory. Using your favorite editor create a file
config.yml, the content should look like this:
tunnel: <Tunnel-UUID> credentials-file: /home/username/.cloudflared/<tunnel-UUID>.json originRequest: originServerName: mydomain.com ingress: - hostname: mydomain.com service: https://localhost:443 - service: http_status:404
A couple of things to note, here:
- Once the tunnel is up and traffic is being routed, Nginx will present the certificate for
cloudflaredwill forward the traffic to
localhostwhich causes a certificate mismatch error. This is corrected by adding the
originServerNamemodifiers just below the credentials-file
Cloudflare’s docs only provide examples for HTTP requests, and also suggests using the url
http://localhost:80. Although Nginx can handle 80 to 443 redirects, our ingress rules and ARGO will handle that for us. It’s not necessary to include any port 80 stuff.
- if you want to host additional services via subdomain, just simply list them with port 443, like so:
- hostname: subdomain1.mydomain.com service: https://localhost:443 - hostname: subdomain2.mydomain.com service: https://localhost:443
Just insure the last line is
- service: http_status:404.
Now, we need to setup a CNAME for the TLD and any services we want. The
cloudflared app handles this easily. The format of the command is:
$ cloudflared tunnel route dns <UUID or NAME> <hostname>
Do this for each service you want (i.e., subdomain1, subdomain2, etc) hosted through ARGO.
Cloudfalres DNS dashboard
Run the tunnel to proxy incoming traffic from the tunnel to any number of services running locally on your origin.
$ cloudflared tunnel run <UUID or NAME>
The above command as written (without specifying a config.yml path) will look in the default cloudflared configuration folder
~/.cloudflared and look for a config.yml file to setup the tunnel.
If everything’s working, the end of the output should be:
... ... <timestamp> INF Connection <redacted> registered connIndex=0 location=ATL <timestamp> INF Connection <redacted> registered connIndex=1 location=IAD <timestamp> INF Connection <redacted> registered connIndex=2 location=ATL <timestamp> INF Connection <redacted> registered connIndex=3 location=IAD
Now, try to access your website and your service from outside your network – for example, a smart phone on cellular connection is an easy way to do this. If your webpage loads, SUCCESS!
You’ll notice if you Ctrl+C out of this last command, the tunnel goes down! That’s not great! We want it up all the time. To do that we turn cloudflared into a service.
$ sudo cloudflared service install
Move the files to /etc/cloudflared
$ sudo mv ~/.cloudflared/* /etc/cloudflared/
Check ownership with
ls -la, should be
Now we need to fix the config file, replace the line:
$ credentials-file: /home/username/.cloudflared/<tunnel-UUID>.json
$ credentials-file: /etc/cloudflared/<tunnel-UUID>.json
Then, start the system service with the following command:
$ sudo systemctl start cloudflared
And start on boot with:
$ sudo systemctl enable cloudflared
Check the status with:
$ sudo systemctl status cloudflared
The output should be similar to that shown in Step 6 above. You can safely delete your
We now have a web-server serving the internet without opening any ports on our network.