深入 iOS 应用
这是深度导览:iPhone 和 iPad 上 URnetwork 的每个屏幕、各项设置及其出厂默认值,以及通常只装在支持工程师脑子里的疑难解答知识。从安装到连接的短路径见 iOS 入门;这一切背后的网络设计见概览。
应用的构造
一个 Xcode 项目同时产出 iOS 和 macOS 应用。在你的设备上它以两个进程运行:
- 应用(bundle
network.ur)是你看到的界面。 - 隧道扩展(
network.ur.extension)是一个由 iOS 亲自启动和监护的网络扩展(NEPacketTunnelProvider)。你的流量走的是这个进程,不是应用:它在流量离开设备之前把你手机发送的内容包进加密里(也就是"隧道")。有四样东西按配置留在隧道之外,任何守规矩的 iOS VPN 都是如此:你的本地网络(打印机、AirPlay、家用设备)、Apple 推送通知、Wi-Fi 通话之类的运营商服务,以及发往你自己附近 Apple 设备的流量。
两个进程通过本地设备 RPC 对话,所以应用重新启动后会接管仍在运行的隧道,而不是拆掉重来。这个拆分就是你把应用划走后 VPN 仍在工作的原因,也是 iOS 第一次要你批准 VPN 配置的原因:扩展是一个由系统管理的组件。那次批准是 Apple 对任何 VPN 应用的标准同意步骤。它不授予对你手机的其他任何控制,并且一直可见、可撤销,位置在设置 → 通用 → VPN 与设备管理。
应用需要 iOS 16.6 或更新版本,一切都在 github.com/urnetwork 开源。尚无独立审计覆盖协议或运营方的服务器代码,而隐私承诺正落在那里。2025 年的两项第三方评估覆盖其他层面:对 Web 应用和 API 的渗透测试,以及 Leviathan Security Group 对 Android 应用的 MASA AL2 评估,结果通过。两者都不覆盖 iOS 应用。威胁模型记录了这两项评估及其局限。
四个标签页
应用是四个标签页:连接(Connect)、账户(Account)、排行榜(Leaderboard)和支持(Support)。
连接
主屏幕,从上到下:
- 地球。 你会话的实时画面。连接后,它显示你的流量正在出网的位置:互联网在哪里看到你。你的客户端同时持有多个提供者,通常三到八个,分在并排的两个窗口里(HTTPS 偏好的质量窗口和服务其余流量的速度窗口),并把每个站点固定到其中一个。画面是有意复数的,而任何单个网站看到的仍是一个稳定地址。概览完整讲解提供者窗口。
- 连接按钮。 一键连接或断开。
- 抽屉。 按钮下方一张可折叠的面板,容纳你选定的位置、连接选项(Connect options)、实时流量图表,以及拦截广告与跟踪器(Block ads and trackers)开关。往上拖看到完整内容;已经在连接标签页时再点一次连接标签,抽屉就折回去。共享连接不在这里。它在账户 → 设置里。
点位置卡片打开可用提供者(Available providers)面板。它打开时显示你自己的设备、"最佳可用提供者"(Best available provider),以及带在线提供者实时数量的国家。在"搜索提供者"(Search providers)里输入地名,结果里会长出一个城市(Cities)区:城市级定位靠搜索到达,不靠滚动。一个位置只在有成员设备在那里在线时才会被列出,平台根据它观察到的连接推导城市,而不是相信提供者自己的申报;看起来像数据中心或 VPN 的地址会被降级而不是被信任。"最佳可用"挑选你附近得分最高的提供者;指定位置让你出现在那里(附近的出口通常最快,因为距离要付延迟的代价)。提供者是共享闲置带宽的其他成员。你的流量到达他们那里时已经是加密的,因为网页在进隧道之前就已经是 HTTPS,所以提供者像 ISP 一样看得到它承载的流量去哪里,但看不到内容,也看不到你的真实地址。
抽屉再往下是四个连接选项:
| 设置 | 默认 | 效果 | 主要代价 |
|---|---|---|---|
| 连接模式(Connection Mode) | 自动(Auto) | 自动同时运行两个提供者窗口,把每个数据包路由到合适的那个 | 网页(Web)或流媒体(Streaming)则押注单一窗口 |
| 固定 IP(Fixed IP) | 关 | 把窗口收窄到一个提供者,每个站点都看到同一个稳定地址 | 放弃复数出口 |
| 强匿名化(Strong Anonymization) | 开 | 禁止客户端到提供者的直连路径,提供者永远见不到你的真实 IP | 比直连路径慢 |
| 后量子加密(Post Quantum Encryption) | 开 | 把会话端到端密封到提供者,运营方承载的是密文 | 跳过无法密封的提供者 |
- 固定 IP 在自动之外的模式下可选。
- 关掉强匿名化就是选择直连模式:匿名化跳点退出,你的客户端直接与提供者对话,吞吐量上升,而那个提供者现在看到你的真实地址。默认保护你的身份;只有当你确实想要时,才拿它换速度。
- 拦截广告与跟踪器,在同一个抽屉里,默认关闭,打开后过滤隧道承载的一切。
- 在两个默认开启的开关之间,提供者永远不知道你是谁,运营方永远读不到你发送的内容。两条不动任何设置就都成立,所以没有任何单独一方同时握有你的身份和你的活动。
这两个开关加上出厂默认就是全景:
| 模式 | 运营方看到 | 提供者看到 | 默认与可用性 |
|---|---|---|---|
| 中继密封 | 你的账户和来源连接、你在用哪些提供者,以及密文及其时序和数据量 | 它出网的目的地和一个设备/合同 id,不含你的真实 IP | 出厂默认:后量子加密,在连接抽屉里开启 |
| 中继标准 | 你的账户和来源连接、你在用哪些提供者,以及里面的目的地和数据包字节 | 它出网的目的地和一个设备/合同 id,不含你的真实 IP | 自行选择开启:关掉后量子加密 |
| 直连 | 更少的中继参与 | 你的真实 IP及它出网的目的地 | 自行选择开启:关掉强匿名化 |
第一行读作你的默认所在。只要后量子加密开着,客户端就是失败即闭合的:与它无法建立密封会话的提供者会被跳过,而不是明文使用,所以不匹配的代价是失去那个提供者,不是失去你的机密性。把这个开关关掉,才会把你放到第二行。还没有应用显示逐连接的"密封还是没密封"结论,所以告诉你身在何处的是设置,不是会话。局限:没有任何机制验证分配给你的提供者彼此独立、且独立于运营方,运营方自己也可以运行提供者。威胁模型把这几行逐一对照具名的对手推演,包括恶意的运营方,并明说每一行在哪里失守。
自定义 DNS
连接标签页的详情之下是一整套 DNS 控制面板。DNS 是互联网的电话簿,是把 ur.io 这样的名字变成网络地址的查询,而应答这些查询的一方(解析器)看得到你访问的每个站点的名字。默认是最安全的安排:加密的 DNS over HTTPS,经隧道解析。其余都是你可以主动做的交换:
- DNS over HTTPS(远程)。 在隧道远端解析的 DoH。默认项,也最私密:解析器看到的是提供者的地址,不是你的。
- DNS over HTTPS(本地)。 直接从你的设备解析的 DoH。
- 不加密 DNS(远程/本地)。 经典的 UDP DNS,走隧道或直接从设备出发,供需要它的网络和解析器使用。
- 本地 DNS 回退(Local DNS fallback)。 在隧道启动期间并发使用一个本地解析器,握手时名字查询不至于卡住。关掉后,DNS 只经隧道解析。
解析器清单可以自己编辑(远程和本地 DoH URL、远程和本地 DNS 服务器、IPv4 和 IPv6)。另有两项便利:
- 按国家推荐。 已知最强的设置在某些国家行不通。当你连接到一个有已知推荐的地方,屏幕会说明,并提供一键"使用推荐设置"(Use recommended settings),以及一键恢复到最安全默认。
- 建议的服务器。 一份精选的远程 DNS 服务器清单,为你所连国家建议的那些以该国颜色标出。打开某一个就把它加进你的远程解析器清单。
分流规则
分流规则让你在域名和 IP 层面把特定流量路由到隧道之外,或把它固定住:
- 连接期间,屏幕显示实时路由活动。点一个域名让它走本地(绕开隧道,于是那个站点看到你的真实地址),或把它按在单个提供者上,让那个站点更长时间地看到一个稳定地址,而不是你平常的复数出口。对任何地址变化都要盘问的银行和登录页很有用。
- 规则作用于域名周围整个协同关联的网络簇,所以相关主机和 CDN 流量被一并捕获,而不是一个子域一个子域地漏。
- 规则持久保存,随时可以在同一屏幕移除。
局限:iOS 上没有按应用拆分隧道(Android 和 Windows 有)。iOS 不给 VPN 应用受支持的按应用包含/排除流量的方式,所以在 iPhone 和 iPad 上,分流规则作用于域名和 IP,不作用于应用。
共享连接
共享你的闲置带宽是账户 → 设置 → 连接里的四档共享连接(Provide mode)选择器,在你改动之前停在永不(Never):
| 模式 | 它承载什么 |
|---|---|
| 永不(Never) | 什么都不承载。默认。 |
| 自动(Auto) | 你自己连接时承载公共流量;不连接时只服务你自己的设备 |
| 始终(Always) | 公共流量,无论你连没连接 |
| 网络(Network) | 只服务你自己网络的设备,无偿。应用实现的最窄共享 |
几条基本规则。除非你在同一区打开允许经蜂窝网络共享(Allow providing on cellular network),共享只用 Wi-Fi,所以它绝不会突然动用你的流量套餐。它运行在隧道进程里,所以手机闲置时也照常工作。你承载的流量是别人的加密会话:你读不了它,它也碰不到你的设备。滥用执法在你的设备上、在流量出网的出口处运行:BitTorrent 和已知攻击模式在那里被丢弃。丢弃不记录任何东西,没有目的地、没有域名、没有内容,不过明文 BitTorrent 命中还会给运营方发一个标记,携带设备 id 和一个布尔值,仅此而已。你承载的公共流量在签名合同下计量,提供者参与 UR protocol。ur.xyz 记录了奖励的运作方式。
账户
你的身份和套餐住在这里:
- 套餐。 免费或 Pro、剩余的余额、升级路径,以及你的连接为网络承载过多少的累计数。
- 兑换余额码(Redeem Balance Code)。 一次性的流量补给,无需订阅。
- 个人资料(Profile)、设置(Settings)、钱包(Wallet)。 设置是最深的一个:恢复短语、登录方式、设备名、连接(共享连接、蜂窝许可、断网保护、屏蔽的位置(Blocked locations):你永远不想从那里出网的国家)、通知、账户删除,以及一个"使用 UR 协议"(Uses the UR Protocol)链接指向 ur.xyz,讲提供者如何获得奖励。
- 检查我的 IP(Check my IP)。 打开 ur.io/ip,从应用之外确认你的流量真的在别处出网的办法。
- 后量子身份(Post Quantum Identity)。 即下面那块面板,也是通往你所连提供者身份的路。
后量子身份面板
账户底部的面板把你设备的身份显示为一个identicon(由密钥推导的图形,比十六进制更容易用肉眼比对),下方是它的密钥哈希和客户端 id,各自点击即可复制,另有分享面板,以及一叠你当前连接的对端,点开是完整列表。它自己说明了用途:如果某个对端的密钥看起来与本地存储的那份不同,居中的运营方就不可信了。这让"运营方的失明"变得可检验。
它点名的加密就是连接抽屉里的后量子加密开关,默认开启,所以你的客户端从第一次连接起就把流量直接密封到提供者。会话是双向认证的 TLS 1.3,密钥来自 X25519MLKEM768(经典曲线与 NIST 的 ML-KEM 的混合体),所以运营方中继的是自己无法读取的字节。应答一侧是机会性的:当前所有提供者构建都启用它,所以同一个提供者可以同时服务密封与未密封的用户。你这一侧不是。只要开关开着,客户端就是失败即闭合的,与它无法建立密封会话的提供者会被跳过,而不是明文使用。还没有应用显示逐连接的"密封还是没密封"结论。身份仍是 Ed25519。
排行榜
按传输数据量排名的顶级提供者。如果你共享连接,可以出现在这里,公开或匿名,由你选择。
支持
标题是"联系我们"(Get in touch):一个反馈框、星级评分、一个可选的随反馈附上日志(Attach logs to feedback)开关,以及一个 Discord 邀请用于实时求助。套餐不在这里;升级在账户标签页。
Siri 与快捷指令
应用注册了两个 App Intent:连接 URnetwork VPN(Connect URnetwork VPN)和断开 URnetwork VPN(Disconnect URnetwork VPN)。它们出现在快捷指令应用里,可以用语音触发("嘿 Siri,连接 URnetwork"),还能串进自动化,比如离开家里 Wi-Fi 时自动连接。
不用邮箱开始,以及守住它的短语
登录屏幕上的创建即时账户(Create Instant Account)一键给你一个真实、永久的网络。不要邮箱、不要手机号、不要密码,屏幕自己也这么说。保护它的是一份恢复短语(seedphrase):平台生成的一列单词,只在创建后紧接着的那个屏幕上展示一次,之后只保留哈希形式。当场保存它。从一台尚未登录的设备回来,它是唯一的路。趁还有一台登录着的设备,设置 → 恢复短语(Settings → Seedphrase)可以铸一份新短语并作废旧的。保存之后,账户经得起重装或换新 iPhone,套餐和历史完好无损,而设备本地的身份永远做不到。这一切都不是二等待遇:设置 → 登录方式(Settings → Sign-In Methods)可以给同一个网络挂上邮箱、手机号、Apple 或 Google 登录、或一个钱包,保留你的流量余额和历史。匿名在账户里,不在支付里:应用内购买的订阅与你的 Apple 账户绑定,余额码则不与任何人绑定。
疑难解答
VPN 配置的批准
第一次连接会请求添加一个 VPN 配置。如果你拒绝了,隧道就永远起不来。在下一次连接尝试时批准它,或检查设置 → 通用 → VPN 与设备管理,URnetwork 的配置应该列在那里。
多个 VPN 配置描述文件,以及应用如何管理它们
经过反复重装和升级,iOS 可能积累不止一份 URnetwork 的 VPN 配置描述文件。应用预料到了这一点:连接时它枚举每一份配置,重置并重试启动失败的,然后转到下一份。如果已经有隧道在运行,它通过设备 RPC 接管那一条而不是重启它。坏掉的配置会被重置或移除,移除有上限所以清理不会失控,而且每次配置操作都有时限,卡死的系统守护进程拖不垮应用。这一切都是自动的。写在这里只是为了当你看到设置里的配置列表时能明白它的来由。
"Failed to load VPN profiles"(错误 12)
如果连接失败并提示 "Failed to load VPN profiles"(无法加载 VPN 配置描述文件,错误代码 12),说明系统的 VPN 偏好存储拒绝枚举配置,这个状态应用无法从内部修复。手动修复:
- 打开设置 → 通用 → VPN 与设备管理。
- 移除 URnetwork 的 VPN 配置。
- 回到应用并连接。系统会请求你批准一份全新配置,隧道干干净净地启动。
断网保护在这里如何工作
应用在账户 → 设置 → 连接里带一个断网保护(Kill switch)开关,与每个 URnetwork 应用相同的 SDK 控制项,默认关闭。打开后,客户端拒绝回落到你的本地路由,流量停住而不是泄漏到隧道之外。iOS 不给它的是系统级执行。应用没有设置 includeAllNetworks,所以如果隧道进程意外死掉,iOS 会恢复正常联网,而不是阻止流量。监护、重试和配置恢复让隧道保持健康,但应用没有要求操作系统硬性闭合失败。如果你的威胁模型要求有保证的"失败即断网",要为此另做打算。
读取隧道的日志
隧道扩展写入统一系统日志,不写文件。要观察它:
- 把设备连到 Mac,打开 Console.app。
- 选中设备,在操作菜单里启用包含信息级消息(Include Info Messages)和包含调试级消息(Include Debug Messages)。有意思的行都在这两级。
- 按
network.ur.extension子系统过滤,或搜索"URnetwork"。
睡眠与后台行为
隧道的配置是 disconnectOnSleep 关闭:VPN 跨设备睡眠保持在线,而不是每次锁屏都重新握手。配合双进程设计,它也经得起应用被划走。断开是你用按钮、Siri 或移除配置来做的事。