Skip to content

Golang based autonomous FTP server with SFTP, S3, Dropbox, and Google Drive connectors.

License

Notifications You must be signed in to change notification settings

fclairamb/ftpserver

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

89edd73 · Oct 14, 2024
Oct 7, 2024
Sep 23, 2022
Jan 11, 2023
May 28, 2024
Aug 8, 2024
Sep 23, 2022
Sep 23, 2022
Jul 27, 2021
May 28, 2024
Jul 14, 2017
Jul 14, 2017
Aug 13, 2024
Sep 6, 2024
Sep 18, 2022
May 28, 2024
Sep 23, 2022
Sep 23, 2022
Jan 11, 2023
Apr 27, 2022
Oct 4, 2024
Oct 4, 2024
May 3, 2020
Sep 23, 2022

Repository files navigation

Golang FTP Server

Build Cross Build Docker Image Docker test Docker downloads Go Report Card GoDoc

This FTP server is a gateway between old-school FTP devices and modern cloud based file systems, using the afero's Fs interface and acting as a reference implementation of the ftpserverlib.

At the current stage, supported backend are:

And with those are supported common parameters to switch them to read-only, enable login access, or use a temporary directory file (see doc).

Current status of the project

Features

FTP protocol

These features are brought by ftpserverlib itself:

  • Uploading and downloading files
  • Directory listing (LIST + MLST)
  • File and directory deletion and renaming
  • TLS support (AUTH + PROT)
  • File download/upload resume support (REST)
  • Complete driver for all the above features
  • Passive socket connections (EPSV and PASV commands)
  • Active socket connections (PORT command)
  • Small memory footprint
  • Only relies on the standard library except for:
  • Supported extensions:
    • AUTH - Control session protection
    • AUTH TLS - TLS session
    • PROT - Transfer protection
    • EPRT/EPSV - IPv6 support
    • MDTM - File Modification Time
    • SIZE - Size of a file
    • REST - Restart of interrupted transfer
    • MLST - Simple file listing for machine processing
    • MLSD - Directory listing for machine processing

Getting started

Get it

Download it

Fetch a binary from the latest release and run it.

Build & run it locally

go install github.com/fclairamb/ftpserver@main

ftpserver &

Run it with docker

There's also a containerized version of the server (31MB, based on alpine).

# Creating a directory
mkdir -p files

# Starting the sample FTP server
docker run --rm -d -p 2121-2130:2121-2130 -v $(pwd)/files:/tmp -v $(pwd):/app fclairamb/ftpserver

Run it with docker compose

# docker-compose.yml

version: '3.3'
services:
  ftpserver:
    ports:
      - '2121-2130:2121-2130'
    volumes:
      - ./files:/tmp
      - .:/app
    image: fclairamb/ftpserver
docker-compose up -d

Test it

This is a quick way to see if it's working correctly:

# Download some file
[ -f kitty.jpg ] || (curl -o kitty.jpg.tmp https://placekitten.com/2048/2048 && mv kitty.jpg.tmp kitty.jpg)

# Upload it to the server
curl -v -T kitty.jpg ftp://test:test@localhost:2121/

# Download it back
curl ftp://test:test@localhost:2121/kitty.jpg -o kitty2.jpg

# Compare it
diff kitty.jpg kitty2.jpg

Config file

If you don't create a ftpserver.json file, one will be created for you.

Here is a sample config file:

{
   "version": 1,
   "passive_transfer_port_range": {
      "start": 2122,
      "end": 2130
   },
   "tls": {
      "server_cert": {
         "cert": "cert.pem",
         "key": "key.pem"
      }
   },
   "accesses": [
      {
         "user": "test",
         "pass": "test",
         "fs": "os",
         "params": {
            "basePath": "/tmp"
         }
      },
      {
         "user": "test",
         "pass": "test",
         "fs": "os",
         "params": {
            "basePath": "/tmp"
         }
      },
      {
         "user": "dropbox",
         "pass": "dropbox",
         "fs": "dropbox",
         "params": {
            "token": "..."
         }
      },
      {
         "user": "gdrive",
         "pass": "gdrive",
         "fs": "gdrive",
         "params": {
            "google_client_id": "***.apps.googleusercontent.com",
            "google_client_secret": "****",
            "base_path": "ftp"
         }
      },
      {

         "user": "s3",
         "pass": "s3",
         "fs": "s3",
         "params": {
            "endpoint": "https://s3.amazonaws.com",
            "region": "eu-west-1",
            "bucket": "my-bucket",
            "access_key_id": "AKIA....",
            "secret_access_key": "IDxd....",
            "disable_ssl": "false",
            "path_style": "false"
         }
      },
      {
         "user": "sftp",
         "pass": "sftp",
         "fs": "sftp",
         "params": {
            "username": "user",
            "password": "password",
            "hostname": "192.168.168.11:22"
         }
      },
      {
         "user": "telegram",
         "pass": "telegram",
         "fs": "telegram",
         "shared": true,
         "params": {
            "Token": "<OBTAIN_TOKEN_FROM_BOTFATHER>",
            "ChatID": "<INSERT_CHAT_ID_HERE>"
         }
      }
   ]
}

You can generate the TLS key pair files with the following command:

openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out cert.pem -keyout key.pem