diff --git a/libfetch/common.c b/libfetch/common.c
index e237828..73758aa 100644
--- a/libfetch/common.c
+++ b/libfetch/common.c
@@ -37,6 +37,7 @@
 #include <sys/uio.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <unbound.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -52,19 +53,6 @@
 #include "fetch.h"
 #include "common.h"
 
-/*** Local data **************************************************************/
-
-/*
- * Error messages for resolver errors
- */
-static struct fetcherr netdb_errlist[] = {
-	{ EAI_NODATA,	FETCH_RESOLV,	"Host not found" },
-	{ EAI_AGAIN,	FETCH_TEMP,	"Transient resolver failure" },
-	{ EAI_FAIL,	FETCH_RESOLV,	"Non-recoverable resolver failure" },
-	{ EAI_NONAME,	FETCH_RESOLV,	"No address record" },
-	{ -1,		FETCH_UNKNOWN,	"Unknown resolver error" }
-};
-
 /*** Error-reporting functions ***********************************************/
 
 /*
@@ -251,49 +239,89 @@ conn_t *
 fetch_connect(struct url *url, int af, int verbose)
 {
 	conn_t *conn;
-	char pbuf[10];
-	const char *bindaddr;
-	struct addrinfo hints, *res, *res0;
-	int sd, error;
-
-	if (verbose)
-		fetch_info("looking up %s", url->host);
+  const char *bindaddr;
+  int sd, error;
+
+  if (verbose)
+    fetch_info("looking up %s", url->host);
+
+  struct ub_ctx* ctx;
+  struct ub_result* result;
+
+  // host resolving using libunbound.
+  // for now, we simply create and initialize a new ctx on every connect.
+  ctx = ub_ctx_create();
+  if(!ctx) {
+    fprintf(stderr, "error: could not create unbound context\n");
+    return (NULL);
+  }
+
+  error = ub_ctx_resolvconf(ctx, "/etc/resolv.conf");
+  if(error != 0) {
+    fprintf(stderr, "error reading resolv.conf: %s. errno says: %s\n",
+        ub_strerror(error), strerror(errno));
+    return (NULL);
+  }
+
+  error = ub_ctx_hosts(ctx, "/etc/hosts");
+  if(error != 0) {
+    fprintf(stderr, "error reading hosts: %s. errno says: %s\n",
+        ub_strerror(error), strerror(errno));
+    return (NULL);
+  }
+
+  /* read public keys for DNSSEC verification */
+  error =ub_ctx_add_ta_file(ctx, "/etc/unbound/root.key");
+  if(error != 0) {
+    fprintf(stderr, "error adding dnssec keys: %s\n", ub_strerror(error));
+    return (NULL);
+  }
+
+  /* query for webserver */
+  error = ub_resolve(ctx, url->host,
+      1 /* TYPE A (IPv4 address) */,
+      1 /* CLASS IN (internet) */, &result);
+  if(error != 0) {
+    fprintf(stderr, "resolve error: %s\n", ub_strerror(error));
+    return (NULL);
+  }
+
+  if(result->havedata) {
+    if(!result->secure) {
+      if(result->bogus)
+        fprintf(stderr, "resolve response is bogus: %s\n", result->why_bogus);
+      else
+        fprintf(stderr, "resolve response is not considered secure/validated.");
+      return (NULL);
+    }
+  }
 
-	/* look up host name and set up socket address structure */
-	snprintf(pbuf, sizeof(pbuf), "%d", url->port);
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = af;
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_protocol = 0;
-	if ((error = getaddrinfo(url->host, pbuf, &hints, &res0)) != 0) {
-		netdb_seterr(error);
-		return (NULL);
-	}
 	bindaddr = getenv("FETCH_BIND_ADDRESS");
-
 	if (verbose)
 		fetch_info("connecting to %s:%d", url->host, url->port);
 
 	/* try to connect */
-	for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) {
-		if ((sd = socket(res->ai_family, res->ai_socktype,
-			 res->ai_protocol)) == -1)
-			continue;
-		if (bindaddr != NULL && *bindaddr != '\0' &&
-		    fetch_bind(sd, res->ai_family, bindaddr) != 0) {
-			fetch_info("failed to bind to '%s'", bindaddr);
-			close(sd);
-			continue;
-		}
-		if (connect(sd, res->ai_addr, res->ai_addrlen) == 0)
-			break;
-		close(sd);
-	}
-	freeaddrinfo(res0);
-	if (sd == -1) {
-		fetch_syserr();
-		return (NULL);
-	}
+  if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+    fprintf(stderr, "cloud not create socket: %s\n", strerror(errno));
+    fetch_syserr();
+    return (NULL);
+  }
+  if(bindaddr != NULL && *bindaddr != '\0' && fetch_bind(sd, AF_INET, bindaddr) != 0) {
+    fetch_info("failed to bind to '%s'", bindaddr);
+    close(sd);
+    fetch_syserr();
+    return (NULL);
+  }
+  struct sockaddr_in sin_addr = {
+    .sin_family = AF_INET,
+    .sin_port = htons(url->port),
+    .sin_addr = *(struct in_addr *)result->data[0]
+  };
+  if(connect(sd, (struct sockaddr *)&sin_addr, sizeof(sin_addr)) != 0) {
+    fetch_syserr();
+    close(sd);
+    return (NULL);
+  }
 
 	if ((conn = fetch_reopen(sd)) == NULL) {
 		fetch_syserr();
@@ -302,6 +330,45 @@ fetch_connect(struct url *url, int af, int verbose)
 	}
 	conn->cache_url = fetchCopyURL(url);
 	conn->cache_af = af;
+
+
+  // step 2: Fetch the TLSA records if available
+  size_t dane_record_str_maxlen = strlen(url->host) + 6 /* _port */ + 4 /* _tcp */ + 4 /* dots+NUL: port >.< _tcp >.< host >.< '\0' */;
+  char *dane_record_str = malloc(dane_record_str_maxlen);
+
+  snprintf(dane_record_str, dane_record_str_maxlen, "_%d._tcp.%s", url->port, url->host);
+
+  error = ub_resolve(ctx, dane_record_str,
+      52 /* TYPE TLSA (DANE record) */,
+      1 /* CLASS IN (internet) */, &result);
+  if(error != 0) {
+    fprintf(stderr, "TLSA error, could not fetch TLSA record for %s: %s\n", dane_record_str, ub_strerror(error));
+    conn->tlsa_records = 0;
+  }
+
+  else if(result->havedata) {
+    if(!result->secure) {
+      if(result->bogus)
+        fprintf(stderr, "TLSA record is bogus: %s\n", result->why_bogus);
+      else
+        fprintf(stderr, "TLSA record is not considered secure/validated.");
+      return (NULL);
+    }
+    for(unsigned int i = 0; result->data[i] != NULL && i < 128; i+=1) {
+      if(result->len[i] < 4) {
+        fprintf(stderr, "received invalid TLSA record (length of fields < 4?), skipping...\n");
+        continue;
+      }
+      conn->tlsa_entries[i].usage = result->data[i][0];
+      conn->tlsa_entries[i].type = result->data[i][1];
+      conn->tlsa_entries[i].matching_type = result->data[i][2];
+      conn->tlsa_entries[i].data = malloc(result->len[i] - 3);
+      memcpy(conn->tlsa_entries[i].data, &result->data[i][3], result->len[i] - 3);
+      conn->tlsa_entries[i].data_size = result->len[i] - 3;
+      conn->tlsa_records += 1;
+    }
+  }
+
 	return (conn);
 }
 
@@ -507,6 +574,7 @@ fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
 	conn->ssl_meth = SSLv23_client_method();
 	conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth);
 	SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY);
+  SSL_CTX_dane_enable(conn->ssl_ctx);
 
 	if (!fetch_ssl_setup_peer_verification(conn->ssl_ctx, verbose))
 		return (-1);
@@ -518,6 +586,16 @@ fetch_ssl(conn_t *conn, const struct url *URL, int verbose)
 		fprintf(stderr, "SSL context creation failed\n");
 		return (-1);
 	}
+  if(SSL_dane_enable(conn->ssl, URL->host) <= 0) {
+    ERR_print_errors_fp(stderr);
+  }
+  for(int i = 0; i <conn->tlsa_records; ++i) {
+    if(SSL_dane_tlsa_add(conn->ssl, conn->tlsa_entries[i].usage, conn->tlsa_entries[i].type, conn->tlsa_entries[i].matching_type,
+        conn->tlsa_entries[i].data, conn->tlsa_entries[i].data_size) <= 0) {
+      ERR_print_errors_fp(stderr);
+      fprintf(stderr, "could not add TLSA record to SSL context\n");
+    }
+  }
 	conn->buf_events = 0;
 	SSL_set_fd(conn->ssl, conn->sd);
 	if (!SSL_set_tlsext_host_name(conn->ssl, (char *)(uintptr_t)URL->host)) {
diff --git a/libfetch/common.h b/libfetch/common.h
index d7ad1d6..3500692 100644
--- a/libfetch/common.h
+++ b/libfetch/common.h
@@ -55,6 +55,13 @@
 /* Connection */
 typedef struct fetchconn conn_t;
 
+struct tlsa_info {
+  int usage;
+  int type;
+  int matching_type;
+  unsigned char *data;
+  size_t data_size;
+};
 struct fetchconn {
 	int		 sd;		/* socket descriptor */
 	char		*buf;		/* buffer */
@@ -72,6 +79,8 @@ struct fetchconn {
 	struct url	*cache_url;
 	int		cache_af;
 	int		(*cache_close)(conn_t *);
+  int tlsa_records;
+  struct tlsa_info tlsa_entries[128];
 	conn_t		*next_cached;
 };
 
diff --git a/src/Makefile b/src/Makefile
index e307ceb..f67d26d 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -68,12 +68,12 @@ apk.static-objs		:= $(filter-out apk.o,$(apk-objs)) apk-static.o
 apk.static-libs		:= $(apk-libs)
 LDFLAGS_apk.static	:= -static
 LIBS_apk.static		:= -Wl,--as-needed -ldl -Wl,--no-as-needed
-LDFLAGS_apk		+= -L$(obj)
+LDFLAGS_apk		+= -L$(obj) -lunbound
 LDFLAGS_apk-test	+= -L$(obj)
 
 CFLAGS_ALL		+= $(OPENSSL_CFLAGS) $(ZLIB_CFLAGS)
 LIBS			:= -Wl,--as-needed \
-				$(OPENSSL_LIBS) $(ZLIB_LIBS) \
+				$(OPENSSL_LIBS) $(ZLIB_LIBS) -lunbound \
 			   -Wl,--no-as-needed
 
 $(obj)/apk: $(LIBAPK-y)