unFTP

repository·master·Indexed 43 days ago

https://github.com/bolcom/unftp

A modern, highly configurable FTP(S) server built in Rust and the Tokio asynchronous runtime. It provides a standard FTP interface while supporting cloud storage backends (GCS, Azure Blob Storage, OpenDAL), flexible authentication (HTTP, PAM, JSON), and observability via Prometheus and structured logging. It can be used as a standalone server application or as an embeddable library via libunftp.

Tokens
16K
Snippets
53
Records
80
Agent score
56%

What's inside unFTP

  1. Overview of unFTP features

    master

    unFTP is an FTP(S) server written in Rust, built on libunftp and the Tokio asynchronous runtime. It is designed to provide RFC-compliant FTP(S) interfaces while using modern backend technologies.

    Key features include:

    • Configurable Authentication: Supports Anonymous, PAM, JSON files, or HTTP.
    • Configurable Storage: Supports backends like Google Cloud Storage (GCS) or local filesystems.
    • Configurable Notifications: Supports events via Google Pub/Sub.
    • Observability: Includes an HTTP server with health endpoints (for Kubernetes probes), Prometheus integration, and structured logging (compatible with Google Cloud Logging or Redis).
    • Proxy Support: Includes a proxy protocol mode for use behind HA Proxy or Nginx.
  2. Overview of libunftp

    master

    libunftp is a Rust crate designed for building custom FTPS (FTP over TLS) servers. It is built on top of the Tokio asynchronous runtime and leverages Async IO for high performance.

    Key features include:

    • Support for 41+ FTP commands.
    • Explicit FTPS (TLS) and Mutual TLS (Client certificates) support.
    • TLS session resumption.
    • Prometheus integration (enabled by default).
    • Structured logging and Proxy Protocol support.
    • Automatic session timeouts and per-user IP allow lists.
    • Configurable cryptographic providers (ring or aws-lc-rs).
  3. Overview of unFTP

    master

    unFTP is an open-source FTPS (not SFTP) server designed for cloud environments. It is built in Rust to provide memory safety and high performance. The project is designed to be highly extensible through three pluggable architectures:

    1. Authenticator: Custom authentication logic.
    2. Storage Back-end: Custom storage implementations.
    3. User Detail Store: Custom user metadata management.

    It is designed to support cloud-native features such as integration with proxy servers, Prometheus monitoring, and structured logging.

  4. Use slog-redis for centralized logging to Redis

    master

    The slog-redis crate provides a slog drain that outputs log messages to a Redis list. This is designed for centralized logging architectures, such as a RELK stack (Redis, Elasticsearch, Logstash, and Kibana).

    Log messages are sent in the Logstash message V0 format, making them immediately compatible with Logstash parsing. Each log entry includes a timestamp, source host, message, and a fields object containing the log level, application name, and any additional logged fields.

     {
        "@timestamp": ${timeRFC3339},
        "@source_host": ${hostname},
        "@message": ${message},
        "@fields": {
           "level": ${levelLowercase},
           "application": ${appName}
           ... // logged field 1
           ... // logged field 2
           ...
        }
    }
  5. Extend libunftp with storage back-ends

    master

    libunftp allows you to implement custom storage back-ends to define how files are stored and retrieved. There is a variety of existing crates available on crates.io to extend functionality:

    • unftp-sbe-fatfs: Read-only access to FAT filesystem images.
    • unftp-sbe-fs: Local filesystem storage.
    • unftp-sbe-gcs: Google Cloud Storage.
    • unftp-sbe-iso: FTP access to ISO 9660 files.
    • unftp-sbe-opendal: Access to various services (S3, Azure Blob Storage, etc.) via Apache OpenDAL.
    • unftp-sbe-restrict: A wrapper to restrict FTP operations (authorization).
    • unftp-sbe-rooter: A wrapper to root a user to a specific home directory.
    • unftp-sbe-webdav: Translation between FTP and WebDAV.

    To create your own, refer to the API Documentation.

  6. Extend libunftp with authentication back-ends

    master

    libunftp allows you to implement custom authentication back-ends to manage user access. Existing implementations include:

    • unftp-auth-jsonfile: Authenticates against JSON text.
    • unftp-auth-pam: Authenticates via PAM (Pluggable Authentication Modules).
    • unftp-auth-rest: Authenticates by consuming an HTTP API.

    To create your own, refer to the API Documentation.

  7. How to use unFTP as a library or a server

    master

    unFTP can be consumed in two primary ways:

    1. As an embeddable library (libunftp): You can integrate the FTP functionality directly into your own Rust applications by using the libunftp crate.
    2. As a standalone server application (unFTP): You can run the pre-built server application out of the box, deploy it to Kubernetes, or use it as a base to craft your own custom server.
    // To use as a library in a Rust project, add libunftp to your Cargo.toml
    // [dependencies]
    // libunftp = "..."
  8. Compress JSON configuration files

    master

    To save space when managing a large number of users (e.g., when using Kubernetes ConfigMaps or Secrets), unFTP supports compressed configuration files. The --auth-json-path and --usr-json-path flags can point to files that are:

    1. Standard JSON.
    2. Gzip-compressed JSON.
    3. Gzip-compressed and Base64-encoded JSON.
  9. Use Google Cloud Storage (GCS) as a storage back-end

    master

    To use Google Cloud Storage instead of a local filesystem, set the storage back-end type (--sbe-type) to gcs.

    Configuration

    • --sbe-gcs-bucket: The name of your GCS bucket.
    • --sbe-gcs-root: The root path inside the bucket where FTP operations will occur.

    Authentication

    You can authenticate using one of two methods:

    1. Workload Identity: Set the --sbe-gcs-service-account argument.
    2. Service Account Key File: Set the --sbe-gcs-key-file argument pointing to your JSON key file.

    Example using a service account key file:

    unftp \
      --sbe-type=gcs \
      --sbe-gcs-bucket=mybucket \
      --sbe-gcs-root=ftp-base \
      --sbe-gcs-key-file=/path/to/file
  10. Configure unFTP log levels

    master

    By default, unFTP outputs logs to STDOUT with only Error and Warning levels. You can increase the verbosity using CLI arguments:

    • INFO level: Use the -v flag.
    • DEBUG level: Use the -vv flag.
    # Default (Error and Warning only)
    ➜ unftp
    
    # INFO level
    ➜ unftp -v
    
    # DEBUG level
    ➜ unftp -vv
  11. Generate secure PBKDF2 passwords with the key generator tool

    master

    Instead of storing plain-text passwords, you can use the bolcom/unftp-key-generator Docker image to generate secure PBKDF2 credentials. This produces a JSON object containing pbkdf2_salt, pbkdf2_key, and pbkdf2_iter fields, which should be used in your JSON credentials file instead of the password field.

    To generate a password for a specific user:

    1. Run the generator with the -u flag.
    2. Enter the username.
    3. Press ENTER to generate the password.

    To view advanced options, run the container with the -h flag.

    # Generate a secure password for a user
    docker run -ti bolcom/unftp-key-generator -u
    
    # View help/advanced options
    docker run -ti bolcom/unftp-key-generator -h
  12. Enable Proxy Protocol support in unFTP

    master

    To preserve client IP addresses when running unFTP behind a load balancer or reverse proxy, you can enable Proxy Protocol support. This allows the server to correctly identify the original client IP instead of the proxy's IP.

    Use the --proxy-external-control-port flag to specify the port used for external control communication when running in proxy protocol mode.

    unftp \
        --proxy-external-control-port=2121