Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Cloudflare Tunnel Support #80

Open
batonac opened this issue Nov 18, 2022 · 7 comments
Open

Feature Request: Cloudflare Tunnel Support #80

batonac opened this issue Nov 18, 2022 · 7 comments
Labels
enhancement New feature or request

Comments

@batonac
Copy link
Contributor

batonac commented Nov 18, 2022

Hey team, congrats on making it to 5.1!

Okay, this might be a bit "far out", but I've known this team to be ambitious, so here goes...

Cloudflare Tunnels are free. This allows a server to serve websites directly through Cloudflare without allowing any other ingress HTTP/HTTPS traffic. This translates to no direct external traffic to your machine that doesn't first pass through Cloudflare WAF (with the exception of SSH for WPCD, of course).

Additionally, this provides a secure way for the web the server to serve to Cloudflare using HTTP rather than HTTPS, avoiding the overhead of SSL, and the maintenance liability of certificate management and renewals. Cloudflare provides and manages public-facing certificates on your behalf, so no problems there.

Taken a step further, both the webserver* and the Cloudflare Tunnel* could be configured to connect to each other through a Unix socket, further eliminating overhead and latency caused by the TCP/IP stack.

By my estimations, this should be the most efficient way to run a web server behind Cloudflare, and should be a boon for both server performance and security.

I doubt that any other competing solutions are doing this, and probably wouldn't for some time (if ever). This could be a real differentiator for WPCD!

--
*Nginx, at least, can be configured to serve to a unix socket instead of a port with syntax like listen unix:/tmp/site-name.sock;. I'm not sure about OLS.
*The syntax for connecting a Cloudflare Tunnel to a unix socket can be found here.

@batonac
Copy link
Contributor Author

batonac commented Nov 18, 2022

Oh, and in a Proxmox/OpenStack scenario, this should allow for servers using private IP addresses, eliminating the cost and hassle of provisioning public IP addresses for ever server, assuming that the WPCD site and servers are in the same private IP subnet and can communicate directly that way. This could mean even more security since all incoming external traffic could be blocked on the WPCD servers. 😯

@elindydotcom elindydotcom added the enhancement New feature or request label Nov 19, 2022
@elindydotcom
Copy link
Contributor

It's a cool idea but I don't think this is something that we can expect to be done anytime soon.

(Plus I shudder to think about the support level that would be required if this was added and a user didn't quite understand what pushing the button did or accidentally triggered it and they suddenly lost access to their servers.)

@batonac
Copy link
Contributor Author

batonac commented Nov 19, 2022

BTW, I have this working with a manual config under WPCD NGINX, following the instructions on the Cloudflare guide, with a bit of community guidance, and my own finagling:

  1. Install the correct package for Cloudflare:
    wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && dpkg -i cloudflared-linux-amd64.deb

  2. Enabling a tunnel (this would be the most difficult part to facilitate with WPCD, but doable):

    • mkdir /etc/cloudflared/
    • cloudflared tunnel login This command returns a link that needs to be followed for authorizing the connection to a particular site, which could presumably be passed back to the WPCD session for completing the activation.
    • cloudflared tunnel create <WPCD-Site>
    • cloudflared tunnel route dns <WPCD-Site> <Domain> --overwrite-dns This sets up a new cname mapping to <Tunnel-UUID>.cfargotunnel.com, which is how the DNS is configured within Cloudflare.

NOTE: Much of this step could be done manually with the Cloudflare Dashboard as well, but inclusion into WPCD would be swell.

  1. Enable the systemd service:

    • cloudflared service install
    • systemctl enable --now cloudflared
  2. Configure the following files (with sites-specific configs replaced with <> tags):

/etc/nginx/userconfigs/site/<WPCD-Site>-cloudflared.conf:

listen unix:/var/www/<WPCD-Site>.sock;

/etc/cloudflared/config.yml:

unix-socket: /var/www/<WPCD-Site>.sock
tunnel: <Tunnel-UUID>
credentials-file: /etc/cloudflared/<Tunnel-UUID>.json

Cloudflared complained about some systemctl parameters, so I setup /etc/sysctl.d/10-udp-recieve-buffer-size.conf:

net.core.rmem_max=2500000
net.core.wmem_max=2500000

From there, I could direct the site to the Tunnel ID in Cloudflare, set Cloudflare Encryption to "Flexible", and turn off HTTPS for the app in WPCD. WordPress didn't seem to like the HTTP to HTTPS handover though, and was leading to infinite redirect loops and mixed content until I added this directive to wp-config.php (props to the community forum):

if ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' )
{
    $_SERVER['HTTPS']       = 'on';
    $_SERVER['SERVER_PORT'] = 443;
}

To verify that everything was working correctly, I ran ufw deny 80 and ufw deny 443 on the server, and verified that the ports are blocked to incoming traffic. The site works and runs great on the frontend!

UPDATES:

11/21/2022: Nginx fails to restart if the .sock file already exists. I updated the .sock files location to /var/www/ (might be a better location...) and updated the Nginx service file to remove any existing .sock files before trying to restart:
mkdir -p /etc/systemd/system/nginx.service.d/
echo $'[Service]\nExecStartPre=/bin/su -s /bin/sh -c "/bin/rm -f /var/www/*.sock"' > /etc/systemd/system/nginx.service.d/rm-sock.conf
systemctl daemon-reload

@elindydotcom
Copy link
Contributor

That is cool. Will have to try it out one of these days.

@batonac
Copy link
Contributor Author

batonac commented Nov 21, 2022

Here's an enhanced snippet for wp-config.php:

if ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' )
{
    $_SERVER['HTTPS']       = 'on';
    $_SERVER['SERVER_PORT'] = 443;
}

@batonac
Copy link
Contributor Author

batonac commented Nov 21, 2022

(Plus I shudder to think about the support level that would be required if this was added and a user didn't quite understand what pushing the button did or accidentally triggered it and they suddenly lost access to their servers.)

My suggestion would be to make it a two-step process where the user enables the tunnel through WPCD, and is then given the tunnel address that they can use for their site's DNS cname (and possibly add it as another copy-able line below the site's IP address). That way, the user needs to explicitly switch the site over if that's what they want to do.

If they really want to block port 80 and 443, that should be their own choice, as a completely separate step...

@batonac
Copy link
Contributor Author

batonac commented Nov 21, 2022

Another possible advantage of this that could impact all types of users, BTW, would be the ability to do quick/seamless server migrations and restorations, and possibly even fail-over, without needing to change the DNS (as long as the tunnel ID can follow the site between WPCD servers).

Just dreaming...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants