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

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

獲取代碼

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

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

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

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

在這個例子中使用的庫是 js-ipfs(https://github.com/ipfs/js-ipfs/blob/master/docs/BROWSERS.md) 和 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,我們實現了直接的瀏覽器對瀏覽器通訊,並配置了兩者之間的迴路中繼。這個聊天應用也在左上方配置了一個狀態指示器,讓你知道自己的連接種類。綠色表示你連接到了中繼(即便是通過另一個節點來連接);黃色表示你只看到直接連接的節點;紅色表示你沒有連接到節點(至少在聊天應用中沒有連接)。

網絡圖表展示路徑中的節點可以彼此間發現和通訊 (https://ipfs.io/ipfs/QmX2og5BKJCMVaebEm9ZGsACEYExoGqxhJjePKNc2mZ2pE "Browser IPFS network graph")

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

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

🐳 Docker 容器 (可選)

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

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

創建一個存儲卷(volume)

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

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

配置一個域名

你需要一個域名和 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 端口沒有被佔用,然後對比下面的檢查清單,接着運行下面的命令:

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

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

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

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

📝 檢查清單

  • 將 DOMAIN.COM 替換成你的域名

  • 確保域名被正確指向到容器運行的機器上(子域名也能正常工作)

運行容器

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

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

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

🌟 WebRTC-Star

我們可以使用 WebRTC-Star(https://github.com/libp2p/js-libp2p-webrtc-star) 節點來幫助發現其他可以直接通過瀏覽器對瀏覽器連接的節點。我覺得可以將此看成跟 STUN(https://en.wikipedia.org/wiki/STUN) 類似,如果你已經熟悉了這個概念的話。實際上,每一個連接節點將會被賦予一個 WebRTC-Star multiaddress(https://docs.libp2p.io/concepts/addressing/) 地址,這樣其他節點可以直接發現和連接到你的瀏覽器。這意味着如果你與其他 star 節點連接上了,當 star 節點下線時,你依然保持連接。

使用

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

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

設置

請注意這個例子使用了我自己的 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(https://docs.libp2p.io/concepts/circuit-relay/) 來繞過它。

⚡ p2p-circuit

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

使用

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

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

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

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

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

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

設置

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

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

首先配置 Go 節點,啓用 WebSocket(https://en.wikipedia.org/wiki/WebSocket) 支持,然後通過編輯~/.ipfs/config 並添加以下的設置來將其指定爲一箇中繼,這樣就可以從瀏覽器裏與其通訊了:

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

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

公告

使用 p2p-circuit 可能會有點麻煩。當我們從瀏覽器連接到中繼時,我們並不會向網絡公告自己將會通過中繼接受連接。爲實現這個目的,我創建了 go-ipfs 一起使用的 Python 腳本,它可以通過 p2p-circuit multiaddress(https://docs.libp2p.io/concepts/addressing/) 以 PubSub(https://docs.libp2p.io/concepts/publish-subscribe/) 來公告其發現的瀏覽器 js-ipfs 節點。

你可以在這裏 (https://gist.github.com/TheDiscordian/51962fea72f8d5a5c3bba79dd7009e1c) 找到該 Python 腳本,運行方式可以是 python ipfs_peeradvertiser.py 命令。不過,確保你先以自己的節點信息編輯 CIRCUIT,否則就無法正確地公告這些節點,這些節點也無法知道如何使用你的中繼連接到其他節點。

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

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

可以看到,這裏只要填入你擁有 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 這樣的配置更改成你實際想用在服務上的完整域名(包含子域名)。

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

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

然後,運行以下命令:

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

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

🌐 通訊

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

📰 PubSub

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

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

發佈也是很簡單的:

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

這就是這個聊天演示應用的功能。它訂閱了一個名爲 "discochat-global" 的全局主題,並簡單地將人們輸入的信息通過 PubSub 進行中繼。

⚠️ 可能存在的瀏覽器問題

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

與節點保持連接

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

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

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

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

🌟 在 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 秒內嘗試初始化啓動時)可以嘗試重新連接到初始化啓動中繼(並展示紅色狀態)。可通過以下的方式實現:

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

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

🎉 總結

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

如果您也對 Filecoin 感興趣,歡迎瞭解更多內容:

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

掃碼關注我們

微信號|Filecoin-Official