摘要
本文記錄以運行於VMware Workstation 12 Player的Ubuntu MATE 16.04作為網路位址轉譯(Network Address Translation)裝置來進行封包轉送的注意事項。說明
網路位址轉譯(NAT)提供一個方法,可將網路上電腦的網際網路通訊協定第4版(IPv4)位址,轉譯成其他網路電腦的IPv4位址。NAT技術的開發提供一個暫時解決 IPv4 位址消耗問題的方法。較為詳細的說明可以參考這裡。本文的實驗將以運行於Windows 10上的VMware Workstation 12 Player的Ubuntu MATE 16.04作為網路位址轉譯裝置,另外搭配一虛擬Windows 7主機、VMware內建的選徑器(router)、以及Internet上Google的DNS伺服器作為協同測試的主機。
擔任網路位址轉譯裝置的Ubuntu MATE具備一張NAT卡和一張host-only卡;NAT卡將對應至enp0s16介面、而host-only卡將對應至enp0s19介面。VMware的NAT卡和host-only卡皆個別連接至一個DHCP伺服器,然而,相較於host-only卡已配置了192.168.50/24的位址和遮罩,NAT卡除了配置192.1689.29.0/24的位址和遮罩之外,還會額外配置選徑器192.168.29.2。
隨後的實驗將令NAT卡具備多組位址,再觀察選徑和NAT的行為。
開機登入Ubuntu MATE,先檢視核心版本。
user@ubuntu:~$ uname -r
4.4.0-112-generic
user@ubuntu:~$
可以見到其具備2張實體的ethernet介面。
user@ubuntu:~$ ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 00:0c:29:75:52:ba brd ff:ff:ff:ff:ff:ff
3: enp0s19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 00:0c:29:75:52:c4 brd ff:ff:ff:ff:ff:ff
user@ubuntu:~$
剛開機完畢時的enp0s16介面已具備一個VMware的NAT卡上的DHCP伺服器所配置的位址192.168.29.128。
user@ubuntu:~$ ip addr list dev enp0s16
2: enp0s16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether 00:0c:29:75:52:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.29.128/24 brd 192.168.29.255 scope global dynamic enp0s16
valid_lft 1457sec preferred_lft 1457sec
inet6 fe80::2c1e:f2fc:e536:790b/64 scope link
valid_lft forever preferred_lft forever
user@ubuntu:~$
透過sudo ip addr add 192.168.29.254/24 dev enp0s16和sudo ip addr add 192.168.29.253/24 dev enp0s16對enp0s16介面添加位址;所以,這時候enp0s16介面具備了3組IPv4的位址。
user@ubuntu:~$ ip addr list dev enp0s16
2: enp0s16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether 00:0c:29:75:52:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.29.128/24 brd 192.168.29.255 scope global dynamic enp0s16
valid_lft 1596sec preferred_lft 1596sec
inet 192.168.29.254/24 scope global secondary enp0s16
valid_lft forever preferred_lft forever
inet 192.168.29.253/24 scope global secondary enp0s16
valid_lft forever preferred_lft forever
inet6 fe80::2c1e:f2fc:e536:790b/64 scope link
valid_lft forever preferred_lft forever
user@ubuntu:~$
檢視選徑表,可以得知預設路徑為透過enp0s16介面傳送封包予192.168.29.2閘道器。
user@ubuntu:~$ ip route list
default via 192.168.29.2 dev enp0s16 proto static metric 100
169.254.0.0/16 dev enp0s19 scope link metric 1000
192.168.29.0/24 dev enp0s16 proto kernel scope link src 192.168.29.128 metric 100
192.168.50.0/24 dev enp0s19 proto kernel scope link src 192.168.50.129 metric 100
user@ubuntu:~$
這時候若在Ubuntu MATE嘗試聯繫Internet上的機器,例如此處下達ping 8.8.8.8 -c 1指令來透過ICMP聯繫Google的DNS伺服器,則Ubuntu MATE將使用192.169.29.128位址作為來源位址。預設路徑僅指定介面,縱然該介面具備多個位址,但選徑時將使用最早設置的那個位址。
不過,若是將預設路徑指定來源位址,則選徑時將使用指定的來源位址。
例如指定預設路徑的來源位址為192.168.29.128,則下達ping 8.8.8.8 -c 1時Ubuntu MATE將使用192.169.29.128位址作為來源位址。
user@ubuntu:~$ sudo ip route replace default via 192.168.29.2 dev enp0s16 src 192.168.29.128 proto static metric 100
user@ubuntu:~$ ip route list
default via 192.168.29.2 dev enp0s16 proto static src 192.168.29.128 metric 100
169.254.0.0/16 dev enp0s19 scope link metric 1000
192.168.29.0/24 dev enp0s16 proto kernel scope link src 192.168.29.128 metric 100
192.168.50.0/24 dev enp0s19 proto kernel scope link src 192.168.50.129 metric 100
user@ubuntu:~$
例如指定預設路徑的來源位址為192.168.29.254,則下達ping 8.8.8.8 -c 1時Ubuntu MATE將使用192.169.29.254位址作為來源位址。
user@ubuntu:~$ sudo ip route replace default via 192.168.29.2 dev enp0s16 src 192.168.29.254 proto static metric 100
user@ubuntu:~$ ip route list
default via 192.168.29.2 dev enp0s16 proto static src 192.168.29.254 metric 100
169.254.0.0/16 dev enp0s19 scope link metric 1000
192.168.29.0/24 dev enp0s16 proto kernel scope link src 192.168.29.128 metric 100
192.168.50.0/24 dev enp0s19 proto kernel scope link src 192.168.50.129 metric 100
user@ubuntu:~$
例如指定預設路徑的來源位址為192.168.29.253,則下達ping 8.8.8.8 -c 1時Ubuntu MATE將使用192.169.29.253位址作為來源位址。
user@ubuntu:~$ sudo ip route replace default via 192.168.29.2 dev enp0s16 src 192.168.29.253 proto static metric 100
user@ubuntu:~$ ip route list
default via 192.168.29.2 dev enp0s16 proto static src 192.168.29.253 metric 100
169.254.0.0/16 dev enp0s19 scope link metric 1000
192.168.29.0/24 dev enp0s16 proto kernel scope link src 192.168.29.128 metric 100
192.168.50.0/24 dev enp0s19 proto kernel scope link src 192.168.50.129 metric 100
user@ubuntu:~$
觀察完本機的選徑行為後,接著將進行轉發(forwarding)和NAT的設置。
啟用轉發功能。
user@ubuntu:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
user@ubuntu:~$ cat /proc/sys/net/ipv4/ip_forward
0
user@ubuntu:~$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
user@ubuntu:~$ cat /proc/sys/net/ipv4/ip_forward
1
user@ubuntu:~$
載入NAT所需的核心模組。
user@ubuntu:~$ sudo modprobe ip_tables
user@ubuntu:~$ sudo modinfo ip_tables
filename: /lib/modules/4.4.0-112-generic/kernel/net/ipv4/netfilter/ip_tables.ko
description: IPv4 packet filter
author: Netfilter Core Team <coreteam@netfilter.org>
license: GPL
srcversion: 89FE8FA5C005273382ED2E6
depends: x_tables
intree: Y
vermagic: 4.4.0-112-generic SMP mod_unload modversions 686
user@ubuntu:~$
選定enp0s19介面作為NAT設置的源頭;先檢視該介面的位址設置的現況。
user@ubuntu:~$ ip addr list dev enp0s19
3: enp0s19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether 00:0c:29:75:52:c4 brd ff:ff:ff:ff:ff:ff
inet 192.168.50.134/24 brd 192.168.50.255 scope global dynamic enp0s19
valid_lft 1208sec preferred_lft 1208sec
inet6 fe80::6af7:d076:167e:5d37/64 scope link
valid_lft forever preferred_lft forever
user@ubuntu:~$
接著檢視filter表的FORWARD的設置現況。
user@ubuntu:~$ sudo iptables -t filter -L FORWARD --line-numbers
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
user@ubuntu:~$
隨後檢視nat表的POSTROUTING的設置現況。
user@ubuntu:~$ sudo iptables -t nat -L POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
user@ubuntu:~$
然後,插入NAT規則;把來自192.168.50.0/24機器要往enp0s16介面傳送的封包的來源位址以MASQUERADE的形式予以改寫。
user@ubuntu:~$ sudo iptables -t nat -A POSTROUTING -s 192.168.50.0/24 -o enp0s16 -j MASQUERADE
user@ubuntu:~$ sudo iptables -t nat -L POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
1 MASQUERADE all -- 192.168.50.0/24 anywhere
user@ubuntu:~$
為了測試前述Ubuntu MATE的轉發功能,接下來要設置輔助測試的Windows 7機器。
首先檢視連接了host-only卡的Windows 7的位址和選徑資訊。
C:\Windows\system32>netsh int ip show addresses
Configuration for interface "Local Area Connection 2"
DHCP enabled: Yes
IP Address: 192.168.50.128
Subnet Prefix: 192.168.50.0/24 (mask 255.255.255.0)
InterfaceMetric: 10
Configuration for interface "Loopback Pseudo-Interface 1"
DHCP enabled: No
IP Address: 127.0.0.1
Subnet Prefix: 127.0.0.0/8 (mask 255.0.0.0)
InterfaceMetric: 50
C:\Windows\system32>route -4 print
===========================================================================
Interface List
15...00 0c 29 75 52 bb ......Intel(R) PRO/1000 MT Network Connection
1...........................Software Loopback Interface 1
11...00 00 00 00 00 00 00 e0 Microsoft ISATAP Adapter
16...00 00 00 00 00 00 00 e0 Teredo Tunneling Pseudo-Interface
===========================================================================
IPv4 Route Table
===========================================================================
Active Routes:
Network Destination Netmask Gateway Interface Metric
127.0.0.0 255.0.0.0 On-link 127.0.0.1 306
127.0.0.1 255.255.255.255 On-link 127.0.0.1 306
127.255.255.255 255.255.255.255 On-link 127.0.0.1 306
192.168.50.0 255.255.255.0 On-link 192.168.50.128 266
192.168.50.128 255.255.255.255 On-link 192.168.50.128 266
192.168.50.255 255.255.255.255 On-link 192.168.50.128 266
224.0.0.0 240.0.0.0 On-link 127.0.0.1 306
224.0.0.0 240.0.0.0 On-link 192.168.50.128 266
255.255.255.255 255.255.255.255 On-link 127.0.0.1 306
255.255.255.255 255.255.255.255 On-link 192.168.50.128 266
===========================================================================
Persistent Routes:
None
C:\Windows\system32>
接著將預設路徑指定為Ubuntu MATE的enp0s19介面上的位址192.168.50.134。
C:\Windows\system32>route add 0.0.0.0 mask 0.0.0.0 192.168.50.134
OK!
C:\Windows\system32>
下達ping 8.8.8.8 -n 1時,Windows 7將可以聯繫到Google的DNS。
封包轉發的流程為:Windows 7先將一個封包傳送至Ubuntu MATE,Ubuntu MATE轉發予VMware選徑器,Ubuntu MATE從VMware選徑器得到回應,Ubuntu MATE最後轉發回應予Windows 7;值得注意的是,從Ubuntu MATE發送予VMware選徑器的來源位址已經改寫為192.168.29.128了,即便Ubuntu MATE的預設路徑的來源位址仍維持在192.168.29.253,可以初步地歸納以MASQUERADE的形式進行改寫時來源位址跟選徑表的設置無關、而是使用該介面最早設置的global範疇的位址。
除了前述令所有的來源位址都改寫為同一個出境位址的作法之外,也可以令指定的來源位址改寫為指定的出境位址,此時規則就得捨棄MASQUERADE形式而以SNAT形式替換。
例如將來源為192.168.50.54改寫為192.168.29.254、並將來源為192.168.50.53改寫為192.168.29.253。
user@ubuntu:~$ sudo iptables -t nat -I POSTROUTING -s 192.168.50.54 -o enp0s16 -j SNAT --to-source 192.168.29.254
user@ubuntu:~$ sudo iptables -t nat -I POSTROUTING -s 192.168.50.53 -o enp0s16 -j SNAT --to-source 192.168.29.253
user@ubuntu:~$ sudo iptables -t nat -L POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
1 SNAT all -- 192.168.50.53 anywhere to:192.168.29.253
2 SNAT all -- 192.168.50.54 anywhere to:192.168.29.254
3 MASQUERADE all -- 192.168.50.0/24 anywhere
user@ubuntu:~$
為了測試更改後Ubuntu MATE的轉發功能,接下來要設置輔助測試的Windows 7機器。
首先檢視連接了host-only卡的Windows 7的位址和選徑資訊;全面改用靜態設置。
接著下達ping 8.8.8.8 -S 192.168.50.53 -n 1時,Windows 7將可以使用指定的位址來跟Google的DNS聯繫。
Ubuntu MATE在轉發該封包時也會將出境位址改寫為192.168.29.253
隨後下達ping 8.8.8.8 -S 192.168.50.54 -n 1時,Windows 7將可以使用指定的位址來跟Google的DNS聯繫。
Ubuntu MATE在轉發該封包時也會將出境位址改寫為192.168.29.254
最後,將來源為192.168.50.54改寫為192.168.29.254、並將來源為192.168.50.53改寫為192.168.29.253等規則予以刪除,Ubuntu MATE僅保留唯一的MASQUERADE形式的規則。
user@ubuntu:~$ sudo iptables -t nat -L POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
1 MASQUERADE all -- 192.168.50.0/24 anywhere
user@ubuntu:~$
令Windows 7將數個封包傳送至Ubuntu MATE,Ubuntu MATE個別地將封包轉發予VMware選徑器,Ubuntu MATE從VMware選徑器得到回應,Ubuntu MATE最後轉發回應予Windows 7;值得注意的是,從Ubuntu MATE發送予VMware選徑器的來源位址仍是192.168.29.128,即便同時存在數個連線。能夠用這個結果初步地歸納以MASQUERADE的形式進行改寫時來源位址跟選徑表的設置無關。
作者已經移除這則留言。
回覆刪除作者已經移除這則留言。
刪除在nf_nat_masquerade_ipv4函式中呼叫的inet_select_addr函式輸入了RT_SCOPE_UNIVERSE引數;
刪除http://elixir.free-electrons.com/linux/v4.4.112/source/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
在inet_select_addr函式將使用了for_primary_ifa巨集;
http://elixir.free-electrons.com/linux/v4.4.112/source/net/ipv4/devinet.c