dovecot-2.2: login proxy: Added login_source_ips setting.

dovecot at dovecot.org dovecot at dovecot.org
Mon Jun 16 16:53:31 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/b6733f4777f1
changeset: 17504:b6733f4777f1
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jun 16 19:52:11 2014 +0300
description:
login proxy: Added login_source_ips setting.
The setting contains a list of IPs/hosts. The setting may be prefixed with
"?" character to indicate that only those IPs should be used that exist in
the current server (allowing the same config to be shared by multiple
servers).

The IPs are used round robin as the source IP address when proxy creates TCP
connections. This becomes useful when there are a ton of connections from
the proxy to the same destination IP, because TCP ports run out after ~64k
connections.

diffstat:

 src/login-common/client-common-auth.c |  12 ++++++--
 src/login-common/login-common.h       |   3 ++
 src/login-common/login-settings.c     |   2 +
 src/login-common/login-settings.h     |   1 +
 src/login-common/main.c               |  49 +++++++++++++++++++++++++++++++++++
 5 files changed, 64 insertions(+), 3 deletions(-)

diffs (145 lines):

diff -r 75d254897442 -r b6733f4777f1 src/login-common/client-common-auth.c
--- a/src/login-common/client-common-auth.c	Mon Jun 16 19:21:36 2014 +0300
+++ b/src/login-common/client-common-auth.c	Mon Jun 16 19:52:11 2014 +0300
@@ -338,9 +338,15 @@
 	if (reply->hostip != NULL &&
 	    net_addr2ip(reply->hostip, &proxy_set.ip) < 0)
 		proxy_set.ip.family = 0;
-	if (reply->source_ip != NULL &&
-	    net_addr2ip(reply->source_ip, &proxy_set.source_ip) < 0)
-		proxy_set.source_ip.family = 0;
+	if (reply->source_ip != NULL) {
+		if (net_addr2ip(reply->source_ip, &proxy_set.source_ip) < 0)
+			proxy_set.source_ip.family = 0;
+	} else if (login_source_ips_count > 0) {
+		/* select the next source IP with round robin. */
+		proxy_set.source_ip = login_source_ips[login_source_ips_idx];
+		login_source_ips_idx =
+			(login_source_ips_idx + 1) % login_source_ips_count;
+	}
 	proxy_set.port = reply->port;
 	proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
 	if (proxy_set.connect_timeout_msecs == 0)
diff -r 75d254897442 -r b6733f4777f1 src/login-common/login-common.h
--- a/src/login-common/login-common.h	Mon Jun 16 19:21:36 2014 +0300
+++ b/src/login-common/login-common.h	Mon Jun 16 19:52:11 2014 +0300
@@ -49,6 +49,9 @@
 extern const struct master_service_ssl_settings *global_ssl_settings;
 extern void **global_other_settings;
 
+extern const struct ip_addr *login_source_ips;
+extern unsigned int login_source_ips_idx, login_source_ips_count;
+
 void login_refresh_proctitle(void);
 void login_client_destroyed(void);
 
diff -r 75d254897442 -r b6733f4777f1 src/login-common/login-settings.c
--- a/src/login-common/login-settings.c	Mon Jun 16 19:21:36 2014 +0300
+++ b/src/login-common/login-settings.c	Mon Jun 16 19:52:11 2014 +0300
@@ -21,6 +21,7 @@
 
 static const struct setting_define login_setting_defines[] = {
 	DEF(SET_STR, login_trusted_networks),
+	DEF(SET_STR, login_source_ips),
 	DEF(SET_STR_VARS, login_greeting),
 	DEF(SET_STR, login_log_format_elements),
 	DEF(SET_STR, login_log_format),
@@ -45,6 +46,7 @@
 
 static const struct login_settings login_default_settings = {
 	.login_trusted_networks = "",
+	.login_source_ips = "",
 	.login_greeting = PACKAGE_NAME" ready.",
 	.login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c session=<%{session}>",
 	.login_log_format = "%$: %s",
diff -r 75d254897442 -r b6733f4777f1 src/login-common/login-settings.h
--- a/src/login-common/login-settings.h	Mon Jun 16 19:21:36 2014 +0300
+++ b/src/login-common/login-settings.h	Mon Jun 16 19:52:11 2014 +0300
@@ -5,6 +5,7 @@
 
 struct login_settings {
 	const char *login_trusted_networks;
+	const char *login_source_ips;
 	const char *login_greeting;
 	const char *login_log_format_elements, *login_log_format;
 	const char *login_access_sockets;
diff -r 75d254897442 -r b6733f4777f1 src/login-common/main.c
--- a/src/login-common/main.c	Mon Jun 16 19:21:36 2014 +0300
+++ b/src/login-common/main.c	Mon Jun 16 19:52:11 2014 +0300
@@ -2,6 +2,7 @@
 
 #include "login-common.h"
 #include "ioloop.h"
+#include "array.h"
 #include "randgen.h"
 #include "process-title.h"
 #include "restrict-access.h"
@@ -44,6 +45,9 @@
 const struct master_service_ssl_settings *global_ssl_settings;
 void **global_other_settings;
 
+const struct ip_addr *login_source_ips;
+unsigned int login_source_ips_idx, login_source_ips_count;
+
 static struct timeout *auth_client_to;
 static bool shutting_down = FALSE;
 static bool ssl_connections = FALSE;
@@ -277,6 +281,40 @@
 	return FALSE;
 }
 
+static const struct ip_addr *
+parse_login_source_ips(const char *ips_str, unsigned int *count_r)
+{
+	ARRAY(struct ip_addr) ips;
+	const char *const *tmp;
+	struct ip_addr *tmp_ips;
+	bool skip_nonworking = FALSE;
+	unsigned int i, tmp_ips_count;
+	int ret;
+
+	if (ips_str[0] == '?') {
+		/* try binding to the IP immediately. if it doesn't
+		   work, skip it. (this allows using the same config file for
+		   all the servers.) */
+		skip_nonworking = TRUE;
+		ips_str++;
+	}
+	t_array_init(&ips, 4);
+	for (tmp = t_strsplit_spaces(ips_str, ", "); *tmp != NULL; tmp++) {
+		ret = net_gethostbyname(*tmp, &tmp_ips, &tmp_ips_count);
+		if (ret != 0) {
+			i_error("login_source_ips: net_gethostbyname(%s) failed: %s",
+				*tmp, net_gethosterror(ret));
+			continue;
+		}
+		for (i = 0; i < tmp_ips_count; i++) {
+			if (skip_nonworking && net_try_bind(&tmp_ips[i]) < 0)
+				continue;
+			array_append(&ips, &tmp_ips[i], 1);
+		}
+	}
+	return array_get(&ips, count_r);
+}
+
 static void main_preinit(bool allow_core_dumps)
 {
 	unsigned int max_fds;
@@ -312,6 +350,17 @@
 			i_fatal("Couldn't connect to anvil");
 	}
 
+	/* read the login_source_ips before chrooting so it can access
+	   /etc/hosts */
+	login_source_ips = parse_login_source_ips(global_login_settings->login_source_ips,
+						  &login_source_ips_count);
+	if (login_source_ips_count > 0) {
+		/* randomize the initial index in case service_count=1
+		   (although in that case it's unlikely this setting is
+		   even used..) */
+		login_source_ips_idx = rand() % login_source_ips_count;
+	}
+
 	restrict_access_by_env(NULL, TRUE);
 	if (allow_core_dumps)
 		restrict_access_allow_coredumps(TRUE);


More information about the dovecot-cvs mailing list