使用go-libp2p搭建中转服务器(circuit relay server)
libp2p算是一个蛮新的库,提供了非常强大的p2p节点发现/连接/通信能力。IPFS的基石。
中文网上的技术教程比较少,所以抛砖引玉开一点坑来体验一下!
这篇博客本质上就是用libp2p做一个NAT打洞建立p2p的实现,不过过程中能够学到很多libp2p的概念,当然用libp2p做也应该有不少好处有待进一步研究。
代码基于:
https://github.com/libp2p/go-libp2p/tree/master/examples
和一些外网教程
复现本篇博客的技术基础
- 基础的Go语言能力(我也不是很懂,GO能学的太多了,超过我上一篇博客的内容基本上都不会)
- Go version>=1.19(libp2p的要求)
- NAT与NAT打洞相关概念
- 一台具有公网IP的服务器
- 你自己的电脑
1. 了解一些libp2p基础概念
libp2p-node, 或说Host, 中文名节点, 不是指网络中的一个主机, 而是指的网络连接中的一个独立端点, 一个独立的应用程序, 一台电脑/服务器上面可以配置多个host. 在go-libp2p的example中, 很多测试都是在同一个电脑上运行的.Multiaddr,libp2p网络传输层的协议中, 用一个Multiaddr概念来统领两个节点之间的多种连接方式. 从而对更高层的应用隐藏底部的具体连接协议.
2. 原理
两个藏在NAT或防火墙后面的host:A, B; 一个可以被公网访问到的(比如说具有公网IP)host:R
这里A是等待被访问的host, B是要去访问A的host
首先A需要先去连接中转服务器R, 进行一个预定Reservation, 这样A和R的双向通路就打开了.
接下来B向R发出连接到A的请求, R帮助B与A建立连接

3. 代码核心语句解释
代码主要分为两个程序: 客户端和服务端/中转服务器
中转服务器的核心代码:
relay1, err := libp2p.New()
_, err = relay.New(relay1)
log.Printf("relay1Info ID: %v Addrs: %v",relay1.ID(), relay1.Addrs())
就这么短, 很简单.
第一句话创建一个新的host,
第二句话在host上配置中转服务器
第三句话将host的ID和地址打印出来, 这里我们手动复制传给A和B
客户端的核心代码:
客户端也分为两个部分, 等待被连接的Ahost, 和去连接A的Bhost.
这里我们直接用是否输入了被连接的Ahost的ID作为本客户端是A还是B的判断条件.
等待被连接的Ahost
unreachableNode, err := libp2p.New(
libp2p.NoListenAddrs,
// Usually EnableRelay() is not required as it is enabled by default
// but NoListenAddrs overrides this, so we're adding it in explictly again.
libp2p.EnableRelay(),
)
relayServerID := "12D3KooWHwN52aYe18Wa6meTcLtrQ6y7jKXaQ85zf2snxsUWPA9B"
ms1, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/43.143.xxx.xxx/tcp/38403/p2p/%v", relayServerID))
relay1info, err := peer.AddrInfoFromP2pAddr(ms1)
if err := unreachableNode.Connect(context.Background(), *relay1info); err != nil {
log.Printf("Failed to connect unreachable1 and relay1: %v", err)
return
}
_, err = client.Reserve(context.Background(), unreachableNode, *relay1info)
// Now, to test the communication, let's set up a protocol handler on unreachable2
unreachableNode.SetStreamHandler("/chatStream", func(s network.Stream) {
log.Println("Awesome! We're now communicating via the relay!")
log.

本文介绍如何使用Go-libp2p库搭建NAT穿透的中转服务器(circuit relay server),实现两个处于NAT后的节点通过该服务器建立P2P连接。文章详细解释了libp2p的基本概念,如libp2p节点、Multiaddr等,并提供了一个具体的代码实例,展示了客户端和服务端的核心代码。
最低0.47元/天 解锁文章





