项目作者: fclairamb

项目描述 :
golang ftp server library
高级语言: Go
项目地址: git://github.com/fclairamb/ftpserverlib.git
创建时间: 2016-09-25T12:05:29Z
项目社区:https://github.com/fclairamb/ftpserverlib

开源协议:MIT License

下载


Golang FTP Server library

Go version
Release
Build
codecov
Go Report Card
GoDoc
Mentioned in Awesome Go

This library allows to easily build a simple and fully-featured FTP server using afero as the backend filesystem.

If you’re interested in a fully featured FTP server, you should use sftpgo (fully featured SFTP/FTP server) or ftpserver (basic FTP server).

Current status of the project

Features

  • Uploading and downloading files
  • Directory listing (LIST + MLST)
  • File and directory deletion and renaming
  • TLS support (AUTH + PROT)
  • File download/upload resume support (REST)
  • Passive socket connections (PASV and EPSV commands)
  • Active socket connections (PORT and EPRT commands)
  • IPv6 support (EPSV + EPRT)
  • Small memory footprint
  • Clean code: No sleep, no panic, no global sync (only around control/transfer connection per client)
  • Uses only 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
    • HASH - Hashing of files
    • AVLB - Available space
    • COMB - Combine files

Quick test

The easiest way to test this library is to use ftpserver.

The driver

The simplest way to get a good understanding of how the driver shall be implemented is to look at the tests driver.

The base API

The API is directly based on afero.

  1. // MainDriver handles the authentication and ClientHandlingDriver selection
  2. type MainDriver interface {
  3. // GetSettings returns some general settings around the server setup
  4. GetSettings() (*Settings, error)
  5. // ClientConnected is called to send the very first welcome message
  6. ClientConnected(cc ClientContext) (string, error)
  7. // ClientDisconnected is called when the user disconnects, even if he never authenticated
  8. ClientDisconnected(cc ClientContext)
  9. // AuthUser authenticates the user and selects an handling driver
  10. AuthUser(cc ClientContext, user, pass string) (ClientDriver, error)
  11. // GetTLSConfig returns a TLS Certificate to use
  12. // The certificate could frequently change if we use something like "let's encrypt"
  13. GetTLSConfig() (*tls.Config, error)
  14. }
  15. // ClientDriver is the base FS implementation that allows to manipulate files
  16. type ClientDriver interface {
  17. afero.Fs
  18. }
  19. // ClientContext is implemented on the server side to provide some access to few data around the client
  20. type ClientContext interface {
  21. // Path provides the path of the current connection
  22. Path() string
  23. // SetDebug activates the debugging of this connection commands
  24. SetDebug(debug bool)
  25. // Debug returns the current debugging status of this connection commands
  26. Debug() bool
  27. // Client's ID on the server
  28. ID() uint32
  29. // Client's address
  30. RemoteAddr() net.Addr
  31. // Servers's address
  32. LocalAddr() net.Addr
  33. // Client's version can be empty
  34. GetClientVersion() string
  35. // Close closes the connection and disconnects the client.
  36. Close() error
  37. // HasTLSForControl returns true if the control connection is over TLS
  38. HasTLSForControl() bool
  39. // HasTLSForTransfers returns true if the transfer connection is over TLS
  40. HasTLSForTransfers() bool
  41. // GetLastCommand returns the last received command
  42. GetLastCommand() string
  43. // GetLastDataChannel returns the last data channel mode
  44. GetLastDataChannel() DataChannel
  45. }
  46. // Settings define all the server settings
  47. type Settings struct {
  48. Listener net.Listener // (Optional) To provide an already initialized listener
  49. ListenAddr string // Listening address
  50. PublicHost string // Public IP to expose (only an IP address is accepted at this stage)
  51. PublicIPResolver PublicIPResolver // (Optional) To fetch a public IP lookup
  52. PassiveTransferPortRange *PortRange // (Optional) Port Range for data connections. Random if not specified
  53. ActiveTransferPortNon20 bool // Do not impose the port 20 for active data transfer (#88, RFC 1579)
  54. IdleTimeout int // Maximum inactivity time before disconnecting (#58)
  55. ConnectionTimeout int // Maximum time to establish passive or active transfer connections
  56. DisableMLSD bool // Disable MLSD support
  57. DisableMLST bool // Disable MLST support
  58. DisableMFMT bool // Disable MFMT support (modify file mtime)
  59. Banner string // Banner to use in server status response
  60. TLSRequired TLSRequirement // defines the TLS mode
  61. DisableLISTArgs bool // Disable ls like options (-a,-la etc.) for directory listing
  62. DisableSite bool // Disable SITE command
  63. DisableActiveMode bool // Disable Active FTP
  64. EnableHASH bool // Enable support for calculating hash value of files
  65. DisableSTAT bool // Disable Server STATUS, STAT on files and directories will still work
  66. DisableSYST bool // Disable SYST
  67. EnableCOMB bool // Enable COMB support
  68. DefaultTransferType TransferType // Transfer type to use if the client don't send the TYPE command
  69. // ActiveConnectionsCheck defines the security requirements for active connections
  70. ActiveConnectionsCheck DataConnectionRequirement
  71. // PasvConnectionsCheck defines the security requirements for passive connections
  72. PasvConnectionsCheck DataConnectionRequirement
  73. }

Extensions

There are a few extensions to the base afero APIs so that you can perform some operations that aren’t offered by afero.

Pre-allocate some space

  1. // ClientDriverExtensionAllocate is an extension to support the "ALLO" - file allocation - command
  2. type ClientDriverExtensionAllocate interface {
  3. // AllocateSpace reserves the space necessary to upload files
  4. AllocateSpace(size int) error
  5. }

Get available space

  1. // ClientDriverExtensionAvailableSpace is an extension to implement to support
  2. // the AVBL ftp command
  3. type ClientDriverExtensionAvailableSpace interface {
  4. GetAvailableSpace(dirName string) (int64, error)
  5. }
  1. // ClientDriverExtensionSymlink is an extension to support the "SITE SYMLINK" - symbolic link creation - command
  2. type ClientDriverExtensionSymlink interface {
  3. // Symlink creates a symlink
  4. Symlink(oldname, newname string) error
  5. // SymlinkIfPossible allows to get the source of a symlink (but we don't need for now)
  6. // ReadlinkIfPossible(name string) (string, error)
  7. }

Compute file hash

  1. // ClientDriverExtensionHasher is an extension to implement if you want to handle file digests
  2. // yourself. You have to set EnableHASH to true for this extension to be called
  3. type ClientDriverExtensionHasher interface {
  4. ComputeHash(name string, algo HASHAlgo, startOffset, endOffset int64) (string, error)
  5. }

History of the project

I wanted to make a system which would accept files through FTP and redirect them to something else. Go seemed like the obvious choice and it seemed there was a lot of libraries available but it turns out none of them were in a useable state.