首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux Namespace详解(二)之Network namespace

Linux Namespace详解(二)之Network namespace

作者头像
用户5921339
发布2025-05-20 16:49:49
发布2025-05-20 16:49:49
24700
代码可运行
举报
运行总次数:0
代码可运行

一、理解Network namespace

摘自:Linux manual page

Network namespaces provide isolation of the system resources

associated with networking: network devices, IPv4 and IPv6

protocol stacks, IP routing tables, firewall rules, the /proc/net

directory (which is a symbolic linkto /proc/pid/net), the

/sys/class/net directory, various files under /proc/sys/net, port

numbers (sockets), and so on. In addition, network namespaces

isolate the UNIX domain abstract socket namespace (see unix(7)).

理解过来就是 Network namespaces 提供了系统资源的网络隔离环境,包括网络设备,IPv4和IPv6协议栈,IP路由表,防火墙规则等。

因为 Network namespace 中具有独立的网络协议栈,因此每个Network namespace 中都有一个 lo 网络接口,但是 lo 接口默认状态是 DOWN,需要手动启动起来

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# unshare -n /bin/bash
root@debian:~# ip add
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
root@debian:~# ip -n ns1 link set lo up

让某个 Network namespace 和 root network namespace 或其他network namespace 之间保持通信是一个非常常见的需求,一般是通过veth虚拟设备来实现。veth类型的虚拟设备通常由一对虚拟的 ethx 网卡设备组成,即 veth pair,一端传输的数据被另一端接收,经常用于在不同网络命名空间之间传输数据包。比如用户可以将veth的其中一端放在某个network namespace中,另一端保留在root network namespace中。这样就可以让用户创建的network namespace和宿主机通信。

在第一个shell窗口创建network namespace,并查看其进程号

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# unshare -n /bin/bash
root@debian:~# echo $$
1235
root@debian:~#

在第二个shell创建创建veth pair设备

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# ip link add veth0 type veth peer name veth1

此时veth0 和 veth1默认都在root network namespace中,为veth0设置IP地址并启用

将veth1置于刚刚创建的network namespace中

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# ip link set veth1 netns 1235

netns 1235中为veth1设置IP地址并启用

在root network namespace中的veth0和netns 1235中的veth1相互ping

但是此时的netns 1235中的veth1还不能和互联网通信,解决这个问题也很简单,在root network namespace开启转发并设置SNAT

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# sysctl -w net.ipv4.ip_forward=1
root@debian:~# iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE

另外在netns 1235配置默认路由即可

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# route add default gw 192.168.100.1

二、持久化Network namespace

正常情况下,当namespace中的所有进程都退出后,此namespace也会随之销毁。但有时候需要让namespace即使没有进程在其中运行也依然有效,即namespace持久化。例如,创建了network namespace后,想要让network namespace中的网络配置一直生效。

实际上,无论是network namespace还是其他类型的namespace,当通过mount bind为某个namespace的namespace文件(/proc/$$/ns/xxx)进行了bind挂载,那么这个namespace将成为持久化的namespace,即使namespace的第一个进程或者所有进程都退出了,namespace也不会被立即销毁,之后仍然可以通过nsenter重新进入这个namespace。

其实方式很简单,直接在unshare创建namespace时的对应长选项上指定一个已存在的文件即可(注:不允许在短选项上指定文件名)。

对于network namespace持久化,通常指定/var/run/netns/NAME作为持久化文件

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~#  mkdir -p /var/run/netns
root@debian:~#  touch /var/run/netns/ns1
root@debian:~# unshare --net=/var/run/netns/ns1 /bin/bash

:也可以不在选项--net上指定文件,而是在network namespace内部,将/var/run/netns/ns1通过mount bind挂载到/proc/$$/ns/net上

现在/var/run/netns/ns1和/proc/$$/ns/net是同一个network namespace,即使退出进程ns1并没有销毁,并可以使用nsenter再次进入ns1

三、ip netns

ip netns命令用于管理network namespace。ip netns将network namespace与/var/run/netns/NAME相关联,将/var/run/netns下的每一个NAME作为其所管理的每一个network namespace的名称。ip netns将/etc/netns/NAME/作为对应network namespace的全局网络配置文件的目录,查找它之后才会查找/etc/目录

例如,如果想要为netns名为ns1的network namespace单独设置DNS,可创建/etc/netns/ns1/resolv.conf,并将DNS相关配置写入该文件,当该文件不存在时才查找/etc/resolv.conf。ip netns创建network namespace时,同时会创建mount namespace,以便将网络相关配置文件/etc/netns/NAME/xxx挂载到对应的/etc/xxx。

  • 「ip netns add NAME」 创建名为NAME的network namespace,同时会关联/var/run/netns/NAME文件,如果文件不存在,则会自动创建
代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# ip netns add ns2
  • 「ip netns list」

列出/var/run/netns下的所有network namespace

  • 「ip netns attach NAME PID」

将PID对应的network namespace关联到/var/run/netns/NAME(不存在时会自动创建),使得该network namespace就像是被ip netns创建一样,之后它将受ip netns管理

在第一个shell窗口中执行,使用unshare而非ip netns创建一个network namespace

在第二个shell窗口中执行,现在这个root network namespace就像是由ip netns创建一样

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# ip netns attach ns3 2037
  • 「ip [-all] netns delete [ NAME ]」

删除/vaer/run/netns/下指定的network namespace,如果指定了--all,则删除/var/run/netns下所有的network namespace。注意,它同时会卸载mount bind的挂载点/var/run/netns/NAME并删除该文件。

  • 「ip netns set NAME NETNSID」

为/var/run/netns/NAME对应的network namespace设置ID号

  • 「ip netns identify [PID]」

根据PID,输出该PID所在的network namespace的netns name

  • 「ip netns pids NAME」

输出network namespace中当前正在运行的所有进程PID

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# ip netns pids ns1
  • 「ip [-all] netns exec [ NAME ] cmd ...」

在指定的network namespace中执行命令CMD。如果指定了--all选项,则CMD命令将在/var/run/netns/下的所有network namespace中都执行。

代码语言:javascript
代码运行次数:0
运行
复制
root@debian:~# ip netns exec ns1 ip link set lo up

如果/etc/netns/NAME下有配置文件,执行ip netns exec命令时会自动将其bind到/etc/下对应的配置文件上。此时还需注意,systemd管理的/etc/resolv.conf是一个软链接,ip netns直接bind时会失败,将其移除后再创建普通文件类型的/etc/resolv.conf才可bind成功

参考:Linux manual page

https://man7.org/linux/man-pages/man7/network_namespaces.7.html

今天的分享就到这里了,如果对文章的内容感兴趣,欢迎留言交流~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT人家 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档