2018/02/11

以運行於VMware上的Ubuntu Linux來進行網路位址轉譯

摘要

本文記錄以運行於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 enp0s16sudo ip addr add 192.168.29.253/24 dev enp0s16enp0s16介面添加位址;所以,這時候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的形式進行改寫時來源位址跟選徑表的設置無關。

小結

透過前述實驗可以得知,預設路徑僅指定介面且未指定來源位址時,縱然該介面具備多個位址,但選徑時將使用最早設置的那個位址,反之,若是將預設路徑指定來源位址,則選徑時將使用指定的來源位址;另外,以MASQUERADE的形式進行改寫時來源位址跟選徑表的設置無關、而是使用該介面最早設置的global範疇的位址,若是打算令指定的來源位址改寫為指定的出境位址,則需改用SNAT形式撰寫規則。

參考文獻

http://engineer-leo.blogspot.tw/2015/07/virtualboxubuntu-linux.html

3 則留言:

  1. 作者已經移除這則留言。

    回覆刪除
    回覆
    1. 作者已經移除這則留言。

      刪除
    2. 在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

      刪除