最近在工作上实在是绷不住微信电话和腾讯会议了,因此决定寻找一些能够自部署的方案

Hanamaru一直有运营一个Mumble服务器,所以先为这个服务器部署一个Web的前端

本来以为会是相当简单的一件事顺手就弄了,结果困难重重。主要还是没事先了解原理导致实践时不知所措被水淹没。故写文纪念

如果你也想部署Mumble的web端,请重点关注本文原理部分

选择

  • Mumble-Web

    选择了当年的Mumble Web项目,但是已经停止维护了,内部的许多依赖都已弃用

  • Mumbling-mole

    目前活得最远的fork,但是似乎是Mumble-Web的阉割版,故没有选择。不过读者可以尝试

Mumble Web 的连接原理

    graph LR

C[Mumble Web Client]

T[TLS Layer<br>e.g. nginx reverse proxy]

subgraph P [proxy]
    direction TB
    PH(Websocket<br>TCP port<br>e.x. 64737)
    PL(ICE<br>UDP port<br>e.x. 20000 - 20500)

end

S[Mumble server<br>e.x. A murmur on<br>port: TCP & UDP 64738]

%% C <-- 1\. Control(TCP packets) through Websocket<br><br>Negotiate the ICE port --> PH
C <-- 1\. Control(TCP packets) through WebSocket<br><br>Negotiates ICE port --> T
T <--> PH

C <-- 3\. Voice through WebRTC protocol --> PL

P <-- 2\. Control --> S
P <-- 4\. Translate WebRTC to Mumble, then Voice through Mumble protocol --> S

Cn[Native Mumble Client] <-- Just uses Mumble Protocol ---> S

Sw[Mumble Server that support WebRTC]

Cn <-- Mumble protocol ----> Sw
C <-- WebRTC protocol ---> Sw

style Cn fill:#eee, stroke:#555
style Sw fill:#eee, stroke:#555

对于大多数人部署的官方mumble-server(Murmur),其只能使用mumble协议来通信。而显而易见的是在浏览器环境很难原生实现mumble协议。因此Mumble Web在浏览器中的语音是基于WebRTC协议的。因此,连接时需要一个协议的转换器(即mumble-web-proxy)。当然这个转换器肯定放不到用户端,因此我们需要同时部署Mumble-Web静态网页和mumble-web-proxy

Mumble Web是一个静态网页,build后web server运行即可

部署mumble web proxy,需要同时开放

  • WebSocket TCP端口(控制端口),用于浏览器与 proxy 之间的控制通道(协商、登录、音轨信息等)
  • 供WebRTC使用的一组ICE UDP端口(语音端口)
    • 这与WebRTC的点对点连接有关,一个WebRTC的连接会建立一次ICE,独占一个UDP端口

以允许Web客户端与proxy建立连接,另外proxy需要能连接到mumble server(废话)。

如果你真的希望把web环境当作你们mumble使用的主力,也可以考虑部署一个支持WebRTC的mumble服务器,我没有实践,请参考:

Build & Deploy

Mumble Web

项目地址:https://github.com/Johni0702/mumble-web

由于不再维护,必须使用node14及以下的版本来构建。我使用了node:14镜像来构建,建议使用nvm来调整node版本。构建结果为一个dist文件夹。使用web server服务即可

话说都停止维护了应该放个release的说..

这个仓库的本地化目前有问题,会导致加载缓慢。使用英文环境进入是没问题的

Proxy

项目地址:https://github.com/Johni0702/mumble-web-proxy

使用rust cargo构建。作者建议使用rust v1.39的版本来编译,如果使用新版rust有一些值得注意的问题:

  • 若libssl持续缺库:修改cargo.toml: openssl = "0.10.38"

  • 编译rtp时出现error[E0282]: type annotations needed

    https://github.com/Johni0702/mumble-web-proxy/issues/31#issuecomment-920449505

    尝试修改cargo.toml: rtp = { git = "https://github.com/Skgland/rtp", rev = "83eb4dd", features = ["rfc5764-openssl"] }

  • 还是rtp,若出现

    help: consider removing the borrow
        |
    822 -     output.reserve_exact(n.next_multiple_of(&16));
    822 +     output.reserve_exact(n.next_multiple_of(16));
        |
    

    照它说的改一下源临时依赖文件就行

其他过程中缺库安装即可。

配置TLS

用nginx等工具为proxy挂载证书并配置反代即可

运行

先跑proxy:

/path/to/mumble-web-proxy \
  --listen-ws 64737 \
  --server your.mumble.server:64738 \
  --accept-invalid-certificate \
  --ice-port-min 20000 \
  --ice-port-max 20256 \
  --ice-ipv4 114.51.41.91
  • --server:应该使用外部名称,用于验证证书
  • --accept-invalid-certificate:如果是自签证书需加上

打开设置好的端口,本例中为64747 TCP,20000-20256 UDP。ice端口的数量视服务器的最大连接数量而定,一般几百个就够用。

随后打开Mumble-web,连接字符串的拼接规则为:wss://{server}:{port}(很怪)。

因此,以我的部署为例,我的wss地址(反代后)为wss://dedfaf.tech/mumble,则需要填server: dedfaf.tech, port: 443/mumble,若服务器有密码则填入密码栏

以上参数可以从url带入,也可以修改静态网页地址下的config.js来设置默认值

总结

以上这些卡了我两天,论实践前了解原理的重要性…