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