diff --git a/_layouts/default.html b/_layouts/default.html index d814646b9..af7904353 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -23,7 +23,7 @@ $("#code").qrcode({ width: 100, height: 100, - text: "http:{{ site.url }}{{ page.url }}" + text: "{{ site.url }}{{ page.url }}" }); diff --git a/_posts/2024-02-23-openwrt-in-a-docker-container.md b/_posts/2024-02-23-openwrt-in-a-docker-container.md new file mode 100644 index 000000000..e9f22d25b --- /dev/null +++ b/_posts/2024-02-23-openwrt-in-a-docker-container.md @@ -0,0 +1,233 @@ +--- +layout: post +title: "Docker 中运行 OpenWrt" +category: Linux +tags: [Docker, OpenWrt] +--- + +玩 OpenWrt 几年,各种 x86/arm 软路由,各种盒子做旁路网关,一圈下来,最后回到了玩客云刷 Armbian,其内安装 Docker,将 OpenWrt 跑在 Docker 容器内作旁路网关为结局。 + +作为家用,性能足够,价格也足够便宜,到写这篇文章时,海鲜市场的价格大概 30 块左右包邮。 + +如何短接触点刷机,略过不表,如何刷 Armbian 略过。这篇文章只是用来记录,在 Armbian (Debian) 下将 OpenWrt 运行起来的流水记录。 + + + +### 安装 Docker + +完全照着 Docker 官方文档来,只不过在最后镜像这一块替换成国内的源。 + +卸载掉 Debian 社区版 Docker + + $ for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done + +添加 Docker 的官方 GPG key: + + $ sudo apt-get update + $ sudo apt-get install ca-certificates curl + $ sudo install -m 0755 -d /etc/apt/keyrings + $ sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc + $ sudo chmod a+r /etc/apt/keyrings/docker.asc + +添加 apt 源,这里我换成了国内上交大的源 + + $ echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ + https://mirror.sjtu.edu.cn/docker-ce/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + $ sudo apt-get update + +接下来安装 Docker + + $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + $ sudo docker info + +我需要打开 Docker IPv6,以及替换 Docker 镜像源为国内上交大源。编辑文件 **/etc/docker/daemon.json**,没有的话创建它。 + + $ vi /etc/docker/daemon.json + { + "experimental": true, + "ip6tables": true, + "registry-mirrors": [ + "https://docker.mirrors.sjtug.sjtu.edu.cn" + ] + } + $ sudo systemctl restart docker.service + +至此,Docker 准备工作完成。 + +#### IPv6 转发 + +内核参数也需要打开 IPv6 的转发 + +临时 + + $ for nic in default eth0 all; do sudo sysctl -w net.ipv6.conf.$nic.forwarding=1; sudo sysctl -w net.ipv6.conf.$nic.accept_ra=2; done + +持久 + + $ sudo vi /etc/sysctl.conf + ... + net.ipv6.conf.default.forwarding = 1 + net.ipv6.conf.all.forwarding = 1 + # Setting accept_ra to 2 allows RAs to be accepted even when forwarding = 1. + net.ipv6.conf.default.accept_ra = 2 + net.ipv6.conf.all.accept_ra = 2 + ... + + +### NIC promiscuous 模式 + +临时打开的方式 + + $ sudo ip link set dev eth0 promisc on + +永久打开的方式,如果你的网络管理器为 NetworkManager 的话 + + $ vim /etc/NetworkManager/dispatcher.d/50-promisc + #!/usr/bin/env bash + # + case "$2" in + up) + if [[ "$1" = "eth0" ]] || [[ "$1" = "eth1" ]]; then + ip link set dev $1 promisc on + fi + ;; + esac + $ sudo chmod +x /etc/NetworkManager/dispatcher.d/50-promisc + +systemd 管理网络的可以看这里:[打开网卡的 promiscuous 模式]({% post_url 2023-02-18-enable-promiscuous-mode-on-nics %}) + +至此,环境配置工作完成。 + +### 制作镜像 + +直接去 github 上以 **onecloud openwrt** 为关键词去搜索,总是会找到你心仪的固件,如果没有,那就自己编译一个吧,这里略过不表。这里默认你已经下载到固件,名为 openwrt-meson-meson8b-thunder-onecloud-ext4-sdcard.img.gz + +#### 挂载 img + + $ gzip -d openwrt-meson-meson8b-thunder-onecloud-ext4-sdcard.img.gz + $ sudo losetup -fP openwrt-meson-meson8b-thunder-onecloud-ext4-sdcard.img + # 确认下是哪个 loop 设备 + $ sudo losetup -a + # 譬如是loop0,准备挂载吧 + $ sudo mkdir -p /mnt/img; sudo mount /dev/loop0p2 /mnt/img + +#### 复制,打包 rootfs + + $ sudo mkdir -p /mnt/openwrt; sudo cp -rpf /mnt/img/* /mnt/openwrt/ + $ sudo tar cvf /mnt/rootfs.tar -C /mnt/openwrt . + +#### 导入 Docker 镜像 + + $ sudo docker import /mnt/rootfs.tar openwrt:onecloud + $ sudo docker images -a + +至此,镜像已经准备好。 + +### 容器测试 + +#### 容器网络 + +下面终于开始进入最终环节了,让我们先创建个 macvlan 网络,这里我打开 ipv6 支持 + + $ sudo docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 --ipv6 --subnet=fd00::/80 -o parent=eth0 openwrt_macvlan + +可以查看是否创建正确 + + $ sudo docker network inspect openwrt_macvlan + +#### 创建容器 + + $ sudo docker run -d --restart=on-failure:3 --name openwrt --network openwrt_macvlan --cap-add=NET_ADMIN --device=/dev/net/tun openwrt:onecloud /sbin/init + +有些固件,带某功能的,可能需要 privileged 模式 + + $ sudo docker run -d --restart=on-failure:3 --name openwrt --network openwrt_macvlan --privileged --device=/dev/net/tun openwrt:onecloud /sbin/init + +#### 容器设置 + +根据固件获取 ip 方式的不同,需要进容器做一些设置,譬如 IPv4 IPv6。 + + $ sudo docker exec -it openwrt sh + # vi /etc/config/network + ... + config interface 'lan' + option device 'eth0' + option proto 'static' + option ipaddr '192.168.1.200' + option netmask '255.255.255.0' + option gateway '192.168.1.1' + list dns '119.29.29.29' + list dns '223.5.5.5' + option delegate '0' + ... + config interface 'wan6' + option proto 'dhcpv6' + option device 'eth0' + option reqaddress 'try' + option reqprefix 'no' + +随后可以打开网页控制台,做进一步设置。 + +#### docker compose + +你也可以用 docker compose 方式,创建 docker-compose.yml,这样前面可以不用手动创建网络,与运行容器了。 + + services: + openwrt: + image: openwrt:onecloud + container_name: openwrt + hostname: openwrt + networks: + openwrt_macvlan: + networks: + openwrt_macvlan: + driver: macvlan + driver_opts: + parent: eth0 + enable_ipv6: true + ipam: + driver: default + config: + - subnet: 192.168.1.0/24 + gateway: 192.168.1.1 + - subnet: fd00::/80 + +如果想使用前面手动创建的网络,那么可以这样 + + services: + openwrt: + image: openwrt:onecloud + container_name: openwrt + hostname: openwrt + networks: + external: + networks: + external: + name: openwrt_macvlan + external: true + +运行一下看看 + + $ sudo docker compose up -d + +#### 保存容器 + +为了下一次不再重复设置,将当前的容器存储为镜像 + + $ sudo docker ps -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + xxxxxxxxxxxx openwrt:onecloud "/sbin/init" 4 days ago Up 4 days openwrt + $ sudo docker commit xxxxxxxxxxxx openwrt:onecloud + +#### 备份镜像 + + $ sudo docker save openwrt:onecloud -o rootfs-onecloud.tar + +参考: + +- +- +-