TINC 源码解读 第二篇 - 模块架构与代码组织
本文是 TINC 源码解读系列的第二篇,重点分析 TINC 的整体架构和代码组织。TINC 采用清晰的分层架构,将系统分为 8 个层次,从应用层到工具层,每层都有明确的职责。
1. 项目概述⌗
TINC 是一个点对点 (P2P) VPN 守护进程,支持任意数量节点的虚拟专用网络。通过指定 VPN 中几个节点的位置和公钥,TINC 能够自动发现所有其他节点并建立连接。当直接连接不可用时,数据通过中间节点转发。
支持的工作模式:
- Router (路由器模式) - 默认,每个节点关联 IPv4/IPv6 子网
- Switch (交换机模式) - 虚拟以太网交换机
- Hub (集线器模式) - 虚拟以太网集线器
2. 分层架构概览⌗
+---------------------------------------------------------------------+
| Application Layer |
| +----------+----------+----------+--------+ |
| | tincd.c | tincctl | info.c | fsck.c | |
| | (daemon) | (control)| (query) |(verify)| |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Control Layer |
| +----------+----------+----------+--------+ |
| | control | command | top.c | script | |
| | (socket) | (handler)| (monitor)|(exec) | |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Protocol & Comm Layer |
| +----------+----------+----------+ |
| | protocol | sptps.c | connec | |
| | * files | (crypto) | tion.c | |
| +----------+----------+----------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Network & Routing Layer |
| +----------+----------+----------+--------+ |
| | net*.c | route.c | graph.c | proxy | |
| | (I/O) | (table) | (topo) | | |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Data Structure Layer |
| +----------+----------+----------+--------+ |
| | node.c | edge.c | subnet.c | names | |
| | +--------+----------+----------+--------+ |
| | | list | splay | hash | | |
| | | tree | tree | table | | |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Cryptography Layer |
| +----------+----------+----------+--------+ |
| | cipher | digest | ecdsa | ecdh | |
| | (sym) | (hash) | (sig) | (kex) | |
| | +--------+----------+----------+--------+ |
| | | rsa | ed25519 | OpenSSL | gcrypt | |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Device & System Layer |
| +----------+----------+----------+--------+ |
| | device.h | *_device | event.c | conf.c | |
| | (intf) | (impl) | (loop) |(config)| |
| | +--------+----------+----------+--------+ |
| | | linux | bsd | solaris | win | |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
|
+---------------------------------------------------------------------+
| Utilities Layer |
| +----------+----------+----------+--------+ |
| | logger | utils | random | buffer | |
| | (log) | (tools) | (prng) | (mem) | |
| | +--------+----------+----------+--------+ |
| | | fs.c | address | autocon | names | |
| | | | cache.c | nect.c | | |
| +----------+----------+----------+--------+ |
+---------------------------------------------------------------------+
3. 模块详细说明⌗
3.1 应用层 (Application Layer)⌗
tincd.c - 主守护进程⌗
- 职责: VPN 守护进程的主程序和事件循环
- 功能:
- 初始化配置和网络
- 启动主事件循环
- 处理信号和优雅关闭
- 管理程序生命周期
- 依赖:
conf.h,event.h,protocol.h
tincctl.c - 控制工具⌗
- 职责: 远程控制 tincd 的命令行工具
- 功能:
- 连接到 tincd 控制套接字
- 发送/接收命令
- 交互式命令处理
- 依赖:
control.h
info.c 和 fsck.c⌗
- info.c: 显示 VPN 节点信息、查询节点状态
- fsck.c: VPN 配置和状态一致性验证
3.2 控制层 (Control Layer)⌗
control.c - 控制连接管理⌗
- 职责: 管理与控制客户端的连接
- 功能:
- 建立和维护控制连接
- 接收/处理控制命令
- 返回状态信息
- 关键结构:
connection_t(带 control 标志)
script.c - 脚本执行⌗
- 职责: 执行 VPN 生命周期脚本
- 功能:
- 执行
tinc-up/tinc-down脚本 - 设置虚拟网络接口
- 执行自定义钩子函数
- 执行
- 环境: 通过环境变量传递配置
event.c - 事件循环⌗
- 职责: 异步事件处理引擎
- 功能:
- I/O 事件(select/epoll/kqueue)
- 超时处理
- 信号处理
- 回调类型:
io_cb_t,timeout_cb_t,signal_cb_t
3.3 协议与通信层 (Protocol & Communication)⌗
protocol*.c - 协议处理⌗
| 文件 | 职责 | 处理消息 |
|---|---|---|
protocol.c |
主协议处理器 | ID, ACK, ERROR |
protocol_auth.c |
认证 | METAKEY, CHALLENGE, CHAL_REPLY |
protocol_edge.c |
边通告 | ADD_EDGE, DEL_EDGE |
protocol_key.c |
密钥交换 | KEY_CHANGED, REQ_KEY, ANS_KEY |
protocol_subnet.c |
子网通告 | ADD_SUBNET, DEL_SUBNET |
protocol_misc.c |
其他 | PING, PONG, STATUS |
net_packet.c |
包转发 | PACKET |
协议版本: PROT_MAJOR=17, PROT_MINOR=7
sptps.c - 安全协议握手⌗
- 职责: 实现 Simple SPTPS 的点对点加密协议
- 功能:
- 密钥交换 (ECDH)
- 会话建立
- 记录加密/解密
- 前向保密
- 状态机:
SPTPS_KEX→SPTPS_KEX1→SPTPS_KEX2→SPTPS_OPEN - 密钥派生: 使用 SHA256/SHA512
connection.c - 连接管理⌗
- 职责: 管理与其他节点的 TCP 连接
- 功能:
- 建立/关闭连接
- 连接状态跟踪
- 连接队列管理
- 元包缓冲 (meta packets)
typedef struct {
io_t io; // I/O event
struct node_t *node; // associated node
buffer_t inbuf, outbuf; // input/output buffers
sptps_t sptps; // SPTPS state
connection_status_t status; // connection status
} connection_t;
3.4 网络与路由层 (Network & Routing)⌗
net*.c - 网络 I/O⌗
| 文件 | 职责 |
|---|---|
net.c |
主网络处理循环 |
net_socket.c |
套接字操作 (UDP) |
net_packet.c |
包处理 (接收/转发) |
net_setup.c |
网络初始化 |
功能:
- UDP 包接收/发送 (fast path)
- TCP 连接处理 (slow path)
- 包加密/解密
- 包转发
route.c - 路由管理⌗
- 职责: 处理数据包路由决策
- 工作模式:
RMODE_ROUTER- 基于子网的路由 (默认)RMODE_SWITCH- 以太网交换RMODE_HUB- 集线器 (广播)
graph.c - 拓扑算法⌗
- 职责: 计算网络拓扑
- 算法:
- Dijkstra 最短路径
- Spanning Tree 构建
- 连通性检查
- 应用:
- 确定最优转发路径
- 检测网络分割
- 计算中继节点
proxy.c - 代理支持⌗
- 职责: 代理协议支持 (SOCKS4/SOCKS5)
- 功能:
- 通过代理建立连接
- SOCKS 握手处理
- 认证支持
3.5 数据结构层 (Data Structures)⌗
核心数据结构⌗
node_t (节点)⌗
node_t
|-- name: 节点名称
|-- id: 节点 ID (ED25519 pub key)
|-- status: 节点状态 flags
|-- address: 节点地址
|-- socket_address: UDP addr
|-- distance: Dijkstra distance
|-- via: routing next hop
|-- nexthop: direct next hop
|-- subnets: owned subnets tree
|-- keys: encrypt keys
+-- connections: TCP conn list
edge_t (边/链路)⌗
edge_t
|-- from: source node
|-- to: target node
|-- address: target address
|-- options: edge opts (flags)
|-- weight: path weight
|-- connection: TCP conn
+-- reverse: reverse edge
subnet_t (子网)⌗
subnet_t
|-- owner: owner node
|-- type: subnet type
|-- weight: priority weight
|-- expires: expire time
+-- net: subnet data
|-- mac.address
|-- ipv4.address/prefix
+-- ipv6.address/prefix
connection_t (连接)⌗
connection_t
|-- io: I/O event handle
|-- node: associated node
|-- address: remote address
|-- inbuf, outbuf: buffers
|-- sptps: SPTPS state
|-- status: connection state
|-- options: connection opts
|-- protocol_version: proto ver
+-- mst: in minimum tree?
容器结构⌗
| 容器 | 用途 | 组织方式 |
|---|---|---|
splay_tree_t |
有序集合 (nodes, subnets, edges) | 平衡树 |
list_t |
无序列表 (connections, events) | 双链表 |
hash.h |
快速查找 (name→node mapping) | 哈希表 |
3.6 密码学与安全层 (Cryptography)⌗
对称加密⌗
-
cipher.c:- AES, Blowfish, Camellia 等
- ECB, CBC, CFB, OFB, CTR 模式
- 后端: OpenSSL 或 libgcrypt
-
chacha-poly1305/:- ChaCha20-Poly1305 AEAD 加密
- 独立实现
哈希与消息摘要⌗
-
digest.c:- SHA1, SHA256, SHA512
- MD5 (遗留)
- 后端: OpenSSL 或 libgcrypt
-
ed25519/sha512.h: ED25519 自带 SHA512
非对称加密与签名⌗
ecdsa.c: ECDSA 签名 (通过 libgcrypt 或 OpenSSL)ecdh.c: ECDH 密钥交换 (SPTPS 握手用)rsa.c(遗留): RSA 签名 (传统握手)ed25519/: EdDSA 实现
后端支持⌗
Cipher/Digest layers
|
+-- openssl/ (libssl/libcrypto)
+-- gcrypt/ (libgcrypto)
+-- ed25519/ (built-in)
密钥管理⌗
-
keys.c:- 生成和加载密钥
- 密钥文件 I/O
- 密钥验证
-
prf.h: 伪随机函数
3.7 设备与系统层 (Device & System)⌗
虚拟网络设备⌗
device.h: 设备操作接口 (抽象)
typedef struct devops_t {
setup_t setup; // initialize
cleanup_t cleanup; // clean up
read_t read; // read packet
write_t write; // write packet
} devops_t;
- 设备实现:
| 平台 | 实现 | 文件 |
|---|---|---|
| Linux | TUN/TAP | linux/device.c |
| BSD | tun/tap | bsd/device.c |
| macOS | tunemu | bsd/darwin/tunemu.c |
| Solaris | TUN | solaris/device.c |
| Windows | TAP | windows/device.c |
- 其他设备:
dummy_device.c- 测试用 (黑洞)fd_device.c- 文件描述符raw_socket_device.c- 原始套接字multicast_device.c- 组播vde_device.c- VDE 交换机
事件驱动⌗
-
event.c:- 事件循环 (select/epoll/kqueue)
- I/O 复用
- 超时和信号处理
-
event_select.c: select() 后端
配置管理⌗
-
conf.c:- 配置文件解析
- 配置树管理
- 配置查询
-
conf_net.c: 网络配置字段
平台特定代码⌗
bsd/ - BSD 特定 (sandbox, tun)
linux/ - Linux 特定 (设备)
solaris/ - Solaris 特定
windows/ - Windows 特定
3.8 实用工具层 (Utilities)⌗
| 模块 | 职责 |
|---|---|
logger.c |
日志记录 (DEBUG/INFO/WARNING) |
utils.c |
通用工具函数 |
random.c |
伪随机数生成 |
buffer.c |
动态缓冲区 |
fs.c |
文件系统操作 |
dropin.c |
缺失函数替代 |
address_cache.c |
节点地址缓存 |
autoconnect.c |
自动连接管理 |
names.c |
名字↔ID 映射 |
netutl.c |
网络工具 |
ifconfig.c |
网络接口配置 |
pidfile.c |
PID 文件管理 |
sandbox.c |
沙箱/安全限制 |
4. 模块依赖关系⌗
tincd/tincctl (Application)
|
v
control + event + logger (Control/Events)
|
v
protocol* + sptps + connection (Protocol)
|
v
node + edge + subnet + graph + route (Data/Topology)
|
v
net* + device + proxy (Network I/O)
|
v
cipher + digest + ecdsa + ecdh (Crypto)
|
v
buffer + list + splay_tree + hash (Containers)
|
v
utils + logger + random + conf (Utilities)
5. 关键工作流⌗
5.1 连接建立流程⌗
1. node.c: create node
|
v
2. connection.c: init TCP conn
|
v
3. protocol_auth.c: send ID
|
v
4. sptps.c: ECDH key exchange
|
v
5. protocol_key.c: exchange session key
|
v
6. net_packet.c: start forward UDP
5.2 数据包转发流程⌗
1. net_socket.c: receive UDP packet
|
v
2. net_packet.c: decrypt packet
|
v
3. route.c: routing decision
|
v
4. graph.c: compute forward path
|
v
5. connection.c / net_socket.c: forward or local
5.3 拓扑更新流程⌗
1. protocol_edge.c: recv ADD_EDGE/DEL_EDGE
|
v
2. edge.c: update edge database
|
v
3. graph.c: recompute shortest path (Dijkstra)
|
v
4. route.c: update forward table
6. 编译配置选项⌗
项目支持多个可选功能,通过编译标志控制:
- 加密后端:
HAVE_OPENSSL/HAVE_LIBGCRYPTO - 压缩:
HAVE_LZO/HAVE_LZ4 - 高级特性:
HAVE_LIBUPNP,HAVE_LIBMINIUPNPC - 平台特定:
HAVE_LINUX,HAVE_BSD,HAVE_WINDOWS等
7. 统计信息⌗
核心代码文件: 60+ files
总代码行数: 15,000+ lines
支持平台: Linux, BSD, macOS, Solaris, Windows
关键数据结构: 5+ (node, edge, subnet, connection, device)
密码算法: 10+
8. 架构设计优势⌗
模块独立⌗
- 每个模块职责清晰
- 最小化模块间耦合
- 便于测试和维护
易于移植⌗
- 设备层、密码层可替换
- 平台特定代码隔离
- 支持 5+ 个操作系统
可扩展⌗
- 易于添加新协议
- 易于添加新加密算法
- 支持可选特性编译
性能优化⌗
- 关键路径 (UDP fast path) 独立优化
- Dijkstra 缓存避免重复计算
- 地址缓存防止 DNS 查询风暴
9. 从 TINC 架构到代码实现⌗
快速导航指南⌗
入门代码:
- 主程序: tincd.c
- 节点定义: node.h
- 连接管理: connection.h
协议处理:
- 协议分发: protocol.c
- 握手流程: protocol_auth.c
数据转发:
- 包接收: net_packet.c
- 路由决策: route.c
拓扑算法:
- 最短路径: graph.c
总结⌗
TINC 的分层架构展现了大型系统软件的设计哲学:
核心原则⌗
分层设计 - 将系统分为 8 个清晰的层次,每层通过定义良好的接口与其他层通信。
模块化 - 每个模块职责单一,相对独立,易于理解和测试。
可移植性 - 通过设备层、密码层等的抽象,支持多平台和多后端。
高效性 - UDP 直接转发为 fast path,TCP 握手和控制走 slow path,最大化性能。
代码启示⌗
- 顶层应用 - 通过控制层与底层通信
- 中层协议 - 实现握手、认证、拓扑交换
- 下层系统 - 提供跨平台的统一接口
- 工具层 - 提供通用服务(日志、缓冲、随机数等)
这种精心设计的架构使 TINC 成为一个既可靠又高效的 VPN 解决方案,也是学习大型系统软件架构的极好范例。
系列预告⌗
- 第一篇:TINC 协议深度解析
- 第二篇:TINC 模块架构与代码组织
- 第三篇:UDP 打洞机制
- 第四篇:TINC 项目 - 模块依赖与数据流图