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;