如何在瀏覽器中實現IPFS連接的指引(詳解教程)

我們看到很多關于在瀏覽器里使用js-ipfs的問題。這篇文章展示了用js-ipfs搭建最小化的哈拉應用的例子,這個應用可以在瀏覽器中運行。它使用WebRTC去實現瀏覽器對瀏覽器的連接(在可用時),如不可用則使用回路中繼(Circuit Relay)去連接瀏覽器節點。消息的傳遞是通過libp2p的pubsub功能實現,

獲取代碼

你可以在這里(https://ipfs.io/ipfs/bafybeia5f2yk6td7ciroeped2uwfivo333b524t3zmoderfhl3xn7wi7aa/)查看演示,如果你想要一個可以自行編輯的本地拷貝,可以使用IPFS下載整個目錄:

ipfs get bafybeia5f2yk6td7ciroeped2uwfivo333b524t3zmoderfhl3xn7wi7aa

然后,只要在瀏覽器中打開index.html,就可以立即自動連接到節點并尋找連接資源,

你也可以在GitHub上分叉 heDiscordian/browser-ipfs-chat(https://github.com/TheDiscordian/browser-ipfs-chat) 項目,就可以立刻開始測試了!如果你想部署自己的版本,只要編輯index.html并遵循以下的設置資訊:

在這個例子中使用的庫是js-ipfs 和 Bootstrap (只包含了最小化的CSS樣式文件)。如果你想要一個新版本的js-ipfs,可以下載這個(https://cdn.jsdelivr.net/npm/ipfs/dist/index.min.js) 以獲得最新的可用版本。

讓我們看一下這個過程的工作原理。

目錄表

節點發現和連接(#peer-discovery-and-connectivity)

* Docker容器 (可選)(#docker-optional)

* 創建一個存儲卷(#create-a-volume)

* 配置域名(#configure-a-domain)

* 運行容器(#running-the-container)

WebRTC-Star(#webrtc-star)

* 使用(#usage)

* 設置(#setup)

p2p-circuit(#p2p-circuit)

* 使用(#usage-2)

* 設置(#setup-2)

* 公告(#advertising)

SSL證書 (Nginx)(#ssl-nginx)

* 通訊(#communication)

*PubSub(#pubsub)

*可能存在的瀏覽器問題(#possible-browser-pitfalls)

* 保持與節點的連接(#staying-connected-to-peers)

* 保持與回路中繼的連接(#staying-connected-to-the-circuit-relay)

總結(#conclusion)

節點發現和連接

在瀏覽器中,發現和連接到節點可能是有難度的,因為我們無法監聽新節點,也沒法訪問分布式哈希表(DHT)。為了實現在瀏覽器中運行的最佳體驗,理解如何尋找節點和保持與其的連接是很重要的。

哈拉應用的例子通過兩種方式實現此目標。使用WebRTC-Star,我們實現了直接的瀏覽器對瀏覽器通訊,并配置了兩者之間的回路中繼。

這個哈拉應用也在左上方配置了一個狀態指示器,讓你知道自己的連接種類。綠色表示你連接到了中繼(即便是通過另一個節點來連接);黃色表示你只看到直接連接的節點;紅色表示你沒有連接到節點(至少在哈拉應用中沒有連接),

上圖展示了一個有3名用戶的網路是什么樣子的。值得注意的是瀏覽器節點也可以與 go-ipfs節點通訊,因此,瀏覽器C并不需要是一個瀏覽器,也可以是一個go-ipfs節點,

Docker容器 (可選)

如果你不想使用Docker容器,可以直接跳到WebRTC-Star(#webrtc-star) 的章節,

在這個章節后,我們會涵蓋WebRTC-Star和回路中繼的作用,以及相關的設置方法。不過,如果你想通過Docker快速上手,我已經準備了一個可用的鏡像,它可能不是最佳的長期解決方案,不過如果你只是想快速上手和進行實驗的話,就是很好的方式了。

創建一個存儲卷(volume)

首先,創建一個存儲卷去存儲密鑰和節點數據這樣的長期數據,

docker volume create ipfs_bundle

配置一個域名

你需要一個域名和SSl證書以在瀏覽器節點里使用這個套件。下面有兩個選項:第一個會運行certbot證書機器人程式并自動獲取域名證書。另一個選項不會處理SSl證書,你需要將9091端口反向代理到9090端口(SSL),且4011端口反向代理到4430端口(SSL)。

你可以選擇其中一種方式,然后你的IPFS節點會初始化并提供像 PeerID(節點ID)和回路中繼地址這樣的資訊。

記住,你想將這個資訊編輯到哈拉客戶端里,這樣可以使用自己的節點 (參考 WebRTC-Star 使用(#usage) and p2p-circuit 使用(#usage-2) 以獲得示例,或者編輯 index.html文件并將我的節點的多個地址設定(multiaddresses)換成你自己的。

使用certbot證書機器人

確保80端口沒有被占用,然后對比下面的檢查清單,接著運行下面的命令:

docker run –mount source=ipfs_bundle,destination=/root -p 9091:9091 -p 4011:4011 -p 9090:9090 -p 4430:4430 -p 80:80 -it trdiscordian/ipfsbundle certbot DOMAIN.COM

不使用certbot證書機器人 (禁用SSL證書)

如果你使用這個選項,容器不會處理SSL證書,你需要將9091端口反向代理到9090端口(SSL),且4011端口反向代理到4430端口(SSL),

docker run –mount source=ipfs_bundle,destination=/root -p 9091:9091 -p 4011:4011 -it trdiscordian/ipfsbundle DOMAIN.COM

檢查清單

  • 將DOMAIN.COM替換成你的域名
  • 確保域名被正確指向到容器運行的機器上(子域名也能正常工作)

運行容器

在配置好后,運行容器是很簡單的。最起碼要確保4430端口和9090端口被轉發。

docker run –mount source=ipfs_bundle,destination=/root -p 9091:9091 -p 4011:4011 -p 9090:9090 -p 4430:4430 -it trdiscordian/ipfsbundle

現在你應該將此機器作用WebRTC-Star節點或p2p-circuit節點。

WebRTC-Star

我們可以使用 WebRTC-Star (https://github.com/libp2p/js-libp2p-webrtc-star)節點來幫助發現其他可以直接通過瀏覽器對瀏覽器連接的節點。

如果你已經熟悉了這個概念的話,我覺得可以將此看成跟STUN類似,實際上,每一個連接節點將會被賦予一個WebRTC-Star multiaddress 地址,這樣其他節點可以直接發現和連接到你的瀏覽器,這意味著如果你與其他star節點連接上了,當star節點下線時,你依然保持連接,

使用

連接到一個star節點是很簡單的:

設置

請注意這個例子使用了我自己的star節點,不過,這些節點并不一定可以在任何時候都連接上,當前重要的事情是要么找一個可靠的star節點,要么搭建自己的。

你可以很容易地根據(https://github.com/libp2p/js-libp2p-webrtc-star#rendezvous-server-aka-signaling-server)這里的指示來以原生的方式搭建自己的節點,

也可以根據(https://github.com/libp2p/js-libp2p-webrtc-star/blob/master/DEPLOYMENT.md)這里的資訊來使用Docker容器(包含為SSL功能配置的Nginx),

如果你選擇原生的方式,我們會在這篇文章的后面介紹Nginx反向代理過程和SSL證書取回的方法。

這是一個簡潔、高效的P2P通訊方式,不過有時候NAT網路會帶來障礙。我們使用p2p-circuit 來繞過它。

p2p-circuit

使用 p2p-circuit對在NAT網路(或VPN等)后面的節點是很有用的。我發現p2p-circuit的中繼與TURN(https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT)是很相似的,如果你對那概念熟悉的話,應該就很容易理解了。

使用

當 p2p-circuit的所有服務就緒后,可以用幾種方式連接到節點,首先,在啟動時僅連接到我們的節點:

或者可以之后添加我們自己的節點,然后手動初始化連接:

如果你想不復制例子并實現自己的客戶端,那確保你與公告頻道(announce channel)也在進行通訊,這在公告(#advertising) 這里描述了,在哈拉演示應用中,相關的代碼簡化如下:

設置

就如star節點,你要認識到這篇文章里列出的節點是在任何時候都可能下線的,所以架設自己的節點是很重要的,

為了實踐這個例子,你還需要在架設自己的go-ipfs節點的服務器上做一些事情。你還需要一個可用的Nginx安裝配置,它將會被SSl證書使用,這個證書是瀏覽器所需要的。

首先配置Go節點,啟用WebSocket支持,然后通過編輯~/.ipfs/config并添加以下的設置來將其指定為一個中繼,這樣就可以從瀏覽器里與其通訊了:

以自己習慣的方式重啟go-ipfs節點 (可能是systemctl –user restart ipfs命令),這樣就差不多就緒了,我們已經啟用了支持中繼的常規WebSockets接口,不過還需要安全的WebSockets接口配置(在下面的SSL章節有介紹),否則瀏覽器就無法與我們連接,

公告

使用p2p-circuit可能會有點麻煩,當我們從瀏覽器連接到中繼時,我們并不會向網路公告自己將會通過中繼接受連接,為實現這個目的,我創建了go-ipfs一起使用的Python腳本,它可以通過p2p-circuit multiaddress以及PubSub來公告其發現的瀏覽器js-ipfs節點,

你可以在這里(https://gist.github.com/TheDiscordian/51962fea72f8d5a5c3bba79dd7009e1c) 找到該Python腳本,運行方式可以是python ipfs_peeradvertiser.py 命令,

不過,確保你先以自己的節點資訊編輯 CIRCUIT,否則就無法正確地公告這些節點,這些節點也無法知道如何使用你的中繼連接到其他節點,

你可以簡單地獲取自己的資訊,在你的go-ipfs節點上運行ipfs id命令獲得你的PeerID標識,然后以下面的方式構造回路URL地址:

/dns6/ipfs.YOURDOMAIN.COM/tcp/4430/p2p/YOUR_PEERID/p2p-circuit/p2p/

可以看到,這里只要填入你擁有SSL證書的域名地址,以及自己節點的PeerID標識,在腳本里,前面的斜杠和后面的斜杠都是需要填入的,

注意

根據你的地址類型(IPv4或IPv6),確保你指定了對應的DNS6或DNS4域名解釋服務,使用DNS解析服務是很重要的,否則瀏覽器節點很可能無法連接。同樣要關注4430端口,如果你使用了另一個端口,就需要進行指定,

SSL證書 (Nginx服務)

現在我們在沒有SSL證書的情況下設置了WebRTC-Star和 p2p-circuit(除非你使用了 WebRTC-Star的docker容器方案)。

如果你想在互聯網上通過瀏覽器使用節點,就需要支持SSL證書。如果你使用了當前的默認配置,那么WebRTC-Star應該是在9090端口(非SSL)上運行,而p2p-circuit應該會在4011端口(非SSL)上運行,我們將會把這些端口各自指向給9091端口(SSL)和4430端口(SSL),

首先確保Nginx服務安裝好了,然后獲取并安裝Certbot證書機器人(https://certbot.eff.org/docs/install.html),

我們將從下面的模板創建兩個文件,確保你將類似YOURDOMAIN.COM這樣的配置更改成你實際想用在服務上的完整域名(包含子域名),

在這個例子中,你可以看到我們在4430端口上接受SSL連接,這就是我們的 “wss端口” (安全的WebSocket端口) ,然后轉發到本地的4011非安全端口(即我們的ws端口),因此如果我們想通過瀏覽器連接到這個節點,就使用4430端口。

然后,運行以下命令:

現在Nginx服務已作為反向代理運行,為你提供安全的WebSockets端口了。

通訊

哇!你已經有這么多進展了,可能會想通訊是什么樣子的?幸運的是,相比于節點發現,通訊是非常簡單的,只是可能會有一點小坑。我們將簡單介紹如何在哈拉的例子中使用PubSub(https://docs.libp2p.io/concepts/publish-subscribe/) 并在此過程中發現的一些坑,

PubSub

使用PubSub,我們可以訂閱主題并取回這些主題下發布的資訊,在js-ipfs中,我們可以設置一個回調函數,這樣在收到資訊時就可以得到通知了:

發布也是很簡單的:

這就是這個哈拉演示應用的功能。它訂閱了一個名為”discochat-global”的全局主題,并簡單地將人們輸入的資訊通過PubSub進行中繼。

可能存在的瀏覽器問題

假設你的操作都正確完成了,就可以使用WebRTC-Star和 p2p-circuit來尋找節點。太棒了!不過,你可能會發現連接超時,而且無法恢復。我并不確定這種行為發生的原因(可能是某些瀏覽器策略);不過我們還是可以努力嘗試應對這些問題的!

與節點保持連接

我們有幾種方式與節點保持連接。第一種是更直接的:每隔4秒通過discochat-keepalive訂閱和發送”keepalive”資訊:

這應該能幫助確保我們為有意向哈拉的節點提供更高的優先度,此外,我們每隔15秒通過announce-circuit進行匯報,以確保維持與回路中繼的連接,這樣就可以連接到NAT網路后的節點。可通過以下的方式實現:

在p2p-circuit#使用(#usage)可以找到簡化版本的processAnnounce。

回路中繼上的Python腳本會每隔4秒匯報一個保持活躍連接(keepalive)資訊,你可能已經注意到我們匯報的是 “peer-alive” 而不是”keep-alive”資訊;這是為了將節點請求與中繼請求區分來開,讓我們更容易知道缺乏可用中繼的情況,

與回路中繼保持連接

在processAnnounce的簡化版本之外,在真實的版本中有幾個變量用于追蹤keep-alive和peer-alive資訊,它們各自是lastAlive和lastPeer。我們甚至可以通過lastBootstrap來追蹤最近一次的初始化啟動(bootstrap)時間。

通過這些,我們可以在只連接到節點(通過lastPeer追蹤)時展示黃色的狀態,而在35秒內沒有看到keep-alive資訊時(且沒有在60秒內嘗試初始化啟動時)可以嘗試重新連接到初始化啟動中繼(并展示紅色狀態)。可通過以下的方式實現:

上述方法應該與processAnnounce的完整版本一起使用,因為它依賴于簡化版本中沒有包含的lastAlive和 lastPeer功能,

總結

我希望這些資訊足夠帶你上手了。如果你成功遵循這個指引,你就有能力部署可完全在瀏覽器中運行的功能強大的IPFS應用,并在任何地方利用去中心化的P2P網路,我選擇了一些有用的資源并分享在下面以供進一步閱讀:

  • js-ipfs/docs/BROWSERS.md(https://github.com/ipfs/js-ipfs/blob/master/docs/BROWSERS.md)
  • js-ipfs/docs/CONFIG.md(https://github.com/ipfs/js-ipfs/blob/master/docs/CONFIG.md)
  • js-ipfs/docs/core-api(https://github.com/ipfs/js-ipfs/tree/master/docs/core-api)
  • js-ipfs/examples/circuit-relaying(https://github.com/ipfs/js-ipfs/tree/master/examples/circuit-relaying)
  • js-libp2p-webrtc-star(https://github.com/libp2p/js-libp2p-webrtc-star)

0 条回复 A文章作者 M管理員
    暫無討論,說說你的看法吧