fix(ios): prompt for Local Network access on .local and RFC1918 connections#1039
Merged
fix(ios): prompt for Local Network access on .local and RFC1918 connections#1039
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
iOS users could not connect to MySQL/PostgreSQL/Redis servers (or SSH tunnels) on the local network using
.localhostnames or RFC1918 addresses. iOS silently dropped every outboundconnect()because the bundle was missingNSLocalNetworkUsageDescriptionandNSBonjourServices, so the system never showed the Local Network permission prompt. Reported by an iOS feedback tester forSeans-MacBook-Pro.local:22SSH tunnel; surfaced as the misleadingMySQL connection failed: Lost connection to server at 'handshake: reading initial communication packet', system error: 60(errno 60 =ETIMEDOUT).What changed
Info.plist: declareNSLocalNetworkUsageDescription(purpose string) andNSBonjourServices(_ssh._tcp,_mysql._tcp,_postgresql._tcp,_redis._tcp).LocalNetworkPermissionactor (Platform/LocalNetworkPermission.swift): briefly starts anNWBrowserfor_ssh._tcpthe first time a connection targets a local-network host (Apple DTS "Local Network Privacy FAQ" pattern; a bareconnect()does not always trigger the consent prompt forgetaddrinfo-based connections). Watches theNWBrowser.Statestream and resolves to.granted/.unavailable. Caches the resolution per process and coalesces concurrent first-time calls via an in-flightTaskso parallel SSH + DB connects do not double-prompt.connect()attempts throwLocalNetworkPermissionError.unavailableimmediately instead of waiting for the 10s TCP timeout. Wired throughSSHTunnelFactory.create()andMySQLDriver/PostgreSQLDriver/RedisDriverconnect(). Loopback (127.0.0.1,::1,localhost) and non-local hosts no-op the gate.isLocalNetworkHost(_:)covers.local, IPv4 RFC1918 (10/8, 172.16-31/12, 192.168/16), IPv4 link-local (169.254/16), IPv6 ULA (fc00::/7), and IPv6 link-local (fe80::/10).ErrorClassifier: matches the typedLocalNetworkPermissionErrordirectly with a dedicated "Local Network Access Required" title. Falls back to detectingETIMEDOUT(system error: 60,operation timed out) on SSH-enabled or local-network connections, replacing the generic "server is not responding" / misleading SSH-handshake copy with "Open Settings > Privacy & Security > Local Network and turn TablePro on."classify()so the timeout signature wins over the substring"handshake"keyword that was previously routing MySQLETIMEDOUTerrors into the SSH branch.Test plan
Run on a real iPhone (Simulator does not enforce Local Network privacy).
Some-Mac.local, tap Test Connection. iOS prompt appears with the purpose string. Allow → connect proceeds..localhost, tap Don't Allow. Error appears in under 1 second with title "Local Network Access Required" and Settings copy..localconnect (no tunnel). Driver-side gate fires for plain MySQL/Postgres/Redis toSome-Mac.local.127.0.0.1/localhostconnections never prompt.db.example.comconnects normally with no prompt.fe80::xxxx%en0triggers gate (if you have a target).swiftlint lint --strictclean on touched files (verified locally).