]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
login-proxy: Add proxy_host_immediate_failure_after=<time> passdb extra field
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Wed, 13 May 2020 12:04:45 +0000 (15:04 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Mon, 25 May 2020 08:38:55 +0000 (08:38 +0000)
If host has only seen connect failures for this long, stop attempting to
connect there (except with one connection) and instead return immediate
failure. This used to be hardcoded to 30 seconds, which can now be
changed. Most importantly 0 means that this functionality is disabled
entirely.

src/login-common/client-common-auth.c
src/login-common/client-common.h
src/login-common/login-proxy.c
src/login-common/login-proxy.h

index b66e63a2e79e6e750ee4462de2d1cda2292e0f79..4c1dcf92dac94c8ac8dad895a9cfdfa7feeb4b7f 100644 (file)
@@ -138,6 +138,8 @@ static void client_auth_parse_args(struct client *client, bool success,
 
        t_array_init(&alt_usernames, 4);
        i_zero(reply_r);
+       reply_r->proxy_host_immediate_failure_after_secs =
+               LOGIN_PROXY_DEFAULT_HOST_IMMEDIATE_FAILURE_AFTER_SECS;
 
        for (; *args != NULL; args++) {
                p = strchr(*args, '=');
@@ -182,6 +184,15 @@ static void client_auth_parse_args(struct client *client, bool success,
                                        "proxy_timeout value '%s': %s",
                                        value, error);
                        }
+               } else if (strcmp(key, "proxy_host_immediate_failure_after") == 0) {
+                       if (settings_get_time(value,
+                               &reply_r->proxy_host_immediate_failure_after_secs,
+                               &error) < 0) {
+                               e_error(client->event,
+                                       "BUG: Auth service returned invalid "
+                                       "proxy_host_immediate_failure_after value '%s': %s",
+                                       value, error);
+                       }
                } else if (strcmp(key, "proxy_refresh") == 0) {
                        if (str_to_uint(value, &reply_r->proxy_refresh_secs) < 0) {
                                e_error(client->event,
@@ -474,6 +485,8 @@ static int proxy_start(struct client *client,
                proxy_set.connect_timeout_msecs = client->set->login_proxy_timeout;
        proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
        proxy_set.ssl_flags = reply->ssl_flags;
+       proxy_set.host_immediate_failure_after_secs =
+               reply->proxy_host_immediate_failure_after_secs;
 
        /* Include destination ip:port also in the log prefix */
        event_set_append_log_prefix(event, t_strdup_printf(
index cacd347049d11f6451d39e3eae354aef54c8d98f..98bebf154ffb9014fcf805f618668f1b4f0b9920 100644 (file)
@@ -87,6 +87,7 @@ struct client_auth_reply {
        in_port_t port;
        unsigned int proxy_timeout_msecs;
        unsigned int proxy_refresh_secs;
+       unsigned int proxy_host_immediate_failure_after_secs;
        enum login_proxy_ssl_flags ssl_flags;
 
        /* all the key=value fields returned by passdb */
index cf317b5b551715dd8c833d702a29054da3446071..7e6acc40bb17725ee71523c9b31311ff02d04f65 100644 (file)
@@ -29,7 +29,6 @@
 #define KILLED_BY_ADMIN_REASON "Disconnected by proxy: Kicked by admin"
 #define KILLED_BY_DIRECTOR_REASON "Disconnected by proxy: Kicked via director"
 #define KILLED_BY_SHUTDOWN_REASON "Disconnected by proxy: Process shutting down"
-#define PROXY_IMMEDIATE_FAILURE_SECS 30
 /* Wait this long before retrying on reconnect */
 #define PROXY_CONNECT_RETRY_MSECS 1000
 /* Don't even try to reconnect if proxying will timeout in less than this. */
@@ -64,6 +63,7 @@ struct login_proxy {
        in_port_t port;
        unsigned int connect_timeout_msecs;
        unsigned int notify_refresh_secs;
+       unsigned int host_immediate_failure_after_secs;
        unsigned int reconnect_count;
        enum login_proxy_ssl_flags ssl_flags;
 
@@ -314,8 +314,10 @@ static int login_proxy_connect(struct login_proxy *proxy)
                   the check below. */
                rec->last_success.tv_sec = ioloop_timeval.tv_sec - 1;
        }
-       if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 &&
-           rec->last_failure.tv_sec - rec->last_success.tv_sec > PROXY_IMMEDIATE_FAILURE_SECS &&
+       if (proxy->host_immediate_failure_after_secs != 0 &&
+           timeval_cmp(&rec->last_failure, &rec->last_success) > 0 &&
+           rec->last_failure.tv_sec - rec->last_success.tv_sec >
+               proxy->host_immediate_failure_after_secs &&
            rec->num_waiting_connections > 1) {
                /* the server is down. fail immediately */
                proxy->disable_reconnect = TRUE;
@@ -364,6 +366,8 @@ int login_proxy_new(struct client *client, struct event *event,
        proxy->port = set->port;
        proxy->connect_timeout_msecs = set->connect_timeout_msecs;
        proxy->notify_refresh_secs = set->notify_refresh_secs;
+       proxy->host_immediate_failure_after_secs =
+               set->host_immediate_failure_after_secs;
        proxy->ssl_flags = set->ssl_flags;
        proxy->state_rec = login_proxy_state_get(proxy_state, &proxy->ip,
                                                 proxy->port);
index 84db55630179d18975932bf14da6d0b21eb9f25e..2f4be72d62b06977e31bad57827d4c2358449fa3 100644 (file)
@@ -9,6 +9,7 @@
    handle the user. This only works if both proxies support the Dovecot
    TTL extension feature. */
 #define LOGIN_PROXY_TTL 5
+#define LOGIN_PROXY_DEFAULT_HOST_IMMEDIATE_FAILURE_AFTER_SECS 30
 
 #define LOGIN_PROXY_FAILURE_MSG "Account is temporarily unavailable."
 
@@ -54,6 +55,7 @@ struct login_proxy_settings {
        /* send a notification about proxy connection to proxy-notify pipe
           every n seconds */
        unsigned int notify_refresh_secs;
+       unsigned int host_immediate_failure_after_secs;
        enum login_proxy_ssl_flags ssl_flags;
 };