Leak between private space and per-app split tunneling · Issue #1153 · MatsuriDayo/NekoBoxForAndroid · GitHub
Skip to content

Leak between private space and per-app split tunneling #1153

Open

Description

@ski0x0

Leak between private space and per-app split tunneling

The government has ordered Russian tech companies to spy on users and detect VPNs. Yandex discovered and is actively exploiting this vulnerability. This vulnerability puts all private servers of users at risk, potentially ending up on a blacklist.

More information here https://github.com/runetfreedom/per-app-split-bypass-poc

Almost all mobile clients based on xray/sing-box run a local socks5 proxy without authentication.

At the same time, per-app split tunneling is implemented using VpnService, which redirects traffic to tun2socks (or something similar). But if there is spyware on the user's device (for example, as part of a government application), nothing prevents it from connecting directly to this socks5 proxy, bypassing VpnService, and discovering the user's external IP address.

Activity

  1. neur0ner25 commented on Apr 7, 2026

    @neur0ner25

    +1

  2. Fa1ry7a1l commented on Apr 7, 2026

    @Fa1ry7a1l
  3. itsTPM commented on Apr 7, 2026

    @itsTPM

    I see two solutions that may work:

    1. Disable the local SOCKS proxy entirely - sing-box does not require a proxy for the tun inbound.
    2. Require authorization for the proxy - either with auth data generated by the app or set by the user.

    With either option, we may enforce this behavior entirely or give a toggle to the user. I think we should prefer the behavior that prevents leaking by default but give a toggle to the user if they know what they are doing.

  4. nyan-ame commented on Apr 7, 2026

    @nyan-ame

    +1

  5. maxi08pa commented on Apr 7, 2026

    @maxi08pa

    +!!!

  6. priZrak7495 commented on Apr 7, 2026

    @priZrak7495

    +1

  7. sou1jacker commented on Apr 7, 2026

    @sou1jacker

    At present, this issue is resolved by a simple routing rule, which blocks all traffic destined for the SOCKS proxy.

    {
      "inbound": ["mixed-in", "socks-in"],
      "outbound": "block"
    }
  8. priZrak7495 commented on Apr 7, 2026

    @priZrak7495

    At present, this issue is resolved by a simple routing rule, which blocks all traffic destined for the SOCKS proxy.

    {
    "inbound": ["mixed-in", "socks-in"],
    "outbound": "block"
    }

    Where should this be written?

  9. sou1jacker commented on Apr 7, 2026

    @sou1jacker

    At present, this issue is resolved by a simple routing rule, which blocks all traffic destined for the SOCKS proxy.
    {
    "inbound": ["mixed-in", "socks-in"],
    "outbound": "block"
    }

    Where should this be written?

    Routes - Create new - Custom configuration
    RU: Маршруты - Создать новый - Пользовательская конфигурация

  10. YegorKehl commented on Apr 7, 2026

    @YegorKehl

    At present, this issue is resolved by a simple routing rule, which blocks all traffic destined for the SOCKS proxy.

    {
    "inbound": ["mixed-in", "socks-in"],
    "outbound": "block"
    }

    Thanks, this prevents leakage of outbound IP, but doesn't prevent observing of VPN app presence on device. For example Yandex.Market app still see and warning about this.

  11. sou1jacker commented on Apr 7, 2026

    @sou1jacker

    It’s impossible to hide the fact that you’re using a VPN without root access. And in my opinion, there’s no need to anyway.
    The main thing is that the IP address of the exit node isn’t leaked (when using per-app split tunnelling)

    Incidentally, there are a few issues with this on xray kernels. I had to create a fork to patch this vulnerability.

  12. YegorKehl commented on Apr 7, 2026

    @YegorKehl

    It’s impossible to hide the fact that you’re using a VPN without root access.

    Is there no other way to implement per-app split tunneling on non-rooted devices other than through the tap2socks?

    And in my opinion, there’s no need to anyway.

    We'll see in a month or two when Russian apps stop allowing users to access their services with the socks5 port detected on the device.

  13. sou1jacker commented on Apr 7, 2026

    @sou1jacker

    It’s impossible to hide the fact that you’re using a VPN without root access.

    Is there no other way to implement per-app split tunneling on non-rooted devices other than through the tap2socks?

    And in my opinion, there’s no need to anyway.

    We'll see in a month or two when Russian apps stop allowing users to access their services with the socks5 port detected on the device.

    The problem isn’t even the proxy, which can be disabled, but the interface detection (tun0, wg0, etc.), which cannot be hidden without root access.
    As a temporary solution, you could use a "system clone" (essentially creating another system with its own apps) on BBK smartphones (Oppo, 1+, Realme, Vivo).

    It’s also worth remembering that many companies use legitimate VPNs to access their remote resources. So the scenario you’ve described seems unfeasible.
    Even if Im wrong and such apps do appear, they can always be patched.

  14. Samamy commented on Apr 7, 2026

    @Samamy

    I think find another "fix".

    • NekoBox > Settings > Service Mode > VPN
    • NekoBox > Settings > Apps VPN mode - Disable
    • The order of the rules is very important; the higher up a rule is, the sooner it applies!!!
    • NekoBox > Route > Create Route > Name "proxy", Chose application, Outbound - "proxy"
    • NekoBox > Route > Create Route > Name "direct", Chose application, Outbound - "bypass"
    • Android, in system menu > Setting > Network and Internet(for me) > VPN > NekoBox > Configure > enable "Always-on VPN", enable "Block connection without VPN"
    • Now all connection, access via NekoBox, add application to Route "direct" if need direct access
    • Add application to Route "proxy" if need use proxy profile

    Думаю нашел еще одно решение.

    • NekoBox > Настройки > Сервисный режим > VPN
    • NekoBox > Настройки > Режим VPN для приложений - Выключить
    • Последовательность правил очень важна, чем выше, тем раньше оно применяется !!!
    • NekoBox > Маршруты > Создать Маршруты > Имя "proxy", Выбрать приложения, Outbound - "Прокси"
    • NekoBox > Маршруты > Создать Маршруты > Имя "direct", Выбрать приложения, Оutbound - "Обход"
    • Android системе > Настройки > Мобильная сеть(у меня) > VPN > NekoBox > Настройки > Включить "Постоянная VPN сеть", включить "Блокировать соединения без VPN"
    • Теперь все соединения в сеть управляются через NekoBox, добавляя в правило "direct" приложения ходят напрямую.
    • Добавляя приложение в правило "proxy" будет ходить через vpn/proxy
      Еще раз повторю последовательность правил важна, чем оно выше тем раньше применяется !
  15. thealien commented on Apr 7, 2026

    @thealien

    Check this, add 3 rules to routing:

    1. Block socks5 (like in prev. messages from sou1jacker)
    {
      "inbound": ["mixed-in", "socks-in"],
      "outbound": "block"
    }
    
    1. Allowed apps + outbound=proxy (just duplicate apps list like in settings)
    2. Block all other
    {
      "ip_cidr": ["0.0.0.0/0", "::/0"],
      "outbound": "block"
    }
    

    before these rules exec
    curl 2ip.io --interface tun0 returns vpn's ip

    but with rules it return error like
    curl: (7) Failed to connect to 2ip.io port 80 after 133 ms: Could not connect to server

    (tested in ternux and ofcourse termux not whitelisted)) )

  16. 26 remaining items

  17. IdiotEbrilo commented on Apr 11, 2026

    @IdiotEbrilo

    @Gpalm1 why?.. The point is that we proxy only specific apps and specific domains, all other domains are beind processed with the last rule, which is direct outbound. So no matter what ip checker is used - if it's url is not in the proxying list, it will go through the last direct rule. At least, it works for me this way on my device (realme gt 7 pro)

  18. IdiotEbrilo commented on Apr 11, 2026

    @IdiotEbrilo

    And i actually got another challenge - attempting to deal with naïve proxy. It keeps socks5 open no matter what i do, guess it just works that way, but not sure actually. Will be much grateful if someone points me how to figure it out.

    It happens with naïve proxy only:

    Image

    And that telegram dc being accessed via socks is real pain in my butt and potential leak of vpn external ip (while vless connections are totally fine, as i posted some messages above), but i have no idea how to fix it

  19. thealien commented on Apr 11, 2026

    @thealien

    A you about line 1 about socks or last line about mtproto?
    I think both things in report in checker.
    I have the same "warns", but:

    1. Socks5 blocked in routing an any connection closed (can be check by curl or any other tool)
    2. Checker says it found Mtproto on ... port with spcks5.. really?.. looks like stupidity.

    Ok, try to use socks5 proxy (opened by NekoBox but blocked by routing rule) in telegram - i thing tg will not work.
    But checker says it saw mtproto!)))

    Ru: я думаю, это какая-то глупость в отчёте чекера. Про сокс написано, что открыто, тут правильно, но коннекта не будет, если проверять руками. А последний пункт про мтпрото да ещё на порте, который выше обозначается как найденный сокс5 - тут звучит как бред.

  20. IdiotEbrilo commented on Apr 11, 2026

    @IdiotEbrilo

    @thealien guess i should ask rknrardener devs about it. I agree, it looks pretty strange, maybe it reports that tg is "accessible" in case it finds socks port no matter can it connect to it or not

  21. IdiotEbrilo commented on Apr 11, 2026

    @IdiotEbrilo

    @thealien checked a bit, and got confused. The first curl was executed with vless up (got rejected), the second with naïve (got connected).

    Image

    Funny thing is in both cases the first rule in routing chain was this one:

    {
      "inbound": [
        "mixed-in",
        "socks-in"
      ],
      "outbound": "block"
    }
    

    Upd: 2080 gets inaccessible if the only inbound available is tun, which is done by that your config:

    {
      "inbounds": [
        {
          "domain_strategy": "",
          "endpoint_independent_nat": true,
          "inet4_address": [
            "172.19.0.1/28"
          ],
          "mtu": 9000,
          "sniff": true,
          "stack": "mixed",
          "tag": "tun-in",
          "type": "tun"
        }
      ]
    }
    

    But naïve fails with it

    Also keep in mind that if you remove that tun config and leave socks blocking rule active you'll be able to curl 127.0.0.1:2080

  22. DarkSide-DarkSide commented on Apr 12, 2026

    @DarkSide-DarkSide

    @thealien Несколько вопросов, первое:
    Я так понимаю в конфигах на правилах нет нужды прописывать аутбаунд? Потому что если проверять и сравнивать то выходит что аутбаунд в самом некобоксе так же справляется с задачей, то есть вместо:
    { "inbound": ["mixed-in", "socks-in"], "outbound": "block" }
    Достаточно написать:
    { "inbound": ["mixed-in", "socks-in"] }
    И в самом приложении в аутбаунд выбрать "Блокировать", результат выходит я так понимаю тот же, второе по поводу последнего правила:
    { "ip_cidr": ["0.0.0.0/0", "::/0"], "outbound": "block" }
    Что именно оно делает? Всё остальное блокирует либо пускает в обход прокси если написать "direct"? (К слову опять же в результате проверки я так понял что "block" будет стоять выше в приоритете, то есть если прописать "block" и в приложении выбрать "direct" или прописать "direct" и выбрать "block" то всё равно будет "block")
    Если да и всё остальное должно как-то пускаться, то не лучше в целом убрать это правило и просто написать:
    { "outbound": "direct" }
    В таком конфиге некобокс вроде как точно пропускает всё остальное в обход прокси и проблемы что в браузере всё проксируется не возникает и тогда уже если нужно можно делать правило чтобы проксировались только определённые домены.
    Не считаю что разбираюсь в теме, просто спрашиваю на основе того что я пытался делать пока бился над решением. В любом случае всё заработало (вместе с решением @s809) и за предложенное решение спасибо!

  23. thealien commented on Apr 12, 2026

    @thealien

    Достаточно написать

    Всё верно.
    Я когда искал инфу о том,что писать в когфигах рулов, были примеры с условием + аутбаунд. Так и пошло в начале и в примерах.
    Ну и вообще очевидно, что кастом конфиг просто сливается с рулом, будучи в приоритете (т.е. аутбаунд в json конфиге рула перезапишет то, что выбрали в ui рула).

    И да, логичнее и очевиднее в конфиге оставить только те условия, которые нельзя и выбрать в ui, а тот же аутбаунд юзать в ui, чтобы не было путаницы и недопонимания.

    А ещё, как я дошел до ip_cidr.
    Я хотел последним правилом блочить все, но если создать правило и в ui выбрать outboud block, то ничего не происходило. Как мне сказал гпт - это из-за того, что условий нет и в финальный конфиг правило просто не попадает (но честно - финальный конфиг я не перепроверял).
    И в итоге спросил у гпт, как сделать, чтобы рул блочил весь трафик. Получил пример кастом конфига с ip cidr, который заработал. И я ним делился в исходном виде :)

    Но очевидно, что достичь цель можно и другими настройками и более кратко и оптимизировано (о чем вы выше и написали).

    Что именно оно делает?

    Мне гпт говорит такое (и поведение вроде получаю описанное, нужное), цитата

    Если в роутинге NekoBox указать:
    JSON
    {
      "ip_cidr": ["0.0.0.0/0", "::/0"],
      "outbound": "block"
    }
    ты получишь полную блокировку всего IP-трафика.
    Почему
    0.0.0.0/0 → охватывает все IPv4 адреса
    ::/0 → охватывает все IPv6 адреса
    То есть правило матчится на любое соединение, у которого известен целевой IP.
    Фактически: 👉 любое подключение, которое дошло до стадии определения IP, будет отправлено в outbound block.
    
  24. thealien commented on Apr 12, 2026

    @thealien

    About telnet to socks5.
    It is success because port opened and telnet can connect.
    But actually request will be blocked (i mean real request via socks5).

    Check should be like curl --proxy socks5h://127.0.0.1:2080 2ip.io
    (in termux for example)

    But!
    It doesn't matter, because U just delete socks5 inbound and now it doesn't exist at all and no problem here.

  25. neur0ner25 commented on Apr 12, 2026

    @neur0ner25

    And i actually got another challenge - attempting to deal with naïve proxy. It keeps socks5 open no matter what i do, guess it just works that way, but not sure actually. Will be much grateful if someone points me how to figure it out.

    It happens with naïve proxy only:

    Image

    And that telegram dc being accessed via socks is real pain in my butt and potential leak of vpn external ip (while vless connections are totally fine, as i posted some messages above), but i have no idea how to fix it

    Just read this issues.

    Image

    Image

  26. Viyorez commented on Apr 12, 2026

    @Viyorez

    Viyorez попробуй добавить самое нижнее правило (в конец всех правил) такое: src ip (source) - 0.0.0.0/0, ::/0 -> Обход каким-то чудом у меня заработало

    это НЕ в конфиг!! в графич интерфейс

    Try adding a bottom-most rule like this: src ip (source) - 0.0.0.0/0, ::/0 -> direct Somehow it worked for me.

    and-rassk не помогло, термукс все также выдает айпишник впна, хардединг детектит. может нам списаться где нить? ибо тут не удобно

    Image

  27. Viyorez commented on Apr 12, 2026

    @Viyorez

    Самый хардкорный способ понять, что не так и почему отличается - сравнить итоговые json конфиги, которые видны в логах (журнал) при запуске соединения.

    Например через https://jsondiff.com (либо другой сервис для сравнивания json структур).

    (но конечно это приемлемо для конфигов родственных программ, тут конечно форк, но мало ли, что под капотом в логике изменено)

    P.s. а общие настройки точно одинаковые? Я про список аппов в главных настройках (не роутинге), там одинаково и режим одинаковый?

    список приложений тот же, да, эскортом пользовался. правило те же.

    поподробнее про джсон конфиги, я не особо понял что сделать и как он работает

  28. alexeygritsenko commented on Apr 12, 2026

    @alexeygritsenko

    Этот вопрос лучше адресовать разработчикам самого ядра (sing-box), так как NekoBox - это только графическая оболочка, и добавление новых протоколов зависит от того, появятся ли они в самом ядре.

    Давайте не будем уводить обсуждение в сторону.

    Простите, а разве sing-box не поддерживает xhttp? Как тогда на винде у меня на нем xhttp ключ работает?

    а как им написать, подскажите пожалуйста)

    Ну если вы уверены что он не поддерживает xhttp, тогда у них есть официальный репозиторий тут https://github.com/SagerNet/sing-box

  29. neur0ner25 commented on Apr 12, 2026

    @neur0ner25

    Если вы настроили работу приложений не через прокси а выбрали российские приложения в обход то правило 0.0.0.0/0 вам не нужно.

  30. IdiotEbrilo commented on Apr 14, 2026

    @IdiotEbrilo

    Добавил отключалку для mixed-in socks5 с блокировкой неиспользуемых контролов, и автогенерируемые креды для naive и подобных, т.к. сейчас они полностью открыты, и через них виден реальный внешний IP впн. С этим теперь не требуется делать отдельные правила для отключения mixed-in и кастомные джейсоны

    Кому нужно - в репе собранный и подписанный релиз

    ПР тут - #1166

    Отдельная благодарность @dv4mp1r3 и @x64BitWorm

    UPD: немного поправил интерфейс для большей логичности

  31. acanthis commented on Apr 17, 2026

    @acanthis

    @thealien Подскажите, а приложения из главных настроек (режим VPN для приложений) нужно убирать? Я создал правило с приложениями, убрал их из настроек и они перестали работать(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions