# 深入 Linux 应用

这是深度导览：Linux 应用的每个主要界面、它控制什么、默认值是什么，以及出问题时怎么修。它假定你已经安装并连接过。如果还没有，先看[入门指南](/docs/getting-started-linux)。应用背后的网络如何运作，读[概览](/docs/overview)。

Linux 客户端是一个 GTK4/libadwaita 桌面应用，架在一个 root systemd 守护进程之上，以 AppImage 加 `.deb` 的形式发行。全部开源在 [github.com/urnetwork/linux](https://github.com/urnetwork/linux)。

## 设置一览

默认值不用配置就保护你。连接控制项在连接抽屉里；共享连接在主屏控制区；设备位置覆盖在已连接提供者地球的上方。

| 设置 | 默认 | 效果 | 主要代价 |
|---|---|---|---|
| 连接模式（Connection mode） | 自动（Auto） | 决定提供者窗口；自动同时运行质量和速度两个窗口 | 网页（Web）或流媒体（Streaming）收窄到一个窗口 |
| 强匿名化（Strong Anonymization） | 开 | 对提供者隐藏你的来源 IP | 延迟更高 |
| 后量子加密（Post Quantum Encryption） | 开 | 从应用一路加密到提供者 | 跳过无法密封的提供者 |
| 断网保护（Kill switch） | 关 | 隧道断开时停止本地回落 | 提供者失联期间没有流量 |
| 固定 IP（Fixed IP） | 关 | 一个提供者，一个出口地址 | 没有故障切换 |
| 拦截广告与跟踪器（Block ads and trackers） | 关 | 过滤广告和跟踪器流量 | 过滤可能弄坏一些网站 |
| 自定义 DNS（Custom DNS） | 经隧道的加密 DoH | DNS 保持加密并留在隧道内 | 放松它就是那笔交换 |
| 共享连接（Provide mode） | 永不 | 把闲置带宽作为出口共享给他人 | 陌生人的流量从你的 IP 出网 |
| 设备位置覆盖（Device location override） | 关 | 向 GeoClue 询问位置的应用看到你持有最久提供者的城市 | 需要 GeoClue 2.7+；影响机器上的每个应用 |
| 分流规则（域名/IP）（Split rules） | 空 | 列出的目的地走你的本地连接 | 那些流量不受保护 |

随表附送的注意事项：

- 关掉**强匿名化**就是直连模式：客户端直接与提供者对话、变快，而那个提供者随即看到你的真实地址。默认保护你的身份。要花掉它，就有意识地花。
- 断网保护还决定被安全过滤器丢弃的数据包的去向（见共享连接）：开，直接阻断；关，从你的正常路由离开。
- Linux 上没有按应用拆分隧道。分流规则是域名和 IP 级的。
- Linux 上也没有删除账户。去管理同一账户的 [ur.io](https://ur.io) Web 应用里做。

## 守护进程的拆分

两个程序，两个权限级别：

- **`urnetworkd`** 是由 `urnetworkd.service` 管理的 root 守护进程，完全没有 GUI 依赖。它内嵌 SDK 的 `DeviceLocal`，打开并拥有 `/dev/net/tun`，经 SDK 的 IO 循环泵送数据包，并应用路由和 DNS。`.deb` 或安装 tarball 负责安装它。
- **`urnetwork`** 是桌面应用，gtkmm-4.0 加 libadwaita，以你的普通用户身份运行，以 AppImage 形式发行。它持有一个 `DeviceRemote`：守护进程设备的一个视图，不是它自己的设备。

两者经两条通道对话：

1. **设备 RPC。** 应用的 `DeviceRemote` 通过 SDK 的双向认证 TLS RPC 驱动守护进程的 `DeviceLocal`，走环回 `127.0.0.1:12025`，与 Windows 应用相同的传输。
2. **控制套接字。** 位于 `/run/urnetwork/control.sock` 的 unix 域套接字承载隧道生命周期：拉起隧道、拆掉隧道、设置共享连接、报告守护进程状态。

unix 套接字才是真正的授权边界。环回 TCP 任何本地进程都够得着，这正是设备 RPC 用证书双向认证的原因。但不经过 unix 套接字，什么都启动不了隧道，而在那里由内核亲自告诉守护进程是哪个用户在请求（`SO_PEERCRED`，在解析请求的任何一个字节之前检查，并按用户 id 授权，绝不按进程 id）。目录是 `0750 root:urnetwork`，套接字是 `0660`，规则是：root，或 `urnetwork` 组的成员。

把设备 RPC 也挪到 unix 传输上是 SDK 里记录在案的后续事项；设计笔记明说了环回的局限，而不是把环回当成私有。

### 两半必须匹配

Linux 是第一个应用和隧道各自独立更新的 URnetwork 平台：AppImage 以你的身份自我更新，守护进程经 apt 更新。所以应用在连接时检查两件事：控制协议版本，以及两半携带的是完全相同的 SDK 构建。不匹配会在一开始就被拒绝，并给出有区分度的消息（*服务未运行*（service not running）、*服务已过期*（service out of date）、*应用已过期*（app out of date）、*构建不一致*（builds differ）），因为每种情况的修法不同，而一条默不作声地半工作的隧道比一个错误更糟。

### 各部分如何安装

两半都来自发布页：`.deb`、`.install.tar.gz` 和 `.AppImage`，amd64 和 arm64，glibc 下限 2.35，即 Ubuntu 22.04 或 Debian 12 及更新。没有商店上架。

软件包拥有一切有特权、需稳定的东西：位于 `/usr/lib/urnetwork/urnetworkd` 的守护进程、它的 systemd 单元、桌面条目、图标、地球绘制所用的世界地图数据、翻译，以及位于 `/usr/bin/urnetwork` 的启动器。

GUI 的 AppImage 从不由软件包安装。它住在你的主目录（`~/.local/lib/urnetwork/URnetwork.AppImage`），用户可写，所以它不用 root 就能替换自己。启动器按固定顺序搜索一组位置（`$URNETWORK_APPIMAGE`，然后 `~/.local/lib/urnetwork/`，然后 `~/Applications/`，然后 `/usr/lib/urnetwork/`，然后 `$PATH` 上的任何 `urnetwork-gui`），运行第一个命中的；一个都没装时它打印一行提示，告诉你去哪里获取。

守护进程带着它需要的特权运行，放弃它不需要的：`NoNewPrivileges`、`ProtectHome`（它没有界面，绝不该读用户主目录）、`PrivateTmp`、只有 root 可访问的状态和日志目录。它排序在 `network-pre.target` 之前，这是 VPN 需要的档位，让它能在网络起来之前动作；它是常驻运行而不是套接字激活，因为惰性启动的单元根本无法参与那个排序。

## 路由

隧道起来时，守护进程不替换你的默认路由。它像 `wg-quick` 那样出更高的价：

- 它添加经隧道接口（`urnet0`）的路由，覆盖整个 IPv4 空间，**除去**私有局域网段：10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。
- 这些路由比你现有的 `0.0.0.0/0` 默认更精确，所以不动它就赢过它。拆除就是把它们移走；你原有的路由从未被修改。
- 排除私有网段让你的打印机、NAS 和本地服务在连接期间照常工作，与 Android、Apple 和 Windows 客户端的行为一致。

NetworkManager 被告知别插手：`urnet0` 经一个 NetworkManager 配置片段和一条 udev 规则标记为不受管理，所以桌面的网络管理器从不和守护进程抢这个接口。

## DNS

隧道链路上的 DNS 经 **systemd-resolved**（`resolvectl`）设置，即 Ubuntu 桌面的标准解析器：把该链路的解析器指向网络的解析器，加上 `~.` 让查询走它，拆除时全部还原。不是每个系统都跑 resolved，所以这个行为按设计是尽力而为：

- **有 systemd-resolved：**隧道链路的 DNS 被接管并恢复。
- **没有它：**隧道照常路由，但该链路的 DNS 不被接管。你的查询继续用系统原有的解析器。

还有一个细节：DHCP 下发的搜索域（`lan`、`home`）比 `~.` 匹配更长，对该域内的名字会赢过它。如果你跑着不寻常的解析器配置，查一查你的 DNS 实际去了哪。

应用自己的**自定义 DNS**面板才是更有意义的控制。它编辑 SDK 的解析器设置，默认是经隧道解析的加密 DNS over HTTPS。它提供 DoH 和不加密解析、远程或本地、按地址族可编辑的服务器清单、一个在隧道启动期间并发本地解析器让查询不卡住的本地 DNS 回退开关、为已知最严格配置会坏掉的地区准备的区域推荐，以及一键恢复安全默认。

## 托盘

状态图标是一个 **StatusNotifierItem**，带 `com.canonical.dbusmenu` 菜单，直接经 GDBus 发声：KDE 和多数面板原生支持这个协议，GNOME 经 AppIndicator 扩展支持。没有托盘宿主时，应用不显示图标，而不是失败。

关掉窗口就藏进托盘，隧道继续运行。菜单包含连接/断开、显示和退出。退出在这里是真正的退出：它结束会话并放倒隧道。日常你要的是关闭按钮，不是退出。

## 窗口

先登录，然后是主视图：连接控制、提供者地球和抽屉。登录可以用邮箱或手机验证码、**创建账户**（Create account）、在已登录设备上生成的授权码，或经 Solana（Phantom、Solflare）或 Bittensor 的钱包签名。那里还有一个遗留的**试用访客模式**（Try Guest Mode）按钮。它在服务器上铸出一个普通的永久账户，但这个应用会把随之返回的恢复短语扔掉，所以想要日后能找回账户，就用其他路径。

**提供者地球**用应用自带的世界拓扑数据绘制。不抓取任何地图瓦片，所以你看着的这张地图不会有任何信息离开你的机器。

**连接抽屉**承载会话：

- **连接控制卡片。** 选定的位置、**自动**（Auto）、**网页**（Web）或**流媒体**（Streaming）三选一的连接模式，以及四个开关：**固定 IP**、**强匿名化**、**后量子加密**和**断网保护**。模式决定运行哪个提供者窗口：**网页**是质量窗口（同时 2–6 个提供者），**流媒体**是速度窗口（1–2 个），**自动**两个并排运行，这就是普通会话通常同时开着 3–8 个提供者而不是一个的原因。强匿名化就是禁止客户端到提供者直连路径的东西，所以没有任何提供者见得到你的真实地址；关掉它就是上表那笔直连模式的交换。后量子加密密封会话本身（见下面的身份面板）。
- **客户端与本地统计**卡片，带实时图表，各自打开一张详情面板。
- **自定义 DNS** 状态，打开上面说的解析器编辑器。
- **拦截广告与跟踪器。**
- **套餐与用量。** 你的档位、已用/待结/可用条、每日额度和推荐奖励行、**获取 UR Pro**（Get UR Pro），以及兑换余额码。
- **后量子身份面板**（见下文）。

**面板**，每一张都是真正的屏幕而不是占位：

- **位置。** SDK 的分桶区块：先是你已连接的网络对端，然后是最佳可用，然后是带实时提供者数量的国家。在搜索框输入会加上最佳匹配，外加地区、城市和设备。城市在这里是搜出来的，不是滚出来的。
- **已连接提供者。** 一个地球，下方每行一个当前在你窗口里的提供者，最早连接的在前，带客户端 id、城市/地区/国家、坐标、时长，以及就地移除。
- **合同。** 你会话背后的实时传输合同，每个对端一叠，发送和接收分开。
- **分流规则。** 把特定流量强制走你本地连接的域名和 IP 级规则，下方是正在被处理流量的实时流。
- **兑换码。** 使用余额码，附你兑换过的历史。
- **升级。** UR Pro 月付或年付，经 Stripe 结账，系统有 WebKitGTK 时内嵌在应用里，否则回落到你的浏览器，因为支付路径绝不能硬性失败。

Linux 上今天没有单独的账户、钱包或排行榜屏幕。套餐和余额住在抽屉和兑换面板里，账户设置住在 [ur.io](https://ur.io) 的 Web 应用里。登出在主视图。

## 设备位置覆盖

Linux 得到了 Android 所谓"同步设备位置"的一个真实版本：向系统询问你在哪里的应用，可以被告知你连接时间最长的那个提供者的坐标，而不是你的实际位置。开关在已连接提供者地球的上方，带设置指南，默认关闭。

机制很窄。GeoClue，桌面应用询问位置的服务，有一个静态源，从 `/etc/geolocation` 读取固定位置并监视文件变化。那个文件是唯一的注入点，而它住在 `/etc` 下，所以写入由守护进程经同一条控制通道完成；GUI 从不碰它，也从不需要 root。

指南直接写明它的局限。它需要 GeoClue 2.7.0 或更新，不是每个系统都有；Ubuntu 22.04 和 Debian 12 带的是更老的版本，永远满足不了。而且它只挪动 GeoClue 报告的东西：GNOME 设置和地图、Firefox，以及沙盒化的 Flatpak 和 Snap 应用会跟随它。Chrome 和 KDE Plasma 根本不问 GeoClue，凡是从你的 IP 地址推算位置的东西都不受影响，而且系统应答慢时 Firefox 会退回它自己的查询。它还会改变报告给机器上每个应用的位置，不只是 URnetwork。应用里的其他一切照常工作。

## 共享连接

共享默认关闭，主屏控制区提供**自动**（Auto）、**始终**（Always）、**网络**（Network，只对你自己账户的设备）或**永不**（Never）。提供者参与 UR protocol；[ur.xyz](https://ur.xyz) 记录了奖励的运作方式。

你共享时保护你的，是连接引擎的开源 `ip_security` 层。它在你自己的出口上做深度包检测，在 DMCA 类流量（有状态的 BitTorrent 和文件共享特征、不透明协议丢弃）和 CFAA 类流量（攻击与入侵模式）离开你的机器之前把它们丢弃。同一个过滤器也在你作为普通用户的发送路径上运行，无论你是否打开过共享，所以你的流量在到达任何提供者之前就在你的机器上接受判定。

命中时数据包被丢弃，不记录目的地、域名或内容。你替别人承载的流量上如果命中 BitTorrent 特征，还会向运营方升起一个滥用标记，只含发送设备的 id 和一个布尔值，而运营方今天没有处理它的代码。不透明加密的流就是普通丢弃，什么都不上报。密封绕不开这个过滤器，因为它运行在流量出网的地方。而断网保护决定你自己机器上被判为丢弃类的数据包的命运：关，从你的本地连接出去；开，停住。

## 后量子身份面板

抽屉显示这台设备的会话身份：一个identicon、规范的密钥哈希和客户端 id（点击复制）、一叠你已建立验证会话的提供者身份、完整的提供者身份列表，以及一个用于带外比对指纹的分享对话框。

这个设置做什么：**后量子加密**出厂即开，开着时你的客户端在一条以 **X25519MLKEM768**（经典加 ML-KEM 混合）协商的会话上，把流量端到端密封到提供者。这条密封的段就是让中间跳失明的东西：运营方承载着自己读不了的字节。它是失败即关闭的：设置开着时客户端不会明文收发应用数据，所以碰到无法建立该会话的提供者就跳过，而不是不加密照用；代价是少一个提供者，不是少了加密，你不会被悄悄降级。当前所有提供者构建都启用应答一侧，所以跳过很少发生。把设置关掉，流量才能重新走标准的 TLS 到平台路径。身份签名仍是 Ed25519，加密算法是 AES-256-GCM。"后量子"指的就是这次密钥交换，不指更多。

## 网络在底下做什么

你的流量走四段：你 → 扩展器 → 运营方 → 提供者 → 互联网。扩展器是一个可达性跳点，原样转发你的加密会话而不读取它；作为你的第一跳，它确实看得到你的地址。[概览](/docs/overview)讲解完整路径、为什么止步于四段，以及提供者窗口。

对这个应用的控制项而言，关键是两个中继方之间的分割。提供者永远不知道你是谁，因为运营方站在中间。运营方读不了你发送的内容，因为后量子加密默认把会话端到端密封到提供者。全新安装两条都成立，所以没有任何单独一方同时握有你的身份和你的活动。两个开关产生的三种状态：

| 模式 | 运营方看到 | 提供者看到 | 默认与可用性 |
|---|---|---|---|
| **中继密封** | 你的账户和来源连接、你在用哪些提供者，以及密文及其时序和数据量 | 它出网的目的地和一个设备/合同 id，**不含**你的真实 IP | 出厂默认：后量子加密，在连接抽屉里开启 |
| **中继标准** | 你的账户和来源连接、你在用哪些提供者，以及里面的目的地和数据包字节 | 它出网的目的地和一个设备/合同 id，**不含**你的真实 IP | 仅在后量子加密关闭时 |
| **直连** | 更少的中继参与 | **你的真实 IP**及它出网的目的地 | 自行选择开启：关掉**强匿名化** |

[威胁模型](/docs/threat-model)把这几行逐一对照具名的对手推演，并明说每一行在哪里失守。

运营方那一侧没什么可留的：连接记录保存的是你 IP 地址块的带密钥单向哈希（用一把保密密钥搅乱），不是地址本身；合同账本保存客户端 id 和字节数，任何地方都没有目的地、主机、URL 或域名；数据路径什么都不记录。地理查询确实会按连接记下一个粗略城市；你经它到达了什么，完全不被记录。尚无独立审计覆盖协议或运营方的服务器代码（2025 年的两项第三方评估覆盖其他层面：对 Web 应用和 API 的渗透测试，以及 Leviathan 对 Android 应用的、已通过的 MASA AL2 评估，不含 Linux 客户端）。实际存在的检验是开源本身——任何人随时可查——以及出口设计：出网是一支由各自运营的提供者组成的去中心化队伍，而不是一个握有一切的托管者。局限：这支队伍到底有多独立从未被测量，也没有什么阻止运营方运行自己的提供者（[威胁模型](/docs/threat-model) §6.1）。

## 局限

- **断网保护出厂关闭。** 它是连接抽屉里一个真实的开关，但在你打开之前，没有提供者在线时流量会回落到你的正常连接，而不是停住。抽屉经设备 RPC 实时应用它，守护进程在下次启动时恢复你的选择。
- **隧道只走 IPv4。** IPv6 不经它路由，所以在启用 IPv6 的网络上，支持 v6 的站点仍可能看到你的真实地址。如果你需要一切都从提供者出网，就在该连接上禁用 IPv6。
- **没有按应用拆分隧道。** 规则是域名和 IP 级的。
- **没有 Google 或 Apple 登录。**
- **DNS 接管依赖 systemd-resolved**，如上所述。

## 疑难解答

### "URnetwork 系统服务未运行"

检查守护进程和它的套接字：

```
systemctl status urnetworkd
journalctl -u urnetworkd -f
```

守护进程会叙述它配置了什么、恢复了什么，所以隧道拉起、路由和 DNS 问题先看这里。GUI 日志留在你的用户会话里，与特权那一半分开，这正是拆分的意义。

如果守护进程在运行而应用仍然够不到它，你多半不在 `urnetwork` 组里：`id -nG` 会告诉你。用 `sudo usermod -aG urnetwork "$USER"` 把自己加进去，然后登出再登录。

### "服务已过期"/"构建不一致"

把两半更新到同一个发布版：守护进程装更新的 `.deb`（或从更新的 tarball 重跑 `install.sh`），AppImage 换掉 `~/.local/lib/urnetwork/` 里的那个。这个检查的存在，就是为了让升级了一半的安装明说，而不是悄悄地行为异常。

### AppImage 启动不了

Ubuntu 22.04+ 默认不带 `libfuse2`，而 AppImage 需要它。`.deb` 声明了这个依赖，所以装守护进程包通常就解决了；否则安装 `libfuse2`（新版本上是 `libfuse2t64`）。也检查一下文件有没有执行权限。

### 没有托盘图标

你的桌面没有 StatusNotifierItem 宿主。GNOME 上装 AppIndicator 扩展；KDE 和多数面板原生支持。没有它应用也工作得很好：关窗口只是隐藏，从应用菜单再打开。

### `urnetwork://` 链接没反应

钱包登录经一个 `urnetwork://` 链接返回，它需要安装后刷新桌面数据库。运行 `update-desktop-database ~/.local/share/applications`（或加 sudo 刷系统路径）。打包安装会替你触发这一步；手动安装可能没有。

### 接口存在但什么都不路由

检查 NetworkManager 是否在管理 `urnet0`。软件包带了把它标记为不受管理的配置片段和 udev 规则，两者都需要重载（`nmcli general reload conf`、`udevadm control --reload`），安装器会做这件事。

## 其他文档

[概览](/docs/overview)端到端讲解这个网络：提供者、合同、各方能看到什么和不能看到什么，以及加密。[FAQ](/docs/faq) 回答常见问题。其他平台：[Android](/docs/getting-started-android)、[iOS](/docs/getting-started-ios)、[macOS](/docs/getting-started-macos)、[Windows](/docs/getting-started-windows)，以及[浏览器](/docs/getting-started-browser)。
