go-libp2p支持holepunching
作为ipfs基础的go-libp2p终于在v0.16.0开始支持holepunching,一个期待已久的功能。如果没有这个功能,很多节点是没有办法联通的,应用场景就很受限。
Internet最开始的初衷就是让任意两个IP可以直接互通的。但由于Ipv4地址的稀缺,以至NAT的广泛存在,大部分节点都已经在内网之内,不能再互联互通了。即便是IPv6已经普及的今天,由于防火墙的普遍存在,IPv6节点互通也只是理论可行而实际不行(普通人不可能去修改家庭路由器的防火墙设置)。所以现在的互联网应用方向大部分都是基于云端的,数据传输主要靠服务器转发。
借助于udp打孔技术,大量的P2P应用重新发明了TCP(可靠流传输协议),让内网节点互联成为可能。因为没有了TCP/IP底层架构支持,udp打孔必须依赖中心服务器进行协助进行。现在的udp打孔功能,都是在P2P应用内部实现的,中心服务器也是为特定应用部署的。要开发新的应用,需要部署新的服务器(有成本),依赖别人的服务器又不可靠,还存在单点问题。
go-libp2p是从ipfs分离出来的,既作为ipfs的一部分也可以单独拿出来使用,我们可以借助go-libp2p完成TCP/IP网络原本应该提供的直接互通功能。在go-libp2p里,peer id等同于ip地址,stream则等同于tcp连接。
go-libp2p很早就支持了relay功能,但通过relay传输数据的效率太低了,限制了应用场景。如今支持了holepunching功能,对relay的依赖大为降低,效率大大提高,应用场景就比较广阔了。
go-libp2p的分布式打孔是先依赖relay完成两节点的连接,然后节点之间交换消息进行打孔,从而完成直连升级。因为基于ipfs网络,有众多relay节点可用,所以不存在单点问题。
为了测试一下libp2p的打孔功能,我简单实现了一个端口转发程序p2p-tun,可解决从外部访问内网应用这个常见问题。