Merge pull request 'fix(companion): mesh VPN no longer blocks IPv4 + off-LAN connect via mesh ULA' (#108) from fix/mesh-vpn-and-offlan-connect into main
All checks were successful
Demo images / Build & push demo images (push) Successful in 2m54s

This commit is contained in:
lfg2025 2026-07-23 21:00:39 +00:00
commit a865306488
5 changed files with 39 additions and 5 deletions

View File

@ -11,8 +11,8 @@ android {
applicationId = "com.archipelago.app" applicationId = "com.archipelago.app"
minSdk = 26 minSdk = 26
targetSdk = 35 targetSdk = 35
versionCode = 21 versionCode = 22
versionName = "0.5.1" versionName = "0.5.2"
vectorDrawables { vectorDrawables {
useSupportLibrary = true useSupportLibrary = true

View File

@ -61,6 +61,13 @@ class ArchyVpnService : VpnService() {
.setMtu(1280) .setMtu(1280)
.addAddress(identity.address, 128) .addAddress(identity.address, 128)
.addRoute("fd00::", 8) .addRoute("fd00::", 8)
// The TUN is IPv6-only. Android blocks every address family
// the VPN has no address for — without this, bringing the
// mesh up cut ALL of the phone's IPv4 internet.
.allowFamily(android.system.OsConstants.AF_INET)
// And let apps that bind their own network skip the TUN
// entirely — this is mesh reachability, not a privacy VPN.
.allowBypass()
.establish() .establish()
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "VPN establish failed", e) Log.e(TAG, "VPN establish failed", e)

View File

@ -85,6 +85,7 @@ import com.archipelago.app.ui.theme.TextMuted
import com.archipelago.app.ui.theme.TextPrimary import com.archipelago.app.ui.theme.TextPrimary
import com.archipelago.app.ui.theme.TextSecondary import com.archipelago.app.ui.theme.TextSecondary
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.net.HttpURLConnection import java.net.HttpURLConnection
@ -171,10 +172,29 @@ fun ServerConnectScreen(
errorMessage = null errorMessage = null
scope.launch { scope.launch {
val result = testConnection(server) var reachable = testConnection(server)
// LAN address didn't answer — phone off-LAN (5G) or DHCP moved the
// node. The scanned IP was only ever a dial hint; the node's real
// identity is its npub and its ULA is reachable from anywhere over
// the mesh. Bring the tunnel up and probe the ULA before failing.
if (!reachable && server.meshIp.isNotBlank()) {
FipsManager.autoStartIfReady(context)
val meshServer = server.copy(
address = server.meshIp,
useHttps = false,
port = "",
)
// The tunnel + mesh route need a moment on cold start.
for (attempt in 0 until 4) {
if (attempt > 0) delay(2000)
reachable = testConnection(meshServer)
if (reachable) break
}
}
isConnecting = false isConnecting = false
if (result) { if (reachable) {
prefs.setActiveServer(server) prefs.setActiveServer(server)
onConnected(server.toUrl()) onConnected(server.toUrl())
} else { } else {

View File

@ -18,7 +18,14 @@ user's hands.
support; web scan modal hands live scanning to it. support; web scan modal hands live scanning to it.
- npub-keyed saved servers (pairing contract item 1, PR #106). - npub-keyed saved servers (pairing contract item 1, PR #106).
- Served APK refreshed: `neode-ui/public/packages/archipelago-companion.apk` - Served APK refreshed: `neode-ui/public/packages/archipelago-companion.apk`
is now **0.5.1 / versionCode 21** (this commit). is now **0.5.2 / versionCode 22**, which additionally fixes the two field
failures from the user's 5G test (screenshots, 21:54):
- **Mesh VPN no longer kills the phone's internet** — the IPv6-only TUN
never called `allowFamily(AF_INET)`, so Android blocked all IPv4 while
the mesh was up. Now allowed (+ `allowBypass`).
- **Off-LAN connect works**`connect()` no longer hard-fails when the
scanned LAN IP doesn't answer; it brings the mesh up and probes the
node's ULA (`meshIp`) with retries before reporting failure.
## What to do ## What to do