标签:
学习 Neutron 系列文章:
(2)Neutron OpenvSwitch + VLAN 虚拟网络
(3)Neutron OpenvSwitch + GRE/VxLAN 虚拟网络
(4)Neutron OVS OpenFlow 流表 和 L2 Population
(9)Neutron FWaas 和 Nova Security Group
(10)Neutron VPNaas
(11)Neutron DVR
(12)Neutron VRRP
(14)使用 NAT 将 Linux network namespace 连接外网
(15)使用 Linux bridge 将 Linux network namespace 连接外网
Linux network namespace 连接外网从大类上来讲主要有两种方法:网络地址转换(NAT) 和 桥接(bridging),而桥接根据使用的网桥又可以分为使用 linux bridge 和 Open vSwitch 网络等。本文将说明 NAT 具体配置过程以及原理。
我们可以把一个 linux network namespace 看作另一个计算机,这样看起来会更加直观:
节点 host1 的 IP 地址为 192.168.1.32. 实验使用的另一个机器 host2 的 IP 为 192.168.1.15.
为了能从在 host1 上的 netns myspace 上能 ping 通 host2 ,你需要做的配置及说明:
步骤# | 命令 | 说明 |
1 | ip netns add myspace | 创建名称为 ‘myspace’ 的 linux network namespace |
2 | ip link add veth1 type veth peer name veth2 | 创建一个 veth 设备,一头为 veth1,另一头为 veth2 |
3 | ip link set veth2 netns myspace | 将 veth2 加入 myspace 作为其一个 network interface |
4 | ifconfig veth1 192.168.45.2 netmask 255.255.255.0 up | 配置 veth1 的 IP 地址 |
5 | ip netns exec myspace ifconfig veth2 192.168.45.3 netmask 255.255.255.0 up | 配置 veth2 的 IP 地址,它和 veth1 需要在同一个网段上 |
6 | ip netns exec myspace route add default gw 192.168.45.2 | 将 myspace 的默认路由设为 veth1 的 IP 地址 |
7 | echo 1 > /proc/sys/net/ipv4/ip_forward | 开启 linux kernel ip forwarding |
8 | iptables -t nat -A POSTROUTING -s 192.168.45.0/24 -o eth0 -j MASQUERADE | 配置 SNAT,将从 myspace 发出的网络包的 soruce IP address 替换为 eth0 的 IP 地址 |
9 | iptables -t filter -A FORWARD -i eth0 -o veth1 -j ACCEPT | 在默认 FORWARD 规则为 DROP 时显式地允许从 veth1 到 eth0 的 forwarding |
这些配置之后,host 上的 route 表中自动添加了一条路由规则:
root@compute2:/home/s1# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 192.168.45.0 0.0.0.0 255.255.255.0 U 0 0 0 veth1
myspace 的路由表:
root@compute2:/home/s1# ip netns exec myspace route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.45.2 0.0.0.0 UG 0 0 0 veth2 192.168.45.0 0.0.0.0 255.255.255.0 U 0 0 0 veth2
其中第一条是显式地被创建的,第二条是自动被创建的。
现在你就可以从 myspace 中 ping 外网的地址了。
如果没有设置第八条 SNAT,那么 ICMP Request 能够到达对方计算机,但是 echo reply 消息回不来,因为其目的地址为一个内部地址。
root@compute1:/home/s1# tcpdump -eni bridge1 -p icmp -v tcpdump: listening on bridge1, link-type EN10MB (Ethernet), capture size 65535 bytes 07:40:03.827852 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 54069, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.45.3 > 192.168.1.15: ICMP echo request, id 26569, seq 1, length 64 07:40:04.829779 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 54194, offset 0, flags [DF], proto ICMP (1), length 84)
加上第八条之后,ping 能成功,也就是 ICMP echo request 能发出,echo reply 能返回。
在 host2 的网卡 eth0 上,能看到 ICMP echo request 网络包的源 IP 为 host1 的 IP:
07:44:19.360519 08:00:27:c7:cf:ca > 08:00:27:4f:56:17, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 54265, offset 0, flags [none], proto ICMP (1), length 84) 192.168.1.15 > 192.168.1.32: ICMP echo reply, id 28534, seq 7, length 64 07:44:20.358360 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 21278, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.1.32 > 192.168.1.15: ICMP echo request, id 28534, seq 8, length 64
在 host1 的网卡 eth0 上,能看到来回网络包使用的是 host1 和 host2 的 IP 地址:
root@compute2:/home/s1# tcpdump -envi eth0 -p icmp -v tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 06:31:27.285150 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 58781, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.1.32 > 192.168.1.15: ICMP echo request, id 29610, seq 158, length 64 06:31:27.285777 08:00:27:c7:cf:ca > 08:00:27:4f:56:17, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 23662, offset 0, flags [none], proto ICMP (1), length 84) 192.168.1.15 > 192.168.1.32: ICMP echo reply, id 29610, seq 158, length 64
在 host1 的 veth1 上,能看到发出的网络包的源 IP 和收到的网络包的目的 IP 皆为内部网段的 IP 地址:
root@compute2:/home/s1# tcpdump -envi veth1 -p icmp -v tcpdump: listening on veth1, link-type EN10MB (Ethernet), capture size 65535 bytes 06:33:13.355956 b2:52:7e:b6:e9:4e > ee:53:ae:dd:6f:7f, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 6989, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.45.3 > 192.168.1.15: ICMP echo request, id 29610, seq 264, length 64 06:33:13.356391 ee:53:ae:dd:6f:7f > b2:52:7e:b6:e9:4e, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 36067, offset 0, flags [none], proto ICMP (1), length 84) 192.168.1.15 > 192.168.45.3: ICMP echo reply, id 29610, seq 264, length 64
那为什么在 forwarding 发生之前,在 iptables nat 表中并没有显式做 DNAT 的情况下 veth1 和 eth0 之间有了 DNAT 呢?
原因是 ICMP 使用了 Query ID,而 NAT 会自动根据 ICMP Query ID 对 ICMP echo reply 做 DNAT。根据 https://tools.ietf.org/html/rfc5508 的 3.1. ICMP Query Mapping 章节,当内部的 host1 发一个 ICMP Query 给外部 host2 时,linux 内核的 NAT 模块会针对 NAT 的外部地址分配一个匹配的 query ID(上面例子中的 id 29610);然后当收到 ICMP echo reply 时,NAT模块会根据 ICMP Query ID 以及 ICMP header checksum 将外部 IP 转化为内部 IP,然后再做 forwarding。也可以看出,ICMP Query ID 类似于 TCP 和 UDP 使用的端口号(port number),两者的区别在于 NAT 为 ICMP 自动做了 DNAT,而 TCP 和 UDP 则需要显式添加 DNAT 规则。
(图片来源)
Linux 内核在从 veth1 上收到 myspace 发过来的 ICMP 包以后,
(3)关于 myspace 的默认路由
因为 myspace 只有一根网线(veth)连接到 veth1,因此,必须将默认的路由器地址设置为 veth1 的 IP 地址。
上面的配置只是为了能从 myspace 中访问外网。要使得外面网络能访问 myspace 中的应用的话,则需要在 host1 上添加 DNAT 规则,比如将 8080 端口受到的 TCP 转到内部 IP 上的 80 端口;同时还需要配置 forward 规则,允许从 eth0 出到 veth1 进。基本过程为:
对方计算机使用 host1 的 IP 地址和特定端口访问 mysapce 中的 TCP 应用 (192.168.1.32:8080),
Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网
标签:
原文地址:http://www.cnblogs.com/sammyliu/p/5760125.html