
我是 https://github.com/sigcn/pg 仓库的作者。 经过几个月的努力,现在用 PG 写 P2P 网络程序似乎很简单了。 发帖希望
这是一个访问虚拟网络内节点 HTTP 服务的示例
package main import ( "context" "encoding/json" "fmt" "io" "net" "net/http" "net/url" "os" "time" "github.com/sigcn/pg/disco" "github.com/sigcn/pg/langs" "github.com/sigcn/pg/p2p" "github.com/sigcn/pg/peermap/network" "github.com/sigcn/pg/vpn" "github.com/sigcn/pg/vpn/nic" "github.com/sigcn/pg/vpn/nic/gvisor" "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" ) var ( server = "wss://openpg.in/pg" secretFile = "psns.json" _, ip4, _ = net.ParseCIDR("100.99.0.27/24") ) // prepareSecret 准备 JSONSecret 用于加入 PG 网络 func prepareSecret() error { fetchSecret := func() error { join, err := network.JoinOIDC("", server) if err != nil { return err } fmt.Println("Open the following link to authenticate") fmt.Println(join.AuthURL()) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) secret, err := join.Wait(ctx) cancel() if err != nil { panic(err) } f, err := os.Create(secretFile) if err != nil { return err } json.NewEncoder(f).Encode(secret) return nil } f, err := os.Open(secretFile) if err != nil { return fetchSecret() } var secret disco.NetworkSecret if err := json.NewDecoder(f).Decode(&secret); err != nil { return err } if time.Now().After(secret.Expire) { return fetchSecret() } return nil } // startVPN 启动 VPN (gVisor + p2p) func startVPN(ctx context.Context) *gvisor.GvisorCard { s := stack.New(stack.Options{ NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol}, TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol}, }) vnic := nic.VirtualNIC{NIC: &gvisor.GvisorCard{Stack: s, Config: nic.Config{IPv4: ip4.String()}}} packetConn := langs.Must(p2p.ListenPacket( &disco.Server{Secret: &disco.FileSecretStore{StoreFilePath: secretFile}, URL: server}, p2p.ListenPeerUp(func(pi disco.PeerID, v url.Values) { vnic.AddPeer(nic.Peer{Addr: pi, IPv4: v.Get("alias1"), IPv6: v.Get("alias2"), Meta: v}) }), p2p.ListenPeerSecure(), p2p.PeerAlias1(ip4.IP.String()), )) go vpn.New(vpn.Config{MTU: 1371}).Run(ctx, &vnic, packetConn) return vnic.NIC.(*gvisor.GvisorCard) } func main() { // 获取 JSONSecret if err := prepareSecret(); err != nil { panic(err) } // 启动 gVisor VPN ctx, cancel := context.WithCancel(context.Background()) defer cancel() gvisorCard := startVPN(ctx) // HTTP 请求 cli := http.Client{ Transport: &http.Transport{DialContext: gvisorCard.DialContext}, Timeout: 15 * time.Second, } r := langs.Must(cli.Get("http://100.99.0.2")) defer r.Body.Close() io.Copy(os.Stdout, r.Body) } 1 lekai63 275 天前 感谢。但似乎一下没想到很赞的使用场景。。 |
2 lizhenda 275 天前 什么场景适用呢? 做个相关的 demo 是不是更好点。 |
3 lloovve 275 天前 via iPhone Ipv6 下,两个 5g 或者 4g 手机能直连么 |
4 v1 275 天前 我只能想到用你的 pg 复刻一个 qvod ,当年欠快播一个会员 |
5 wangtian2020 274 天前 webrtc p2p 已经很成熟了,为什么其他语言不 all in 呢 |
6 iYume 274 天前 之前搞区块链时 libp2p 和 devp2p 都用过,你的介绍说的 nat / 25519 这些其他库也都有,我并不算特别了解,只是觉得在 README 搞个 vs. 块对比一下特性可能会便于大家直观看出来 |
7 zzhirong 274 天前 1. 看到 PG 第一反应联想到 PostgreSQL 。 2. 在阅读 README 时,我发现了一个有趣的词“Birthday Paradox (生日悖论,在一个群体中,只需要 23 个人,就有超过 50% 的概率存在两个人的生日相同)”,用在 NAT 穿越上,指的是在双方都知道对方 NAT 地址但不知道对方 NAT 映射端口的情况下,各自随机选择一组目标端口发起通信,从而有一定概率能建立连接,这不禁让人联想到你我相识全靠缘分。最近刚好看了两个关于概率相关的数据结构:跳跃表和 HyperLogLog 。感叹数学真美和烧脑。 |
8 lujiaxing 274 天前 国内大概没啥用. 国内封得厉害. 连 WebRTC 都连不上更何况你这 |
9 cloverzrg2 274 天前 @zzhirong #7 同,我也是想到 postgresql ,不知道作者这个 pg 是什么的缩写呢 |
10 zzhirong 274 天前 @cloverzrg2 PeerGuard “夜幕降临,我的守望始于此,直至死亡将我收走。我不娶妻、不育子、不占有土地;我不争荣誉,不戴王冠;我只在城墙上生、老、病、死。我是黑暗中的剑,是守护 peer 的盾,我以我的生命和荣誉守护 peers ,直到永远。” |
11 vfs 274 天前 最关心这个 “NAT traversal with high success rate” 国内成功率有多少? |
12 sdvfO3n7a6RP18nN 274 天前 via iPhone 这个可以搞 ipc 串流的,请问成功率有测试报告么 |
13 stormtrooperx5 274 天前 跟 libp2p 有啥区别呢 |