Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在docker中运行openwrt #4

Open
lisaac opened this issue Jan 10, 2019 · 34 comments
Open

在docker中运行openwrt #4

lisaac opened this issue Jan 10, 2019 · 34 comments

Comments

@lisaac
Copy link
Owner

lisaac commented Jan 10, 2019

docker 中运行 openwrt

[toc]

思路

利用 macvlan 方式创建虚拟接口进行配置。
有感于来自恩山 betterman 及 rightwifi2017 两位大佬斐讯 N1 的玩法,也获得两位大佬的帮助,在此感谢两位大佬。
由于 N1 为单网卡,所以配置只能为单臂路由,本案为双网卡 opewnrt

机器拥有双网卡: enp1s0enp3s0 ,本案将 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 网络采用 macvlanbridge 模式,即使宿主机与容器在同一网段,相互之间也是无法通信的。
为了解决这个问题,需利用多个 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 中事先加载

@WinterXMQ
Copy link

能否写一下如何在docker中使用openwrt,我没有测试成功

@pingod
Copy link

pingod commented Jun 5, 2019

佩服博主的抽象思维能力,配网络都不用画图。

另外:
第五步中的关于去修改宿主机路由规则的命令:
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

@pingod
Copy link

pingod commented Jun 5, 2019

其实觉得如果在容器起来的时候使用--net host 会更加简单,后面加MacVlan网卡和配路由应该都不用弄了,但是没有测试过

@lisaac
Copy link
Owner Author

lisaac commented Jun 5, 2019

@WinterXMQ
使用方法和正常的 openwrt 无异,不知道没有测试成功指的是?

@pingod
嗯,用 iptables 也可以,好处是不用改主机默认路由,但是流量会再转发一次。
--net host 我也没测试过,应该是可以的,macvlan 是起到网络虚拟化作用的,对于强迫症应该不喜欢用 host

@darktitty
Copy link

我家里的宽带网络是直接DHCP获取公网ip的。我是在双网口群辉Docker跑Openwrt的,打算拿来做主路由。按照博主的教程配置好了以后,插网线到WAN口,但是公网ip就直接被群辉获取了,Openwrt根本无法获取到,请问这种情况,我完全按照上面的教程去做可以啦?

@lisaac
Copy link
Owner Author

lisaac commented Jun 25, 2019

@darktitty
首先我不确定群晖内核模块是否完全能够支持 Openwrt

群晖需要关闭 DHCP,同时,网线必须对应 Openwrt WAN 侧,并且在群晖中新建一个 macvlan 虚拟接口(对应 Openwrt LAN 侧的那个网卡),这样才能通过 Openwrt 来上网。

@darktitty
Copy link

darktitty commented Jun 25, 2019

奇怪的是 我执行第五步以后 openwrt就连不上啦 晚点我试试在Debian上搞搞看

@kanshudj
Copy link

新编译的rootfs.tar.gz拖进docker启动后,web显示不正常:luci web响应速度比较慢,首页网口信息显示“正在收集”无信息显示,工作时间和负载也是空白,能ping通网关。
之前编译的正常,不知道什么原因。

@lisaac
Copy link
Owner Author

lisaac commented Jul 26, 2019

@kanshudj
不清楚原因,应该是镜像的关系,感觉是占用过高?可以查一下 cpu 的占用率

@ywjdlq
Copy link

ywjdlq commented Sep 4, 2019

奇怪的是 我执行第五步以后 openwrt就连不上啦 晚点我试试在Debian上搞搞看

你好,群晖里的docker能访问到吗?试了很多次了, 还是访问不了docker中的openwrt?

@ywjdlq
Copy link

ywjdlq commented Sep 4, 2019

@darktitty
首先我不确定群晖内核模块是否完全能够支持 Openwrt

群晖需要关闭 DHCP,同时,网线必须对应 Openwrt WAN 侧,并且在群晖中新建一个 macvlan 虚拟接口(对应 Openwrt LAN 侧的那个网卡),这样才能通过 Openwrt 来上网。

请教一下,docker中运行openwrt需要哪些内核模块呢?在群晖里的docker装上了,就是没法访问

@darktitty
Copy link

@ywjdlq 我折腾了好久没成功 都放弃啦…

@lisaac
Copy link
Owner Author

lisaac commented Sep 5, 2019

@ywjdlq
没有在群晖中使用过,由于群晖内核裁剪的比较厉害,我有空的时候装个黑群晖试一下

@ywjdlq
Copy link

ywjdlq commented Sep 19, 2019

@lisaac
尝试过了吗?我看openwrt内核都到4.15了,群晖的3.10

@lisaac
Copy link
Owner Author

lisaac commented Sep 20, 2019

@ywjdlq
还没,最近在忙其他项目,抽空试一下

@lisaac
Copy link
Owner Author

lisaac commented Sep 21, 2019

@ywjdlq
抽空刚刚在虚拟机黑裙中试了一下,是可以进luci界面的,没有做过多测试
如果是单网口,可能需要先停用firewall:
/etc/init.d/firewall sotp

@manooog
Copy link

manooog commented Mar 21, 2020

docker 中的openwrt 外网和网关都不通。。

@deepline1986
Copy link

成功配置双网卡。但添加第三个网卡作为第二LAN口后,wan口就无法pppoe拨号了。
操作方法是docker中新建第三个macvlan网络,用了不同的网段,绑定第三个网卡,之后将新的macvlan链接到openwrt的容器。
求教了,多谢。

@lisaac
Copy link
Owner Author

lisaac commented Mar 24, 2020

@deepline1986
感觉应该不会有问题,无法拨号具体表现是什么?
另外可以试一下在宿主建立bridge-lan,然后在bridge-lan上建macvlan,挂进docker

@deepline1986
Copy link

@deepline1986
感觉应该不会有问题,无法拨号具体表现是什么?
另外可以试一下在宿主建立bridge-lan,然后在bridge-lan上建macvlan,挂进docker

@lisaac
在宿主机给容器连接第二个lan口的macvlan,分两种情况。

  1. 在openwrt中添加lan的interface,完成后,新lan口工作正常,上网,但重启宿主机后wan口拨号失效。
  2. 不在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口,还是别的理解?谢谢。

@lisaac
Copy link
Owner Author

lisaac commented Mar 24, 2020

@deepline1986
由于没有环境,没有测过,按道理来讲,应该不会出现这个问题,如果有结果请 po 出来,谢谢。

另外,关于网桥的方案,我也没测试过,只是一个想法:
在宿主机上在两个lan口上建立bridge-lan,然后把bridge-lan看成双网口方案中的lan口,按照双网口方案进行部署

@deepline1986
Copy link

deepline1986 commented Mar 24, 2020

@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逻辑口顺序一致。

👍感谢分享

@bestK
Copy link

bestK commented Mar 31, 2020

这种方式 openwrt 的端口转发好像不行啊,是不是必须在 docker run 的是时候设置宿主机 -p 参数?

@rilyuuj
Copy link

rilyuuj commented Apr 5, 2020

尝试了下--net host,是无法使用的,至少本人测试的时候docker container一起来,宿主机网络就混乱造成重启,总结了一下

  1. 使用 --net host的时候是无法使用--ip指定ip地址的user specified IP address is supported on user defined networks only.
  2. openwrt 作为旁路必须设置的ip和网关,net host 与主机共享network space,所以两者冲突
    以上是我的测试结果,当然也有可能是我的宿主机跑的armbian版本太低有bug,如果有其他大佬测试出来麻烦分享下经验!

@CC342
Copy link

CC342 commented Jun 16, 2020

遇到一个问题:
先说背景,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。小白一个,实在搞不明白,请求帮助,谢谢。

@origalin
Copy link

origalin commented Dec 9, 2020

我搞了另一个做法
网卡A上的macvlan作为单臂路由lan口,和单网卡配置方式一样
网卡B通过DHCP或者其他方式指定网关为macvlan的ip
宿主机指定其他接口的网桥接口docker0网段,SNAT到网卡B上
宿主机自己默认网关使用网卡B 不过这段我还没试。。。这样宿主机倒是不用改网桥

@daiaji
Copy link

daiaji commented Jan 9, 2021

在容器中做tproxy可能够呛,我在podman里部署带tproxy的v2,结果提示权限不足,root下启动容器也一样…
而且openwrt本身也要部署一些防火墙规则,在容器中怕不是要把人头搞大…

@lazywen
Copy link

lazywen commented Oct 24, 2021

遇到个奇怪的问题,我有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网口无法连接网关跟上面表现一致,百思不得解😭

@daiaji
Copy link

daiaji commented Oct 25, 2021

非要跑macvlan的话果然要特权模式,不知道能不能用普通的网桥。

@lazywen
Copy link

lazywen commented Oct 25, 2021

非要跑macvlan的话果然要特权模式,不知道能不能用普通的网桥。

可以的,--cap-add NET_ADMIN,如果需要拨号的话宿主机先加载pppoe模块, 再加上 --device /dev/ppp,可以避免使用特权模式

@daiaji
Copy link

daiaji commented Oct 26, 2021

非要跑macvlan的话果然要特权模式,不知道能不能用普通的网桥。

可以的,--cap-add NET_ADMIN,如果需要拨号的话宿主机先加载pppoe模块, 再加上 --device /dev/ppp,可以避免使用特权模式

实际上我还要跑透明代理,防火墙麻烦。

@lazywen
Copy link

lazywen commented Oct 28, 2021

非要跑macvlan的话果然要特权模式,不知道能不能用普通的网桥。

可以的,--cap-add NET_ADMIN,如果需要拨号的话宿主机先加载pppoe模块, 再加上 --device /dev/ppp,可以避免使用特权模式

实际上我还要跑透明代理,防火墙麻烦。

基于iptables的透明代理不影响的,在桥接模式的容器里面完美使用

@snbdot
Copy link

snbdot commented May 29, 2022

佩服博主的抽象思维能力,配网络都不用画图。

另外: 第五步中的关于去修改宿主机路由规则的命令: 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

马克一下,曾主的网络环境是什么?这条路由设置啥意思啊?

@Zxklinux
Copy link

请问大佬们,我的r2s刷了官方armbian.按照上面教程,导入官方armvirt的openwrt ,在op里面执行ip link show 只有一个lo接口,没有eth0 和lan0 怎么办

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests