acmesh-official / acme.sh

A pure Unix shell script implementing ACME client protocol
https://acme.sh
GNU General Public License v3.0
38.38k stars 4.89k forks source link

Feature Request: NSD DNS server support using nsd-control #1260

Open temporaryaccount opened 6 years ago

temporaryaccount commented 6 years ago

Would it be possible to add NSD DNS server support in DNS API using the nsd-control tool?

Neilpang commented 6 years ago

Is there a way to test the api ?

temporaryaccount commented 6 years ago

Other than installing nsd locally or on any kind of Linux VPS, I don't think so.

Here is my configuration for Ubuntu 16.04 if it is any help:

Installation

$ sudo apt install nsd

$ sudo mkdir /etc/nsd/zones

Configuration Files

/etc/nsd/nsd.conf.d/01-server.conf

server:
    # Number of NSD servers to fork.  Put the number of CPUs to use here.
    # server-count: 1

    # uncomment to specify specific interfaces to bind (default are the
    # wildcard interfaces 0.0.0.0 and ::0).
    # ip-address: 1.2.3.4
    # ip-address: 1.2.3.4@5678
    # ip-address: 12fe::8ef0

    # Allow binding to non local addresses. Default no.
    # ip-transparent: no

    # enable debug mode, does not fork daemon process into the background.
    # debug-mode: no

    # listen on IPv4 connections
    # do-ip4: yes

    # listen on IPv6 connections
    do-ip6: no

    # port to answer queries on. default is 53.
    # port: 53

    # Verbosity level.
    verbosity: 2

    # After binding socket, drop user privileges.
    # can be a username, id or id.gid.
    username: nsd

    # Run NSD in a chroot-jail.
    # make sure to have pidfile and database reachable from there.
    # by default, no chroot-jail is used.
    # chroot: "/etc/nsd"

    # The directory for zonefile: files.  The daemon chdirs here.
    zonesdir: "/etc/nsd/zones"

    # the list of dynamically added zones.
    zonelistfile: "/var/lib/nsd/zone.list"

    # the database to use
    # if set to "" then no disk-database is used, less memory usage.
    database: "/var/lib/nsd/nsd.db"

    # log messages to file. Default to stderr and syslog (with
    # facility LOG_DAEMON).  stderr disappears when daemon goes to bg.
    # logfile: "/var/log/nsd.log"

    # File to store pid for nsd in.
    pidfile: "/run/nsd/nsd.pid"

    # The file where secondary zone refresh and expire timeouts are kept.
    # If you delete this file, all secondary zones are forced to be 
    # 'refreshing' (as if nsd got a notify).  Set to "" to disable.
    xfrdfile: "/var/lib/nsd/xfrd.state"

    # The directory where zone transfers are stored, in a subdir of it.
    # xfrdir: "/tmp"

    # don't answer VERSION.BIND and VERSION.SERVER CHAOS class queries
    hide-version: yes

    # identify the server (CH TXT ID.SERVER entry).
    identity: ""

    # NSID identity (hex string, or "ascii_somestring"). default disabled.
    # nsid: "aabbccdd"

    # Maximum number of concurrent TCP connections per server.
    tcp-count: 200

    # Maximum number of queries served on a single TCP connection.
    # By default 0, which means no maximum.
    # tcp-query-count: 0

    # Override the default (120 seconds) TCP timeout.
    # tcp-timeout: 120

    # Preferred EDNS buffer size for IPv4.
    # ipv4-edns-size: 4096

    # Preferred EDNS buffer size for IPv6.
    # ipv6-edns-size: 4096

    # statistics are produced every number of seconds. Prints to log.
    # Default is 0, meaning no statistics are produced.
    statistics: 3600

    # Number of seconds between reloads triggered by xfrd.
    # xfrd-reload-timeout: 1

    # log timestamp in ascii (y-m-d h:m:s.msec), yes is default.
    # log-time-ascii: yes

    # round robin rotation of records in the answer.
    # round-robin: no

    # check mtime of all zone files on start and sighup
    # zonefiles-check: yes

    # write changed zonefiles to disk, every N seconds.
    # default is 0(disabled) or 3600(if database is "").
    zonefiles-write: 3600

    # RRLconfig
    # Response Rate Limiting, size of the hashtable. Default 1000000.
    # rrl-size: 1000000

    # Response Rate Limiting, maximum QPS allowed (from one query source).
    # Default 200. If set to 0, ratelimiting is disabled. Also set
    # rrl-whitelist-ratelimit to 0 to disable ratelimit processing.
    # rrl-ratelimit: 200

    # Response Rate Limiting, number of packets to discard before
    # sending a SLIP response (a truncated one, allowing an honest
    # resolver to retry with TCP). Default is 2 (one half of the
    # queries will receive a SLIP response, 0 disables SLIP (all
    # packets are discarded), 1 means every request will get a
    # SLIP response.
    # rrl-slip: 2

    # Response Rate Limiting, IPv4 prefix length. Addresses are
    # grouped by netblock. 
    # rrl-ipv4-prefix-length: 24

    # Response Rate Limiting, IPv6 prefix length. Addresses are
    # grouped by netblock. 
    # rrl-ipv6-prefix-length: 64

    # Response Rate Limiting, maximum QPS allowed (from one query source)
    # for whitelisted types. Default 2000.
    # rrl-whitelist-ratelimit: 2000
    # RRLend

/etc/nsd/nsd.conf.d/02-remote.conf

    # Enable remote control with nsd-control(8) here.
    # set up the keys and certificates with nsd-control-setup.
    control-enable: yes

    # what interfaces are listened to for control, default is on localhost.
    control-interface: 127.0.0.1
    # control-interface: ::1

    # port number for remote control operations (uses TLS over TCP).
    control-port: 8952

    # nsd server key file for remote control.
    server-key-file: "/etc/nsd/nsd_server.key"

    # nsd server certificate file for remote control.
    server-cert-file: "/etc/nsd/nsd_server.pem"

    # nsd-control key file.
    control-key-file: "/etc/nsd/nsd_control.key"

    # nsd-control certificate file.
    control-cert-file: "/etc/nsd/nsd_control.pem"

/etc/nsd/nsd.conf.d/11-example.com.conf

zone:
    name: "example.com"
    zonefile: "%s.zone"

/etc/nsd/zones/example.com.zone

$ORIGIN com.
example              3600 IN SOA   ns1.example.com. admin.example.com. (2018021300 3600 1800 86400 1800)
                     3600 IN A     93.184.216.34
                     3600 IN NS    ns1.example.com.
                     3600 IN NS    ns2.example.com.
                     3600 IN MX    0 example.com.

$ORIGIN example.com.
www                  3600 IN CNAME example.com
Neilpang commented 6 years ago

It's simple, please check our guide: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide

you can write it yourself.

temporaryaccount commented 6 years ago

Thank you, after also reading some Shell programming guides and examining the other API implementations maybe I'll try :-)

temporaryaccount commented 6 years ago

Please consider this situation:

There is a master authoritative DNS server running NSD (which we can control) and there are a couple of secondary authoritative DNS servers which sync every serveral hours using zone transfer protocol.

Does ACMEv2 use only the master authoritative server, or does it support telling the server exactly which authoritative DNS server they must use to check the TXT records? If it doesn't then the ACMEv2 server may randomly decide to use one of the out-of-sync secondary authoritative servers and fail to get the required TXT records, and so writing an API for NSD wouldn't have a point.

Neilpang commented 6 years ago

It's not predictable that where/how the letsencrypt CA validates the domain. But mostly, it would resolve the domain at public dns server, such as 8.8.8.8.

If the api is not good to sync, you can use our new domain alias mode:

https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode

temporaryaccount commented 6 years ago

Thanks again. So, lots of options..

I don't though quite agree with the section 5 of that page because when the CNAME is there the "unimportant" domain becomes just as important as the "important" one - it can now issue certificates for the important domain on its own any time while the CNAME is there. So I don't really see the point of the alias mode in regard of security.

Alias mode could be handy for centralizing things though (which itself can reduce security), i.e. issuing certificates for all your domains using one domain's API access.

penglongli commented 6 years ago

@temporaryaccount I didn't find the command on it's man page can change the DNS with nsd-control. There are only some commands like it:

addzone <zone name> <pattern name>
              Add  a new zone to the running server.  The zone is added to the zonelist file on disk, so it stays after a restart.  The pattern name determines
              the options for the new zone.  For slave zones a zone transfer is immediately attempted.  For zones with a zonefile, the zone file  is  attempted
              to be read in.
delzone <zone name>
              Remove  the  zone  from the running server.  The zone is removed from the zonelist file on disk, from the nsd.db file and from the memory.  If it
              had a zonefile, this remains (but may be outdated).  Zones configured inside nsd.conf itself cannot be removed this way because the  daemon  does
              not write to the nsd.conf file, you need to add such zones to the zonelist file to be able to delete them with the delzone command.

nsd-control only can do something with zones, but it can't change DNS.

Is there any other way here by nsd-control?

temporaryaccount commented 6 years ago

I don't think so. We should somehow generate and insert the required strings into the example.com.zone file mentioned earlier, and also change the serial number. It shouldn't be that difficult to do that using the rich shell commands available in UNIX.

Once the zone file is ready, we'll have to then:

# reload our new zone file
nsd-control reload example.com

# notify the changes to the secondary servers, if any
nsd-control notify
plantroon commented 5 years ago

I have developed a simple NSD hook.

https://github.com/plantroon/acme.sh/blob/master/dnsapi/dns_nsd.sh

2242

bjmgeek commented 4 years ago

@temporaryaccount I didn't find the command on it's man page can change the DNS with nsd-control. There are only some commands like it:

addzone <zone name> <pattern name>
              Add  a new zone to the running server.  The zone is added to the zonelist file on disk, so it stays after a restart.  The pattern name determines
              the options for the new zone.  For slave zones a zone transfer is immediately attempted.  For zones with a zonefile, the zone file  is  attempted
              to be read in.
delzone <zone name>
              Remove  the  zone  from the running server.  The zone is removed from the zonelist file on disk, from the nsd.db file and from the memory.  If it
              had a zonefile, this remains (but may be outdated).  Zones configured inside nsd.conf itself cannot be removed this way because the  daemon  does
              not write to the nsd.conf file, you need to add such zones to the zonelist file to be able to delete them with the delzone command.

nsd-control only can do something with zones, but it can't change DNS.

Is there any other way here by nsd-control?

From the nsd-control man page, it looks like nsd-control also supports the changezone command, which would seem to be what you want. However,

Zones configured in nsd.conf can- not be changed like this, instead edit the nsd.conf (or the included file in nsd.conf) and reconfig.

So you'd have to have three cases: when the zone is defined in a config file, when it exists but it is not in a config file, and when it does not exist. If it's in a config file, you'd have to find the config file, edit it, and then reload the zone with nsd-control reload [zone]. If it's not in a config file (e.g. because it was added with nsd-control addzone, then nsd-control changezone would be the way to go. If the zone doesn't exist at all, nsd-control addzone would be the command to use.