Azure Firewall은 VNet 트래픽을 L3~L7에서 검사하는 관리형 Stateful 방화벽으로, 보통 Hub VNet의 AzureFirewallSubnet에 두고 Spoke 서브넷의 기본 경로(0.0.0.0/0)를 방화벽으로 보내서 씁니다. 규칙은 Firewall Policy로 관리하고, Threat Intelligence → DNAT → Network → Application Rule 순서로 처리됩니다. SKU는 Basic(250Mbps), Standard(30Gbps), Premium(100Gbps) 세 가지입니다.
1. Azure Firewall이란
Azure Firewall은 Azure가 운영하는 Stateful(연결 상태를 기억해 응답 트래픽을 자동으로 허용하는 방식) 방화벽입니다. 방화벽 VM을 직접 관리하지 않아도 되고, 기본으로 고가용성과 자동 확장이 들어가 있으며 Availability Zone에 나눠 배포할 수 있습니다. NSG가 서브넷 단위로 IP·포트를 거르는 것과 달리, Azure Firewall은 여러 VNet의 트래픽을 한곳에 모아 FQDN(도메인 이름), Threat Intelligence, Web Category까지 보고 판단합니다(역할 차이는 Azure Firewall, NSG, WAF 역할 정리에 정리했습니다).
Hub-Spoke 구조에서는 방화벽을 Hub에 하나 두고, 트래픽 방향마다 경로와 규칙을 다르게 잡습니다.
| 방향 | 라우팅 | 규칙 |
| 아웃바운드 (Spoke → 인터넷) |
Spoke 서브넷 UDR 0.0.0.0/0 → 방화벽 Private IP |
Application Rule(FQDN) Network Rule(IP·포트) |
| 인바운드 (인터넷 → VM) |
방화벽 Public IP로 접속 | DNAT Rule |
| East-West (Spoke ↔ Spoke) |
각 Spoke UDR에 상대 Spoke 대역 → 방화벽 |
Network Rule |
| Hybrid (온프레미스 ↔ Azure) |
GatewaySubnet UDR + Spoke UDR |
Network Rule |
2. 구성 구조

Spoke VM의 아웃바운드는 UDR로 Hub의 Azure Firewall을 거쳐 방화벽 Public IP로 나가고, 인바운드는 방화벽 Public IP의 DNAT Rule으로 VM에 들어오는 구성
Spoke 서브넷에 Route Table을 연결해 기본 경로(0.0.0.0/0)의 Next Hop을 방화벽 Private IP로 지정하면, Spoke에서 나가는 모든 트래픽이 VNet Peering을 지나 방화벽으로 갑니다. 방화벽은 규칙에 맞는 트래픽만 자신의 Public IP로 바꿔(SNAT, 출발지 주소 변환) 내보냅니다. 반대로 인터넷에서 들어올 때는 방화벽 Public IP의 특정 포트로 접속하면 DNAT(목적지 주소 변환) 규칙이 VM의 Private IP로 바꿔 전달합니다.
| 항목 | 조건 |
| AzureFirewallSubnet | 이름 고정, /26 이상 (확장할 때 인스턴스가 늘어나므로) |
| AzureFirewallManagementSubnet | 이름 고정, /26 이상 Basic SKU와 Forced Tunneling에 필요 |
| Public IP | Standard SKU, 고정(Static) 최대 250개 |
| Resource Group | 방화벽과 VNet은 같은 Resource Group Public IP는 다른 Resource Group도 가능 |
| NSG | AzureFirewallSubnet에는 연결할 수 없음 |
| Spoke Route Table | 0.0.0.0/0 → Virtual Appliance(방화벽 Private IP) BGP Route Propagation 끔 |
3. SKU 비교
SKU는 Basic, Standard, Premium 세 가지입니다. 요금은 배포 시간당 요금과 처리한 데이터 GB당 요금으로 나뉘고, 위로 갈수록 기능과 처리량이 늘어납니다.
| 항목 | Basic | Standard | Premium |
| 최대 처리량 | 250Mbps | 30Gbps | 100Gbps |
| Network·Application·DNAT Rule | 지원 | 지원 | 지원 |
| Threat Intelligence | Alert만 | Alert·Deny | Alert·Deny |
| Network Rule의 FQDN | 지원 안 함 | 지원 | 지원 |
| DNS Proxy | 지원 안 함 | 지원 | 지원 |
| Web Category | 지원 안 함 | 지원 | 지원 |
| TLS Inspection·IDPS·URL Filtering | 지원 안 함 | 지원 안 함 | 지원 |
| Prescaling | 지원 안 함 | 지원 | 지원 |
IDPS(침입 탐지·방지 시스템)는 알려진 공격 패턴을 찾아 경고하거나 차단하고, TLS Inspection은 HTTPS 트래픽을 방화벽에서 복호화해 URL 단위로 거를 수 있게 합니다. Standard와 Premium은 서로 바꿀 수 있지만 Basic에서 Standard로는 바꿀 수 없습니다. 그래서 저는 나중에 DNS Proxy나 Web Category가 필요할 가능성이 있으면 처음부터 Standard로 시작합니다.
4. 규칙 처리 순서

Threat Intelligence를 먼저 보고, DNAT → Network → Application Rule 순서로 처리하며, 아무 규칙에도 맞지 않으면 거부
규칙 종류의 처리 순서는 우선순위 숫자와 관계없이 항상 DNAT → Network → Application입니다. 같은 종류 안에서는 Rule Collection Group의 우선순위, 그다음 Rule Collection의 우선순위 순서로 처리하고, 숫자는 100(가장 높음)부터 65,000(가장 낮음)까지 씁니다. 처음 맞은 규칙에서 처리가 끝나므로 Network Rule에 맞은 트래픽은 Application Rule까지 가지 않습니다. 기본 동작은 전부 거부라서 허용할 트래픽만 규칙으로 엽니다.
| 규칙 | 기준 | SNAT | 용도 |
| DNAT | 방화벽 Public IP·포트 | 목적지를 VM IP로 변환 | 인바운드 공개 |
| Network | IP·포트·프로토콜 (FQDN은 DNS Proxy 필요) |
사설 대역 목적지는 안 함 | Spoke 간, 온프레미스, HTTP 외 프로토콜 |
| Application | FQDN, FQDN Tag, Web Category(HTTP/S, MSSQL) |
항상 함 | 인터넷 아웃바운드 |
Application Rule은 방화벽이 투명 프록시로 처리하므로 목적지가 사설 IP여도 항상 방화벽 Private IP로 SNAT됩니다. 그래서 Spoke 간 통신에서 원래 출발지 IP를 보존해야 하면 Network Rule로 엽니다.
4.1 Firewall Policy와 Classic Rule
규칙은 방화벽 리소스에 직접 넣는 Classic Rule과, 별도 리소스인 Firewall Policy 두 가지 방식으로 관리할 수 있습니다. Microsoft는 Firewall Policy를 권장하고, Premium 기능(IDPS, TLS Inspection, URL Filtering)은 정책에서만 설정할 수 있습니다.
| 항목 | Firewall Policy | Classic Rule |
| 관리 위치 | 별도 리소스 (Firewall Manager에서 중앙 관리) |
방화벽 리소스 안 |
| 여러 방화벽에 적용 | 정책 하나를 여러 방화벽·Region에 연결 | 방화벽마다 따로 설정 |
| 상속 | Parent Policy → Child Policy | 없음 |
| Premium 기능 | 지원 | 지원 안 함 |
| Virtual WAN Secured Hub | 지원 | 지원 안 함 |
| 요금 | 방화벽 1개 연결까지 무료 2개 이상이면 정책 요금 |
무료 |
Parent Policy의 Network·Application Rule은 Child Policy보다 항상 먼저 처리됩니다. 보안팀이 Parent Policy에 전사 공통 차단 규칙을 두고, 각 팀은 Child Policy에 자기 서비스 규칙만 넣는 식으로 나눕니다. DNAT Rule은 방화벽마다 다르므로 상속되지 않습니다.
5. Azure CLI로 구성해 보기
Hub VNet에 Standard 방화벽을 만들고, Spoke VM의 인터넷 트래픽을 방화벽으로 보내 허용한 도메인만 나가게 합니다. 방화벽 명령은 azure-firewall extension에 들어 있습니다.
5.1 Hub와 Spoke 네트워크
RG=rg-fw
LOC=koreacentral
az group create --name $RG --location $LOC
az extension add --name azure-firewall
# Hub: 방화벽 서브넷은 이름이 AzureFirewallSubnet, /26 이상
az network vnet create --resource-group $RG --name vnet-hub \
--address-prefixes 10.0.0.0/16 \
--subnet-name AzureFirewallSubnet --subnet-prefixes 10.0.1.0/26
# Spoke: 워크로드 서브넷
az network vnet create --resource-group $RG --name vnet-spoke \
--address-prefixes 10.1.0.0/16 \
--subnet-name snet-app --subnet-prefixes 10.1.1.0/24
# 양방향 Peering(방화벽을 거쳐 전달되는 트래픽 허용)
az network vnet peering create --resource-group $RG --name hub-to-spoke \
--vnet-name vnet-hub --remote-vnet vnet-spoke --allow-forwarded-traffic
az network vnet peering create --resource-group $RG --name spoke-to-hub \
--vnet-name vnet-spoke --remote-vnet vnet-hub --allow-forwarded-traffic
5.2 Firewall Policy와 규칙
# 방화벽 Public IP(Zone Redundant)
az network public-ip create --resource-group $RG --name pip-fw \
--sku Standard --zone 1 2 3
FW_PIP=$(az network public-ip show --resource-group $RG --name pip-fw \
--query ipAddress --output tsv)
# 정책: Threat Intelligence는 Deny 모드
az network firewall policy create --resource-group $RG --name fwpol-hub \
--sku Standard --threat-intel-mode Deny
# DNAT Rule: 내 공인 IP에서 방화벽 2222 포트 → VM 22 포트
az network firewall policy rule-collection-group create --resource-group $RG \
--policy-name fwpol-hub --name rcg-dnat --priority 100
az network firewall policy rule-collection-group collection add-nat-collection \
--resource-group $RG --policy-name fwpol-hub --rcg-name rcg-dnat \
--name dnat-ssh --collection-priority 100 --action DNAT \
--rule-name ssh-vm-app --ip-protocols TCP --source-addresses <내 공인 IP> \
--destination-addresses $FW_PIP --destination-ports 2222 \
--translated-address 10.1.1.4 --translated-port 22
# Network Rule: NTP(UDP 123)
az network firewall policy rule-collection-group create --resource-group $RG \
--policy-name fwpol-hub --name rcg-spoke --priority 200
az network firewall policy rule-collection-group collection add-filter-collection \
--resource-group $RG --policy-name fwpol-hub --rcg-name rcg-spoke \
--name net-allow --collection-priority 100 --action Allow \
--rule-type NetworkRule --rule-name allow-ntp --ip-protocols UDP \
--source-addresses 10.1.0.0/16 --destination-addresses '*' --destination-ports 123
# Application Rule: 허용한 도메인만 HTTP/HTTPS로
az network firewall policy rule-collection-group collection add-filter-collection \
--resource-group $RG --policy-name fwpol-hub --rcg-name rcg-spoke \
--name app-allow --collection-priority 200 --action Allow \
--rule-type ApplicationRule --rule-name allow-web \
--protocols Http=80 Https=443 --source-addresses 10.1.0.0/16 \
--target-fqdns '*.ubuntu.com' learn.microsoft.com ifconfig.me
5.3 방화벽 만들기
az network firewall create --resource-group $RG --name fw-hub \
--sku AZFW_VNet --tier Standard --zones 1 2 3 \
--vnet-name vnet-hub --conf-name ipconfig --public-ip pip-fw \
--firewall-policy fwpol-hub
FW_PRIVATE=$(az network firewall show --resource-group $RG --name fw-hub \
--query "ipConfigurations[0].privateIPAddress" --output tsv)
echo $FW_PRIVATE # 보통 10.0.1.4
5.4 Spoke Route Table
az network route-table create --resource-group $RG --name rt-spoke \
--disable-bgp-route-propagation true
az network route-table route create --resource-group $RG --route-table-name rt-spoke \
--name default-to-fw --address-prefix 0.0.0.0/0 \
--next-hop-type VirtualAppliance --next-hop-ip-address $FW_PRIVATE
az network vnet subnet update --resource-group $RG --vnet-name vnet-spoke \
--name snet-app --route-table rt-spoke
5.5 동작 확인
# 공용 IP 없는 VM(첫 VM이라 10.1.1.4를 받음)
az vm create --resource-group $RG --name vm-app --image Ubuntu2404 \
--size Standard_D2s_v5 --vnet-name vnet-spoke --subnet snet-app \
--public-ip-address "" --nsg "" --admin-username azureuser --generate-ssh-keys
# 허용한 도메인은 200, 규칙에 없는 도메인은 연결 실패(000)
az vm run-command invoke --resource-group $RG --name vm-app \
--command-id RunShellScript --scripts \
"curl -s -o /dev/null -w '%{http_code}\n' https://learn.microsoft.com; \
curl -s -m 5 -o /dev/null -w '%{http_code}\n' https://www.bing.com; \
curl -s ifconfig.me"
# DNAT로 SSH 접속
ssh -p 2222 azureuser@$FW_PIP
# 실습이 끝나면 삭제
az group delete --name $RG --yes --no-wait
ifconfig.me가 돌려주는 IP가 방화벽 Public IP($FW_PIP)와 같으면 VM의 아웃바운드가 방화벽을 거쳐 나가는 것입니다. 막힌 요청은 방화벽 로그(AZFWApplicationRule 테이블)에 거부 기록이 남으므로, 규칙이 의도대로 동작하는지 로그로 함께 확인합니다.
6. Forced Tunneling과 Management NIC
기본 구성에서는 AzureFirewallSubnet의 기본 경로가 인터넷이어야 합니다. 방화벽이 인터넷 트래픽을 온프레미스 방화벽이나 다른 NVA(Network Virtual Appliance)로 다시 보내는 Forced Tunneling을 하려면, Azure가 방화벽을 관리하는 트래픽을 따로 내보낼 Management NIC이 필요합니다.
| 항목 | 내용 |
| Management Subnet | AzureFirewallManagementSubnet, /26 이상 |
| Management Subnet 경로 | 0.0.0.0/0 → Internet, BGP Route Propagation 끔 |
| Management Public IP | 플랫폼 운영 전용(다른 용도로 못 씀) |
| Basic, Virtual WAN Secured Hub | 항상 켜져 있음 |
| 기존 Standard·Premium | Deallocate 후 Management Public IP와 함께 Allocate |
CLI에서는 방화벽을 만들 때 --m-conf-name, --m-public-ip를 함께 넘깁니다. 기존 방화벽에 켜려면 Deallocate·Allocate하는 동안 트래픽이 끊기므로 점검 시간에 작업합니다.
7. 운영 시 주의점
| 항목 | 조치 |
| SNAT 포트 부족 | Public IP 1개당 인스턴스별 2,496개입니다. Public IP를 늘리거나 AzureFirewallSubnet에 NAT Gateway를 연결합니다(Azure NAT Gateway 정리). |
| 오래 연결이 끊김 | TCP Idle Timeout은 4분이고 직접 바꿀 수 없습니다. 애플리케이션에서 TCP keep-alive를 켭니다(인바운드·아웃바운드는 지원 요청으로 최대 15분). |
| 트래픽 급증 때 지연 | 확장에 5~7분이 걸립니다. 행사처럼 예측되는 급증은 Prescaling으로 최소 Capacity Unit을 미리 올려 둡니다(Standard, Premium). |
| Deallocate 후 Allocate | 비용은 멈추지만 Private IP가 바뀔 수 있습니다. 바뀌면 UDR의 Next Hop도 고칩니다. |
| Spoke 간 통신 안 됨 | 양쪽 UDR에 상대 Spoke 대역 → 방화벽 경로가 있는지, Peering의 Allow Forwarded Traffic이 켜져 있는지 확인합니다. |
| Provisioning State Failed | 일부 인스턴스에 설정이 반영되지 않은 상태입니다. 방화벽은 동작하지만, 같은 설정을 다시 적용해 Succeeded로 만듭니다. |
| 로그 | Diagnostic Settings에서 Resource Specific 테이블로 Log Analytics에 보내면 규칙 종류별 테이블로 나눠 조회할 수 있습니다. |
8. 정리
- Azure Firewall은 Hub의 AzureFirewallSubnet(/26)에 두고, Spoke 서브넷의 0.0.0.0/0을 방화벽 Private IP로 보내 아웃바운드를 모읍니다.
- 규칙은 Firewall Policy로 관리하며 Threat Intelligence → DNAT → Network → Application 순서로 처리하고, 맞는 규칙이 없으면 거부합니다.
- SKU는 기능과 처리량으로 고르되 Basic에서 Standard로는 바꿀 수 없고, SNAT 포트가 부족하면 NAT Gateway를 함께 씁니다.
참고
'Cloud > Azure' 카테고리의 다른 글
| [Azure] Private Link Service 정리 (0) | 2026.09.25 |
|---|---|
| [Azure] Microsoft Foundry 구성 정리 (0) | 2026.09.25 |
| [Azure] AKS Ingress Gateway API 이전 정리 (0) | 2026.09.25 |
| [Azure] Azure NAT Gateway 정리 (0) | 2026.09.25 |
| [Azure] Azure Kubernetes Service 구성 정리 (0) | 2026.09.25 |