Skip to content

Commit

Permalink
feat: allow dynamic pasv_url depending on remote address (#269)
Browse files Browse the repository at this point in the history
Co-authored-by: Matt Forster <hey@mattforster.ca>
  • Loading branch information
vdiez and matt-forster committed Aug 9, 2021
1 parent bf44cbb commit 02227d6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,31 @@ _Note:_ The hostname must be the external IP address to accept external connecti
__Default:__ `"ftp://127.0.0.1:21"`

#### `pasv_url`
This **must** be the external WAN **IP address** that the FTP server is bound to. `FTP-srv` provides this IP address to the client when a `PASV` command is received in the handshake for a passive connection. Reference [PASV verb](https://cr.yp.to/ftp/retr.html#pasv).
`FTP-srv` provides an IP address to the client when a `PASV` command is received in the handshake for a passive connection. Reference [PASV verb](https://cr.yp.to/ftp/retr.html#pasv). This can be one of two options:
- A function which takes one parameter containing the remote IP address of the FTP client. This can be useful when the user wants to return a different IP address depending if the user is connecting from Internet or from an LAN address.
```js
const {Netmask} = require('netmask');
const networks = {
'$GATEWAY_IP/32': `${public_ip}`,
'10.0.0.0/8' : `${lan_ip}`
}

const resolverFunction = (address) => {
for (const network in networks) {
try {
const mask = new Netmask(network);
if (mask.contains(address)) return networks[network];
}
catch (err) {
logger.error('Error checking source network', err);
}
}
return '127.0.0.1';
}

new FtpSrv({pasv_url: resolverFunction});
- A static IP address (ie. an external WAN **IP address** that the FTP server is bound to). In this case, only connections from localhost are handled differently returning `127.0.0.1` to the client.

If not provided, clients can only connect using an `Active` connection.

#### `pasv_min`
Expand Down
16 changes: 11 additions & 5 deletions src/commands/registration/pasv.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Promise = require('bluebird');
const PassiveConnector = require('../../connector/passive');
const {isLocalIP} = require('../../helpers/is-local');

Expand All @@ -11,12 +12,17 @@ module.exports = {
this.connector = new PassiveConnector(this);
return this.connector.setupServer()
.then((server) => {
let address = this.server.options.pasv_url;
// Allow connecting from local
if (isLocalIP(this.ip)) {
address = this.ip;
}
const {port} = server.address();
let pasvAddress = this.server.options.pasv_url;
if (typeof pasvAddress === "function") {
return Promise.try(() => pasvAddress(this.ip))
.then((address) => ({address, port}));
}
// Allow connecting from local
if (isLocalIP(this.ip)) pasvAddress = this.ip;
return {address: pasvAddress, port};
})
.then(({address, port}) => {
const host = address.replace(/\./g, ',');
const portByte1 = port / 256 | 0;
const portByte2 = port % 256;
Expand Down

0 comments on commit 02227d6

Please sign in to comment.