mirror of
git://f0xx.org/android_cast
synced 2026-07-29 04:18:09 +03:00
fix(dev): show WG VPN IP and RSSH bind in network self-test
Persist tunnel endpoint metadata from connect credentials so the VPN section reports allocated addresses: WireGuard vpn-ip plus hub-only egress hint, and RSSH bastion/remote-bind/local-forward with live rssh-connected status. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -69,6 +69,10 @@ public final class AppPreferences {
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_RANDOM = "dev_remote_access_random";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_SESSION_ID = "dev_remote_access_session_id";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_EXPIRES_AT = "dev_remote_access_expires_at";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_VPN_ADDRESS = "dev_remote_access_vpn_address";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_RSSH_BASTION = "dev_remote_access_rssh_bastion";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_RSSH_REMOTE_BIND = "dev_remote_access_rssh_remote_bind";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_RSSH_LOCAL_FORWARD = "dev_remote_access_rssh_local_forward";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_VPN_ROUTE_SCOPE = "dev_remote_access_vpn_route_scope";
|
||||
private static final String KEY_DEV_REMOTE_ACCESS_VPN_APP_SCOPE = "dev_remote_access_vpn_app_scope";
|
||||
private static final String KEY_DEV_ADB_WIFI_KEEPER = "dev_adb_wifi_keeper";
|
||||
@@ -519,11 +523,73 @@ public final class AppPreferences {
|
||||
.apply();
|
||||
}
|
||||
|
||||
/** WG interface address from last connect credentials (host part, no CIDR). */
|
||||
public static String getDevRemoteAccessVpnAddress(Context context) {
|
||||
return prefs(context).getString(KEY_DEV_REMOTE_ACCESS_VPN_ADDRESS, "");
|
||||
}
|
||||
|
||||
public static void setDevRemoteAccessVpnAddress(Context context, String addressCidr) {
|
||||
String host = addressCidr != null ? addressCidr.trim() : "";
|
||||
int slash = host.indexOf('/');
|
||||
if (slash > 0) {
|
||||
host = host.substring(0, slash);
|
||||
}
|
||||
prefs(context).edit()
|
||||
.putString(KEY_DEV_REMOTE_ACCESS_VPN_ADDRESS, host)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static String getDevRemoteAccessRsshBastionEndpoint(Context context) {
|
||||
return prefs(context).getString(KEY_DEV_REMOTE_ACCESS_RSSH_BASTION, "");
|
||||
}
|
||||
|
||||
/** Bastion-side operator bind (127.0.0.1:port) from last RSSH connect. */
|
||||
public static String getDevRemoteAccessRsshRemoteBind(Context context) {
|
||||
return prefs(context).getString(KEY_DEV_REMOTE_ACCESS_RSSH_REMOTE_BIND, "");
|
||||
}
|
||||
|
||||
public static String getDevRemoteAccessRsshLocalForward(Context context) {
|
||||
return prefs(context).getString(KEY_DEV_REMOTE_ACCESS_RSSH_LOCAL_FORWARD, "");
|
||||
}
|
||||
|
||||
public static void setDevRemoteAccessRsshTunnelMeta(
|
||||
Context context,
|
||||
String bastionHost,
|
||||
int bastionPort,
|
||||
int remoteBindPort,
|
||||
String localForwardHost,
|
||||
int localForwardPort) {
|
||||
String host = bastionHost != null ? bastionHost.trim() : "";
|
||||
String bastion = host.isEmpty()
|
||||
? ""
|
||||
: host + ":" + Math.max(1, Math.min(65535, bastionPort));
|
||||
String remoteBind = remoteBindPort > 0 ? "127.0.0.1:" + remoteBindPort : "";
|
||||
String localHost = localForwardHost != null && !localForwardHost.isEmpty()
|
||||
? localForwardHost.trim() : "127.0.0.1";
|
||||
String localForward = localForwardPort > 0 ? localHost + ":" + localForwardPort : "";
|
||||
prefs(context).edit()
|
||||
.putString(KEY_DEV_REMOTE_ACCESS_RSSH_BASTION, bastion)
|
||||
.putString(KEY_DEV_REMOTE_ACCESS_RSSH_REMOTE_BIND, remoteBind)
|
||||
.putString(KEY_DEV_REMOTE_ACCESS_RSSH_LOCAL_FORWARD, localForward)
|
||||
.apply();
|
||||
}
|
||||
|
||||
/** Clears WG/RSSH tunnel endpoint fields from the last connect (not mode/route prefs). */
|
||||
public static void clearDevRemoteAccessTunnelMeta(Context context) {
|
||||
prefs(context).edit()
|
||||
.remove(KEY_DEV_REMOTE_ACCESS_VPN_ADDRESS)
|
||||
.remove(KEY_DEV_REMOTE_ACCESS_RSSH_BASTION)
|
||||
.remove(KEY_DEV_REMOTE_ACCESS_RSSH_REMOTE_BIND)
|
||||
.remove(KEY_DEV_REMOTE_ACCESS_RSSH_LOCAL_FORWARD)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void clearDevRemoteAccessSession(Context context) {
|
||||
prefs(context).edit()
|
||||
.remove(KEY_DEV_REMOTE_ACCESS_SESSION_ID)
|
||||
.remove(KEY_DEV_REMOTE_ACCESS_EXPIRES_AT)
|
||||
.apply();
|
||||
clearDevRemoteAccessTunnelMeta(context);
|
||||
}
|
||||
|
||||
public static long getDevRemoteAccessExpiresAt(Context context) {
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class DevVpnStatusProbe {
|
||||
String typeLabel = mode == RemoteAccessMode.DISABLED ? "off" : mode.name().toLowerCase(Locale.US);
|
||||
r.itemPass("type", typeLabel);
|
||||
|
||||
if (mode != RemoteAccessMode.DISABLED) {
|
||||
if (mode == RemoteAccessMode.WIREGUARD) {
|
||||
r.itemPass(
|
||||
"vpn-route-scope",
|
||||
RemoteAccessVpnRouting.routeScopeLabel(
|
||||
@@ -78,6 +78,24 @@ public final class DevVpnStatusProbe {
|
||||
String tunnelLabel = formatTunnelStateLabel(tunnelState, last);
|
||||
r.item(tunnelLevel, "tunnel-state", tunnelLabel);
|
||||
|
||||
if (mode == RemoteAccessMode.WIREGUARD) {
|
||||
String vpnIp = AppPreferences.getDevRemoteAccessVpnAddress(context);
|
||||
if (!vpnIp.isEmpty()) {
|
||||
r.itemPass("vpn-ip", vpnIp);
|
||||
} else if (RemoteAccessStatusStore.STATE_SUCCESS.equals(tunnelState)
|
||||
|| RemoteAccessStatusStore.STATE_CONNECTING.equals(tunnelState)) {
|
||||
r.item(DevNetworkSelfTestReport.Level.WARN, "vpn-ip", "not stored (reconnect session)");
|
||||
}
|
||||
if (AppPreferences.getDevRemoteAccessVpnRouteScope(context)
|
||||
== RemoteAccessVpnRouting.RouteScope.HUB_ONLY) {
|
||||
r.itemPass(
|
||||
"wan-egress-via-vpn",
|
||||
"no (hub-only — only " + RemoteAccessVpnRouting.DEFAULT_HUB_ALLOWED_IPS + ")");
|
||||
}
|
||||
} else if (mode == RemoteAccessMode.RSSH) {
|
||||
appendRsshTunnelMeta(context, r, tunnelState);
|
||||
}
|
||||
|
||||
if (mode != RemoteAccessMode.DISABLED
|
||||
&& !RemoteAccessStatusStore.STATE_OFF.equals(controlPlane)) {
|
||||
DevNetworkSelfTestReport.Level cpLevel;
|
||||
@@ -98,6 +116,8 @@ public final class DevVpnStatusProbe {
|
||||
if (mainProcess && mode == RemoteAccessMode.WIREGUARD) {
|
||||
boolean bound = VpnServiceClient.get(context).isBound();
|
||||
r.itemPass("vpn-process-bound", bound ? "yes (:vpn AIDL)" : "no (not bound — normal if idle)");
|
||||
} else if (mainProcess && mode == RemoteAccessMode.RSSH) {
|
||||
r.itemPass("rssh-connected", ReverseSshTunnelBridge.isConnected() ? "yes" : "no");
|
||||
}
|
||||
if (!vpnDetail.isEmpty()) {
|
||||
r.itemPass("detail", vpnDetail);
|
||||
@@ -304,6 +324,33 @@ public final class DevVpnStatusProbe {
|
||||
return caps != null && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
||||
}
|
||||
|
||||
private static void appendRsshTunnelMeta(
|
||||
Context context,
|
||||
DevNetworkSelfTestReport r,
|
||||
String tunnelState) {
|
||||
String bastion = AppPreferences.getDevRemoteAccessRsshBastionEndpoint(context);
|
||||
if (!bastion.isEmpty()) {
|
||||
r.itemPass("rssh-bastion", bastion);
|
||||
} else if (RemoteAccessStatusStore.STATE_SUCCESS.equals(tunnelState)
|
||||
|| RemoteAccessStatusStore.STATE_CONNECTING.equals(tunnelState)) {
|
||||
r.item(DevNetworkSelfTestReport.Level.WARN, "rssh-bastion", "not stored (reconnect session)");
|
||||
}
|
||||
String remoteBind = AppPreferences.getDevRemoteAccessRsshRemoteBind(context);
|
||||
if (!remoteBind.isEmpty()) {
|
||||
r.itemPass("rssh-remote-bind", remoteBind);
|
||||
} else if (RemoteAccessStatusStore.STATE_SUCCESS.equals(tunnelState)
|
||||
|| RemoteAccessStatusStore.STATE_CONNECTING.equals(tunnelState)) {
|
||||
r.item(DevNetworkSelfTestReport.Level.WARN, "rssh-remote-bind", "not stored (reconnect session)");
|
||||
}
|
||||
String localForward = AppPreferences.getDevRemoteAccessRsshLocalForward(context);
|
||||
if (!localForward.isEmpty()) {
|
||||
r.itemPass("rssh-local-forward", localForward);
|
||||
}
|
||||
r.itemPass(
|
||||
"wan-egress-via-vpn",
|
||||
"no (RSSH — reverse SSH only, no device routing)");
|
||||
}
|
||||
|
||||
private static void appendTraffic(DevNetworkSelfTestReport r, Context context) {
|
||||
int uid = Process.myUid();
|
||||
long rx = TrafficStats.getUidRxBytes(uid);
|
||||
|
||||
@@ -219,6 +219,19 @@ public final class RemoteAccessService extends Service {
|
||||
"connect without credentials", sessionId);
|
||||
return;
|
||||
}
|
||||
AppPreferences.clearDevRemoteAccessTunnelMeta(this);
|
||||
if ("wireguard".equals(tunnel)) {
|
||||
AppPreferences.setDevRemoteAccessVpnAddress(
|
||||
this, creds.optString("interface_address", ""));
|
||||
} else if ("ssh_reverse".equals(tunnel)) {
|
||||
AppPreferences.setDevRemoteAccessRsshTunnelMeta(
|
||||
this,
|
||||
creds.optString("bastion_host", ""),
|
||||
creds.optInt("bastion_port", 443),
|
||||
creds.optInt("remote_bind_port", 0),
|
||||
creds.optString("local_forward_host", "127.0.0.1"),
|
||||
creds.optInt("local_forward_port", 8022));
|
||||
}
|
||||
if ("wireguard".equals(tunnel)) {
|
||||
String wgConfig = WireGuardConfigBuilder.fromConnectCredentials(this, creds);
|
||||
if (wgConfig.isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user