Web-App benötigt eine benutzerdefinierte Domäne? DNS-Namen zuordnen

Veröffentlicht am:

CloudTrips benötigt eine erkennbare Adresse statt des generierten azurewebsites.net-Hostnamens. Eine benutzerdefinierte Domänenzuordnung weist App Service an, Anfragen für einen eigenen DNS-Namen anzunehmen. DNS muss diesen Namen außerdem zur Web-App leiten.

Dieser Trip ist unabhängig von früheren App-Service-Trips. Erstelle:

Resource group: rg-cloudtrips-customdomain-test-weu
Web app: app-cloudtrips-domain-dmytro-test-weu
App Service plan: asp-cloudtrips-domain-test-weu
Pricing tier: Basic B1
DNS provider for cloudtrips.dev: Vercel
Custom hostname: appservice.cloudtrips.dev

Benutzerdefinierte Domänen benötigen einen kostenpflichtigen App-Service-Tarif. Du musst außerdem die öffentliche DNS-Zone bearbeiten können. Kontrollierst du cloudtrips.dev nicht, verwende im gesamten Trip eine Subdomäne einer eigenen Domäne.

Erstelle die Web-App

Suche nach App Services, wähle Create > Web App und trage ein:

Subscription: CloudTrips TEST
Resource group: rg-cloudtrips-customdomain-test-weu
Name: app-cloudtrips-domain-dmytro-test-weu
Publish: Code
Runtime stack: Node 24 LTS
Operating System: Linux
Region: West Europe
Linux Plan: Create new
Plan name: asp-cloudtrips-domain-test-weu
Pricing plan: Basic B1
Zone redundancy: Disabled

Der Web-App-Name muss global eindeutig sein. Ist er nicht verfügbar, ergänze ein kurzes Suffix und verwende den daraus entstehenden Namen einheitlich im CNAME und in den Befehlen. Wähle Review + create > Create.

Basic B1 ist der kleinste dedizierte Tarif für dieses Labor mit verwaltetem Zertifikat und bleibt bis zur Löschung kostenpflichtig.

Create Web App mit der eigenständigen Node-24-Linux-App im Tarif Basic B1

Stelle die Testseite bereit

Erstelle einen lokalen Ordner mit package.json:

{
  "name": "cloudtrips-custom-domain",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js"
  }
}

Füge server.js hinzu:

const http = require('http');
const port = process.env.PORT || 8080;

http.createServer((request, response) => {
  response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  response.end('<h1>CloudTrips Custom Domain</h1>');
}).listen(port);

Packe die Dateien in diesem Ordner und stelle sie bereit:

zip cloudtrips-domain.zip package.json server.js

az webapp deploy \
  --resource-group rg-cloudtrips-customdomain-test-weu \
  --name app-cloudtrips-domain-dmytro-test-weu \
  --src-path cloudtrips-domain.zip \
  --type zip

Bestätige vor der DNS-Änderung, dass der Standardhostname funktioniert:

curl --fail \
  https://app-cloudtrips-domain-dmytro-test-weu-csf8bpczcqdmfngc.westeurope-01.azurewebsites.net

Azure hat diesen Hostnamen für die App erzeugt. Leite ihn nicht aus dem App-Namen ab: Neuere App-Service-Hostnamen können ein eindeutiges Suffix und eine Regionsbezeichnung enthalten. Kopiere immer Default domain aus Overview oder rufe defaultHostName mit dem folgenden Befehl ab.

Verstehe die beiden DNS-Einträge

Der autoritative DNS-Anbieter ist der Dienst, der die offiziellen öffentlichen DNS-Einträge einer Domäne speichert. DNS-Resolver im Internet fragen diesen Anbieter nach der Antwort. Für cloudtrips.dev ist Vercel DNS der autoritative Anbieter. Erstelle die folgenden Einträge daher in Vercel und nicht in der App-Service-Ressource:

CNAME: Leitet appservice.cloudtrips.dev zur Web-App
TXT:   Beweist Azure, dass du appservice.cloudtrips.dev kontrollierst
Browser fragt appservice.cloudtrips.dev an

DNS fragt Vercel nach dem offiziellen Eintrag

Vercel liefert den Azure-App-Service-Hostnamen

Der TXT-Eintrag transportiert keinen Anwendungsverkehr. Er verhindert, dass ein anderer Azure-Kunde deinen Hostnamen allein durch dessen Kenntnis beansprucht.

Beginne die Domänenzuordnung

Öffne app-cloudtrips-domain-dmytro-test-weu, wähle Settings > Custom domains und anschließend Add custom domain:

Domain provider: All other domain services
TLS/SSL certificate: Add certificate later
Domain: appservice.cloudtrips.dev

Wähle noch nicht Validate. Lasse den Bereich geöffnet und beachte die erwarteten DNS-Einträge. Die Zuordnung des Hostnamens vor der Zertifikatserstellung trennt DNS-Validierung und Zertifikatsausstellung und erleichtert die Fehlersuche.

Bereich Add custom domain für appservice.cloudtrips.dev mit Add certificate later

Erstelle die Einträge in Vercel DNS

Rufe App-Hostname und eindeutigen Besitzprüfungswert ab:

az webapp show \
  --resource-group rg-cloudtrips-customdomain-test-weu \
  --name app-cloudtrips-domain-dmytro-test-weu \
  --query "{cname:defaultHostName,verificationId:customDomainVerificationId}" \
  --output yaml

Öffne das Vercel-Team, das cloudtrips.dev verwaltet, öffne die DNS-Einträge der Domäne und erstelle:

Type: CNAME
Name: appservice
Value: app-cloudtrips-domain-dmytro-test-weu-csf8bpczcqdmfngc.westeurope-01.azurewebsites.net
TTL: Provider default

Type: TXT
Name: asuid.appservice
Value: Den von Azure zurückgegebenen customDomainVerificationId verwenden
TTL: Provider default

Kopiere die Prüf-ID exakt ohne Anführungszeichen oder Leerzeichen. Verwende den von Azure zurückgegebenen defaultHostName als CNAME-Wert und ersetze ihn nicht durch einen kürzeren, aus dem App-Namen abgeleiteten Hostnamen. Der CNAME muss direkt auf den azurewebsites.net-Hostnamen der App zeigen, damit Ausstellung und Erneuerung des verwalteten Zertifikats funktionieren.

Vercel DNS mit dem CNAME appservice und dem TXT-Eintrag asuid.appservice

Prüfe die öffentlichen Einträge auf deinem Mac:

dig appservice.cloudtrips.dev CNAME +short
dig asuid.appservice.cloudtrips.dev TXT +short

Der erste Befehl sollte den Web-App-Hostnamen liefern, der zweite die Azure-Prüf-ID. DNS-Verteilung kann mehrere Minuten dauern.

Validiere und füge die Domäne hinzu

Kehre zu Add custom domain zurück und wähle Validate. Fahre erst fort, wenn Azure grüne Häkchen für die benötigten Einträge zeigt, und wähle dann Add.

Der Hostname sollte nun unter Custom domains mit No binding erscheinen. Das ist erwartet: DNS und Besitzprüfung funktionieren, aber HTTPS besitzt noch kein Zertifikat.

App Service Custom domains zeigt appservice.cloudtrips.dev zugeordnet und ohne TLS-Bindung

Erlaube DigiCert per CAA

Prüfe vor der Zertifikatsanforderung, ob die übergeordnete Domäne bereits CAA-Einträge besitzt:

dig cloudtrips.dev CAA +short

CAA bedeutet Certification Authority Authorization. Diese DNS-Einträge beschränken, welche Zertifizierungsstellen Zertifikate für die Domäne ausstellen dürfen. Existieren keine CAA-Einträge, gilt keine Aussteller-Positivliste. Existiert mindestens einer, muss die von App Service verwendete Zertifizierungsstelle ausdrücklich erlaubt sein.

cloudtrips.dev erlaubte bereits Let’s Encrypt, Google Trust Services und Sectigo, jedoch nicht DigiCert. App Service Managed Certificates verwenden DigiCert. Ergänze deshalb in Vercel DNS diesen Eintrag:

Name: @
Type: CAA
Value: 0 issue "digicert.com"
TTL: 60
Priority: Leer lassen

Behalte die vorhandenen CAA-Einträge. Dabei ist 0 das CAA-Flag, issue erlaubt einer Zertifizierungsstelle die Ausstellung gewöhnlicher Zertifikate und digicert.com ist die autorisierte Stelle. Fehlt diese DigiCert-Erlaubnis, kann Azure beim Erstellen des verwalteten Zertifikats einen irreführenden ResourceNotFound-Fehler anzeigen.

Vercel DNS mit dem CAA-Eintrag, der DigiCert für cloudtrips.dev erlaubt

Warte auf die DNS-Verteilung und bestätige, dass die öffentliche Antwort DigiCert enthält:

dig cloudtrips.dev CAA +short

Erstelle das verwaltete Zertifikat

Öffne Settings > Certificates. Wähle unter Managed certificates Add certificate:

Custom domain: appservice.cloudtrips.dev

Wähle Validate und anschließend Add. Die Domänenzuordnung muss bestehen, bevor App Service dieses Zertifikat ausstellen kann. Das App Service Managed Certificate ist kostenlos, wird automatisch erneuert, solange seine Anforderungen erfüllt bleiben, und kann nicht außerhalb von App Service exportiert werden.

Die Ausstellung erfolgt asynchron und kann mehrere Minuten dauern. Warte, bis das Zertifikat unter Managed certificates erscheint, bevor du die Bindung erstellst. Bleibt die kombinierte Zertifikats- und Bindungsaktion beschäftigt, sende sie nicht wiederholt ab. Aktualisiere die Zertifikatsseite und prüfe das Activity Log.

Managed certificates mit dem ausgestellten Zertifikat für appservice.cloudtrips.dev

Füge die SNI-SSL-Bindung hinzu

Kehre zu Custom domains zurück. Wähle neben appservice.cloudtrips.dev Add binding:

Certificate: Verwaltetes Zertifikat für appservice.cloudtrips.dev auswählen
TLS/SSL type: SNI SSL

SNI bedeutet Server Name Indication. Beim TLS-Verbindungsaufbau sendet der Browser den angeforderten Hostnamen, damit App Service das richtige Zertifikat präsentieren kann. Moderne Clients unterstützen SNI.

SNI SSL:      Client sendet Hostnamen; mehrere HTTPS-Sites teilen eine IP
IP-based SSL: Hostname erhält eine dedizierte eingehende IP-Adresse

IP-basiertes SSL ist hauptsächlich für alte Clients ohne SNI-Unterstützung oder Workloads mit Bedarf an einer dedizierten IP gedacht. Es kann mehr kosten und benötigt mindestens Standard, während diese B1-App SNI SSL unterstützt. Wähle Add und warte, bis die Domäne Secured anzeigt.

Custom domains zeigt appservice.cloudtrips.dev mit einer SNI-SSL-Bindung als Secured

Prüfe HTTPS

Rufe die Anwendung über ihren benutzerdefinierten Namen auf:

curl --fail --show-error \
  https://appservice.cloudtrips.dev

Die erwartete Ausgabe enthält:

CloudTrips Custom Domain

Prüfe das für den Hostnamen präsentierte Zertifikat:

openssl s_client \
  -connect appservice.cloudtrips.dev:443 \
  -servername appservice.cloudtrips.dev \
  </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

Verwende nicht curl -k; dies deaktiviert genau die Zertifikatsprüfung, die der Test nachweisen soll.

Browser mit der CloudTrips-Web-App über HTTPS unter appservice.cloudtrips.dev

Räume sicher auf

Lösche zuerst den CNAME appservice und den TXT-Eintrag asuid.appservice in Vercel. Das Entfernen von DNS vor der Azure-App verhindert einen verwaisten CNAME und damit ein mögliches Subdomain-Takeover-Risiko.

Lösche anschließend die isolierte Azure-Ressourcengruppe, um B1-Gebühren zu beenden:

az group delete --name rg-cloudtrips-customdomain-test-weu --yes

Bestätige die Bereinigung:

az group exists --name rg-cloudtrips-customdomain-test-weu
dig appservice.cloudtrips.dev CNAME +short

Der erste Befehl sollte false liefern; nach Ablauf der DNS-Caches sollte der zweite keinen CNAME mehr zurückgeben.