Deprocrastinating

2018-02-16 - Progress - Tony Finch

I'm currently getting several important/urgent jobs out of the way so that I can concentrate on the IP Register database project.

DHCP

This week I finished incorporating the DHCP server Ansible setup into the ipreg Ansible setup. (It should really have been done last year.)

The old DHCP repository was an interesting beast. It was my first proper try with Ansible (and the UCS/UIS's first!) and it was set up in a mad rush as part of our office move project in autumn 2013. The combination of git and Ansible was very effective, and using DHCP to renumber the old staff network went surprisingly smoothly.

regpg

Both the git server I had set up earlier in 2013 and the DHCP service used the same setup for storing secrets: I had a tar file encrypted with gpg in password-protected symmetric cipher mode.

Last year as part of the git server refresh, I wrote a new utility for managing secrets called regpg. This uses a gpg public-key encrypted file for each secret.

It has turned out to be much more pleasant to use, and it has been adopted by a number of other teams in the UIS and the Sanger Institute. A nice success.

Along with the DHCP server refresh, I have converted the ipreg repository to use regpg instead of the old secrets.tar.gz.asc. This includes using regpg to manage the DNSSEC private key files, which is a major step towards automated key management, as I looked forward to back in October.

Packet filters

Another thing I worked out during the git server refresh was a better way of configuring iptables.

The model I use is very basic, inherited from the Hermes packet filters that David Carter originally set up before I started to work with him in 2002. On Hermes the filrewall configuration is a simple formulaic list of rules that is directly fed to iptables - no abstractions.

The thing that makes this model simple is to only explicitly allow or block incoming TCP SYN packets; all other TCP packets are allowed, but if the SYN didn't get through, they will get rejected by the TCP state machine (rather than the packet filter). All outgoing TCP connections are implicitly allowed.

UDP isn't so simple - permitted flows have to be explicitly allowed in both directions. This isn't too bad bacause UDP tends to be simpler - just NTP, DNS, and occasionally DHCP.

For the ipreg repository, I used Ansible Jinja2 templates to reduce the amount of repetition in the firewall configuration. This worked OK, except I made it too DRY - there was a confusing muddle of header and footer and common templates, and it wasn't clear what they did.

When I refreshed the git server, I got more relaxed about repeating myself. Instead, I made a collection of filter modules in the form of little templates, which each do a single thing like allow NTP, or serve HTTP, etc.

I've expanded this scheme for the ipreg servers, and it works very nicely. It even reduces repetition in cases where a little module can be independent of v4/v6. For example:

    # IPtables configuration for authoritative DNS servers
    #
    {% set cudn = cudn4 %}
    {% set privileged = privileged4 %}
    {% include "iptables.header.j2" %}
    {% include "iptables.drop-multicast.v4.j2" %}
    {% include "iptables.allow-ntp.v4.j2" %}
    {% include "iptables.allow-ssh-admin.j2" %}
    {% include "iptables.allow-rndc.j2" %}
    {% include "iptables.serve-dns-auth.j2" %}
    {% include "iptables.footer.j2" %}

And one of the included files:

    # serve-dns-auth
    #
    # DNS UDP responses and UDP+TCP queries from everywhere
    # (Responses mainly arise from refresh queries.)
    #
    -A INPUT -p udp -m udp --sport 53       -j ACCEPT
    -A INPUT -p udp -m udp --dport 53       -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 53 --syn -j ACCEPT
    #

BIND 9.12

I have a build of BIND 9.12.0 which I expect to roll out next week.

This is a significant milestone because we will no longer need to patch BIND. We have a few patches in the current production build:

  • Drop packets matching a DDoS signature: I inherited this patch from Chris Thompson, and it has been mostly redundant since BIND added support for RRL (response rate limiting);

  • Re-sign in bigger chunks: another Chris Thompson patch, a nice tweak but not vital;

  • Transitional support for my minimal-qtype-any option, which was renamed to minimal-any when it was incorporated upstream. I've renamed it in our configuration so this isn't needed any more;

  • Automatic tuning of max-journal-size: this patch dates back to my revamp of the DNS servers in 2014/2015 and it has taken a very long time (and one significant re-work) to get incorporated upstream.

BIND 9.12 also includes a really nice DNSSEC-related performance enhancement: it can use NSEC records to synthesize negative responses, rather than re-querying authoritative servers. Our current configuration includes a lot of verbiage to suppress junk queries, all of which can be removed because of this new feature.

It also includes my dnssec-cds utility, for automatically updating DS records in a parent zone based on CDS records in the child zone, as I described back in October. Deploying this in production will be another thing to look forward to.

Remaining jobs

Once that is done, I need to sort out the much-delayed RPZ web site, to which people will be redirected when they try to visit a blocked site.

And when that is done, it will be full speed ahead on the IP Register database port to PostgreSQL.