[GH-ISSUE #2452] [Android] Per-app split tunneling bypass via unauthenticated local SOCKS5 listener on 127.0.0.1:10808 #1095

Open
opened 2026-10-13 20:34:06 +00:00 by bsakaguchi · 7 comments
Owner

Originally created by @sandvagg on GitHub (Apr 7, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2452

Summary

When AmneziaVPN is active on Android (X-ray profile), it exposes a SOCKS5 listener on 127.0.0.1:10808 that accepts unauthenticated connections. Because Android loopback is shared across apps, another application can connect to this listener. As a result, an app excluded from VPN routing via per-app split tunneling can still send traffic through the VPN by using the local SOCKS5 proxy. This behavior may unintentionally weaken the isolation guarantees of split tunneling and could increase the detectability of VPN usage in environments where app-level network monitoring is employed.

Environment

  • App version: 4.8.14.5
  • Android version: 15
  • Device: Samsung Galaxy S25
  • Protocol used: Xray
  • Split tunneling: Enabled (Termux excluded from VPN)

To Reproduce
Steps to reproduce the behavior:

  1. Install AmneziaVPN and configure a working connection.
  2. Enable Per-app VPN (split tunneling) and exclude Termux (or any test app with INTERNET permission).
  3. Connect to the VPN.
  4. In Termux, run:
    # Verify that direct traffic is not using the VPN
    curl -s https://ifconfig.me/ip
    # Expected: your real public IP
    
    # Check whether the localhost proxy is reachable
    nc -vz -w1 127.0.0.1 10808
    # Observed: connection succeeds only while VPN is active
    
    # Send traffic through the local SOCKS5 proxy from excluded app
    curl -s --socks5-hostname 127.0.0.1:10808 --connect-timeout 10 https://ifconfig.me/ip
    # Observed: VPN exit IP
    
    

Observed behavior

  • Port 127.0.0.1:10808 is open only when VPN is active.
  • The listener accepts SOCKS5 connections without authentication.
  • An app excluded from VPN routing can still reach the VPN exit by using this localhost proxy.

Expected Behavior
Applications excluded from VPN routing should not be able to send traffic through the VPN tunnel via a localhost proxy, unless this behavior is explicitly documented and user-controlled. If a local listener is required for internal purposes, access should be restricted to the app's own components.

Security Impact
If the proxy accepts unauthenticated connections and forwards traffic through the VPN tunnel:

  • User-configured per-app routing policies can be bypassed by any app with INTERNET permission.
  • Traffic that the user explicitly intended to route directly may leak through the VPN (or vice versa).
  • The presence of an open, unauthenticated localhost proxy may serve as a detectable signal of VPN usage to monitoring applications.

Operational relevance
In environments where applications or platforms monitor network behavior for signs of VPN usage, this issue may increase the detectability of VPN use. Because an app excluded from VPN routing can still access the VPN tunnel via localhost, it can both infer that the VPN is active and send probe traffic through the tunnel. This may also aid enumeration of VPN egress IPs and contribute to blocking of VPN endpoints. This consideration is particularly relevant given recent reports of app-level VPN detection guidelines being distributed to IT platforms [1][2].

Suggested Mitigations

  • Require SOCKS5 authentication (username/password) for the localhost listener, if the feature is intended for external use.
  • If the listener is only needed for internal IPC, consider using a private communication channel (e.g., Unix domain socket with restrictive permissions, or Android Binder with UID verification) instead of a shared TCP port on loopback.
  • Document the behavior and its implications in the app's settings or security notes, so users can make informed decisions about split tunneling usage.

References

  1. Technical analysis of localhost proxy bypass in mobile VPN clients (Russian):
    https://habr.com/ru/articles/1020080/

  2. Community discussion: MinDigital guidelines for VPN detection (Russian):
    https://habr.com/ru/news/1019646/
    Summary: Russian Ministry of Digital Development issued guidelines for IT platforms to detect VPN usage via app-level network monitoring (ConnectivityManager/NetworkCapabilities APIs on Android). The report highlights split tunneling as a known challenge for detection, making proper isolation of per-app routing critically important.

Originally created by @sandvagg on GitHub (Apr 7, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2452 **Summary** When AmneziaVPN is active on Android (X-ray profile), it exposes a SOCKS5 listener on 127.0.0.1:10808 that accepts unauthenticated connections. Because Android loopback is shared across apps, another application can connect to this listener. As a result, an app excluded from VPN routing via per-app split tunneling can still send traffic through the VPN by using the local SOCKS5 proxy. This behavior may unintentionally weaken the isolation guarantees of split tunneling and could increase the detectability of VPN usage in environments where app-level network monitoring is employed. **Environment** - **App version**: 4.8.14.5 - **Android version**: 15 - **Device**: Samsung Galaxy S25 - **Protocol used**: Xray - **Split tunneling**: Enabled (Termux excluded from VPN) **To Reproduce** Steps to reproduce the behavior: 1. Install AmneziaVPN and configure a working connection. 2. Enable **Per-app VPN** (split tunneling) and **exclude Termux** (or any test app with `INTERNET` permission). 3. Connect to the VPN. 4. In Termux, run: ```bash # Verify that direct traffic is not using the VPN curl -s https://ifconfig.me/ip # Expected: your real public IP # Check whether the localhost proxy is reachable nc -vz -w1 127.0.0.1 10808 # Observed: connection succeeds only while VPN is active # Send traffic through the local SOCKS5 proxy from excluded app curl -s --socks5-hostname 127.0.0.1:10808 --connect-timeout 10 https://ifconfig.me/ip # Observed: VPN exit IP **Observed behavior** - Port `127.0.0.1:10808` is open **only when VPN is active**. - The listener accepts SOCKS5 connections without authentication. - An app excluded from VPN routing can still reach the VPN exit by using this localhost proxy. **Expected Behavior** Applications excluded from VPN routing should not be able to send traffic through the VPN tunnel via a localhost proxy, unless this behavior is explicitly documented and user-controlled. If a local listener is required for internal purposes, access should be restricted to the app's own components. **Security Impact** If the proxy accepts unauthenticated connections and forwards traffic through the VPN tunnel: - User-configured per-app routing policies can be bypassed by any app with INTERNET permission. - Traffic that the user explicitly intended to route directly may leak through the VPN (or vice versa). - The presence of an open, unauthenticated localhost proxy may serve as a detectable signal of VPN usage to monitoring applications. **Operational relevance** In environments where applications or platforms monitor network behavior for signs of VPN usage, this issue may increase the detectability of VPN use. Because an app excluded from VPN routing can still access the VPN tunnel via localhost, it can both infer that the VPN is active and send probe traffic through the tunnel. This may also aid enumeration of VPN egress IPs and contribute to blocking of VPN endpoints. This consideration is particularly relevant given recent reports of app-level VPN detection guidelines being distributed to IT platforms [1][2]. **Suggested Mitigations** - Require SOCKS5 authentication (username/password) for the localhost listener, if the feature is intended for external use. - If the listener is only needed for internal IPC, consider using a private communication channel (e.g., Unix domain socket with restrictive permissions, or Android Binder with UID verification) instead of a shared TCP port on loopback. - Document the behavior and its implications in the app's settings or security notes, so users can make informed decisions about split tunneling usage. **References** 1. **Technical analysis of localhost proxy bypass in mobile VPN clients** (Russian): https://habr.com/ru/articles/1020080/ 2. **Community discussion: MinDigital guidelines for VPN detection** (Russian): https://habr.com/ru/news/1019646/ *Summary: Russian Ministry of Digital Development issued guidelines for IT platforms to detect VPN usage via app-level network monitoring (ConnectivityManager/NetworkCapabilities APIs on Android). The report highlights split tunneling as a known challenge for detection, making proper isolation of per-app routing critically important.*
Author
Owner

@Gerk17 commented on GitHub (Apr 7, 2026):

I'm working on a fix and suggest the following quick solution:
SOCKS5 password auth with a random secret per-process. I'll leave the Unix socket as follow-up due to hev-socks5-tunnel limitations. Ok?

<!-- gh-comment-id:4202187757 --> @Gerk17 commented on GitHub (Apr 7, 2026): I'm working on a fix and suggest the following quick solution: SOCKS5 password auth with a random secret per-process. I'll leave the Unix socket as follow-up due to hev-socks5-tunnel limitations. Ok?
Author
Owner

@Gerk17 commented on GitHub (Apr 8, 2026):

Submitted a fix as #2453. Approach: enable SOCKS5 username/password auth on the local Xray inbound, with random per-process credentials, and update the desktop/Android/iOS tun2socks consumers to authenticate with the same secret. The bypass is closed end-to-end. Moving the IPC off loopback TCP entirely (e.g. Unix domain socket) is left as a follow-up since it requires upstream changes in hev-socks5-tunnel. Happy to take feedback.

<!-- gh-comment-id:4204121154 --> @Gerk17 commented on GitHub (Apr 8, 2026): Submitted a fix as #2453. Approach: enable SOCKS5 username/password auth on the local Xray inbound, with random per-process credentials, and update the desktop/Android/iOS tun2socks consumers to authenticate with the same secret. The bypass is closed end-to-end. Moving the IPC off loopback TCP entirely (e.g. Unix domain socket) is left as a follow-up since it requires upstream changes in hev-socks5-tunnel. Happy to take feedback.
Author
Owner

@hurrycane1 commented on GitHub (Apr 8, 2026):

Hello!
Will this solve the problem of bypassing by explicitly using the interface? For example, in Termux:
curl -s https://ifconfig.me/ip --interface tun0

<!-- gh-comment-id:4206219661 --> @hurrycane1 commented on GitHub (Apr 8, 2026): Hello! Will this solve the problem of bypassing by explicitly using the interface? For example, in Termux: `curl -s https://ifconfig.me/ip --interface tun0`
Author
Owner

@Fast-and-Pythonic commented on GitHub (Apr 8, 2026):

Hello! Will this solve the problem of bypassing by explicitly using the interface? For example, in Termux: curl -s https://ifconfig.me/ip --interface tun0

Yes. This is a serious problem. Now it is easy to detect the ip of the server. And block this server.

<!-- gh-comment-id:4207159676 --> @Fast-and-Pythonic commented on GitHub (Apr 8, 2026): > Hello! Will this solve the problem of bypassing by explicitly using the interface? For example, in Termux: `curl -s https://ifconfig.me/ip --interface tun0` Yes. This is a serious problem. Now it is easy to detect the ip of the server. And block this server.
Author
Owner

@Fast-and-Pythonic commented on GitHub (Apr 8, 2026):

Amnezia wg2 4.8.14.5 also has this issue.
Poco f7
Android 16
Hyper OS 3.0.6.0
Traffic splitting is also enabled. Traffic splitting is also enabled. Termux is not included in the tunneling list. Its traffic does not go through the tunnel. However, Termux can see the server's IP address using the command curl -s https://ifconfig.me/ip --interface tun0.

<!-- gh-comment-id:4207228932 --> @Fast-and-Pythonic commented on GitHub (Apr 8, 2026): Amnezia wg2 4.8.14.5 also has this issue. Poco f7 Android 16 Hyper OS 3.0.6.0 Traffic splitting is also enabled. Traffic splitting is also enabled. Termux is not included in the tunneling list. Its traffic does not go through the tunnel. However, Termux can see the server's IP address using the command `curl -s https://ifconfig.me/ip --interface tun0`.
Author
Owner

@R4L34 commented on GitHub (Apr 9, 2026):

Amnezia wg2 4.8.14.5 also has this issue. Poco f7 Android 16 Hyper OS 3.0.6.0 Traffic splitting is also enabled. Traffic splitting is also enabled. Termux is not included in the tunneling list. Its traffic does not go through the tunnel. However, Termux can see the server's IP address using the command curl -s https://ifconfig.me/ip --interface tun0.

I made a separate issue on this matter in case it will be closed when the pull request will be accepted. If someone fixes this, make sure to also close this one either.
https://github.com/amnezia-vpn/amnezia-client/issues/2457

<!-- gh-comment-id:4211485737 --> @R4L34 commented on GitHub (Apr 9, 2026): > Amnezia wg2 4.8.14.5 also has this issue. Poco f7 Android 16 Hyper OS 3.0.6.0 Traffic splitting is also enabled. Traffic splitting is also enabled. Termux is not included in the tunneling list. Its traffic does not go through the tunnel. However, Termux can see the server's IP address using the command `curl -s https://ifconfig.me/ip --interface tun0`. I made a separate issue on this matter in case it will be closed when the pull request will be accepted. If someone fixes this, make sure to also close this one either. https://github.com/amnezia-vpn/amnezia-client/issues/2457
Author
Owner

@egoroof commented on GitHub (Apr 14, 2026):

Will be fixed by github.com/amnezia-vpn/amnezia-client@92deee5f67 ?

<!-- gh-comment-id:4242728728 --> @egoroof commented on GitHub (Apr 14, 2026): Will be fixed by https://github.com/amnezia-vpn/amnezia-client/commit/92deee5f67e1f40bfdcf9bc8b64f8f84e29514c9 ?
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1095
No description provided.