]> jfr.im git - irc/unrealircd/unrealircd.git/commitdiff
Add set::dns and increase DNS timeout for DNSBL (3000ms first, then on retry 6000ms).
authorBram Matthys <redacted>
Wed, 11 Oct 2023 16:56:12 +0000 (18:56 +0200)
committerBram Matthys <redacted>
Wed, 11 Oct 2023 17:04:06 +0000 (19:04 +0200)
This is quite a bit higher than client DNS lookups (1500ms first, on retry 3000ms)
and is because some DNSBL are reported to be quite a bit slower than ordinary DNS.
(Maybe just some, but.. the higher timeout does not hurt anyone anyway)

Note that all this has no effect on client handshake times, as DNSBL checks are
done in the background. Only side-effect is that if we do get a "late hit" then
you may now see a kill a few seconds after the client is online (which was actually
already possible before too for quick clients, but.. yeah...)

These settings can be overriden via set::dns, these are the defaults:

set {
        dns {
                client {
                        timeout 1500;
                        retry 2;
                }
                dnsbl {
                        timeout 3000;
                        retry 2;
                }
        }
}

When you REHASH we will check if the values are different than the current
c-ares settings and if so, reinitialize the resolver. Reinitializing the
resolver will destroy outstanding DNS requests, eg DNS lookups for clients
currently connecting, but so be it. Not a super-huge issue since changing
this is rare.

Requested by BlackBishop in https://bugs.unrealircd.org/view.php?id=6306

include/config.h
include/dynconf.h
include/h.h
src/conf.c
src/dns.c

index 633b7314098c7f347cef7289c69fd649bae9807a..3695edb6db1747100b4a06e626367723ffc8b34e 100644 (file)
 #define UNREALIRCD_DEFAULT_ECDH_CURVES "secp521r1:secp384r1:prime256v1"
 #endif
 
+/* These are just defaults, which you can override via set::dns */
+#define DNS_DEFAULT_CLIENT_TIMEOUT 1500
+#define DNS_DEFAULT_CLIENT_RETRIES 2
+#define DNS_DEFAULT_DNSBL_TIMEOUT 3000
+#define DNS_DEFAULT_DNSBL_RETRIES 2
+
 /* ------------------------- END CONFIGURATION SECTION -------------------- */
 #define MOTD MPATH
 #define RULES RPATH
index 2a3c000fdefd087fcc1d5d7fe5817f430b505c79..4d273a6823034fe041d4bc097dfa78f065f073d8 100644 (file)
@@ -179,6 +179,10 @@ struct Configuration {
        int server_notice_show_event;
        LimitSVSCMDS limit_svscmds;
        int high_connection_rate;
+       int dns_client_timeout;
+       int dns_client_retry;
+       int dns_dnsbl_timeout;
+       int dns_dnsbl_retry;
 };
 
 extern MODVAR Configuration iConf;
index 4480b2a4da8c9f8d4dea139117f21bce6724b754..828f37708a7ea4f23bc86a197e38566fc6421255 100644 (file)
@@ -1126,6 +1126,7 @@ extern void set_targmax_defaults(void);
 extern void parse_chanmodes_protoctl(Client *client, const char *str);
 extern void concat_params(char *buf, int len, int parc, const char *parv[]);
 extern void charsys_check_for_changes(void);
+extern void dns_check_for_changes(void);
 extern MODVAR int maxclients;
 extern int fast_badword_match(ConfigItem_badword *badword, const char *line);
 extern int fast_badword_replace(ConfigItem_badword *badword, const char *line, char *buf, int max);
index 2248c438e88ae8e8bb7fa1a248b689d9a5bc90f0..422a2615f1feb7f76c464a7afe6df2dae28e6ab2 100644 (file)
@@ -1825,6 +1825,10 @@ void config_setdefaultsettings(Configuration *i)
        i->central_spamfilter_except = safe_alloc(sizeof(SecurityGroup));
        i->central_spamfilter_except->reputation_score = 2016; /* 7 days unregged, or 3.5 days identified */
        unreal_add_mask_string(&i->central_spamfilter_except->mask, "*.irccloud.com");
+       i->dns_client_timeout = DNS_DEFAULT_CLIENT_TIMEOUT;
+       i->dns_client_retry = DNS_DEFAULT_CLIENT_RETRIES;
+       i->dns_dnsbl_timeout = DNS_DEFAULT_DNSBL_TIMEOUT;
+       i->dns_dnsbl_retry = DNS_DEFAULT_DNSBL_RETRIES;
 }
 
 /* Some settings have been moved to here - we (re)set some defaults */
@@ -8311,6 +8315,31 @@ int      _conf_set(ConfigFile *conf, ConfigEntry *ce)
                } else if (!strcmp(cep->name, "best-practices"))
                {
                        /* This is handled in config test already (there is no other way) */
+               } else if (!strcmp(cep->name, "dns"))
+               {
+                       for (cepp = cep->items; cepp; cepp = cepp->next)
+                       {
+                               if (!strcmp(cepp->name, "client"))
+                               {
+                                       for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
+                                       {
+                                               if (!strcmp(ceppp->name, "timeout"))
+                                                       tempiConf.dns_client_timeout = atoi(ceppp->value);
+                                               else if (!strcmp(ceppp->name, "retry"))
+                                                       tempiConf.dns_client_retry = atoi(ceppp->value);
+                                       }
+                               } else
+                               if (!strcmp(cepp->name, "dnsbl"))
+                               {
+                                       for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
+                                       {
+                                               if (!strcmp(ceppp->name, "timeout"))
+                                                       tempiConf.dns_dnsbl_timeout = atoi(ceppp->value);
+                                               else if (!strcmp(ceppp->name, "retry"))
+                                                       tempiConf.dns_dnsbl_retry = atoi(ceppp->value);
+                                       }
+                               }
+                       }
                } else if (config_set_dynamic_set_block_item(conf, &dynamic_set, cep))
                {
                        /* Handled by config_set_dynamic_set_block_item - nothing to do here */
@@ -9755,6 +9784,52 @@ int      _test_set(ConfigFile *conf, ConfigEntry *ce)
                                        continue;
                                }
                        }
+               } else if (!strcmp(cep->name, "dns"))
+               {
+                       for (cepp = cep->items; cepp; cepp = cepp->next)
+                       {
+                               if (!strcmp(cepp->name, "client") || !strcmp(cepp->name, "dnsbl"))
+                               {
+                                       for (ceppp = cepp->items; ceppp; ceppp = ceppp->next)
+                                       {
+                                               CheckNull(ceppp);
+                                               if (!strcmp(ceppp->name, "timeout"))
+                                               {
+                                                       int v = atoi(ceppp->value);
+                                                       if ((v < 1000) || (v > 10000))
+                                                       {
+                                                               config_error("%s:%i: the timeout needs to be in milliseconds and in the range 1000-10000.",
+                                                                            ceppp->file->filename, ceppp->line_number);
+                                                               errors++;
+                                                       }
+                                               } else
+                                               if (!strcmp(ceppp->name, "retry"))
+                                               {
+                                                       int v = atoi(ceppp->value);
+                                                       if ((v < 0) || (v > 5))
+                                                       {
+                                                               config_error("%s:%i: retry value needs to be in range 0-5.",
+                                                                            ceppp->file->filename, ceppp->line_number);
+                                                               errors++;
+                                                       }
+                                               } else
+                                               {
+                                                       config_error_unknown(ceppp->file->filename,
+                                                               ceppp->line_number, "set::dns::..::",
+                                                               ceppp->name);
+                                                       errors++;
+                                                       continue;
+                                               }
+                                       }
+                               } else
+                               {
+                                       config_error_unknown(cepp->file->filename,
+                                               cepp->line_number, "set::dns",
+                                               cepp->name);
+                                       errors++;
+                                       continue;
+                               }
+                       }
                } else if ((n = test_dynamic_set_block_item(conf, NULL, cep)) >= 0)
                {
                        /* Handled by test_dynamic_set_block_item:
@@ -9982,6 +10057,7 @@ void config_run(void)
        if (!loop.booted)
                add_proc_io_server();
        free_all_config_resources();
+       dns_check_for_changes();
 }
 
 int    _conf_offchans(ConfigFile *conf, ConfigEntry *ce)
index b77aa4b985e1c58fdf8a4bc4bf864586c580557c..024532619df00383ac13457c34a942bf2251a24f 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -157,14 +157,6 @@ void init_resolver(int firsttime)
        }
 
        memset(&options, 0, sizeof(options));
-       options.timeout = 1500; /* 1.5 seconds */
-       options.tries = 2;
-       /* Note that the effective DNS timeout is NOT simply 1500*2=3000.
-        * This is because c-ares does some incremental timeout stuff itself
-        * that may add up to twice the timeout in the second round,
-        * so effective max is 1500ms first and then up to 3000s, so 4500ms in total
-        * (until they change the algorithm again, that is...).
-        */
        options.flags |= ARES_FLAG_NOALIASES|ARES_FLAG_IGNTC;
        options.sock_state_cb = unrealdns_sock_state_cb;
        /* Don't search domains or you'll get lookups for like
@@ -181,8 +173,10 @@ void init_resolver(int firsttime)
        optmask |= ARES_OPT_LOOKUPS;
 #endif
 
-       /* First the client channel */
+       /*** First the client channel ***/
        options.sock_state_cb_data = RESOLVER_CHANNEL_CLIENT;
+       options.timeout = iConf.dns_client_timeout ? iConf.dns_client_timeout : DNS_DEFAULT_CLIENT_TIMEOUT;
+       options.tries = iConf.dns_client_retry ? iConf.dns_client_retry : DNS_DEFAULT_CLIENT_RETRIES;
        n = ares_init_options(&resolver_channel_client, &options, optmask);
        if (n != ARES_SUCCESS)
        {
@@ -197,6 +191,8 @@ void init_resolver(int firsttime)
 
        /* And then the DNSBL channel */
        options.sock_state_cb_data = RESOLVER_CHANNEL_DNSBL;
+       options.timeout = iConf.dns_dnsbl_timeout ? iConf.dns_dnsbl_timeout : DNS_DEFAULT_DNSBL_TIMEOUT;
+       options.tries = iConf.dns_dnsbl_retry ? iConf.dns_dnsbl_retry : DNS_DEFAULT_DNSBL_RETRIES;
        n = ares_init_options(&resolver_channel_dnsbl, &options, optmask);
        if (n != ARES_SUCCESS)
        {
@@ -667,6 +663,34 @@ void unrealdns_delasyncconnects(void)
        
 }
 
+void dns_check_for_changes(void)
+{
+       struct ares_options inf;
+       int changed = 0;
+       int optmask;
+
+       memset(&inf, 0, sizeof(inf));
+       ares_save_options(resolver_channel_client, &inf, &optmask);
+       if ((inf.timeout != iConf.dns_client_timeout) || (inf.tries != iConf.dns_client_retry))
+               changed = 1;
+       ares_destroy_options(&inf);
+
+       memset(&inf, 0, sizeof(inf));
+       ares_save_options(resolver_channel_dnsbl, &inf, &optmask);
+       if ((inf.timeout != iConf.dns_dnsbl_timeout) || (inf.tries != iConf.dns_dnsbl_retry))
+               changed = 1;
+       ares_destroy_options(&inf);
+
+       if (changed)
+       {
+               if (loop.booted)
+                       config_status("DNS Configuration changed, reinitializing DNS...");
+               ares_destroy(resolver_channel_client);
+               ares_destroy(resolver_channel_dnsbl);
+               init_resolver(0);
+       }
+}
+
 CMD_FUNC(cmd_dns)
 {
        DNSCache *c;
@@ -749,6 +773,7 @@ CMD_FUNC(cmd_dns)
                        sendtxtnumeric(client, "        timeout: %d", inf.timeout);
                if (optmask & ARES_OPT_TRIES)
                        sendtxtnumeric(client, "          tries: %d", inf.tries);
+               ares_destroy_options(&inf);
 
                sendtxtnumeric(client, "=== DNSBL resolver channel ===");
                i = 0;
@@ -768,10 +793,10 @@ CMD_FUNC(cmd_dns)
                        sendtxtnumeric(client, "        timeout: %d", inf.timeout);
                if (optmask & ARES_OPT_TRIES)
                        sendtxtnumeric(client, "          tries: %d", inf.tries);
+               ares_destroy_options(&inf);
 
                sendtxtnumeric(client, "****** End of DNS Configuration Info ******");
 
-               ares_destroy_options(&inf);
        } else /* STATISTICS */
        {
                sendtxtnumeric(client, "DNS CACHE Stats:");