Theme NexT works best with JavaScript enabled

学习飞翔的企鹅

What's the point in living if I have to hide ?

0%

Linux Network Namespace(netns)使用——以PPPoE实验为例

​ netns是用来建立隔离的网络协议栈的,学习netns是因为计算机网络原理课程作业中有一个研究 PPPoE 网络协议的实验,需要有一个 server 和一个 client,通过对两者通信的抓包来理解协议内容和过程。Windows 有 wsl2,和 Windows 本身不共用网络层,因此可以一个当 server,一个当 client,但我只有一台 Linux 电脑,所以就需要用 netns 建立隔离的网络栈来模拟两台电脑。

一、netns 使用

netns 的使用是需要 sudo 权限的,且是 ip 系列的指令,因此相关指令的前缀都为 sudo ip netns

增加一个网络空间的指令为add,后接网络名称,在这里创建两个网络空间,一个为net0,一个为net1,分别用于 PPPoE 的 server 和 client 搭建(之后如果想删除的话只需要用del指令即可):

1
2
sudo ip netns add net0
sudo ip netns add net1

使用lsshow指令查看网络空间,确认两个网络空间已经建立:

1
2
3
4
sudo ip netns ls
# 输出应为:
# net0
# net1

如果想在某个特定的网络空间下运行指令,只需要给前缀sudo ip netns exec name即可,想在net0 空间中运行 ip addr 指令,只需要:

1
sudo ip netns exec net0 ip addr

新建立的网络命名空间的 loopback 接口是默认关闭的(在 ip addr 中可以看到接口lo的状态是DOWN),如果需要打开,使用:

1
2
# ip link set xxx up 是打开接口 xxx
sudo ip netns exec net0 ip link set lo up

此时两个网络空间之间无法互相通信,需要有一根虚拟网线连接两个网络空间。这根虚拟网线就是 veth (virtual ethernet)。veth 总是成对出现的(相当于网线的两头),因此创建时是两个同时创建。使用ip link系列的add指令进行创建(同样,要删除只需要ip link del dev xxx):

1
2
3
4
# 默认名字为 veth0 和 veth0
sudo ip link add type veth
# 或者也可以用自定义名字的方式:
# sudo ip link add name veth0 type veth peer name veth1

此时用ip addr指令应该可以看到这两个接口。接下来需要将两个接口分别绑定到两个网络空间:

1
2
sudo ip link set veth0 netns net0
sudo ip link set veth1 netns net1

这样虚拟网线的两端就绑定到两个网络空间了。但是此时两个网络之间还是不能通信,因为veth端口还没有打开,且还没有分配IP地址,因此要打开接口并分配地址:

1
2
3
4
5
6
7
# 打开接口
sudo ip netns exec net0 ip link set veth0 up
sudo ip netns exec net1 ip link set veth1 up
# 分配 IP 地址,这里以 192.168.0.2/24 和 192.168.0.3/24 为例(/24是子网掩码)
# ip a 是 ip addr 的缩写
sudo ip netns exec net0 ip a add 192.168.0.2/24 dev veth0
sudo ip netns exec net1 ip a add 192.168.0.3/24 dev veth1

分配好之后还需要手动配置路由,否则无法互相找到,使用ip r指令(是ip route的缩写)

1
2
3
# 表示所有192.168.0.x的地址都通过veth0和veth1寻找
sudo ip netns exec net0 ip r add 192.168.0.0/24 dev veth0
sudo ip netns exec net1 ip r add 192.168.0.0/24 dev veth1

这样两个子网就可以互相ping通了,即可以互相通信了:

1
2
sudo ip netns exec net0 ping 192.168.0.3 # 从net0 ping net1
sudo ip netns exec net1 ping 192.168.0.2 # 从net1 ping net0

至此两个互相能通信的子网已经建立。

二、PPPoE

1. server 搭建

安装 PPPoE server:

1
sudo apt install pppoe

通过vim /etc/ppp/options 编辑 PPPoE 的配置文件并删除 #+chap 行首的注释符 #

通过 vim /etc/ppp/pppoe-server-options 进行 server 的配置,写入:

1
2
3
4
require-chap
lcp-echo-interval 60
lcp-echo-failure 5
logfile /var/log/pppd.log

通过 vim /etc/ppp/chap-secrets 编辑 server 端认证的帐号密码,在最后一行加入:

1
test * 123456 *  # client/server/secret/IP address

这里注意,因为本实验中 server 和 client 其实是同一台机器模拟的两个网络空间,即配置文件是共用的,因此在配置客户端的时候可能会把服务端的配置覆盖,需要配置完客户端后重新回来把被覆盖的部分加上。

之后启动server即可(注意在 net0 空间中启动)

1
2
3
# -I 后跟的是使用的interface,选择和 net1 连接的 veth0,-L 指定server在子网中的地址,-R指定接入client的地址分配的起始点,-N指定允许的最多client
sudo ip netns exec net0 sudo pppoe-server -I veth0 -L 10.0.0.1 -R 10.0.0.2 -N
20

2. client 搭建

安装pppoeconf:

1
sudo apt install pppoeconf

在子网net1中运行pppoeconf,并且指定使用veth1接口:

1
sudo ip netns exec net1 pppoeconf veth1

按顺序:popular options,选否;用户名,删掉默认的username,输入test;密码,输入123456;User peer DNS,选是;Limited MSS Problem,选是;Start connection at boot time,否;Establish a Connection,否。

此时pppoeconf应该覆盖了原先server端的chap-secrets,需要把test * 123456 * 重新加回配置文件。

更改结束后如果需要开启client连接,只需要在net1网络空间下运行sudo pon dsl-provider

1
sudo ip netns exec net1 sudo pon dsl-provider

查看状态可以使用sudo plog,关闭连接可以用sudo poff

三、使用 tcpdump 抓包

我们需要在运行pon dsl-provider之前开启抓包,这样就能得到客户端进行连接时和server进行的交互信息。在客户端抓包还是在服务端抓包是一样的,只是发送的和接收的相反而已。在客户端抓包:

1
2
# -i 为选择监听的 interface,-v 为 verbose(显示详细信息),-n 为不翻译地址(即不用dns翻译,可以加快速度),-w 为设置数据存储路径(存为pcap文件,可以用wireshark进行分析)
sudo ip netns exec net1 tcpdump -i veth1 -vn -w packet.cap

此时已经tcpdump已经开始监听 net1 的 veth1 了,之后所有通过这个接口发送的包都会被存下来,此时再开始连接过程:

1
sudo ip netns exec net1 sudo pon dsl-provider

连接完成后再关闭监听,此时所有连接过程的包都已经被保存到packet.cap文件中了,使用wireshark打开即可得到PPPoE各阶段的报文:

all