HomeTopicsRetiring Plain FTP › Discovery

Finding Every Plain-FTP Flow You Own

The most dangerous FTP flow in your organization is the one nobody remembers. When an FTP retirement fails, it almost never fails on the flows in the project plan — it fails two weeks after shutdown, when a warehouse label printer stops receiving files, or a partner's invoices silently stop arriving, because a flow existed that no document mentioned. Discovery is therefore not a preliminary step in the retirement; it is the step that decides whether the retirement works.

This article is the discovery procedure: a systematic sweep of your own network and systems that surfaces every plain-FTP flow — the servers you run, the scripts and scheduled jobs dialing out, the devices uploading quietly, and the partner exchanges crossing your boundary. Everything here uses standard administrative tools against infrastructure you are responsible for, framed as the self-audit it is. The output is a retirement inventory: one table, one row per flow, that the rest of our Retiring Plain FTP series runs on.

Why Discovery Decides the Whole Program

FTP estates grow silently. The protocol has been the default glue between systems for decades, so it accumulated integrations the way an attic accumulates boxes: a script here, a device there, each added by someone solving that day's problem, none recorded centrally. The result is shadow FTP — flows that work, matter to someone, and appear in no documentation. Shadow FTP is not negligence; it is the natural state of any protocol that ran unattended for years.

The business case you made in the previous article also depends on discovery twice over. Before approval, real numbers ("we found 23 flows, 6 involving partners") turn a vague concern into a fundable project. After approval, the inventory becomes the project plan itself: every row gets an owner, a destination, and a date. And at the very end, the same sweep run one last time becomes your proof of completion. One procedure, three uses — which is why it is worth doing properly rather than from memory.

The Three Directions You Must Search

A complete sweep looks in three directions, because FTP can be present in three distinct roles. Miss a direction and you miss a category of flow entirely:

Direction The question Primary evidence
Servers you run What on our network is listening for FTP connections? Port scan of your own subnets; per-server service checks; server logs
Clients dialing out What scripts, jobs, applications, and devices initiate FTP connections? Scheduled-task and script sweep; firewall logs; device admin pages
Partner-facing flows What FTP traffic crosses our network boundary, in either direction? Firewall and NAT rules; boundary traffic logs; account lists on your servers

The three sweeps below cover these directions. Each catches things the others miss: the port scan finds a listener whose logs rotate away, the firewall logs find a client on a machine you cannot inspect, and the script sweep finds a job that only runs quarterly and therefore appears in no recent log at all.

Ground Rules Before You Scan

Everything in this article is a self-audit — examining infrastructure you administer, on networks your organization owns. Three ground rules keep it clean:

  • Get the nod first. Even on your own network, tell whoever owns change control and security monitoring before you scan. Port scans light up intrusion-detection systems, and "that was me, here's the ticket" is a much better conversation had in advance. Scan only address ranges you are authorized to audit.
  • Never scan other people's networks. Partner-facing flows are discovered from your side — your firewall logs, your NAT rules, your server accounts — never by probing a partner's systems. Their network is theirs to audit.
  • Mind fragile devices. Old embedded equipment occasionally reacts badly to aggressive scanning. Default scan speeds are fine for office networks; on segments with industrial controllers or lab instruments, scan slowly and during a maintenance window.

Sweep One: Port-Scan Your Own Network for Listeners

A port scan asks every address in a range "are you listening on this port?" — the fastest way to find FTP servers, including the ones nobody remembers installing. The standard tool is nmap, run from a machine with reach into each subnet:

# Find FTP listeners across your subnets (adjust ranges to yours)
nmap -p 21,990 --open 10.10.0.0/16 192.168.0.0/24 -oA ftp-sweep

# Add service detection: confirms it is FTP and reads the banner
nmap -p 21,990 --open -sV 10.10.0.0/16 -oA ftp-sweep-detail

Read the results with three things in mind. First, port 21 is plain FTP's control port, but a listener there is not automatically cleartext-only — some servers on 21 also offer explicit FTPS, an encrypted upgrade negotiated after connecting. Note the host now; classification comes later. Second, port 990 is implicit FTPS — encrypted from the first byte — so hits there are not plain FTP, but they belong in your inventory as context. Third, FTP occasionally hides on nonstandard ports; the -sV service-detection flag identifies FTP banners wherever they answer, and a wider port range on critical subnets is worth the extra scan time.

The scan has honest blind spots. A host-based firewall that only admits specific source addresses will hide a listener from your scanning machine; a server bound only to an internal interface is invisible from outside that segment. So complement the outside view with an inside check on every server you administer:

# Windows: what is listening on 21, and which process owns it?
netstat -ano | findstr :21
Get-NetTCPConnection -LocalPort 21 -State Listen

# Windows: is an FTP service installed?
Get-Service | Where-Object {$_.DisplayName -match "ftp"}

# Linux: listener plus owning process
ss -ltnp | grep -w :21

For each listener you confirm, pull its account list and recent logs — they convert "a server exists" into "these twelve accounts, these source addresses, this data." A server product with activity logging, such as Sysax Multi Server, gives you this per-session view directly, which later tells you who still uses plain FTP versus who already moved. And while you have each server open, check whether it accepts anonymous logins — a separate exposure with its own cleanup, covered in our anonymous and guest access series.

Sweep Two: Mine the Firewall Logs for Flows

Your firewall is the one witness that saw every FTP conversation cross a boundary, including clients on machines you cannot inspect and devices with no login. Two queries against it do most of the discovery work.

Query the traffic logs. Search recent history for connections to destination port 21, then group by source and destination. The exact syntax depends on your firewall or log platform, but the shape is always:

# The query shape (adapt to your firewall / log tool):
#   match:    destination port 21, action allowed
#   group by: source IP, destination IP
#   output:   connection count, first seen, last seen

# Example: iptables-style syslog lines (SRC=... DST=... DPT=21)
grep "DPT=21 " firewall.log | grep -o "SRC=[^ ]* DST=[^ ]*" | sort | uniq -c | sort -rn

Each distinct source–destination pair is a candidate flow. Outbound pairs (internal source, external destination) are your scripts, applications, and devices sending to partners — this is how partner-facing flows surface without touching the partner's network. Inbound pairs are outsiders reaching your servers. Internal pairs are east-west flows between your own systems. Look back as far as retention allows: monthly and quarterly jobs are exactly the ones a two-week window misses.

Query the rule base. Traffic logs show what happened; the rule base shows what is allowed. List every firewall rule and NAT forward that references port 21 or 990. A rule with zero recent hits is still a finding — either a dormant flow waiting to surprise you or a stale hole to close. Note each rule's ID in the inventory now; the final verification will want that list when the rules come out.

One caveat: firewalls only see traffic that crosses them. Two machines on the same network segment exchanging files by FTP never appear in boundary logs, which is why the port scan and the script sweep exist alongside this one.

Sweep Three: Scripts, Scheduled Tasks, and Config Files

Now hunt the initiators — the automation that dials FTP on a schedule. This sweep runs on every server that automates anything, and it is the one that finds the quarterly job sleeping between runs.

# Windows: scheduled tasks that mention FTP anywhere in their definition
schtasks /query /fo LIST /v | findstr /i "ftp"

# PowerShell equivalent, showing task names and the commands they run
Get-ScheduledTask | ForEach-Object {
  $a = ($_.Actions | ForEach-Object { "$($_.Execute) $($_.Arguments)" }) -join " "
  if ($a -match "ftp") { "$($_.TaskName)  ::  $a" }
}

# Windows: sweep script folders for FTP usage and hardcoded URLs
findstr /s /i /m "ftp://" C:\Scripts\* D:\Jobs\*
findstr /s /i /m "ftp" C:\Scripts\*.bat C:\Scripts\*.cmd C:\Scripts\*.ps1

# Linux: cron in all its hiding places, then the scripts themselves
crontab -l; ls /etc/cron.d /etc/cron.daily /etc/cron.weekly /etc/cron.monthly
grep -rn --include="*.sh" -e "ftp://" -e "^ftp " -e "curl ftp" /opt /usr/local /home

# Stored FTP credentials in per-user config files
ls -la /home/*/.netrc /root/.netrc 2>/dev/null   # Linux: login/password triplets
dir /s /b C:\Users | findstr /i "netrc"          # Windows: .netrc or _netrc

Widen the net beyond scripts. Application configuration files often carry ftp:// URLs — check the config folders of your line-of-business applications, web applications, and backup software. GUI transfer clients store site lists (profiles with saved hosts and credentials) in user-profile folders; a saved site is evidence a human uses that flow by hand. And .netrc files deserve special attention: they hold FTP passwords in plain text on disk, so each one you find is both a discovery lead and a cleanup item in its own right.

Every hit here is a future conversion task: the job itself will later be repointed at an encrypted protocol — the mechanics live in our migration guide, and jobs consolidated into a scheduler like Sysax FTP Automation can switch protocol in the connection profile without rewriting logic. For now, resist fixing anything. Discovery and conversion are different phases, and mixing them breaks both. If a script has no identifiable owner, log it anyway — our guide to inherited FTP automation covers safely dissecting jobs nobody admits to owning.

What the Sweeps Miss: Devices and People

Two categories evade all three sweeps some of the time, and both need a manual pass.

Devices. Multifunction printers with scan-to-FTP, security cameras uploading footage, lab instruments exporting results, backup appliances, badge systems, industrial controllers — these initiate FTP from firmware, appear in no script folder, and may transfer so rarely that logs miss them. Walk the fleet: each device's web admin page lists its upload destinations under names like "scan destination," "export target," or "archive server." When the firewall logs show an FTP source you cannot identify, resolve it the unglamorous way — reverse DNS, the switch's MAC address table, the MAC vendor prefix, and finally asking whose office that cable runs to. Devices that turn out to be FTP-only get their own path in this program: containment rather than conversion.

People. Manual workflows — a finance clerk uploading a file every month with a GUI client — leave traces only when they run. A short, blame-free note to team leads fills the gap: "We are retiring an old transfer method. What files does your team send or receive, with what program, to whom?" Phrase it as protecting their workflow, because that is exactly what it does. The census approach in our file flow census article generalizes this beyond FTP if you want the fuller picture while you are at it.

Building the Retirement Inventory

Every sweep result lands in one place: the retirement inventory, one row per flow. A flow is a repeating transfer with a purpose — "nightly sales export to partner X," not "port 21 open on 10.1.4.7." Several sweep hits often merge into one flow; one server usually hosts several flows. This is the record to fill in per row:

RETIREMENT INVENTORY — one row per flow
----------------------------------------
Flow name:        short, human ("Nightly sales export to partner X")
Direction:        inbound / outbound / internal
Source:           host, script, device, or person initiating
Destination:      server and folder receiving
Found via:        port scan / firewall log / task sweep / device / person
Owner:            named human accountable for the flow
Data carried:     what the files contain; sensitivity class
Schedule:         continuous / daily / monthly / quarterly / manual
Partner involved: yes (which, and their contact) / no
Device involved:  yes (make, model, firmware) / no
Credentials:      account used; where the password is stored
Last activity:    date of most recent transfer evidence
Disposition:      migrate / retire outright / contain (device) / TBD
Status:           found / owner confirmed / planned / converted / verified

Two fields do outsized work. Owner turns a technical artifact into an accountable conversation — no row should stay ownerless for long, even if the owner is initially "IT, by default." Disposition records the decision that the retirement plan will schedule; a surprising number of discovered flows turn out to be dead, and "retire outright, no replacement" is the cheapest disposition there is. Keep the inventory in one shared, versioned place — it is about to become the program's source of truth.

Classifying what you found

Raw findings become a plan when you sort them along three axes:

  • Live or dormant. Compare last-activity evidence against the schedule. A flow with no traffic in two retention cycles is presumed dead — but announce before deleting, because "dormant" sometimes means "annual."
  • Cleartext or already encrypted. A listener on port 21 might serve plain FTP, explicit FTPS, or both; a client might already negotiate encryption. The inventory tracks candidates; actual wire truth comes from a packet capture, which is the next section's subject.
  • Easy or entangled. A script you own converting to SFTP is an afternoon. A partner flow needs coordination and notice. A firmware device may never convert. This axis drives sequencing — easy wins first — in the plan article.

Proving Cleartext on the Wire

The inventory tells you where FTP might be moving in the clear; a packet capture tells you where it is. Watching your own network's traffic for readable USER and PASS lines settles every "but it might be encrypted" debate with evidence, and produces the kind of one-page exhibit that moves meetings. That wire-level verification is a discipline of its own, and we keep it in one place rather than duplicating it here: see finding cleartext on your network, this article's companion. Run the inventory sweep first — the capture is far more useful when you know which conversations to watch.

Remember: discovery is a cycle, not an event. Run the full sweep at the program's start, re-run it monthly while the retirement proceeds, and run it one final time as your proof. Flows you missed — and new ones people quietly create — only show up on the repeat passes.

Repeat Until Quiet, Then Plan

You are done with the first pass when a re-run of all three sweeps produces no new rows — typically after two or three iterations a week apart. At that point you hold something few organizations ever have: a complete, owned, classified map of every plain-FTP flow you operate. The business case gets its real numbers, and the project gets its work list.

Next comes sequence: grouping these rows by owner and partner, ordering the easy wins first, and setting the shutdown date — the subject of the FTP retirement plan. Keep the sweep commands from this page in a runbook; you will use them at least twice more before this program ends.

Frequently Asked Questions

Is it legal to port-scan my own network?
Scanning networks your organization owns, with authorization from whoever governs them, is a routine self-audit. The etiquette is to notify change control and the security team first so your scan is not mistaken for an attack. Never scan networks you do not administer — including partners' — even with good intentions.
Why didn't my scan find a server I know exists?
The usual reasons: a host firewall admits only specific source addresses, the service binds to an interface your scanner cannot reach, or it listens on a nonstandard port. That is why the sweep pairs the outside view (scan) with the inside view (netstat or ss on each server).
A listener on port 21 showed up — is it automatically plain FTP?
Not automatically. Port 21 can carry plain FTP, explicit FTPS (encryption negotiated after connect), or both, depending on server settings. Inventory it either way, then classify: server configuration and logs show what clients negotiate, and a packet capture proves what actually crosses the wire.
What is a .netrc file and why does it matter here?
It is a per-user file that FTP clients read for automatic logins, storing server, username, and password in plain text. Each one is both a discovery lead — it names an FTP flow — and a security cleanup item, since the password sits readable on disk.
How do I discover partner-facing FTP without touching the partner's network?
Entirely from your own side: firewall traffic logs show your systems connecting out to port 21, NAT and firewall rules show inbound paths you have published, and your server's account list shows which partners log in. That evidence is complete enough to plan every partner conversation.
How often should the sweep be repeated?
Run it until consecutive passes find nothing new — usually two or three rounds. Then monthly while the retirement program runs, and one final full pass as the proof of completion. After retirement, a periodic re-scan keeps FTP from quietly returning.

From the Sysax team: we build secure file transfer software for Windows — Sysax Multi Server, an FTP, FTPS, SFTP, and HTTPS server, and Sysax FTP Automation for scheduled, scripted transfers. Free trials are on the download page.