- ACL per interface: refactor, complete testing and a bugfix for

interface names.
This commit is contained in:
George Thessalonikefs 2022-09-11 20:57:41 +02:00
parent fc123303ac
commit d301bfe4a2
14 changed files with 339 additions and 104 deletions

View file

@ -139,7 +139,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
$(CACHEDB_SRC) respip/respip.c $(CHECKLOCK_SRC) \
$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC) daemon/acl_list.c
$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC) $(IPSET_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
@ -154,7 +154,7 @@ val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo acl_list.lo
outside_network.lo
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
# set to $COMMON_OBJ or to "" if --enableallsymbols
COMMON_OBJ_ALL_SYMBOLS=@COMMON_OBJ_ALL_SYMBOLS@
@ -186,9 +186,9 @@ readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo unitzonemd.lo \
unittcpreuse.lo
UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
$(COMPAT_OBJ)
DAEMON_SRC=daemon/cachedump.c daemon/daemon.c \
DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@
DAEMON_OBJ=cachedump.lo daemon.lo \
DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo \
shm_main.lo remote.lo stats.lo unbound.lo \
worker.lo @WIN_DAEMON_OBJ@
DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \

View file

@ -142,8 +142,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
/** find or create node (NULL on parse or error) */
static struct acl_addr*
acl_find_or_create(struct acl_list* acl, const char* str, int is_interface,
int port)
acl_find_or_create_str2addr(struct acl_list* acl, const char* str,
int is_interface, int port)
{
struct acl_addr* node;
struct sockaddr_storage addr;
@ -174,6 +174,27 @@ acl_find_or_create(struct acl_list* acl, const char* str, int is_interface,
return node;
}
/** find or create node (NULL on error) */
static struct acl_addr*
acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen, enum acl_access control)
{
struct acl_addr* node;
int net = (addr_is_ip6(addr, addrlen)?128:32);
/* find or create node */
if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr,
addrlen, net))) {
/* create node;
* can override with specific access-control: cfg */
if(!(node=(struct acl_addr*)acl_list_insert(acl, addr,
addrlen, net, control, 1))) {
log_err("out of memory");
return NULL;
}
}
return node;
}
/** apply acl_interface string */
static int
acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
@ -184,7 +205,7 @@ acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
if(!parse_acl_access(s2, &control)) {
return 0;
}
if(!(node=acl_find_or_create(acl_interface, interface, 1, port))) {
if(!(node=acl_find_or_create_str2addr(acl_interface, interface, 1, port))) {
log_err("cannot update ACL on non-configured interface: %s %d",
interface, port);
return 0;
@ -194,25 +215,11 @@ acl_interface_str_cfg(struct acl_list* acl_interface, const char* interface,
}
struct acl_addr*
acl_interface_insert(struct acl_list* acl_interface, const char* interface,
const char* s2, int port)
acl_interface_insert(struct acl_list* acl_interface,
struct sockaddr_storage* addr, socklen_t addrlen,
enum acl_access control)
{
struct acl_addr* node;
struct sockaddr_storage addr;
socklen_t addrlen;
enum acl_access control;
int net = (str_is_ip6(interface)?128:32);
if(!parse_acl_access(s2, &control)) {
return NULL;
}
if((node=acl_find_or_create(acl_interface, interface, 1, port))) {
return node;
}
if(!extstrtoaddr(interface, &addr, &addrlen, port)) {
log_err("cannot parse access control: %s %s", interface, s2);
return NULL;
}
return acl_list_insert(acl_interface, &addr, addrlen, net, control, 1);
return acl_find_or_create(acl_interface, addr, addrlen, control);
}
/** apply acl_tag string */
@ -221,7 +228,7 @@ acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
size_t bitmaplen, int is_interface, int port)
{
struct acl_addr* node;
if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
if(is_interface)
log_err("non-configured interface: %s", str);
return 0;
@ -241,7 +248,7 @@ acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
struct views* vs, int is_interface, int port)
{
struct acl_addr* node;
if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
if(is_interface)
log_err("non-configured interface: %s", str);
return 0;
@ -264,7 +271,7 @@ acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
struct acl_addr* node;
int tagid;
enum localzone_type t;
if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
if(is_interface)
log_err("non-configured interface: %s", str);
return 0;
@ -357,7 +364,7 @@ acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
struct acl_addr* node;
int tagid;
char* dupdata;
if(!(node=acl_find_or_create(acl, str, is_interface, port))) {
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
if(is_interface)
log_err("non-configured interface: %s", str);
return 0;
@ -557,10 +564,12 @@ void
acl_interface_init(struct acl_list* acl_interface)
{
regional_free_all(acl_interface->region);
/* We want comparison in the tree to include both IP and port.
* Initialise with the given compare fucntion but keep treating it as
* an addr_tree. */
rbtree_init(&acl_interface->tree, &acl_interface_compare);
/* We want comparison in the tree to include only address and port.
* We don't care about comparing node->net. All addresses in the
* acl_interface->tree should have either 32 (ipv4) or 128 (ipv6).
* Initialise with the appropriate compare fucntion but keep treating
* it as an addr_tree. */
addr_tree_addrport_init(&acl_interface->tree);
}
static int
@ -604,7 +613,7 @@ read_acl_interface_view(struct acl_list* acl_interface,
return 0;
}
for(i = 0; i<num_resif; i++) {
if(!acl_list_view_cfg(acl_interface, p->str, p->str2,
if(!acl_list_view_cfg(acl_interface, resif[i], p->str2,
v, 1, port)) {
config_del_strarray(resif, num_resif);
config_deldblstrlist(p);
@ -639,7 +648,7 @@ read_acl_interface_tags(struct acl_list* acl_interface,
return 0;
}
for(i = 0; i<num_resif; i++) {
if(!acl_list_tags_cfg(acl_interface, p->str, p->str2,
if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2,
p->str2len, 1, port)) {
config_del_strbytelist(p);
config_del_strarray(resif, num_resif);
@ -676,8 +685,8 @@ read_acl_interface_tag_actions(struct acl_list* acl_interface,
return 0;
}
for(i = 0; i<num_resif; i++) {
if(!acl_list_tag_action_cfg(acl_interface, cfg, p->str,
p->str2, p->str3, 1, port)) {
if(!acl_list_tag_action_cfg(acl_interface, cfg,
resif[i], p->str2, p->str3, 1, port)) {
config_deltrplstrlist(p);
config_del_strarray(resif, num_resif);
return 0;
@ -714,8 +723,8 @@ read_acl_interface_tag_datas(struct acl_list* acl_interface,
return 0;
}
for(i = 0; i<num_resif; i++) {
if(!acl_list_tag_data_cfg(acl_interface, cfg, p->str,
p->str2, p->str3, 1, port)) {
if(!acl_list_tag_data_cfg(acl_interface, cfg,
resif[i], p->str2, p->str3, 1, port)) {
config_deltrplstrlist(p);
config_del_strarray(resif, num_resif);
return 0;

View file

@ -123,14 +123,15 @@ void acl_list_delete(struct acl_list* acl);
* Insert interface in the alc_list. This should happen when the listening
* interface is setup.
* @param acl_interface: acl_list to insert to.
* @param interface: interface (IP) in string format.
* @param s2: acl_access in string format.
* @param port: default port.
* @param addr: interface IP.
* @param addrlen: length of the interface IP.
* @param control: acl_access.
* @return new structure or NULL on error.
*/
struct acl_addr*
acl_interface_insert(struct acl_list* acl_interface, const char* interface,
const char* s2, int port);
acl_interface_insert(struct acl_list* acl_interface,
struct sockaddr_storage* addr, socklen_t addrlen,
enum acl_access control);
/**
* Process access control config.

View file

@ -96,6 +96,9 @@
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
/** How many quit requests happened. */
static int sig_record_quit = 0;
@ -314,6 +317,29 @@ daemon_init(void)
return daemon;
}
static int setup_acl_for_ports(struct acl_list* list,
struct listen_port* port_list)
{
struct acl_addr* acl_node;
struct addrinfo* addr;
for(; port_list; port_list=port_list->next) {
if(!port_list->socket) {
/* This is mainly for testbound where port_list is
* empty. */
continue;
}
addr = port_list->socket->addr;
if(!(acl_node = acl_interface_insert(list,
(struct sockaddr_storage*)addr->ai_addr,
(socklen_t)addr->ai_addrlen,
acl_refuse))) {
return 0;
}
port_list->socket->acl = acl_node;
}
return 1;
}
int
daemon_open_shared_ports(struct daemon* daemon)
{
@ -342,8 +368,8 @@ daemon_open_shared_ports(struct daemon* daemon)
daemon->reuseport = 1;
#endif
/* try to use reuseport */
p0 = listening_ports_open(daemon->cfg, daemon->acl_interface,
resif, num_resif, &daemon->reuseport);
p0 = listening_ports_open(daemon->cfg, resif, num_resif,
&daemon->reuseport);
if(!p0) {
listening_ports_free(p0);
config_del_strarray(resif, num_resif);
@ -364,12 +390,17 @@ daemon_open_shared_ports(struct daemon* daemon)
return 0;
}
daemon->ports[0] = p0;
if(!setup_acl_for_ports(daemon->acl_interface,
daemon->ports[0])) {
listening_ports_free(p0);
config_del_strarray(resif, num_resif);
return 0;
}
if(daemon->reuseport) {
/* continue to use reuseport */
for(i=1; i<daemon->num_ports; i++) {
if(!(daemon->ports[i]=
listening_ports_open(daemon->cfg,
daemon->acl_interface,
resif, num_resif,
&daemon->reuseport))
|| !daemon->reuseport ) {
@ -380,6 +411,15 @@ daemon_open_shared_ports(struct daemon* daemon)
config_del_strarray(resif, num_resif);
return 0;
}
if(!setup_acl_for_ports(daemon->acl_interface,
daemon->ports[i])) {
for(i=0; i<daemon->num_ports; i++)
listening_ports_free(daemon->ports[i]);
free(daemon->ports);
daemon->ports = NULL;
config_del_strarray(resif, num_resif);
return 0;
}
}
}
config_del_strarray(resif, num_resif);

View file

@ -1196,7 +1196,6 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param hints: for getaddrinfo. family and flags have to be set by caller.
* @param port: Port number to use (as string).
* @param list: list of open ports, appended to, changed to point to list head.
* @param acl_interface: acl list with options for the interface.
* @param rcv: receive buffer size for UDP
* @param snd: send buffer size for UDP
* @param ssl_port: ssl service port number
@ -1216,7 +1215,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
struct acl_list* acl_interface, size_t rcv, size_t snd, int ssl_port,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int https_port,
int* reuseport, int transparent, int tcp_mss, int freebind,
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
@ -1225,7 +1224,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
int is_https = if_is_https(ifname, port, https_port);
int nodelay = is_https && http2_nodelay;
struct unbound_socket* ub_sock;
struct acl_addr* acl_node;
#ifdef USE_DNSCRYPT
int is_dnscrypt = ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
@ -1240,7 +1238,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_auto) {
ub_sock = calloc(1, sizeof(struct unbound_socket));
acl_node = NULL;
if(!ub_sock)
return 0;
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
@ -1269,17 +1266,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
free(ub_sock);
return 0;
}
if(!(acl_node = acl_interface_insert(acl_interface, ifname,
"refuse", ntohs(((struct sockaddr_in*)ub_sock->addr->ai_addr)->sin_port)))) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
ub_sock->acl = acl_node;
} else if(do_udp) {
ub_sock = calloc(1, sizeof(struct unbound_socket));
acl_node = NULL;
if(!ub_sock)
return 0;
/* regular udp socket */
@ -1301,21 +1289,12 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
free(ub_sock);
return 0;
}
if(!(acl_node = acl_interface_insert(acl_interface, ifname,
"refuse", ntohs(((struct sockaddr_in*)ub_sock->addr->ai_addr)->sin_port)))) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
ub_sock->acl = acl_node;
}
if(do_tcp) {
int is_ssl = if_is_ssl(ifname, port, ssl_port,
tls_additional_port);
enum listen_type port_type;
ub_sock = calloc(1, sizeof(struct unbound_socket));
acl_node = NULL;
if(!ub_sock)
return 0;
if(is_ssl)
@ -1345,14 +1324,6 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
free(ub_sock);
return 0;
}
if(!(acl_node = acl_interface_insert(acl_interface, ifname,
"refuse", ntohs(((struct sockaddr_in*)ub_sock->addr->ai_addr)->sin_port)))) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
ub_sock->acl = acl_node;
}
return 1;
}
@ -1750,8 +1721,8 @@ int resolve_interface_names(char** ifs, int num_ifs,
}
struct listen_port*
listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
char** ifs, int num_ifs, int* reuseport)
listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
int* reuseport)
{
struct listen_port* list = NULL;
struct addrinfo hints;
@ -1842,7 +1813,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
hints.ai_family = AF_INET6;
if(!ports_create_if(do_auto?"::0":"::1",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list, acl_interface,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
@ -1857,7 +1828,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
hints.ai_family = AF_INET;
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list, acl_interface,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
@ -1874,7 +1845,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
continue;
hints.ai_family = AF_INET6;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list, acl_interface,
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,
@ -1889,7 +1860,7 @@ listening_ports_open(struct config_file* cfg, struct acl_list* acl_interface,
continue;
hints.ai_family = AF_INET;
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list, acl_interface,
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,

View file

@ -138,7 +138,6 @@ struct listen_port {
* interfaces for IP4 and/or IP6, for UDP and/or TCP.
* On the given port number. It creates the sockets.
* @param cfg: settings on what ports to open.
* @param acl_interface: acl list for interface options.
* @param ifs: interfaces to open, array of IP addresses, "ip[@port]".
* @param num_ifs: length of ifs.
* @param reuseport: set to true if you want reuseport, or NULL to not have it,
@ -147,7 +146,6 @@ struct listen_port {
* @return: linked list of ports or NULL on error.
*/
struct listen_port* listening_ports_open(struct config_file* cfg,
struct acl_list* acl_interface,
char** ifs, int num_ifs, int* reuseport);
/**

View file

@ -1341,11 +1341,10 @@ int resolve_interface_names(char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
}
struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg),
struct acl_list* ATTR_UNUSED(acl_interface),
char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
int* ATTR_UNUSED(reuseport))
{
return calloc(1, 1);
return calloc(1, sizeof(struct listen_port));
}
void listening_ports_free(struct listen_port* list)

View file

@ -6,22 +6,39 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
use-caps-for-id: yes
use-caps-for-id: no
define-tag: "one two refuse"
# Interface configuration for IPv4
interface: @IPV4_ADDR@@@PORT_ALLOW@
interface: @IPV4_ADDR@@@PORT_DENY@
interface: @IPV4_ADDR@@@PORT_REFUSE@
interface: @IPV4_ADDR@@@PORT_TAG_1@
interface: @IPV4_ADDR@@@PORT_TAG_2@
interface: @IPV4_ADDR@@@PORT_TAG_3@
interface: @IPV4_ADDR@@@PORT_VIEW_INT@
interface: @IPV4_ADDR@@@PORT_VIEW_EXT@
interface: @IPV4_ADDR@@@PORT_VIEW_INTEXT@
interface-action: @IPV4_ADDR@@@PORT_ALLOW@ allow
interface-action: @IPV4_ADDR@@@PORT_DENY@ deny
# interface-action: @IPV4_ADDR@@@PORT_REFUSE@ refuse # This is the default action
interface-action: @IPV4_ADDR@@@PORT_TAG_1@ allow
interface-action: @IPV4_ADDR@@@PORT_TAG_2@ allow
interface-action: @IPV4_ADDR@@@PORT_TAG_3@ allow
interface-action: @IPV4_ADDR@@@PORT_VIEW_INT@ allow
interface-action: @IPV4_ADDR@@@PORT_VIEW_EXT@ allow
interface-action: @IPV4_ADDR@@@PORT_VIEW_INTEXT@ allow
interface-tag: @IPV4_ADDR@@@PORT_TAG_1@ "one"
interface-tag: @IPV4_ADDR@@@PORT_TAG_2@ "two"
interface-tag: @IPV4_ADDR@@@PORT_TAG_3@ "refuse"
interface-tag-action: @IPV4_ADDR@@@PORT_TAG_1@ one redirect
interface-tag-data: @IPV4_ADDR@@@PORT_TAG_1@ one "A 1.1.1.1"
interface-tag-action: @IPV4_ADDR@@@PORT_TAG_2@ two redirect
interface-tag-data: @IPV4_ADDR@@@PORT_TAG_2@ two "A 2.2.2.2"
interface-tag-action: @IPV4_ADDR@@@PORT_TAG_3@ refuse always_refuse
interface-view: @IPV4_ADDR@@@PORT_VIEW_INT@ "int"
interface-view: @IPV4_ADDR@@@PORT_VIEW_EXT@ "ext"
interface-view: @IPV4_ADDR@@@PORT_VIEW_INTEXT@ "intext"
@ -30,20 +47,75 @@ server:
interface: @IPV6_ADDR@@@PORT_ALLOW@
interface: @IPV6_ADDR@@@PORT_DENY@
interface: @IPV6_ADDR@@@PORT_REFUSE@
interface: @IPV6_ADDR@@@PORT_TAG_1@
interface: @IPV6_ADDR@@@PORT_TAG_2@
interface: @IPV6_ADDR@@@PORT_TAG_3@
interface: @IPV6_ADDR@@@PORT_VIEW_INT@
interface: @IPV6_ADDR@@@PORT_VIEW_EXT@
interface: @IPV6_ADDR@@@PORT_VIEW_INTEXT@
interface-action: @IPV6_ADDR@@@PORT_ALLOW@ allow
interface-action: @IPV6_ADDR@@@PORT_DENY@ deny
# interface-action: @IPV6_ADDR@@@PORT_REFUSE@ refuse # This is the default action
interface-action: @IPV6_ADDR@@@PORT_TAG_1@ allow
interface-action: @IPV6_ADDR@@@PORT_TAG_2@ allow
interface-action: @IPV6_ADDR@@@PORT_TAG_3@ allow
interface-action: @IPV6_ADDR@@@PORT_VIEW_INT@ allow
interface-action: @IPV6_ADDR@@@PORT_VIEW_EXT@ allow
interface-action: @IPV6_ADDR@@@PORT_VIEW_INTEXT@ allow
interface-tag: @IPV6_ADDR@@@PORT_TAG_1@ "one"
interface-tag: @IPV6_ADDR@@@PORT_TAG_2@ "two"
interface-tag: @IPV6_ADDR@@@PORT_TAG_3@ "refuse"
interface-tag-action: @IPV6_ADDR@@@PORT_TAG_1@ one redirect
interface-tag-data: @IPV6_ADDR@@@PORT_TAG_1@ one "A 1.1.1.1"
interface-tag-action: @IPV6_ADDR@@@PORT_TAG_2@ two redirect
interface-tag-data: @IPV6_ADDR@@@PORT_TAG_2@ two "A 2.2.2.2"
interface-tag-action: @IPV6_ADDR@@@PORT_TAG_3@ refuse always_refuse
interface-view: @IPV6_ADDR@@@PORT_VIEW_INT@ "int"
interface-view: @IPV6_ADDR@@@PORT_VIEW_EXT@ "ext"
interface-view: @IPV6_ADDR@@@PORT_VIEW_INTEXT@ "intext"
# Mirrored interface configuration for interface name
interface: @INTERFACE@@@PORT_ALLOW@
interface: @INTERFACE@@@PORT_DENY@
interface: @INTERFACE@@@PORT_REFUSE@
interface: @INTERFACE@@@PORT_TAG_1@
interface: @INTERFACE@@@PORT_TAG_2@
interface: @INTERFACE@@@PORT_TAG_3@
interface: @INTERFACE@@@PORT_VIEW_INT@
interface: @INTERFACE@@@PORT_VIEW_EXT@
interface: @INTERFACE@@@PORT_VIEW_INTEXT@
interface-action: @INTERFACE@@@PORT_ALLOW@ allow
interface-action: @INTERFACE@@@PORT_DENY@ deny
# interface-action: @INTERFACE@@@PORT_REFUSE@ refuse # This is the default action
interface-action: @INTERFACE@@@PORT_TAG_1@ allow
interface-action: @INTERFACE@@@PORT_TAG_2@ allow
interface-action: @INTERFACE@@@PORT_TAG_3@ allow
interface-action: @INTERFACE@@@PORT_VIEW_INT@ allow
interface-action: @INTERFACE@@@PORT_VIEW_EXT@ allow
interface-action: @INTERFACE@@@PORT_VIEW_INTEXT@ allow
interface-tag: @INTERFACE@@@PORT_TAG_1@ "one"
interface-tag: @INTERFACE@@@PORT_TAG_2@ "two"
interface-tag: @INTERFACE@@@PORT_TAG_3@ "refuse"
interface-tag-action: @INTERFACE@@@PORT_TAG_1@ one redirect
interface-tag-data: @INTERFACE@@@PORT_TAG_1@ one "A 1.1.1.1"
interface-tag-action: @INTERFACE@@@PORT_TAG_2@ two redirect
interface-tag-data: @INTERFACE@@@PORT_TAG_2@ two "A 2.2.2.2"
interface-tag-action: @INTERFACE@@@PORT_TAG_3@ refuse always_refuse
interface-view: @INTERFACE@@@PORT_VIEW_INT@ "int"
interface-view: @INTERFACE@@@PORT_VIEW_EXT@ "ext"
interface-view: @INTERFACE@@@PORT_VIEW_INTEXT@ "intext"
# Local zones configuration
local-zone: local. transparent
local-data: "local. A 0.0.0.0"
local-zone-tag: local. "one two refuse"
# Views configuration
view:
name: "int"

View file

@ -7,25 +7,37 @@ if test ! -x "`which unshare 2>&1`"; then
skip_test "no unshare (from util-linux package) available, skip test"
fi
get_random_port 8
get_random_port 11
PORT_ALLOW=$RND_PORT
PORT_DENY=$(($RND_PORT + 1))
PORT_REFUSE=$(($RND_PORT + 2))
PORT_VIEW_INT=$(($RND_PORT + 3))
PORT_VIEW_EXT=$(($RND_PORT + 4))
PORT_VIEW_INTEXT=$(($RND_PORT + 5))
FORWARD_PORT=$(($RND_PORT + 6))
STUB_PORT=$(($RND_PORT + 7))
PORT_TAG_1=$(($RND_PORT + 3))
PORT_TAG_2=$(($RND_PORT + 4))
PORT_TAG_3=$(($RND_PORT + 5))
PORT_VIEW_INT=$(($RND_PORT + 6))
PORT_VIEW_EXT=$(($RND_PORT + 7))
PORT_VIEW_INTEXT=$(($RND_PORT + 8))
FORWARD_PORT=$(($RND_PORT + 9))
STUB_PORT=$(($RND_PORT + 10))
IPV4_ADDR=192.168.1.1
IPV6_ADDR=2001:db8::1
INTERFACE=eth24
INTERFACE_ADDR_1=10.0.0.1
INTERFACE_ADDR_2=10.0.0.2
INTERFACE_ADDR_3=10.0.0.3
INTERFACE_ADDR_4=10.0.0.4
# make config file
sed \
-e 's/@PORT_ALLOW\@/'$PORT_ALLOW'/' \
-e 's/@PORT_DENY\@/'$PORT_DENY'/' \
-e 's/@PORT_REFUSE\@/'$PORT_REFUSE'/' \
-e 's/@PORT_TAG_1\@/'$PORT_TAG_1'/' \
-e 's/@PORT_TAG_2\@/'$PORT_TAG_2'/' \
-e 's/@PORT_TAG_3\@/'$PORT_TAG_3'/' \
-e 's/@PORT_VIEW_INT\@/'$PORT_VIEW_INT'/' \
-e 's/@PORT_VIEW_EXT\@/'$PORT_VIEW_EXT'/' \
-e 's/@PORT_VIEW_INTEXT\@/'$PORT_VIEW_INTEXT'/' \
@ -33,6 +45,7 @@ sed \
-e 's/@STUB_PORT\@/'$STUB_PORT'/' \
-e 's/@IPV4_ADDR\@/'$IPV4_ADDR'/' \
-e 's/@IPV6_ADDR\@/'$IPV6_ADDR'/' \
-e 's/@INTERFACE\@/'$INTERFACE'/' \
< acl_interface.conf > ub.conf
if test -x "`which bash`"; then
@ -44,6 +57,9 @@ fi
echo "PORT_ALLOW=$PORT_ALLOW" >> .tpkg.var.test
echo "PORT_DENY=$PORT_DENY" >> .tpkg.var.test
echo "PORT_REFUSE=$PORT_REFUSE" >> .tpkg.var.test
echo "PORT_TAG_1=$PORT_TAG_1" >> .tpkg.var.test
echo "PORT_TAG_2=$PORT_TAG_2" >> .tpkg.var.test
echo "PORT_TAG_3=$PORT_TAG_3" >> .tpkg.var.test
echo "PORT_VIEW_INT=$PORT_VIEW_INT" >> .tpkg.var.test
echo "PORT_VIEW_EXT=$PORT_VIEW_EXT" >> .tpkg.var.test
echo "PORT_VIEW_INTEXT=$PORT_VIEW_INTEXT" >> .tpkg.var.test
@ -51,4 +67,9 @@ echo "FORWARD_PORT=$FORWARD_PORT" >> .tpkg.var.test
echo "STUB_PORT=$STUB_PORT" >> .tpkg.var.test
echo "IPV4_ADDR=$IPV4_ADDR" >> .tpkg.var.test
echo "IPV6_ADDR=$IPV6_ADDR" >> .tpkg.var.test
echo "INTERFACE=$INTERFACE" >> .tpkg.var.test
echo "INTERFACE_ADDR_1=$INTERFACE_ADDR_1" >> .tpkg.var.test
echo "INTERFACE_ADDR_2=$INTERFACE_ADDR_2" >> .tpkg.var.test
echo "INTERFACE_ADDR_3=$INTERFACE_ADDR_3" >> .tpkg.var.test
echo "INTERFACE_ADDR_4=$INTERFACE_ADDR_4" >> .tpkg.var.test
echo "shell=$shell" >> .tpkg.var.test

View file

@ -10,6 +10,13 @@ ip addr add $IPV4_ADDR dev lo
ip addr add $IPV6_ADDR dev lo
ip link set lo up
ip link add $INTERFACE type dummy
ip addr add $INTERFACE_ADDR_1 dev $INTERFACE
ip addr add $INTERFACE_ADDR_2 dev $INTERFACE
ip addr add $INTERFACE_ADDR_3 dev $INTERFACE
ip addr add $INTERFACE_ADDR_4 dev $INTERFACE
ip link set $INTERFACE up
# start the forwarder in the background
get_ldns_testns
$LDNS_TESTNS -p $FORWARD_PORT acl_interface.testns >fwd.log 2>&1 &
@ -31,6 +38,14 @@ wait_ldns_testns_up fwd.log
wait_ldns_testns_up fwd2.log
wait_unbound_up unbound.log
end () {
echo "> cat logfiles"
cat fwd.log
cat fwd2.log
cat unbound.log
exit $1
}
# Query for the given domain to the given port
# $1: address family [4, 6]
# $2: port
@ -44,13 +59,22 @@ query () {
dig @"$addr" -p $2 $3 | tee outfile
}
# Query for the given domain to the given port
# $1: address
# $2: port
# $3: dname
query_addr () {
echo "> dig @$1 -p $2 $3"
dig @"$1" -p $2 $3 | tee outfile
}
expect_refused () {
echo "> check answer for REFUSED"
if grep "REFUSED" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
end 1
fi
}
@ -60,7 +84,7 @@ expect_external_answer () {
echo "OK"
else
echo "Not OK"
exit 1
end 1
fi
}
@ -70,10 +94,29 @@ expect_internal_answer () {
echo "OK"
else
echo "Not OK"
exit 1
end 1
fi
}
expect_tag_one_answer () {
echo "> check tag 'one' answer"
if grep "1.1.1.1" outfile; then
echo "OK"
else
echo "Not OK"
end 1
fi
}
expect_tag_two_answer () {
echo "> check tag 'two' answer"
if grep "2.2.2.2" outfile; then
echo "OK"
else
echo "Not OK"
end 1
fi
}
# do the test
@ -90,6 +133,15 @@ for i in 4 6; do
query $i $PORT_ALLOW "www.internal"
expect_internal_answer
query $i $PORT_TAG_1 "local"
expect_tag_one_answer
query $i $PORT_TAG_2 "local"
expect_tag_two_answer
query $i $PORT_TAG_3 "local"
expect_refused
query $i $PORT_VIEW_INT "www.internal"
expect_internal_answer
@ -109,8 +161,45 @@ for i in 4 6; do
expect_external_answer
done
echo "> cat logfiles"
cat fwd.log
cat fwd2.log
cat unbound.log
exit 0
for addr in $INTERFACE_ADDR_1 $INTERFACE_ADDR_2 $INTERFACE_ADDR_3 $INTERFACE_ADDR_4; do
query_addr $addr $PORT_REFUSE "www.external"
expect_refused
query_addr $addr $PORT_REFUSE "www.internal"
expect_refused
query_addr $addr $PORT_ALLOW "www.external"
expect_external_answer
query_addr $addr $PORT_ALLOW "www.internal"
expect_internal_answer
query_addr $addr $PORT_TAG_1 "local"
expect_tag_one_answer
query_addr $addr $PORT_TAG_2 "local"
expect_tag_two_answer
query_addr $addr $PORT_TAG_3 "local"
expect_refused
query_addr $addr $PORT_VIEW_INT "www.internal"
expect_internal_answer
query_addr $addr $PORT_VIEW_INT "www.external"
expect_refused
query_addr $addr $PORT_VIEW_EXT "www.internal"
expect_refused
query_addr $addr $PORT_VIEW_EXT "www.external"
expect_external_answer
query_addr $addr $PORT_VIEW_INTEXT "www.internal"
expect_internal_answer
query_addr $addr $PORT_VIEW_INTEXT "www.external"
expect_external_answer
done
end 0

View file

@ -11,3 +11,16 @@ www IN A
SECTION ANSWER
www IN A 1.2.3.4
ENTRY_END
$ORIGIN local.
$TTL 3600
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
@ IN A
SECTION ANSWER
@ IN A 127.0.0.1
ENTRY_END

View file

@ -44,7 +44,6 @@
* boundaries in the program.
*/
#include "config.h"
#include "daemon/acl_list.h"
#include "util/fptr_wlist.h"
#include "util/mini_event.h"
#include "services/outside_network.h"
@ -222,6 +221,7 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
if(fptr == &mesh_state_compare) return 1;
else if(fptr == &mesh_state_ref_compare) return 1;
else if(fptr == &addr_tree_compare) return 1;
else if(fptr == &addr_tree_addrport_compare) return 1;
else if(fptr == &local_zone_cmp) return 1;
else if(fptr == &local_data_cmp) return 1;
else if(fptr == &fwd_cmp) return 1;
@ -245,7 +245,6 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
else if(fptr == &auth_zone_cmp) return 1;
else if(fptr == &auth_data_cmp) return 1;
else if(fptr == &auth_xfer_cmp) return 1;
else if(fptr == &acl_interface_compare) return 1;
return 0;
}

View file

@ -71,6 +71,14 @@ int addr_tree_compare(const void* k1, const void* k2)
return 0;
}
int addr_tree_addrport_compare(const void* k1, const void* k2)
{
struct addr_tree_node* n1 = (struct addr_tree_node*)k1;
struct addr_tree_node* n2 = (struct addr_tree_node*)k2;
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr,
n2->addrlen);
}
void name_tree_init(rbtree_type* tree)
{
rbtree_init(tree, &name_tree_compare);
@ -81,6 +89,11 @@ void addr_tree_init(rbtree_type* tree)
rbtree_init(tree, &addr_tree_compare);
}
void addr_tree_addrport_init(rbtree_type* tree)
{
rbtree_init(tree, &addr_tree_addrport_compare);
}
int name_tree_insert(rbtree_type* tree, struct name_tree_node* node,
uint8_t* name, size_t len, int labs, uint16_t dclass)
{

View file

@ -153,6 +153,13 @@ int name_tree_next_root(rbtree_type* tree, uint16_t* dclass);
*/
void addr_tree_init(rbtree_type* tree);
/**
* Init addr tree to be empty.
* The comparison function to be used is addr_tree_addrport_compare.
* @param tree: to init.
*/
void addr_tree_addrport_init(rbtree_type* tree);
/**
* insert element into addr tree.
* @param tree: addr tree
@ -207,4 +214,7 @@ int name_tree_compare(const void* k1, const void* k2);
/** compare addr tree nodes */
int addr_tree_compare(const void* k1, const void* k2);
/** compare addr tree nodes (address and port only) */
int addr_tree_addrport_compare(const void* k1, const void* k2);
#endif /* UTIL_STORAGE_DNSTREE_H */