Perte de connectivité réseau sur machines virtuelles

J'ai été confronté à un problème de manière aléatoire sur quelques machines virtuelles d'un cluster vSphere. Ce problème se traduisait par une perte de connectivité réseau : les machines virtuelles étaient incapables de joindre leur gateway et de communiquer avec d'autres machines du même VLAN. Une manière temporaire de rétablir la connectivité réseau était de réaliser un vMotion sur la machine virtuelle afin de la déplacer sur un autre hôte.

De nombreuses manipulations ont été tentées sur ces machines pour tenter de garder une connectivité durable : changement de type de carte réseau, création de nouvelle machine avec rattachement des disques virtuels, changement d'adresse MAC, etc. mais sans succès.

Les 2 hôtes vSphere formant le cluster ont chacun 4 interfaces physiques : 2 pour les machines virtuelles, une pour le management network et la dernière pour le vMotion. Sur ces deux dernières interfaces, seul un VLAN était déclaré côté switch physique.

En regardant du côté des vSwitch positionnés sur chaque hôte, il apparaissait qu'en fait les VLAN déclarés sur vSphere étaient poussés sur toutes les interfaces physiques (vmnic) du serveur. Cette configuration pouvait donc faire qu'une machine située sur le VLAN "PROD_CLIENT" tentait de communiquer sur les 2 interfaces qui n'avaient pas ce VLAN de déclaré côté switch physique.

Explications : considérons un serveur avec 4 interfaces (vmnic0 à vmnic3) branchées sur les ports 1, 2, 3 et 4 d'un switch. Les ports 1 et 2 (branchés sur vmnic0 et vmnic1) donnent accès au VLAN "ADMIN" tandis que les ports 3 et 4 (branchés sur vmnic2 et vmnic3) donnent accès aux VLAN "PROD_CLIENT", "PROD_INTERNE", "RE7_CLI", "RE7_INT". Côté vSphere, ces VLAN sont visibles et peuplés ; seulement ils doivent être configurés sur les bonnes interfaces. Si le VLAN "PROD_CLIENT" était accessible sur vmnic2 et vmnic3 puisqu'il est disponible sur les ports 3 et 4 du switch, il ne l'était pas sur les ports 1 (vmnic0) ni 2 (vmnic1). Or, ce VLAN était configuré sur ESXi pour utiliser les 4 interfaces physiques.

Sur cette capture, le VLAN est configuré pour être accessible sur tous les vmnic ; cependant côté switch physique cela n'est pas le cas puisque le VLAN est configuré sur les seuls ports 3 et 4 (vmnic2 et vmnic3).

Étant donné que ce VLAN utilisait des interfaces sur lesquelles il était injoignable côté switch physique, lorsque vSphere faisait passer le trafic réseau de la VM sur ces interfaces les machines devenaient de ce fait inaccessibles et incapables de joindre leur passerelle. Un redémarrage complet de la machine virtuelle (et non pas uniquement l'OS invité) pouvait résoudre le souci temporairement puisque vSphere réinscrit la carte réseau virtuelle sur une des interfaces sur lesquelles le VLAN en question était accessible (dans notre exemple, vmnic2 ou vmnic3). La même action de réinscription se faisait dans le cadre d'un déplacement d'hôte, puisque la VM passait sur un autre hôte physique, avec d'autres cartes physiques ; cependant le dysfonctionnement persistait puisque l'autre hôte du cluster était configuré de la même manière.

Afin de résoudre le dysfonctionnement, il a donc fallu déplacer les vmnic0 et vmnic1 dans les adaptateurs inutilisés pour les VLAN "PROD_CLIENT", "PROD_INTERNE", "RE7_CLI" et "RE7_INT". Ainsi, le trafic des VM configurées sur ces réseaux passent désormais uniquement via vmnic2 et vmnic3 et le problème est résolu.

Sur cette capture, les VLAN sont bien configurés pour n'utiliser que les vmnic qui sont interfacés sur les ports du switch physique donnant accès aux VLAN en question.

Restriction du Windows Update Delivery Optimization par groupe ActiveDirectory

Le WUDO ou Windows Update Delivery Optimization est un composant Windows présent sous Windows 10 qui permet d'optimiser la bande passante réseau consommée lors de la distribution de mises à jour système via WSUS par exemple. En imaginant un réseau d'une dizaine de stations, une seule d'entre elles pourrait utiliser le WAN pour récupérer les mises à jour depuis un serveur WSUS situé en central et les autres utilisent le LAN pour les télécharger à partir de celle les ayant obtenues via le WAN afin d'éviter une saturation de ce dernier. Ce qui peut être un gain de bande passante peut avoir des effets de bord notables ; c'est pourquoi il est possible de contrôler finement le comportement du WUDO via GPO. Un moyen de mieux centrer son action est de passer par la création de groupes ActiveDirectory pour regrouper des stations ; c'est ce que je vais présenter dans cet article.

La problématique est la suivante : des stations du site fictif de Paris utilisent le WAN pour télécharger des mises à jour WSUS sur des stations à Londres. Afin d'éviter de saturer ce lien, on souhaite donc limiter le WUDO à récupérer des données depuis des stations d'un même site uniquement.

Voici la composition de cette maquette de test :

  • OU computers, comprenant 3 OU paris, bxl et london, comprenant les stations propres à chaque site.
  • OU wudo-grp, qui contiendra les groupes AD wudo_paris, wudo_bxl et wudo_ldn dans lesquels seront placées les stations de chaque site.

Il est nécessaire de créer une GPO par groupe AD, d'où l'importance de bien définir ses besoins et surtout, l'organisation qui va être adoptée pour bien séparer les flux de communication WUDO. Une séparation trop granulaire demandera beaucoup de travail d'administration et l'inverse n'aura probablement aucun effet de correction des effets de bord ! Cette GPO va prendre en paramètre unique le GUID du groupe, il faut donc le récupérer et surtout, le stocker quelque part pour toujours avoir une association facile entre GUID et GPO associée.

En Powershell, l'instruction suivante nous permettra de récupérer le GUID du groupe.

(Get-AdGroup wudo_paris).ObjectGuid.Guid

Bien entendu, une boucle foreach dans un script récupérant tous les groupes d'une OU permettra de tous les obtenir facilement.

Désormais, il faut s'occuper de la création des GPO. Les réglages qui nous intéressent sont dans Computer Configuration > Policies > Administrative Templates > Windows Components > Delivery Optimization.

La première option est le Download Mode, qu'il faut passer à 2. La description du paramètre explique bien les différentes options possibles. Il est important de noter que ce qui est désigné comme "LAN" ici n'est pas un LAN au sens physique du terme mais un réseau interne ActiveDirectory. Par exemple, si votre domaine s'appelle schmitouille.net, alors le LAN englobera toutes les stations dans schmitouille.net. Si vous avez des sous-domaines, alors le LAN considèrera les stations du sous-domaine, par exemple fr.schmitouille.net.

Ensuite, l'autre paramètre est Group ID. C'est ici que devra être renseigné le GUID du groupe correspondant. Ici, je vais placer le GUID du groupe wudo_bxl car c'est la GPO qui va régir le WUDO des stations du site fictif de Bruxelles.

Il ne me reste plus qu'à lier cette GPO sur l'OU contenant les stations, et non celle contenant les groupes. Toujours en restant dans le cadre du site de Bruxelles :

... et à répéter l'opération autant de fois que nécessaire. En fonction de l'architecture de l'ActiveDirectory, il peut être nécessaire d'appliquer un Security Filtering sur le groupe d'ordinateurs concerné afin d'être sûr que la GPO ne s'applique que sur les stations désirées.

Afin de faire en sorte que les paramètres soient pris en compte le plus rapidement possible, il est possible de forcer un gpupdate à distance via Powershell. Voici un snippet que j'ai réalisé permettant de passer sur toutes les stations désormais régies par ces politiques de groupe pour mettre à jour ces dernières (à noter qu'en fonction de la disponibilité des stations, des paramètres firewall ou des droits du compte l'exécutant, il peut y avoir des erreurs) :

$grouplist = Get-ADGroup -Filter 'Name -like "wudo_*"'
foreach ($group in $grouplist){
    $complist = Get-AdGroupMember $group
    foreach ($comp in $complist){
        Write-Host "Processing:"$comp.Name
        Invoke-GPUpdate -Computer $comp.Name -RandomDelayInMinutes 0
    }
}

Enfin, pour vérifier que la GPO est bien redescendue, il est possible d'utiliser la fonctionnalité Group Policy Result et d'avoir un rapport indiquant si oui ou non la GPO a bien été appliquée. Si oui, le WUDO de la station concernée ne pourra donc interroger que les membres du groupe AD dont le GUID correspond à la GPO appliquée.

Installation des drivers réseau pour une VM Windows Server 2016 sur hôte Proxmox VE 5

Voici ce qui m'est arrivé à la fin de l'installation d'un contrôleur de domaine de test sous 2016 en mode Core sur mon hyperviseur fonctionnant sous Proxmox VE 5. En cause, l'absence de drivers pour la carte réseau qui est de type virtIO.

sconfig m'indique bien que je n'ai pas de carte réseau active.

Il est donc nécessaire d'installer ces drivers. Le site de documentation de la distribution Fedora explique rapidement ce que sont ces drivers virtIO et pourquoi il est nécessaire de les installer à part. Dans le cas présent, l'installation va être très facile. Il suffit de télécharger l'ISO (dernière version stable ou le canal "développement"), la monter sur la VM et ensuite d'installer le pilote correspondant.

Il y a pléthore de pilotes sur cet ISO, celui qui nous intéresse est dans NetKVM\2k16\amd64. En partant du principe que l'ISO est monté sur le lecteur D:, cela nous donne ceci dans l'invite de commandes :

d:
cd NetKVM\2k16\amd64

Bien évidemment, on remplacera 2k16 par la version de Windows concernée. Il y a de multiples fichiers dans le répertoire, mais le pilote s'installe à partir du fichier inf. Il reste à appeler pnputil pour installer le driver :

pnputil -i -a netkvm.inf

Quelques secondes plus tard :

Comme indiqué dans la documentation de Fedora, le pilote n'est pas signé par Microsoft - qu'importe.

L'instruction se termine, il suffit alors d'appeler de nouveau sconfig et de se rendre dans les propriétés de la carte réseau pour voir qu'elle est désormais visible et configurable !

Quelques billes pour automatiser la préparation d'un serveur en Powershell

Je déploie régulièrement des VM à partir d'un template, seulement il reste pas mal d'opérations à faire à la main, comme le changement de nom, la configuration du réseau, l'installation de certaines applications et paramètres qui redescendent pas forcément par GPO.

Je vais donc présenter plusieurs instructions et snippets Powershell qui pourront fournir une bonne base pour la création d'un script complet pouvant être intégré dans un template et exécuté directement après le déploiement.

Tout d'abord, le changement du nom du serveur. On peut faire quelque chose de sympa comme ceci :

$hostname = $env:computername
Write-Host "Current Server name: $hostname"
$newhostname = Read-Host "New hostname"
Rename-Computer -NewName $newhostname
Write-Host "A reboot is required and will be performed in approx. 10 seconds. The script will automatically start after reboot to continue post-deployment operations."
shutdown -r -t 10

On affiche le nom actuel du serveur, puis un prompt permettant de saisir le nouveau nom de machine. Un reboot permettra de prendre en compte le changement.

Après le redémarrage, on peut passer à la configuration de la carte réseau. En fonction de la configuration de la machine, cela peut être délicat puisqu'il faut être sûr d'affecter l'IP à la bonne carte réseau ; pour cela, on va donc récupérer toutes les cartes réseaux branchées sur le système, puis faire un filtre par nom et qui fonctionnent en IPv4. Par exemple, si la carte réseau s'appelle Ethernet0 :

$ipv4 = Read-Host "IPV4 address"
$gateway = Read-Host "Gateway"
$dnsprim = Read-Host "Primary DNS"
$dnssec = Read-Host "Secondary DNS"

$networkcards = Get-NetIPInterface | Where-Object {$_.InterfaceAlias -eq "Ethernet0" -and $_.AddressFamily -eq "IPv4"}
$interfaceindex = $networkcards[0].ifIndex
New-NetIPAddress -InterfaceIndex $interfaceindex -IPAddress $ipv4 -PrefixLength 24 -DefaultGateway $gateway
Set-DnsClientServerAddress -InterfaceIndex $interfaceindex -ServerAddresses ($dnsprim,$dnssec)

Get-NetIPInterface avec son pipe nous permet de rechercher les interfaces ayant pour nom Ethernet0 et configurées en IPv4. On récupère donc la carte qui est retournée par l'instruction et son index (qui n'est naturellement pas 1, ce serait trop facile !), qui nous permet ensuite de pouvoir le passer en paramètre de l'instruction New-NetIPAddress qui va se charger de coller la configuration IP à la carte. Le masque de sous réseau ne s'exprime pas en 255.255.255.0 mais notation CIDR, soit 24. Des tables de conversion sont facilement accessibles grâce à n'importe quel moteur de recherche, vous pouvez utiliser celle-ci. Si l'instruction est bien passée, elle retournera alors plusieurs informations quant à l'interface.

Ensuite, maintenant que le réseau est configuré, on peut joindre la machine au domaine.



Add-Computer -DomainName "super-domaine.local"
if ($?){ Write-Host "A reboot is required and will be performed in approx. 10 seconds. The script will automatically start after reboot to continue post-deployment operations."
shutdown -r -t 10 }

Un prompt devrait apparaître pour demander un identifiant et un mot de passe d'un compte autorisé à ajouter des machines au domaine. Si la jonction se fait bien, alors le code dans la boucle if est exécuté et la machine redémarre après environ 10 secondes.

La machine mise sur le domaine, les divers paramètres poussés par GPO devraient redescendre (il faut bien évidemment pas oublier de déplacer l'objet Ordinateur qui s'est créé dans l'AD dans la bonne OU, sinon ça risque de ne pas bien marcher 😱). Cependant, d'autres opérations ou paramètres peuvent être modifiés par Powershell ; en voici quelques-uns.

Autorisation de l'exécution de scripts Powershell sans restriction :

Write-Host "Setting Powershell execution policy to Unrestricted..."
Set-ExecutionPolicy Unrestricted

Désactivation du pare-feu pour le domaine :

Set-NetFirewallProfile -Profile Domain -Enabled False 

Si on souhaite tout automatiser et placer dans un même script, il faut prévoir la phase de reboot suite au changement de nom de la machine et la jonction au domaine (bien que la commande Add-Computer tolère un renommage de la station dans l'instruction). Pour n'utiliser qu'un seul script, et faire en sorte qu'il reprenne exactement là où il s'était arrêté, on peut placer chaque étape dans une fonction, et placer en paramètre facultatif le numéro de l'étape sur laquelle le script démarre ; ensuite une tâche planifiée démarre le script à l'ouverture de session de l'administrateur local.

Déclaration du paramètre :

Param
([string]$step)

Ensuite, une fonction pour créer la tâche, qui elle-même va prendre un paramètre :

function createtask{
param($rebootstep)
$TaskDetails = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType ServiceAccount -RunLevel Highest
$TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "C:\post-deployment.ps1 -s $rebootstep"
$TaskSched = New-ScheduledTaskTrigger -AtLogOn
$TaskName = "PostDeployReboot"
Register-ScheduledTask -Action $TaskAction -Principal $TaskDetails -Trigger $TaskSched -TaskName $TaskName
}

Et on appelle cette fonction après le renommage de la machine par exemple :

Rename-Computer -NewName $newhostname
createtask(2)

Ainsi, au début du script, on peut placer cette instruction qui appellera la fonction setnetwork dans laquelle le code pour paramétrer la carte réseau sera placé :

if ($step -eq "2") { setnetwork }

La tâche planifiée exécutant le script avec le paramètre -s 2, le script démarrera directement sur cette étape.