FTP is still running in more environments than most teams expect. The real risk is usually not a complex zero-day. It is simple exposure: internet-facing services, weak transport settings, and cleartext fallback left enabled.
If FTP exists in your environment, treat it like technical debt with internet reach.
1) Confirm what is actually exposed
Linux (local listeners)
sudo ss -ltnp | egrep ':21|:20|:990|:2121'
sudo lsof -iTCP -sTCP:LISTEN -P | egrep ':(21|20|990|2121)'
Windows Server (local listeners)
Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -in 21,20,990,2121 } |
Select-Object LocalAddress,LocalPort,OwningProcess
Map PID to process:
Get-Process -Id <PID>
External validation (run from another host)
nmap -sV -p 21,20,990,2121 your-public-ip
nmap -sV -p- --open your-public-ip | egrep 'ftp|21/tcp|990/tcp'
Do not rely on port 21 checks only. Legacy services often run on alternate ports.
2) Validate encryption behavior (not just config)
A common failure is “TLS looks enabled” but cleartext still works.
openssl s_client -connect your-server-ip:21 -starttls ftp
If negotiation fails or cleartext auth is still accepted, remediation is required.
Encryption quick note
Use SFTP (SSH, port 22) for new deployments. It encrypts auth and data by default and is easier to secure consistently.
If legacy FTP must remain:
- use FTPS with enforced TLS
- block cleartext fallback
- disable SSLv2/SSLv3/TLS 1.0/TLS 1.1
Avoid plain FTP on internet-facing systems.
3) Linux hardening (vsftpd baseline)
Example /etc/vsftpd.conf:
ssl_enable=YES
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
allow_anon_ssl=NO
anonymous_enable=NO
local_enable=YES
write_enable=NO
chroot_local_user=YES
pasv_min_port=40000
pasv_max_port=40100
Restart and verify:
sudo systemctl restart vsftpd
sudo systemctl status vsftpd
Restrict exposure (example UFW):
sudo ufw allow from <trusted-ip>/32 to any port 21 proto tcp
sudo ufw allow 40000:40100/tcp
sudo ufw deny 21/tcp from any
4) Windows Server hardening (IIS FTP)
If you use IIS FTP, verify both policy and certificate binding. “Require SSL” without correct cert binding can create false confidence.
Check FTP sites
Import-Module WebAdministration
Get-ChildItem IIS:\Sites | Where-Object { $_.Bindings.Collection.protocol -match "ftp" } |
Select-Object Name, State
Check FTP SSL settings
Get-WebConfigurationProperty -PSPath "IIS:" `
-Filter "system.applicationHost/sites/site[@name='YourFTPSite']/ftpServer/security/ssl" `
-Name "."
In IIS Manager, set for each FTP site:
- FTP SSL Settings
- Control Channel: Require SSL
- Data Channel: Require SSL
- Valid certificate selected
Restrict firewall access
New-NetFirewallRule -DisplayName "Allow FTP Control Trusted" -Direction Inbound -Protocol TCP -LocalPort 21 -RemoteAddress <TrustedIP/CIDR> -Action Allow
New-NetFirewallRule -DisplayName "Allow FTP Passive Trusted" -Direction Inbound -Protocol TCP -LocalPort 50000-50100 -RemoteAddress <TrustedIP/CIDR> -Action Allow
New-NetFirewallRule -DisplayName "Block FTP Control Public" -Direction Inbound -Protocol TCP -LocalPort 21 -RemoteAddress Any -Action Block
Adjust passive range to your IIS FTP firewall support configuration.
5) Migration path (recommended)
Where possible, move to SFTP and retire FTP/FTPS complexity.
Linux
sudo apt install openssh-server
sudo systemctl enable --now ssh
sudo systemctl disable --now vsftpd
Windows Server (OpenSSH)
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
