I have been struggling yesterday and today to get FTP working on IIS 7.5 in a Windows Azure Virtual Machine and I just achieved victory! To remember all the steps myself and to help others in achieving the same, I’ll describe how to accomplish this.
Spin up a virtual machine
First of all, you need a virtual machine. I needed a Windows machine with a SQL Server database so I chose 'Microsoft SQL Server 2012 Evaluation Edition' from the available templates.
Once the machine has booted, you can RDP into it via the connect option at the bottom of the management portal.
When you’re in, you need to configure IIS. A summary of the required steps:
- Add the 'Web Server (IIS)' role to the server.
- Add the IIS features you need.
- Add a TCP endpoint to your VM in the management portal with public and private port 80.
To enable FTP, make sure you enable the 'FTP Server' role services for your IIS role:
Add and configure FTP site
The next step is to create the actual FTP site in IIS. Right-click on 'Sites' in IIS Manager and select 'Add FTP Site…':
Specify the name and the local path for the site:
Specify binding and SSL information:
And finally specify who should have access to the FTP site. Note that I selected Basic Authentication and the administrator user. This corresponds to the local administrator account on the VM (the same account you use when you use RDP to login). This is definitely not the best solution. When you do not use SSL to secure access to the FTP site, your FTP credentials are sent in cleartext when logging in to the FTP site.
You should now be able to access the FTP site from within the VM. Open a command prompt, type 'ftp 127.0.0.1' and login with your administrator account.
Well, that was the easy part. You now have an FTP site that you can access locally. When you try to access it from another machine, you will notice that you can't get a connection.
We are now getting into the nitty gritty details of the FTP protocol. Whereas you may think that FTP only uses port 21, it actually doesn't. I’m not going into the details but there's a good explanation here.
Configuring remote connectivity
First of all, for active FTP, in theory you need to allow access to ports 21 (FTP command port) and 20 (FTP data port). So you need to add two endpoints to your VM:
So far the theory. When attempting to connect to the FTP site using Filezilla, explicitly indicating that we’d like to use active mode, still no connection can be established. I haven't figured out why exactly…
But of course we can still try to configure passive FTP. For this to work, we need to tell the IIS FTP server the port range it can use for data connections and we need to add endpoints to the VM that correspond to this port range.
First of all, configure the port range and external IP address for passive data connections. This can be found in IIS Manager:
The external IP address should be the Virtual IP address you can find in the Azure Management portal. Unfortunately, it seems impossible to specify the data channel port range here. To set this, we need the appcmd utility, which can be found in
appcmd set config /section:system.ftpServer/firewallSupport /lowDataChannelPort:7000 /highDataChannelPort:7014
In the example, I chose ports 7000 to 7014 but you can choose any port range you like as long as it corresponds to the endpoints you configure for your Azure VM.
For configuring 15 extra endpoints for my VM I decided to use the Windows Azure Powershell cmdlets which you can download here. You can also add 15 endpoints in the management portal but you can only add them one by one which takes a considerable amount of time. To be able to use these cmdlets, you first need the publish settings file for your Azure account. There are a number of ways to download the publish settings file and one way is to start Windows Azure Powershell and use the cmdlet
Get-AzurePublishSettingsFile. It opens a browser and allows you to download the publish settings file that corresponds to your Windows Live id.
When you have downloaded the publish settings file, you can import it using the
Import-AzurePublishSettingsFile cmdlet and we’re ready to start adding endpoints. I simply created a text file containing the list of commands I wanted to run and copied that into the Powershell window:
Get-AzureVM -ServiceName 'myServiceName' -Name 'ftpportal' | Add-AzureEndpoint -Name 'FTPPassive00' -Protocol 'TCP' -LocalPort 7000 -PublicPort 7000 | Update-AzureVM Get-AzureVM -ServiceName 'myServiceName' -Name 'ftpportal' | Add-AzureEndpoint -Name 'FTPPassive01' -Protocol 'TCP' -LocalPort 7001 -PublicPort 7001 | Update-AzureVM ...
We're almost there. Although the Windows firewall seems to allow all traffic that's required, you also need to enable stateful FTP filtering on the firewall:
netsh advfirewall set global StatefulFtp enable
Finally, restart the FTP Windows service and we should be up and running:
net stop ftpsvc net start ftpsvc
Testing with Filezilla confirms that we can now successfully connect to our new FTP site, hosted on a Windows Azure VM:
Adding extra user accounts
As I said before, using the default administrator account for accessing your FTP site is a BAD idea because credentials are sent in clear-text. Therefore, create a new local user account on the VM and add an FTP authorization rule to allow access to your FTP site.
I had some help writing this article, mainly from this article by Angelo Laris that describes how to add active and passive FTP functionality to an Azure Web or Worker Role.
Other references include: