Access Denied en chaîne sur un FTP porté par IIS

J'ai mis en place un serveur FTP porté par un serveur IIS installé sur un Windows Server 2016. Ce serveur FTP autorise un compte de service sans droits particuliers à écrire sur un répertoire virtuel configuré dans IIS.

Ce compte de service est bien renseigné pour avoir les droits sur le répertoire dans lequel il est censé écrire, et ses droits Read, Write sont bien portés à la fois sur la racine FTP ftproot et sur le répertoire virtuel. Cependant, à la connexion et ce peu importe le client FTP, j'obtenais un simple Access Denied après la transaction d'authentification et l'acceptation du certificat SSL. Après avoir essayé avec mon compte d'administration ayant exactement les mêmes privilèges sur la machine, cela fonctionnait. Le problème est donc lié au compte en lui-même.

Un petit tour dans le fichier de configuration de IIS disponible dans C:\Windows\System32\inetsrv\config\applicationHost.config (comme expliqué dans cet article) me donne rien de plus : les balises sont bien renseignées et le compte en question a bien les droits de connexion.


J'essaye alors d'ajouter le compte en tant qu'administrateur local pour voir si cela fait la différence, et c'est alors qu'un détail me saute aux yeux : dans la fenêtre du groupe des administrateurs locaux, le compte apparaît avec son appellation pré-Windows 2000. Sur cet exemple, le compte testcomptedeserviceftp@mondomaine.com est renseigné avec son nom pré-Windows 2000 MONDOMAINE\testcomptedeservicef :


On peut vérifier dans l'ActiveDirectory les deux noms de connexion :

La console ActiveDirectory Users and Computers permet de vérifier les deux logins d'un utilisateur.

Dans IIS, en remplaçant le nom de connexion usuel par le nom pré-Windows 2000, j'ai pu me connecter.

Il est donc nécessaire d'attribuer les privilèges en utilisant les noms pré-Windows 2000.

En effet, si le nom de mon compte d'administration n'était pas tronqué car identique qu'il soit pré-Windows 2000 ou non, ce n'était pas le cas pour mon compte de service (identifiant trop long). Je tentais donc de me connecter avec un compte inconnu de IIS ; j'ai donc appris aujourd'hui que ce dernier gère les privilèges FTP avec les noms de connexion pré-Windows 2000, ce qui m'a pris une petite heure à réaliser.

550 Cannot create a file when that file already exists sur un FTP porté par IIS

J'ai rencontré une erreur 550 ce jour en tentant d'accéder à un répertoire situé à la racine d'un serveur FTP porté par IIS sur 2008 R2 (IIS 7).

Après vérifications dans le IIS Manager, je n'ai rien trouvé de particulier au niveau des autorisations, le compte que j'utilisais avait bien les droits en lecture et en écriture ; les autorisations NTFS sur le répertoire physique étaient également valides. De plus, ce répertoire n'est qu'une variante de deux autres répertoires identiques, créés en même temps, gérés par les mêmes comptes et accédés par les mêmes applications. Il n'y a donc aucune raison d'avoir une différence de configuration.

J'ai donc été vérifier le fichier de configuration des sites IIS dans C:\Windows\System32\inetsrv\config\applicationHost.config. A la toute fin de ce fichier, la première entrée concerne la racine du FTP, la deuxième concerne spécifiquement le répertoire auquel je n'ai pas accès.

En supprimant cette seconde balise <location> et en redémarrant mon site FTP, tout est revenu dans l'ordre.

Il n'y avait aucune raison d'avoir cette balise pour un seul des 3 répertoires ; par ailleurs ajouter une balise <add accessType="Allow" users="MonUser" permissions="Read, Write" /> n'avait rien changé.

Powershell : recyclage de pool WSUS à distance

J'avais déjà abordé la question de la consommation de RAM de WSUS à travers son pool applicatif IIS nommé WsusPool dans cet article ; j'ai décidé d'en faire un script Powershell afin de déclencher un recyclage du pool à distance.

Ce script va requêter le serveur via WinRM pour obtenir les informations concernant l'usage de la mémoire vive physique, et sur confirmation, déclencher à distance un recyclage du pool WsusPool.

Vous pouvez télécharger une version commentée du script à ce lien. 💾

function recycle{
Write-Host "Trying to start recycling in 5 seconds. Script will automatically end when recycling has successfully been initiated."
Start-Sleep 5
Invoke-Command -ComputerName $iishost -ScriptBlock { Restart-WebAppPool WsusPool }
}

Write-Host "WSUS IIS Application Pool Recycler"
Write-Host "=================================="
Write-Host ""
$iishost = Read-Host "Server to recycle the pool for ?"
$hostdetails = Get-Ciminstance Win32_operatingsystem -ComputerName $iishost
$hostramtotal = $hostdetails.TotalVisibleMemorySize
$hostramused = $hostdetails.TotalVisibleMemorySize - $hostdetails.FreePhysicalMemory
$hostramperc = [math]::Round(($hostramused/$hostramtotal)*100,0)
$hostramtotal = [math]::Round($hostdetails.TotalVisibleMemorySize/1048576,0)
Write-Host "% RAM used: $hostramperc"
Write-Host "Server $iishost has $hostramtotal GB total memory."
$confirm = Read-Host "Please confirm you wish to recycle the WsusPool IIS Application Pool on $iishost (yes)"
if ($confirm -eq "yes") { recycle }
else { Write-Host "Bye." ; break }

Au final, il est possible d'utiliser ce script pour n'importe quel pool car la commande Restart-WebAppPool est liée à IIS et pas spécialement à WSUS.

Réguler la consommation de RAM sur un serveur WSUS

Il arrive que WSUS et IIS qui fonctionnent de pair puissent déclencher fréquemment des alertes de sur-consommation de mémoire vive. Bien que cela n'impacte pas forcément les performances dudit serveur, il peut être nécessaire de forcer une "purge" du processus IIS exécutant le pool applicatif de WSUS afin que la consommation en RAM redescende.

Par exemple, ce matin :

Dans IIS, on peut "forcer" le pool applicatif de WSUS simplement nommé WsusPool à faire un recyclage des ressources systèmes qu'il occupe. Il suffit de sélectionner ce pool et de cliquer sur les options de recyclage (et non l'action de recyclage elle-même avec son icône de flèches vertes). Une fenêtre s'ouvre alors, proposant diverses options :

La fenêtre des options de recyclage permet de choisir une échéance de temps, de nombre de requêtes ou de consommation de mémoire vive, ou plusieurs à la fois.

On choisit donc les options qui nous conviennent : dans mon cas, en plus de l'intervalle de temps entre deux recyclages, j'ai défini un maximum de mémoire vive (à adapter en fonction de la charge souhaitée sur le serveur, il est évident que si l'on décide de n'y allouer que 500 Mo, les performances vont en pâtir), mais c'est optionnel. Une fois ce choix validé, nous pouvons lancer à la main un recyclage :

IIS va donc recycler le pool : cela signifie qu'il va créer un autre processus exécutant ce pool, puis transférer la charge mémoire du premier vers le nouveau, en faisant le "ménage" parmi ce dont il n'a plus besoin.

Le recyclage est en cours, le premier processus se vide en faveur du deuxième avant de disparaître.

Ainsi, la consommation en RAM a bien chuté et ne pourra dépasser 4 Go. Bien évidemment, cette limite n'est pas obligatoire ; en cas de surcharge ponctuelle du serveur, on peut toujours déclencher un recyclage manuel qui aura le même effet.

Erreur 530 lors de la connexion sur un FTP géré par IIS

J'ai installé récemment sous IIS un site FTP de backup qui est une réplication exacte du premier pour un client externe. Avant de procéder à la livraison de celui-ci, je voulais faire un test de connexion avec un utilisateur lambda pour m'assurer que tout était bien configuré proprement. Dans cet exemple, le serveur FTP se base sur ActiveDirectory pour obtenir la liste des comptes habilités ou non à lire ou écrire.

Et voilà que sur FileZilla, je me heurte à une erreur 530.

Un petit tour dans l'ActiveDirectory pour voir si il ne s'agit pas d'une variable mal configurée :

Aucun répertoire de profil n'est configuré, mais pas plus sur tous les autres comptes qui fonctionnent sur le premier environnement. Je décide donc de tester ce compte sur ce dit premier environnement et pas mieux, je me heurte à la même erreur.

Avec accord du client, je duplique donc un compte qui fonctionne et fais le test : pas mieux.

Je vérifie donc ma configuration IIS, et tous les paramètres sont strictement identiques. S'agissant visiblement d'un problème de répertoire, je vais sur la page des paramètres d'isolement des utilisateurs et le désactive (ce qui fait que chaque utilisateur n'est plus cantonné à son propre répertoire) :

Sur cette capture d'écran, le réglage bloque l'utilisateur dans un répertoire donné afin qu'il ne puisse pas browser l'intégralité du serveur FTP.

Une fois l'option Do not isolate users cochée, tout fonctionne avec les deux comptes, le dupliqué et mon compte de test. Le problème provient donc bien d'un répertoire non accessible qui est indiqué quelque part dans les comptes utilisateurs. Je fais un test avec l'original du compte dupliqué, et ça fonctionne !

Je décide donc de regarder au niveau des attributs des comptes. Sur les comptes qui fonctionnent, je vois ceci :

Deux attributs msIIS-FTPDir et msIIS-FTPRoot qui contiennent les informations permettant au serveur FTP d'isoler l'utilisateur. Sans ces attributs, pas de connexion possible. En analysant les attributs du compte dupliqué et de mon compte de test, je ne vois pas ces attributs, rendant alors la connexion impossible :

L'erreur n'a donc côté client jamais existé puisque les comptes utilisés avaient bien ces attributs de renseignés, ce qui n'était pas le cas pour mon compte de test.