- Fix #618: enabling interface-automatic disables DNS-over-TLS.

Adds the option to list interface-automatic-ports.
This commit is contained in:
W.C.A. Wijngaards 2022-02-11 10:58:53 +01:00
parent 4c6b59fa47
commit a0feea393a
12 changed files with 4112 additions and 3278 deletions

View file

@ -1,6 +1,8 @@
11 February 2022: Wouter 11 February 2022: Wouter
- Fix #624: Unable to stop Unbound in Windows console (does not - Fix #624: Unable to stop Unbound in Windows console (does not
respond to CTRL+C command). respond to CTRL+C command).
- Fix #618: enabling interface-automatic disables DNS-over-TLS.
Adds the option to list interface-automatic-ports.
7 February 2022: Wouter 7 February 2022: Wouter
- Fix that TCP interface does not use TLS when TLS is also configured. - Fix that TCP interface does not use TLS when TLS is also configured.

View file

@ -55,6 +55,10 @@ server:
# Socket options are not supported on all platforms. experimental. # Socket options are not supported on all platforms. experimental.
# interface-automatic: no # interface-automatic: no
# instead of the default port, open additional ports separated by
# spaces when interface-automatic is enabled, by listing them here.
# interface-automatic-ports: ""
# port to answer queries from # port to answer queries from
# port: 53 # port: 53

View file

@ -140,6 +140,15 @@ ip\-transparent you can select which (future) interfaces Unbound provides
service on. This feature is experimental, and needs support in your OS for service on. This feature is experimental, and needs support in your OS for
particular socket options. Default value is no. particular socket options. Default value is no.
.TP .TP
.B interface\-automatic\-ports: \fI<string>
List the port numbers that interface-automatic listens on. If empty, the
default port is listened on. The port numbers are separated by spaces in the
string. Default is "".
.IP
This can be used to have interface automatic to deal with the interface,
and listen on the normal port number, by including it in the list, and
also https or dns over tls port numbers by putting them in the list as well.
.TP
.B outgoing\-interface: \fI<ip address or ip6 netblock> .B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given queries to authoritative servers and receive their replies. Can be given

View file

@ -47,6 +47,7 @@
#ifdef USE_TCP_FASTOPEN #ifdef USE_TCP_FASTOPEN
#include <netinet/tcp.h> #include <netinet/tcp.h>
#endif #endif
#include <ctype.h>
#include "services/listen_dnsport.h" #include "services/listen_dnsport.h"
#include "services/outside_network.h" #include "services/outside_network.h"
#include "util/netevent.h" #include "util/netevent.h"
@ -1716,6 +1717,63 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
} }
/* create ip4 and ip6 ports so that return addresses are nice. */ /* create ip4 and ip6 ports so that return addresses are nice. */
if(do_auto || num_ifs == 0) { if(do_auto || num_ifs == 0) {
if(do_auto && cfg->if_automatic_ports &&
cfg->if_automatic_ports[0]!=0) {
char* now = cfg->if_automatic_ports;
while(now && *now) {
char* after;
int extraport;
while(isspace((unsigned char)*now))
now++;
if(!*now)
break;
after = now;
extraport = (int)strtol(now, &after, 10);
if(extraport < 0 || extraport > 65535) {
log_err("interface-automatic-ports port number out of range, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports);
listening_ports_free(list);
return NULL;
}
if(extraport == 0 && now == after) {
log_err("interface-automatic-ports could not be parsed, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports);
listening_ports_free(list);
return NULL;
}
now = after;
snprintf(portbuf, sizeof(portbuf), "%d", extraport);
if(do_ip6) {
hints.ai_family = AF_INET6;
if(!ports_create_if("::0",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
}
if(do_ip4) {
hints.ai_family = AF_INET;
if(!ports_create_if("0.0.0.0",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
}
}
return list;
}
if(do_ip6) { if(do_ip6) {
hints.ai_family = AF_INET6; hints.ai_family = AF_INET6;
if(!ports_create_if(do_auto?"::0":"::1", if(!ports_create_if(do_auto?"::0":"::1",

View file

@ -408,6 +408,29 @@ interfacechecks(struct config_file* cfg)
} }
} }
/** check interface-automatic-ports */
static void
ifautomaticportschecks(char* ifautomaticports)
{
char* now = ifautomaticports;
while(now && *now) {
char* after;
int extraport;
while(isspace((unsigned char)*now))
now++;
if(!*now)
break;
after = now;
extraport = (int)strtol(now, &after, 10);
if(extraport < 0 || extraport > 65535)
fatal_exit("interface-automatic-ports: port out of range at position %d in '%s'", (int)(now-ifautomaticports)+1, ifautomaticports);
if(extraport == 0 && now == after)
fatal_exit("interface-automatic-ports: parse error at position %d in '%s'", (int)(now-ifautomaticports)+1, ifautomaticports);
log_info("extraport %d", extraport);
now = after;
}
}
/** check acl ips */ /** check acl ips */
static void static void
aclchecks(struct config_file* cfg) aclchecks(struct config_file* cfg)
@ -608,6 +631,7 @@ morechecks(struct config_file* cfg)
warn_hosts("stub-host", cfg->stubs); warn_hosts("stub-host", cfg->stubs);
warn_hosts("forward-host", cfg->forwards); warn_hosts("forward-host", cfg->forwards);
interfacechecks(cfg); interfacechecks(cfg);
ifautomaticportschecks(cfg->if_automatic_ports);
aclchecks(cfg); aclchecks(cfg);
tcpconnlimitchecks(cfg); tcpconnlimitchecks(cfg);

View file

@ -195,6 +195,7 @@ config_create(void)
cfg->use_systemd = 0; cfg->use_systemd = 0;
cfg->do_daemonize = 1; cfg->do_daemonize = 1;
cfg->if_automatic = 0; cfg->if_automatic = 0;
cfg->if_automatic_ports = NULL;
cfg->so_rcvbuf = 0; cfg->so_rcvbuf = 0;
cfg->so_sndbuf = 0; cfg->so_sndbuf = 0;
cfg->so_reuseport = REUSEPORT_DEFAULT; cfg->so_reuseport = REUSEPORT_DEFAULT;
@ -559,6 +560,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("http-nodelay:", http_nodelay) else S_YNO("http-nodelay:", http_nodelay)
else S_YNO("http-notls-downstream:", http_notls_downstream) else S_YNO("http-notls-downstream:", http_notls_downstream)
else S_YNO("interface-automatic:", if_automatic) else S_YNO("interface-automatic:", if_automatic)
else S_STR("interface-automatic-ports:", if_automatic_ports)
else S_YNO("use-systemd:", use_systemd) else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize) else S_YNO("do-daemonize:", do_daemonize)
else S_NUMBER_NONZERO("port:", port) else S_NUMBER_NONZERO("port:", port)
@ -990,6 +992,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_IFC(opt, "interface", num_ifs, ifs) else O_IFC(opt, "interface", num_ifs, ifs)
else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs) else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs)
else O_YNO(opt, "interface-automatic", if_automatic) else O_YNO(opt, "interface-automatic", if_automatic)
else O_STR(opt, "interface-automatic-ports", if_automatic_ports)
else O_DEC(opt, "port", port) else O_DEC(opt, "port", port)
else O_DEC(opt, "outgoing-range", outgoing_num_ports) else O_DEC(opt, "outgoing-range", outgoing_num_ports)
else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp) else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp)
@ -1534,6 +1537,7 @@ config_delete(struct config_file* cfg)
free(cfg->directory); free(cfg->directory);
free(cfg->logfile); free(cfg->logfile);
free(cfg->pidfile); free(cfg->pidfile);
free(cfg->if_automatic_ports);
free(cfg->target_fetch_policy); free(cfg->target_fetch_policy);
free(cfg->ssl_service_key); free(cfg->ssl_service_key);
free(cfg->ssl_service_pem); free(cfg->ssl_service_pem);

View file

@ -205,6 +205,8 @@ struct config_file {
/** automatic interface for incoming messages. Uses ipv6 remapping, /** automatic interface for incoming messages. Uses ipv6 remapping,
* and recvmsg/sendmsg ancillary data to detect interfaces, boolean */ * and recvmsg/sendmsg ancillary data to detect interfaces, boolean */
int if_automatic; int if_automatic;
/** extra ports to open if if_automatic enabled, or NULL for default */
char* if_automatic_ports;
/** SO_RCVBUF size to set on port 53 UDP socket */ /** SO_RCVBUF size to set on port 53 UDP socket */
size_t so_rcvbuf; size_t so_rcvbuf;
/** SO_SNDBUF size to set on port 53 UDP socket */ /** SO_SNDBUF size to set on port 53 UDP socket */

File diff suppressed because it is too large Load diff

View file

@ -272,6 +272,7 @@ interface{COLON} { YDVAR(1, VAR_INTERFACE) }
ip-address{COLON} { YDVAR(1, VAR_INTERFACE) } ip-address{COLON} { YDVAR(1, VAR_INTERFACE) }
outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) } outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) }
interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) } interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) }
interface-automatic-ports{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC_PORTS) }
so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) } so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) }
so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) } so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) } so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.7.6. */ /* A Bison parser, made by GNU Bison 3.6.4. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc. Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -16,7 +16,7 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains /* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work part or all of the Bison parser skeleton and distribute that work
@ -374,12 +374,12 @@ extern int yydebug;
VAR_ZONEMD_PERMISSIVE_MODE = 575, /* VAR_ZONEMD_PERMISSIVE_MODE */ VAR_ZONEMD_PERMISSIVE_MODE = 575, /* VAR_ZONEMD_PERMISSIVE_MODE */
VAR_ZONEMD_CHECK = 576, /* VAR_ZONEMD_CHECK */ VAR_ZONEMD_CHECK = 576, /* VAR_ZONEMD_CHECK */
VAR_ZONEMD_REJECT_ABSENCE = 577, /* VAR_ZONEMD_REJECT_ABSENCE */ VAR_ZONEMD_REJECT_ABSENCE = 577, /* VAR_ZONEMD_REJECT_ABSENCE */
VAR_RPZ_SIGNAL_NXDOMAIN_RA = 578 /* VAR_RPZ_SIGNAL_NXDOMAIN_RA */ VAR_RPZ_SIGNAL_NXDOMAIN_RA = 578, /* VAR_RPZ_SIGNAL_NXDOMAIN_RA */
VAR_INTERFACE_AUTOMATIC_PORTS = 579 /* VAR_INTERFACE_AUTOMATIC_PORTS */
}; };
typedef enum yytokentype yytoken_kind_t; typedef enum yytokentype yytoken_kind_t;
#endif #endif
/* Token kinds. */ /* Token kinds. */
#define YYEMPTY -2
#define YYEOF 0 #define YYEOF 0
#define YYerror 256 #define YYerror 256
#define YYUNDEF 257 #define YYUNDEF 257
@ -704,6 +704,7 @@ extern int yydebug;
#define VAR_ZONEMD_CHECK 576 #define VAR_ZONEMD_CHECK 576
#define VAR_ZONEMD_REJECT_ABSENCE 577 #define VAR_ZONEMD_REJECT_ABSENCE 577
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 578 #define VAR_RPZ_SIGNAL_NXDOMAIN_RA 578
#define VAR_INTERFACE_AUTOMATIC_PORTS 579
/* Value type. */ /* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@ -713,7 +714,7 @@ union YYSTYPE
char* str; char* str;
#line 717 "util/configparser.h" #line 718 "util/configparser.h"
}; };
typedef union YYSTYPE YYSTYPE; typedef union YYSTYPE YYSTYPE;

View file

@ -188,7 +188,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DYNLIB VAR_DYNLIB_FILE VAR_EDNS_CLIENT_STRING %token VAR_DYNLIB VAR_DYNLIB_FILE VAR_EDNS_CLIENT_STRING
%token VAR_EDNS_CLIENT_STRING_OPCODE VAR_NSID %token VAR_EDNS_CLIENT_STRING_OPCODE VAR_NSID
%token VAR_ZONEMD_PERMISSIVE_MODE VAR_ZONEMD_CHECK VAR_ZONEMD_REJECT_ABSENCE %token VAR_ZONEMD_PERMISSIVE_MODE VAR_ZONEMD_CHECK VAR_ZONEMD_REJECT_ABSENCE
%token VAR_RPZ_SIGNAL_NXDOMAIN_RA %token VAR_RPZ_SIGNAL_NXDOMAIN_RA VAR_INTERFACE_AUTOMATIC_PORTS
%% %%
toplevelvars: /* empty */ | toplevelvars toplevelvar ; toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -311,7 +311,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_tls_use_sni | server_edns_client_string | server_tls_use_sni | server_edns_client_string |
server_edns_client_string_opcode | server_nsid | server_edns_client_string_opcode | server_nsid |
server_zonemd_permissive_mode | server_max_reuse_tcp_queries | server_zonemd_permissive_mode | server_max_reuse_tcp_queries |
server_tcp_reuse_timeout | server_tcp_auth_query_timeout server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
server_interface_automatic_ports
; ;
stubstart: VAR_STUB_ZONE stubstart: VAR_STUB_ZONE
@ -800,6 +801,13 @@ server_interface_automatic: VAR_INTERFACE_AUTOMATIC STRING_ARG
free($2); free($2);
} }
; ;
server_interface_automatic_ports: VAR_INTERFACE_AUTOMATIC_PORTS STRING_ARG
{
OUTYY(("P(server_interface_automatic_ports:%s)\n", $2));
free(cfg_parser->cfg->if_automatic_ports);
cfg_parser->cfg->if_automatic_ports = $2;
}
;
server_do_ip4: VAR_DO_IP4 STRING_ARG server_do_ip4: VAR_DO_IP4 STRING_ARG
{ {
OUTYY(("P(server_do_ip4:%s)\n", $2)); OUTYY(("P(server_do_ip4:%s)\n", $2));