前言

Bilibili 直播有限制推流和在网页上点开播按钮的 IP 都需要是大陆的,不然不给开。为了解除这个限制,我打算用家里的机器和几台国内外的机器用 wireguard(wg) 起 tunnel 组网,然后再用 Nginx 反代 rtmp. 本文将包含 wireguard 的使用,Nginx 的配置。

架构说明

https://img.trumpdns.com/2022/02/08/o5q8rjFV.png
本文想要实现的网络架构是这样的。国内 NAT 和国外机器之间使用 IPv6 连接,本地到国外机器,国内 NAT 到 home 则使用 IPv4. 这么做一个是因为国内 NAT 的商家不让 IPv4 走大流量,还有就是为了优化整个网络的速率。我在使用这套架构之前只用了一台到大陆走的 CN2 机器作为中间节点,可无奈没办法达到要求速率才出此下策。一般情况下来讲,中继节点越多,从起源机器到目标机器所需延迟则越长。但这里为了业务需求只能牺牲一下延迟了。

Wireguard

wireguard 咋装这里就不赘述了,官网写的挺清楚的

配置

先生成一个私钥用于 wg 加密数据,记录一下等下要用到. 这个步骤每台机器都要执行。

wg genkey > private

如果要查看私钥对应的公钥,可以使用 cat private | wg pubkey.

编辑 /etc/wireguard/wg0.conf, 简单写入配置

下面是 home 节点的示例配置。中继节点(在我的架构中:国内 NAT 和国外机器)的配置和这个大同小异,就不单独贴了。

[Interface]
Address = 172.17.87.86/24
SaveConfig = false
MTU =1300
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -j MASQUERADE
ListenPort = 51787
PrivateKey = # 刚刚生成的私钥填在这

[Peers]
Endpoint = # 对端 IP:ListenPort
AllowedIPs = 172.17.87.93/32
PublicKey = # 对端公钥

简单说明一下。wg 是没有明确的客户端和服务端一说的。被链接的两端中的一端有了需求就会去连接另一端。但是两端中有一端需要有公网 IP,或者能被公网访问到的端口。这个端口应该被定义为 ListenPort.
[Interface] 是对本机端口的定义,[Peers] 是针对远端的定义。
PortsUpPortsDown 分别是启动和停止 wg 时执行的命令。这里是把 NAT 做上了,以方便进行 IP 转发。
Endpoint 不是必选的,但是就如上面说的,两台对端之间必须要有一台配置上 Endpoint。两个黑瞎子没法找到对方,总有一个得带盏灯:Endpoint.
AllowedIPs 是走隧道的 IP, 加进去了之后 wg 会自动做好路由。如果需要走隧道的 IP 不加到这里,就算做好了路由也是没办法走隧道的。
MTU 设成 1300 解君愁,管他底层 MTU 是多少,IPv4 还是 IPv6, 跑就完事了。

注意!

要注意,需要走代理的 IP 都要加入 AllowedIPs. 就比如我本机的配置是

AllowedIPs = 172.17.87.86/32, 172.17.87.92/32, 172.17.87.93/32

别忘了启用 IP forward

echo 1 > /proc/sys/net/ipv4/ip_forward

如果还是不行的话,有可能是 NAT 规则的问题。清除重做一下。不过如果你还有别的 NAT 规则别这么玩啊。

iptables -t nat -F
iptables -t nat -A POSTROUTING -j MASQUERADE

Nginx

rtmp 代理我选择用 Nginx 来做。Nginx 需要装一个叫 nginx-rtmp-module 的模块。安装默认是不装的。这里记录下如果用 oneinstack 安装环境的话要怎么弄(我也不太清楚我当初为什么光装一个 nginx 也要用 oneinstack). 编译安装的方法就不记录了。

按照 说明 将文件下载下来后,先别着急运行 install.sh. 找个目录运行

git clone https://github.com/arut/nginx-rtmp-module

这会把我们要用的模块下载下来。如果网络不好你想下压缩包再传到机器上解压也可以,记住路径。编辑 oneinstack 文件夹里的 options.conf,找到 nginx_modules_options='', 改成

nginx_modules_options='--add-module=/Path/To/The/Model'

然后再安装的 Nginx 就包含我们要用的模块了。

配置

nginx.conf 中添加

rtmp {
  server {
    listen	31451;
    chunk_size 4096;
    include /usr/local/nginx/conf/stream-enabled/*;
  }
}

这个要加到最顶层,和 http 块同级。然后放行下端口 31451.

然后创建目录 /usr/local/nginx/conf/stream-enabled, 编辑 default.conf。加入如下内容

application restream {
live on;
record off;

push rtmp://live-push.bilivideo.com/live-bvc/Your_Key;
}

记得把 Your_Key 换成你 B 站的直播密钥。
然后用 obs 推流到 rtmp://内网 IP:31451/restream 就可以了。

后记

感谢 eq, woomai, 老咸鱼和 kirito对我折腾过程中的帮助。下一部的计划是用 ros 来实现这个架构,抛弃 wireguard.

除另有声明外,本博客文章均采用 知识共享(Creative Commons) 署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。