FTP is 50 years old
filestash.app
filestash.app
I never thought I would say this, but I actually implemented an FTP server in 2020. This was needed to support firmware updates to specific hardware (Electric Vehicle charging stations). Apparently embedded software developers choose FTP whenever a spec doesn't specify how binary file transfers should work.
It was kind of amusing getting FTP to work in a modern cloud environment. I run a single Kubernetes pod with a Node.js based FTP server optimized for one thing: Transferring files between FTP and Google Cloud Storage. A series of ports are specified in the Docker file to enable passive FTP transfers.
Even more amusing was the number of varieties in which FTP was implemented by different hardware manufacturers. I regularly had to dive into the FTP libraries to add support for crazy edge cases (tcpflow in kubectl exec -it is your friend!). Example: one device added a newline in the middle of a command (USER\n myusername)..
The latest curve ball I received this week is that a certain firmware version of a Qualcomm modem chip cannot deal with the size of the IP packets coming from our FTP server... Fun stuff!
The similarity of the names often causes confusion, but SFTP has nothing to do with the venerable FTP.
SFTP stands for "SSH file transfer protocol" and it's a completely different beast. IMHO, a somewhat unfortunate naming choice, but that's water under the bridge.
(...while FTPS stands for "FTP over SSL", and that actually uses plain old FTP with an additional SSL/TLS layer...)
TFTP is actually over UDP, guarantees only one data packet on the wire at any one time (no sliding window), does not support listing a remote directory, and is extreme in simplicity.
FTPS has such arbitrary controls for TLS optional versus required status over control and data channels that it is easy to misconfigure.
SFTP lacks two key features (amidst jump host and other scope creep frenzy), anonymous mode and URL support in a browser.
A new file transfer protocol, restricted to DJB ciphers a la Wireguard, able to run over TCP or UDP would likely be best. If Chrome and Safari both added browser clients, the server world would likely dump most FTP the next day.
Forcing the null password up the stack to /etc/shadow (or other credential sources) potentially compromises PAM and other applications that may depend upon it.
It sounds like you've implemented a separate SSH server within a chroot for this to protect the base OS; I've done the same for tinyssh with nspawn for an internal project. This is not easy.
Anonymous access for SFTP doesn't scale to the extent used in FTP, even omitting browser access.
Regarding SFTP and null passwords, I do not use a separate sshd. I just use the "Match" stanza in OpenSSH. Any SFTP users I add are in the sftpusers group and don't have a shell. SELinux will block some nonsense. For a few years, I had a cron job that was dynamically adding any account that bots would try. I think I was up to about 23k SFTP accounts. I will fire it back up either today or tomorrow and you are welcome to do a pen-test on it. I will also post the sshd_config.
The OpenSSH 4.3 release on this platform does not support the "match" keyword, but I was able to coerce it to run a separate SFTP-only on port 24, where I constrained the SFTP-specific accounts. I find that I prefer this approach.
My wily users then discovered that the working passwd entry also let them login with FTP on port 21, so careful control of allowed groups for both protocols was eventually required. Afterwards there is always the nagging suspicion that something was missed.
OpenSSH would also be much better with localized SFTP accounts that were not defined in /etc/passwd. Add that to the wishlist.
I put a sftp server back up. Feel free to play around with it. This is a single sshd instance and a copy of the config is in the /pub directory of the anonymous user. I did not change anything in pam. The sftp users are selinux confined as user_u.
server: 45.79.100.12
port: 22
username: anonymous, anon, pub, public
pw: (null) just hit enter
This message probably won't age well if I remove that node.It’s dangerous though, be sure to check these users don’t get shell access or the ability to create network pipes.
You forgot the abysmal performance compared to FTPS due to the SSH flow control conflicting with the underlying TCP flow control.
If I had any influence on the protocol it would be HTTPs. This is why I wasn't expecting to build an FTP server in 2020.
I learned this lesson in the mid 90s when fixing client compatibility bugs in an FTP server module we had built in an interpreted language, because, how hard could it be...
> The latest curve ball I received this week is that a certain firmware version of a Qualcomm modem chip cannot deal with the size of the IP packets coming from our FTP server... Fun stuff!
Right.
My experience... there aren't a ton of choices in this space. There are a few FTP servers designed to power B2B backend services. Many of the options are designed only to provide access to the local filesystem.
The "local filesystem" doesn't have to be a local file system. It's just a good, common abstraction useful for interoperability. Why not "rclone mount" your Google Drive, or use some other FUSE based file system to get easy interoperability between legacy FTP servers and modern storage options?
Going through FUSE is, in my mind, a last resort.
Why not run a regular FTP server and have your application periodically look for new files to process? For horizontal scaling, you just take a distributed lock on the file name.
Not necessarily so. The history of FTP servers is ridden by bugs with practically no exceptions. At some point some folks decided they finally implement a bug-free implementation and even dared to call it "Very Secure FTPd." Needless to say, it turned out it has bugs, too.
As most of these bugs were related to buffer overflows and similar issues, implementing a new FTP server in a safer language is not such a bad idea, and today's JavaScript is efficient enough to make it a reasonably well-working implementation. I pity the author though for the bugs they encounter and workarounds that will need to be implemented.
I'm making the maintenance of this less painful by doing a hacking/debugging session with manufacturers once a month where we hook up many devices and fix issues. After addressing most edge cases fewer are coming up now (despite a relentless stream of new cheaply manufactured devices)
I see a fairly alarming open issue: https://github.com/autovance/ftp-srv/issues/167
We use MongoDB as persistence and have existing wrappers for dealing with Google Cloud Storage.
Since it's an isolated service we could've used a different implementation language.
In our case Node.js in our existing Kubernetes environment was the least amount of friction
If you deploy an existing FTP server, and _then_ integrate with it at the filesystem level you now have two components, and your sysadmin requirements grow. Now you gotta administrate an FTP server that's probably written for classic UNIX single server usage, gotta handle filesystem permissions, gotta somehow hook up your distributed locks to the filesystem, sanitize filenames for your chosen filesystem.
Honestly filesystems suck, there's so many gotchas from a security perspective, when all you really want is to pipe binary data in this side, and out the other side.
I implemented an IRC bot in a few hours in javascript one day. Those classic IETF text based protocols are actually really fun and easy to implement, especially in a language that makes strings safe and easy (i.e. not C).
I could easily see figuring out all the deployment concerns around integrating with an existing FTP server end up taking way longer than just integrating the subset needed for this use case.
Cordinating a client across two ports sounds trivial compared to for example properly implementing client and server versions of IMAP search commands when no client or server follows the specification.
But yeah, if you only need to support one client, I can see the reasoning. It would never have flied at any of the places I've worked, though, having to support tons of clients.
- Scaling requirements are relatively low. Even though we're dealing with 10 thousands of devices, the amount of firware updates at a given time to those devices is minimal. Our main scaling challenges are around OCPP over websockets. Story for another day.
- I have bad memories of ProFTPd etc buffer overflow exploits.
- I wanted something simple that could bridge between FTP and our cloud persistence (MongoDB and Cloud Storage).
- I found this Node.js library that I since then forked: https://github.com/autovance/ftp-srv - The great thing about this library is that it allows a quick implementation of a custom filesystem.
- For Kubernetes pods the file system should really be treated as a /tmp - which we are doing.
- When a charge station connects, the FTP username/password is a temporary generated set of tokens that is checked against our MongoDB.
Essentially, I'm using FTP as a throwaway here.
If you think through this you can imagine it would be quite a lift to accomplish this with an existing FTP server.
If you did this for work, junior engineer move in my opinion. This practice is called not invented here syndrome.
You don't always have off-the-shelf packages for every conceivable environment you work in.
Username: anonymous
Anonymous login accepted, enter e-mail address as password.
Password: aoeu@aoeu.com
I bet aoeu.com and asdf.com got a good amount of unwanted mail back then.
> It resulted from a typo. I was writing a domain registration system for an ISP and, during some debugging, forgot to use the --no-act command line flag and ended up registering aoeu.com for real. Since it was so easy to type, I kept it.
The letters A O E U are the first four characters of the left hand on a Dvorak keyboard, which is the layout I use.
2. The FTP protocol got a lot of cruft added to it that modern clients don't implement (e.g. any transfer mode other than stream).
3. FTP over TCP predates NATs and firewalls, which caused a lot of problems as well.
4. FTP was designed for human-readable, not machine-readable output. In particular the output of a LIST command is woefully underspecified.
I think #1 is the biggest issue for long-term viability of protocols. Not following Postel's law is a recipe for death (same reason why it's suicide for a browser to unilaterally untrust a major CA; any site that doesn't work in browser X is assumed to be browser X's fault), but following Postel's law is a recipe for undocumented de-facto standards with crazy edge cases.
I see that there's been a debate over the applying Postel's Law, a.k.a. the Robustness Principle, for some time:
https://en.wikipedia.org/wiki/Robustness_principle#Criticism
> a defective implementation that sends non-conforming messages might be used only with implementations that tolerate those deviations from the specification until, possibly several years later, it is connected with a less tolerant application that rejects its messages.
That Wikipedia page led me on to this IETF draft from 2019 on protocol maintenance
https://tools.ietf.org/html/draft-iab-protocol-maintenance-0...
> Abstract
> The robustness principle, often phrased as "be conservative in what you send, and liberal in what you accept", has long guided the design and implementation of Internet protocols. The posture this statement advocates promotes interoperability in the short term, but can negatively affect the protocol ecosystem over time. For a protocol that is actively maintained, the robustness principle can, and should, be avoided.
It seems that you need both for the protocol to be unambiguously, fully specified, and for popular implementations to avoid applying Postel's Law! But we've seen how market forces conspire to work against that.
Brainstorming opportunities for improvement beyond the suggestions in the IETF doc:
• Accompany the protocol with a validation test suite.
• Provide a validation service.
• Treat non-validating messages skeptically ("quirks mode").
So FTP is older than the standardisation of byte size :-)
What’s a nibble of a byte is 8bits
> nybble: /nib´l/, nibble, n.
^---- see that word over here?I was curious and searched HN and found this 2012 comment explaining octet is essentially an anachronism, as bytes have been standardized at 8 bits: https://news.ycombinator.com/item?id=4649528 . Feeling old!
I see it used (and use it myself) from time to time in contexts where you want to differentiate between 7/8/9-bit bytes, mostly when working with embedded/low-level software.
Commonly, the word octet is used to refer to IP addresses, and the permission octets of files in nix systems.
"The size of the byte has historically been hardware-dependent and no definitive standards existed that mandated the size. Sizes from 1 to 48 bits have been used.[4][5][6][7] The six-bit character code was an often-used implementation in early encoding systems, and computers using six-bit and nine-bit bytes were common in the 1960s. These systems often had memory words of 12, 18, 24, 30, 36, 48, or 60 bits, corresponding to 2, 3, 4, 5, 6, 8, or 10 six-bit bytes. In this era, bit groupings in the instruction stream were often referred to as syllables[a] or slab, before the term byte became common."
If you want to be specific, you could say "octet" to describe a set of 8 bits.
There are differing sizes for bytes. This isn't so common, anymore, but that was the point being made.
> What’s a nibble of a byte is 8bits
A nibble is 4 bits not 8 bits.
https://blog.mozilla.org/addons/2021/04/15/built-in-ftp-impl...
For my first dev job we would develop on production using an FTP client to push up changes on save. One day I was writing an SQL UPDATE statement and I forgot to include a WHERE clause. I basically nuked the entire product DB and it took days to recover because it was also not unheard of to not have regular db back ups. No one really questioned it too much though. Stuff like that just happened from time to time back then.
I rarely ever use FTP today. I wonder if students learning to code today even know what FTP is? It was one of the first things I learnt when learning to build websites as a teenager, but I don't that's the case anymore.
It's kind of interesting how processes in tech have evolved as much as the technology over the last few decades. It's hard to think of a good usecase for FTP anymore, but just a couple of decades ago it was used everywhere. Is anyone still using it for anything?
So FTP wins easily this one. It's free with unlimited storage, always has been, always will be.
All the developer were sat around one table but you couldn’t see each other behind the dual screens. So every hour or so, somebody stood up to inform the team that he is going to be editing file xyz, so please don’t touch.
It wasn’t production though, everyone was just working on a shared staging system.
Only 5 years ago, we had an 'editing stick'. Only the person physically in possession of the editing stick was allowed to make edit the configs to our (early 90's vintage) SCADA system.
Frankly the system worked very well: "if it ain't broke, don't fix it".
We only got rid of the editing stick when the machinery in question was scrapped.
Didn't last long, obviously, but that was back in the days when every site had a well-publicized guest login and you could telnet anywhere. (Well, OK, in 1972 there were only a few dozen nodes, but there were some really interesting ones to play with.)
We used to play a game with telnet from HARV-10 where we'd telnet-chain around the world until someone dropped the connection or it got too slow.
I still own the domains ftphub.com and ftphub.net, and I put the domains at auction since it looks like I'll never get around to it.
Should I work on this ? Or has this opportunity been commoditized to the point where I there is no way it could turn a profit ? Also has anyone under 30 even heard of "ftp" ? The abbreviation in our brand but not sure it's meaningful anymore. Thanks and sorry if this is too off topic.
Pedantry: It's "Jimi".
FTP predates Ethernet, Token Ring and ARCNET. It predates TCP/IP. For an actual protocol, and not just a simple format specification like ASCII, it doesn't get older than that in current use.
In 5th grade, I had the attention span of a fruit fly. Probably would have tried drawing phalluses in ascii if I had known about it.
[1] Sometimes it seems like every interesting discussion boils down to definitions, doesn't it?
...which is an unlikely contender for oldest protocol!
https://en.wikipedia.org/wiki/Baudot_code#ITA2
> In 1924, the CCITT introduced the International Telegraph Alphabet No. 2 (ITA2) code[14] as an international standard, which was based on the Western Union code with some minor changes.
> ITA2 is still used in telecommunications devices for the deaf (TDD), Telex, and some amateur radio applications, such as radioteletype ("RTTY").
It's interesting that the fundamentals of this were invented in 1870s. Who needs semiconductors when you have gears and levers?
Morse code from 1840s. Ham radio still uses it when signal took weak fir voice. Proficiency was required for a ham license until 2006.
Each team of four came up with their own signaling method, trying to balance how many bits were transmitted with each symbol with how quickly we could encode/decode the message.
Binoculars were not allowed. We were outside, so we didn't know how windy it would be.
I seem to recall on my team, we were sending two bits per symbol. I think it was just a large cardboard box, we colored each of the four flaps visually distinct, then unfolded one of the flaps for each symbol.
I don't recall a single team thinking to re-purpose naval flags.
Duh.
Naval flags would be higher bandwidth if you could pre-arrange a modest-sized dictionary of the words and phrases you’d need.
https://www.navalgazing.net/Signalling-Part-1 is a good read.
Or maybe morse code counts as a protocol?, Still around in VOR (VHF omnidirectional range) and NDB (Non-directional beacon) in the aviation world.
People are answering with old telephone codes and British naval signals, etc.
You should be thinking:
- The muslim call to prayers.
- The affirmation of faith, as it is spoken in mass or (protestant) church ... or the first and second readings, followed by a Gospel reading.
- The Jewish rite of circumcision (which is, among other things, almost certainly a signaling mechanism).
https://en.wikipedia.org/wiki/Protocol_(diplomacy)
> The term protocol is derived, via French and Medieval Latin, from the Greek word πρωτόκολλον protokollon "first glued sheet of or onto a papyrus-roll".
> The rules of protocol to create space where meetings can take place.
https://www.protocol.dubai.ae/About/Protocol-History
> The diplomatic relations that existed between Egypt and Babel, which started in 1450 B.C., included highlights on the application of standards for Protocol and Etiquette that were related to both diplomatic immunities as well as receptions and ceremonies.
It's one of those things that stands up to its name: it's a file transfer protocol, and is still, practically, the best.
I didn’t have the time/resources for a deep dive to determine the root cause of the problem so my work-around at the time was to use `stat` to compare file sizes of the local and uploaded file. If they didn’t match, the file was simply re-transmitted – and it always worked the second time. ¯\_(ツ)_/¯
There's still millions of ftp servers running the wild: https://www.shodan.io/search?query=ftp
And this was a year or so after a major, and costly, rework was required due to a real-world system failure (no fatalities or injuries, fortunately) that would have been caught if testing had been more thorough. But testing wasn't more thorough because we simply couldn't actually flip switches fast enough to simulate a wide enough variety of behaviors, so the testing was woefully incomplete and the timing issue at the heart of the failure was sufficiently complex to be non-discoverable in code and design reviews. Literally having to spend several million out of pocket to fix a broken system wasn't enough on its own to cause them to let us improve our testing methods.
Worth noting, the cost of the new testing equipment was only in the 5-figure range, not the 7-figure range of the rework.
I had some related thoughts. They may have a strong content filter on their incoming web. I was sending them a CSV but we had to talk about it like it was a proprietary-format Excel document for the sake of those who would eventually be loading it with Excel.
My best guess eventually was that FTP was considered the best way to go around their content filter on purpose. Makes negative sense to me.
Still, a couple of years back now I had to setup an IP-limited SFTP server for our comms team. But I made them 'sign in blood' that it was a temporary solution until their supplier could implement a more secure alternative. Like I said, it was a few years ago...
FTP definitely still has its uses, it just needs careful thought and setup.
$ /usr/bin/ftp
ftp> help
Commands may be abbreviated. Commands are:
...proxy...
While I've never been able to make that work correctly, it supposedly allows transfers between two remote hosts (all cleartext of course). The logins work, but the gets and puts don't.It didn't seem worth the time to set up, and similar functionality has been added to SSH file transfer.
The SITE command can also run arbitrary programs on the server (becoming something like an rsh), which will never be added to SFTP. I've actually written a couple web applications that drive a VAX with "site spawn" and some DCL.
That’s commonly known as “FXP”, and has been disabled for security reasons on all modern platforms.
The FTP protocol provides lots of features that SFTP doesn't. However, most of those distinctive features are rarely implemented in FTP clients for Unix-like systems or Windows. It is more common to find them implemented in mainframe or minicomputer FTP implementations:
- Record-oriented files (STRU R). Unix-like systems and Windows don't have any concept of record-oriented files (where the filesystem is aware of record boundaries–on Unix and Windows, record boundaries are an application-level concept only.) Platforms such as IBM mainframe operating systems, and OpenVMS RMS, do have such files, and so FTP implementations for them often support STRU R
- Block mode file transfer (MODE B). This is where transfers are broken into blocks and each block has a header with a length and flags. You need this to transfer STRU R files (especially binary STRU R files). Unix and Windows FTP programs generally only support stream transfer mode (MODE S)
- Flagging data blocks as corrupt (in a MODE B transfer). This was intended to be used when the file being FTPed is being read directly from a tape. If one of the tape blocks has an invalid checksum, and repeated reads fail to read it with a valid checksum, you can transfer what you read from the block, but set a bit in the block header to indicate the data could be corrupt
- Compressed transfers (MODE C). This is like MODE B but blocks can be compressed. Unfortunately the compression is really basic, just run-length encoding. Some non-standardised extensions to FTP add support for better compression formats (e.g. "MODE Z" for zlib), but those generally are adding compression to MODE S not MODE B.
- Built-in ASCII-EBCDIC conversion (TYPE A vs TYPE E). Unfortunately, this is not aware of the existence of different variants of ASCII and EBCDIC ("code pages"), although there are some non-standardised extensions to add that (which IBM mainframe FTP servers/clients commonly implement). There was also an Internet draft to define a TYPE U explicitly for UTF-8, but it never advanced to an RFC [0]
- Metadata to indicate the carriage control format used in a text file ("FORM"). ("Carriage control" is about telling old-fashioned line printers how to print each line.) You can mark a file as using either ASA carriage control [4] (TYPE A A, TYPE E A), or TELNET carriage control (TYPE A T, TYPE E T; this means carriage control using CR, LF, HT, VT, FF, etc). This feature is rarely implemented except on mainframe platforms where this metadata is supported by the filesystem. (It isn't in the FTP standard, but I believe some IBM mainframe FTP clients/servers also support the IBM proprietary 'machine code' [5] carriage control as well.)
- Non-8 bit bytes. This was commonly used with 36-bit operating systems, for example TOPS-10 or TOPS-20, to transfer files made up of 36-bit words (TYPE L 36).
- "Paged files" (STRU P). These are files composed of "pages" (blocks) where each page has a header, you can have sparse files (some pages not present), even different access control for each page. Unfortunately, the specification is overly specific to the needs of TOPS-10, and can't really be used on other platforms that have the same concept but implement it in a different way. RFC1123 recommends not to implement this feature.
- Account numbers (ACCT). This lets you supply an account number, as well as username (USER) and password (PASS). This was used on some mainframe systems, to bill each transfer to a particular account. (The same user may have access to multiple accounts, and this lets them choose which one to bill the transfer to – consider the case of an academic working on multiple research projects simultaneously.)
- Structure Mount (SMNT). This lets you mount a filesystem over FTP. Most commonly used for DOS/Windows FTP servers to change drive letters.
- Store Unique (STOU). Allows you to upload a file without choosing a name for it. The server chooses a unique name for you, and at the end of the transfer tells you the name it chose.
- Allocate space for a file (ALLO). This allows you to allocate disk space for a file upfront before you transfer it. For record-oriented files (STRU R) or page-oriented files (STRU P), also supports specifying the maximum size of a record/page. Especially used in IBM mainframe operating systems where you are expected to say how big your file (dataset) is going to be before you write any data to it. (In principle, this could be implemented on Linux using fallocate, but in practice Linux FTP servers just ignore the ALLO command.)
It is common for IBM mainframe systems to prefer FTPS (FTP over SSL/TLS) over SFTP, because they actively implemented and use some of the above features which are unique to FTP and lacking in SFTP. IBM mainframe FTP servers also often offer lots of proprietary (non-standard) features in their FTP servers, such as setting dataset allocation parameters, submitting batch jobs (JCL), checking batch job status and retrieving batch job output, executing MVS console commands, running SQL queries (especially with DB2). Since FTP commands are ASCII, it is easy to invoke commands not supported by a particular FTP client simply with "QUOTE SITE". That generally isn't possible with SFTP, since its commands are in a binary format.
There are also some interesting FTP extensions defined for use with high-performance computing – GridFTP [1] [2] [3], including an extended version of block mode (MODE E) with support for "striped" transfers, in which multiple connections (possibly even running across different hosts) transfer different parts of a very large file.
[0] https://tools.ietf.org/html/draft-klensin-ftpext-typeu-00
[1] https://www.ogf.org/documents/GFD.20.pdf
[2] https://www.ogf.org/documents/GFD.21.pdf
[3] https://www.ogf.org/documents/GFD.47.pdf
[4] https://en.wikipedia.org/wiki/ASA_carriage_control_character...
[5] https://en.wikipedia.org/wiki/IBM_Machine_Code_Printer_Contr...
http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R....
(ASCII mode automatically translates line-endings, which can break non-text formats in confusing ways)
FTP -> Ratio servers -> Napster -> MP3.com -> iTunes -> Spotify.
FTP -> Ratio servers -> Napster -> MP3.com -> 99c songs on iTunes -> 24x7 streaming music.