findings

command module
v0.0.0-...-a08ad04 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2024 License: AGPL-3.0 Imports: 14 Imported by: 0

README

节点发现服务(findings)

前言

提供各种类型节点的登记注册,维护一个节点连系信息的暂存池,向请求目标类型节点信息的用户提供连系清单。同时,作为P2P网络的基础设施,为新节点的加入提供 NAT打洞 服务支持,因为findings已经是一个网络,所以可以多机协作而无需双IP配置。

一台服务器维护的节点信息包含同类节点(findings)、数据驿站的 depots/archivesdepots/blockqs 公共服务节点,以及不同区块链的工作节点。

通常,应用节点会启动一个自己的findings服务器,该服务器通过多种方式搜寻其它findings服务节点进行组网。如果存在已知的公共findings节点,组网会很快,否则可能是一个比较耗时的过程。如果需要服务器实时可用,运行一个自己的长期在线的findings是一个不错的选择。

除了对 depots/archives, blockqs 公共服务节点会普遍支持外,对于不同的区块链应用,findings服务器会有自己的选择。服务器通常会先声明自己支持的区块链的名称,并向请求节点信息的区块链应用传递一个相同链的地址,用于接收可能有的奖励。

用法

(略)

性能

(略)

附:网络的连通性

暴力发现

传统的P2P网络有一个致命的缺陷:起始中枢。即新节点刚上线时需要获得其它节点的信息以建立初次连接,这时就需要一个提供这些信息的中心服务器。而一旦这样的服务器被禁用,P2P的逻辑就执行不起来。

目前解决这个问题的办法有几个,比如在App发布时就加入几个主要节点的IP,或者通过专用的渠道获取。但实际上这些都可以被封堵。

findings是一个网络,通过大众化的利益驱动模式运行且成本低廉。如果网络已经启动运行,假以时日,数以万计的服务器规模是可预期的。如果无需顾及时间,用IP遍历的 暴力发现 方式去发现这个已经运行的网络,则不应该是一件太困难的事。findings服务器可以仅仅只是一台旧手机或树莓派,可以长期挂机,因此这个P2P网络就会很大。

用户用一台小设备挂机扫描,暴力发现findings网络,一旦成功,用户就无需担心自己的具体类P2P网络找不到了。

App发布时会默认配置几个IP,这些IP至少曾经有效,用户也可以修改这个配置。作为一种暴力发现优化,这些IP会作为随机IP的衍生起点,新创建的IP会围绕着它。这是基于友好用户可能成群结队的假设。同时,这也可用于IP簇优化:配置一个簇中间的一个IP号,然后随机衍生的IP就会在它附近。

标准端口混入

如果管理者屏蔽了Findings服务的默认端口号,我们可以采用通用服务端口混入的方式,比如 https 的标准端口 443。因为大多数的公网IP都不会提供这种标准服务,所以在这个端口提供 findings 服务也是可行的。

这需要公网IP主机们的共同努力,来应对这种网络封锁。

动态端口(含工作量)

网络阻断可能针对特定的端口,目的是阻断某种特定的应用通讯。对抗这种封锁的一个方法就是采用动态端口的策略。

这里的动态端口是可预测的,预测算法加入了工作量的逻辑,用户需要一定量的计算才能获知目标端口。这种策略迫使攻击者也需要付出同样的代价,如果每一台服务器的动态端口都不一样,那么阻断这种通讯就需要大量的工作量运算。而对于单一节点而言,它们只连接少量的服务器,计算消耗是可以接受的。

算法是通用的,但会加入服务器自身的IP地址作为动态因素。目标端口将在一定的时间段(如1小时)内保持不变,来获得确定性。

算法示意

随机动态端口的算法加入了工作量机制。代码仅为示意,但借助了Go语言的语法高亮友好。

// App配置项:
// 服务器和客户端其值相同,在App发布时设置。
var timeFrom   time.Time = GetConfig("timeFrom")    // 起始计算时间。
var randBase    int64    = GetConfig("randBase")    // 随机数种子。
var diffValue  [32]byte  = GetConfig("diffValue")   // 难度标的值(前置零越多则越难)。

// 参与运算的随机因子
// 这些值在当前App运行期间动态获取。
var IP netip.AddrPort   // 服务器网址(IP+Port)
var hours int64         // 起始时间到当前时间的小时数
var portRnd int64       // 端口随机源

// 随机值确定性
rand.Seed( randBase )
// 随机值边界
const randMax = 1<<63 - 1

// 循环尝试:
// 难度标的值(diffValue)通常会设置在普通单机需运算约1~2秒的程度。
// 工作量在此产生。
for {
    // 以小时为单位
    // 即:1小时内该值不会变,获得一种确定性。
    hours = time.Since(timeFrom) % time.Hour

    // 端口随机源
    portRnd = rand.Intn(randMax)

    // 随机因子串联,计算哈希
    // 注:仅为示意,实际代码需要转换后串联。
    tmp := sha256.Sum256( IP + hours + portRnd )

    // 是否满足目标难度
    if tmp < diffValue {
        break
    }
}
// 目标端口,
// +1024,使不占用系统端口,端口上界 65535
return (portRnd % 64511) + 1024

为避免计算出来的端口与服务器本机上其它端口冲突,可以约定2个备用端口:即目标端口 +1+2。如计算的端口是 1234,则 1235(1234+1)和 1236(1234+2)都为备用端口。

Documentation

Overview

节点发现服务主程序。 节点相互连接构建为一个P2P网络,向应用类节点提供其同类节点的信息, 同时也提供NAT类型侦测和STUN打洞服务。

候选池: ------- 可直接连通,仅限于可直接连接的(Pub/FullC)公网类节点。 候选池里的公网节点是节点信息交换的目标。 组网池的节点会不定时更新,更新时会与新节点交换节点信息。这些信息会合并进入候选池。 如果组网池成员不足,也会从候选池中提取成员创建新的连接。

组网池: ------- 公网节点的当前连接池,仅支持TCP连接。 池成员可能为其它公网类节点,也可能是受限节点,取决于连入的请求类型。 当前节点除了提供基本的公网节点信息交换外,也提供STUN服务,可能需要池成员的配合。

受限连接池: ----------- 受限节点的当前连接池,支持对外连出的TCP连接,以及通过UDP打洞服务获得的UDP连接。 TCP连出通常仅为了获取公网节点信息,以构建自己的公网节点清单。 TCP与UDP连接数量各占一半。

节点信息: --------- - 应用类型:depots:[name] | blockchain:[name] | app:[name] | findings - 连接协议:tcp | udp - NAT 类型:Pub | FullC | RC | P-RC | Sym - 公网地址:[IP]:[Port] - 加密公钥:公钥:算法

Directories

Path Synopsis
base 基础支持包
base 基础支持包
Package config 全局配置集
Package config 全局配置集
crypto
selfsign
Package selfsign is a test helper that generates self signed certificate.
Package selfsign is a test helper that generates self signed certificate.
utilx
util-X 工具包 收纳一些基础性的加密相关工具函数。
util-X 工具包 收纳一些基础性的加密相关工具函数。
作为客户端使用的代码实现
作为客户端使用的代码实现
NAT 探测协助包(UDP)
NAT 探测协助包(UDP)
natx
STUN 客户端。
STUN 客户端。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL