设备
- Newifi D2
- RaspberryPi 3B+
- 笔记本电脑
网络拓扑
Raspberry Pi 3B+
和Newifi D2 CPU(Openwrt)
的地位是类似的,它们都同时属于VLAN-1
和VLAN-2
,eth0.1
处理VLAN-1
的数据包,eth0.2
处理VLAN-2
的数据包Raspberry Pi 3B+
和Newifi D2 CPU(Openwrt)
的不同之处仅仅在于,Raspberry Pi 3B+
通过外部接口LAN1
接入交换机,而Newifi D2 CPU(Openwrt)
通过内部接口Internal Port
接入交换机Newifi D2 CPU(Openwrt)
内部通过网桥br-lan
将eth0.1
,wlan0
,wlan1
桥接在一起,使得wlan0
,wlan1
可以和eth0.1
所属的vlan1
互通
配置过程
VLAN配置
交换机VLAN配置
- 路由器内嵌可编程交换机的
LAN2/LAN3/LAN4
属于untagged VLAN-1
- 路由器内嵌可编程交换机的
WAN
属于untagged VLAN-2
- 路由器内嵌可编程交换机的
LAN1
和Internal Port
属于tagged VLAN-1
&tagged VLAN-2
树莓派VLAN接口配置
树莓派的 eth0.1
属于 VLAN 1
,eth0.2
属于 VLAN 2
,到达 eth0
的数据包会根据其中包含的 VLAN ID
传递到对应的VLAN虚拟接口,而从VLAN虚拟接口发出的数据包也会打上对应的 VLAN ID
(后两句是我的猜测,然而由于我并不了解Linux协议栈以及虚拟接口的工作原理,无法保证准确性,大致工作原理可能类似)。其实路由器的 eth0.1
和 eth0.2
也是这样的。
配置方法
- 通过IP命令配置
1
2sudo ip link add link eth0 name eth0.1 type vlan id 1
sudo ip link add link eth0 name eth0.2 type vlan id 2 - 在
/etc/network/interfaces
中配置1
2
3
4
5
6
7
8
9
10
11
12
13# interfaces(5) file used by ifup(8) and ifdown(8)
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto eth0.1
iface eth0.1 inet manual
auto eth0.2
iface eth0.2 inet manual
为树莓派的 eth0.1
配置静态IP
树莓派默认会通过 dhcpcd
为各个接口配置IP,可以为树莓派的eth0.1
配置静态IP便于进行局域网访问并进一步作为网关。可以在 /etc/dhcpcd.conf
中配置:1
2interface eth0.1
static ip_address=192.168.2.10/24
如果仅仅希望阻止 dhcpcd
自动为某些接口通过局域网中的DHCP服务器配置IP,可以这样配置:1
2# deny
denyinterfaces eth0 eth0.2
树莓派利用PPPoE连接网络
Raspberry Pi 3B+
可以通过 eth0.2
与经 WAN
连接的运营商通信,就像 Newifi D2 CPU(Openwrt)
一样。
连接步骤
- 安装 pppoe 相关软件包
1
sudo apt install pppoe pppoeconf pppstatus
- 配置 pppoe 连接信息 然后根据提示输入账号和密码即可,账号和密码只需配置一次
1
sudo pppoeconf eth0.2
- 连接管理
1
2
3sudo pon dsl-provider #建立连接
sudo poff #断开连接
sudo plog #查看连接日志
连接成功之后,通过 ip -d addr
就能看到PPPoE接口 ppp0
,下面的内容还顺便展示了 eth0.1
和 eth0.2
的接口信息,可以忽略其中的 wlan0
,树莓派的 wlan0
其实连接到了路由器的无线网络 Openwrt
当中,与本次实验关系不大。
1 | 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 |
树莓派配置路由表
如果树莓派在建立PPPoE之前不存在默认路由,那么在PPPoE连接过程中应该会自动添加至新建的 PPPoE接口 ppp0
的默认路由,否则,它将不会覆盖原本就存在的默认路由。
由于我的树莓派还同时经树莓派的无线网卡 wlan0
连接了路由器的无线网络,原本存在默认路由,故在连接PPPoE之后需要配置默认路由,从而确保树莓派通过其自身建立的 ppp0
连接互联网,而非路由器。
配置好之后的默认路由为PPPoE接口 ppp0
:
1 | pi@rasp:~ $ ip route |
网络测试1
在完成上述配置之后,如果不出意外的话,树莓派应该就可以连接互联网了,可以随便ping一下百度进行测试,或者ping一个知名如 114.114.114.114
,如果能ping IP却不能ping 域名,可以检查下DNS设置,在此不再赘述。
配置NAT(Network Address Translation)
完成上面的配置之后,树莓派本身可以通过其建立的PPPoE连接互联网,但局域网中的其他设备却仍然无法访问互联网,那么如何使其他设备可以借助树莓派的PPPoE访问互联网呢?答案是NAT。
NAT的中文名称是网络地址转换,配置好NAT之后,局域网其他设备就可以将树莓派作为网关,然后该设备(称为设备A)的网络协议栈就会将目的地址为外部网络的数据包发往树莓派(IP数据包目的地址仍然是真实目的IP,MAC数据包的目的地址是树莓派,准确地说是树莓派的eth0.1
),树莓派会将原始IP数据包的 src
改为自身PPPoE接口ppp0
的IP地址,然后发往目标设备,并且,会将目标设备返回的IP数据包的 dst
改为设备A的IP地址,使得局域网设备可以透明地与互联网中的设备进行通信。
如果想要深入了解NAT,可以参考Network address translation - Wikipedia,NAT - Network Address Translation,前一篇文章侧重于NAT的概念和实现,后一篇文章侧重于Linux系统中NAT的配置和用途。
配置方法
配置NAT需要使用*nux的防火墙工具,比如 iptables
。关于防火墙可以参考Linux防火墙配置(iptables, firewalld)。
在本次实验当中,我使用iptables,并且配置为masquerade
,除了masquerade
还可以采用snat
。他们的区别在于,snat
需要指定要改写为哪个IP地址,这种情况适用于静态IP用户,而PPPoE分配的IP一般为动态IP,这时一般应该采用masquerade
,在这种情况下,无需指定要改写为哪个IP,内核会自动读取对应网络接口的IP地址进行改写。
不过在配置NAT之前,需要先开启Linux内核的数据包转发功能,默认情况下会禁止转发数据包。配置命令如下:
1 | sudo bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward' |
下面是NAT配置命令:
1 | sudo iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j MASQUERADE |
上面的命令的意思是这样的,在nat表中的POSTROUTING链中添加一条规则:如果IP数据包的 src
属于 192.168.2.0/24
网段,则在发送出去之前,改写其 src
为出口网络接口的IP地址。同时,该规则隐含了一条反向规则,将应答数据包的 dst
改为真实的 dst
(即被改掉的 src
)。实际实现过程中,只改IP应该是不够的,可能还需要修改sport
,并对应修改应答数据包的dport
。
网络测试2
完成上述配置之后,为局域网设备设置合适的IP地址,网关设为树莓派的局域网IP 192.168.2.10
,配置好DNS,应该就可以访问互联网了。
我的测试设备IP是这样的:
- 笔记本电脑:无线网卡连接至路由器的无线网 Openwrt-5G,IP为
192.168.2.51
(Openwrt-5G经路由器的br-lan
与路由器的eth0.1
桥接在一起,从而能够接入vlan1) - 树莓派:通过 LAN1 接入 vlan-1 和 vlan-2,
eth0.1
的IP为192.168.2.10
,经eth0.2
建立的PPPoE连接ppp0
的IP为100.82.232.18
测试方法为,在笔记本电脑上 ping 8.8.4.4
,然后在树莓派的 eth0.1
和 ppp0
上抓包。测试结果如下:
ping 8.8.4.4
1 | PS C:\Users\lpy> ping -n 4 8.8.4.4 |
抓包结果
1 | pi@rasp:~ $ sudo tcpdump -i eth0.1 dst 8.8.4.4 |
测试结果是:
- 笔记本电脑ping通8.8.4.4
- 在
ppp0
上可以看到 dns.google(即8.8.4.4
) 与 ppp0(即100.82.232.18
)之间的往来数据包,ppp0 发出ICMP echo request
,然后 dns.google 回应ICMP echo reply
- 在
eth0.1
上可以看到 dns.google(即8.8.4.4
) 与笔记本电脑(即192.168.2.51
)之间的往来数据包,笔记本电脑发出ICMP echo request
,然后 dns.google 回应ICMP echo reply
数据交换流程如下所示,由于这个例子是ICMP协议,不涉及端口号,如果是TCP/UDP还需要考虑端口号的转换:
需要再次强调一下,本例只是选用了最简单的ICMP协议,而应用程序大部分情况下使用的是TCP和UDP协议,在这种情况下,NAT是同时涉及IP和Port的,此图展示了两次对NTP服务器的访问,其中就涉及到了端口号。
扩展玩法
- 进一步在树莓派上安装
dnsmasq
,提供DNS Server以及DNS缓存服务 - 利用树莓派的wlan0开启无线热点,并通过Linux虚拟网桥桥接wlan0和eth0.1,将网关IP配置在虚拟网桥接口上,使wlan0所创建的WLAN也能通过树莓派的PPPoE接口经NAT访问互联网