How can I use ZScaler to access protected websites via Ubuntu without a dedicated Ubuntu client?
My company decided to drop our VPN for ZScaler and being the only person running Linux at my company I was left behind because ZScaler doesn't have a native Linux client.
Let me start by saying that this workaround is extremely labyrinthine and equally fragile. It requires two full computers which makes it both expensive and impossible to do on the go so this is not a solution for laptops and remote / traveling employees. For the second computer I recommend picking up an old used computer on eBay to use as the dedicated Windows 10 machine. Otherwise you can repurpose almost any old laptop laying around. Anything with WiFi and an Ethernet port will work.
Additionally, I hope that the product team at ZScaler sees the fragility of this workaround (a hack really) and is inspired to create a dedicated Linux client for us diehard Linux guys who just can't go back to macOS once we've switched.
Here's what you're going to need for this workaround:
- A windows 10 laptop fully updated with WiFi and Ethernet capabilities
- The ZScaler client for Windows 10
- A short Ethernet cable for connecting your Linux and Windows 10 machines
- A long Ethernet cable for connecting your Linux machine to the Internet
- A USB->Ethernet adapter for giving your Linux desktop a second Ethernet connection
Step 1: Connecting to ZScaler on Windows 10
Install the ZScaler client for Windows 10. Login with your credentials and verify you can access internal and/or ZScaler protected websites as well as external websites and the broader Internet.
Step 2: Verify all the necessary connections in Windows 10
In order for this to work your Windows 10 computer will need access to the outside internet (WiFi in this example), and the ZScaler adapter, and a local Ethernet connection to share ZScaler over. The below picture shows all of this.
Step 3: Prepare your local Ethernet connection
Part of the magic of this workaround is directly connecting your Windows 10 machine to your Linux machine via Ethernet and creating a private network between the two. In order to do this, you'll need to enter the properties of the local Ethernet connection's adapter and adjust the IPV4 settings to set a static IP address (very important) and also a subnet mask. I've chosen
255.255.255.0 respectively and it works great. Any valid internal IP address and subnet mask combination should work fine in theory.
Step 4: Sharing the ZScaler connection
This is one of the critical parts of the puzzle. Your Linux machine is going to get access to ZScaler via Windows 10 connection sharing. Right click on the ZScaler connection once it's connected and go to 'Properties'.
Step 5: Share your ZScaler adapter to your Linux machine
To do this, make sure your two computers are connected directly via Ethernet to Ethernet. It should be Linux <- Ethernet -> Windows 10. Then, go to the Sharing tab for the ZScaler adapter properties and share the ZScaler adapter with the Ethernet adapter which bridges your Linux machine to your Windows 10 machine.
Step 6: Verify ZScaler access on Linux
By now your Linux computer should be connected directly to your Windows 10 Machine and you should be able to resolve your internal website(s) on your Linux machine and nothing else. You should have no internet access. If you do, unplug your adapter(s) that give you internet connection. This is an extremely important step. Verify you can only access internal ZScaler-specific targets. If you're still having trouble with this step then try rebooting everything and starting over. Also, double check your static IP configuration on the Windows 10 machine as this doesn't tend to stick between reboots.
Step 7: Get internet access
In order to get Internet access you'll now need to use your USB->Ethernet adapter and plug it into your Linux machine. You should see services like Slack auto-login once your second Ethernet connection resolves and connects.
Step 8: Restore access to ZScaler-protected websites
Because plugging in a new internet connection changes your DNS and internet settings configuration at the Linux adapter level you need to restore access to ZScaler-protected assets via IP Tables in Linux. For this you need to know the IP address range of your protected assets, the static IP of your Windows 10 machine, and the device name itself for your internal private connection between Linux and Windows 10. For myself and my company the commands are:
sudo ip route add 100.64.0.0/10 via 192.168.137.1 dev eno1
sudo ip route add 172.16.0.0/12 via 192.168.137.1 dev eno1
eno1 is the name of the network adapter that is directly connecting Windows 10 to Linux and
192.168.137.1 is the static IP address you configured in Windows 10 and
172.16.0.0/12 are the CIDR ranges for your ZScaler protected assets. You can find the name of the correct adapter using to route your ZScaler traffic through using
ifconfig on your Linux machine and substitute in your device hardware name for
Step 9: Enable access to future ZScaler-protected websites
Right now you can only access websites that you've already requested from ZScaler before plugging in your internet connection. This is a DNS issue. In order to fix this, you need to set the Windows 10 machine as your default DNS server so that when you request access to internal websites by name
internal.mycompany.com then ZScaler can be used to resolve those hostnames. Once the hostname is resolved and the IP address shows a valid internal range you configured previously via IPTables then the traffic should be routed to the
eno1 or equivalent adapter and then to ZScaler to load. You should see two wired connections now in Linux when you're done.
Go ahead and edit the 'PCI Ethernet Connected' connection because that's the one we get internet from via our USB->Ethernet adapter.
Now we need the static IP address that we chose for our Windows 10 machine on the private network that exists between Linux <-> Windows 10. This is why setting a static IP address is important. We want to hard code this IP address as our DNS server.
And that's it! And this is how it works. All DNS requests are sent to ZScaler due to the DNS entry when configuring your network adapter. When a public IP is returned, your regular USB Ethernet connection resolves it successfully. When a private IP is returned, the IPTables forward the request to the adapter you specified when you executed
sudo ip route add.... This allows the Windows 10 / ZScaler machine to load the website's content and send it back to you via Windows 10 connection sharing.
This is essentially a split connection where all DNS requests are handled by ZScaler (since it is the only one who can resolve and load internal hostnames) but public content is loaded via your Linux USB Ethernet adapter and private content is loaded via your Ethernet<->Ethernet shared connection to Windows 10.
What breaks this 'workaround'?
- Windows 10 automatic updates reboot the machine
- ZScaler connection expires and you have to re-enable it (about every week)
- Google SSO session expires and you have to log back into Google inside ZScaler and restart your connection (about every week)
- Rebooting either the windows 10 or Linux machine. (yes you have to keep them both on 24/7)
- Power outage. See above.
- Changes in network topography on the Windows 10 side causing a new network / internet connection
- Changes in DHCP lease timing / renewing
- A slight breeze.
What is sub-optimal about this workaround?
- All DNS requests go through the ZScaler machine so your once hyper-fast wired connection is now as slow as WiFi for DNS requests at least.
- It finds a way to break at least once a week. Sometimes twice.
- You can never turn off your computers ever again otherwise you must perform this ritual every time to get your internet working again for both internal and external hosts.
I'll finish by saying that this is an absolute last-resort and that any company looking to switch to ZScaler from a VPN solution should consider the lack of a dedicated Linux client and how that may or may not affect their engineers' ability to get work done.