hiddify / hiddify-app

Multi-platform auto-proxy client, supporting Sing-box, X-ray, TUIC, Hysteria, Reality, Trojan, SSH etc. It’s an open-source, secure and ad-free.
https://hiddify.com
Other
17.47k stars 1.58k forks source link

VPN Connection Dies After Periods of Inactivity #458

Open AshkanRafiee opened 9 months ago

AshkanRafiee commented 9 months ago

Search first

What Happened?

The app's VPN connection automatically dies after a few minutes of inactivity. Users must manually disable and re-enable the VPN to restore connectivity. This issue affects the user experience by requiring frequent manual intervention to maintain a stable VPN connection.

Reproduce the Bug

  1. Open the app and connect to the VPN (WARP Method).
  2. Leave the VPN connected without transferring any data or using the device for a few minutes.
  3. Observe that the VPN connection dies, indicated by a loss of internet connectivity.

Expected Behavior

The VPN connection should remain active and stable, even during periods of inactivity, until the user decides to disconnect manually.

Version

v0.15.4

Platform/OS

Android

Additional Context

To address the issue of the VPN connection dying after minutes of not using it, you might need to implement or adjust several aspects of your application. Here are some suggestions based on the potential areas identified:

1. Enhancing VPN Service Persistence

Foreground Service: Ensure your VPNService runs as a foreground service with a persistent notification. This makes it less likely for the system to kill your service due to inactivity or when freeing up resources. In VPNService.kt, ensure you're calling startForeground() with a proper notification to keep the service running in the foreground.

val notification = Notification.Builder(this, CHANNEL_ID) // Customize this startForeground(NOTIF_ID, notification.build())

Service Restart: Implement logic to automatically restart the VPN service if it gets disconnected or killed by the system. This can be done by listening for system broadcast actions indicating that your app's process has been killed and then restarting the service.

2. Improving Network Monitoring and Handling

Reliable Network Change Detection: Ensure that DefaultNetworkMonitor.kt accurately detects network changes and appropriately handles them. Consider registering for network change callbacks using ConnectivityManager.NetworkCallback to get more reliable network change events.

Reconnection Strategy: Implement a reconnection strategy in case of network changes or when the VPN connection drops. This could involve automatically attempting to re-establish the VPN connection upon detecting network availability.

3. Service Binding Robustness

Persistent Connection: In ServiceBinder.kt and related service connection components, ensure that the app maintains a persistent connection to the VPN service. Implement re-binding logic in case the service connection is lost.

4. Adapting to Power Management

Whitelisting from Battery Optimizations: Prompt users to whitelist your app from battery optimizations. This can help prevent the system from stopping your VPN service. You can prompt users with an intent to the battery optimization settings:

val intent = Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) startActivity(intent)

5. Settings and Configuration Management

Dynamic Configuration: Ensure that the app dynamically adjusts its settings based on current conditions. For example, if Settings.kt indicates that a certain proxy mode is less stable under certain network conditions, provide logic to switch modes or adjust settings for better stability.

Code Changes

Here are some code snippets to illustrate the changes:

Foreground Service Notification Setup in VPNService.kt

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    // Create a notification channel for Android O and above
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val serviceChannel = NotificationChannel(
            CHANNEL_ID,
            "VPN Service Channel",
            NotificationManager.IMPORTANCE_DEFAULT
        )
        val manager = getSystemService(NotificationManager::class.java)
        manager.createNotificationChannel(serviceChannel)
    }

    val notificationIntent = Intent(this, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(
        this,
        0, notificationIntent, 0
    )

    val notification = NotificationCompat.Builder(this, CHANNEL_ID)
        .setContentTitle("VPN Service Running")
        .setContentText("Tap to return to the app.")
        .setSmallIcon(R.drawable.ic_vpn)
        .setContentIntent(pendingIntent)
        .build()

    startForeground(1, notification)

    return super.onStartCommand(intent, flags, startId)
}

Network Change Handling in DefaultNetworkMonitor.kt

fun registerNetworkCallback() {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkRequest = NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .build()
    connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}

private val networkCallback = object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
        // Handle network available
    }

    override fun onLost(network: Network) {
        super.onLost(network)
        // Handle network lost, attempt to reconnect or adjust settings
    }
}

Implementing these changes should help in making the VPN service more resilient to disconnections and system interventions.

Relevant log output

No response

Are you willing to submit a PR? If you know how to fix the bug.

TheMarwin commented 5 months ago

The problem still exists.. I hope the necessary follow-up will be done next update

alisamie97 commented 3 months ago

I faced the same issue using Hiddify Next on Ubuntu. At first, I thought it was related to the power management of my LapTop that puts my WiFi network adapter into standby mode, and then relatively the VPN goes dead, but even after turning off the power management on my WiFi network adapter, the VPN issue remains. I have to disconnect the VPN, disconnect my WiFi, reconnect the WiFi, and reconnect the VPN every time. It's strange because when I'm listening to Spotify it gets disconnected too, it should be downloading some data to play the music, so it's not related to idling, right?