From 46c8a17e5f71f180864f4af28580b45a366707d2 Mon Sep 17 00:00:00 2001 From: mk-pmb Date: Thu, 17 Sep 2020 03:21:53 +0200 Subject: [PATCH] Add option pasvHostAliases for PASV behind NAT Fixes #143. --- README.md | 8 ++++++++ lib/FtpConnection.js | 3 +++ 2 files changed, 11 insertions(+) diff --git a/README.md b/README.md index c4d463f..e3539ab 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,14 @@ The user is not able to escape this directory. - Integer, specifies the lower-bound port (min port) for creating PASV connections - `pasvPortRangeEnd`: _(default: random?)_ - Integer, specifies the upper-bound port (max port) for creating PASV connections +- `pasvHostAliases`: _(default: auto-detect)_ + - Dictionary object string → string, mapping auto-detected IP addresses (key) to addresses that shall be announced (value). + The values must be IPv4 addresses (four decimal numbers separated by dots) that shall be sent as the server IP in the PASV reply. + This is required when you want to use PASV transfers with the FTP server behind a NAT, especially if the internal network uses IPv6. + - If you want to support PASV connections inside the FTP server's network, you'll need separate IPs for the internal connections and the NAT connections. + Internal clients that accidentially connect to the IP configured for NAT will receive announcements for the external IP, which may cause redundant NAT traffic or might just fail. + - If the auto-detected IP address doesn't have its own entry, the fallback entry with key `*` (U+002A asterisk) will be tried. + Thus, in simple scenarios where your NAT only has one external IP and you do not need PASV mode inside the network behind the NAT, you can always use the fallback key `*`. ## Filesystem Abstraction diff --git a/lib/FtpConnection.js b/lib/FtpConnection.js index 828e1a8..4966f70 100644 --- a/lib/FtpConnection.js +++ b/lib/FtpConnection.js @@ -759,10 +759,13 @@ FtpConnection.prototype._writePASVReady = function(command) { var a = self.pasv.address(); var host = self.server.host; + var ipMap; var port = a.port; if (command === 'PASV') { var i1 = (port / 256) | 0; var i2 = port % 256; + ipMap = self.server.options.pasvHostAliases; + if (ipMap) { host = (ipMap[host] || ipMap['*'] || host); } self.respond('227 Entering Passive Mode (' + host.split('.').join(',') + ',' + i1 + ',' + i2 + ')'); } else { // EPASV self.respond('229 Entering Extended Passive Mode (|||' + port + '|)');