Hi all,
We develop a product that contains unbound server, and we want to use 
unbound-control utility for managing running unbound instances. This utility 
looks very powerful, with ability to query server status, flush/restore zone 
caches and even add new zone entries on the fly.
One thing that we miss is the ability to control unbound via unix sockets. 
This may be quite useful and secure setup. Using unix sockets makes it 
possible to use traditional unix permissions for controlling access to 
unbound, and it's impossible to access control interface when an attacker 
occasionally breaks some other chrooted process on the system (because chroot 
restricts access only to file system namespace, not to IP sockets namespace). 
The other advantage is that they are faster than local TCP, which may be 
useful if loading cache via load_cache command.

Attached is a patch that adds unix sockets support to unbound and 
unbound-control. After applying patch it is possible to have such 
configuration:
>>>>>>>>>>>>>>>>>>>>>>>>>>
remote-control:
        control-enable: yes
        control-interface: /tmp/unbound.sock
        server-key-file: /cage/unbound/etc/unbound_server.key
        server-cert-file: /cage/unbound/etc/unbound_server.pem
        control-key-file: /cage/unbound/etc/unbound_control.key
        control-cert-file: /cage/unbound/etc/unbound_control.pem
>>>>>>>>>>>>>>>>>>>>>>>>>>
Additionally, this patch fixes log_addr() function in libunbound, that is not 
fully compatible with unix sockets.

This patch is made for unbound 1.4.15.

Please review attached patch and tell me if you find this feature useful! :-)

--
Best regards,
Ilya Bakulin

genua
Gesellschaft fuer Netzwerk- und Unix-Administration mbH
Domagkstrasse 7, 85551 Kirchheim bei Muenchen
tel +49 89 991950-0, fax -999, www.genua.de
Geschaeftsfuehrer: Dr. Magnus Harlander, Dr. Michaela Harlander,
Bernhard Schneck. Amtsgericht Muenchen HRB 98238
diff --git a/unbound-1.4.15/daemon/remote.c b/unbound-1.4.15/daemon/remote.c
index a2b2204..708a167 100644
--- a/unbound-1.4.15/daemon/remote.c
+++ b/unbound-1.4.15/daemon/remote.c
@@ -48,6 +48,7 @@
 #endif
 #include <ctype.h>
 #include <ldns/ldns.h>
+#include <sys/un.h>
 #include "daemon/remote.h"
 #include "daemon/worker.h"
 #include "daemon/daemon.h"
@@ -246,6 +247,37 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
 	snprintf(port, sizeof(port), "%d", nr);
 	port[sizeof(port)-1]=0;
 	memset(&hints, 0, sizeof(hints));
+
+	if(ip[0] == '/') {
+	  /* This looks like UNIX socket! TODO: move into listen_dnsport.c */
+	  struct sockaddr_un unixaddr;
+	  unixaddr.sun_len = sizeof(unixaddr);
+	  unixaddr.sun_family = AF_UNIX;
+	  strlcpy(unixaddr.sun_path, ip, 104);
+
+	  if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+	  	log_err("Cannot create UNIX socket %s for remote-control (%s)",
+		    ip, strerror(errno));
+	  	return 0;
+	  }
+
+	  if(bind(fd, (struct sockaddr *) &unixaddr,
+		  sizeof(struct sockaddr_un)) == -1) {
+	    log_err("Cannot bind UNIX socket %s (%s)", ip, strerror(errno));
+	    return 0;
+	  }
+
+	  if(!fd_set_nonblock(fd)) {
+	    log_err("Cannot set non-blocking mode");
+	    return 0;
+	  }
+
+	  if(listen(fd, 10) == -1) { /* TODO: TCP_BACKLOG when moved */
+	    log_err("can't listen: %s", strerror(errno));
+	    return 0;
+	  }
+	  /* End of constructing UNIX socket instead of AF_INET crap */
+	} else {
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
 	if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
@@ -269,6 +301,8 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
 	/* open fd */
 	fd = create_tcp_accept_sock(res, 1, &noproto);
 	freeaddrinfo(res);
+	}
+
 	if(fd == -1 && noproto) {
 		if(!noproto_is_err)
 			return 1; /* return success, but do nothing */
diff --git a/unbound-1.4.15/smallapp/unbound-control.c b/unbound-1.4.15/smallapp/unbound-control.c
index a872f92..c649e02 100644
--- a/unbound-1.4.15/smallapp/unbound-control.c
+++ b/unbound-1.4.15/smallapp/unbound-control.c
@@ -59,6 +59,8 @@
 #include "util/locks.h"
 #include "util/net_help.h"
 
+#include <sys/un.h>
+
 /** Give unbound-control usage, and exit (1). */
 static void
 usage()
@@ -158,6 +160,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
 {
 	struct sockaddr_storage addr;
 	socklen_t addrlen;
+	int addrfamily;
 	int fd;
 	/* use svr or the first config entry */
 	if(!svr) {
@@ -176,12 +179,21 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
 	if(strchr(svr, '@')) {
 		if(!extstrtoaddr(svr, &addr, &addrlen))
 			fatal_exit("could not parse IP@port: %s", svr);
+	} else if(svr[0] == '/') {
+	    struct sockaddr_un* unixsock = (struct sockaddr_un *) &addr;
+	    unixsock->sun_family = AF_UNIX;
+	    unixsock->sun_len = sizeof(unixsock);
+	    strlcpy(unixsock->sun_path, svr, 104);
+	    addrlen = sizeof(struct sockaddr_un);
+	    addrfamily = AF_UNIX;
 	} else {
 		if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
 			fatal_exit("could not parse IP: %s", svr);
 	}
-	fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET, 
-		SOCK_STREAM, 0);
+
+	if(addrfamily != AF_UNIX)
+	  addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
+	fd = socket(addrfamily, SOCK_STREAM, 0);
 	if(fd == -1) {
 #ifndef USE_WINSOCK
 		fatal_exit("socket: %s", strerror(errno));
diff --git a/unbound-1.4.15/util/net_help.c b/unbound-1.4.15/util/net_help.c
index b3136a3..582964a 100644
--- a/unbound-1.4.15/util/net_help.c
+++ b/unbound-1.4.15/util/net_help.c
@@ -45,6 +45,7 @@
 #include "util/module.h"
 #include "util/regional.h"
 #include <fcntl.h>
+#include <sys/un.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 
@@ -135,7 +136,7 @@ log_addr(enum verbosity_value v, const char* str,
 {
 	uint16_t port;
 	const char* family = "unknown";
-	char dest[100];
+	char dest[108];
 	int af = (int)((struct sockaddr_in*)addr)->sin_family;
 	void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
 	if(verbosity < v)
@@ -148,6 +149,8 @@ log_addr(enum verbosity_value v, const char* str,
 		case AF_UNIX: family="unix"; break;
 		default: break;
 	}
+
+	if(af != AF_UNIX) {
 	if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
 		strncpy(dest, "(inet_ntop error)", sizeof(dest));
 	}
@@ -157,6 +160,12 @@ log_addr(enum verbosity_value v, const char* str,
 		verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 
 			(int)port, (int)addrlen);
 	else	verbose(v, "%s %s port %d", str, dest, (int)port);
+	} else {
+		struct sockaddr_un* unixsock;
+		unixsock = (struct sockaddr_un *) addr;
+		strlcpy(dest, unixsock->sun_path, sizeof(dest));
+		verbose(v, "%s %s %s", str, family, dest);
+	}
 }
 
 int 
_______________________________________________
Unbound-users mailing list
[email protected]
http://unbound.nlnetlabs.nl/mailman/listinfo/unbound-users

Reply via email to