0

I've attempted searching just about anywhere I could find to figure out why a seemingly legitimate setup isn't working. I'm trying to archive DDNS with OpenVPN clients utilizing the --learn-address of the OpenVPN server. The DNS server is bind9. I'm not sure about 3 things:

  • Are my nameservers correct?
  • Why am I getting SERVFAIL?
  • When I ping 587-gc2 (or 587-gc2.proxy.example.com) I get Name or service not known, even as my zone file is currently with a manual entry.

db.vpn zone file in /var/lib/bind/:

$ORIGIN .
$TTL 60 ; 1 minute
proxy.example.com   IN SOA  ns4.example.com. (
    20180711 ; serial
    60         ; refresh (1 minute)
    120        ; retry (2 minutes)
    60         ; expire (1 minute)
    60         ; minimum (1 minute)
    )
NS      ns1.example.com.
NS      ns4.example.com.
$ORIGIN proxy.example.com.
$TTL 14400      ; 4 hours
587-gc2         A   172.XX.XX.26

Attempted nsupdate query:

Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  17693
;; flags:; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 1
;; ZONE SECTION:
;proxy.example.com.              IN      SOA

;; UPDATE SECTION:
587-gc2.proxy.example.com. 60 IN A       172.XX.XX.26

;; TSIG PSEUDOSECTION:
keyname.         0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1531335476 300 16 TSIGSECRET 17693 NOERROR 0

Reply from above nsupdate query:

Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: SERVFAIL, id:  17693
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 1
;; ZONE SECTION:
;proxy.example.com.              IN      SOA
;; TSIG PSEUDOSECTION:
SECRETKEY.          0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1531335476 300 16 TSIGSECRET 17693 NOERROR 0

full syslog logs (named log) while reconnecting device

setup_system()
Creating key...
namefromtext
keycreate
reset_system()
user_interaction()
do_next_command()
message repeated 3 times: [ do_next_command()]
evaluate_update()
update_addordelete()
do_next_command()
start_update()
send_update()
Sending update to 127.0.0.1#53
show_message()
update_completed()
tsig verification successful
show_message()
Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: SERVFAIL, id:  36239
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 1
;; ZONE SECTION:
;proxy.example.com.              IN      SOA
;; TSIG PSEUDOSECTION:
SECRETKEY.          0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1531416897 300 16 TSIGSECRET 36239 NOERROR 0
done_update()
reset_system()
user_interaction()
cleanup()
detach tsigkey x0x7fb6a35cf0b8
Shutting down task manager
shutdown_program()
Shutting down request manager
Destroy DST lib
Destroying request manager
Freeing the dispatchers
Shutting down dispatch manager
Destroying event
Shutting down socket manager
Shutting down timer manager
Destroying hash context
Destroying name state
Removing log context
Destroying memory context

--learn-address script in /usr/local/sbin/

#!/usr/bin/php
<?php
/* 
 * This script can be passed to --learn-address of the openvpn server, it will
 * update the local bind9 server whenever an ip address is passed 
 */
// Bind9 server to update
define("NS_ADDR", "127.0.0.1");
// Domain to prepend common name to
define("DOMAIN", "proxy.example.com");
// nsupdate bin
define("NSUPDATE", "/usr/bin/nsupdate");
// Temp path
define("TMP_PATH", "/tmp/");
// Private key path
define("PRIVATE_KEY", "SECRETKEY:SECRETHASH");
// Debug
define("DEBUG", true);
function failWithError($error) {
    syslog(LOG_ERR, $error);
    exit(1);
}
function addRecordWithIP($record, $ip) {
    $domain = $record.".".DOMAIN;
    $filepath = TMP_PATH."/". __FUNCTION__."_" .rand(900, 999);
    $fh = fopen($filepath, "w");
    fwrite($fh, "server ".NS_ADDR."\n");
    fwrite($fh, "debug ".(DEBUG?'yes':'no')."\n");
    fwrite($fh, "zone ".DOMAIN."\n");
    fwrite($fh, "update add {$domain} 60 A {$ip}\n");
    fwrite($fh, "send\n");
    fclose($fh);
    $output = [];
    exec(NSUPDATE." -y ".PRIVATE_KEY." -D -v ".escapeshellarg($filepath).(DEBUG?"":" 2>&1 > /dev/null"), $output);
    if (DEBUG) {
    syslog(LOG_ERR, print_r($output, true));
    }
    // clean up
    unlink($filepath);
}
function removeRecord($record) {
    $domain = $record.".".DOMAIN;
    $filepath = TMP_PATH."/". __FUNCTION__."_" .rand(900, 999);
    $fh = fopen($filepath, "w");
    fwrite($fh, "server ".NS_ADDR."\n");
    fwrite($fh, "debug ".(DEBUG?'yes':'no')."\n");
    fwrite($fh, "zone ".DOMAIN."\n");
    fwrite($fh, "update delete {$domain}\n");
    fwrite($fh, "send\n");
    fclose($fh);
    $output = [];
    exec(NSUPDATE." -y ".PRIVATE_KEY." -v ".escapeshellarg($filepath).(DEBUG?"":" 2>&1 > /dev/null"), $output);
    if (DEBUG) {
    syslog(LOG_ERR, print_r($output, true));
    }
    // clean up
    unlink($filepath);
}
if ($argc < 3) {
    failWithError("Incorrect number of params");
}
$slashpos = strpos($argv[2], "/");
if ($slashpos !== false) {
    // Remove subnet from ip
    $argv[2] = substr($argv[2], $slashpos);
}
if (inet_pton($argv[2]) === false) {
    failWithError("{$argv[2]} is not a valid ip address");
}
switch($argv[1]) {
    case "update":
    case "add":
    if (isset($argv[3])) {
        removeRecord($argv[3]);
        addRecordWithIP($argv[3], $argv[2]);
    }
    break;
    case "remove":
    // Since openvpn only provides the ip on this request we cannot remove the 
    break;
}
// Success
exit(0);

named.conf.local in /etc/bind/:

include "/etc/bind/named.conf.log";
acl vpnnets { 172.XX.XX.XX/16; 192.168.3.0/24; };
acl ourservers { SERVERIP; };
key dhcpupdate {
  algorithm hmac-md5;
  secret "SECRETHASH";
};
view "vpn" {
        match-clients { vpnnets;ourservers; };
        recursion yes;
         zone "proxy.example.com" {
                type master;
                file "/var/cache/bind/db.vpn";
                allow-update { key SECRETKEY;};
        };
include "/etc/bind/named.conf.default-zones-vpn";
     allow-query { vpnnets;ourservers;any; };
     allow-query-cache { vpnnets;ourservers; };
     allow-recursion { vpnnets;ourservers; };
};
view "external" {
        match-clients {any;};
        recursion yes;
         zone "proxy.example.com" {
                type master;
                file "/var/cache/bind/db.vpn-external";
                allow-update { key SECRETKEY;};

        };
};

resolv.conf in /etc/:

# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.
nameserver 172.XX.XX.1
nameserver 169.254.169.254
search c.GOOGLEPROJECT.internal google.internal

dig output from 587-gc2.proxy.example.com

; <<>> DiG 9.11.3-1ubuntu1.1-Ubuntu <<>> 587-gc2.proxy.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 50282
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 3e50511a4a2fe8a1f5ba4f2d5b47943d6559b3ba4abf601e (good)
;; QUESTION SECTION:
;587-gc2.proxy.example.com. IN      A
;; Query time: 46 msec
;; SERVER: 172.XX.XX.1#53(172.XX.XX.1)
;; WHEN: Thu Jul 12 12:47:41 CDT 2018
;; MSG SIZE  rcvd: 86

named/bind log when trying to dig the fully 587-gc2.proxy.example.com

13-Jul-2018 12:49:49.445 queries: info: client @0x7f69407fa110 172.XX.XX.1#54377 (587-gc2.proxy.example.com): view vpn: query: 587-gc2.proxy.example.com IN A +E(0)K (172.XX.XX.1)
13-Jul-2018 12:49:49.445 query-errors: info: client @0x7f69407fa110 172.XX.XX.1#54377 (587-gc2.proxy.example.com): view vpn: query failed (SERVFAIL) for 587-gc2.proxy.example.com/IN/A at ../../../bin/named/query.c:6984
  • Your DNS server reply looks good as it returns NOERROR. I assume you ran the nsupdate command manually, right? Please append the output of dig @172.XX.XX.1 587-gc2.proxy.example.com after you used nsupdate. In the upper part of your question you referred to proxy.teamlogical.com but your configuration files point to proxy.example.com, but I guess that is just an incomplete attempt to a generic domain name. Anyway, try to keep it consistent. – Kevin K. Jul 12 '18 at 6:50
  • Initially I manually created the db.vpn file. Attached the dig output at the end of the post. – AfterLemon Jul 12 '18 at 17:48
0

It would be also very helpful to see named logs from the time window when you try the nsupdate command. For me it looks like there is an issue during the update., The SERVERFAIL response indicates that there is a problem. The NOERROR is most likely related to the encryption.

| improve this answer | |
  • Attached full syslog section when reconnecting OpenVPN device. – AfterLemon Jul 12 '18 at 17:36
  • Did you check Apparmor/Selinux? named log gives no good hint on why the response is SERVERFAIL. It could be interesting to increase the loglevel on bind to see why it fails. – hargut Jul 12 '18 at 17:50
  • Apparmor seems to allow specifically using /var/lib/bind/ as a location with full access. I'll look into Selinux; I wasn't familiar with it and didn't know it could affect this. I've attached the query and response from named at the bottom (now in a separate log). – AfterLemon Jul 13 '18 at 17:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.