Azure Web App(Linux)から Azure SQL や他のデータベースへ安全に接続するには、送信元として見える Outbound IP の変動を正しく理解し、設計と運用で吸収することが重要です。本記事では「どの操作で IP が変わるのか」「どう設計すれば影響を最小化できるのか」を、実運用で役立つ手順・スクリプト・チェックリストまで含めて具体的に解説します。
Azure Web App(Linux)の Outbound IP が“固定でない”理由
Azure App Service(マルチテナント)では、アプリの外向き通信はプラットフォーム側の SNAT(Source NAT)を経由してインターネットや PaaS サービスに到達します。SNAT の終端に使われる送信元 IP は環境の増減・配置換え・メンテナンス等で変化し得るため、「完全固定のグローバル送信元 IP」を前提にしたアクセス制御は基本的に推奨されません。
用語の整理
- outboundIpAddresses:
現時点でアプリが利用している送信元 IP の集合(カンマ区切り)。 - possibleOutboundIpAddresses:
今後のスケールや基盤操作により割り当てられる可能性のある送信元 IP の「上限集合」。
実運用ではこちらを すべて許可する設計が基本方針になります。
どの操作・イベントで Outbound IP が変わるのか
結論として、以下のあらゆる操作・イベントで IP の追加・削除が発生する可能性があります。特に、計画的な変更や“最後のアプリの削除→再作成”などは変動リスクが高まります。
| 操作/イベント | 変動しやすさ | 起きる理由(要約) | 実運用の注意 | 推奨対応 |
|---|---|---|---|---|
| スケールアウト(インスタンス数変更) | 中 | ワーカー割り当てや SNAT プールの変化で 増減・再配置 の可能性。 | 普段は大きく変わらないこともあるが保証はない。 | possibleOutboundIpAddresses を常時許可。作業前に新旧 IP を併存。 |
| スケールアップ/ダウングレード(SKU 変更) | 高 | 別の計算スタンプへ再配置されることがある。 | Basic ⇔ Standard ⇔ Premium の切替は特に要注意。 | 作業前に possible を反映、切替後の確認を自動化。 |
| サービスプラン変更(別プランへの移行) | 高 | プラン間移行でワーカー群が変わる。 | リソースグループやサブスクリプション跨ぎでリスク上昇。 | 一時的に新旧 IP を併存許可。自動更新スクリプトを併用。 |
| リージョンメンテナンス/基盤アップグレード | 中 | 基盤側の最適化・ローテーションで SNAT 先が変化。 | 予告なく発生し得る。 | 常に possible を許可。接続監視の導入。 |
| リージョン移行(再配置) | 最高 | リージョンが変われば SNAT も別物に。 | 移行計画のクリティカルパスに。 | 移行先で possible を先入れ。移行期間は併存許可。 |
| アプリ削除 → 再作成 | 最高 | 割当てが解放され別のプールで再取得される。 | 同名・同リージョンでも別物と考える。 | 再作成前に possible を取得・許可。再作成後に確定反映。 |
最小工数で実現する基本対処方針
- DB 側ファイアウォールには「可能性のあるすべての IP」を許可する。
=possibleOutboundIpAddressesの全件を投入。 - 計画変更(スケール/SKU 変更等)の直前・直後に必ず差分確認し、旧 IP を段階的に外す。
- 根本的に変動を避けたい場合はパブリック IP 依存をやめる(後述の設計パターンへ移行)。
CLI で current / possible を即時確認
# 現在利用中の IP と、今後割当ての可能性がある IP を同時に取得
az webapp show \
--resource-group <リソースグループ名> \
--name <アプリ名> \
--query "{current: outboundIpAddresses, possible: possibleOutboundIpAddresses}"
設計パターンの比較:パブリック IP 許可 vs. Private Link
| 接続方式 | 概要 | セキュリティ | 可用性/運用 | 向いているケース |
|---|---|---|---|---|
| ① パブリック IP 許可 (possible 全許可) | DB のファイアウォールに Web App の possibleOutboundIpAddresses を全て投入。 | 送信元 IP ベース。鍵・資格情報の管理が別途必要。 | SKU変更や基盤変更の影響を 事前許可で吸収。IP 管理の自動化が鍵。 | 短期/既存環境の延命。まずは早く安定させたい場合。 |
| ② Private Link(推奨) | DB にプライベート エンドポイントを作成し、Web App は VNet 統合で プライベート IPに接続。 | インターネットを経由せず、送信元 IP 管理から解放。ゼロトラストに整合。 | DNS/VNet 設計が必要。だが一度構築すれば IP 変動の影響を受けない。 | 本番・機微データ。将来の変更にも強い標準解。 |
| ③ App Service Environment(ASE v3) | アプリを専用 VNet にホスト。NAT ゲートウェイ等で 送信元 IP を自社管理可能。 | 最も厳格に制御可能。 | コストと運用の複雑さは増える。高要件向け。 | 厳格なネットワーク分離・大規模環境。 |
重要な補足:Service Endpoints について
マルチテナントの App Service(通常の Web App)が VNet 統合だけで Service Endpoints を直接活用して Azure SQL のパブリック エンドポイントへ到達する設計は、制約や前提が多く現実的ではありません。Private Link(プライベート エンドポイント)を第一選択とし、Web App は VNet 統合、DB 側は Private Endpoint、DNS はプライベート DNS ゾーンで解決という構成が最もシンプルで堅牢です。ASE を利用する場合は Service Endpoints も選択肢になりますが、多くの環境では Private Link の方が設計・運用の一貫性に優れます。
段階的移行ガイド:パブリック IP 許可から Private Link へ
- 現行の安定化:DB 側に possibleOutboundIpAddresses を一括許可。
- Web App の VNet 統合を設定(専用のサブネットを用意)。
- DB(Azure SQL など)に プライベート エンドポイントを作成し、同一またはピアリング済みの VNet に配置。
- プライベート DNS ゾーンにレコードを作成し、Web App の VNet にリンク。
- 接続文字列を FQDN(プライベート解決される既存名)で保持し、疎通確認。
- エラー監視(後述)で 24〜48 時間ほど動作を検証。問題なければ パブリック IP 許可を縮小。
運用で効く“3 つの保険”
1) 継続監視(アラート)
- アプリ側:接続失敗レート、例外(SQL error 40615:IP 許可がない場合に発生)、リトライ回数。
- DB 側:拒否ログ、拒否 IP(どの IP が塞がれているか)。
- 変更検知:
outboundIpAddressesに変化があったら通知。
2) 自動更新スクリプト(サンプル)
以下は Azure SQL サーバーに possibleOutboundIpAddresses を自動反映する Bash 例です。CRON / Azure Automation などでの定期実行を想定し、差分追加のみ・命名規則・冪等性を意識しています。
#!/usr/bin/env bash
set -euo pipefail
RESOURCE_GROUP=""
WEBAPP_NAME=""
SQL_SERVER="" # .database.windows.net の 部分
RULE_PREFIX="webapp-egress-"
LOCATION="" # ルールのメタ管理に使う場合
# 1) possibleOutboundIpAddresses を取得(カンマ区切り)
IPS_CSV=$(az webapp show
--resource-group "$RESOURCE_GROUP"
--name "$WEBAPP_NAME"
--query "possibleOutboundIpAddresses" -o tsv)
# 2) 配列化
IFS=',' read -ra IPS <<< "$IPS_CSV"
# 3) 既存ルール一覧を取得
EXISTING=$(az sql server firewall-rule list
--resource-group "$RESOURCE_GROUP"
--server "$SQL_SERVER"
--query "[?starts_with(name, '$RULE_PREFIX')].name" -o tsv || true)
# 4) 可能性のある IP をすべて投入(既存はスキップ)
for ip in "${IPS[@]}"; do
rule="${RULE_PREFIX}${ip//./-}" # 例: 20-40-60-80
if echo "$EXISTING" | grep -qx "$rule"; then
echo "Skip (exists): $rule"
else
az sql server firewall-rule create
--resource-group "$RESOURCE_GROUP"
--server "$SQL_SERVER"
--name "$rule"
--start-ip-address "$ip"
--end-ip-address "$ip"
>/dev/null
echo "Created: $rule ($ip)"
fi
done
echo "Completed: $(date) @ $LOCATION"
※ Azure Database for PostgreSQL / MySQL を使用している場合は、各サービス用の CLI サブコマンド(az postgres flexible-server firewall-rule、az mysql flexible-server firewall-rule など)に置き換えてください。
3) 計画作業前の“一時的併存”
スケール/SKU 変更を行う前に possible を DB 側へ投入し、新旧 IP を一時併存させてから作業します。切替完了後、current を確認して不要ルールのみを段階的に除去すると、通信断の可能性を大幅に下げられます。
Linux Web App 特有の補足
- Container(カスタムイメージ)利用時も Outbound IP の考え方は同じです。ベースイメージの差異は送信元 IP の固定性に影響しません。
- 外部のレジストリ(プライベート ACR など)へアクセスする場合は、レジストリ側のファイアウォールも possible で許可するか、ACR Private Link を用いてプライベート接続へ切替えます。
- アプリの**受信トラフィックに対するアクセス制限(Access Restrictions)**は送信元 IP(Outbound)とは無関係です。混同しないよう注意してください。
よくある誤解とアンチパターン
- 「今見えている Outbound IP は当面変わらないはず」:
変わらないこともありますが、保証はありません。運用方針としては possible の全許可が前提です。 - 「VNet 統合だけで送信元 IP を固定化できる」:
マルチテナントの Web App でインターネット宛を特定の固定 IP にすることはできません。固定化したい場合は Private Link や ASE を検討します。 - 「Service Endpoints を使えば簡単」:
通常の Web App では前提条件や制約が多く、汎用的な解は Private Link です。
設計と運用のチートシート
| テーマ | 推奨 | チェックポイント |
|---|---|---|
| 初期接続方式 | 短期は「possible 全許可」、中長期は「Private Link」。 | 要件(セキュリティ/コスト/導入速度)に合わせてロードマップ化。 |
| 変更作業の手順 | 作業前に possible を投入 → 作業 → 作業後に current を確認 → 不要 IP を削除。 | アラートやダッシュボードで失敗がないか即時検知。 |
| 監視 | アプリ例外(40615 等)・接続失敗レート・リトライ・DB 側拒否ログ。 | 閾値と通知先(チャット/メール)を運用 Runbook に明記。 |
| 自動化 | CLI / IaC(Bicep, Terraform)でファイアウォールを冪等更新。 | 命名規則・タグ・変更履歴を残し、棚卸しを半自動化。 |
| DNS | Private Link 移行時はプライベート DNS ゾーンを正しくリンク。 | 名前解決がパブリックに漏れていないか nslookup で確認。 |
PowerShell での一括反映(例)
$rg = "<rg>"
$app = "<app>"
$sql = "<sql-server-name>"
$prefix = "webapp-egress-"
# WebApp の possible を取得
$site = az webapp show --resource-group $rg --name $app | ConvertFrom-Json
$ips = $site.possibleOutboundIpAddresses.Split(',')
# 既存ルール名を取得
$existing = az sql server firewall-rule list --resource-group $rg --server $sql | ConvertFrom-Json
$existingNames = $existing.name
foreach ($ip in $ips) {
$rule = "$prefix$($ip -replace '.', '-')"
if ($existingNames -contains $rule) {
Write-Host "Skip $rule"
} else {
az sql server firewall-rule create ` --resource-group $rg`
--server $sql ` --name $rule`
--start-ip-address $ip `
--end-ip-address $ip | Out-Null
Write-Host "Created $rule ($ip)"
}
}
トラブルシューティング:接続できなくなったら
- 症状:アプリから DB へ接続不可、SQL error 40615 が増加。
- 原因候補:Outbound IP が変わった/可能性のある IP を許可していない/DNS が誤ってパブリックを向いている(Private Link 移行中)。
- 一次対処:
az webapp showで current と possible を取得。- DB 側に possible を一括投入し、直ちに疎通確認。
- 監視ダッシュボードでエラー減少を確認。
- 恒久対処:Private Link へ設計移行し、IP ベース許可を段階的に撤廃。
セキュリティ強化の実践ポイント
- 資格情報の最小化:接続は マネージド ID(Managed Identity)+ DB 側のロールで厳格化。秘密管理は Key Vault を利用。
- ゼロトラスト整合:ネットワーク的に閉域化(Private Link)+ ID ベース制御(データプレーン)を基本に。
- 権限分離:ネットワーク変更・DB 変更・アプリデプロイの責務を分離し、Change 管理で可視化。
ケーススタディ:よくある 3 つのシナリオ
シナリオ A:既存本番でたびたび接続断が出る
即応:possible を全許可 → アラート調整 → デプロイ時のチェックリストに az webapp show を追加。
中期:Private Link 設計・試験(ステージング) → 夜間に切替 → 旧ルール撤去。
シナリオ B:大規模スケールアップを予定
作業 2〜3 営業日前に 新旧併存でルール投入。作業後に current を確認し、不要ルールを削除。リハーサルで平均所要時間・復旧手順をドキュメント化。
シナリオ C:厳格な規制要件がある環境
ASE v3+NAT ゲートウェイ/ファイアウォールで送信元 IP を自社管理し、DB は Private Link。コンプライアンス監査に合わせたネットワーク・ログの長期保管を設計。
チェックリスト(そのまま運用 Runbook に転記可)
- [ ] データベース側に possibleOutboundIpAddresses を全件登録済み
- [ ] スケール/SKU 変更の前後で current と possible を取得・差分確認
- [ ] 40615 をはじめとする接続エラーに対するアラート閾値を設定
- [ ] Private Link 設計(VNet 統合/Private DNS/RBAC)が承認済み
- [ ] 自動更新スクリプトの実行結果が監査ログに残る
- [ ] 変更凍結期間やロールバック手順が Runbook に明記されている
まとめ
Azure Web App(Linux)の Outbound IP は固定ではありません。スケールや SKU 変更、基盤メンテナンス、再作成等で追加・削除が起こり得ます。短期的な安定化には possibleOutboundIpAddresses の全許可と自動反映、そして変更前後の併存が最もコスト対効果の高い対処です。中長期的には Private Link を採用して「送信元 IP という概念に依存しない」状態を作ることで、セキュリティと運用の両面で強固かつシンプルな接続基盤が得られます。設計・監視・自動化という 3 本柱を押さえ、IP 変動の不確実性を仕組みで吸収していきましょう。

コメント