1. 背景:なぜ「独自ドメインのみ」に限定したいのか

App Service を作成すると myapp.azurewebsites.net のような既定ホスト名が自動で払い出されます。独自ドメイン(例: www.example.com)を割り当てた後も、この既定ホスト名は有効なままで、同じコンテンツに 2 つの入口ができます。これを放置すると次の課題が生じます。

動機 何が問題か 対策の方向性
SEO(重複コンテンツ) 既定ドメインと独自ドメインで同一コンテンツが 2 つの URL に露出し評価が分散 301 で独自ドメインへ正規化
ブランド統一 既定ホスト名が検索結果・共有リンクに出るとブランドが分散する 301 リダイレクト
サブドメイン乗っ取り対策 使われなくなった既定ホスト名が dangling サブドメインの温床になり得る 推測困難化・露出削減
セキュリティ(露出面の最小化) 直アクセス経路が増えるほど攻撃面が広がる Front Door / Private Endpoint でオリジンを隠す

本記事では、これらを SEO 重視の公開サイト遮断重視の API・社内システム に分けて、最適な手段を提示します。App Service の一般的な設定に関する Q&A は App Service 質問回答リスト も参考にしてください。

2. 結論:既定ドメインだけを選択的に無効化するネイティブ機能は存在しない

まず核心の結論です。2026 年半ば時点で、既定ホスト名だけを選択的にブロックしつつ独自ドメインは公開のまま生かす、というネイティブ機能はありません。よく混同される 3 つのプロパティはいずれも目的に合致しません。

Azure は機能追加が速いため、この否定的な結論も含め、公開前に必ず最新のドキュメントと実機で再確認することを推奨します。

2.1 混同されやすい近縁 3 プロパティ

プロパティ / 機能 何をするか 目的に合うか
autoGeneratedDomainNameLabelScope(Secure unique default hostname) 既定ホスト名にハッシュ+リージョン接尾辞を付与し推測困難にする(乗っ取り対策)。ブロックはしない ✕(無効化ではない)
hostNamesDisabled すべての公開ホスト名(既定+カスタム両方)を無効化 ✕(カスタムも死ぬ)
publicNetworkAccess = Disabled("App access") 公開エンドポイント全体を無効化(Private Endpoint 前提) ✕(カスタムも公開からは死ぬ)

hostNamesDisabledpublicNetworkAccess = Disabled は「全体ブロック(方法C)」として §5 で詳説します。ここでは、無効化と誤解されやすい autoGeneratedDomainNameLabelScope を整理します。

2.2 autoGeneratedDomainNameLabelScope は「推測困難化」であって「無効化」ではない

これは Web App 作成時の「Unique default hostname」トグルに対応するプロパティで、作成後は変更できません。既定ホスト名を contoso-a6gqaeashthkhkeu.eastus-01.azurewebsites.net のようなハッシュ付きの推測困難な名前にします。ただしアクセス自体は引き続き可能で、無効化ではありません。

  • GA 状況: Web Apps は 2024 年後半に GA、Functions / Logic Apps は 2026 年 1 月に GA。
  • 設定タイミング: 作成時のみ。既存アプリへの後付けは不可。スロットは各々独自のハッシュを持ちます。
  • 注意: リージョン番号の接尾辞は将来変わり得ます。
az webapp create -g <RG> -n <App> -p <Plan> --domain-name-scope TenantReuse
# 値: NoReuse | ResourceGroupReuse | SubscriptionReuse | TenantReuse
resource web 'Microsoft.Web/sites@2024-04-01' = {
  name: 'myapp'
  location: resourceGroup().location
  properties: {
    serverFarmId: plan.id
    autoGeneratedDomainNameLabelScope: 'TenantReuse'
  }
}

ポイント: この機能は「既定ホスト名を当てにくくする」ものであり、「独自ドメインのみに限定する」要件そのものは満たしません。目的を達成するには次の方法 A〜C を使います。

3. 方法A: アプリ層で 301 リダイレクト(公開サイト推奨)

App Service は受信リクエストの Host ヘッダーを書き換えずにアプリまで届けます(Host Name Preservation)。そのため直アクセス構成では、アプリやプラットフォームが受け取った Host を直接見れば「既定ホスト名で来たか」を判定できます。公開サイトでは、既定ホスト名を独自ドメインへ 301 恒久リダイレクト するのが SEO 上も最適です。

3.1 web.config URL Rewrite(Windows / IIS)

Windows プランの App Service には URL Rewrite モジュールがプリインストールされており、追加インストール不要です。action には Rewrite / Redirect(301・302・303・307 対応、308 は非対応)/ CustomResponse(任意ステータス)/ AbortRequest(TCP 切断)/ None があります。ホスト名は <match url> ではなく {HTTP_HOST} サーバー変数を <conditions> で判定します。

A. 301 リダイレクト(推奨・SEO 向け)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <!-- ACME/well-known は素通し(将来の catch-all 対策の保険) -->
        <rule name="Allow well-known" stopProcessing="true">
          <match url="^\.well-known/" />
          <action type="None" />
        </rule>
        <!-- *.azurewebsites.net → カスタムドメインへ 301 -->
        <rule name="Redirect default host" stopProcessing="true">
          <match url="(.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{HTTP_HOST}" pattern="azurewebsites\.net$" ignoreCase="true" />
          </conditions>
          <action type="Redirect" url="https://www.example.com/{R:1}"
                  appendQueryString="true" redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

B. ハードブロック(403) にするなら、アクションを差し替えます。

<action type="CustomResponse" statusCode="403" statusReason="Forbidden"
        statusDescription="Direct access via the default hostname is not permitted." />
<!-- もしくは <action type="AbortRequest" />(応答なしで切断) -->

落とし穴:

  • web.config はメインサイトのみに適用され、SCM/Kudu には影響しません。
  • App Service Managed Certificate(ASMC)の ACME 検証は Host: www.example.com(カスタムドメイン)で届くため、この azurewebsites.net ルールとは干渉しません。ただし SPA の catch-all リライトがある場合は、\.well-known/ の素通しルールを前段に置いてください。
  • 前段に Front Door を置き、オリジンのホストヘッダーが azurewebsites.net のままの構成だと、正規の AFD 経由トラフィックまで 301 されてしまいます。その場合は {HTTP_HOST} ではなく X-Forwarded-Host で判定するなど、ロジックの反転が必要です。

3.2 Node.js / Express(Linux)

Linux App Service はコンテナを内部リバースプロキシ配下で動かし、process.env.PORT に HTTP を転送し、X-Forwarded-For / X-Forwarded-Proto を付与します。trust proxy が無効なら req.hostname は生の Host を返します。

const express = require("express");
const app = express();
app.set("trust proxy", 1); // 前段プロキシ 1 ホップを信頼

const CANONICAL = "www.example.com";
app.use((req, res, next) => {
  const host = req.hostname; // ポート除外。trust proxy 有効時は X-Forwarded-Host 優先→Host
  if (host && host.toLowerCase().endsWith("azurewebsites.net")) {
    return res.redirect(301, `https://${CANONICAL}${req.originalUrl}`);
    // ブロックする場合: return res.status(403).send('Direct access not permitted.');
  }
  next();
});

trust proxy を使わずに明示的に読むなら req.headers['x-forwarded-host'] を参照します(カンマ区切りのときは先頭値)。

3.3 前段プロキシがある場合の Host 読み取り注意

Front Door や Application Gateway が前段にいて Host を書き換える構成のときだけ、X-Forwarded-Host が必要になります。ASP.NET Core では ForwardedHeaders を明示的に有効化します。

builder.Services.Configure<ForwardedHeadersOptions>(o =>
{
    o.ForwardedHeaders = ForwardedHeaders.XForwardedFor
                       | ForwardedHeaders.XForwardedProto
                       | ForwardedHeaders.XForwardedHost;   // ← 既定では無効
    o.KnownNetworks.Clear();
    o.KnownProxies.Clear();
});
var app = builder.Build();
app.UseForwardedHeaders();   // パイプライン最前段
  • 破壊的変更(ASP.NET Core 8.0.17 / 9.0.6 以降のサービシングリリースで導入): ForwardedHeadersMiddleware は、明示的に信頼設定していない(KnownProxies / KnownNetworks 未登録の)プロキシからの X-Forwarded-* を無視します。上記の Clear() で従来動作に戻します。
  • IIS 統合ミドルウェアが自動有効化するのは XForwardedFor / XForwardedProto のみで、XForwardedHost は含まれません。
  • X-Forwarded-Host は直アクセスでは付与されず(=既定ホスト名の直アクセス検知には使えない)、かつクライアントが任意に付与できるためスプーフ可能です。AFD 経由時は AFD が値を上書きします。

要検証: 公式ドキュメントは「App Service が常に X-Forwarded-Host を必ず注入する」とは明記していません(TLS 相互認証のドキュメントで保証されるのは X-ARR-ClientCert / X-Forwarded-For / X-Forwarded-Proto)。直アクセス検知が目的なら、Request.Host / req.hostname の Host 直読みを基本にしてください。

4. 方法B: アクセス制限 + Azure Front Door でオリジンをロックダウン

エンタープライズでは、App Service を Azure Front Door(AFD)の背後に置き、AFD 経由のトラフィックだけを許可する構成が定番です。ここで使うのが App Service のアクセス制限(Access Restrictions)です。なお Front Door は Standard / Premium 前提で解説します(Classic は 2027-03-31 にリタイア予定)。

4.1 アクセス制限でフィルターできる HTTP ヘッダーは 4 つだけ

アクセス制限のルールで判定に使える HTTP ヘッダーは、次の 4 つに限定されています。

ヘッダー 意味 制限
X-Forwarded-For プロキシ経由の元クライアント IP 最大 64 文字
X-Forwarded-Host 元のホスト名 最大 64 文字
X-Azure-FDID Front Door インスタンスの GUID 最大 64 文字
X-FD-HealthProbe AFD ヘルスプローブ識別(値は "1") 最大 64 文字

各ヘッダー名につき値は最大 8 個(カンマ区切りで OR)。1 つのルール内で複数ヘッダーを指定すると AND 条件になります。

4.2 Host ヘッダーで既定ドメインは弾けない

重要な制約として、Host はフィルター対象外です(上記 4 つのみ)。つまり「Hostazurewebsites.net なら拒否」という条件はアクセス制限では直接書けません。

X-Forwarded-Host での代替は、リバースプロキシ(Front Door 等)が前段にいる場合のみ意味を持ちます。理由は次のとおりです。

  1. 直アクセスでは付与されない(クライアントが myapp.azurewebsites.net に直アクセスしても、プラットフォームは X-Forwarded-Host を設定しません)。
  2. スプーフ可能(直リクエストにクライアントが任意で付与すれば通過し得ます)。
  3. AFD 経由時は AFD が値を上書きします。

明示ルールを 1 つでも追加すると、未一致は暗黙 Deny になります(ipSecurityRestrictionsDefaultAction = Allow / Deny)。拒否時の応答は HTTP 403 です。プロキシ無しで既定ドメインだけを弾く手段にはならない点を押さえてください。

4.3 Front Door の 2 層ロック(X-Azure-FDID + サービスタグ)

公式ガイダンスは「Front Door を経由していないトラフィックをオリジンでブロックせよ」です。これを 2 層の AND で実現します。

チェック内容 単独では不十分な理由
サービスタグ AzureFrontDoor.Backend 送信元 IP が AFD egress レンジ内か 全 Azure 顧客が同レンジを共有する
X-Azure-FDID ヘッダー 自分の Front Door プロファイルの GUID か ヘッダー単独はスプーフ可能

両方を AND にすることで「AFD 経由かつ自分の AFD」だけを通します。Front Door ID は Portal → Front Door プロファイル → Overview で確認できます。

az webapp config access-restriction add \
  -g <RG> -n <App> \
  --rule-name "Allow-AFD" --action Allow --priority 100 \
  --service-tag AzureFrontDoor.Backend \
  --http-header x-azure-fdid=<front-door-id-guid>

az resource update -g <RG> -n <App> --resource-type "Microsoft.Web/sites" \
  --set properties.siteConfig.ipSecurityRestrictionsDefaultAction=Deny

# SCM も同一制限にする場合
az webapp config access-restriction set -g <RG> -n <App> --use-same-restrictions-for-scm-site true

CLI フラグ名の注記: 正式名は --http-headers(複数形)ですが、公式例は --http-header(単数形)です。CLI の一意プレフィックス解決により単数形でも同義で動作します。

4.4 さらに強固に:Private Link(Front Door Premium)

Front Door Premium なら、AFD → App Service を Private Link で接続できます(GA)。これにより AFD からオリジンへはプライベート経路で到達できます。

az afd origin create ... \
  --enable-private-link true \
  --private-link-resource <webapp-id> \
  --private-link-sub-resource-type sites
  • 公開アクセスは自動では塞がりません: Private Link を有効化しても、公開アクセスとプライベートアクセスは共存し得ます。既定の *.azurewebsites.net を確実に遮断するには、Private Link 有効化に伴う自動遮断に依存せず、別途 publicNetworkAccess = Disabled を明示設定してください。
  • 実際の挙動は構成(publicNetworkAccess が null / Enabled かなど)によって差があるため、公開前に実機で要検証です。
  • 制約: 同一オリジングループで public / private の混在は不可。スロットは Private Link 非対応です。
  • Private Endpoint の DNS 解決など周辺の論点は ネットワークの質問回答リスト も参照してください。

4.5 Application Gateway は X-Azure-FDID を注入しない

Application Gateway(App GW)は X-Azure-FDID を注入しないため、AFD とは別方式でロックダウンします。

  1. Service Endpoints: App GW サブネットに Microsoft.Web サービスエンドポイントを有効化し、そのサブネットのみ許可する。
  2. Private Endpoint: App Service を Private Endpoint 化し、App GW から到達する(最も強い分離)。
  3. 多段構成(Front Door → App GW → App Service)では、X-Azure-FDID チェックを App GW の WAF カスタムルールで行う。

サービスタグは用途で使い分けます。オリジン向け(アクセス制限に使う)は AzureFrontDoor.Backend、クライアント向けは AzureFrontDoor.Frontend です。

5. 方法C: ネイティブの全体ブロック(all-or-nothing)

SEO が不要な API やコンプラ要件では、プラットフォーム層で公開エンドポイントを止める方法が適します。ただし前述のとおり、これらは既定・カスタムを区別せず全体を止める all-or-nothing の挙動です。

5.1 hostNamesDisabled(全公開ホスト名を無効化)

Microsoft.Web/sitesproperties.hostNamesDisabled(bool、既定 false)です。長年 GA ですが、ポータルの UI トグルはありません。REST 定義には次のようにあります。

"true to disable the public hostnames of the app; otherwise, false. If true, the app is only accessible via API management process."

つまり既定・カスタムを問わず全公開ホスト名が無効になり、目的には不適です。専用の CLI フラグはないため az resource update で設定します。

az resource update -g <RG> -n <App> --resource-type Microsoft.Web/sites \
  --set properties.hostNamesDisabled=true

要検証: 全ホスト名で HTTP 403 / "HostNames Disabled" が返るという報告はコミュニティベースで、公式には応答コードが明記されていません

5.2 publicNetworkAccess = Disabled + Private Endpoint

Portal の App Service → Settings → Networking → Public network access("App access")で Enabled / Disabled を切り替えます。プロパティは properties.publicNetworkAccess(Enabled | Disabled、GA)です。公開エンドポイント全体が無効化され、既定・カスタム両方が公衆からアクセス不可になります。到達は Private Endpoint 経由が前提です。

az resource update -g <RG> -n <App> --resource-type Microsoft.Web/sites \
  --set properties.publicNetworkAccess=Disabled

⚠ Linux アプリでは、この変更でアプリの再起動が発生します(ドキュメント記載)。正確な応答コードは公式に明記されておらず、403 相当とされます(要検証)。

5.3 全ブロック系の副作用(要検証を明示)

全体ブロックは周辺機能に副作用があります。**公式に明記されていない項目は正直に「要検証」**とします。

対象 影響 確度
SCM/Kudu(*.scm.azurewebsites.net)/ ZIP デプロイ 公開ホスト名無効化でデプロイ破綻の可能性大 公式非明記・要検証
デプロイスロット 影響を受ける想定 個別確認要
Easy Auth のリダイレクト URI アプリのホスト名にリダイレクトするため破綻し得る 推定
App Service Managed Certificate 発行/更新 検証経路依存。既定ホスト名依存だと発行不可の恐れ 低確度・要検証
Health check / Front Door・App Gateway オリジン オリジンが無効ホスト名を指すとプローブ/転送が 403 で破綻 破綻する
プラン tier 要件 専用 tier 要件の記載なし(カスタムドメイン自体は Basic 以上が必要) 記載なし

6. SEO の観点:301 リダイレクト vs ハードブロック

公開サイトでは、ブロック(403/404)よりも 301 恒久リダイレクトが望ましいです。判断の分かれ目を整理します。

6.1 301 が推奨される理由(Google Search Central)

Google Search Central は次のように説明しています。

  • 301(恒久) はリダイレクト先が検索結果に表示され、302(一時) は元 URL が残ります。"use a permanent server-side redirect whenever possible"。
  • リダイレクトは最も強い正規化シグナルです。403 / 404 はシグナルを破棄するだけで、評価は引き継がれません。
観点 301 リダイレクト ハードブロック(403 / 404)
SEO シグナル 独自ドメインへ統合される 破棄される
ユーザー体験 独自ドメインへ自動遷移 エラー表示
向くケース 公開マーケサイト・LP・ブログ API・社内システム・コンプラ遮断

6.2 canonical URL と HSTS はカスタムドメイン側に

  • Canonical URL: 公開サイトではカスタムドメイン(https://www.example.com)を canonical にします。シグナルの強い順に ①301 / 308 リダイレクト ②<link rel="canonical"> ③HTTP Link ヘッダー ④sitemap です。
  • HSTS: Strict-Transport-Security はホスト単位です。*.azurewebsites.net は共有マルチテナントドメインのため、preload / HSTS を付けるのは不適切です(他テナントに影響します)。HSTS は自分のカスタムドメインにのみ付与します(例: max-age=31536000; includeSubDomains)。リダイレクト先は必ず https:// にします。
  • App Service の「HTTPS Only」は同一ホスト内の HTTP→HTTPS であり、azurewebsites.net → カスタムドメインのリダイレクトではありません。
  • publicNetworkAccess = DisabledhostNamesDisabled はリダイレクトではなくブロック(403)なので、SEO シグナルは移りません。公開マーケサイトは 301、API / コンプラ要件はハードブロック / 無効化が適切です。

6.3 AFD Rules Engine で 301 とオリジンロックを両立

Front Door 併用時のうまい手として、Rules Engine を使うと SEO と遮断を両立できます。「Hostmyapp.azurewebsites.net の要求を https://www.example.com{path} へ 301」する規則をエッジで返せば、SEO 上正当な 301 と、§4 のオリジンロックダウンを同時に実現できます。

7. 意思決定ガイド(用途別)

自分のケースに当てはめるためのフローと早見表です。

独自ドメインのみに限定する手段を選ぶ意思決定フロー

シナリオ 推奨手段 中核メカニズム 備考
① 単純な公開サイト(LP / ブログ) 既定ホスト名 → カスタムへ 301 リダイレクト(§3 / §4 のアプリ層 or AFD Rules Engine) ミドルウェア or web.config の Redirect Permanent ランキング統合。canonical・HSTS はカスタムドメイン側
② API / バックエンド 既定 Deny のアクセス制限、または publicNetworkAccess = Disabled + Private Endpoint ipSecurityRestrictionsDefaultAction=Deny / publicNetworkAccess=Disabled SEO 不要なので 403 で可
③ Front Door 配下 AzureFrontDoor.Backend サービスタグ + X-Azure-FDID 許可 + 既定 Deny。強化は Premium + Private Link access-restriction add --service-tag ... --http-header x-azure-fdid=... ヘッダー方式なら publicNetworkAccess=Disabled にしない。SEO 併用は AFD Rules Engine で 301
④ コンプラ要件で既定を完全遮断 publicNetworkAccess = Disabled(App access=Disabled)+ Private Endpoint --set properties.publicNetworkAccess=Disabled プラットフォーム層で公衆遮断。Linux は再起動。デプロイは PE / スロット経由に

8. まとめ

  • 既定ホスト名「だけ」を選択無効化するネイティブ機能は 2026 年半ば時点で存在しません。選択的挙動はアプリ層か Front Door トポロジで作ります。
  • 公開サイトは 301 リダイレクト(アプリ層 or AFD Rules Engine)が最適です。SEO シグナルを独自ドメインへ寄せられます。
  • エンタープライズは Front Door + アクセス制限(サービスタグ + X-Azure-FDID + 既定 Deny)。Premium なら Private Link でさらに堅牢にできます。
  • コンプラ遮断は publicNetworkAccess = Disabled + Private Endpoint。ただし副作用(SCM/Kudu・スロット・Easy Auth・証明書)は要検証項目を含むため、事前に実機で確認してください。
  • 本記事の否定的結論と「要検証」項目は、公開前に最新ドキュメントと実機で必ず再確認してください。

参考リンク


この記事の執筆にあたり、AI の支援を受けています。