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 | sudo ip netns add net0 |
使用ls
或show
指令查看网络空间,确认两个网络空间已经建立:
1 | sudo ip netns ls |
如果想在某个特定的网络空间下运行指令,只需要给前缀sudo ip netns exec name
即可,想在net0
空间中运行 ip addr
指令,只需要:
1 | sudo ip netns exec net0 ip addr |
新建立的网络命名空间的 loopback 接口是默认关闭的(在
ip addr
中可以看到接口lo
的状态是DOWN),如果需要打开,使用:
1 | # ip link set xxx up 是打开接口 xxx |
此时两个网络空间之间无法互相通信,需要有一根虚拟网线连接两个网络空间。这根虚拟网线就是
veth (virtual ethernet)。veth
总是成对出现的(相当于网线的两头),因此创建时是两个同时创建。使用ip link
系列的add
指令进行创建(同样,要删除只需要ip link del dev xxx
):
1 | # 默认名字为 veth0 和 veth0 |
此时用ip addr
指令应该可以看到这两个接口。接下来需要将两个接口分别绑定到两个网络空间:
1 | sudo ip link set veth0 netns net0 |
这样虚拟网线的两端就绑定到两个网络空间了。但是此时两个网络之间还是不能通信,因为veth端口还没有打开,且还没有分配IP地址,因此要打开接口并分配地址:
1 | # 打开接口 |
分配好之后还需要手动配置路由,否则无法互相找到,使用ip r
指令(是ip route
的缩写)
1 | # 表示所有192.168.0.x的地址都通过veth0和veth1寻找 |
这样两个子网就可以互相ping通了,即可以互相通信了:
1 | sudo ip netns exec net0 ping 192.168.0.3 # 从net0 ping net1 |
至此两个互相能通信的子网已经建立。
二、PPPoE
1. server 搭建
安装 PPPoE server:
1 | sudo apt install pppoe |
通过vim /etc/ppp/options
编辑 PPPoE 的配置文件并删除
#+chap
行首的注释符 #
。
通过 vim /etc/ppp/pppoe-server-options
进行 server
的配置,写入:
1 | require-chap |
通过 vim /etc/ppp/chap-secrets
编辑 server
端认证的帐号密码,在最后一行加入:
1 | test * 123456 * # client/server/secret/IP address |
这里注意,因为本实验中 server 和 client 其实是同一台机器模拟的两个网络空间,即配置文件是共用的,因此在配置客户端的时候可能会把服务端的配置覆盖,需要配置完客户端后重新回来把被覆盖的部分加上。
之后启动server即可(注意在 net0 空间中启动)
1 | # -I 后跟的是使用的interface,选择和 net1 连接的 veth0,-L 指定server在子网中的地址,-R指定接入client的地址分配的起始点,-N指定允许的最多client |
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 | # -i 为选择监听的 interface,-v 为 verbose(显示详细信息),-n 为不翻译地址(即不用dns翻译,可以加快速度),-w 为设置数据存储路径(存为pcap文件,可以用wireshark进行分析) |
此时已经tcpdump已经开始监听 net1 的 veth1 了,之后所有通过这个接口发送的包都会被存下来,此时再开始连接过程:
1 | sudo ip netns exec net1 sudo pon dsl-provider |
连接完成后再关闭监听,此时所有连接过程的包都已经被保存到packet.cap文件中了,使用wireshark打开即可得到PPPoE各阶段的报文: