Categories
Web

Get thee behind me, Facebook

A few weeks ago when I upgraded this site to a new server, I spent the time to overhaul my DNS setup. I host my own nameservers for several domains and wanted to automate their configuration more than the edit-in-nano hand management I’d been doing. While I was at it, I set up DNSSEC for the domains and even DNS-over-TLS.

The latter was nice because with the latest version of Android I was able to set it up to have my phone use my DNS over TLS, thus providing an encrypted tunnel for my DNS lookups, as well as forcing all DNS lookups from my phone to go through my own server.

Today, I was able to cash in on that effort. I was looking through the DNS-over-TLS logs and noticed that one of my apps was phoning home to graph.facebook.com, even though the app did not disclose this. In something of a smoldering fury I decided to implement response policy zones (RPZ) on my nameserver. In effect, this allows me to blackhole any domains that I want: whenever any app on my phone tries to find Facebook or any other domain I’ve blacklisted, they get told there’s no such domain.

rpz QNAME NXDOMAIN rewrite graph.facebook.com via graph.facebook.com.blackhole

I did all this with Ansible, making for a very simple script:

---
- hosts: dns
  become: yes
  vars_files:
    - '../../secrets.yml'
  vars:
    dns_serial: "{{ ansible_date_time.year }}{{ ansible_date_time.month }}{{ ansible_date_time.day }}{{ ansible_date_time.hour }}"
    dns_rpz_zone: blackhole
    dns_rpz_domains:
      - doublelick.net
      - app-measurement.com
      - facebook.com
      - facebook.net
      - fbcdn.com
      - fbsbx.com
      - fbcdn.net
      - messenger.com
      - m.me
      - instagram.com
      - instagramstatic-a.akamaihd.net
      - cdninstagram.com
      - tfbnw.net
      - whatsapp.com
      - fb.me
      - fb.com
    dns_rpz_cdns:
      - edgesuite.net
      - edgekey.net
  tasks:
    - name: named.conf.options
      become: yes
      template:
        src: named.conf.options.j2
        dest: /etc/bind/named.conf.options
        owner: root
        group: bind
    - name: Hosts file
      become: yes
      template:
        src: rpz.hosts.j2
        dest: "{{ dns_path }}/{{ dns_rpz_zone }}.hosts"
        owner: bind
        group: bind
    - name: Zone file
      become: yes
      template:
        src: rpz.zone.j2
        dest: "{{ dns_path }}/{{ dns_rpz_zone }}.zone"
        owner: bind
        group: bind
    - name: Ensure zone file reference
      lineinfile:
        dest: /etc/bind/named.conf.local
        line: "include \"{{ dns_path }}/blackhole.zone\";"
        state: present

The hosts template is the only interesting one:

$ttl 86400
@   IN  SOA {{ dns_rpz_zone }}.  root.{{ dns_rpz_zone }}. {{ dns_serial }} 10800 3600 604800 86400
@   IN  NS  {{ dns_rpz_zone }}.
@   IN  A   127.0.0.66
{% for domain in dns_rpz_domains %}
{{ domain }}	IN	CNAME	.
*.{{ domain }}	IN	CNAME	.
{% for cdn in dns_rpz_cdns %}
{{ domain }}.{{ cdn }}	IN	CNAME	.
*.{{ domain }}.{{ cdn }}	IN	CNAME	.
{% endfor %}
{% endfor %}

The trick here is that the RPZ hosts file, unlike regular domains, has hosts without a trailing ‘.’, even though they are fully-qualified names. I spent a half hour trying to figure out why Bind was giving me errors about “ignoring out-of-zone data” and not working, because I had ‘.’ at the end of my domains.

This produces an output with lines that look like:

facebook.com    IN      CNAME   .
*.facebook.com  IN      CNAME   .
facebook.com.edgesuite.net      IN      CNAME   .
*.facebook.com.edgesuite.net    IN      CNAME   .
facebook.com.edgekey.net        IN      CNAME   .
*.facebook.com.edgekey.net      IN      CNAME   .

Check to ensure your config looks good, then restart:

$ named-checkzone blackhole /etc/bind/blackhole.hosts
$ named-checkconf
$ /etc/init.d/bind9 restart

(Or have ansible do this for you.)

You can test it by trying to find the domain:

$ dig +noall +answer +additional @localhost facebook.com
blackhole.  86400  IN  SOA  blackhole. root.blackhole. 2019021618 10800 3600 604800 86400

And, of course, by trying to pull up facebook.com on your phone.

By Rick Osborne

I am a web geek who has been doing this sort of thing entirely too long. I rant, I muse, I whine. That is, I am not at all atypical for my breed.