Securing a super secret service with Zero Trust

Picture it, Sicily, 1937… OK, maybe not that. Picture it, you have a custom network service that you want to get at via Cloudflare WARP logged in to Cloudflare Zero Trust, but it isn’t the kind of thing that easily fits into the Public Hostname way of doing stuff (for example, it may run on a bunch of random port numbers and not work in a web browser). You also don’t want the service to be visible on the LAN where it is hosted.

So how do you go about satisfying all these requirements? With some hocus-pocus on the host machine and some careful setup in Zero Trust.

The setup we’ll use in this example

So we’re going to assume a bunch of things:

  • The host machine will be Ubuntu 22.04.
  • You want the service to be available only to selected Zero Trust users in your organization.
  • It can’t be set up as an Application in Zero Trust.
  • We’ll select an arbitrary private IP address not used anywhere else for this service: 10.0.0.1 (adjust to taste).
  • The service can be configured to listen on a specified IP address, the one we selected above.

On the host machine

So the basic idea is to add an IP address to the local loopback network interface (lo), so it is only visible to processes on the host machine (It’s a bit of a kluge, and I didn’t know this was possible until I tried). The command to do this would be ip address add 10.0.0.1/32 dev lo

Since we don’t want to have to log in to run this command after every reboot, we’ll set up a systemd service to run it at boot time. Start by creating /etc/systemd/system/customstart.service, using the command sudo nano /etc/systemd/system/customstart.service. Put this in it:

[Unit]
After=network.target

[Service]
ExecStart=/usr/local/bin/customstart.sh

[Install]
WantedBy=default.target

Next, we create /usr/local/bin/customstart.sh (sudo nano /usr/local/bin/customstart.sh) and put this in it:

#!/bin/bash

ip addr add 10.0.0.1/32 dev lo

Once that’s done, we set permissions because Security Is Important:

sudo chmod 644 /etc/systemd/system/customstart.service
sudo chmod 700 /usr/local/bin/customstart.sh

Now we can enable out new “service” to run customstart.sh at boot time:

sudo systemctl enable customstart.service

Now you can happily reboot the host machine an the custom IP will be added to the loopback interface at boot time. You can also do other stuff in customstart.sh, maybe set up firewall rules and/or start your custom service. But because Security Is Important, starting or running a custom service type thing as root is a Bad Thing, using @reboot in a non-root user’s crontab is a better idea and setting it up as a systemd service that runs as a non-root user is an even better idea.

While you are on the host machine, install/configure your service to only bind to 10.0.0.1. If your service can’t do this, you will need to do clever iptables stuff to limit your service to only be accessible on the lo interface. For a Minecraft server (though Minecraft servers can bind to a specific IP address by setting server-ip in server.properties, so this is just an example), you would want something like:

iptables -A INPUT -i lo -p tcp --dport 25565 -j ACCEPT
iptables -A INPUT -p tcp --dport 25565 -j DROP

Zero Trust tunnel setup

You will need to set up a cloudflared tunnel connecting the host machine to your Zero Trust organization. Some things that are different from the general documentation for that:

  • You can skip the Public Hostname stuff.
  • In Private Network, add 10.0.0.1/32 as the only entry.

WARP client profile

You may want to set up a Profile in WARP Client (under Settings in the Zero Trust dashboard) that has Split Tunneling set to Include instead of Exclude and only have 10.0.0.1/32 in the Include list, you can then assign this profile to users who must only see your service and nothing else. For other users, just make sure that 10.0.0.1/32 is either covered by Include mode split tunneling, or not blocked by Exclude mode split tunneling.

Zero Trust policies

In Gateway -> Policies on the Zero Trust dashboard, you need to set up policies controlling who can access your 10.0.0.1/32 “network”. In general (for the paranoid, like me, because Security Is Important), it’s a good idea to have an Allow rule specifying the destination IP and specific user accounts allowed to access it. Directly after that, add a Block rule specifying the destination IP and Everyone.

Conclusion

So, with these little tricks, a bit of hocus-pocus on the host machine and three basic things in Zero Trust, you have your service available to selected people in a secure way.

Users will just need to have the WARP client installed on their device and log in to your Zero Trust organization with it, then they can access the service on 10.0.0.1.


Posted

in

,

by