Skip to content

Commit 072c271

Browse files
committed
Issue #285: Implement an IgnoreForeignAddress ProxyOption, such that backend passive data transfers always use the same IP address as used for the control connection, regardless of the address provided in the backend server's PASV response.
1 parent bcb6126 commit 072c271

File tree

4 files changed

+70
-17
lines changed

4 files changed

+70
-17
lines changed

lib/proxy/ftp/xfer.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* ProFTPD - mod_proxy FTP data transfer routines
3-
* Copyright (c) 2013-2024 TJ Saunders
3+
* Copyright (c) 2013-2025 TJ Saunders
44
*
55
* This program is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -550,25 +550,43 @@ const pr_netaddr_t *proxy_ftp_xfer_prepare_passive(int policy_id, cmd_rec *cmd,
550550

551551
remote_port = ntohs(pr_netaddr_get_port(remote_addr));
552552

553-
if (!(proxy_opts & PROXY_OPT_ALLOW_FOREIGN_ADDRESS)) {
554-
/* Make sure that the given address matches the address to which we
555-
* originally connected.
556-
*/
553+
/* See if the given address matches the address to which we originally
554+
* connected.
555+
*/
556+
if (pr_netaddr_cmp(remote_addr,
557+
proxy_sess->backend_ctrl_conn->remote_addr) != 0) {
558+
559+
pr_trace_msg(trace_channel, 2,
560+
"backend passive transfer address %s does not match backend control "
561+
"connection address %s", pr_netaddr_get_ipstr(remote_addr),
562+
pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr));
557563

558-
if (pr_netaddr_cmp(remote_addr,
559-
proxy_sess->backend_ctrl_conn->remote_addr) != 0) {
564+
if (proxy_opts & PROXY_OPT_IGNORE_FOREIGN_ADDRESS) {
560565
(void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
561-
"Refused %s address %s (address mismatch with %s)",
562-
(char *) pasv_cmd->argv[0], pr_netaddr_get_ipstr(remote_addr),
566+
"Ignoring %s address %s per IgnoreForeignAddress ProxyOption, using %s "
567+
"instead", (char *) pasv_cmd->argv[0],
568+
pr_netaddr_get_ipstr(remote_addr),
563569
pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr));
564-
xerrno = EPERM;
565570

566-
pr_response_add_err(error_code, "%s: %s", (char *) cmd->argv[0],
567-
strerror(xerrno));
568-
pr_response_flush(&resp_err_list);
571+
remote_addr = pr_netaddr_dup(proxy_sess->dataxfer_pool,
572+
proxy_sess->backend_ctrl_conn->remote_addr);
573+
pr_netaddr_set_port2(remote_addr, remote_port);
574+
575+
} else {
576+
if (!(proxy_opts & PROXY_OPT_ALLOW_FOREIGN_ADDRESS)) {
577+
(void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
578+
"Refused %s address %s (address mismatch with %s)",
579+
(char *) pasv_cmd->argv[0], pr_netaddr_get_ipstr(remote_addr),
580+
pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr));
581+
xerrno = EPERM;
569582

570-
errno = xerrno;
571-
return NULL;
583+
pr_response_add_err(error_code, "%s: %s", (char *) cmd->argv[0],
584+
strerror(xerrno));
585+
pr_response_flush(&resp_err_list);
586+
587+
errno = xerrno;
588+
return NULL;
589+
}
572590
}
573591
}
574592

mod_proxy.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,9 @@ MODRET set_proxyoptions(cmd_rec *cmd) {
816816
} else if (strcmp(cmd->argv[i], "AllowForeignAddress") == 0) {
817817
opts |= PROXY_OPT_ALLOW_FOREIGN_ADDRESS;
818818

819+
} else if (strcmp(cmd->argv[i], "IgnoreForeignAddress") == 0) {
820+
opts |= PROXY_OPT_IGNORE_FOREIGN_ADDRESS;
821+
819822
} else {
820823
CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown ProxyOption '",
821824
(char *) cmd->argv[i], "'", NULL));

mod_proxy.h.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* ProFTPD - mod_proxy
3-
* Copyright (c) 2012-2024 TJ Saunders
3+
* Copyright (c) 2012-2025 TJ Saunders
44
*
55
* This program is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -104,6 +104,7 @@
104104
#define PROXY_OPT_USE_PROXY_PROTOCOL_V20x0020
105105
#define PROXY_OPT_USE_PROXY_PROTOCOL_V2_TLVS0x0040
106106
#define PROXY_OPT_ALLOW_FOREIGN_ADDRESS0x0080
107+
#define PROXY_OPT_IGNORE_FOREIGN_ADDRESS0x0100
107108

108109
/* mod_proxy datastores */
109110
#define PROXY_DATASTORE_SQLITE1

mod_proxy.html

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,37 @@ <h3><a name="ProxyOptions">ProxyOptions</a></h3>
504504
# address for data transfers than the IP address to which mod_proxy connected.
505505
ProxyOptions AllowForeignAddress
506506
</pre>
507+
508+
<p>
509+
Note that the <code>IgnoreForeignAddress</code> option takes precedence
510+
over this option.
511+
</li>
512+
513+
<p>
514+
<li><code>IgnoreForeignAddress</code><br>
515+
<p>
516+
Use this option to tell the <code>mod_proxy</code> module to <i>always</i>
517+
use the same IP address for passive data transfers to the backend server as
518+
used for the control connection, ignoring any different IP address that
519+
the backend server may provide in its <code>PASV</code> response.
520+
521+
<p>
522+
This option may be needed in cases where you see backend data transfers fail with errors logged such as:
523+
<pre>
524+
unable to connect to 172.16.1.2#8200: Network unreachable
525+
unable to connect to 172.16.2.2#8200: Connection refused
526+
</pre>
527+
Example:
528+
<pre>
529+
# When the backend server tells us to use a different IP address for data
530+
# transfers than the IP address to which mod_proxy connected, ignore that
531+
# different IP address and use the original initial IP address.
532+
ProxyOptions IgnoreForeignAddress
533+
</pre>
534+
535+
<p>
536+
Note that this option takes precedence over the
537+
<code>AllowForeignAddress</code> option.
507538
</li>
508539

509540
<p>
@@ -2561,7 +2592,7 @@ <h2><a name="Installation">Installation</a></h2>
25612592
<hr>
25622593

25632594
<font size=2><b><i>
2564-
&copy; Copyright 2015-2024 TJ Saunders<br>
2595+
&copy; Copyright 2015-2025 TJ Saunders<br>
25652596
All Rights Reserved<br>
25662597
</i></b></font>
25672598

0 commit comments

Comments
 (0)