一说到软路由,大家都会想到大名鼎鼎的 OpenWrt,不过一般大家通常都是将固件直接刷写为系统直接运行在各类盒子上。之前在树莓派3上用了一段时间发现 OpenWrt 对资源的消耗还是很低的,毕竟我的带宽只有100M,而且树莓派的硬件性能相比传统的路由器还是高了很多。如果让OpenWrt运行在dokcer里将其与底层linux系统解耦,不仅可以利用树莓派的剩余性能去做一些其他的事情,对于 OpenWrt 的备份及迁移来说也更方便。本来很早就想把 pi3 上的 OpenWrt 迁移到 Docker 里去了,无奈只有一个树莓派,虽然是做的旁路网关,但也是挂在主路由器上的,所有的设备上网都会经过,如果迁移又需要要重新刷写 Linux 系统固件,会导致一小段时间的断网,而且上面还有 plex、aria2 的 Docker 在运行,折腾起来又是小半天没了。所以就搁置了一段时间,刚好最近新入手了一块树莓派4的板子,就折腾折腾。

直接刷写 OpenWrt 固件到SD卡作为树莓派系统的方法比较简单,而且相关教程也很多就不写了。本文主要是介绍基于 Docker 运行OpenWrt。请先阅读完文章,再进行相关操作。

更新日志

2020年5月30日 新增 openwrt 镜像拉取及导入方式。

网络方案


开始之前请仔细阅读这一部分

先来说一下网络情况,我的主路由是一台斐讯k2p博通版(也就是金色版),只能刷官改系统。当然使用官改系统也是能进行上网魔法加持的,但是受限于k2p的性能,带宽根本跑不满。故采取了树莓派做旁路网关的方法,这种方法最简单,只需要一根网线把树莓派接入到路由器上即可,对于现有网络侵入性低,而且配置简单、即插即用,甚至可以把树莓派作为便携式魔法上网盒子。简单来说就是把终端的上网流量引流到树莓派上进行魔法加持然后再返回给路由器,那么怎么引流呢?有两种办法:

  • 需要你的路由器上可以配置 DHCP,把 DHCP 分发的网关地址更改为 OpenWrt 的地址。注意:因为是 Docker 运行的 OpenWrt 所以不是树莓派的地址
  • 如果路由器不能自定义配置DHCP(很多都不能),那就需要使用 OpenWrt 来做 DHCP 服务器。只需要关闭路由器上的 DHCP服务即可(基本所有路由器都可以,如果不行说明该换路由器了)

如果你的路由器可以自定义 DHCP 分发的网关地址,那么建议使用第一种方式,就算是树莓派坏了,那么你也还是可以通过 DHCP 连接上路由器做配置。

旁路网关的方法既能弥补路由器的性能短板,同时也解决了树莓派板载无线垃圾的问题。路由器负责无线接入,树莓派负责流量处理,效率更高。

下面我们将在树莓派4上使用 Docker 运行自己编译的 OpenWrt 19.07 固件。并对OpenWrt的部分常用功能进行测试,让你的树莓派不再吃灰。

前期准备


固件介绍与下载

此次教程使用的镜像基于 project-OpenWrt 18.06 固件制作镜像,编译方法及模板来自 SuLingGG https://github.com/SuLingGG/OpenWrt-Rpi 使用Github Actions 编译固件,在此感谢基于官方 OpenWrt 19.07 编译的固件在插件兼容性上还有很多问题,极不稳定。如果是要稳定使用建议使用 Lean 或者 project-OpenWrt 18.06 固件,后面提供的下载链接里都可以下载到。想尝鲜的也可以使用 OpenWrt 19.07 固件。

项目 Github 地址scenerycm/OpenWrt-Raspi
OpenWrt 下载地址如下:

宿主机系统

本文提供的方法只在树莓派3B+/4B测试过,其他设备请自行探索,原理基本一致。

树莓派上可选择的系统有很多,如官方的Raspbian、Ubuntu、Debain等,为了尽量减少不必要的操作,我使用的是由树莓派爱好者基地编译的Debian-Pi-Aarch64树莓派64位系统,后面的所有操作都将基于此系统。详细介绍及下载:https://github.com/openfans-community-offical/Debian-Pi-Aarch64/blob/master/README_zh.md

如果你选择其它系统也是没问题的,只要安装好 Docker 即可,教程百度一大堆,就不详细展开了。

推荐下载无桌面增强版2019-12-30-OPENFANS-Debian-Buster-Aarch64-ext4-v2019-2.0-U2-Release-plus++.img.xz

将镜像烧录到SD卡上,并加点开机后,用网线将树莓派与路由器的lan口相连,在路由器上查看树莓派的IP地址,通过ssh登录树莓派。默认账户:pi ,默认密码:raspberry

登陆以后执行 sudo passwd root,修改root用户密码。执行 passwd修改默认用户 pi密码。

开启root用户远程登录

因为是在内网所以开启远程登陆问题不大,执行 sudo vim /etc/ssh/sshd_config修改 Authentication 配置如下:

# Authentication:

LoginGraceTime 2m
PermitRootLogin yes
StrictModes yes
MaxAuthTries 3
MaxSessions 10

开启sftp方便通过ssh客户端传输文件

同样修改 /etc/ssh/sshd_config文件如下:

# override default of no subsystems
#Subsystem      sftp    /usr/lib/openssh/sftp-server
Subsystem      sftp    internal-sftp

修改完之后保存 /etc/ssh/sshd_config文件,执行 sudo systemctl restart sshd,然后新开一个窗口测试一下使用 root 用户 ssh 登录树莓派。

如果想给树莓派配置静态地址可以修改 /etc/network/interfaces文件,具体地址按需修改,此项可以不做,示例如下:

auto eth0
iface eth0 inet manual

auto macvlan
iface macvlan inet static
  address 192.168.2.110
  netmask 255.255.255.0
  gateway 192.168.2.1
  dns-nameservers 192.168.2.200
  pre-up ip link add macvlan link eth0 type macvlan mode bridge
  post-down ip link del macvlan link eth0 type macvlan mode bridge

至此,系统方面的基础准备已经完成,下面马上开始在 Docker 中运行 OpenWrt。

注:后续所有操作都是使用 root 用户进行。

Docker 网络配置


打开网卡混杂模式

ip link set eth0 promisc on

创建 macvlan 网络

在 Docker 中,macvlan 是众多 Docker 网络模型中的一种,并且是一种跨主机的网络模型,作为一种驱动(driver)启用(-d 参数指定),Docker macvlan 只支持 bridge 模式。相同的 macvlan 之间可以互相通信,不同的 macvlan 网络之间在二层上不能通信,需要借助三层的路由器才能完成通信。做这一步就是让 Docker 中的 OpenWrt容器和路由器等其他终端设备处在同一个二层网络中。

docker network create -d macvlan --subnet=192.168.2.0/24 --gateway=192.168.2.1 -o parent=eth0 macnet

命令解释如下:

  • -d 指定 Docker 网络 driver
  • --subnet 指定 macvlan 网络所在的网络
  • --gateway 指定网关
  • -o parent 指定用来分配 macvlan 网络的物理网卡

很重要 命令中的 --subnet--gateway参数需要根据自己的网络环境修改,切记不要照抄。其中 --gateway就是你的路由器地址,--subnet是你路由器地址所在的网段。

创建完成后可以使用 docker network ls 查看当前主机的网络环境,其中出现了 macvlan 网络 macnet

root@raspbian:~# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
0f209dd7c2a1        bridge              bridge              local
6198a67c49b8        docker_gwbridge     bridge              local
f96fe0754642        host                host                local
95fce42d03d9        macnet              macvlan             local
60c71bbb553b        none                null                local

创建并启动容器


2020年5月30日更新

由于固件编译新增了推送 docker 镜像到 dockerhub, 所以可以直接从 dockerhub 拉取镜像到树莓派。可以使用下面的方法代替 将固件导入 Docker 镜像这一步

拉取镜像

Dockerhub地址:https://hub.docker.com/u/scenerycmopen

选择自己需要的镜像然后点击Tags,复制右上角拉取镜像命令,例如 docker pull scenerycmopen/openwrt-brcm2708-bcm2710-device-rpi-3-offical-openwrt-1907:latest

查看镜像列表 docker image ls

root@raspbian:~# docker image ls
REPOSITORY                                                                 TAG                 IMAGE ID            CREATED             SIZE
scenerycmopen/openwrt-bcm27xx-bcm2711-rpi-4-lean-openwrt                   latest              cd4f35bf9f90        9 days ago          578MB
scenerycmopen/openwrt-brcm2708-bcm2710-device-rpi-3-offical-openwrt-1907   latest              904a2707773f        12 days ago         252MB

然后直接跳转到 启动 OpenWrt 容器 ,根据镜像名称 REPOSITORYTAG 修改创建容器命令。

此步骤已废弃

首先下载编译好的官方固件,提供 Github 和 OneDrive两种下载方式,Github 如果比加慢可以使用 OneDrive。由于OneDrive 容量 有限只提供基于官方源码编译的固件。制作 Docker 镜像需要使用 rootfs 固件别下错了。

稳定使用建议下载 Lean 版固件。

下载好固件之后解压,得到文件 openwrt-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz,通过 sftp 将固件上传至树莓派。

推荐使用 ssh 客户端 MobaXterm 功能强大方便

root@raspbian:/tmp# ls -l
total 181556
-rw-r--r-- 1 root root 185904713 May  4 17:46 openwrt-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz

将固件导入 Docker 镜像

执行命令导入,稍做休息

docker import openwrt-bcm27xx-bcm2711-rpi-4-rootfs.tar.gz openwrt-pi4

查看镜像 docker image ls ,可以看到镜像已经导入成功

root@raspbian:/tmp# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
openwrt-pi4         latest              e33cc215d75d        About a minute ago   485MB

启动 OpenWrt 容器

首先创建容器,命令如下

docker create \
    --restart unless-stopped  \
    --network macnet  \
    --privileged \
    --name openwrt \
    -v /etc/resolv.conf:/etc/resolv.conf \
    -v /mnt/sda1:/home/harddisk/ \
    openwrt-pi4:latest \
    /sbin/init

-v 参数用于挂载宿主机目录到 Docker 容器中,由于未知原因,每次重启 OpenWrt 容器都会导致其 DNS 服务器被修改为 127.0.0.11,导致域名解析失败不能上网,所以使用挂载宿主机 DNS 服务器文件 /etc/resolv.conf 的方式解决此问题。

因为 OpenWrt 中有 smba 文件共享服务功能,所以使用 -v /mnt/sda1:/home/harddisk/ 挂载 /mnt/sda1作为媒体目录。如果不需要也可以不挂载此目录。

创建完成后使用 docker ps -a 查看容器创建情况

root@raspbian:/tmp# docker ps -a
CONTAINER ID        IMAGE                 COMMAND        CREATED           STATUS      PORTS      NAMES
8233c6d29528        openwrt-pi4:latest   "/sbin/init"  50 seconds ago      Created                openwrt

启动容器 docker start openwrt

修改 OpenWrt 容器相关配置

进入容器内部

docker exec -it openwrt bash

修改容器网络配置

vi /etc/config/network

请根据自己的网络情况进行修改,不要照抄,修改后的完整配置如下

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd1d:4f70:9021::/48'

config interface 'lan'
        option type 'bridge'
        option ifname 'eth0'
        option proto 'static'
        option ipaddr '192.168.2.240'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option gateway '192.168.2.1'
        option broadcast '192.168.2.255'
        option dns '192.168.2.240'

重启容器内部网络服务

/etc/init.d/network restart

这里需要提到的一点是,如果你需要同时使用多个OpenWrt容器,那么一定要修改mac地址,因为OpenWrt的固件mac地址都是一样的,不修改mac地址会出现冲突导致网络不稳定。

修改 lan 的 mac 地址 vi /etc/config/network

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd1d:4f70:9021::/48'

config interface 'lan'
        option type 'bridge'
        option ifname 'eth0'
        option proto 'static'
        option ipaddr '192.168.2.240'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option gateway '192.168.2.1'
        option broadcast '192.168.2.255'
        option dns '192.168.2.240'
        option 'macaddr' 'd8:64:c7:5e:f1:c6'

修改 eth0 mac 地址 vi /etc/rc.local,之后重启 OpenWrt 容器 docker restart openwrt

ifconfig eth0 down;ifconfig eth0 hw ether d8:64:c7:5e:f1:c6;ifconfig eth0 up

至此OpenWrt容器的安装及配置部分我们就已经完成了。接下来就是登录 OpenWrt 的 web 页面操作了。

OpenWrt 上网配置

在浏览器输入之前在OpenWrt容器里配置的地址 192.168.2.240,即可打开 OpenWrt 控制面板登陆页。默认密码:password

登录页面
登录页面

状态页面

状态页面
状态页面

第一次配置的时候可能会出现访问有卡住的现象,需要重启一下 OpenWrt 容器,ssh 登录树莓派执行 docker restart openwrt

重启过程中ssh可能会断开,属于正常现象,重连即可。

网络--接口关闭接口的DHCP服务

DHCP 配置
DHCP 配置

配置DNS转发服务器

DNS 配置
DNS 配置

配置好DNS后在网络诊断部分进行网络测试,使用域名baidu.com

网络测试
网络测试

如果此处网络不通,请登录树莓派检查DNS配置文件 /etc/resolv.conf,将 nameserver 设置为 OpenWrt 的地址 。

root@raspbian:~# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 192.168.2.240
search lan

至此上网的部分就基本设置好了,需要魔法加持的,可以先配置好酸酸乳plus或者passwall,再进行下面的测试。

网络及功能测试


然后将电脑的自动获取地址改为手动设置,指定网关为 OpenWrt 的地址 192.168.2.240 进行测试。

手动指定网关
手动指定网关

通过 CMD 查看网关是否配置正确

查看网关
查看网关

Spedtest 网络测试

  • 第一种上网方式,因为我是连的WIFI所以带宽基本上是跑满了。

speedtest测试
speedtest测试

  • 第二种上网方式,速度也很不错,基本跑满服务器的带宽。

speedtest测试
speedtest测试

相关功能截图


使用的皮肤是 Argon

服务
服务

网络存储
网络存储

其他功能
其他功能

系统
系统

注意事项


  • 如果要同时使用多个 OpenWrt 容器,一定要修改容器的 mac 地址,否则会上不了网。
  • 固件中的功能插件不保证可用,建议使用 Lean 版固件,最稳定。
  • 如果要使用 project 版 OpenWrt 固件,可以跳过固件下载与导入步骤直接从dockerhub 拉取镜像,这个镜像经过本人测试在树莓派4和3上都可以使用,而且比较稳定,基本上所有的功能插件都可以使用。

    镜像地址:https://hub.docker.com/repository/docker/scenerycm/openwrt

    拉取方式: docker pull scenerycm/openwrt:19.07

参考