Networking
Azure Bastion : diagnostiquer une connexion native avant d'ouvrir RDP ou SSH
Un runbook de production pour séparer client local, SKU, tunneling, RBAC, NSG et service invité quand une connexion native Azure Bastion échoue.
Une connexion az network bastion ssh, rdp ou tunnel échoue vers une VM privée. La VM répond aux probes applicatives et aucune panne générale Azure n’est visible. Le correctif rapide consiste alors à lui ajouter une IP publique ou à autoriser 22 et 3389 depuis Internet.
Ce contournement change le modèle d’exposition sans prouver la panne. Le refus peut se produire sur le poste opérateur, dans le plan de contrôle Azure, sur le sous-réseau AzureBastionSubnet, entre Bastion et la VM, ou dans le système invité. Le cas fil rouge est un accès d’administration utilisé pendant un incident. L’objectif est de rétablir un chemin privé borné, puis de décider entre correction, maintien du portail comme solution temporaire ou rollback du dernier changement réseau.
Figer une tentative représentative
Conservez une tentative avant de modifier les règles. Relevez l’heure UTC, l’identité Azure, l’abonnement, le nom du Bastion, l’ID de la VM, le mode de connexion, le port cible et le message exact. Ne conservez ni clé privée ni mot de passe dans le ticket.
incident:
detected_utc: 2026-10-07T15:20:00Z
operator: <entra-object-id>
subscription: <subscription-id>
bastion: bas-hub-prod
target: /subscriptions/<id>/resourceGroups/rg-app-prod/providers/Microsoft.Compute/virtualMachines/vm-api-01
mode: tunnel
target_port: 22
local_port: 22022
symptom: tunnel creation fails before SSH handshake
last_changes:
- AzureBastionSubnet NSG update
- target subnet deny rule
- Bastion SKU or configuration update
- operator role assignment change
containment:
public_ip_on_target: forbidden
internet_ssh_rdp_rule: forbidden
approved_fallback: portal_session_only La position de l’erreur réduit immédiatement le champ. Si la commande ne crée pas de tunnel, vérifiez client, contexte Azure, RBAC et configuration Bastion. Si le port local s’ouvre mais que SSH ou RDP échoue, concentrez-vous sur le chemin Bastion-vers-VM, le port réellement écouté et l’authentification invitée.
Comparer portail et client natif
Testez le même compte, la même ressource Bastion, la même VM et le même port dans le portail puis avec le client natif. Ne changez qu’une variable à la fois.
Portail OK, client natif KO
Vérifier Azure CLI, extension Bastion, SKU, native client support et chemin HTTPS local
Portail KO, client natif KO
Vérifier état Bastion, NSG AzureBastionSubnet, NSG cible, service invité et port
Tunnel créé, handshake SSH/RDP KO
Vérifier NSG cible, route retour, sshd/TermService, port personnalisé et authentification
Une VM KO, autres VMs OK
Priorité au subnet/NIC NSG, OS invité, identité et configuration de la VM cible
Toutes les VMs KO après un changement
Priorité à AzureBastionSubnet, SKU/configuration, policy, route ou dépendance partagée Cette matrice évite de conclure qu’un Bastion sain garantit un service invité sain. Elle évite aussi de modifier la VM quand le client natif n’est simplement pas activé.
Prouver SKU, tunneling et état du Bastion
Les connexions par client natif exigent un SKU Standard ou supérieur et le support correspondant activé. Lisez l’état réellement déployé, pas seulement le template attendu.
RG="rg-connectivity-prod"
BASTION="bas-hub-prod"
az network bastion show \
--resource-group "$RG" \
--name "$BASTION" \
--query '{id:id,sku:sku.name,provisioningState:provisioningState,enableTunneling:enableTunneling,subnet:ipConfigurations[0].subnet.id}' \
--output jsonc
az version --output json Arrêtez la correction si provisioningState n’est pas Succeeded. Un changement encore en cours ou en échec doit d’abord être qualifié. Si le portail fonctionne mais que enableTunneling est faux, corrigez cette capacité de façon contrôlée ; n’élargissez pas le NSG de la VM.
Vérifiez ensuite le contexte du poste : tenant, abonnement sélectionné, version Azure CLI et extension Bastion. Une session authentifiée sur le mauvais tenant peut produire un échec qui ressemble à une indisponibilité réseau.
Vérifier les droits au bon scope
Le client doit pouvoir lire le Bastion, la VM et sa carte réseau. Une authentification Microsoft Entra dans la VM ajoute les rôles de connexion adaptés, mais ne remplace pas les droits de lecture nécessaires au montage du chemin.
OPERATOR_OBJECT_ID="<entra-object-id>"
BASTION_ID=$(az network bastion show -g "$RG" -n "$BASTION" --query id -o tsv)
VM_ID="<vm-resource-id>"
az account show --query '{tenant:tenantId,subscription:id,user:user.name}' -o jsonc
az role assignment list \
--assignee "$OPERATOR_OBJECT_ID" \
--all \
--query "[?scope=='$BASTION_ID' || scope=='$VM_ID'].{role:roleDefinitionName,scope:scope}" \
--output table Complétez l’inventaire avec les droits hérités et le scope de la NIC. Si une attribution vient d’être modifiée, consignez son heure et retestez après propagation avec une nouvelle session. N’accordez pas Owner pour transformer un diagnostic RBAC en accès permanent surdimensionné.
Lire les deux plans NSG séparément
Un NSG sur AzureBastionSubnet doit conserver l’ensemble des flux requis par le service : HTTPS et gestion en entrée, communication interne sur 8080/5701, sorties vers les VMs sur 22/3389 ou le port personnalisé autorisé, ainsi que les dépendances Azure documentées. Une règle manquante peut casser les sessions même si le portail affiche encore la ressource.
Le NSG du subnet ou de la NIC cible répond à une autre question : autorise-t-il le port d’administration depuis le sous-réseau Bastion ? N’ouvrez pas la source Internet et ne remplacez pas une règle ciblée par VirtualNetwork sans analyser ce que ce service tag couvre dans la topologie réelle.
BASTION_NSG="nsg-azure-bastion-prod"
TARGET_NIC="nic-vm-api-01"
TARGET_RG="rg-app-prod"
az network nsg rule list \
--resource-group "$RG" \
--nsg-name "$BASTION_NSG" \
--include-default \
--query "sort_by([].{priority:priority,name:name,direction:direction,access:access,source:sourceAddressPrefix,destination:destinationAddressPrefix,ports:destinationPortRanges}, &priority)" \
--output table
az network nic list-effective-nsg \
--resource-group "$TARGET_RG" \
--name "$TARGET_NIC" \
--output json
az network nic show-effective-route-table \
--resource-group "$TARGET_RG" \
--name "$TARGET_NIC" \
--output table Les règles effectives de la NIC réunissent les contrôles du subnet et de la NIC. Cherchez la priorité réellement gagnante pour la source Bastion, la destination privée et le port exact. Lisez également les routes si le subnet cible force un next hop : une session peut atteindre la VM puis perdre son retour dans une appliance qui ne connaît pas le flux.
Confirmer le service invité sans contourner Bastion
Si le tunnel local est créé, testez le port par ce tunnel. Un échec à ce stade ne justifie pas une IP publique : il faut prouver que le service écoute et que le pare-feu invité accepte la connexion.
az network bastion tunnel \
--resource-group "$RG" \
--name "$BASTION" \
--target-resource-id "$VM_ID" \
--resource-port 22 \
--port 22022
# Dans un second terminal, sans exposer la VM publiquement.
ssh -vv -p 22022 <user>@127.0.0.1 Sur Linux, vérifiez sshd, le port d’écoute et le pare-feu local depuis la console série ou une automatisation approuvée. Sur Windows, contrôlez TermService, le listener RDP et Windows Firewall. Séparez enfin transport et authentification : un handshake atteint l’OS ; une clé refusée, un droit de connexion absent ou une policy Entra se traite après le réseau.
Canaryer la plus petite correction
Corrigez une seule couche et rejouez une matrice minimale : une VM Linux ou Windows cible, un port attendu, une identité autorisée et un contrôle négatif. Le contrôle négatif peut être une seconde VM ou un port qui doit rester interdit.
Autoriser la reprise
Bastion est Succeeded avec SKU et tunneling attendus
Les règles requises d'AzureBastionSubnet sont complètes
La règle cible autorise uniquement la source et le port nécessaires
Le tunnel s'ouvre puis le protocole atteint le service invité
Une identité ou une cible non autorisée reste refusée
Aucune IP publique ni règle Internet 22/3389 n'a été ajoutée
Maintenir le fallback portail
Le client local ou son chemin HTTPS reste non qualifié
Les droits effectifs ne sont pas encore prouvés
Le changement réseau partagé aurait un rayon d'impact trop large
Rollback
Restaurer la version précédente du NSG, de la route ou de la configuration Bastion
Fermer le changement canari si le contrôle négatif devient accessible
Révoquer tout rôle temporaire et conserver les preuves avant/après Conclusion
Une panne de client natif Azure Bastion ne doit pas transformer une VM privée en endpoint public. Le diagnostic utile localise le refus entre poste opérateur, plan de contrôle, configuration Bastion, AzureBastionSubnet, chemin réseau cible et système invité.
La décision devient alors réversible : corriger le tunneling, le scope RBAC, une règle NSG précise, une route ou le service invité ; garder temporairement le portail si le chemin natif reste ambigu ; ou rollbacker le dernier changement partagé. La reprise n’est validée qu’après un canari positif, un refus attendu et la confirmation qu’aucun accès direct Internet n’a été créé.