diff --git a/Makefile b/Makefile
index 086c47c..aa6da10 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,9 @@
all:
- $(CC) src/dnssec.c -Iinc -g -Wall -lcurl -std=gnu99 -o dnsd
+ $(CC) src/dnssec.c -Iinc -Wall -lcurl -std=gnu11 -o dnsd
install:
- cp dnsd.conf /etc/dnsd.conf
+ mkdir -p /etc/dnsd
+ cp dnsd.conf /etc/dnsd/dnsd.conf
+ cp google.der /etc/dnsd/google.der
cp dnsd /usr/local/bin/
linux-service:
cp service/dnsd.service /lib/systemd/system/
diff --git a/README.md b/README.md
index 3d4adae..ee80b8d 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@ DNSd is a daemon a.k.a. service for Unix-like systems. It provides a local DNS b
- Highly configurable through a simple config. file.
- A Self contained package that depends only on [libcurl](https://curl.haxx.se/libcurl/).
- Supported records are **A**,**AAAA**,**CNAME**,**NS** and **MX**.
+ - Public key pinning
# Build and Install
Build the software by running the following commands in the terminal.
@@ -38,8 +39,13 @@ For macOS systems install and launch the service as follows.
make macos-service
launchctl load -w /Library/LaunchDaemons/service.dnsd.plist
```
+### Obtain Public Key
+`openssl s_client -connect google.com:443 | openssl x509 -pubkey -noout`
+
### Verification
-You can verify wether the service is accessible through ```host -va github.com localhost```.
+You can verify wether the service is accessible through
+ - `host -va github.com localhost`
+ - `nslookup -port=5454 -query=mx github.com 127.0.0.1`
```
Trying "github.com"
Using domain server:
diff --git a/google.der b/google.der
new file mode 100644
index 0000000..390b0f6
Binary files /dev/null and b/google.der differ
diff --git a/inc/dnssec.h b/inc/dnssec.h
index 02eeae6..3e3a7f0 100644
--- a/inc/dnssec.h
+++ b/inc/dnssec.h
@@ -69,6 +69,7 @@
#define OPT_DEFAULT_URL "https://dns.google.com"
#define OPT_SERVICE_PORT "service_port"
#define OPT_SERVICE_IP "service_ip"
+#define OPT_SERVICE_PUB_KEY "service_pub_key"
#define OPT_SERVICE_IP_LEN INET6_ADDRSTRLEN
#define OPT_ENABLE_TRUE "true"
#define OPT_ENABLE_FALSE "false"
@@ -94,6 +95,7 @@ struct func_options
char server_url[OPT_SERVER_URL_LEN];
char server_ip_list[OPT_SERVER_IP_LEN];
char service_ip[OPT_SERVICE_IP_LEN];
+ char service_pub_key[OPT_CONIG_FILE_LEN];
uint16_t server_timeout;
uint16_t service_port;
uint8_t enable_debug;
diff --git a/service/dnsd.service b/service/dnsd.service
index 79a376f..6616a30 100644
--- a/service/dnsd.service
+++ b/service/dnsd.service
@@ -5,7 +5,7 @@ After=network.target
[Service]
Type=forking
PIDFile=/var/run/dnsd.pid
-ExecStart=/usr/local/bin/dnsd -f /etc/dnsd.conf
+ExecStart=/usr/local/bin/dnsd -f /etc/dnsd/dnsd.conf
KillMode=process
Restart=on-failure
diff --git a/service/service.dnsd.plist b/service/service.dnsd.plist
index 359cfd3..8a1bc01 100644
--- a/service/service.dnsd.plist
+++ b/service/service.dnsd.plist
@@ -10,7 +10,7 @@
/usr/local/bin/dnsd
-f
- /etc/dnsd.conf
+ /etc/dnsd/dnsd.conf
RunAtLoad
diff --git a/src/dnssec.c b/src/dnssec.c
index 7744cab..222196b 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -92,7 +92,6 @@ static void __attribute__ ((unused)) start_daemon()
fprintf(stderr, "open(stderr)");
exit(EXIT_FAILURE);
}
-
}
#if DEBUG_AUDIT_ENABLE
@@ -182,11 +181,6 @@ int https_query (struct dns_query* query)
struct curl_slist* headers = NULL;
- headers = curl_slist_append(headers, "Accept-Encoding : deflate, sdch, br");
- headers = curl_slist_append(headers, "Accept : txt/html, application/xml;q=0.8");
- headers = curl_slist_append(headers, "Accept-Language : en-US,en;q=0.8");
- headers = curl_slist_append(headers, "Cache-Control : max-age=0");
-
curl = curl_easy_init();
if(curl && strlen(getTypeString(ntohs(query->qstn->qtype), FALSE)))
{
@@ -197,6 +191,7 @@ int https_query (struct dns_query* query)
// do not check the SSL certificate authenticity
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+ //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// failed to work with libcurl/7.65.3 and HTTP/2.0
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
@@ -208,6 +203,15 @@ int https_query (struct dns_query* query)
curl_easy_setopt(curl, CURLOPT_PROXY, options.https_proxy);
}
+ if (options.service_pub_key[0])
+ {
+ if (curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, options.service_pub_key) != CURLE_OK)
+ {
+ LOG_ERROR("failed to load the pinned public key");
+ return EXIT_FAILURE;
+ }
+ }
+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, body_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)query);
@@ -376,6 +380,7 @@ int server()
char* answer = (char *)(buffer + sizeof(struct dns_question) + sizeof(struct dns_header) + dnlen + 1);
answer_length = json_to_answer(answer, header, max_len);
}
+ else LOG_ERROR("https_query() failed.");
}
if (!answer_length || answer_length == JSON_NO_ANSWER)
@@ -525,7 +530,7 @@ size_t json_to_answer(char* answer, struct dns_header_detail* header, size_t max
{
token = strstr(token, "type");
- char* beg = strchr(token, ':') + 2;
+ char* beg = strchr(token, ':') + 1;
size_t len = strchr(beg, ',') - beg;
memset(ctype, 0x00, 10);
@@ -742,36 +747,31 @@ void hexdump (char *desc, void *addr, int len)
unsigned char buff[17];
unsigned char *pc = (unsigned char*)addr;
- // Output description if given.
if (desc != NULL)
printf ("%s:\n", desc);
- if (len == 0) {
+ if (len == 0)
+ {
printf(" ZERO LENGTH\n");
return;
}
- if (len < 0) {
+ if (len < 0)
+ {
printf(" NEGATIVE LENGTH: %i\n",len);
return;
}
// Process every byte in the data.
- for (i = 0; i < len; i++) {
- // Multiple of 16 means new line (with line offset).
-
- if ((i % 16) == 0) {
- // Just don't print ASCII for the zeroth line.
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16) == 0)
+ {
if (i != 0)
printf (" %s\n", buff);
- // Output the offset.
printf (" %04x ", i);
}
-
- // Now the hex code for the specific character.
printf (" %02x", pc[i]);
-
- // And store a printable ASCII character for later.
if ((pc[i] < 0x20) || (pc[i] > 0x7e))
buff[i % 16] = '.';
else
@@ -779,13 +779,12 @@ void hexdump (char *desc, void *addr, int len)
buff[(i % 16) + 1] = '\0';
}
- // Pad out last line if not exactly 16 characters.
- while ((i % 16) != 0) {
+ while ((i % 16) != 0)
+ {
printf (" ");
i++;
}
- // And print the final ASCII bit.
printf (" %s\n", buff);
}
@@ -870,6 +869,10 @@ int parse_options()
{
strncpy(options.service_ip, line + sizeof(OPT_SERVICE_IP), OPT_SERVICE_IP_LEN);
}
+ else if (strstr(line, OPT_SERVICE_PUB_KEY) != NULL)
+ {
+ strncpy(options.service_pub_key, line + sizeof(OPT_SERVICE_PUB_KEY), OPT_CONIG_FILE_LEN);
+ }
else if (strstr(line, OPT_ENABLE_EDNS) != NULL)
{
if (strcasestr(line, OPT_ENABLE_TRUE) != NULL) options.enable_edns = 1;