mod_proxy
The purpose of the mod_proxy
module is to provide FTP proxying
capabilities in proftpd
, both reverse (or "gateway")
proxying and forward proxying.
Installation instructions are discussed here.
Note that mod_proxy
requires ProFTPD 1.3.6rc2 or later.
Detailed notes on best practices for using this module are
here.
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/).
This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).
The most current version of mod_proxy
can be found at:
https://github.com/Castaglia/proftpd-mod_proxy.git
Please contact TJ Saunders <tj at castaglia.org> with any questions, concerns, or suggestions regarding this module.
2015-08-24: Thanks to Michael Toth <mtoth at queldor.net>
for helping test multiple iterations of mod_proxy
with IIS
servers.
<VirtualHost>
, <Global>
The ProxyDataTransferPolicy
directive configures the data
transfer policy that mod_proxy
uses when performing
data transfers (e.g. file uploads/downloads, directory listings) with
the backend/destination server.
The currently supported policies are:
client
This policy indicates that mod_proxy
will use whatever
the connected client uses. Thus if the client sends PORT
,
mod_proxy
will send PORT
to the
backend/destination server.
This is the recommended policy in most cases.
active
Regardless of the commands sent by the client, mod_proxy
will use only active data transfers (i.e. using
PORT
commands) with the backend/destination server.
passive
Regardless of the commands sent by the client, mod_proxy
will use only passive data transfers (i.e. using
PASV
commands) with the backend/destination server.
PASV
Regardless of the commands sent by the client, mod_proxy
will use only PASV
commands with the backend/destination
server.
PORT
Regardless of the commands sent by the client, mod_proxy
will use only PORT
commands with the backend/destination
server.
EPSV
Regardless of the commands sent by the client, mod_proxy
will use only EPSV
commands with the backend/destination
server.
EPRT
Regardless of the commands sent by the client, mod_proxy
will use only EPRT
commands with the backend/destination
server.
The ProxyDatastore
directive configures the type of
datastore that mod_proxy
uses for persistence. The currently
supported datastore types are:
Note that the Redis type also requires the info
parameter, namely a prefix for all of the Redis keys. This prefix must
be different/unique among all of your mod_proxy
servers using
that Redis server/cluster; the prefix is used to keep all of the data
for this server separate from all other servers. For example:
<IfModule mod_proxy.c> ... <IfModule mod_redis.c> # Use our IP address as our prefix ProxyDatastore Redis 1.2.3.4. </IfModule> </IfModule>
<VirtualHost>
, <Global>
The ProxyDirectoryListPolicy
directive configures the directory
list policy that mod_proxy
uses when performing
directory lists with the backend/destination server.
The currently supported policies are:
client
This policy indicates that mod_proxy
will use whatever
the connected client uses. Thus if the client sends MLSD
,
mod_proxy
will send MLSD
to the
backend/destination server.
This is the recommended policy in most cases.
LIST
This policy instructs mod_proxy
to use the LIST
command with the backend/destination server, regardless of the command
used by the client. The mod_proxy
module then handles any
reformatting of the LIST
response into the response needed
by the client. For example, if the client sends MLSD
but the
backend/destination server does not support this command,
mod_proxy
will send LIST
instead, and translate
the backend format into the client-requested format.
The current implementation of this policy handles LIST-<MLSD
translations only.
UseSlink
Use this option to have mod_proxy
use the broken
"OS.unix=slink" syntax, preferred by FTP clients such as FileZilla, for
indicating symlinks, rather than the more correct "OS.unix=symlink"
syntax. See
Bug#3318 for
a more detailed discussion.
<VirtualHost>
, <Global>
The ProxyEngine
directive toggles the support for proxying by
mod_proxy
. This is usually used inside a
<VirtualHost>
section to enable proxying of FTP sessions for
a particular virtual host. By default mod_proxy
is disabled for
both the main server and all configured virtual hosts.
<Class>
The ProxyForwardEnabled
directive determines whether a client
can use mod_proxy
for forward proxying, based on that client's
class.
By default, mod_proxy
rejects any forward proxy request from
any client, with the exception of clients connecting from
RFC 1918 addresses:
192.168.0.0/16 172.16.0.0/12 10.0.0.0/8This is done as a security measure: open/unrestricted proxy servers are dangerous both to your network and to the Internet at large. Thus to make it possible for clients to use your server for forward proxying, they must be explicitly enabled to do so.
Example:
<Class forward-proxy> From 1.2.3.4/12 # Allow clients from this class to use FTP forward proxying ProxyForwardEnabled on </Class>
See also: ProxyForwardTo
<VirtualHost>
, <Global>
The ProxyForwardMethod
directive configures the method
that clients can use for requesting forward proxying. Some methods require
that the client authenticate to the proxy first, and then separately
authenticate to the destination server; these methods differ on just when
the client specifies the destination server. Other methods do not require
proxy authentication. There are many variations on a theme with these methods.
The currently supported methods are:
proxyuser,user@host
This method indicates that proxy authentication is required. The
client first authenticates to the proxy via USER/PASS
commands:
USER proxy-user PASS proxy-passwdThen the client authenticates again, this time including the address (and optionally port) of the destination server as part of the second
USER
command:
USER real-user@ftp.example.com PASS real-passwdThe
mod_proxy
module will remove the destination address
portion of the second USER
command before proxying it to
the destination server.
proxyuser@host,user
This method indicates that proxy authentication is required. The
client first authenticates to the proxy via USER/PASS
commands;
note that the destination address (and optionally port) is included as part
of the first USER
command:
USER proxy-user@ftp.example.com PASS proxy-passwdThen the client authenticates again, this time sending the
USER/PASS
commands to authenticate to the destination server:
USER real-user PASS real-passwd
user@host
This methods indicates that no proxy authentication is used. The
client indicates the destination address (and optionally port) of the
server as part of the USER
command:
USER real-user@ftp.example.com PASS real-passwdThe
mod_proxy
module will remove the destination address
portion of the USER
command before proxying it to the
destination server.
user@sni
This methods indicates that no proxy authentication is used. The client indicates the destination address (and optionally port) of the server as part of a TLS SNI (Server Name Indication) portion of a TLS session:
AUTH TLS handshake with SNI USER real-user PASS real-passwd
Configuring the FTP client's proxy settings to match the above methods varies greatly, depending on the FTP client.
<VirtualHost>
, <Global>
The ProxyForwardTo
directive is used to restrict which
hosts/domains can be requested for forward proxying. The destination host/port
for forward proxying must match the configured pattern
regular expression, or the forward proxying request will fail.
The optional flags parameter, if present, modifies how the given pattern will be evaludated. The supported flags are:
ProxyForwardTo
limits the destination hosts to which
clients can request forward proxying; by contrast,
ProxyForwardEnabled
controls
forward proxying based on where clients connect from.
Example:
# Limit forward proxying to specific host and port ProxyForwardTo ^ftp.example.com:21$
<VirtualHost>
, <Global>
The ProxyLog
directive is used to specify a log file for
mod_proxy
's reporting on a per-server basis. The path
parameter given must be the full path to the file to use for logging.
Note that this path must not be to a world-writable directory and,
unless AllowLogSymlinks
is explicitly set to on
(generally a bad idea), the path must not be a symbolic link.
<VirtualHost>
, <Global>
The ProxyOptions
directive is used to configure various optional
behavior of mod_proxy
. For example:
ProxyOptions UseProxyProtocolV1
The currently implemented options are:
AllowForeignAddress
The AllowForeignAddress
directive controls the policy for
frontend data transfer requests from clients connecting to the proxy
server; it does not apply to backend data transfer requests.
For those, you will want to use this AllowForeignAddress
option:
# Allow for cases where the backend server tells us to use a different IP # address for data transfers than the IP address to which mod_proxy connected. ProxyOptions AllowForeignAddress
Note that the IgnoreForeignAddress
option takes precedence
over this option.
IgnoreForeignAddress
Use this option to tell the mod_proxy
module to always
use the same IP address for passive data transfers to the backend server as
used for the control connection, ignoring any different IP address that
the backend server may provide in its PASV
response.
This option may be needed in cases where you see backend data transfers fail with errors logged such as:
unable to connect to 172.16.1.2#8200: Network unreachable unable to connect to 172.16.2.2#8200: Connection refusedExample:
# When the backend server tells us to use a different IP address for data # transfers than the IP address to which mod_proxy connected, ignore that # different IP address and use the original initial IP address. ProxyOptions IgnoreForeignAddress
Note that this option takes precedence over the
AllowForeignAddress
option.
ShowFeatures
When reverse proxying, mod_proxy
defaults to not responding to
the FTP FEAT
command, which is used to determine the supported
features/capabilities of the FTP server; this is done to prevent leaking
of information about internal FTP servers to the outside world. However,
some clients rely on the FEAT
data. For such clients/use
cases, use this option to tell mod_proxy
to proxy the
FEAT
command/response to the backend server.
UseDirectDataTransfers
The mod_proxy
module will, by default, proxy all data transfers
through the proxy server. Some sites may wish to have the FTP data
transfers occur directly between the frontend client and the backend server,
to avoid the latency/overhead of the proxying. Use this option to
enable these direct data transfers (akin to Direct Server
Return, or DSR), for both forward and reverse proxy roles:
# Enable data transfers directly from frontend client to/from backend server ProxyOptions UseDirectDataTransfers
UseProxyProtocolV1
When mod_proxy
connects to the backend/destination server,
use the PROXY
V1 protocol, sending the human-readable PROXY
command to the destination server. This allows backend servers to implement
access controls/logging, based on the IP address of the connecting client.
The mod_proxy_protocol
ProFTPD module can be used to handle the PROXY
command on
the receiving side, i.e. when using proftpd
as the
backend/destination server.
Note: do not use this option unless the backend server
does support the PROXY
V1 protocol. Otherwise, the
PROXY
protocol message will only confuse the backend server,
possibly leading to connection/login failures.
UseProxyProtocolV2
When mod_proxy
connects to the backend/destination server,
use the PROXY
V2 protocol, sending a binary-encoded "PROXY" command
to the destination server. This allows backend servers to implement
access controls/logging, based on the IP address of the connecting client.
The mod_proxy_protocol
ProFTPD module can be used to handle the "PROXY" command on the receiving
side, i.e. when using proftpd
as the
backend/destination server.
Note: do not use this option unless the backend server
does support the PROXY
V2 protocol. Otherwise, the
"PROXY" protocol message will only confuse the backend server, possibly
leading to connection/login failures.
UseProxyProtocolV2TLVs
When mod_proxy
is configured to use the PROXY protocol V2,
via the UseProxyProtocolV2
option, this option tells
mod_proxy
to send additional data as Type/Length/Value (TLV).
These TLVs include:
mod_unique_id
is present/used)
Note: use of the UseProxyProtocolV2
option is also
required for the TLVs to be sent.
UseReverseProxyAuth
When reverse proxying, mod_proxy
delegates user authentication
to the selected backend server. However, there are some sites which need
to centralize user authentication in the proxy; use this option to require
proxy authentication for such cases. Note that this option
only pertains to reverse proxy connections; proxy authentication
when forward proxying is determined by the ProxyForwardMethod
directive.
<VirtualHost>
, <Global>
The ProxyRetryCount
directive configures the number of times
mod_proxy
will attempt to connect to the backend/destination
server. The default is 5 attempts.
<VirtualHost>
, <Global>
The ProxyReverseConnectPolicy
directive configures the
policy that mod_proxy
will use for selecting the backend
server when reverse proxying.
The currently supported policies are:
LeastConns
Select the backend server with the lowest number of proxied connections.
LeastResponseTime
Select the backend server with the least response time; this is determined based on the connect time to the backend server, and its number of current connections.
PerGroup
Select a backend server based on the primary group of the authenticated
USER
name used by the connecting client; any future
connections using that same USER
name will be routed to the
same backend server.
Note: use of this ProxyReverseConnectPolicy
also
requires use of the UseReverseProxyAuth
ProxyOption
, as authenticating the given USER
name is required for discovering the primary group of that user.
PerHost
Select a backend server based on the IP address of the connecting client; any future connections from that IP address will be routed to the same backend server.
PerUser
Select a backend server based on the USER
name used by the
connecting client; any future connections using that same USER
name will be routed to the same backend server.
Random
Randomly select any of the backend servers.
RoundRobin
Select the next backend server in the list.
Shuffle
Similar to the Random
policy, except the selection happens
from the not-yet-chosen backend servers. This means that all
backend servers will eventually be used evenly, just in a random order.
<VirtualHost>
, <Global>
The ProxyReverseServers
directive configures the list of servers
to be used as the backend servers for reverse proxying.
Each server must be configured as a URL. Only the "ftp" and "ftps" schemes are currently supported. If not specified, the port will be 21. IPv6 addresses must be enclosed within square brackets. Thus, for example, the following are all valid URLs:
ftp://ftp1.example.com:2121 ftp://1.2.3.4 ftp://[::ffff:6.7.8.9]:2121 ftps://ftp2.example.com ftps://ftp3.example.com:990And using them all in the configuration would look like:
ProxyReverseServers ftp://ftp1.example.com:2121 ftps://1.2.3.4 ftp://[::ffff:6.7.8.9]:2121
The backend servers can also be discovered via DNS SRV
or TXT
records, using SRV/TXT
URL scheme variants, e.g.:
# Discover backend addresses via DNS SRV records ftp+srv://_ftp._tcp.castaglia.org # Discover backend addresses via DNS TXT records (which must be an FTP URL) ftp+txt://castaglia.orgThese
SRV/TXT
URL scheme variations also apply to FTPS URLs.
Note that any explicit port numbers provided in URLs using these
SRV/TXT
scheme variants will be ignored; the actual port
numbers to use will be discovered from the SRV
and TXT
DNS records.
The backend servers can also be contained in a list in a JSON file, e.g.:
[ "ftp://ftp1.example.com:2121", "ftp://[::ffff:6.7.8.9]:2121" ]You then only need to configure the path to that JSON file:
ProxyReverseServers file:/path/to/backends.json
Note that mod_proxy
has strict requirements for the
permissions on ProxyReverseServers
files. The configured file
must not be world-writable, since that would allow any user
on the system to modify the file, directing proxied connections anywhere else.
If a world-writable ProxyReverseServers
file is found, you will
see the following error message logged:
unable to use world-writable ProxyReverseServers '/opt/proxy/reverse.json' (perms 0666): Operation not permittedIn addition, the directory containing the
ProxyReverseServers
file cannot be world-writable, either. Even
if the file itself is not world-writable, being in a world-writable directory
means that any user on the system can delete that file, and write a new
file. When a world-writable directory is found, the following error is logged:
unable to use ProxyReverseServers '/opt/proxy/reverse.json' from world-writable directory '/opt/proxy' (perms 0777): Operation not permitted
The backend servers can also be provided from an external SQL database,
queried by mod_proxy
via SQLNamedQuery
. For example,
assuming a schema such as this:
CREATE TABLE proxy_user_servers ( user_name TEXT, url TEXT ); CREATE INDEX proxy_user_servers_name_idx ON proxy_user_servers (user_name);where url contains URLs, e.g. "ftp://1.2.3.4:21". Then you would configure
mod_proxy
to query for those per-user backend URLs
using ProxyReverseServers
like this:
<IfModule mod_sql.c> ... SQLNamedQuery get-user-servers SELECT "url FROM proxy_user_servers WHERE user_name = %{0}" </IfModule> ProxyRole reverse ProxyReverseConnectPolicy PerUser ProxyReverseServers sql:/get-user-servers
Given that mod_proxy
uses SQLite, does that mean that the table
used for storing these per-user URLs must be SQLite? No. The
use of SQLNamedQuery
means that any database, supported
by mod_sql
, can be used.
<VirtualHost>
, <Global>
The ProxyRole
directive configures whether mod_proxy
will perform forward or reverse proxying. The list of supported roles
are thus:
forward
Perform forward proxying.
reverse
Perform reverse proxying.
Note that the ProxyRole
directive is required
for mod_proxy
to function. If this directive is not configured,
connections to mod_proxy
will fail.
<VirtualHost>
, <Global>
The ProxySFTPCiphers
directive is used to specify the list of
cipher algorithms that mod_proxy
should use when connecting to
backend SSH servers. The current list of supported cipher algorithms is, in
the default order of preference:
The "none" cipher (i.e. no encryption) will not be presented to
the server by default; any sites which wish to use "none" will have to
explicitly configure it via ProxySFTPCiphers
.
Note that CTR mode ciphers (e.g. the aes128-ctr
,
aes192-ctr
, and aes256-ctr
ciphers) are recommended.
Any CBC mode cipher allows for the possibility of an attack which causes
several bits of plaintext to be leaked; the attack is described
here.
This attack is on the SSH2 protocol design itself; any SSH2 implementation
which conforms to the RFCs will have this weakness.
In general, there is no need to use this directive unless only one specific cipher must be used.
<VirtualHost>
, <Global>
The ProxySFTPCompression
directive enables the use of zlib
compression of the payload of SSH2 packets. This can make for smaller packets,
but require more CPU time to compress/uncompress the data.
The delayed parameter tells mod_proxy
to support a custom
extension used by OpenSSH, where compression is not actually enabled until
after the client has successfully authenticated.
<VirtualHost>
, <Global>
The ProxySFTPDigests
directive is used to specify the list of
MAC digest algorithms that mod_proxy
should use when connecting to
backend SSH servers. The current list of supported MAC algorithms is:
The following list of algorithms are supported, but not
presented to servers by default. These algorithms must be explicitly
configured via ProxySFTPDigests
to be available for use by servers:
The "none" MAC (i.e. no MAC) will not be presented to the server
by default; any sites which wish to use "none" will have to explicitly
configure it via ProxySFTPDigests
.
In general, there is no need to use this directive unless only one specific MAC algorithm must be used.
<VirtualHost>
, <Global>
The ProxySFTPHostKey
directive configures the path to a host key
file. The mod_proxy
module uses the keys thus configured for
"hostbased" user authentication to backend SSH servers.
You can use either an RSA key, a DSA key, and/or ECDSA keys. These could be the exact same host key files as used by your SSH server, e.g.:
<IfModule mod_sftp.c> ... SFTPHostKey /etc/ssh_host_dsa_key SFTPHostKey /etc/ssh_host_rsa_key SFTPHostKey /etc/ssh_host_ecdsa_key SFTPHostKey /etc/ssh_host_ed25519_key </IfModule> <IfModule mod_proxy.c> ProxyEngine on .. ProxySFTPHostKey /etc/ssh_host_dsa_key ProxySFTPHostKey /etc/ssh_host_rsa_key ProxySFTPHostKey /etc/ssh_host_ecdsa_key ProxySFTPHostKey /etc/ssh_host_ed25519_key </IfModule>
The ProxySFTPHostKey
directive can also be used to load host keys
from an SSH agent such as OpenSSH's ssh-agent
. For example:
# Load all of the keys from the ssh-agent configured for proxy use ProxySFTPHostKey agent:%{env:SSH_AUTH_SOCK}Using an SSH agent for storing host keys allows for configurations where the host keys are not stored on files on the server system, e.g. the keys can be loaded into the SSH agent from a PKCS#11 token.
<VirtualHost>
, <Global>
The ProxySFTPKeyExchanges
directive is used to specify the list of
key exchange algorithms that mod_proxy
should use when connecting
to backend SSH servers. The current list of supported key exchange algorithms
is:
diffie-hellman-group1-sha1
are presented to the server, in
the above order, during the key exchange.
Note that the diffie-hellman-group1-sha1
key exchange
algorithm uses a weak hardcoded Diffie-Hellman group, and thus is not
enabled by default. To enable this key exchange algorithm, you must
configure the ProxySFTPKeyExchanges
list to explicitly
include this algorithm, or use the following in your configuration:
ProxySFTPOptions AllowWeakDH
In general, there is no need to use this directive unless only one specific key exchange algorithm must be used.
<VirtualHost>
, <Global>
The ProxySFTPOptions
directive is used to configure various
optional SSH-specific behavior of mod_proxy
.
For example:
ProxySFTPOptions AllowWeakDH
The currently implemented options are:
AllowWeakDH
The mod_proxy
module will not use Diffie-Hellman groups of less
than 2048 bits, due to weaknesses
that can downgrade the security of an SSH session. If for any reason
your SFTP/SCP servers require smaller Diffie-Hellman groups, then
use this option.
NoExtensionNegotiation
By default, mod_proxy
will offer/support the SSH extension
negotiation, defined by
RFC 8308. Use this
option to disable support for extension negotiations.
NoHostkeyRotation
By default, mod_proxy
will offer/support the OpenSSH
hostkey rotation extensions, "hostkeys-00@openssh.com" and
"hostkeys-prove-00@openssh.com". Use this option to disable support for
these custom OpenSSH extensions.
NoStrictKex
By default, mod_proxy
will honor/support the OpenSSH
"strict KEX" mode extension, "kex-strict-c-v00@openssh.com" and
"kex-strict-s-v00@openssh.com". Use this option to disable support for
these custom OpenSSH extensions.
OldProtocolCompat
Older servers identity their protocol versions as "1.99", rather than as
"2.0". By default, mod_proxy
will refuse to handle connections
to such servers. To enable compatibility with these servers (which
tend to be derived from ssh.com/Tectia code), use this option.
Note that this option automatically enables the
PessimisticKexinit
ProxySFTPOption as well.
PessimisticKexinit
As described here, the mod_proxy
module tries to reduce the connection latency by optimistically sending
the KEXINIT
key exchange message. However, some SSH servers
cannot handle this behavior. Use this option to disable the optimistic
sending of the KEXINIT
message.
<VirtualHost>
, <Global>
The ProxySFTPPassPhraseProvider
directive is used to specify an
external program which will be called, when mod_proxy
starts up,
for each encrypted ProxySFTPHostKey
file. The program will be
invoked with two command-line arguments, passed on stdin
to the
program:
servername:portnumber filewhere
servername:portnumber
indicates the
server using that encrypted certificate key, and file indicates the
host key file in question. The program then must print the corresponding
passphrase for the key to stdout
.
The intent is that this external program can perform any security checks necessary, to make sure that the system is not compromised by an attacker, and only when these checks pass successfully will the passphrase be provided. These security checks, and the way the passphrase is determined, can be as complex as you like.
Example:
ProxySFTPPassPhraseProvider /etc/ftpd/proxy/get-ssh-passphrase
<VirtualHost>
, <Global>
The ProxySFTPServerAlive
directive configures
mod_proxy
to send messages to a server, through the encrypted
channel, to request a response from the server. If count server alive
messages are sent without receiving any response messages from the server, the
client will disconnect. The interval indicates how much time, in
seconds, that mod_proxy
waits for data from the server before
sending a server alive message.
For example, using:
ProxySFTPServerAlive 3 15will cause an unresponsive server to be disconnected after approximately 45 seconds.
<VirtualHost>
, <Global>
The ProxySFTPServerMatch
directive is used to tune some of the
SSH2/SFTP values based on the connected server, for better interoperability
with those servers. The pattern parameter specifies a POSIX regular
expression which will be matched against the connected server's SSH version
banner. If the server's banner version matches pattern, then
the configured keys/values are used for that session.
The currently supported SSH2/SFTP keys which can be tuned via
ProxySFTPServerMatch
are:
<VirtualHost>
, <Global>
The ProxySFTPVerifyServer
directive tells mod_proxy
whether to verify whether the host keys presented by backend SSH servers have
changed.
When mod_proxy
connects to a backend SSH server for the very first
time, its hostkey will be recorded. The next time mod_proxy
connects, the hostkey presented will be compared to the previously recorded
hostkey. When ProxySFTPVerifyServer
is on, any hostkey
mismatches will be logged.
<VirtualHost>
, <Global>
The ProxySourceAddress
directive configures the address
(or device name) of a network interface on the host machine, to
be used when connecting to the backend/destination server. This directive
is most useful on a multi-homed (or DMZ) host; frontend connections can
be received on one network interface, and the backend connections can use
a different network interface. Imagine e.g. separate WAN/LAN interfaces
on a proxying host.
The ProxyTables
directive is used to specify a directory that
mod_proxy
will use for storing its database files; these files
are used for tracking the various load balancing/healthcheck statistics used
for proxying.
Note that the ProxyTables
directive is required
for mod_proxy
to function. If this directive is not configured,
connections to mod_proxy
will fail.
<VirtualHost>
, <Global>
The ProxyTimeoutConnect
directive configures the amount of time
that mod_proxy
will wait for the backend/destination server to
accept a TCP connection, before giving up.
Note that if there are many different backend/destination servers to try
(due to e.g. ProxyRetryCount
), and if those
backend servers are slow, the connecting client might itself see connection
timeouts to mod_proxy
. To guard against such slow backend
servers, a more aggressively short timeout can be used:
ProxyTimeoutConnect 1sec
<VirtualHost>
, <Global>
The ProxyTimeoutLinger
directive configures the amount of time
that mod_proxy
will wait (lingering), after receiving
all of the data on the data transfer connection to the backend server, for the
explicit "end of transfer" response from the backend server, before giving up.
<VirtualHost>
, <Global>
The ProxyTLSCACertificateFile
directive configures one file where
you can assemble the certificates of Certification Authorities (CA) which will
be used to verify the servers' certificates. Such a file is merely the
concatenation of the various PEM-encoded CA certificates. This directive can
be used in addition to, or as an alternative for,
ProxyTLSCACertificatePath
.
Example:
ProxyTLSCACertificateFile /etc/ftpd/cacerts.pem
Note that the location of CA certificates is required for
mod_proxy
's TLS support; verification of server certificates
is required for secure connections to backend/destination servers. For
this reason, mod_proxy
ships with its own default
ProxyTLSCACertificateFile
, which is generated using libcurl
's mk-ca-bundle.pl
script:
$ lib/mk-ca-bundle.pl -u cacerts.pem
<VirtualHost>
, <Global>
The ProxyTLSCACertificatePath
directive sets the directory for the
certificates of Certification Authorities (CAs); these are used to verify the
server certificates presented. This directive may be used in addition to, or
as alternative for, ProxyTLSCACertificateFile
.
The files in the configured directory have to be PEM-encoded, and are accessed
through hash filenames. This means one cannot simply place the CA certificates
there: one also has to create symbolic links named hash-value.N. The
c_rehash
utility that comes with OpenSSL can be used to create
the necessary symlinks.
Example:
ProxyTLSCACertificatePath /etc/ftpd/cacerts/
<VirtualHost>
, <Global>
The ProxyTLSCARevocationFile
directive configures one file that can
contain the Certificate Revocation Lists (CRL) of Certification Authorities
(CA); these CRLs are used during the verification of server certificates. Such
a file is merely the concatenation of the various PEM-encoded CRL files. This
directive can be used in addition to, or as an alternative for,
ProxyTLSCARevocationPath
.
Example:
ProxyTLSCARevocationFile /etc/ftpd/cacrls.pem
<VirtualHost>
, <Global>
The ProxyTLSCARevocationPath
directive sets the directory for the
Certificate Revocation Lists (CRL) of Certification Authorities (CAs); these
are used during the verification of server certificates. This directive may
be used in addition to, or as alternative for,
ProxyTLSCARevocationFile
.
The files in the configured directory have to be PEM-encoded, and are accessed
through hash filenames. This means one cannot simply place the CRLs there:
one also has to create symbolic links named hash-value.N. The
c_rehash
utility that comes with OpenSSL can be used to create
the necessary symlinks.
Example:
ProxyTLSCARevocationPath /etc/ftpd/cacrls/
<VirtualHost>
, <Global>
The ProxyTLSCertificateFile
directive points to the PEM-encoded
file containing the client certificate file, and optionally also
the corresponding private key. Note that this directive is only
needed for backend/target FTPS servers which require client authentication.
Example:
ProxyTLSCertificateFile /etc/ftpd/client-cert.pem
<VirtualHost>
, <Global>
The ProxyTLSCertificateKeyFile
directive points to the PEM-encoded
file containing the client certificate file, and optionally also
The ProxyTLSCertificateKeyFile
directive points to the PEM-encoded
private key file for the client certificate indicated by
ProxyTLSCertificateFile
. If the private key is not combined with
the certificate in the ProxyTLSCertificateFile
, use this additional
directive to point to the file with the standalone private key. When
ProxyTLSCertificateFile
is used and the file contains both the
certificate and the private key, this directive need not be used. However,
this practice is strongly discouraged. Instead we recommend you to separate
the certificate and the private key.
<VirtualHost>
, <Global>
The ProxyTLSCipherSuite
directive configures the list of
acceptable SSL/TLS ciphersuites to use for backend SSL/TLS connections. The
syntax is that of the OpenSSL ciphers
command, e.g.:
$ openssl ciphers -v <cipher-list>may be used to list all of the ciphers and the order described by a specific <cipher-list>.
If the SSL library supports TLSv1.3 (e.g. OpenSSL-1.1.1 and later), the protocol specifier "TLSv1.3" can be used to configure the cipher suites for that protocol:
# Configure TLSv1.3 ciphersuites ProxyTLSCipherSuite TLSv1.3 TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256
<VirtualHost>
, <Global>
The ProxyTLSEngine
directive configures the use of SSL/TLS for
backend FTP connections. Note that SSL/TLS support
requires the presence/use of the mod_tls
ProFTPD module.
The supported values are:
Use of SSL/TLS is required; backend servers which do not support SSL/TLS or which fail the SSL/TLS handshake will cause the proxied session to be closed.
Use of SSL/TLS is disabled; backend servers which do support SSL/TLS will be ignored, and only FTP will be used.
Use of SSL/TLS will be automatically used if the backend server
supports SSL/TLS (via AUTH TLS
in its FEAT
response). If the SSL/TLS handshake fails, the backend connection will
proceed using plain FTP.
Note: this is the default behavior in mod_proxy
.
Use of SSL/TLS to the backend server will attempt to match the SSL/TLS usage of the frontend client. Thus if the frontend client uses explicit FTPS, then explicit FTPS will be attempted with the backend; similarly for implicit FTPS. And if the frontent client does not use FTPS, then SSL/TLS will not be used for the backend connection.
<VirtualHost>
, <Global>
The ProxyTLSOptions
directive is used to configure various
optional SSL/TLS behavior of mod_proxy
.
Example:
ProxyTLSOptions EnableDiags
The currently implemented options are:
AllowWeakSecurity
Sets the cryptographic security level to "zero", meaning that any/all ciphers and key sizes are permitted. This option allows for the best interoperability with any FTPS server, but is not recommended. Use only when necessary.
EnableDiags
Sets callbacks in the OpenSSL library such that a lot of
SSL/TLS protcol information is logged to the
ProxyLog
file. This option is
very useful when debugging strange interactions with FTPS servers.
NoSessionCache
By default, when using SSL/TLS, mod_proxy
will cache
the negotiated SSL sessions in its local database, for reuse in enabling
SSL session resumption in future connections to those hosts. Use this
option to disable use of session caching if/when needed.
NoSessionTickets
By default, when using SSL/TLS, mod_proxy
will cache
any session tickets
offered by the server in its local database, for reuse in enabling
SSL session resumption in future connections to those hosts. Use this
option to disable use of session tickets if/when needed.
<VirtualHost>
, <Global>
The ProxyTLSPreSharedKey
directive is used to configure a
pre-shared key (PSK), for use in
TLS-PSK ciphersuites. Each
PSK has an identity (a string/name used by clients to request the use
of that PSK), and the actual key data. The key data may be encoded in different
ways; the ProxyTLSPreSharedKey
directive requires that the data be
hex-encoded, as indicated in the key-info parameter.
The key-info parameter is comprised of the type of encoding used for
the key data, and the full path to the key file. Only "hex" encoding is
supported right now. Thus an example ProxyTLSPreSharedKey
directive would be:
ProxyTLSPreSharedKey MyPSK hex:/path/to/psk.keyThe configured file cannot be world-readable or world-writable; the
mod_proxy
module will skip/ignore such insecure permissions.
To generate this shared key (which is just a randomly generated bit of data), you can use:
$ openssl rand 160 -out /path/to/identity.key -hexNote that
ProxyTLSPreSharedKey
requires at least 20 bytes of key
data. Having generated the random key data, tell mod_proxy
to use
it via:
ProxyTLSPreSharedKey identity hex:/path/to/identity.key
<VirtualHost>
, <Global>
The ProxyTLSProtocol
directive is used to configure the SSL/TLS
protocol versions that mod_proxy
should use when establishing
SSL/TLS sessions to backend servers.
The allowed protocols are:
SSLv3 |
Use only SSLv3 |
TLSv1 |
Use only TLSv1 |
TLSv1.1 |
Use only TLSv1.1 |
TLSv1.2 |
Use only TLSv1.2 |
To support both SSLv3 and TLSv1, simply list both parameters for the
ProxyTLSProtocol
directive, e.g.:
ProxyTLSProtocol SSLv3 TLSv1
The ProxyTLSProtocol
directive can also be used in a different
manner, to add or subtract protocol support. For example,
to enable all protocols except SSLv3, you can use:
ProxyTLSProtocol ALL -SSLv3Using the directive in this manner requires that "ALL" be the first parameter, and that all protocols have either a
+
(add) or -
(subtract) prefix. "ALL" will
always be expanded to all of the supported SSL/TLS protocols known by
mod_proxy
and supported by OpenSSL
.
<VirtualHost>
, <Global>
The ProxyTLSTimeoutHandshake
directive configures the maximum
number of seconds for mod_proxy
to complete an SSL/TLS handshake.
If set to zero, mod_proxy
will wait forever for a handshake to
complete. The default is 30 seconds.
<VirtualHost>
, <Global>
The ProxyTLSTransferProtectionPolicy
directive configures the data
transfer protection policy, when using SSL/TLS, that
mod_proxy
uses when performing data transfers (e.g. file
uploads/downloads, directory listings) with the backend/destination server.
The currently supported policies are:
client
This policy indicates that mod_proxy
will use whatever
the connected client uses. Thus if the client sends PROT C
,
mod_proxy
will send PROT C
to the
backend/destination server.
required
Regardless of the commands sent by the client, mod_proxy
will use only protected TLS data transfers (i.e. using
PROT P
commands) with the backend/destination server.
This is the recommended policy in most cases.
clear
Regardless of the commands sent by the client, mod_proxy
will use only clear (i.e. unprotected) data
transfers (i.e. using PROT C
commands) with the
backend/destination server.
<VirtualHost>
, <Global>
The ProxyTLSVerifyServer
directive configures how
mod_proxy
handles certificates presented by servers. If
off, the module will accept any server certificate and
establish an SSL/TLS session, but will not verify the certificate. If
on, the module will verify a server's certificate and, furthermore,
will fail all SSL handshake attempts unless the server presents a valid
certificate.
Benefits of Proxying
The benefits of using a module like mod_proxy
depend mostly
on the type of proxying, forward or reverse, that mod_proxy
is configured to perform. There are some benefit, however, that the module
can bring, regardless of the type of proxying:
mod_tls
) for FTP servers which do not support FTPS
TransferLog
, ExtendedLog
, etc) for FTP servers which do not provide such versatile logging
mod_snmp
) for FTP servers which do not have such features
When using mod_proxy
for proxying, all data transfers
(e.g. file uploads/downloads, directory listings, etc) pass through
mod_proxy
; data transfers do not occur directly between
the "frontend" clients and the "backend" servers. This happens so that
clients are completely unaware of the network structure for the
backend servers; this is especially important when reverse proxying, where
it means that the client sees mod_proxy
as the real FTP
server.
Forward Proxying
One of the most common benefits of a forward proxy is having controlled access,
by clients within an internal LAN, to outside servers. FTP makes this sort
of thing notoriously difficult for firewalls/routers due to its multi-TCP
connection nature; this, in turn, makes proxying of FTP more difficult. But
mod_proxy
makes this possible; it understands FTP, and thus
provides the access control needed for such use cases.
When using mod_proxy
as a forward proxy, FTP clients which can
only perform active data transfers can use mod_proxy
as a way
to use passive data transfers with the destination FTP server.
Similarly, FTP clients which do not support IPv6 can proxy through
mod_proxy
to reach a destination FTP server with an IPv6 address;
mod_proxy
handles IPv4 and IPv6 addresses transparently.
Reverse Proxying
Just as mod_proxy
can aid naive/legacy FTP clients via forward
proxying, mod_proxy
can similarly front legacy FTP servers.
For example, mod_proxy
can sit in front of FTP servers which
do not handle IPv6 addresses, and provide this functionality transparently
to IPv6-capable FTP clients.
When performing reverse proxying, mod_proxy
can also perform
load balancing in various ways. The common methods of "round robin" and
"least connections" are implemented; mod_proxy
also provides
"sticky session" load balancing of clients as well.
Handling of Proxied Sessions
Once a proxied session has authenticated with the backend/destination server,
the mod_proxy
module automatically chroots itself to a
subdirectory of the ProxyTables
directory, after which all root privileges are permanently dropped.
Forward Proxy Configuration
Before discussing example forward proxy configurations for
mod_proxy
, it is very important to understand the consequences
of providing forward proxy capabilities.
Important Security Considerations
A forward proxy can be used by any client to have the proxy
connect to any arbitrary host, while hiding the client's true identity.
Malicious behavior, hacking or denial-of-service attempts, etc will
appear to be coming from your proxy; this is dangerous for your
network, and for the Internet at large. Think of the damage that has been
done, and continues to happen, due to open/unrestricted proxies/relays
such as open DNS or SMTP/email proxies.
This is the reason that mod_proxy
does not allow just any
client to use its forward proxy capabilities by default; instead, only
clients connecting from the LAN are allowed by default. Allowing trusted
outside clients is done using the
ProxyForwardEnabled
directive.
Even allowing internal clients to use your forward proxy can be troublesome,
depending on the destination hosts selected by the clients. To ensure that
your clients are using the forward proxy to connect only to the hosts allowed,
you can use the ProxyForwardTo
directive to configure a regular expression-based whitelist of allowed
destination/target hosts; this is strongly recommended.
With all that said, here's an example mod_proxy
configuration
for supporting forward proxying:
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole forward ProxyForwardMethod user@host ProxyForwardTo ^ftp\.example\.com\:21$ [NC] </IfModule>If the configured
ProxyForwardTo
pattern is not met,
the following will be logged in the ProxyLog
:
mod_proxy/0.7[16151]: host/port 'server.example.org:2121' did not match ProxyForwardTo ^ftp\.example\.com\:21$, rejecting
Reverse Proxy Configuration
Reverse proxies (also known as "gateways") are often used to provide access
to FTP resources, located with internal networks, to the outside world. The
reverse proxy can perform load balancing, provide functionality that the
internal servers may not be able to do, and even perform things like caching.
Access control for reverse proxies is less critical than for forward proxies because clients can only reach, via the reverse proxy, the backend servers that the reverse proxy has been configured to use; the clients do not get to choose arbitrary hosts for the reverse proxy to use.
Here's an example mod_proxy
configuration for supporting reverse
proxying:
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole reverse ProxyReverseConnectPolicy RoundRobin ProxyReverseServers ftp://ftp-backend1.example.com:2121 ftp://ftp-backend2.example.com:2121 ... </IfModule>
Here's an example mod_proxy
configuration for reverse proxying,
with lookup of per-user backend servers:
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole reverse ProxyReverseConnectPolicy PerUser # We need to provide a pool of backend servers as a fallback ProxyReverseServers ftp://ftp-backend1.example.com:2121 ftp://ftp-backend2.example.com:2121 ... # Look up per-user backend servers from user-specific JSON files ProxyReverseServers file:/var/ftp/proxy/backends/%U.json </IfModule>Similarly, you can use a per-group lookup for the backend servers when reverse proxying:
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole reverse ProxyReverseConnectPolicy PerGroup ProxyOptions UseReverseProxyAuth # We need to provide a pool of backend servers as a fallback ProxyReverseServers ftp://ftp-backend1.example.com:2121 ftp://ftp-backend2.example.com:2121 ... # Look up per-group backend servers from group-specific JSON files ProxyReverseServers file:/var/ftp/proxy/backends/%g.json </IfModule>
In order to support FTP over SSL/TLS (FTPS) connections from clients
when reverse proxying, simply include your normal mod_tls
configuration with the same <VirtualHost>
configuration
with your mod_proxy
configuration.
For FTPS support to the backend servers, your reverse proxy configuration would look something like this:
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole reverse ProxyReverseConnectPolicy RoundRobin ProxyReverseServers ftp://ftp-backend1.example.com:2121 ftp://ftp-backend2.example.com:2121 ... # Use FTPS when supported/available by the backend server ProxyTLSEngine auto # List of trusted root CAs ProxyTLSCACertificateFile /etc/ftpd/cacerts.pem </IfModule>In fact,
mod_proxy
comes with a default
ProxyTLSCACertificateFile
(comprised of the root CAs that most
browsers use/trust), and the default ProxyTLSEngine
value is auto. This means that, by default, mod_proxy
will try to use FTPS for backend connections automatically (assuming that
ProFTPD is built with OpenSSL support using the --enable-openssl
configure option).
Load Balancing versus Session Stickiness
For reverse proxy configurations, there is a choice between
load balancing and sticky session
ProxyReverseConnectPolicy
parameters; these parameters determine
the selection of the backend server that will handle the incoming connection.
Which should you use, and why?
All of the balancing policies are able to select the backend server
when the FTP client connects to the proxy, before sending any commands.
Most of the "sticky" policies, on the other hand, require more knowledge about
the user (e.g. USER
name, HOST
name, SSL
session ID) before the backend server can be determined, thus backend
server selection is delayed until that information is obtained.
Balancing is best when all of your backend severs are identical with regard to the content they have, and when it does not matter which server handles a particular client. Maybe all of your backend servers use a shared filesystem via NFS or similar, thus directory listings will be the same for a user no matter which backend server is used, and uploading files to one server means that those files can be downloaded/seen by the other servers. Balancing policies are also best when all of your backend servers have similar processing power (memory, CPU, network, disk), so that all backend servers are equally capable of providing the same service to the connecting client.
The balancing policies are:
LeastConns
Random
RoundRobin
Shuffle
Stickiness is best when your backend servers are not identical, and some users/clients should only ever go to the same set of backend servers. Thus the user/client needs to be "sticky" to a given backend server.
The sticky policies are:
PerGroup
PerHost
PerUser
Implicit FTPS Support
The mod_proxy
module includes support for using implicit FTPS with backend servers,
both when forward and reverse proxying. Note that implicit FTPS support
requires the presence/use of the mod_tls
ProFTPD module.
In order to use implicit FTPS for a reverse proxy server, the URI syntax
must be used in a ProxyReverseServers
directive; the scheme
must be "ftps" and the port must be explicitly specified as 990,
thus:
ProxyReverseServers ftps://ftp.example.com:990
When forward proxying, the client must request the destination server and
specify a port of 990, e.g.:
USER user@ftp.example.com:990
Note that there is an additional wrinkle/caveat for implicit FTPS support when
your mod_proxy
installation uses shared/DSO modules. You must
ensure, in a list of LoadModule
directives, that
mod_proxy
appears before mod_tls
:
# Make sure that mod_tls appears after mod_proxy in the list of loaded # modules LoadModule mod_proxy.c LoadModule mod_tls.cWhy does this matter?
A lot of things happen when a client connects, via TCP, to the server (in this
case, to a server configured to be a proxy). ProFTPD publishes this "on connect"
event to all of the modules, in "module load order". The last module
loaded will be the first module to receive this event; this means
"module loader order" is the reverse order of your
LoadModule
directives.
What we want is for the mod_tls
module to handle the "on connect"
event first, so that it handles the implicit TLS handshake. In doing so, the
mod_tls
module will record some internal session state showing
that a TLS handshake occurred. The mod_proxy
module looks for the
internal session state that mod_tls
sets, and will Do The Right
Thing if it sees that a TLS session is in effect.
On the other hand, if mod_proxy
appears after mod_tls
in the LoadModule
list, then it is the mod_proxy
module which handles the "on connect" event before mod_tls
does.
mod_proxy
looks for the session state to see if a TLS session is
in effect, does not find the session state, and then attempts to proxy things
like the backend banner to the client. The frontend client is expecting TLS
handshake bytes, not plaintext text bytes from the banner, and thus the frontend
client will see a TLS error.
SFTP/SCP Support
The mod_proxy
module now supports reverse proxying (but
not forward proxying) of SFTP/SCP sessions.
To support a reverse proxy configuration for SFTP/SCP sessions, specify
the sftp
scheme in your ProxyReverseServers
URIs,
like so:
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole reverse ProxyReverseConnectPolicy RoundRobin ProxyReverseServers sftp://ssh-backend1.example.com:2222 sftp://ssh-backend2.example.com ... </IfModule>
When proxying SSH connections like this, there will be two separate SSH sessions:
frontend client --- (SSH session #1) --> proxy --- (SSH session #2) --> backend serverEach SSH session creates a unique session ID, as a hash of client- and server-provided values known as
H
. This is important for some
types of authentication, as we see later.
Proxying of SSH connections is more complex than proxying of FTP/FTPS
connections, especially when it comes to authentication. FTP supports
simple password-based authentication, whereas SSH supports multiple different
authentication mechanisms. And two authentication mechanisms, in particular,
require a slightly more sophisticated mod_proxy
configuration:
"hostbased" and "publickey".
When the frontend SSH client requests the "keyboard-interactive"
or "password" authentication mechanisms, then mod_proxy
can handle the client using the above configuration as-is. For the
"hostbased" and "publickey" authentication mechanisms,
mod_proxy
needs to do a little more work -- and it requires
support on the backend servers for "hostbased" authentication.
Let's consider the common "publickey" use case (the frontend
"hostbased" case is quite similar). The frontend client has a
public/private key pair; mod_proxy
has no knowledge or access to
that frontend private key (by design). The frontend client performs the
"publickey" authentication by hashing several types of data, then
encrypts that hash with its private key; the server (mod_proxy
in
this case) then hashes the same data, and decrypts the client-sent value with
the client's public key. The complication is that one of the types of data
included in these hashes is the unique session ID known as H
mentioned above. The H
values for the SSH connections (from the
frontend client to the proxy, and separately from the proxy to the backend
server) will be different. And since mod_proxy
has no
access to the frontend private key, it cannot forge or change H
(and this is a good thing). But it does mean that mod_proxy
cannot simply proxy the "publickey" authentication request as is,
from frontend client to backend server.
Instead, for these authentication mechanisms, mod_proxy
will
use a different authentication mechanism, specifically "hostbased"
authentication, to the backend server. This makes sense, right? The backend
server trusts that the proxy is doing proper handling of all frontend
clients, thus backend server can trust the entire proxy host, not just
individual clients proxied by that host. In order support these backend
"hostbased" authentication requests, mod_proxy
will
need to know its private key to use for such things, via
ProxySFTPHostKey
; this can
actually the same private key used by the SFTPHostKey
directive
(or be a different private key, depending on your needs). It also requires
that the backend servers be configured to trust the corresponding public key;
for mod_sftp
, this would be done using its
SFTPAuthorizedHostKeys
directive.
The SFTP/SCP support in mod_proxy
also properly supports the
PerUser
, PerGroup
ProxyReverseConnectPolicy
values, subject the same caveats. This means that mod_proxy
can proxy different frontend SSH users to different backend servers (and
even rewrite/change the user name via the mod_rewrite
module); just like for
FTP/FTPS sessions, you can configure the per-user lookup of backend servers
using SQL queries, JSON files, etc.
Logging
The mod_proxy
module supports different forms of logging. The
main module logging is done via the
ProxyLog
directive. For debugging
purposes, the module also uses trace logging, via the module-specific channels:
Thus for trace logging, to aid in debugging, you would use the following in
your proftpd.conf
:
TraceLog /path/to/proxy-trace.log Trace proxy:20This trace logging can generate large files; it is intended for debugging use only, and should be removed from any production configuration.
Logging Notes
The following is a list of notes, logging variables that can be used in
custom LogFormats
and/or custom SQL statements:
%{note:mod_proxy.backend-ip}
: IP address of the backend/proxied server
%{note:mod_proxy.backend-port}
: Port of the backend/proxied server
%{note:mod_proxy.backend-url}
: URL to the backend/proxied server
SELinux
If using the mod_proxy
module on an SELinux-enabled system, you
may need the following to allow for proper operations of proxying. For example,
using the following mod_proxy
configuration:
ProxyTables /var/ftp/proxymay require that you run:
$ semanage fcontext --add --type public_content_rw_t '/var/ftp/proxy(/.*)?' $ setsebool -P ftpd_anon_write=1 $ setsebool -P nis_enabled=1
Suggested Future Features
The following lists the features I hope to add to mod_proxy
,
according to need, demand, inclination, and time:
MODE Z
support
See the GitHub issues page for current bugs and feature requests, and to report issues.
Question: I have heard a lot about both "round robin"
and "least conns" for load balancing. Which is better for FTP connections?
Answer: There is not an easy answer to this, because
it really comes down to the type of traffic that your FTP servers will see.
If your FTP sessions tend to be long-lived (e.g. on the
order of minutes to hours), then using ProxyReverseConnectPolicy
LeastConns
will tend to provide the best distribution of those sessions
across your pool of backend servers. The assumption here is that new
connections arrive infrequently relative to the number of existing
connections.
On the other hand, if your FTP sessions tend to be shorter
(e.g. minutes at most), then using ProxyReverseConnectPolicy
RoundRobin
might provide a more even distribution of connections
across your pool of backend servers.
ProxyReverseConnectPolicy PerHostand would like to configure different pools of backend servers for different incoming clients. How do I do this?
mod_ifsession
's <IfClass>
sections. For
example:
<Class proxied-clients> </Class> ProxyRole reverse ProxyReverseConnectPolicy PerHost <IfClass proxied-clients> ProxyReverseServers ftp://ftp-special1.example.com:2121 ftp://ftp-special2.example.com:2121 ... </IfClass> # Don't forget to configure the backend server pool for clients coming # from other networks! <IfClass !proxied-clients> ProxyReverseServers ftp://ftp-backend1.example.com:2121 ftp://ftp-backend2.example.com:2121 ... </IfClass>
Question: Does mod_proxy
support SSL/TLS
connections, i.e. FTPS?
Answer: Short answer: yes.
The long answer is the mod_proxy
supports FTPS connections
both on the frontend, from connecting clients, and on
the backend, to backend servers. This means that all of the following
flows are supported:
client --- FTPS ---> proxy --- FTP ---> server client --- FTP ---> proxy --- FTPS ---> server client --- FTPS ---> proxy --- FTPS ---> server
Thus mod_proxy
's FTPS support is suited for reverse proxy
configurations, where mod_proxy
can be used to provide SSL/TLS
capabilities to old/legacy FTP servers which do not implement it. The
mod_proxy
module is also suited for forward proxy
configurations, where the FTPS support can be used to provide SSL/TLS
capabilities to old/legacy FTP clients which do not implement it.
Question: I want to use mod_proxy
for
reverse proxying. I want to centralize all of my user authentication in
mod_proxy
, and I want to use different user
credentials when logging in to the backend servers. Can mod_proxy
do all of this?
Answer: Yes.
There are a couple of key parts of your mod_proxy
configuration
to pay attention to, for achieving the above.
<IfModule mod_proxy.c> ProxyEngine on ProxyLog /path/to/proxy.log ProxyTables /var/ftp/proxy ProxyRole reverse # Make sure to authenticate in the proxy itself ProxyOptions UseReverseProxyAuth ProxyReverseConnectPolicy ... # Include the username/passwords to use for the backend servers # in the URLs. ProxyReverseServers ftp://user1:password1@ftp-backend1.example.com:2121 ftp://user2:password2@ftp-backend2.example.com:2121 ... </IfModule>When a URL uses the "username:password" syntax for including the credentials to use for that connection,
mod_proxy
will use those URI
credentials when logging in to that backend server.
Question: I have configured mod_proxy
to
block the LIST
command for one group of users, like so:
<Limit LIST> DenyGroup somegroup </Limit>But this
<Limit>
is not working. Is this a bug?
The <Limit>
mechanism works on the authenticated
user/group names. And in many cases, it is not mod_proxy
which authenticates the user, it is the backend server. Thus it is the
backend server which knows the groups to which the authenticated user belongs;
mod_proxy
only knows that the USER
name was
successfully authenticated by the backend user. Thus group-based
limits cannot be honored.
However, if proxy auth is enabled, then group-based limits will work. This means using either the following when forward proxying:
ProxyRole forward # Either of these two methods result in proxy auth ProxyForwardMethod proxyuser,user@host ProxyForwardMethod proxyuser@host,useror this, when reverse proxying:
ProxyRole reverse ProxyOptions UseReverseProxyAuth
Question: Can mod_proxy
be configured
as a reverse proxy, and to select the backend server based on the client
certificate used by the frontend FTPS client?
Answer: Yes, but it requires the use of a custom SQL
query.
The idea here is to define a SQL query which looks up the backend server to
use, based on information in the frontend FTPS client certificate. Since the
mod_proxy
module already uses SQLite, you should
be able to use the mod_sql_sqlite
module if needed. The SQL
table schema might look like:
CREATE TABLE proxy_backends ( common_name TEXT PRIMARY KEY, url TEXT );
<IfModule mod_tls.c> ... # Tell mod_tls to export environment variables containing various # certificate fields, for use by e.g. mod_sql. TLSOptions StdEnvVars ... </IfModule> <IfModule mod_sql.c> ... # Use the TLS_CLIENT_S_DN_CN environment variable (for the CommonName of # the Subject section of the frontend FTPS client certificate) provided # by mod_tls in our selection. SQLNamedQuery get-user-servers SELECT "url FROM proxy_backends WHERE common_name = '%{env:TLS_CLIENT_S_DN_CN}'" ... </IfModule> <IfModule mod_proxy.c> ... ProxyRole reverse ProxyReverseConnectPolicy PerUser # Use a named SQL query to lookup the backend server to use. Note that # the name used here is the name of our SQLNamedQuery defined above. ProxyReverseServers sql:/get-user-servers ... </IfModule>Note that the
mod_tls
module provides many other environment
variables for other fields of the certificate; using a field other than
CommonName is also quite doable, depending on your needs.
mod_proxy
, go to the third-party module area in
the proftpd source code and unpack the mod_proxy
source tarball:
$ cd proftpd-dir/contrib/ $ tar zxvf /path/to/mod_proxy-version.tar.gzafter unpacking the latest proftpd-1.3.x source code. For including
mod_proxy
as a statically linked module:
$ ./configure --with-modules=mod_proxy:...To build
mod_proxy
as a DSO module:
$ ./configure --enable-dso --with-shared=mod_proxy:...Then follow the usual steps:
$ make $ make installNote:
mod_proxy
uses the
SQLite
library; thus the
sqlite3
development library/headers must be installed for
building mod_proxy
.
It is highly recommended that SQLite 3.8.5 or later be used. Problems
have been reported with mod_proxy
when SQLite 3.6.20 is used;
these problems disappeared once SQLite was upgraded to a newer version.
Note: mod_proxy
uses the OpenSSL library, so its
development library/header files must be installed for building
mod_proxy
.