Rock Pi4 中用 Docker 容器搭建 OpenWRT 做旁路由

Posted by 风舞山湖博客 on Thursday, November 18, 2021

前阵子在海鲜市场上入手一个 Rock Pi 4B, 4GB RAM, 16G eMMC,400 大洋,包散热器和电源。Rock Pi 4B 也很新,总体感觉比较划算,无论性能还是价格都优于树梅派4。另外花费 90 元购买 M.2 SSD 扩展板,180 元 240GB NVME SSD。Rock Pi 4B 上使用 NVME SSD 还有个小插曲。第一次买的是朗科的 NVME SSD,直接插 Rock Pi 4B 上没有问题。但加了 M.2 SSD 扩展板后初始化 NVME SSD 会引起 CPU 复位。最后换了一块铭宣的则没有任何问题。进入正题,下面说说整个搭建过程。

首先是选择 OS。由于需要跑 Docker,个人倾向于使用 mainline kernel。在经历自己编译 U-Boot, Linux kernel 和移植 Ubuntu rootfs 后,还是放弃了。转投 armbian 生态。他们提供了 mainline U-Boot 和 kernel,社区也很不错。

 ____            _          _   _  _   ____  
|  _ \ ___   ___| | ___ __ (_) | || | | __ ) 
| |_) / _ \ / __| |/ / '_ \| | | || |_|  _ \ 
|  _ < (_) | (__|   <| |_) | | |__   _| |_) |
|_| \_\___/ \___|_|\_\ .__/|_|    |_| |____/ 
                     |_|                     
Welcome to Armbian 21.08.1 Focal with Linux 5.10.60-rockchip64

接下里是安装 docker。Armbian 发行版也是基于 debian,所有可以很方便使用 apt 安装软件。这里安装 docker 的方法就不再重复。为了编译管理容器,特别接下来还算打运行其他容器,这里也就安装 portainer/portainer-ce:latest。

docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

OpenWRT 容器使用的是 suling/openwrt:rpi4。都是 Armv8 CPU,所以在 Rock Pi 4B 运行完全没有问题。

OpenWRT 容器将用独立的 IP 运行,这就需要在 docker 中创建一个 macvlan 网络,使 OpenWRT 可以直接访问物理网卡。在 portainer 中可以很便捷地创建。这里需要注意的 IP 设置。我的网络中 Rock Pi 4B 的 OpenWRT 作为二级路由。它可以通过 DHCP 获取到一个 192.168.20.0/24 网段中的 IP。所以 macvlan 网络也使用该网段。 macvlan.png

然后使用创建好的网络启动 OpenWRT 容器。

docker run -d --name openwrt --restart always --network macnet --privileged \
-v /lib/modules/5.10.60-rockchip64:/lib/modules/5.10.60-rockchip64 \
registry.cn-shanghai.aliyuncs.com/suling/openwrt:rpi4 /sbin/init

macvlan 网络会从 192.168.20.1 以后的 IP 中依次分配给容器,并不会和网络中现有的 DHCP 协商。所以 DHCP 服务器的 IP 地址池最好避开这些 IP。-v /lib/modules/5.10.60-rockchip64:/lib/modules/5.10.60-rockchip64 用于将 Armbian 的内核模块挂载到 OpenWRT,其中不少功能需要动态加载内核驱动模块。这时应该可以看到运行的容器了。 running-containers.png

进入容器中做一些基础的配置。 console-in-container.png

修改 /etc/config/network 配置网络接口。由于只有一个网卡,默认为 LAN,设置静态 IP 地址、网关和 DNS。

config interface 'lan'
        option type 'bridge'
        option ifname 'eth0'
        option proto 'static'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option ipaddr '192.168.20.2'
        option gateway '192.168.20.1'
        option dns '192.168.2.1'

修改/etc/rc.local ,停止看门狗。当重启 OpenWRT 容器时,由于无法正确停止看门狗,会导致整个 Armbian 系统因看门狗超时而复位。关闭看门狗也有个副作用,OpenWRT 容器在运行期间宕机,就无法及时重启。除了将下面两个命令保存到 /etc/rc.local中,也可以同时在命令行中先运行。这样的话待会儿如果关闭容器就不会引起复位。

ubus call system watchdog '{"magicclose":true}'
ubus call system watchdog '{"stop":true}'

不要忘记用 passwd 命令设置 root 用户的密码。

重启容器后,就可以用上面配置的 IP 192.168.20.2 登录网页管理界面。登录名为root,密码是上面所设置的。进入“网络”->“接口”->“LAN”->“修改”,禁用 LAN 接口上的 DHCP 服务。OpenWRT 作为旁路由,DHCP 功能由其他路由器负责。 disable-dhcp-on-lan.png

进入“网络”->“防火墙”->“自定义规则”,注释掉原来的iptables -t nat -I POSTROUTING -j MASQUERADE,添加 iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE,实现单臂路由功能。点击“重启防火墙”。最后重启 OpenWRT 容器。

# iptables -t nat -I POSTROUTING -j MASQUERADE
iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE

我将另外一个路由器 WAN 的网关和 DNS 指向 OpenWRT LAN 的 IP。这个路由器下的所有设备即可通过 OpenWRT 上网。基本功能已经实现。接下来则要开始在 OpenWRT 上增加其他服务,如 mosdns, Xray, Wireguard 等。

关于双网口。双网口做主路由的方法似乎会更好。我尝试增加一块 USB3.0 千兆网卡,这样两个网口都可以跑满千兆。Rock Pi 4B 整体功耗会增加 1.2W,达到 4.2W 左右。使用当网口做旁路由,实际测试在700M 左右,并没有很大的下降,况且宽带也就 300M。在创建容器的时候只能指定一个 macvlan 网络,当连接第二个 macvlan 时,OpenWRT 并不能识别添加的网络。用 debian 容器进行同样的测试,则可以看到两个网络。这可能和 OpenWRT 初始化网络的机制有关,暂时没有弄明白。最终还是决定用单网口方案。

之所以采用容器方式来运行 OpenWRT,主要还是处于好奇和折腾。当然也带了一些好处。把配置的容器打包成 image 后,将来可以很方便地部署到其他类似 Rock Pi 的板子上。如果这个容器在运行时出现异常,立马另起一个容器也是很便捷的。不会导致长时间断网。