Skip to content

Commit

Permalink
Merge pull request #273 from Castaglia/proxy-dynamic-src-addr-issue272
Browse files Browse the repository at this point in the history
Issue #272: Let the kernel automatically select the best source addre…
  • Loading branch information
Castaglia authored Aug 17, 2024
2 parents 58c45f6 + 90a4b61 commit d78df97
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 11 deletions.
27 changes: 23 additions & 4 deletions lib/proxy/conn.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* ProFTPD - mod_proxy conn implementation
* Copyright (c) 2012-2023 TJ Saunders
* Copyright (c) 2012-2024 TJ Saunders
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -677,7 +677,7 @@ conn_t *proxy_conn_get_server_conn(pool *p, struct proxy_session *proxy_sess,
const char *remote_ipstr = NULL;
unsigned int remote_port;
conn_t *server_conn, *ctrl_conn;
int res;
int res, default_inet_family = 0;

if (proxy_sess->connect_timeout > 0) {
const char *notes_key = "mod_proxy.proxy-connect-address";
Expand Down Expand Up @@ -750,8 +750,21 @@ conn_t *proxy_conn_get_server_conn(pool *p, struct proxy_session *proxy_sess,
}

bind_addr = proxy_sess->src_addr;

/* We need to set the default inet family to use for the local address of
* our socket. We do NOT want to just use the family of the local address of
* our control connection, since we could be listening on an IPv6 address
* and want to connect to a backend IPv4 address, or vice versa; see
* Issue #272.
*/
if (bind_addr == NULL) {
bind_addr = local_addr;
int remote_family;

remote_family = pr_netaddr_get_family(remote_addr);

pr_trace_msg(trace_channel, 9, "using %s family for socket local address",
remote_family == AF_INET ? "IPv4" : "IPv6");
default_inet_family = pr_inet_set_default_family(p, remote_family);
}

/* Note: IF mod_proxy is running on localhost, and the connection to be
Expand All @@ -760,7 +773,8 @@ conn_t *proxy_conn_get_server_conn(pool *p, struct proxy_session *proxy_sess,
* and of course not reachable from a public IP. Thus we check for this
* edge case (which happens often for development).
*/
if (pr_netaddr_is_loopback(bind_addr) == TRUE &&
if (bind_addr != NULL &&
pr_netaddr_is_loopback(bind_addr) == TRUE &&
pr_netaddr_is_loopback(remote_addr) != TRUE) {
const char *local_name;
const pr_netaddr_t *new_local_addr;
Expand Down Expand Up @@ -814,6 +828,11 @@ conn_t *proxy_conn_get_server_conn(pool *p, struct proxy_session *proxy_sess,
return NULL;
}

/* Restore the previous default inet family if necessary. */
if (bind_addr == NULL) {
(void) pr_inet_set_default_family(p, default_inet_family);
}

pr_trace_msg(trace_channel, 12,
"connecting to backend address %s#%u from %s#%u", remote_ipstr, remote_port,
pr_netaddr_get_ipstr(server_conn->local_addr), server_conn->local_port);
Expand Down
14 changes: 7 additions & 7 deletions t/lib/ProFTPD/Tests/Modules/mod_proxy.pm
Original file line number Diff line number Diff line change
Expand Up @@ -4963,11 +4963,12 @@ sub proxy_reverse_eprt_ipv6 {
ScoreboardFile => $scoreboard_file,
SystemLog => $log_file,
TraceLog => $log_file,
Trace => 'DEFAULT:10 event:0 lock:0 scoreboard:0 signal:0 proxy:20 proxy.ftp.conn:20 proxy.ftp.ctrl:20 proxy.ftp.data:20 proxy.ftp.msg:20',
Trace => 'DEFAULT:10 event:0 lock:0 scoreboard:0 signal:0 proxy:20 proxy.conn:20 proxy.ftp.conn:20 proxy.ftp.ctrl:20 proxy.ftp.data:20 proxy.ftp.msg:20',

AuthUserFile => $auth_user_file,
AuthGroupFile => $auth_group_file,
AuthOrder => 'mod_auth_file.c',
UseIPv6 => 'on',

SocketBindTight => 'on',
TimeoutIdle => $timeout_idle,
Expand Down Expand Up @@ -5036,19 +5037,16 @@ EOC

my ($resp_code, $resp_msg) = $client->eprt('|2|::ffff:127.0.0.1|4856|');

my $expected;

$expected = 200;
my $expected = 200;
$self->assert($expected == $resp_code,
test_msg("Expected $expected, got $resp_code"));
test_msg("Expected response code $expected, got $resp_code"));

$expected = "EPRT command successful";
$self->assert($expected eq $resp_msg,
test_msg("Expected '$expected', got '$resp_msg'"));
test_msg("Expected response message '$expected', got '$resp_msg'"));

$client->quit();
};

if ($@) {
$ex = $@;
}
Expand Down Expand Up @@ -23599,6 +23597,7 @@ sub proxy_forward_noproxyauth_login_ipv6_dst_addr {

ServerIdent => 'on "Forward Proxy Server"',
SocketBindTight => 'on',
UseIPv6 => 'on',

IfModules => {
'mod_proxy.c' => $proxy_config,
Expand Down Expand Up @@ -26121,6 +26120,7 @@ sub proxy_forward_eprt_ipv6 {

ServerIdent => 'on "Forward Proxy Server"',
SocketBindTight => 'on',
UseIPv6 => 'on',

IfModules => {
'mod_proxy.c' => $proxy_config,
Expand Down

0 comments on commit d78df97

Please sign in to comment.