Creating a Lego selfdns Provider
Server
Lastmod: 2023-02-17
Published: 2023-02-16

I created a provider that makes the lego command itself a DNS server to perform DNS-01 authentication when obtaining Let’s Encrypt SSL certificates using Lego.

Introduction

Lego is a command-line tool written in Go that acts as an ACME client to obtain SSL certificates from Let’s Encrypt and other certificate authorities.

What did I do?

Lego’s DNS-01 authentication supports various DNS providers, but for times when “there’s no DNS server with an API available!” I created a selfdns provider that acts as its own DNS server to perform DNS-01 authentication and issue SSL certificates.

Since running Lego itself as a server is probably not intended by the original authors, I didn’t make a pull request and positioned it as a personal fork without writing test code, just for my own use.

This way, even with DNS services that don’t have an API (such as domain-attached DNS), you can still obtain SSL certificates via DNS-01 authentication by pointing NS records to it.

To run Lego itself as a DNS server, it needs to be accessible as a DNS server from the outside.

Disclaimer

This is made with the assumption that it will be used personally, so there is no guarantee of operation.
Also, I made it with a “let’s just make it work” approach without confirming the ACME specifications.

How to use

Point NS records to the DNS where you want to issue the certificate

  • If you want to issue a certificate on a certain VPS server (hoge), point the NS records to the DNS of the hoge server.

    hoge            60  IN A  XXX.XXX.XXX.XXX
    _acme-challenge 60  IN NS hoge.example.jp.
    
  • To verify if it worked as expected, check with the dig command.

    $ dig _acme-challenge.example.jp -t ns
    ;; AUTHORITY SECTION:
    _acme-challenge.example.jp. 60 IN  NS      hoge.example.jp.
    
    ;; ADDITIONAL SECTION:
    hoge.example.jp.   60      IN      A       XXX.XXX.XXX.XXX
    

Prepare the server with a global IP to run lego

  • Open the ports in iptables. Open port 53 for both UDP/TCP to operate as a DNS server.

    # iptables -A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
    # iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT
    
  • Download the modified Lego.

    # wget https://github.com/masa23/lego/releases/download/v4.10.0/lego_v4.10.0-1_linux_amd64.tar.gz
    # tar zxvf lego_v4.10.0_linux_amd64.tar.gz
    
  • Run lego to issue the certificate.
    To operate as a DNS server, specify --dns selfdns.
    Root privileges are required to use port 53.

    # SELFDNS_LISTEN_ADDRESS=XXX.XXX.XXX.XXX SELFDNS_SERVER_HOSTNAME=hoge.example.jp ./lego --email <email_address> --domains="*.example.jp" --accept-tos --dns=selfdns run 
    

    Specify the global IP of the server running lego for SELFDNS_LISTEN_ADDRESS.
    Specify the hostname of the server running lego for SELFDNS_SERVER_HOSTNAME.
    This is used in the SOA record during responses.

If there are no issues, the certificate will be issued.

.lego/certificates/

Addendum (2023/02/17)

By specifying an IPv6 address for SELFDNS_LISTEN_ADDRESS, the DNS server will start with the IPv6 address. With this, you can now obtain Let’s Encrypt SSL certificates with a global IPv6 address.

  • DNS registration

    hoge            60  IN AAAA  20XX:XX:...
    _acme-challenge 60  IN NS hoge.example.jp.
    
  • Run lego

    # SELFDNS_LISTEN_ADDRESS=20XX:XX:... SELFDNS_SERVER_HOSTNAME=hoge.example.jp ./lego --email <email_address> --domains="*.example.jp" --accept-tos --dns=selfdns run
    

This allows you to obtain Let’s Encrypt SSL certificates