01 / 设计目标与技术选型
SharkLan 旨在解决传统 VPN 依赖中心服务器、单点故障、配置复杂的问题。其核心目标:
- 去中心化:所有节点对等,无中央协调器,通过 DHT 或手动连接实现自发现。
- 安全通信:节点间所有流量均使用 libp2p 的 Noise 加密 传输,同时节点本地密钥以 Argon2 + AES-GCM 加密存储。
- 透明代理:在用户侧创建 TUN 虚拟网卡,使应用程序无感接入虚拟局域网,IP 包自动路由。
- 轻量可移植:纯 Rust 实现,借助 Tokio 异步运行时,单进程即可运行。
技术选型方面,SharkLan 大量使用了以下生态组件:
- libp2p:模块化 P2P 网络栈,提供传输、加密、多路复用、协议协商等基础能力。
- QUIC:基于 UDP 的可靠传输,低延迟、多路复用,天然支持 NAT 穿透。
- Tokio:异步运行时,支撑高并发事件循环。
- wintun(Windows) /
tun(Linux):虚拟网卡驱动,实现数据面注入。 - Argon2 + AES-GCM:密钥派生与对称加密,保障本地密钥存储安全。
SharkLan 将控制面(节点管理、路由同步)和数据面(IP 包转发)分离,控制面基于 libp2p 的 request-response 协议,数据面直接封装 IPv4 包通过同样的协议传输,实现了简洁而高效的统一通道。
02 / 节点身份与密钥管理
每个 SharkLan 节点拥有唯一的 PeerId,由 Ed25519 公钥派生。私钥用于 libp2p 的身份认证和 Noise 握手。
密钥存储
为了保护私钥,SharkLan 在首次启动时生成密钥对,并使用用户提供的密码进行加密保存。加密流程如下:
- 使用 Argon2id(64 MB 内存、3 轮迭代)从密码派生出 32 字节 AES 密钥。
- 生成随机 16 字节 Salt 和 12 字节 Nonce。
- 使用 AES-256-GCM 加密 Ed25519 私钥的 Protobuf 编码。
- 存储格式为
[salt (16) | nonce (12) | ciphertext],确保每次加密结果不同。
解密时校验数据长度,若密码错误则解密失败,有效防止离线暴力破解(Argon2 设计具有高计算成本)。
03 / 控制协议与节点发现
SharkLan 在 libp2p 之上自定义了三种 request-response 协议,分别用于握手、节点发现和数据转发。
协议定义
- Hello(
/sharklan/control/1.0.0):连接建立后双方交换版本、节点名称、虚拟 IP,并确认连接。 - KnownPeers(
/sharklan/peers/1.0.0):增量同步已知节点列表,每次请求携带since_version(上次收到的最新更新时间戳),服务端只返回比该版本新的记录,大幅减少冗余传输。 - TunPacket(
/sharklan/tun/1.0.0):封装一个完整的 IPv4 数据包(raw bytes),目标节点收到后将其写入本地 TUN 设备,实现数据面路由。 - NodeLeaving:优雅退出时广播通知,帮助其他节点立即标记离线,避免超时等待。
节点发现与自动拨号
节点发现采用 “启动时从磁盘恢复 + 运行时主动拉取 + 自动拨号” 三级机制:
- 持久化:所有已知节点信息(PeerId、地址、虚拟 IP、最后更新时间等)定期序列化到本地
peers.bin,重启后恢复。 - 主动同步:每 30 秒向当前所有已连接节点发起
KnownPeers请求,获取增量更新,并合并到本地 PeerStore。 - 自动拨号:对于离线但地址已知且最近活跃过的节点,系统会每隔 30 秒尝试重连(退避机制),尝试恢复连接。
这一设计使得网络无需中央追踪器,节点间通过相互交换信息就能逐渐发现全网拓扑。
增量同步的版本控制
每个节点为每个对端维护一个 sync_version,即该对端上次返回的全局版本号。当本地 PeerStore 中任何记录更新时,全局版本号(最大 last_updated)递增。下次请求时带上该版本,服务端只返回 last_updated > since_version 的记录,同时返回新的全局版本号。这种方式在网络规模较大时依然保持高效。
04 / 数据面:TUN 设备与 IP 转发
数据面是 SharkLan 的“最后一公里”,负责将来自本机应用程序的 IP 包转发到对应节点,并将远程节点发来的 IP 包注入本机网络栈。
Windows 实现 (wintun)
在 Windows 上,SharkLan 使用 wintun 驱动创建虚拟网卡,设置 IP 地址(如 100.64.0.1/10),并启动两个阻塞线程分别负责读包和写包。为了与异步主循环融合,通过 mpsc 通道将阻塞 I/O 转化为异步事件:
- 读线程:循环调用
session.receive_blocking(),收到数据后通过from_tun_tx发送给主循环的tun_rx。 - 写线程:循环从
to_tun_rx接收数据,使用allocate_send_packet分配缓冲并写入网卡。
主循环在每次迭代中优先检查 tun_rx,若收到 IP 包,则解析目的 IP,并在 PeerStore 中查找对应的节点(通过虚拟 IP 映射),然后调用 send_request(Request::TunPacket) 将其转发给目标节点。
路由表(虚拟 IP 映射)
每个节点可以配置一个虚拟 IP(如 --ip 100.64.0.1),并在 Hello 握手时告知对端。PeerStore 维护 virtual_ip → PeerId 的映射,供数据面查询。若目的 IP 不在映射表中,则丢弃包并记录日志。
性能考量
SharkLan 对每个 IP 包都进行完整的 libp2p 请求-响应往返,这并非性能最优(更高效的做法是使用流式传输),但实现简单且适用于小规模网络(< 50 节点)。此外,通过重用 QUIC 连接,避免了重复握手开销。
05 / 持久化与状态恢复
为了在重启后快速恢复网络状态,SharkLan 将 PeerStore 中所有节点的 持久化字段(PeerId、地址、虚拟 IP、版本、最后更新等)序列化为二进制格式(使用 bincode)存入 peers.bin。连接状态(在线/离线)和拨号尝试时间等瞬时信息不保存。
节点启动时调用 restore_known_peers() 加载文件,若文件不存在则视为空列表。之后通过定时维护(每 15 秒)触发 save_peers(),仅当 dirty 标志为 true 时执行写入,避免频繁磁盘 I/O。
此外,优雅退出时(Ctrl+C 或输入 exit),节点会向所有已连接节点发送 NodeLeaving 请求,并等待 500ms 让请求发出,然后保存 PeerStore 并退出。这样其他节点能立即获知离线,无需等待超时(默认 60 秒)。
06 / 安全与加密
SharkLan 在多个层次上保障安全:
- 传输层:libp2p 默认使用 Noise 协议(基于
xx握手模式)进行密钥交换和会话加密,所有控制协议和数据包均在加密通道中传输。 - 身份认证:每个节点持有 Ed25519 密钥对,PeerId 即为公钥的哈希,连接建立时自动验证对方身份,防止中间人攻击。
- 本地密钥保护:私钥使用用户提供的密码加密存储(Argon2 + AES-GCM),即便磁盘泄露,未授权者也无法获取私钥。
值得注意的是,数据面(TunPacket)并未在应用层额外加密,因为 libp2p 的传输层已经提供了完整的机密性和完整性。这简化了设计,并避免了双重加密带来的性能损耗。
07 / 命令行与用户体验
SharkLan 提供了简洁的交互式命令行,方便用户管理连接:
connect <multiaddr>—— 手动连接指定节点(如/ip4/192.168.1.10/udp/5000/quic-v1/p2p/12D3KooW...)。peers—— 列出所有已知节点及其状态(在线/离线)、虚拟 IP。peersync—— 手动触发一次已知节点同步,适用于首次加入网络或需要立即更新路由表。exit—— 优雅退出,通知其他节点。
启动参数支持指定节点实例名称(用于多开)和虚拟 IP,使得在同一台机器上运行多个节点成为可能(只要 IP 不冲突)。
项目使用 Cargo 构建,依赖 rustls、ring 等纯 Rust 加密库,编译后单二进制文件约 10 MB。
运行示例:cargo run -- --node alice --ip 100.64.0.1
08 / 总结与展望
SharkLan 是一个完整且具有教育意义的 P2P VPN 实现,它展示了如何使用 libp2p 快速构建去中心化网络应用,同时也体现了 Rust 在系统编程领域的优势(内存安全、高性能、异步)。
目前项目尚在积极开发中,核心数据面与控制面逻辑已基本跑通,但距离生产稳定版本仍有不少打磨工作(如跨平台适配、性能优化等)。后续计划增加:
- Linux / macOS TUN 支持(已预留接口,仅需替换
tun.rs实现)。 - 基于 Kademlia DHT 的自动节点发现,代替手动连接。
- 支持 IPv6 包转发和更灵活的路由策略。
- 性能优化:引入流式传输或 UDP 直通,减少每个包的 RTT 开销。
如果你对 P2P 网络或 Rust 异步编程感兴趣,SharkLan 是一个不错的参考项目。待稳定后将择机开源,欢迎持续关注。
项目仍处于早期开发阶段,代码仓库暂未公开。
待核心功能稳定、跨平台适配完成后,将择机开源。欢迎持续关注。