Fix: ExpressVPN 14.2.0 connects but DNS/internet dies on Pop!_OS 24.04
TRANSPARENCY: this post was generated by AI. The fix is by AI. I did my best to ensure that the AI tested for DNS leaks and vulnerabilities the fix might create. Be skeptical. Use at your own risk.
I am sending the report to ExpressVPN support.
---
[AI generated text from here on in.]
I found and worked around a DNS compatibility bug between ExpressVPN 14.2.0 and Pop!_OS 24.04.
This is not a general "VPN tunnel will not connect" problem. ExpressVPN reported Connected, the tunnel passed traffic to literal IP addresses, and the public address changed to an ExpressVPN exit address. However, DNS failed, so browsers timed out and most applications appeared to have no internet.
Environment
- Pop!_OS 24.04 LTS with COSMIC
/etc/os-release:ID=pop,ID_LIKE="ubuntu debian"- systemd 255
- NetworkManager 1.46.0
systemd-resolvedenabled and active- ExpressVPN 14.2.0+13656
- Reproduced with Lightway UDP and WireGuard
Root cause
The installed ExpressVPN script /opt/expressvpn/bin/openvpn-updown.sh contains this test:
# NOTE: Work-around for DNS bug in Ubuntu 24 - where resolvectl may hang
if /usr/bin/systemctl --version | grep -q "systemd 255"; then
hasUbuntuDnsBug=1
It does not check the distribution. It assumes every system running systemd 255 has the Ubuntu 24 DNS bug.
Pop!_OS is based on Ubuntu, but it is a separate distribution and identifies itself as ID=pop. On this machine, resolvectl works normally. Nevertheless, ExpressVPN took its Ubuntu workaround path, bypassed systemd-resolved, and directly overwrote /etc/resolv.conf with:
nameserver 100.64.100.1
Because /etc/resolv.conf is a symlink to /run/systemd/resolve/stub-resolv.conf, this also writes into a file managed by systemd-resolved.
The ExpressVPN SDK then repeatedly logged errors including:
Temporary failure in name resolution
User IP fetch did not complete within 2s
Workaround
This is an unofficial, local workaround. It makes the Ubuntu-specific branch require an actual Ubuntu ID, allowing Pop!_OS to use the script's existing systemd-resolved integration.
Disconnect ExpressVPN first. Back up the script without overwriting an existing backup:
test ! -e /opt/expressvpn/bin/openvpn-updown.sh.before-popos-dns-fix && \
sudo cp -a \
/opt/expressvpn/bin/openvpn-updown.sh \
/opt/expressvpn/bin/openvpn-updown.sh.before-popos-dns-fix
Apply the one-line change:
sudo sed -i \
's@if /usr/bin/systemctl --version | grep -q "systemd 255"; then@if grep -q "^ID=ubuntu$" /etc/os-release \&\& /usr/bin/systemctl --version | grep -q "systemd 255"; then@' \
/opt/expressvpn/bin/openvpn-updown.sh
Validate the shell syntax and inspect the exact change:
bash -n /opt/expressvpn/bin/openvpn-updown.sh
sudo diff -u \
/opt/expressvpn/bin/openvpn-updown.sh.before-popos-dns-fix \
/opt/expressvpn/bin/openvpn-updown.sh
The diff should show exactly one changed line:
-if /usr/bin/systemctl --version | grep -q "systemd 255"; then
+if grep -q "^ID=ubuntu$" /etc/os-release && /usr/bin/systemctl --version | grep -q "systemd 255"; then
Do not continue if the diff shows any other change.
Verification
After reconnecting, these commands should show that the systemd stub remains intact and the VPN interface owns the global DNS route:
For WireGuard:
readlink -f /etc/resolv.conf
grep '^nameserver' /etc/resolv.conf
resolvectl status wgexpressvpn0
timeout 8 getent ahostsv4 www.google.com
For Lightway:
readlink -f /etc/resolv.conf
grep '^nameserver' /etc/resolv.conf
resolvectl status tun0
timeout 8 getent ahostsv4 www.google.com
Expected results:
/run/systemd/resolve/stub-resolv.conf
nameserver 127.0.0.53
The VPN interface should show:
Current DNS Server: 100.64.100.1
DNS Domain: ~.
In my test, ExpressVPN logged Applying nameservers using systemd-resolved..., DNS worked immediately, and normal HTTPS traffic used the VPN exit.
I tested again with Lightway UDP and re-enabled ExpressVPN's malicious-site, tracker, and ad blockers without breaking connectivity. A packet capture showed DNS requests and responses only on tun0; no port 53 traffic left through the physical Ethernet interface. ExpressVPN's DNS leak and WebRTC leak tests both passed.
Rollback
Disconnect ExpressVPN, then restore the original file:
expressvpnctl disconnect
sudo cp -a \
/opt/expressvpn/bin/openvpn-updown.sh.before-popos-dns-fix \
/opt/expressvpn/bin/openvpn-updown.sh
Caveats
- This is not an official ExpressVPN patch.
- It modifies a root-owned vendor script. Verify the diff before reconnecting.
- An ExpressVPN update may overwrite the change.
- Do not blindly reapply this workaround after an update. Check whether ExpressVPN has fixed the detection logic first.
- The ExpressVPN daemon has a separate compiled systemd-255 check, so it may continue logging
Ubuntu 24 DNS bug is presenteven though the patched DNS script usessystemd-resolved. Split tunneling was disabled during my tests. - The better upstream fix would detect actual resolver capability, with a timeout, instead of inferring behavior from the systemd major version alone.