feat: allow dynamic pasv_url depending on remote address (#269)
Co-authored-by: Matt Forster <hey@mattforster.ca>
This commit is contained in:
26
README.md
26
README.md
@@ -73,7 +73,31 @@ _Note:_ The hostname must be the external IP address to accept external connecti
|
|||||||
__Default:__ `"ftp://127.0.0.1:21"`
|
__Default:__ `"ftp://127.0.0.1:21"`
|
||||||
|
|
||||||
#### `pasv_url`
|
#### `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.
|
If not provided, clients can only connect using an `Active` connection.
|
||||||
|
|
||||||
#### `pasv_min`
|
#### `pasv_min`
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const Promise = require('bluebird');
|
||||||
const PassiveConnector = require('../../connector/passive');
|
const PassiveConnector = require('../../connector/passive');
|
||||||
const {isLocalIP} = require('../../helpers/is-local');
|
const {isLocalIP} = require('../../helpers/is-local');
|
||||||
|
|
||||||
@@ -11,12 +12,17 @@ module.exports = {
|
|||||||
this.connector = new PassiveConnector(this);
|
this.connector = new PassiveConnector(this);
|
||||||
return this.connector.setupServer()
|
return this.connector.setupServer()
|
||||||
.then((server) => {
|
.then((server) => {
|
||||||
let address = this.server.options.pasv_url;
|
|
||||||
// Allow connecting from local
|
|
||||||
if (isLocalIP(this.ip)) {
|
|
||||||
address = this.ip;
|
|
||||||
}
|
|
||||||
const {port} = server.address();
|
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 host = address.replace(/\./g, ',');
|
||||||
const portByte1 = port / 256 | 0;
|
const portByte1 = port / 256 | 0;
|
||||||
const portByte2 = port % 256;
|
const portByte2 = port % 256;
|
||||||
|
|||||||
Reference in New Issue
Block a user