
自动,安全,分布式,具有过渡连接(即在订户之间没有直接访问时转发消息),没有单点故障,对等,经过时间考验,资源消耗低,具有“打孔”功能的全网状VPN网络NAT-有可能吗?
正确的答案是:
- 是的。
- 是的,如果您使用tinc + tinc-boot很容易
跳过介绍链接
锡描述
不幸的是,在Habré上发布了有关Tinc VPN的一些信息,但是仍然可以找到一些相关文章:
从英文文章中可以区分出:
原始资料最好考虑原始的Tinc man文档
因此(从官方站点免费转载)Tinc VPN是一项服务( tincd
守护程序),该服务通过在节点之间建立隧道并加密流量来确保专用网络的功能。 源代码是开放的,并根据GPL2许可证提供。 与经典(OpenVPN)解决方案一样,创建的虚拟网络在IP(OSI 3)级别可用,这意味着在通常情况下,无需更改应用程序。
主要特点:
- 流量的加密,认证和压缩;
- 全自动的全网状解决方案,包括以所有模式建立与网络节点的连接,或者,如果不适用,则在中间主机之间转发消息;
- 打孔NAT;
- 在以太网级别(虚拟交换机)连接隔离网络的能力;
- 多种操作系统支持:Linux,FreeBSD,OS X,Solaris,Windows等。
tinc开发有两个分支:1.0.x(几乎在所有存储库中)和1.1(永恒的beta)。 本文在各处使用版本1.0.x。
Tinc 1.1x提供了几个新的关键功能:完善的前向安全性,简化的客户端连接(实际上替代了tinc-boot
)以及总体上更周到的设计。
但是,目前,在官方网站上显示并突出显示了一个稳定的版本-1.0.x,因此,在使用1.1分支的所有优点时,您应该评估使用非最终版本的所有优点和缺点。
在我看来,最强的可能性之一是在无法直接连接时转发消息。 同时,路由表是自动构建的。 即使没有公共地址的节点也可以通过自身进行通信。

考虑三个服务器(中国,俄罗斯,新加坡)和三个客户(俄罗斯,中国和菲律宾)的情况:
- 服务器具有公共地址,客户端位于NAT之后;
- 在下一次可能的代理禁令中,ILV封锁了除“友好”中国之外的所有房东。
- 中国<-> RF的网络边界不稳定并且可能会下降(由于ILV和/或由于中国检查员的原因);
- 与新加坡的联系条件稳定(个人经验);
- 马尼拉(菲律宾)对任何人都不构成威胁,因此允许所有人(由于与所有人和一切都相距遥远)。
例如,上海和莫斯科之间的交通交换,请考虑Tinc的场景(大约):
- 原始情况:莫斯科<->俄罗斯-srv <->中国-srv <->上海
- ILV与中国的封闭联系:莫斯科<->俄罗斯-srv <->马尼拉<->新加坡<->上海
- (第2点之后),如果新加坡服务器发生故障,流量将转移到中国的服务器,反之亦然。
只要有可能,Tinc都会尝试通过打孔在NAT之后的两个节点之间建立直接连接。
tinc配置简介
Tinc被定位为易于配置的服务。 但是,出了点问题-创建一个新节点,最小的必要是:
- 描述主机配置(类型,名称)(
tinc.conf
); - 描述配置文件(服务的子网,公共地址)(
hosts/
); - 创建密钥;
- 创建一个指定节点地址和相关参数的脚本(
tinc-up
); - 建议创建一个脚本,该脚本在停止后清除创建的参数(
tinc-down
)。
除此之外,连接到现有网络时,必须获取现有主机密钥并提供自己的密钥。
即:对于第二个节点

对于第三

使用双向同步时(例如, unison
),附加操作的数量增加到N个,其中N是公共节点的数量。
我们必须向Tinc的开发者致敬-包含在网络中,只需交换密钥
只有一个节点(bootnode)。 启动服务并连接到参与者后,tinc将获得拓扑
网络,并将能够与所有订户一起使用。
但是 ,如果引导主机不可用,并且tinc已重新启动,则无法
将连接到虚拟网络。
此外,tinc的巨大可能性及其相关的学术文档(详细描述,但示例很少)为错误提供了广阔的领域。
创建tinc-boot的原因
如果我们概括上述问题并将其表述为任务,那么我们将得到:
- 需要能够以最小的努力来创建新站点;
- 潜在地,有必要使普通专家(enikey)有一条小线可以创建一个新节点并连接到网络;
- 必须在所有活动节点之间自动分配密钥;
- 有必要在bootnod和新客户端之间提供简化的密钥交换过程。
bootnode-具有公共地址的节点(请参见上文);
由于权利要求2的要求,可以说在引导节点和新节点之间的密钥交换之后以及之后
将节点连接到网络后,新密钥的分发将自动进行。
tinc-boot执行的正是这些任务。
除tinc
之外, tinc-boot是一个自包含的开源应用程序,它提供:
- 简单创建新节点;
- 自动连接到现有网络;
- 默认设置大多数参数;
- 分配给蜜节点。
建筑学
tinc-boot
可执行文件由四个组件组成:一个引导节点服务器,一个密钥分发管理服务器及其RPC管理命令,以及一个节点生成模块。
节点生成模块
节点生成模块( tinc-boot gen
)创建所有必要的文件,以使tinc成功运行。
简化后,其算法可以描述如下:
- 定义主机名,网络,IP参数,端口,子网掩码等。
- 标准化它们(tinc在某些值上有限制)并创建缺失的值
- 检查参数
- 如有必要,在系统上安装tinc-boot(禁用)
- 创建
tinc-up
, tinc-down
, subnet-up
, subnet-down
- 创建
tinc.conf
配置tinc.conf
- 创建
hosts/
- 执行密钥生成
- 与bootnode进行密钥交换
- 使用xchacha20poly1305使用公共密钥,随机初始化向量(nounce)和主机名对您自己的主机文件进行加密和签名,其中加密密钥是令牌中sha256函数的结果
- 通过HTTP协议将数据发送到bootnode
- 使用原始nounce和相同算法解密收到的答案和包含引导节点名称的
X-Node
标头 - 如果成功,请将接收到的密钥保存在
hosts/
然后将ConnectTo
条目添加到配置文件中(例如,建议连接位置) - 否则,请在引导节点列表中使用以下地址,并从步骤2开始重复
- 显示有关启动服务的建议
通过SHA-256进行的转换仅用于将密钥标准化为32个字节
对于第一个节点(即,在没有任何要指定的引导地址的情况下),将跳过步骤9。 标记--standalone
。
示例1-创建第一个公共站点
公用地址为1.2.3.4
sudo tinc-boot gen --standalone -a 1.2.3.4
示例1-将非公共节点添加到网络
引导节点将取自以上示例。 主机必须正在运行tinc-boot引导节点(稍后描述)。
sudo tinc-boot gen --token "MY TOKEN" http://1.2.3.4:8655
引导模块
tinc-boot bootnode
会引发一个HTTP服务器,该服务器具有用于与新客户端进行主密钥交换的API。
默认情况下,使用端口8655
。
简化后,该算法可以描述如下:
- 接受客户的请求
- 使用在请求期间传递的初始化矢量,使用xchacha20poly1305解密和验证请求,其中加密密钥是令牌中sha256函数的结果
- 支票名称
- 如果没有相同名称的文件,请保存文件
- 使用上述算法对自己的主机文件和名称进行加密和签名
- 返回项目1
总而言之,主密钥交换过程如下:

示例1-启动下载节点
假定已执行节点的初始初始化( tinc-boot gen
)
tinc-boot bootnode --token "MY TOKEN"
--token
标志设置授权令牌。 对于连接到主机的客户端,它应该是相同的。
示例2-将下载节点作为服务启动
tinc-boot bootnode --service --token "MY TOKEN"
--service
标志--service
创建systemd服务(默认情况下,对于本示例而言tinc-boot-dnet.service
)--token
标志设置授权令牌。 对于连接到主机的客户端,它应该是相同的。
密钥分配模块
密钥分发模块( tinc-boot monitor
)生成一个HTTP服务器,该服务器带有一个API,用于与VPN内的其他节点交换密钥。 它固定为网络发布的地址(默认端口为1655
,与多个网络没有冲突,因为每个网络都有/必须具有自己的地址)。
该模块将启动并完全自动运行:您无需在手动模式下使用它。
该模块在网络启动时自动启动(在tinc-up
脚本中),并在网络停止时自动停止(在tinc-down
脚本中)。
支持运营:
GET /
提供您的节点文件POST /rpc/watch?node=<>&subnet=<>
-假设另一个类似的服务正在运行,则从另一个节点获取文件。 默认情况下,尝试会以10秒(每30秒)超时,直到成功或取消为止。POST /rpc/forget?node=<>
-尝试从另一个节点提取文件(如果有)POST /rpc/kill
终止服务
此外,每分钟(默认情况下)以及收到新配置文件时,都会为新的公共节点建立已保存节点的索引。 当检测到带有Address
标志的节点时, tinc.conf
条目添加到tinc.conf
配置文件中,以在重新启动时建议连接。
密钥分发模块(管理)
当检测到新节点( subnet-up
脚本)和停止新节点( subnet-up
subnet-down
脚本)时,分别自动执行用于从其他节点请求配置文件的命令( tinc-boot watch
)和取消该命令( tinc-boot forget
)。
在停止服务的过程中,将tinc-down
脚本,其中tinc-boot kill
命令将停止密钥分发模块。
而不是总数
该实用程序是在Tinc开发人员的天才与建立新节点的线性复杂性之间的认知失调的影响下创建的。
开发过程中的主要思想是:
- 如果某些东西可以自动化,那它必须是自动化的;
- 默认值应至少覆盖使用量的80%(帕累托原理);
- 可以使用标志和环境变量重新定义任何值;
- 公用事业应提供帮助,而不是引起对造物主的一切天堂惩罚的渴望;
- 使用授权令牌进行初始初始化是一个明显的风险,但是,由于总的加密和身份验证(即使无法替换响应头中的节点名称),也可能将其最小化。
年表:
- 我4年前第一次使用tinc。 研究了大量的材料。 建立理想的网络(我认为)
- 半年后,tinc被替换为零级,这是一种更方便/灵活的工具
- 2年前,我制作了一个有趣的剧本来部署Tinc
- 一个月后,我的脚本无法进行增量部署(即,当不可能访问所有网络节点时,这意味着分发密钥)
- 两周前,我写了一个bash脚本脚本,它是
tinc-boot
的原型。 - 3天前,在第二次迭代之后,该实用程序的第一个版本(准确地说是0.0.1版)诞生了
- 1天前,我将新节点的安装减少到一行:
curl -L https://github.com/reddec/tinc-boot/releases/latest/download/tinc-boot_linux_amd64.tar.gz | sudo tar -xz -C /usr/local/bin/ tinc-boot
curl -L https://github.com/reddec/tinc-boot/releases/latest/download/tinc-boot_linux_amd64.tar.gz | sudo tar -xz -C /usr/local/bin/ tinc-boot
- 不久,将增加与网络的更简单连接的可能性(不牺牲安全性)
在开发过程中,我在真实的服务器和客户端上进行了积极的测试(上面的tinc描述中的图片来自真实生活)。 现在,该系统可以正常运行,并且所有第三方VPN服务都已禁用。
应用程序代码用GO编写, 并在MPL 2.0许可下打开 。 许可证(免费翻译)允许商业用途(如果有人突然需要)而无需打开源产品。 唯一的要求是必须将更改转移到项目中。
欢迎泳池要求。
有用的链接