Cannot connect to a private HTTP resource - no private DNS
- Dominant language
- Kotlin
- Stars
- 43
- Forks
- 10
- Avg merge
- 1m
- Merged PRs (30d)
- 1
Description
### Describe the Bug
I have set up a private HTTP resource pointing to a Vaultwarden service. Everything is working fine connecting from my linux laptop running nixos and the pangolin-cli client.
On Android, I cannot connect. After setting it all up, enabling pangolin, and connecting to my self-hosted url in the Bitwarden android app, I get the following error:
```Stacktrace: kotlinx.serialization.json.JsonDecodingException: Unexpected JSON token at offset 0: Expected start of the object '{', but had '<' instead at path: $ cy.l(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:40) cy.m(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:13) cy.E(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:96) cy.h(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:45) jv9.c(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:43) com.bitwarden.network.model.InternalPreLoginResponseJson$$serializer.deserialize(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:6) com.bitwarden.network.model.InternalPreLoginResponseJson$$serializer.deserialize(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:113) jv9.r(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:303) com.bitwarden.network.serializer.BaseSurrogateSerializer.deserialize(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:10) jv9.r(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:303) o65.b(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:24) fz1.h(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:22) qx6.c(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:53) zj4.b(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:9) j58.run(r8-map-id-e23a7c24a2804d6c3e558e52e3511cf8a6897bc6a98b50ef2115d355c8cdf547:49) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1100) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) java.lang.Thread.run(Thread.java:1572) Version: 2026.8.0 (21819) Device: 📱 google Pixel 8 Pro 🤖 17@37 📦 prod CI: 🧱 commit: bitwarden/android/release/2026.8-rc60@8be53c1ae519ab417b64b0d2154f9815adf7c44a 💻 build source: bitwarden/android/actions/runs/31214376447/attempts/118:50```
If I browse to my Vaultwarden server url in a web browser on my Pixel, I get the "Private Placeholder Screen".
I have the enabled several options in Android to try to force the connection over the private DNS, but so far nothing has worked (see below for details).
In the pangolin web interface, the Android client is showing up under "User Devices" as "Connected".
The logged in user has been given authorization to connect to the private resource in the "Private Resources/Vaultwarden/Authentication" page.
The pangolin VPS has access to port 28120 udp at both the VPS and OS levels.
Here is some more diagnostic data:
In termux on android, I ran these commands:
```
> nslookup vault.mettavi.cloud
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: vault.mettavi.cloud
Address: 72.62.193.208
Name: vault.mettavi.cloud
Address: 2a02:4680:5e:a648::1
> nslookup vault.mettavi.cloud 100.96.128.1
Server: 100.96.128.1
Address: 100.96.128.1#53
Name: vault.mettavi.cloud
Address: 100.96.128.8
```
Also, using the `chrome://net-internals/#dns` page in the Chrome browser to query `vault.mettavi.cloud` shows the same details as `nslookup` above.
Please see the "To Reproduce" section below for all the settings I am testing under.
### Environment
- OS Type & Version: Android version 17 (Pixel 8 Pro)
- Pangolin Version: ee 1.21.1
- Edition (Community or Enterprise): Enterprise (free license)
- Gerbil Version: 1.5.0
- Traefik Version: 3.7.11
- Newt Version: 1.16
- Client Version: 0.5.0 (Android)
- Bitwarden client: 2026.8.0 (Android)
- Chrome client: 151.0.7922.173 (Android)
### To Reproduce
1. Using all the app versions as per the "Environment" section above
2. Configure the following settings in Android:
- in the Pangolin app, "Override DNS" is enabled, and "DNS Over Tunnel" is disabled
- In the system-wide Android settings (Settings → Network & internet), "Private DNS" is turned OFF.
- In the Chrome browser, "Use secure DNS" is turned off.
- In the system-wide VPS settings for Pangolin (Settings → Network & internet → VPN → gear icon next to the Pangolin app), "Always-on VPN" / "Block connections without VPN" are both turned off.
3. Enable the pangolin app, logging in with your use credentials. Ensure pangolin is connected both in the android app and on the pangolin web interface. Ensure the user has been given access to the private HTTP resource in the pangolin web interface. Ensure the private resource is showing as online in the pangolin web interface. Ensure port 28120 udp is open on the server.
4. Open the Bitwarden app on Android, and enter the private resource url in the "self-hosted" server settings. Login to the Vaultwarden server. See the popup message "An error has occurred" and click on the "Share error details" link. See the `Stacktrace: kotlinx.serialization.json.JsonDecodingException: Unexpected JSON token at offset 0: Expected start of the object` error as quoted in full above.
5. Open the Chrome android browser, and try to open the Vaultwarden URL, and see the "Private Placeholder" screen.
### Expected Behavior
The Bitwarden client should connect to the private HTTP Vaultwarden resource without error, while the pangolin android app is running.
Contributor guide
Research direction
Start by reproducing the Android connection with Override DNS and DNS Over Tunnel settings, using the provided nslookup results and the Chrome and Bitwarden behaviors as diagnostics. Trace how the Android client handles private DNS resolution and private HTTP resources, then verify that the Bitwarden URL loads instead of showing the Private Placeholder and that Android login succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin
- Domain
- mobile-dev, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 42/100