DragonSSH XHTTP Public Example
A deliberately small Android reference client for the DragonSSH XHTTP-SSH transport.
It contains one home screen, the XHTTP split-stream transport, SSH password authentication,
an Android VpnService, a local SOCKS relay, and BadVPN tun2socks with UDPGW.
Public scope
Included:
- XHTTP over TLS/HTTP/2
- streamed downlink:
GET {path}/{sessionId} - ordered packet uplink:
POST {path}/{sessionId}/{sequence} - simple Server, Port, SNI, XHTTP Host, and XHTTP Path configuration
- SSH username/password authentication
- silent SSH/XHTTP transport reconnect while the Android VPN remains established
- configurable VPN DNS resolvers
- UDPGW forwarding through BadVPN tun2socks
- separate Home, Settings, VPN/UDPGW, and Logs screens
Not included:
- paid application screens, branding, panel URLs, certificates, signing fingerprints, or secrets
- remote/online configuration
- config import/export or config protection
- Xray, DNSTT/SlowDNS, SSL payload modes, ads, analytics, accounts, profiles, or reseller features
- production server addresses or credentials
The large com.trilead, com.jcraft, org.spongycastle, and badvpn trees are vendored
transport dependencies. The native build compiles only libancillary, the socket-protection
bridge, and the UDPGW-enabled tun2socks executable.
Dependency note
The ConnectBot bcrypt fork is resolved from Maven Central as org.connectbot:jbcrypt:1.0.2. The former relocated coordinate org.connectbot.jbcrypt:jbcrypt:1.0.0 is intentionally not used.
Build fix in 1.0.7
- Corrected the password storage notice so it compiles with Android AAPT2.
- Updated the password storage notice and its resource reference.
- No tunnel behavior or saved-password behavior changed.
Build
- Open the root folder in Android Studio.
- Install Android SDK 36 and an Android NDK compatible with Gradle's
ndkBuildintegration. - Let Android Studio create
local.propertieswith your SDK path. - Build and install the
appmodule.
The minimum Android version is API 26. Four ABIs are enabled: ARMv7, ARM64, x86, and x86_64.
System-bar behavior
The sample handles Android edge-to-edge window insets explicitly. The configuration screen adds safe padding for the status bar, display cutouts, gesture navigation, three-button navigation, and the on-screen keyboard, so controls remain visible on Android 15/16 and earlier versions.
Configuration mapping
The app uses the same names as SocksRevive VOID:
- Server: the XHTTP proxy IP address or hostname.
- Port: the XHTTP listener port, normally
443. - User name / Password: SSH credentials carried inside the XHTTP stream.
- SNI: the hostname sent during the TLS handshake.
- XHTTP Host: the CDN or reverse-proxy routing hostname.
- XHTTP Path: the base path, such as
/ssh. - XHTTP TLS: enables TLS and HTTP/2 for the XHTTP connection.
There is no separate SSH destination. Server is the XHTTP proxy, and the XHTTP session exposes the SSH byte stream used for authentication.
TLS certificate behavior
To match the original SocksRevive VOID implementation, XHTTP TLS intentionally accepts every server certificate and skips hostname verification. Self-signed, expired, mismatched, and otherwise untrusted certificates are accepted. SNI is still sent for CDN/fronting routing, but it is not used to validate the certificate.
This is intentionally insecure against man-in-the-middle attacks and is included only because it is required by this transport example. There is no certificate-validation toggle in the sample.
Log viewer
The sample log is structured rather than rendered as one large text block:
- timestamp per entry
- INFO, WARNING, ERROR, DEBUG, or VERBOSE badge
- color-coded rows
- DEBUG/VERBOSE filter
- follow-newest toggle
- copy and clear actions
Passwords are never written to the log.
Protocol behavior
The SSH library receives a virtual duplex socket:
- its input stream is the body of one long-lived XHTTP GET response;
- its output stream is buffered and sent as strictly ordered POST requests;
- only one POST is in flight at a time, preserving sequence order;
- bounded buffering applies backpressure instead of creating an unbounded HTTP request queue;
- control sockets are excluded from the Android VPN to prevent routing loops.
See docs/XHTTP_PROTOCOL.md for the request contract.
License
The combined sample is distributed under GPL-3.0-or-later because its VPN layer contains
GPL-covered source. Third-party components retain their own notices; see
THIRD_PARTY_NOTICES.md and license files kept beside native sources.