首页 > 系统相关 >Linux namespace之:network namespace

Linux namespace之:network namespace

时间:2023-09-20 23:12:29浏览次数:54  
标签:sudo network ip Linux namespace ns1 netns


Linux namespace系列文章


理解network namespace

network namespace用来隔离网络环境,在network namespace中,网络设备、端口、套接字、网络协议栈、路由表、防火墙规则等都是独立的

因network namespace中具有独立的网络协议栈,因此每个network namespace中都有一个lo接口,但lo接口默认未启动,需要手动启动起来。

# -n或--net选项用于创建network namespace
$ sudo unshare -n /bin/bash

# 默认未启动lo
root@longshuai-vm:/home/longshuai# ip a
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@longshuai-vm:/home/longshuai# ip link set lo up
root@longshuai-vm:/home/longshuai# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

让某个network namespace和root network namespace或其他network namespace之间保持通信是一个非常常见的需求,这一般通过veth虚拟设备实现。veth类型的虚拟设备由一对虚拟的eth网卡设备组成,像管道一样,一端写入的数据总会从另一端流出,从一端读取的数据一定来自另一端。

用户可以将veth的其中一端放在某个network namespace中,另一端保留在root network namespace中。这样就可以让用户创建的network namespace和宿主机通信。

例如:

##### 在第一个shell窗口
# 创建network namespace ns1
$ sudo unshare -n /bin/bash

# 查看该network namespace的进程号
root@longshuai-vm:/home/longshuai# echo $$
53091


##### 在第二个shell窗口
# 创建veth设备
$ sudo ip link add veth0 type veth peer name veth1

# 创建之后,就有了一对虚拟的eth设备
$ ip a | grep veth
3: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
4: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000

# veth0准备留在root network namespace中
# 为veth0设置IP地址并启动
$ sudo ip a add dev veth0 192.168.10.10/24
$ sudo ip link set veth0 up
$ ip a s veth0
4: veth0@veth1: <NO-CARRIER,BROADCAST,MULTICAST,UP,M-DOWN> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
    link/ether 36:30:54:ba:d3:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.10/24 scope global veth0
       valid_lft forever preferred_lft forever

# 最后,将veth1移动到刚才新建的network namespace ns1中
# ip link set xxx netns [ PID|NETNS_NAME ]
$ sudo ip link set veth1 netns 53091

# 注:
# 并不是所有的网络设备都能在network namespace之间移动,
# ethtool -k <interface>输出的结果中,netns-local为on的表示不能移动
$ ethtool -k lo | grep netns
netns-local: on [fixed]
$ ethtool -k ens32 | grep netns      
netns-local: off [fixed]
$ ethtool -k veth1 | grep netns                         
netns-local: off [fixed]

##### 在ns1中启动veth1并设置IP地址
root@longshuai-vm:/home/longshuai# ip link set dev veth1 up

root@longshuai-vm:/home/longshuai# ip a add dev veth1 192.168.10.20/24

root@longshuai-vm:/home/longshuai# ip a s veth1
3: veth1@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 22:a8:4b:5b:55:4d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.10.20/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::20a8:4bff:fe5b:554d/64 scope link 
       valid_lft forever preferred_lft forever 

# 互ping,测试两端是否能通信,例如在ns1测试
root@longshuai-vm:/home/longshuai# ping 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data.
64 bytes from 192.168.10.10: icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from 192.168.10.10: icmp_seq=2 ttl=64 time=0.189 ms

但现在ns1还不能和公网通信。解决这个问题也很简单,在root network namespace中开启转发并设置SNAT,在ns1中添加默认路由即可。

##### 在root network namespace中执行
$ sudo sysctl -w net.ipv4.ip_forward=1
$ sudo iptables -t nat -A POSTROUTING -o ens32 -j MASQUERADE

##### 在network namespace ns1中执行
$ route add default gw 192.168.10.10
$ ping www.baidu.com
PING www.baidu.com (36.152.44.95) 56(84) bytes of data.
64 bytes from 36.152.44.95: icmp_seq=1 ttl=127 time=53.4 ms
64 bytes from 36.152.44.95: icmp_seq=2 ttl=127 time=51.0 ms

持久化的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时的对应长选项上指定一个已存在的文件即可(注:不允许在短选项上指定文件名)。

unshare: 
 -m, --mount[=<file>]   unshare mounts namespace
 -u, --uts[=<file>]     unshare UTS namespace (hostname etc)
 -i, --ipc[=<file>]     unshare System V IPC namespace
 -n, --net[=<file>]     unshare network namespace
 -p, --pid[=<file>]     unshare pid namespace
 -U, --user[=<file>]    unshare user namespace
 -C, --cgroup[=<file>]  unshare cgroup namespace

例如,想要让network namespace持久化:

# 对于network namespace持久化,通常指定/var/run/netns/NAME作为持久化文件
$ sudo mkdir -p /var/run/netns
$ sudo touch /var/run/netns/ns1

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

# 现在/var/run/netns/ns1和/proc/$$/ns/net是同一个network namespace
root@longshuai-vm:/home/longshuai# ls -i /var/run/netns/ns1 
4026532587 /var/run/netns/ns1

root@longshuai-vm:/home/longshuai# readlink /proc/$$/ns/net
net:[4026532587]

# 退出ns1
root@longshuai-vm:/home/longshuai# exit
exit

# /var/run/netns/ns1仍然指向net inode
$ ls -i /var/run/netns/ns1 
4026532587 /var/run/netns/ns1

# nsenter重新进入ns1
$ sudo nsenter --net=/var/run/netns/ns1 /bin/bash
root@longshuai-vm:/home/longshuai# hostname -I
192.168.10.20

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。

  1. ip netns add NAME
    创建名为NAME的network namespace,同时会关联/var/run/netns/NAME文件,如果文件不存在,则会自动创建

    $ sudo ip netns add ns2
    $ ls -i /var/run/netns/ns2
    4026532759 /var/run/netns/ns2
    
  2. ip netns list
    列出/var/run/netns下的所有network namespace

    # 带有id的,表示正在运行(即有进程尚未退出)的network namespace以及它的ID号
    # ID会自动分配,从0开始,后面通过ip netns命令也可以自己设置ID号
    $ ip netns list
    ns2
    ns1 (id: 0)
    
  3. ip netns attach NAME PID
    将PID对应的network namespace关联到/var/run/netns/NAME(不存在时会自动创建),使得该network namespace就像是被ip netns创建一样,之后它将受ip netns管理

    # 在第一个窗口中执行
    # 使用unshare而非ip netns创建一个network namespace
    $ sudo unshare -n /bin/bash
    root@longshuai-vm:/home/longshuai# echo $$
    5094
    
    # 在第二个窗口中执行
    # 现在这个network namespace就像是由ip netns创建一样
    $ sudo ip netns attach ns3 5094
    
  4. ip [-all] netns delete [ NAME ]
    删除/vaer/run/netns/下指定的network namespace,如果指定了--all,则删除/var/run/netns下所有的network namespace。注意,它同时会卸载mount bind的挂载点/var/run/netns/NAME并删除该文件。

    $ ip netns list
    ns3
    ns2
    ns1 (id: 0)
    
    $ sudo ip netns del ns3
    $ ls /var/run/netns
    ns1  ns2
    
    $ sudo ip --all netns del
    $ ls /var/run/netns
    
  5. ip netns set NAME NETNSID
    为/var/run/netns/NAME对应的network namespace设置ID号。

    $ sudo ip netns add ns1
    $ ip netns list
    ns1
    
    $ sudo ip netns set ns1 11
    $ ip netns list
    ns1 (id: 11)
    
  6. ip netns identify [PID]
    根据PID,输出该PID所在的network namespace的netns name。

    $ ip netns list
    ns1 (id: 11)
    $ sudo nsenter --net=/var/run/netns/ns1 /bin/bash
    root@longshuai-vm:/home/longshuai# echo $$
    5298
    
    # 在另一个窗口中查询进程PID=5298在哪一个network namespace中
    $ sudo ip netns identify 5298
    ns1
    
  7. ip netns pids NAME
    输出networ namespace中当前正在运行的所有进程PID

    $ sudo ip netns pids ns1
    5298
    
  8. ip [-all] netns exec [ NAME ] cmd ...
    在指定的network namespace中执行命令CMD。如果指定了--all选项,则CMD命令将在/var/run/netns/下的所有network namespace中都执行。

    $ sudo ip netns exec ns1 ip link set lo up
    $ sudo ip netns exec ns1 ping www.baidu.com
    

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

$ sudo mkdir -p /etc/netns/ns1
$ echo 'nameserver 8.8.8.8' | sudo tee /etc/netns/ns1/resolv.conf


$ sudo ip netns exec ns1 ping www.baidu.com
Bind /etc/netns/ns1/resolv.conf -> /etc/resolv.conf failed: No such file or directory
PING www.baidu.com (36.152.44.96) 56(84) bytes of data.
64 bytes from 36.152.44.96 (36.152.44.96): icmp_seq=1 ttl=127 time=36.2 ms
64 bytes from 36.152.44.96 (36.152.44.96): icmp_seq=2 ttl=127 time=37.5 ms

# 创建普通文件类型的/etc/resolv.conf
$ readlink /etc/resolv.conf
../run/systemd/resolve/stub-resolv.conf
$ sudo mv /etc/resolv.conf{,.bak}
$ sudo touch /etc/resolv.conf
$ sudo ip netns exec ns1 dig -t A www.baidu.com
......
;www.baidu.com.                 IN      A

;; ANSWER SECTION:
www.baidu.com.          581     IN      CNAME   www.a.shifen.com.
www.a.shifen.com.       51      IN      CNAME   www.wshifen.com.
www.wshifen.com.        70      IN      A       104.193.88.77
www.wshifen.com.        70      IN      A       104.193.88.123

;; Query time: 215 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)      # 已经成功使用8.8.8.8作为nameserver
;; WHEN: Sun Oct 11 16:58:51 CST 2020
;; MSG SIZE  rcvd: 127m

标签:sudo,network,ip,Linux,namespace,ns1,netns
From: https://www.cnblogs.com/f-ck-need-u/p/17718778.html

相关文章

  • 测试linux代码运行时间
    1. 前置知识  (1)gettid内核给线程(轻量级进程)分配的进程id,全局(所有进程中)唯一;  (2)pthread_self()是在用户态实现的,获取的是相对于进程的线程控制块的首地址,只是在当前进程空间中是唯一的。不能保证同一进程先后多个线程具有不同的id。(当前一个线程结束其生命周期,进程又新......
  • Linux Namespace
    1LinuxNamespace概述Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace中的进程没有影响。1.1Linux内核支持的namespaces目前,Linux内核里面实现了7种不同类型的......
  • Metasploitable-Linux靶机配置
    Metasploitable和kali是课上下载好的。直接打开进入欢迎界面用默认账号登录了之后,修改root密码(sudopasswdroot),登录root账号,查看本机IP(ifconfig)切换到kali,把kali的IP改为192.168.72.129,且能ping通192.168.72.131在kali的浏览器中输入靶机的IP,可以看到靶机的界面......
  • linux中grep与find的区别,Linux三剑客【grep、sed和awk】
    在使用linux时,经常需要进行文件查找。其中查找的命令主要有find和grep。两个命令是有区的。区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间等。(2)grep是根据文件的内容进行查找,会对文件的每一行按照给定的模式(patter)......
  • linux第四周技术博客
    这周我们学习了Linux的文件的操作之前我们已经在/home目录中创建了/swxy目录我们首先来学习touch命令,用户可以通过touch命令来创建一个空白文件,也可以设置文件属性cd/home/swxytouchabc.txtecho‘abc'>>abc.txt我们可以看到在swxy这个目录中已经创建了abc.txt这个文件,......
  • 1-Linux操作系统 的介绍和安装教程
    一、Linux的介绍1)常见的操作系统Windows,它微软公司开发的一款桌面操作系统(闭源系统)。版本有dos、win98、winNT、winXP、win7、winvista、win8、win10。服务器操作系统:winserver2003、winserver2008、winserver2012。Mac,苹果公司开发的一款操作系统(闭源系统),目前最......
  • linux网络配置
    linux网络配置一:网络配置的相关概念1:网关网关就是连接不同网段的,可以让不同网段的主机进行通信,就相当于是一个网段鹅出口,必须通过这个出口出去,才能与外界进行通信,在linux中有默认的网关,NAT模式中默认的网关就是以.2结尾比如Ip为192.168.10.10它的网关就是192.168.10.2......
  • 《Linux命令行与shell脚本编程大全.第3版》电子书PDF+源代码
    精通Linux命令行与shell脚本编程,尽在本书中本书是关于Linux命令行和shell命令的全面参考资料,涵盖详尽的动手教程和实际应用指南,并提供相关参考信息和背景资料,带你从Linux命令行基础入手,直到写出自己的shell。时隔四年后的这一版本,针对Linux的新特性和实践,进行了全面更新:使用......
  • Linux用户和组命令
    用户和组配置文件1.用户:Linux基于用户身份对资源进行控制用户账号root用户程序用户:不需要登录系统,服务于应用程序,维护系统的运行普通用户:可以登录系统的一般用户组账号基本组(私有组):当用户创建文件和文件夹时,默认的属组,只能有一个附加组(公共组):用户可以有多个附加组UID和GIDUI......
  • linux 中字符串处理函数 ${i%%.*}
     001、[root@pc1test2]#ls[root@pc1test2]#str1="ab.cd_kk.mn_jjy"##测试字符串[root@pc1test2]#echo${str1%%.*}##从左侧开始,删除.号右侧所有的内容ab[root@pc1test2]#echo${str1%.*}##从左侧开始,删除最后一个.右侧的内容ab.......