Linux 3.8內(nèi)核中包括了6種命名空間:
命名空間 | 描述 |
---|---|
Mount(mnt) | 隔離掛載點(diǎn) |
Process ID(process) | 隔離進(jìn)程ID |
Network(net) | 隔離網(wǎng)絡(luò)設(shè)備蚓哩、協(xié)議棧缘眶、端口等 |
InterProcess Communication(ipc) | 隔離進(jìn)程間通信 |
UTS | 隔離Hostname和NIS域名 |
User ID(user) | 隔離用戶和group ID |
還有一個(gè)CGroup Name Space拦坠,和上述這些命名空間是container技術(shù)的一個(gè)基礎(chǔ)坠狡。
這篇文章我們只討論Network Namespaces
1. 創(chuàng)建一個(gè)新的network namespace
$ ip netns add blue
查看新創(chuàng)建network namespace
$ ip netns list
2. 分配一個(gè)網(wǎng)絡(luò)接口給Network Namespaces
首先我們考慮一下虛擬網(wǎng)卡Veth泵三, veth很有意思咽安;它都是成對(duì)出現(xiàn)的伴网,就像一個(gè)管道的兩端,從這個(gè)管道的一端的veth進(jìn)去的數(shù)據(jù)會(huì)從另一端的veth再出來妆棒。也就是說澡腾,你可以使用veth接口把一個(gè)網(wǎng)絡(luò)命名空間連接到外部的默認(rèn)命名空間或者global命名空間,而物理網(wǎng)卡就存在這些命名空間里糕珊。
首先我們來創(chuàng)建一個(gè)veth對(duì):
$ ip link add veth0 type veth peer name veth1
這一條命令就會(huì)同時(shí)創(chuàng)建veth0和veth1兩個(gè)虛擬網(wǎng)卡动分,運(yùn)行如下命令來驗(yàn)證一下
$ ip link list
這個(gè)時(shí)候你就可以看到這一對(duì)veth接口了
4: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether be:68:5b:da:60:1d brd ff:ff:ff:ff:ff:ff
5: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether d2:70:e9:c1:31:2f brd ff:ff:ff:ff:ff:ff
這個(gè)時(shí)候這兩個(gè)網(wǎng)卡還都屬于“default”或“global”命名空間,和物理網(wǎng)卡一樣红选。
現(xiàn)在我們要把這個(gè)global namesapce連接到blue namespace澜公,做法就是把其中的一個(gè)veth轉(zhuǎn)移到blue命名空間中去,
$ ip link set veth1 netns blue
這個(gè)時(shí)候再用命令ip link list來查看就會(huì)發(fā)現(xiàn)veth1不見了喇肋,這個(gè)時(shí)候veth1以及設(shè)置到了blue命名空間中了坟乾,運(yùn)行如下命令查看
$ ip netns exec blue ip link list
這個(gè)時(shí)候你可以看到里面有兩個(gè)網(wǎng)絡(luò)接口
- 一個(gè)是回環(huán)網(wǎng)絡(luò)lo
- 另一個(gè)是veth1
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
4: veth1@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether be:68:5b:da:60:1d brd ff:ff:ff:ff:ff:ff link-netnsid 0
3. 配置Network Namespaces里面的網(wǎng)絡(luò)接口
可以通過運(yùn)行如下命令來配置blue命名空間中的veth1接口
$ ip netns exec blue ip addr add 10.1.1.1/24 dev veth1
$ ip netns exec blue ip link set veth1 up
$ ip netns exec blue ip link set lo up
這個(gè)命令中迹辐,通過ip addr add命令給veth1分配了一個(gè)IP 地址,并且把這個(gè)網(wǎng)卡啟動(dòng)了甚侣;同時(shí)也啟動(dòng)了回環(huán)網(wǎng)卡明吩;
然后查看一下blue命名空間里面的兩個(gè)網(wǎng)卡的狀態(tài)
$ ip netns exec blue ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
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
11: veth1@if12: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
link/ether a6:41:bf:fc:8c:5e brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.1.1.1/32 scope global veth1
valid_lft forever preferred_lft forever
同時(shí)還需要配置一下host上面對(duì)端網(wǎng)卡的ip
$ ip addr add 10.1.1.2/24 dev veth0
$ ip link set veth0 up
這個(gè)時(shí)候在blue命名空間里面ping 10.1.1.1(veth1)已經(jīng)ok了
root@ubuntu:~# ip netns exec blue ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.058 ms
但是依舊ping不通10.1.1.2(veth0)
這是因?yàn)閎lue命名空間中的路由還沒有設(shè)置。
4. 設(shè)置命名空間內(nèi)的路由
通過如下命令來設(shè)置一個(gè)默認(rèn)路由
$ ip netns exec blue ip route add default via 10.1.1.1
$ ip netns exec blue ip route show
default via 10.1.1.1 dev veth1
所有找不到目的地址的數(shù)據(jù)包都通過設(shè)備veth1轉(zhuǎn)發(fā)出去殷费。
這個(gè)時(shí)候就可以成功ping通host上的veth0網(wǎng)卡了
$ip netns exec blue ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.086 ms
但是到了這里依舊還不夠印荔,blue命名空間中已經(jīng)可以聯(lián)通主機(jī)上的網(wǎng)絡(luò),但是依舊連不同主機(jī)以外的外部網(wǎng)絡(luò)详羡。這個(gè)時(shí)候必須在host主機(jī)上啟動(dòng)轉(zhuǎn)發(fā)仍律,并且在iptables中設(shè)置偽裝
5. 使能IP轉(zhuǎn)發(fā):IP_FORWARD
Linux系統(tǒng)的IP轉(zhuǎn)發(fā)的意思是,當(dāng)Linux主機(jī)存在多個(gè)網(wǎng)卡的時(shí)候实柠,允許一個(gè)網(wǎng)卡的數(shù)據(jù)包轉(zhuǎn)發(fā)到另外一張網(wǎng)卡水泉;在linux系統(tǒng)中默認(rèn)禁止IP轉(zhuǎn)發(fā)功能,可以打開如下文件查看主到,如果值為0說明禁止進(jìn)行IP轉(zhuǎn)發(fā)
cat /proc/sys/net/ipv4/ip_forward
運(yùn)行如下的命令茶行,其中ens160是host的一個(gè)對(duì)外網(wǎng)卡躯概,這樣的就允許ens160和veth0之間的轉(zhuǎn)發(fā)登钥;也就是說blue命名空間可以和外網(wǎng)聯(lián)通了。
#使能ip轉(zhuǎn)發(fā)
echo 1 > /proc/sys/net/ipv4/ip_forward
#刷新forward規(guī)則
iptables -F FORWARD
iptables -t nat -F
#刷新nat規(guī)則
iptables -t nat -L -n
#使能IP偽裝
iptables -t nat -A POSTROUTING -s 10.1.1.0/255.255.255.0 -o ens160 -j MASQUERADE
#允許veth0和ens160之間的轉(zhuǎn)發(fā)
iptables -A FORWARD -i ens160 -o veth0 -j ACCEPT
iptables -A FORWARD -o ens160 -i veth0 -j ACCEPT
- 使能IP偽裝這條語句娶靡,添加了一條規(guī)則到NAT表的POSTROUTING鏈中牧牢,對(duì)于源IP地址為10.1.1.0網(wǎng)段的數(shù)據(jù)包,用ens160網(wǎng)口的IP地址替換并發(fā)送姿锭。
- iptables -A FORWARD這兩條語句使能物理網(wǎng)口ens160和veth0之間的數(shù)據(jù)轉(zhuǎn)發(fā)
6. 演示一下整個(gè)流程
7. 完整的示例代碼
#!/bin/bash
#Create new namesapce
ip netns delete ns1
ip netns add ns1
ip link add veth0 type veth peer name veth1
ip link set veth0 netns ns1
echo "====Create New Network namespace and spcify a eth===="
ip netns list
ip netns ns exec if config -a
#Assign the IP and bring up
ip addr add 10.100.1.1/24 dev veth1
ip link set veth1 up
ip netns exec ns1 ip addr add 10.100.1.2/24 dev veth0
ip netns exec ns1 ip link set veth0 up
ip netns exec ns1 ip link set lo up
echo "====Bring up the veth0 and lo inside Namespace===="
ip netns exec ns1 ip addr show
#add route inside namespace
ip netns exec ns1 ip route add default via 10.100.1.1
echo "====Add new default rout inside the namespace===="
ip netns exec ns1 ip route show
echo "====Tryting to ping the veth1 on host===="
ip netns exec ns1 ping 10.100.1.1 -c 4
#Config the host to enable forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -t nat -F
#enalbe masquerading of 10.100.1.0
iptables -t nat -A POSTROUTING -s 10.100.1.0/255.255.255.0 -o ens160 -j MASQUERADE
#Allow forwarding
iptables -A FORWARD -i ens160 -o veth1 -j ACCEPT
iptables -A FORWARD -o ens160 -i veth1 -j ACCEPT
echo "====Enable the forwarding of veth1 to ens160(NIC)on host ===="
echo "Show the iptables of filter"
iptables -L -n
echo "Show the iptables of nat"
iptables -t nat -L -n
參考文檔
https://coolshell.cn/articles/17010.html
https://coolshell.cn/articles/17029.html
https://segmentfault.com/a/1190000005794036
https://blogs.igalia.com/dpino/2016/04/10/network-namespaces/