AzureのNAT GatewayでLinux VMのアウトバウンドIPを固定する方法|az network nat gateway createとSNATポート管理の実践

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Azure > AzureのNAT GatewayでLinux VMのアウトバウンドIPを固定する方法|az network nat gateway createとSNATポート管理の実践
「AzureのVMからcurlを実行するたびに送信元IPが変わってしまい、外部APIのIPホワイトリスト申請が通らない」
「本番環境でいきなり外部へのHTTPS接続がリトライを繰り返してタイムアウトするようになった」

このような問題の多くは、SNATポートの枯渇またはアウトバウンドIPの不固定に起因しています。AzureのLinux VMは、作成時の設定によってパブリックIPの直接アタッチ、ロードバランサー経由のSNAT、デフォルトアウトバウンドアクセスのいずれかでアウトバウンド通信を行いますが、設計によってはSNATポートが枯渇したり送信元IPが不規則に変動したりします。

この記事では、Azure NAT Gateway(az network nat gateway)を使ってサブネットのアウトバウンド通信を固定IPで制御する方法を解説します。NAT Gatewayの作成からサブネットへの関連付け、Linux VMからの動作確認、SNATポート枯渇の診断とパブリックIPを追加する手順、アイドルタイムアウトとTCP Keepaliveの設定、さらにAWSのNAT Gatewayとの設計上の違いまで、azコマンドの実践例と実機ログを交えて解説します。

動作確認環境:Azure CLI 2.61 / RHEL 9.4(Azure VM上で動作確認済み)

この記事のポイント

・NAT GatewayをサブネットにつけるだけでアウトバウンドIPを固定できる
・SNATポートは1IPあたり64,000個で枯渇するとタイムアウトになる
・IPを追加するだけでSNATポートを64,000個ずつ増やせる(ダウンタイムなし)
・MonitorのUsed SNAT Portsで使用率75%超えを検知したらIP追加のサイン
・--idle-timeout(分単位)とTCP KeepaliveでアイドルRSTを防ぐ
・AWSのNAT GatewayはAZごとに1個必要だがAzureはゾーン冗長で1個で済む


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜAzure NAT Gatewayが必要なのか(デフォルトの問題と限界)

AzureのLinux VMは、作成時の設定によって次のいずれかのパスでアウトバウンド通信を行います。
・パブリックIPを直接アタッチ:VMのIPがそのまま送信元になる(固定だが、VMにIPを露出させる)
・ロードバランサー経由のSNAT:共有のフロントエンドIPで変換(SNATポートが制限される)
・デフォルトアウトバウンドアクセス:VNetが自動的に一時的なIPを割り当て(2025年以降、新規VMでは廃止方針)

3つの方式をアウトバウンドIPの固定・SNATポート数・管理コストの観点で整理すると次のようになります。

方式 送信元IP SNATポート数 主な課題
パブリックIP直接アタッチ 固定(VM固有) 制限なし(直接通信) VMのIPが外部に露出する。VMごとにIPが必要
Standard LB経由のSNAT LBのフロントエンドIP バックエンドVM数に応じて分割(最大1,024~64,000) VM台数が増えると1台あたりのポート数が減少。設計を誤ると枯渇しやすい
デフォルトアウトバウンドアクセス 不定(Azure管理IP) Azureが自動管理 IPが固定されない。2025年9月以降、新規VMでは廃止方針
NAT Gateway(推奨) 固定(割り当てたパブリックIP) 1IPあたり64,000個(IP追加で線形増加) コスト(NAT GatewayリソースとパブリックIPの課金が発生)

特に問題になりやすいのが「ロードバランサー経由のSNAT」です。Azure Standard Load BalancerのSNATは、バックエンドインスタンスの台数が多いほど1台あたりに割り当てられるポート数が減ります。例えばバックエンドVM数が16台なら1台あたり4,000ポートに制限され、大量の外部接続が発生するとすぐに枯渇します。枯渇するとアウトバウンド接続がドロップし、HTTPタイムアウトやDNS名前解決の失敗として現れます。

SNATポート枯渇が起きやすいシナリオを具体的に挙げます。
・Webスクレイピング:短時間に大量のTCP接続を張って切る処理は、TIME_WAITのポートが解放されるまで約4分間ポートを占有する
・マイクロサービス間通信:複数のサービスが外部APIを個別に呼ぶ設計では、接続先IPとポートの組み合わせ数が急増する
・夜間バッチ処理:平常時は余裕があっても、バッチ実行時に一気にポートを消費して枯渇する

また「デフォルトアウトバウンドアクセス」は2025年9月以降、新規に作成するVMでは廃止されつつあります。Azureの公式推奨はNAT Gatewayをサブネットに関連付けることで、シンプルかつ予測可能なアウトバウンド設計を実現することです。

なお、NAT GatewayはVMのアウトバウンド通信を制御する仕組みです。Azure StorageやKey VaultといったサービスへのアクセスをVNet内に閉じるPrivate Endpointとは補完関係にあります。本番環境では「NAT GatewayでアウトバウンドIPを固定しつつ、Private Endpointで必要なサービスをVNet内に閉じる」という組み合わせが設計の定石です。本記事はNAT Gatewayのアウトバウンド制御に絞って解説します。

NAT Gatewayを使う主なメリットをまとめます。
・固定のパブリックIP:送信元IPが変動しないため、外部サービスのIPフィルタリングに対応できる
・大量のSNATポート:1つのパブリックIPで最大64,000ポート(IPを追加すれば線形に増加)
・フルマネージド:可用性・スケーリングをAzureが自動で管理
・サブネット単位で適用:プライベートサブネット全体に一括適用できる

NAT Gatewayの構成要素と設計方針

NAT Gatewayを設定するには、次の3つのリソースが必要です。

リソース 役割 注意点
パブリックIPアドレス NAT後の送信元IPとなる固定グローバルIP Standard SKUが必須(Basic SKUは不可)
NAT Gatewayリソース SNATポートの管理とIP変換を行うフルマネージドゲートウェイ ゾーン冗長にするかゾーン指定かを選択する
サブネットへの関連付け 特定のサブネットのアウトバウンドをNAT Gateway経由にする 1サブネットに関連付けできるNAT Gatewayは1つのみ

ゾーン設計について:NAT Gatewayはゾーン指定とゾーン冗長(ゾーン非指定)の2種類から選べます。
・ゾーン指定(例:--zone 1):特定のAvailability Zone内でのみ動作する。同じゾーンのVMに適用する構成で使う
・ゾーン冗長(既定):--zoneを省略するとゾーンをまたいで動作するゾーン冗長構成になる

本番環境でゾーン冗長VMを使っている場合は、ゾーン非指定(既定)のNAT Gatewayを作成することでゾーンに依存しないアウトバウンド設計が実現できます。ゾーン指定にする場合は、接続するパブリックIPも同じゾーンで作成する必要があります(ゾーンが異なるとAssociate時にエラーになります)。

パブリックIPプレフィックス(Public IP Prefix)を使う選択肢もあります。これは連続したIPアドレスのブロック(例:/28 = 16アドレス)をまとめて固定できるため、外部ベンダーに「この範囲のIPからアクセスします」と申告する場合に便利です。単一IPを個別に管理する代わりにプレフィックスで一括申告できるため、外部サービスへのIPホワイトリスト申請の手間が減ります。ただし本記事では基本構成として単一のパブリックIPを使う方法を解説します。

設計のポイントとして、NAT Gatewayのアイドルタイムアウトのデフォルトは4分です。アウトバウンド方向のTCP接続で4分間通信がない状態が続くと、Azureのファイアウォールがその接続を解放します。アプリ側はRSTやタイムアウトで接続断を検知します。長時間続く接続(例:DBコネクションプーリングや長寿命HTTP Keep-Alive)がある場合は、アプリ側のTCP Keepaliveを60秒程度に設定しておくことで、Azureがアイドル接続と判断する前に定期的にパケットを送信できます。

Linuxカーネルのレベルでは次のパラメータが参考になります。

# TCP Keepalive設定(/etc/sysctl.confに追記) # アイドル60秒後にKeepAliveを送信開始 net.ipv4.tcp_keepalive_time = 60 # 10秒間隔で9回試みて応答なしなら接続断 net.ipv4.tcp_keepalive_intvl = 10 net.ipv4.tcp_keepalive_probes = 9 # 設定を即時反映 sysctl -p

アプリケーション(例:PostgreSQL接続プール)がソケットオプションのSO_KEEPALIVEをサポートしている場合は、アプリ側の接続設定でKeepaliveを有効にするほうが確実です。なお、TCPレベルのKeepaliveではなくHTTP Keep-Aliveを使うアプリケーションの場合、HTTP Keep-Aliveのタイムアウト値もNAT Gatewayのアイドルタイムアウト(デフォルト4分)より短くなるよう調整してください。

サブネット設計の観点では、NAT Gatewayを適用するサブネット(プライベートサブネット)と適用しないサブネット(パブリックサブネット)を分けて管理するのが推奨です。例えば「snet-private(NAT Gateway適用)」と「snet-public(Application Gateway等のフロントエンド)」に分けることで、アクセス制御のポリシーをサブネット単位で明確に管理できます。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Azureの学習をもっと体系的に進めたいなら、Azure実践ハンズオン講座をご覧ください。現役エンジニアが教える実務直結カリキュラムで、VM構築からインフラ管理まで一気に習得できます。

NAT Gatewayを設定する手順

実際のazコマンドを使って、NAT Gatewayの作成からサブネットへの関連付け、Linux VMからの動作確認まで順を追って説明します。

前提として、リソースグループ(rg-demo)とVNet(vnet-demo、アドレス空間 10.1.0.0/16)、サブネット(snet-private、10.1.1.0/24)が作成済みであることとします。VNetの作成やAzure CLIのセットアップがまだの場合は、先にそちらを済ませてから本記事の手順を進めてください。

1. 既存VNetとサブネットの確認

まず、対象のVNetとサブネットが正しく存在するか確認します。

# vnet list: リソースグループ内のVNetとサブネットを確認 az network vnet list --resource-group rg-demo --query "[].{Name:name, AddressSpace:addressSpace.addressPrefixes[0]}" -o table # サブネット一覧の確認(NatGwがnoneならNAT Gateway未設定) az network vnet subnet list --resource-group rg-demo --vnet-name vnet-demo --query "[].{Name:name, Prefix:addressPrefix, NatGw:natGateway}" -o table

実行結果の例:

Name Prefix NatGw ------------ ------------- ------ snet-private 10.1.1.0/24 None snet-public 10.1.2.0/24 None

NatGwがNoneならNAT Gateway未設定です。これからNAT Gatewayを作成して関連付けていきます。

2. Standard SKUのパブリックIPアドレスを作成する

NAT GatewayにはStandard SKUの静的パブリックIPが必要です。Basic SKUは使用できないため注意してください。ゾーン指定でNAT Gatewayを構成する場合は、パブリックIPも同じゾーン番号を指定する必要があります(ここではゾーン冗長構成のため--zone指定は省略します)。

# Standard SKU・静的パブリックIPの作成 az network public-ip create --resource-group rg-demo --name pip-natgw-01 --sku Standard --allocation-method Static --location japaneast # IPアドレスの確認 az network public-ip show --resource-group rg-demo --name pip-natgw-01 --query "{Name:name, IP:ipAddress, SKU:sku.name}" -o table

実行結果の例:

Name IP SKU ------------- --------------- -------- pip-natgw-01 20.x.xxx.xxx Standard

このIPアドレスがNAT後の送信元IPとなります。外部サービスへのIPホワイトリスト申請はこのIPを使用します。

3. NAT Gatewayリソースを作成する

次にNAT Gatewayリソース本体を作成し、手順2で作成したパブリックIPを関連付けます。--idle-timeoutは秒ではなく分単位で指定します。デフォルトの4分から2分に短縮することで、TIME_WAIT状態になったポートが早めに解放されSNATポートの消費を抑えられます。ただし、短すぎるとアプリ側でRSTを受け取る頻度が増えるため、アプリケーションの通信パターンに合わせて調整してください。

# NAT Gatewayの作成(アイドルタイムアウト2分・ゾーン冗長) az network nat gateway create --resource-group rg-demo --name natgw-demo --public-ip-addresses pip-natgw-01 --idle-timeout 2 --location japaneast # ゾーン1に固定する場合は --zone 1 を追加(パブリックIPも同じゾーンで作成要) # az network nat gateway create ... --zone 1 # 作成確認 az network nat gateway show --resource-group rg-demo --name natgw-demo --query "{Name:name, ProvisionState:provisioningState, IdleTimeout:idleTimeoutInMinutes, Zones:zones}" -o table

実行結果の例:

Name ProvisionState IdleTimeout Zones ---------- -------------- ----------- ------- natgw-demo Succeeded 2 None

ProvisioningStateがSucceededになればNAT Gatewayの作成完了です。ZonesがNoneであればゾーン冗長構成として動作します。

4. NAT GatewayをサブネットにAssociateする

作成したNAT Gatewayを対象のサブネットに関連付けます。この操作でサブネット内のVMのアウトバウンド通信がNAT Gateway経由になります。

# サブネットにNAT Gatewayを関連付け az network vnet subnet update --resource-group rg-demo --vnet-name vnet-demo --name snet-private --nat-gateway natgw-demo # 関連付けの確認 az network vnet subnet show --resource-group rg-demo --vnet-name vnet-demo --name snet-private --query "natGateway.id" -o tsv

実行結果の例(NAT GatewayのリソースIDが返れば成功):

/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-demo/providers/Microsoft.Network/natGateways/natgw-demo

リソースIDが返れば関連付け成功です。「None」が返る場合は--nat-gatewayオプションの値(リソース名またはリソースID)を確認してください。

5. Linux VMからアウトバウンドIPを確認する

サブネット内のLinux VMにSSHで接続し、実際の送信元IPを確認します。ifconfig.meは送信元IPをそのまま返すAPIサービスです。

# VM上でアウトバウンドIPを確認 [user@vm-private-01 ~]$ curl -s https://ifconfig.me 20.x.xxx.xxx # 何度実行しても同じIPが返ることを確認(3回試して全て一致すればOK) [user@vm-private-01 ~]$ for i in 1 2 3; do curl -s https://ifconfig.me; echo; done 20.x.xxx.xxx 20.x.xxx.xxx 20.x.xxx.xxx # 外部TCPサービスへの疎通確認(ncコマンドでHTTPS接続を試みる) [user@vm-private-01 ~]$ nc -zv ifconfig.me 443 Connection to ifconfig.me 443 port [tcp/https] succeeded!

手順2で確認したパブリックIPと一致していれば、NAT Gatewayが正しく機能しています。送信元IPが固定されているため、外部サービスのIPフィルタリングに対応できます。

なお、NAT Gatewayに複数のパブリックIPを割り当てている場合は、接続先ごとに送信元IPが変わる可能性があります。その場合は割り当てたすべてのIPをホワイトリストに登録してください。また、ncコマンドが「Command not found」になる環境では dnf install nmap-ncat(RHEL系)または apt install netcat-openbsd(Ubuntu系)でインストールできます。

SNATポート枯渇の診断と解消方法

NAT Gatewayを使っていても、SNATポートは有限です。1つのパブリックIPで同時に確保できるSNATポートは最大64,000個です。Webスクレイピングやマイクロサービスが大量の外部接続を同時に張る環境では、このポートが枯渇して接続障害が発生します。

SNATポートが枯渇すると、アプリ側では「Connection timed out」や「No buffer space available」として現れます。Azure MonitorのメトリクスでSNAT使用量を確認しましょう。

1. Azure MonitorでSNAT使用量を確認する

azコマンドでSNATポートの使用状況をリアルタイムに取得できます。

# NAT GatewayのリソースIDを取得 NATGW_ID=$(az network nat gateway show --resource-group rg-demo --name natgw-demo --query id -o tsv) # 過去1時間のUsed SNAT Portsを5分粒度で確認 az monitor metrics list --resource "$NATGW_ID" --metric "UsedSNATPorts" --interval PT5M --aggregation Maximum --start-time "$(date -u -d '1 hour ago' '+%Y-%m-%dT%H:%M:%SZ')" --end-time "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" --query "value[0].timeseries[0].data[-5:].{Time:timeStamp, Used:maximum}" -o table

実行結果の例(1IPあたり64,000ポートが上限):

Time Used ------------------------ -------- 2026-07-26T04:00:00+00:00 1024.0 2026-07-26T04:05:00+00:00 8192.0 2026-07-26T04:10:00+00:00 24576.0 2026-07-26T04:15:00+00:00 51200.0 2026-07-26T04:20:00+00:00 59392.0

この値が60,000(64,000の約93%)を超えてきたら、SNATポート枯渇のリスクがあります。Azureの推奨は使用率75%(48,000ポート)を超えたらパブリックIPを追加することです。

サブネット内に複数のVMが存在する場合、SNATポートは1IPあたりの合計が64,000個で、VM台数に関係なくこの上限が適用されます。つまり、10台のVMが同時に接続を張る環境では事実上「6,400ポート×10台相当の競合」になる点を念頭に置いてください。アクセスが集中するシステムでは、最初からIPを2本以上割り当てる設計が安定します。

Azure Monitorのアラートルールを事前に設定しておくと、枯渇の予兆を自動で検知できます。

# Used SNAT Portsが50,000を超えたらメールで通知するアラートを作成 az monitor metrics alert create --resource-group rg-demo --name "alert-snat-port-high" --resource "$NATGW_ID" --metric "UsedSNATPorts" --condition "avg UsedSNATPorts > 50000" --window-size 5m --evaluation-frequency 1m --action-group "ag-ops-team" --description "NAT Gateway SNATポート使用量が50,000を超えました"

--action-groupにはあらかじめ作成したアクショングループ(メール・SMS・Webhookの宛先)を指定します。アラートグループがない場合は先にaz monitor action-group createで作成してください。

2. パブリックIPを追加してSNATポートを増やす

SNATポート枯渇への対処として最もシンプルな方法は、NAT Gatewayに割り当てるパブリックIPを追加することです。IPを1つ追加するたびにSNATポートが64,000個ずつ増加します。この操作はダウンタイムなしで実施できます。

# 2本目のパブリックIPを作成 az network public-ip create --resource-group rg-demo --name pip-natgw-02 --sku Standard --allocation-method Static --location japaneast # NAT Gatewayに2本目のIPを追加 # ※--public-ip-addressesには既存のpip-natgw-01と新規のpip-natgw-02を両方指定する az network nat gateway update --resource-group rg-demo --name natgw-demo --public-ip-addresses pip-natgw-01 pip-natgw-02 # 割り当てIP一覧の確認 az network nat gateway show --resource-group rg-demo --name natgw-demo --query "publicIpAddresses[].id" -o table

実行結果の例(2本のIPが表示されれば合計128,000ポートに増加):

Result ---------------------------------------------------------------------------------------------- /subscriptions/xxxx.../publicIPAddresses/pip-natgw-01 /subscriptions/xxxx.../publicIPAddresses/pip-natgw-02

注意点:--public-ip-addressesオプションは「既存 + 追加したいIP」をすべて指定します。既存のpip-natgw-01を書き忘れると、そのIPがNAT Gatewayから切り離されます。なお、NAT Gatewayには最大16個のパブリックIPを割り当てられるため、最大で1,024,000ポートまでスケールできます。

3. IP追加後の送信元IP確認と外部サービスへの登録

IP追加後は、割り当てた全IPアドレスを確認して外部サービスのIPホワイトリストに追加する必要があります。

# NAT Gatewayに割り当てたすべてのIPアドレスを確認 az network public-ip list --resource-group rg-demo --query "[?starts_with(name,'pip-natgw')].{Name:name, IP:ipAddress}" -o table

実行結果の例:

Name IP ------------- --------------- pip-natgw-01 20.x.xxx.xxx pip-natgw-02 20.y.yyy.yyy

Azure NAT Gatewayは複数IPが割り当てられると、接続先ごとに送信元IPを振り分けます。外部サービスへのIPフィルタリング申請には、このリストにあるすべてのIPアドレスを登録してください。

4. VM内でTCP接続状況を確認する

SNATポート枯渇の原因調査として、VM内でのTCP接続状況を確認することも有効です。TIME_WAIT状態の接続が大量にある場合は、短命なTCP接続を大量に張る処理がSNATポートを消費している可能性があります。

# TIME_WAIT状態の接続数を確認 [user@vm-private-01 ~]$ ss -ant | grep TIME-WAIT | wc -l 3842 # 接続先の上位を確認(どこへの接続がTIME_WAITを多く作っているか) [user@vm-private-01 ~]$ ss -ant state time-wait | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10 2341 203.0.113.xx 987 198.51.100.xx 514 192.0.2.xx

TIME_WAITが数千件を超えている場合は、HTTP接続でKeep-Aliveを有効にして接続の再利用率を上げること、または接続プールを使うことでTIME_WAIT数を減らせます。なお、TIME_WAITは正常なTCP終了シーケンスの一部であり、それ自体がエラーではありません。SNATポート枯渇につながるのは、その数がSNATポートの上限に近づいた場合です。ポート確認コマンドの詳細は「Linuxのポート確認コマンド」も参考にしてください。

トラブルシュート|NAT Gatewayが機能しない時の確認ポイント

NAT Gatewayを設定したのにアウトバウンドIPが変わらない、または接続できないという場合、次のポイントを順に確認してください。

【確認1】サブネットへの関連付けを確認する

最も多いのはサブネットへのAssociate忘れです。次のコマンドで確認します。

az network vnet subnet show --resource-group rg-demo --vnet-name vnet-demo --name snet-private --query "natGateway.id" -o tsv

「None」または空行が返る場合は、手順4のサブネット更新コマンドを再実行してください。

【確認2】VMのNICがパブリックIPを直接持っていないか確認する

VMのNICにパブリックIPが直接アタッチされている場合、そのVMはNAT GatewayではなくインスタンスレベルのパブリックIP(ILPIP)経由でアウトバウンドします。ILPIPはNAT Gatewayより優先されるため、NAT Gatewayが適用されません。

# VMのNICを確認してパブリックIPの有無をチェック NIC_ID=$(az vm show --resource-group rg-demo --name vm-private-01 --query "networkProfile.networkInterfaces[0].id" -o tsv) az network nic show --ids "$NIC_ID" --query "ipConfigurations[0].publicIpAddress.id" -o tsv

何も表示されなければNICへのパブリックIPアタッチはなく、NAT Gateway経由でアウトバウンドされます。パブリックIPが表示された場合は、そのIPをNICからデタッチする必要があります。

【確認3】NSGのアウトバウンドルールを確認する

サブネットまたはNICにNSG(ネットワークセキュリティグループ)が設定されていて、アウトバウンドのHTTPS(443)をDENYしている場合は通信が遮断されます。ポート疎通確認の方法は「Linuxのポート確認コマンド」も参考にしてください。

# サブネットに紐づくNSGのアウトバウンドルールを確認 NSG_ID=$(az network vnet subnet show --resource-group rg-demo --vnet-name vnet-demo --name snet-private --query "networkSecurityGroup.id" -o tsv) az network nsg rule list --ids "$NSG_ID" --query "[?direction=='Outbound'].{Name:name, Priority:priority, Access:access, Port:destinationPortRange}" -o table

「Deny」ルールがポート443や80をブロックしている場合は、ルールを修正するか優先度の高い「Allow」ルールを追加してください。NSGとNAT Gatewayを組み合わせる場合、NSGルールの送信先にIPアドレスの代わりにApplication Security Group(ASG)を使うと、VM台数が増えてもルールの修正なしに管理できます。

【確認4】Route TableでUDRがアウトバウンドをバイパスしていないか確認する

Route Table(ルートテーブル)に「アウトバウンドをNVAやAzure Firewallへ転送するUDR」が設定されていると、NAT Gatewayではなくそちらへ転送されます。有効ルートで経路を確認します。

# VMのNICに適用されている有効ルートを確認 az network nic show-effective-route-table --resource-group rg-demo --name nic-vm-private-01 --query "value[?addressPrefix=='0.0.0.0/0'].{Prefix:addressPrefix, NextHopType:nextHopType, NextHopIP:nextHopIpAddress}" -o table

「NextHopType」が「Internet」であればNAT Gateway経由の正常フローです。「VirtualAppliance」であればNVAやFirewallへの転送が設定されているため、意図した動作かを確認してください。Azure FirewallとNAT Gatewayを組み合わせる場合は、UDRでFirewallを経由した後にNAT Gatewayでアウトバウンドするよう設計し、Firewallの設定でアウトバウンド方向のSNATを担わせるかNAT Gatewayに任せるかを意識して設計してください。

【確認5】パブリックIPとNAT Gatewayのゾーンが一致しているか確認する

ゾーン指定でNAT Gatewayを作成した場合、割り当てるパブリックIPのゾーンが一致していないとAssociate時にエラーになります。ゾーン冗長構成(--zone省略)では発生しませんが、ゾーン固定構成に変更した際にゾーンのミスマッチが起きやすいため確認方法を押さえておいてください。

# NAT Gatewayのゾーン設定を確認 az network nat gateway show --resource-group rg-demo --name natgw-demo --query "zones" -o tsv # パブリックIPのゾーン設定を確認 az network public-ip show --resource-group rg-demo --name pip-natgw-01 --query "zones" -o tsv

両者のゾーン値が一致していない場合は、同じゾーンでパブリックIPを作成し直してから関連付けてください。ゾーン冗長構成(どちらもNone)の場合は問題ありません。

【確認6】TCPアイドルタイムアウトによる接続リセットが起きていないか確認する

NAT Gatewayのアイドルタイムアウト(デフォルト4分)以上にわたって通信のないTCP接続は、AzureがSNATエントリを解放します。アプリ側がその接続を再利用しようとするとRSTが返り「Connection reset by peer」として現れます。

この症状が疑われる場合は、まずtcpdumpでRSTパケットを確認してください。

# VM内でRSTパケットの発生を確認(eth0はNICに合わせて変更) [user@vm-private-01 ~]$ sudo tcpdump -i eth0 "tcp[tcpflags] & tcp-rst != 0" -n -c 20 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes 04:23:11.123456 IP 10.1.1.4.52341 > 203.0.113.xx.443: Flags [R.], seq 0, ack 1, win 0, length 0 ...

RSTが頻繁に発生している場合は、前述の「NAT Gatewayの構成要素と設計方針」で説明したTCP Keepaliveの設定を見直してください。アイドルタイムアウトよりも短い間隔でKeepAliveパケットを送ることで、SNATエントリが維持されます。

【確認7】az network nat gateway createでエラーが出た場合

NAT Gateway作成時によく出るエラーとその対処を紹介します。

# エラー例1: Basic SKUのパブリックIPを指定した場合 az network nat gateway create --public-ip-addresses pip-basic-01 ... # (BadRequest) PublicIPAddress /subscriptions/xxx/pip-basic-01 is not Standard SKU. # 対処: Standard SKUでパブリックIPを作成し直す # エラー例2: ゾーン指定のNAT GatewayにゾーンなしIPを割り当てた場合 az network nat gateway create --zone 1 --public-ip-addresses pip-no-zone ... # (BadRequest) Public IP address pip-no-zone zone must match NAT gateway zone. # 対処: 同じゾーン番号でパブリックIPを作成し直す(--zone 1 を指定) # エラー例3: --idle-timeoutに秒数を指定した場合(分単位が正しい) az network nat gateway create --idle-timeout 120 ... # idleTimeoutInMinutes は分単位のため「120分」として扱われる # デフォルト4分に戻すには --idle-timeout 4 を指定する

いずれのエラーも、エラーメッセージをそのまま読むと原因と対処が分かります。NAT Gateway作成後に設定を変更したい場合はaz network nat gateway updateで上書きできます。

AWSのNAT GatewayとAzure NAT Gatewayの違い

AWSにも同名の「NAT Gateway」があります。機能面は似ていますが、ゾーン設計・コスト構造・スケール方法に重要な違いがあります。AWSのEC2環境でNAT Gatewayを使ったことがある方向けに、運用上の差異を整理します。

比較軸 Azure NAT Gateway AWS NAT Gateway
作成コマンド az network nat gateway create aws ec2 create-nat-gateway
サブネットへの適用方法 az network vnet subnet update --nat-gatewayでサブネットに直接関連付け ルートテーブルの 0.0.0.0/0 → NAT Gateway ID を設定
ゾーン冗長 --zone を省略すればゾーン冗長(1リソースで複数AZをカバー) AZごとに1個作成が推奨(AZ間でのフェイルオーバーなし)
最大SNATポート数(1IP) 64,000ポート 約64,512ポート
IPを追加してスケールする方法 az network nat gateway update --public-ip-addressesで最大16個まで追加(ダウンタイムなし) 1 NAT GatewayにElastic IPは1個のみ。別AZに追加のNAT Gatewayを作成してスケール
アイドルタイムアウト --idle-timeout で変更可能(分単位、デフォルト4分・最大120分) 固定350秒(変更不可)
コスト構造 NAT Gatewayリソース時間料金 + パブリックIP時間料金 + データ処理量(GB単位) NAT Gateway時間料金 + データ処理量(GB単位)

AzureのNAT GatewayはAZ横断のゾーン冗長が組み込まれているため、AWSのように「AZごとに1個」作る必要がなく、1リソースでサブネット全体をカバーできます。一方、AWSのNAT GatewayはElastic IPを1本しか持てないため、SNATポートを増やすには別AZに追加のNAT Gatewayを作成するという設計になります。Azureは1つのNAT Gatewayに最大16個のパブリックIPを割り当てられ(最大1,024,000ポート)、管理が1リソースに集中できる点が利点です。

アイドルタイムアウトについては、AWSは350秒固定でアプリ側のKeepalive設定に頼るしかありませんが、AzureはNAT Gateway側で分単位に調整できます。長時間接続が多いアプリケーションでは、AzureはNAT Gatewayのタイムアウトを延ばすことで接続維持のチューニング幅が広がります。

コスト面では、AzureはパブリックIPのリソース料金が別途かかる点がAWSと異なります。複数IPを割り当てた場合はIP数分の料金が発生するため、割り当てIPを定期的に見直すことをお勧めします。

本記事のまとめ

Azure NAT GatewayでLinux VMのアウトバウンド通信を制御するポイントをまとめます。

やりたいこと コマンド
Standard SKUのパブリックIPを作成する az network public-ip create --sku Standard --allocation-method Static
NAT Gatewayを作成する(ゾーン冗長) az network nat gateway create --public-ip-addresses pip名 --idle-timeout 分数
NAT Gatewayを作成する(ゾーン指定) az network nat gateway create --public-ip-addresses pip名 --idle-timeout 分数 --zone 1
サブネットにNAT Gatewayを関連付ける az network vnet subnet update --nat-gateway natgw名
VM上でアウトバウンドIPを確認する curl -s https://ifconfig.me
外部TCPポートへの疎通を確認する nc -zv ホスト名 ポート番号
SNATポート使用量を確認する az monitor metrics list --metric UsedSNATPorts
SNATポート超過アラートを設定する az monitor metrics alert create --metric UsedSNATPorts --condition "avg UsedSNATPorts > 50000"
パブリックIPを追加してSNATポートを増やす az network nat gateway update --public-ip-addresses pip01 pip02
サブネットへのNAT Gateway関連付けを確認する az network vnet subnet show --query "natGateway.id"
VMのNICに有効なルートを確認する az network nic show-effective-route-table --name NIC名
VM内のTIME_WAIT接続数を確認する ss -ant | grep TIME-WAIT | wc -l
NAT GatewayのゾーンとIPのゾーンを確認する az network nat gateway show --query "zones"
TCPアイドルタイムアウトを変更する az network nat gateway update --idle-timeout 分数

Azure NAT Gatewayはサブネットにアタッチするだけで、仮想マシンのアウトバウンドIPを固定して大量のSNATポートを提供するフルマネージドサービスです。デフォルトアウトバウンドアクセスは廃止される方向にあるため、本番環境ではNAT Gatewayへの移行が推奨されます。

SNATポートが逼迫してきたらaz network nat gateway updateでパブリックIPを追加するだけで、ダウンタイムなしでスケールできます。Azure MonitorのUsed SNAT Portsに閾値アラートを設定しておくことで、問題が顕在化する前に対処できます。アイドルタイムアウトによる接続リセットが起きている場合は、TCP Keepalive設定を見直して接続を維持する設計を検討してください。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。