mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-20 02:38:32 +00:00
Add --port-limit option.
By default, when sending a query via random ports to multiple upstream servers or retrying a query dnsmasq will use a single random port for all the tries/retries. This option allows a larger number of ports to be used, which can increase robustness in certain network configurations. Note that increasing this to more than two or three can have security and resource implications and should only be done with understanding of those.
This commit is contained in:
@@ -182,6 +182,14 @@ spoofing attacks but it may be faster and use less resources. Setting this opti
|
||||
to zero makes dnsmasq use a single port allocated to it by the
|
||||
OS: this was the default behaviour in versions prior to 2.43.
|
||||
.TP
|
||||
.B --port-limit=<#ports>
|
||||
By default, when sending a query via random ports to multiple upstream servers or
|
||||
retrying a query dnsmasq will use a single random port for all the tries/retries.
|
||||
This option allows a larger number of ports to be used, which can increase robustness
|
||||
in certain network configurations. Note that increasing this to more than
|
||||
two or three can have security and resource implications and should only
|
||||
be done with understanding of those.
|
||||
.TP
|
||||
.B --min-port=<port>
|
||||
Do not use ports less than that given as source for outbound DNS
|
||||
queries. Dnsmasq picks random ports as source for outbound queries:
|
||||
|
||||
@@ -1139,6 +1139,7 @@ extern struct daemon {
|
||||
int log_fac; /* log facility */
|
||||
char *log_file; /* optional log file */
|
||||
int max_logs; /* queue limit */
|
||||
int randport_limit; /* Maximum number of source ports for query. */
|
||||
int cachesize, ftabsize;
|
||||
int port, query_port, min_port, max_port;
|
||||
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
|
||||
|
||||
@@ -2311,7 +2311,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
|
||||
{
|
||||
static int finger = 0;
|
||||
int i, j = 0;
|
||||
struct randfd_list *rfl;
|
||||
struct randfd_list **up, *rfl, *found, **found_link;
|
||||
struct randfd *rfd = NULL;
|
||||
int fd = 0;
|
||||
|
||||
@@ -2319,16 +2319,26 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
|
||||
if (serv->sfd)
|
||||
return serv->sfd->fd;
|
||||
|
||||
/* existing suitable random port socket linked to this transaction? */
|
||||
for (rfl = *fdlp; rfl; rfl = rfl->next)
|
||||
/* existing suitable random port socket linked to this transaction?
|
||||
Find the last one in the list and count how many there are. */
|
||||
for (found = NULL, found_link = NULL, i = 0, up = fdlp, rfl = *fdlp; rfl; up = &rfl->next, rfl = rfl->next)
|
||||
if (server_isequal(serv, rfl->rfd->serv))
|
||||
return rfl->rfd->fd;
|
||||
{
|
||||
i++;
|
||||
found = rfl;
|
||||
found_link = up;
|
||||
}
|
||||
|
||||
/* No. need new link. */
|
||||
if ((rfl = daemon->rfl_spare))
|
||||
daemon->rfl_spare = rfl->next;
|
||||
else if (!(rfl = whine_malloc(sizeof(struct randfd_list))))
|
||||
return -1;
|
||||
/* We have the maximum number for this query already. Promote
|
||||
the last one on the list to the head, to circulate them,
|
||||
and return it. */
|
||||
if (found && i >= daemon->randport_limit)
|
||||
{
|
||||
*found_link = found->next;
|
||||
found->next = *fdlp;
|
||||
*fdlp = found;
|
||||
return found->rfd->fd;
|
||||
}
|
||||
|
||||
/* limit the number of sockets we have open to avoid starvation of
|
||||
(eg) TFTP. Once we have a reasonable number, randomness should be OK */
|
||||
@@ -2345,6 +2355,31 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
|
||||
break;
|
||||
}
|
||||
|
||||
/* We've hit the global limit on sockets before hitting the query limit,
|
||||
use an exsiting socket as source in that case. */
|
||||
if (!rfd && found)
|
||||
{
|
||||
*found_link = found->next;
|
||||
found->next = *fdlp;
|
||||
*fdlp = found;
|
||||
return found->rfd->fd;
|
||||
}
|
||||
|
||||
/* No good existing. Need new link. */
|
||||
if ((rfl = daemon->rfl_spare))
|
||||
daemon->rfl_spare = rfl->next;
|
||||
else if (!(rfl = whine_malloc(sizeof(struct randfd_list))))
|
||||
{
|
||||
/* malloc failed, don't leak allocated sock */
|
||||
if (rfd)
|
||||
{
|
||||
close(rfd->fd);
|
||||
rfd->refcount = 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No free ones or cannot get new socket, grab an existing one */
|
||||
if (!rfd)
|
||||
for (j = 0; j < daemon->numrrand; j++)
|
||||
|
||||
@@ -181,6 +181,7 @@ struct myoption {
|
||||
#define LOPT_STRIP_MAC 372
|
||||
#define LOPT_CONF_OPT 373
|
||||
#define LOPT_CONF_SCRIPT 374
|
||||
#define LOPT_RANDPORT_LIM 375
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -366,6 +367,7 @@ static const struct myoption opts[] =
|
||||
{ "log-debug", 0, 0, LOPT_LOG_DEBUG },
|
||||
{ "umbrella", 2, 0, LOPT_UMBRELLA },
|
||||
{ "quiet-tftp", 0, 0, LOPT_QUIET_TFTP },
|
||||
{ "port-limit", 1, 0, LOPT_RANDPORT_LIM },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -430,6 +432,7 @@ static struct {
|
||||
{ 'P', ARG_ONE, "<integer>", gettext_noop("Maximum supported UDP packet size for EDNS.0 (defaults to %s)."), "*" },
|
||||
{ 'q', ARG_DUP, NULL, gettext_noop("Log DNS queries."), NULL },
|
||||
{ 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
|
||||
{ LOPT_RANDPORT_LIM, ARG_ONE, "#ports", gettext_noop("Set maximum number of random originating ports for a query."), NULL },
|
||||
{ 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
|
||||
{ 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
|
||||
{ LOPT_SERVERS_FILE, ARG_ONE, "<path>", gettext_noop("Specify path to file with server= options"), NULL },
|
||||
@@ -3180,6 +3183,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
daemon->osport = 1;
|
||||
break;
|
||||
|
||||
case LOPT_RANDPORT_LIM: /* --port-limit */
|
||||
if (!atoi_check(arg, &daemon->randport_limit) || (daemon->randport_limit < 1))
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
|
||||
case 'T': /* --local-ttl */
|
||||
case LOPT_NEGTTL: /* --neg-ttl */
|
||||
case LOPT_MAXTTL: /* --max-ttl */
|
||||
@@ -5494,6 +5502,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
daemon->soa_refresh = SOA_REFRESH;
|
||||
daemon->soa_retry = SOA_RETRY;
|
||||
daemon->soa_expiry = SOA_EXPIRY;
|
||||
daemon->randport_limit = 1;
|
||||
|
||||
#ifndef NO_ID
|
||||
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
|
||||
|
||||
Reference in New Issue
Block a user