Skip to content

讓 Azure VM 對外連線的多種花樣

或許有些讀者知道小弟以前是專搞地端 Infra 服務的架構師,興趣就是專門看 Networking 和他相關連的服務,最近來到雲端之後,只能說雖然看起來都是一台 VM 連線出去到 Internet,但實際上眉角還蠻多的...倒是如果你是地端網路工程師的話,剛接觸 Azure 網路的話,蠻推薦基礎先從 AZ-700 Designing and Implementing Microsoft Azure Networking Solutions 開始著手,保證你可以研究很久

另外要特別感恩國外的大神 Toni Pasanen 寫了一堆文章讓我更清楚瞭解 Azure Networking 架構 Toni Pasanen - Azure Networking Fundamentals: Internet Access with VM-Specific Public IP 一圖解釋 Azure VM 對外網路連線方式,強烈推薦給大家

Inbound Traffic 和 Outbound Traffic

先了解一下用詞定義

  • Inbound Traffic: 特定 Azure VM 可以接收來自 Internet 的連線,於 Azure 實際上的做法,不外乎 DNAT (Destination NAT)、 1 to 1 NAT 或直接從 Internet 路由進來
  • Outbound Traffic: 特定 Azure VM 可以發送連線到 Internet,於 Azure 實際上的做法就是 SNAT (Source NAT) 或直接路由到 Internet

本文會著重討論 Outbound Traffic 的狀況

了解 Azure Public IP 能夠的分配種類

依據 Public IP addresses - At a glance 指出,若你的 Azure VM Instance 前面有 Azure 服務且具有 Azure Public IP 的話,是具備從 VM 發送連線到 Internet 或連線進來的能力,下列條列常見服務但不限於:

Componets IPv4 Static 指派 IPv4 Dynamic 指派
Azure Firewall ✅ ⛔
Azure NAT Gateway ✅ ⛔
Azure Route Server ✅ ⛔
Azure Bastion ✅ ⛔
Azure Application Gateway ✅ (v2 only) ✅ (v1 only)
Azure Virtual Network Gateway ✅ ✅
Azure Load Balancer (Public) ✅ ✅
Network Interace Card (Public) ✅ ✅

若你想了解 Azure Public IP Static 跟 Dynamic 的差異,可以點選此文參考 Azure Public IP - SKU,本文不贅述

但就一個 Azure VM 的角度來講,並不是上述的所有服務都能夠讓 VM 直接連線出去,譬如說今天一台 RHEL VM 要進行 dnf update 你勢必要連線到 Red Hat 的 Repos 才能下載,故下面再從中整理出能夠讓一台 VM 透過 Outbound Traffic 連線到 Internet 的多種連線方式

Outbound Traffic 之 5 種連線方式

依據 Use Source Network Address Translation (SNAT) for outbound connections 指出,

方法 生產環境用? 推薦等級? 適用 SKU
使用 Azure Firewall 透過 SNAT 連線到 Internet ✅ 極佳 Basic / Standard / Premium 可用
使用 Azure NAT Gateway 透過 SNAT 連線到 Internet ✅ 極佳 N/A
使用 Azure Load Balancer (Public) 透過 Oubound rules 連線到 Internet ✅ Stanard 可用,Basic 不可
直接將 Public IP 掛在 NIC 上讓 VM 連線到 Internet ✅ Standard / Basic 可用
什麼都不做,預設採用 Default Outbound Access IP 連線到 Internet ⛔ N/A

首先是關於 Azure Firewall v.s. Azure NAT Gateway 的選擇,因為都可以做 SNAT 出去,架構選擇關鍵在 2 個地方

  • 連線要不要 Firewall 保護? 這個蠻直覺的我就不講了
  • 要不要做 DNAT? 因為 Azure Firewall 可以做 DNAT 和 SNAT,但 Azure NAT Gateway 只能做 SNAT,不能使用 DNAT 管理 Inbound Traffic

這邊還有一個派生作法就是 Azure NAT Gateway with Azure Firewall,主要用 Azure NAT Gateway 可支援 64,512 SNAT Port 解決 Azure Firewall SNAT Port 僅 2,496 port 不足問題,詳細可以參考 Scale Azure Firewall SNAT,本文不贅述

其次是 Azure NAT Gateway v.s Azure Load Balancer,雖然前者是用 SNAT 出去,後者是用 Outbound Policy 出去,架構選擇關鍵在

  • 服務連線特性需不需要大量的 Outbound Traffic? 如果是的話,建議使用 Azure NAT Gateway,因為這服務專為 Outbound Traffic 設計,完全受控且具有高度復原性,可最大化避免 SNAT 耗盡問題 (SNAT Exhaustion Scenarios) 是 Outbound Traffic 最佳選擇

至於 Azure Load Balancer 服務本身是為了 Inbound Traffic 而設計,而非 Outbound Traffic,但他剛好具備 Outbound Policy - Outbound source network address translation (SNAT) 的管理功能,所以在本文中是一個選項,正也因為如此有一個派生作法就是 Azure NAT Gateway with Azure Load Balancer,但 Azure Load Balancer 處理 Inbound Traffic,而 Azure NAt Gateway 處理 Outbound Traffic,詳細可以參考 NAT and VM with a standard public load balancer,本文不贅述

關於 Default outbound access IP !!!???

什麼都不做也能連出去!!??

是,什麼都不設定的狀況下,也可以連線出去,基於 When is default outbound access provided?,這是 Azure 平台特性,這個功能叫做 Default Outbound Access IP,是一個隱含 (Implicit) 的資源,該 Public IP 並不會 顯示在 Azure Portal 上,且不算 Subscription Cost 的一環,而這個 Default Outbound Access IP 的特性如下:

  1. 只出不進: 只有 Outbound Traffic 能力,不具備 Inbound Traffic 能力
  2. 僅支援 TCP/UDP 連線,不支援 ICMP: 故你可以下載 package 但不能 ping 出去
  3. IP 會自己變動: 因為這個 IP 不歸屬客戶管理,故不會通知更換,故如果有任何跟這個 IP 有關連的服務,會直接受到影響

如何驗證我現在的 VM 是不是有這種隱含的 Public IP 資源?

基於 How To: 查詢及驗證自身 Public IP 所列,因為 Default outbound access IP 並不支援 ICMP,我們僅有 TCP/UDP 可用,故可以採用 DNS 查詢的方式來驗證

command
dig myip.opendns.com @resolver1.opendns.com

如何關閉或避免此狀況?

簡單來說就是要針對 Outbound Traffic 做顯式 (Explicit) 的設定,也就是明顯的告訴 Azure 要用什麼方式連線出去

  1. 設定 NSG (Network Security Group) 來限制 Outbound Traffic
  2. 採用 Outbound Traffic 之多種連線方式 章節所列方式之一,明確表示要怎麼介接出去

下面會針對方式 1 的 NSG 來做實測完全關閉 Outbound Traffic,並且驗證 VM 是否能正常運作

如何使用 Default outbound access IP?

於 Create a Virtual Machine 時,針對 Networking 頁面,使用下列參數:

選項 參數
Public IP None
NIC network security group None / Basic 皆可
Load Balancing None

實測 Default outbound access IP 行為

Lab 1: 新增 VM 且使用 Default outbound access IP 的 Outbound Traffic

選項 Outbound Traffic Inbound Traffic
ICMP ⛔ ⛔
TCP ✅ ⛔
UDP ✅ ⛔
HTTP ✅ ⛔
DNS ✅ ⛔
output_without_nsg
repairman@black-vm:~$ ping -c 1 www.microsoft.com
PING e13678.dscb.akamaiedge.net (23.219.5.163) 56(84) bytes of data.

--- e13678.dscb.akamaiedge.net ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

repairman@black-vm:~$ nc -zvw3 www.microsoft.com 80
Connection to www.microsoft.com 80 port [tcp/http] succeeded!
repairman@black-vm:~$ nc -zvw3 www.microsoft.com 443
Connection to www.microsoft.com 443 port [tcp/https] succeeded!


repairman@black-vm:~$ dig myip.opendns.com @resolver1.opendns.com

; <<>> DiG 9.16.1-Ubuntu <<>> myip.opendns.com @resolver1.opendns.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20264
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myip.opendns.com.              IN      A

;; ANSWER SECTION:
myip.opendns.com.       0       IN      A       x.x.x.x

;; Query time: 4 msec
;; SERVER: 208.67.222.222#53(208.67.222.222)
;; WHEN: Fri Feb 10 02:15:56 UTC 2023
;; MSG SIZE  rcvd: 61

repairman@black-vm:~$ curl -s -o /dev/null -I -w "%{http_code}" http://www.microsoft.com/
200

repairman@black-vm:~$ sudo apt update -y
Hit:1 http://azure.archive.ubuntu.com/ubuntu focal InRelease
Get:2 http://azure.archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:3 http://azure.archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB]
Get:4 http://azure.archive.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:5 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 Packages [8628 kB]
Get:6 http://azure.archive.ubuntu.com/ubuntu focal/universe Translation-en [5124 kB]
Get:7 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 c-n-f Metadata [265 kB]
Get:8 http://azure.archive.ubuntu.com/ubuntu focal/multiverse amd64 Packages [144 kB]
Get:9 http://azure.archive.ubuntu.com/ubuntu focal/multiverse Translation-en [104 kB]
Get:10 http://azure.archive.ubuntu.com/ubuntu focal/multiverse amd64 c-n-f Metadata [9136 B]
Get:11 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [2377 kB]

運作截圖:

Lab 2: 基於 Lab1 的情況將 NSG 掛載到 NIC 的 Outbound Traffic

新增一個 NSG 且於 Outbound Security rules 中設定

Key Value
Source Any
Source port ranges *
Destination Service Tag
Destination port ranges Internet
Service Custom
Protocol Any
Action Deny
Priority 100
Name DenyInternetOutbound

去覆蓋掉預設 65001 AllowInternetOutbound 的規則

在 Lab 1 的情況下,將該 NSG 並掛載 (Associate) 到這個 VM NIC 上,則測試效果會變成如下:

選項 Outbound Traffic Inbound Traffic
ICMP ⛔ ⛔
TCP ⛔ ⛔
UDP ⛔ ⛔
HTTP ⛔ ⛔
DNS ⛔ ⛔
output_with_nsg
repairman@black-vm:~$ ping -c 1 www.microsoft.com
PING e13678.dscb.akamaiedge.net (23.220.113.163) 56(84) bytes of data.

--- e13678.dscb.akamaiedge.net ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms


repairman@black-vm:~$ nc -zvw3 www.microsoft.com 80
nc: connect to www.microsoft.com port 80 (tcp) timed out: Operation now in progress
nc: connect to www.microsoft.com port 80 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 80 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 80 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 80 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 80 (tcp) failed: Network is unreachable
repairman@black-vm:~$ nc -zvw3 www.microsoft.com 443
nc: connect to www.microsoft.com port 443 (tcp) timed out: Operation now in progress
nc: connect to www.microsoft.com port 443 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 443 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 443 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 443 (tcp) failed: Network is unreachable
nc: connect to www.microsoft.com port 443 (tcp) failed: Network is unreachable


repairman@black-vm:~$ dig myip.opendns.com @resolver1.opendns.com

; <<>> DiG 9.16.1-Ubuntu <<>> myip.opendns.com @resolver1.opendns.com
;; global options: +cmd
;; connection timed out; no servers could be reached

實測總結

要達到對 Outbound Traffic 進行嚴格控管,包含 Default outbound access IP 的網路行為也在內,需要做下列事情

  • 使用 NSG 針對 Subnet 或 NIC 進行綁定
  • NSG 內的設定 Outbound Security rules 規則 DenyAllInternetOutbound 明確規範 Outbound 流量

如何正確 Outbound Traffic 連線方式?

  • 如果你是有一堆服務 (SNAT Port 大於 2,496) 只是想要有 1 ~ N 個受控 IP 連出外網的話,可以用 Azure NAT Gateway 來做
  • 如果你是有部分服務 (SNAT Port 小於 2,496) 需要連線出外網的話,但有重度資安需求的話,可以用 Azure Firewall 來做
  • 如果你是有上述兩個需求的綜合需求,可以用 Azure Firewall + Azure NAT Firewall Gateway 來做
  • 如果你只是單台 VM 想出網的話,直接將 Public IP 掛在 NIC 搭配 NSG 進行網路控管即可
  • 如果你要完全關閉 Default outbound access IP 能力的話,可以用 NSG 對 Subnet 範圍進行網路控管

Q & A

Q1: 預設狀況下,NSG 提供的 Rules 有哪一些?

A1: 讓 VM 可以透過 Default outbound access IP 的方式連線出的是因為 65001 AllowInternetOutbound 的規則

Q2: 我可不可以直接拿掉 65001 AllowInternetOutbound 的規則?

A2: 不行,這是 Azure 預設的規則,建議新增一條 DenyAllInternetOutbound 的規則透過較高的 Priority 覆蓋規則或於 OS Level 進行防火牆管理,如 Linux iptables, Windows Firewall

Q3: 我可不可以不要有 Default outbound access IP?

A3: 不行,這是 Azure 預設的能力

Q4: 我是不是可以一直用 Default outbound access IP 來連線?

A4: 不保證,因並非正式服務,建議掛載 Azure Public IP 來連線

Q5: 為啥我沒指派任何 Public IP 的 VM 可以連到 Internet 去更新系統?

A5: 因預設狀況下有 Default outbound access IP 的存在,和 NSG 預設規則 65001 AllowInternetOutbound 的存在,所以你可以連到 Internet 去更新系統

Q6: 那我可以用 Default outbound access IP 連線進來嗎?

A6: 不行,沒有給 Inbound Traffic 能力,Ping 不到,連不進來

Q7: TL;DR 給我一句話

A7: NSG 要用,用了平安,IP 後上,上班順遂

References