blog
blog copied to clipboard
在docker中运行openwrt
docker 中运行 openwrt
[toc]
思路
利用 macvlan
方式创建虚拟接口进行配置。
有感于来自恩山 betterman 及 rightwifi2017 两位大佬斐讯 N1 的玩法,也获得两位大佬的帮助,在此感谢两位大佬。
由于 N1 为单网卡,所以配置只能为单臂路由,本案为双网卡 opewnrt
机器拥有双网卡: enp1s0
及 enp3s0
,本案将 enp3s0
用作 LAN
口,enp1s0
用作 WAN
口。
0. 安装 docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
1. 配置系统环境
#打开网卡混杂模式
ip link set enp1s0 promisc on
ip link set enp3s0 promisc on
#加载 PPPOE 内核模块
modprobe pppoe
2.docker 网络配置
# 为 docker 创建 macvlan 虚拟接口,并链接到 host 网卡
# LAN 口
docker network create -d macvlan \
--subnet=10.1.1.0/24 --gateway=10.1.1.1 \
--ipv6 --subnet=fe80::/16 --gateway=fe80::1 \
-o parent=enp3s0 \
-o macvlan_mode=bridge \
dMACvLAN
# WAN 口
docker network create -d macvlan \
--subnet=192.168.254.0/24 --gateway=192.168.254.1 \
--ipv6 --subnet=fe81::/16 --gateway=fe81::1 \
-o parent=enp1s0 \
-o macvlan_mode=bridge \
dMACvWAN
3. 创建容器
#导入镜像
docker import https://downloads.openwrt.org/releases/18.06.1/targets/x86/64/openwrt-18.06.2-x86-64-generic-rootfs.tar.gz openwrt:18.06.2
#创建并启动容器
docker run -d \
--restart unless-stopped \
--network dMACvLAN \
--privileged \
--name openwrt \
openwrt:18.06.2 \
/sbin/init
#将第二网卡的 macvlan 挂接到 openwrt
docker network connect dMACvWAN openwrt
4. 配置 openwrt
#进入容器
docker exec -it openwrt /bin/sh
#编辑 / etc/config/network
config interface 'lan'
option type 'bridge'
option ifname 'eth0' # 需要与 docker netwrok 中的虚拟接口匹配(dMACvLAN)
option proto 'static'
option ipaddr '10.1.1.254'
option netmask '255.255.255.0'
option ip6assign '60'
config interface 'wan'
option ifname 'eth1' # 需要与 docker netwrok 中的虚拟接口匹配(dMACvWAN)
option proto 'dhcp'
option ip6assign '60'
#重启 openwrt 网络
/etc/init.d/network restart
5. 宿主机出口
由于 docker
网络采用 macvlan
的 bridge
模式,即使宿主机与容器在同一网段,相互之间也是无法通信的。
为了解决这个问题,需利用多个 macvlan
接口之间是互通的原理,在 LAN
口新建一个 macvlan
虚拟接口:
# 使用 ip 命令
ip link add link enp3s0 hMACvLAN type macvlan mode bridge # 在 enp3s0 接口下添加一个 macvlan 虚拟接口
ip addr add 10.1.1.2/24 brd + dev hMACvLAN # 为 hMACvLAN 分配 ip 地址
ip link set hMACvLAN up
ip route del default #删除默认路由
ip route add default via 10.1.1.254 dev hMACvLAN # 设置静态路由
echo "nameserver 10.1.1.1" > /etc/resolv.conf # 设置静态 dns 服务器
# 或者使用 nmcli
nmcli connection add type macvlan dev enp3s0 mode bridge ifname hMACvLAN autoconnect yes save yes
或者,若是在 debian 中可以编辑 /etc/network/interface
并加入:
auto hMACvLAN
iface hMACvLAN inet static
address 10.1.1.2
netmask 255.255.255.0
gateway 10.1.1.254
pre-up ip link add hMACvLAN link enp3s0 type macvlan mode bridge
post-down ip link del hMACvLAN link enp3s0 type macvlan mode bridge
6. 配置客户端 IP&enjoy
后续就是 openwrt 的玩法,除了没有 wifi,其他基本一致。有一点,若需要加载内核模块,则需要在 host 中事先加载
能否写一下如何在docker中使用openwrt,我没有测试成功
佩服博主的抽象思维能力,配网络都不用画图。
另外: 第五步中的关于去修改宿主机路由规则的命令: ip route del default #删除默认路由 ip route add default via 10.1.1.254 dev hMACvLAN # 设置静态路由 echo "nameserver 10.1.1.1" > /etc/resolv.conf # 设置静态 dns 服务器
建议是不要动宿主机的路由,删除宿主机的默认路由在很多场景下还是比较危险的,我的做法是: 在宿主机上执行SNAT iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o ens192 -j MASQUERADE
而后在容器中配置路由: ip route add default via 10.1.1.2 dev br-lan
其实觉得如果在容器起来的时候使用--net host 会更加简单,后面加MacVlan网卡和配路由应该都不用弄了,但是没有测试过
@WinterXMQ 使用方法和正常的 openwrt 无异,不知道没有测试成功指的是?
@pingod 嗯,用 iptables 也可以,好处是不用改主机默认路由,但是流量会再转发一次。 --net host 我也没测试过,应该是可以的,macvlan 是起到网络虚拟化作用的,对于强迫症应该不喜欢用 host
我家里的宽带网络是直接DHCP获取公网ip的。我是在双网口群辉Docker跑Openwrt的,打算拿来做主路由。按照博主的教程配置好了以后,插网线到WAN口,但是公网ip就直接被群辉获取了,Openwrt根本无法获取到,请问这种情况,我完全按照上面的教程去做可以啦?
@darktitty 首先我不确定群晖内核模块是否完全能够支持 Openwrt
群晖需要关闭 DHCP,同时,网线必须对应 Openwrt WAN 侧,并且在群晖中新建一个 macvlan 虚拟接口(对应 Openwrt LAN 侧的那个网卡),这样才能通过 Openwrt 来上网。
奇怪的是 我执行第五步以后 openwrt就连不上啦 晚点我试试在Debian上搞搞看
新编译的rootfs.tar.gz拖进docker启动后,web显示不正常:luci web响应速度比较慢,首页网口信息显示“正在收集”无信息显示,工作时间和负载也是空白,能ping通网关。 之前编译的正常,不知道什么原因。
@kanshudj 不清楚原因,应该是镜像的关系,感觉是占用过高?可以查一下 cpu 的占用率
奇怪的是 我执行第五步以后 openwrt就连不上啦 晚点我试试在Debian上搞搞看
你好,群晖里的docker能访问到吗?试了很多次了, 还是访问不了docker中的openwrt?
@darktitty 首先我不确定群晖内核模块是否完全能够支持 Openwrt
群晖需要关闭 DHCP,同时,网线必须对应 Openwrt WAN 侧,并且在群晖中新建一个 macvlan 虚拟接口(对应 Openwrt LAN 侧的那个网卡),这样才能通过 Openwrt 来上网。
请教一下,docker中运行openwrt需要哪些内核模块呢?在群晖里的docker装上了,就是没法访问
@ywjdlq 我折腾了好久没成功 都放弃啦…
@ywjdlq 没有在群晖中使用过,由于群晖内核裁剪的比较厉害,我有空的时候装个黑群晖试一下
@lisaac 尝试过了吗?我看openwrt内核都到4.15了,群晖的3.10
@ywjdlq 还没,最近在忙其他项目,抽空试一下
@ywjdlq
抽空刚刚在虚拟机黑裙中试了一下,是可以进luci界面的,没有做过多测试
如果是单网口,可能需要先停用firewall:
/etc/init.d/firewall sotp
docker 中的openwrt 外网和网关都不通。。
成功配置双网卡。但添加第三个网卡作为第二LAN口后,wan口就无法pppoe拨号了。 操作方法是docker中新建第三个macvlan网络,用了不同的网段,绑定第三个网卡,之后将新的macvlan链接到openwrt的容器。 求教了,多谢。
@deepline1986 感觉应该不会有问题,无法拨号具体表现是什么? 另外可以试一下在宿主建立bridge-lan,然后在bridge-lan上建macvlan,挂进docker
@deepline1986 感觉应该不会有问题,无法拨号具体表现是什么? 另外可以试一下在宿主建立bridge-lan,然后在bridge-lan上建macvlan,挂进docker
@lisaac 在宿主机给容器连接第二个lan口的macvlan,分两种情况。
- 在openwrt中添加lan的interface,完成后,新lan口工作正常,上网,但重启宿主机后wan口拨号失效。
- 不在openwrt中添加lan的interface,直接重启宿主机,之后wan口同样拨号失效。 wan拨号的错误信息如下。
Protocol: PPPoE
RX: 0 B (0 Pkts.)
TX: 0 B (0 Pkts.)
Error: Connection attempt failed
在宿主机给容器断开第二个lan口的macvlan,重启宿主机,wan口拨号恢复正常。
另外,请问宿主机建立bridge-lan,是分割wan口和lan口,还是别的理解?谢谢。
@deepline1986 由于没有环境,没有测过,按道理来讲,应该不会出现这个问题,如果有结果请 po 出来,谢谢。
另外,关于网桥的方案,我也没测试过,只是一个想法:
在宿主机上在两个lan
口上建立bridge-lan
,然后把bridge-lan
看成双网口方案中的lan
口,按照双网口方案进行部署
@deepline1986 由于没有环境,没有测过,按道理来讲,应该不会出现这个问题,如果有结果请 po 出来,谢谢。
另外,关于网桥的方案,我也没测试过,只是一个想法: 在宿主机上在两个
lan
口上建立bridge-lan
,然后把bridge-lan
看成双网口方案中的lan
口,按照双网口方案进行部署@lisaac 已经找到问题了,根据测试结果显示,openwrt内ethX的排序,是按照连接中的macvlan网络的命名的顺序来的。 例如四个物理网卡,对应四个macvlan网络,我们希望发生下面这样的配对
计划: 网卡1 => dMACvLAN1 => eth0 网卡2 => dMACvWAN => eth1 网卡3 => dMACvLAN3 => eth2 网卡4 => dMACvLAN4 => eth3
实际添加之后,如果重启系统,openwrt会基于中间的dMACvXXXX来排序。 因为第二个dMACvWAN,第6个字母是“W”而不是“L”。 结果左边两项按照中间这列排序之后,物理网卡和ethX是下面这样的对应关系。
实际: 网卡1 => dMACvLAN1 => eth0 网卡3 => dMACvLAN3 => eth1 网卡4 => dMACvLAN4 => eth2 网卡2 => dMACvWAN => eth3
那么原先基于eth1并作用在物理网卡2的pppeo拨号配置,就被转移到物理网卡3上面,那么自然就没有拨号对象了。 也就是说macvlan的命名排序,和物理网口顺序一致,才能保证物理口和eth逻辑口顺序一致。
👍感谢分享
这种方式 openwrt 的端口转发好像不行啊,是不是必须在 docker run
的是时候设置宿主机 -p
参数?
尝试了下--net host,是无法使用的,至少本人测试的时候docker container一起来,宿主机网络就混乱造成重启,总结了一下
- 使用 --net host的时候是无法使用--ip指定ip地址的user specified IP address is supported on user defined networks only.
- openwrt 作为旁路必须设置的ip和网关,net host 与主机共享network space,所以两者冲突 以上是我的测试结果,当然也有可能是我的宿主机跑的armbian版本太低有bug,如果有其他大佬测试出来麻烦分享下经验!
遇到一个问题: 先说背景,N1刷armbian ubuntu18.04,docker下以macvlan模式部署openwrt。刚开始是OP和宿主机N1(ubuntu)无法ping通。按照你的思路在eth0上建立了虚拟网卡mac0,在interfaces文件里加入代码,重启后OP和N1(ubuntn)确实是可以ping通了。但是有一个问题,N1(ubuntu)的mac是固定写在interfaces文件里面,主路由给N1(ubuntu)分配静态ip。mac0虚拟网卡也自动配备了mac地址,但是主路由在读取mac0的mac地址的时候,生成了两个host,一个是N1(ubuntu),另一个是mac0,并且这两个mac是一样的。这就导致了N1(ubuntu)只有一个ip地址,但是却有两个mac地址,主路由一直在不停的切换,导致发热增大,后面只能重启。即使把mac0绑定静态ip锁住mac码,主路由还是读出N1有两个mac。小白一个,实在搞不明白,请求帮助,谢谢。
我搞了另一个做法 网卡A上的macvlan作为单臂路由lan口,和单网卡配置方式一样 网卡B通过DHCP或者其他方式指定网关为macvlan的ip 宿主机指定其他接口的网桥接口docker0网段,SNAT到网卡B上 宿主机自己默认网关使用网卡B 不过这段我还没试。。。这样宿主机倒是不用改网桥
在容器中做tproxy可能够呛,我在podman里部署带tproxy的v2,结果提示权限不足,root下启动容器也一样… 而且openwrt本身也要部署一些防火墙规则,在容器中怕不是要把人头搞大…
遇到个奇怪的问题,我有4个网口A,B,C,D, 网口A在容器内是eth0作为wan,网口B,C,D分别为eth1, eth2, eth3,这3个网口在openwrt里面被桥接到br-lan,奇怪的是只有B网口接上电脑能上网(其余C,D网口表现为访问不到网关,tcp udp ping均不行)。 如果我把B网口去掉不挂进容器,只用C,D两个网口桥接到br-lan,也只有C网口能够上网,D网口无法连接网关跟上面表现一致,百思不得解😭
非要跑macvlan的话果然要特权模式,不知道能不能用普通的网桥。
非要跑macvlan的话果然要特权模式,不知道能不能用普通的网桥。
可以的,--cap-add NET_ADMIN,如果需要拨号的话宿主机先加载pppoe模块, 再加上 --device /dev/ppp,可以避免使用特权模式