github infosave2007/aivpn v1.0.2

latest releases: v1.1.0, v1.0.5, v1.0.4...
2 months ago

⚠️ Android: uninstall the old app before installing this APK

The APK published with 1.0.0 and 1.0.1 was a debug build — signed with the
public Android debug key and marked android:debuggable, which let anyone with
adb access attach to the VPN process and read session keys out of its memory.
This release ships a properly signed, non-debuggable build, so Android will
refuse to install it over the old one ("App not installed" / signature
mismatch).

Uninstall the previous version first, then install this APK. Saved
connection keys live in app storage and are removed with it — export or
re-add your aivpn:// key afterwards. Nothing changes on the server side.

Fixed

Android: tunnel connected but carried no traffic until the app was reinstalled (#71, #70)

The native core duplicates the Android TUN descriptor, and those duplicates outlived the interface: Kotlin closes its ParcelFileDescriptor on disconnect and gives the native call 3 s to unwind, so a slower unwind left the tun device alive as a zombie still holding the VPN address. The next session established a second tun with the same address, app packets were routed into the dead one nobody reads, and the tunnel reported "connected" while the server saw keepalives and not one data packet. Caught on a device as tun0 DOWN holding the VPN address next to a live tun1 — which is why only a reinstall, a force-stop or clearing app data appeared to help: they kill the process and with it the stray descriptor.

The session now owns both duplicates (the AsyncFds only borrow them), so stopping the tunnel destroys the device immediately. After a disconnect the process holds zero tun descriptors and the device zero tun interfaces.

Android: a cached bootstrap descriptor could strand the data plane — a session that completes the handshake but never receives a single downlink data packet now discards its cached descriptors (the verdict surviving an app restart) and pins the next attempt to a builtin preset.

Server: an uplink packet that failed to decrypt could wedge the packet loop — the diagnostic path re-locked a session mutex already held by the enclosing block, deadlocking the worker and every other session with it.

Added

Interoperability with servers and clients from before the embedded-tag wire layout

An app updated past that change could not reach an older server at all, and an upgraded server could not serve an older app; both sides retried forever. Clients now fall back to the legacy tag-prefix layout (and the single, non-directional session key that goes with it) after repeated failed handshakes, and servers accept that layout in a second handshake pass that runs only when the modern pass finds nothing — so a current client's handshake costs exactly what it did before.

Upgrade order no longer matters, and existing aivpn:// keys keep working. See "Version Compatibility" in the README.

Verified

On a Xiaomi 2203129G against a live server over the real internet: consecutive disconnect/reconnect cycles each came back with the phone's egress IP equal to the server's and 0% loss; masks work and adapt (covert descriptor handshake, mask catalog, server-raised adaptive level mid-session); a current client reaches a pre-Variant-A server through the fallback in about a minute.

Not covered

The Windows half of #70 ("wintun adapter has no internet") was not investigated — no Windows machine available.

Don't miss a new aivpn release

NewReleases is sending notifications on new releases.