fix(ios): stop forcing VPN on-demand so the native toggle works#2262
fix(ios): stop forcing VPN on-demand so the native toggle works#22620443n wants to merge 1 commit into
Conversation
|
Follow-up after digging into how iOS actually handles this. I wanted to check whether users could just manage "Connect On Demand" from iOS Settings themselves, instead of the app deciding it in code. Turns out that toggle on its own doesn't do anything. Per Apple's docs and DTS, on-demand needs two things together: So "let the user set it in Settings" isn't really a workaround. The rules have to come from the app. A couple of consequences:
Doesn't change my recommendation, but it does mean an opt-in setting is the only way to keep on-demand available at all. Happy to switch to that if you'd prefer. Sources: |
|
@veto9292 sorry for the ping - mind taking a look at this one when you get a chance? it's a small iOS-only change (one file). no rush, and i'm happy to rework it into an opt-in setting instead if you'd rather keep on-demand around. |
|
@hiddify-com could you take a look when you have a sec? small one-file iOS fix. thanks! |
What's wrong
On iOS, flipping the system VPN switch off (Settings > VPN, or Control Center) while you're connected through Hiddify doesn't actually stop the tunnel. It disconnects and comes right back. So the native on/off control does nothing.
I ran into this on my own device, I haven't seen anyone else report it. But it looks like a bug rather than intended behavior, and the cause is clear, so I figured it was worth a PR.
Why
On every connect,
VPNManager.enableVPNManager()installs an on-demand rule and turns it on:NEOnDemandRuleConnectwithinterfaceTypeMatch = .anytells iOS the tunnel should always be up. Flip the native switch off and iOS re-checks the rule and reconnects straight away. The only way around it is digging into the VPN profile in Settings and turning off "Connect On Demand" by hand.The change
Stop forcing on-demand.
enableVPNManager()now clears the rules and turns it off, so the native toggle does what people expect. I set it tofalserather than just deleting the lines so the next connect also wipes any on-demand state left behind by an older build. The cleanup already indisconnect()stays, since it covers the case where someone updates the app while the tunnel is running.This is iOS only. Android has no on-demand logic (always-on VPN is an OS-level setting there), and macOS runs sing-box as a process with no NetworkExtension, so neither one is affected.
One thing I want to check with you
I'd rather raise this than decide it on my own. That on-demand rule was also acting as a reconnect / kill switch: if the tunnel drops, iOS brings it back so traffic doesn't go out in the clear. For a circumvention tool that's worth something. The catch is that it was on with no way to turn it off, and it broke the native switch.
Most tap-to-connect iOS VPN apps don't force on-demand, so I just removed it here. If you'd rather keep that safety net, I'm happy to make it a setting instead: off by default so the native switch works, on for anyone who wants the kill switch. Tell me which way you want it and I'll redo it.
Testing
I couldn't build it locally (no iOS toolchain on my machine). The change only touches
enableVPNManager()and leaves the rest of the connect/disconnect path alone.