標籤:
學習 Neutron 系列文章:
(1)Neutron 所實現的虛擬化網路
(2)Neutron OpenvSwitch + VLAN 虛擬網路
(3)Neutron OpenvSwitch + GRE/VxLAN 虛擬網路
(4)Neutron OVS OpenFlow 流表 和 L2 Population
(5)Neutron DHCP Agent
(6)Neutron L3 Agent
(7)Neutron LBaas
(8)Neutron Security Group
(9)Neutron FWaas 和 Nova Security Group
(10)Neutron VPNaas
(11)Neutron DVR
(12)Neutron VRRP
(13)High Availability (HA)
(14)使用 NAT 將 Linux network namespace 串連外網
(15)使用 Linux bridge 將 Linux network namespace 串連外網
Linux network namespace 串連外網從大類上來講主要有兩種方法:網路位址轉譯(NAT) 和 橋接(bridging),而橋接根據使用的橋接器又可以分為使用 linux bridge 和 Open vSwitch 網路等。本文將說明 NAT 具體配置過程以及原理。
1. 環境及配置
我們可以把一個 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 表中自動添加了一條路由規則:
[email protected]:/home/s1# route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0192.168.45.0 0.0.0.0 255.255.255.0 U 0 0 0 veth1
myspace 的路由表:
[email protected]:/home/s1# ip netns exec myspace route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 192.168.45.2 0.0.0.0 UG 0 0 0 veth2192.168.45.0 0.0.0.0 255.255.255.0 U 0 0 0 veth2
其中第一條是顯式地被建立的,第二條是自動被建立的。
現在你就可以從 myspace 中 ping 外網的地址了。
2 原理2.1 關於第八條 SNAT
如果沒有設定第八條 SNAT,那麼 ICMP Request 能夠到達對方電腦,但是 echo reply 訊息回不來,因為其目的地址為一個內部地址。
[email protected]:/home/s1# tcpdump -eni bridge1 -p icmp -vtcpdump: listening on bridge1, link-type EN10MB (Ethernet), capture size 65535 bytes07: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 6407: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 6407: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 位址:
[email protected]:/home/s1# tcpdump -envi eth0 -p icmp -vtcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes06: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 6406: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 位址:
[email protected]:/home/s1# tcpdump -envi veth1 -p icmp -vtcpdump: listening on veth1, link-type EN10MB (Ethernet), capture size 65535 bytes06: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 6406: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 規則。
2.2 關於 IP forwarding
(圖片來源)
Linux 核心在從 veth1 上收到 myspace 發過來的 ICMP 包以後,
- 執行 PREROTING 規則,本例不需要此配置此規則。
- 執行 Routing decision。它會檢查網路包的目的IP地址,發現它不在本機上,說明需要進行 routing (FORWARD)。因為 Linux 上預設的 IP forwarding 是關閉的,因此需要執行第七條命令來開啟它;然後再檢查 iptable 規則中的這種 forwarding (ICMP 包從veth1 出再進入 eth0)。通常為了安全起見,管理員會將 FORWARD 的預設規則設定為 DROP,此時則需要執行第九條命令顯式地允許(ACCEPT)所需要的 forwarding。
- 執行 ip forwarding。尋找 host1 上的路由表,網路包會被路由到 eth0。
- 執行 POSTROUTING 規則。因為此時的網路包的源 IP 位址仍然為內部地址,為了避免 ICMP 網路包有去無回,需要通過 SNAT 將內部地址轉換為外部地址。這就是第八條的作用。
- 從 eth0 發出
(3)關於 myspace 的預設路由
因為 myspace 只有一根網線(veth)串連到 veth1,因此,必須將預設的路由器地址設定為 veth1 的 IP 位址。
2.3 DNAT
上面的配置只是為了能從 myspace 中訪問外網。要使得外面網路能訪問 myspace 中的應用的話,則需要在 host1 上添加 DNAT 規則,比如將 8080 連接埠受到的 TCP 轉到內部 IP 上的 80 連接埠;同時還需要配置 forward 規則,允許從 eth0 出到 veth1 進。基本過程為:
對方電腦使用 host1 的 IP 位址和特定連接埠訪問 mysapce 中的 TCP 應用 (192.168.1.32:8080),
- Linux 核心在從 eth0 上收到發過來的TCP包(IP 為 192.168.1.32,連接埠為 8080)
- 執行 PREROTING 規則,將目的 IP 及連接埠修改為 192.168.45.3 和 80
- 執行 Routing decision。它會檢查網路包的目的IP地址,發現它不在本機上,說明需要進行 routing (FORWARD)。檢查 Linux 的 IP forwarding 是否開啟;然後再檢查 iptable 規則中的這種 forwarding (TCP 包從 eth0 出再進入 veth1)。通常為了安全起見,管理員會將 FORWARD 的預設規則設定為 DROP,此時則需要執行類似第九條命令顯式地允許(ACCEPT)所需要的 forwarding。
- 執行 ip forwarding。尋找 host1 上的路由表,網路包會被路由到 veth1。
- 執行 POSTROUTING 規則。儘管有第八條規則,但是它要求源地址在內部網段,因此不會執行。
- 從 veth1 發出的包通過 veth 裝置進入 myspace 的 veth0 網卡。
- 被 80 連接埠上的應用接收到。
Netruon 理解(11):使用 NAT 將 Linux network namespace 串連外網