SwordArMor

Le nœud AS112 chez grifon et Breizh-IX

Le rôle de l’AS112

Cet AS est assez spécial, il sert de trou noir du DNS. C’est aussi l’une des premières utilisations de l’anycast.

En regardant la charge des serveurs racines du DNS, les administrateurs se sont rendu compte qu’une quantité non négligeable de requêtes étaient des demandes de PTR sur les adresses 1918. La parade est donc de créer une délégation pour ces zones et d’avoir des serveurs qui répondent que le domaine n’existe pas avec un très grand TTL. Ainsi, les serveurs racines seront soulagés de ces requêtes le temps que le TTL expire.
Le serveur doit répondre sur cinq IPs différentes :

  1. prisoner.iana.org car c’est le serveur maître renseigné dans le SOA,
  2. blackhole-1.iana.org et blackhole-2.iana.org car les zones sont déléguées dessus,
  3. blackhole.as112.arpa afin de supporter les redirections DNAME,
  4. et bien sûr les IPs anycast du nœud.

Bien évidemment, un administrateur consciencieux ne devrait pas faire sortir ce genre de requêtes de son réseau ; mais nous savons tous que nous ne sommes pas entourés que de gens compétents.

Le projet est défini dans le RFC 6304 et le support d’IPv6 et du DNAME sont ajoutés dans le RFC 7534.
Un brouillon est en cours de rédaction afin d’ajouter le support de la zone home.arpa.

Mise en place du nœud

Pour ce nœud j’ai choisi d’utiliser FreeBSD (en 11.1 à l’heure où j’écris ces lignes) avec les implémentations NSD pour le DNS et OpenBGPd pour le BGP.

DNS

Je me suis très fortement inspiré du fichier de configuration donné par Stéphane Bortzmeyer. Je l’ai adapté pour respecter le nouveau nommage de zones et supporter l’IPv6 d’une part, puis pour supporter les statistiques ainsi que quelques autres fioritures d’autre part.

Par défaut, NSD n’est pas compilé avec le support des statistiques dans FreeBSD, j’ai donc utilisé la version des ports en ajoutant les options BIND8_STATS et MUNIN_PLUGIN. Cette dernière servira à grapher les requêtes.

Voici les fichiers de configuration actuellement utilisés :

nsd.conf


# NSD configuration file for an AS112 name server. See RFC 6304 and
# 

# Inspired from http://www.bortzmeyer.org/6304.html

server:
	zonesdir: "/var/db/nsd"
	# Replace both with the real name
	# CH TXT queries
	identity: "hostname.as112.net - grifon node"
	# NSID (RFC 5011) queries. *Must* be in hex :-( Use for instance:
	# echo -n "ns.example.net" | hexdump -v -e '/1 "%02X"'
	nsid: "61733131322e677269666f6e2e6672"
	# The default value is too small
	tcp-count: 100
	tcp-query-count: 10
	tcp-timeout: 60

	# localhost
	ip-address: ::1
	ip-address: 127.0.0.1
	# Breizh-IX
	ip-address: 2001:7f8:b1::12
	ip-address: 185.1.89.16
	# grifon
	ip-address: 2a00:5884:0:100::1:10
	ip-address: 89.234.186.134
	# AS112
	ip-address: 2620:4f:8000::1
	ip-address: 2620:4f:8000::6
	ip-address: 2620:4f:8000::42
	ip-address: 2001:4:112::1
	ip-address: 192.175.48.1
	ip-address: 192.175.48.6
	ip-address: 192.175.48.42
	ip-address: 192.31.196.1

	logfile: "/var/log/nsd.log"
	statistics: 3600
	username: nsd

remote-control:
        control-enable: yes

# RFC 1918
zone:
       name: "10.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "16.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "17.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "18.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "19.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "20.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "21.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
	name: "22.172.in-addr.arpa"
	zonefile: "db.dd-empty"
	provide-xfr: 0.0.0.0/0 BLOCKED
	notify-retry: 0

zone:
       name: "23.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "24.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "25.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "26.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "27.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "28.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "29.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "30.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "31.172.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

zone:
       name: "168.192.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0

# RFC 5735
zone:
       name: "254.169.in-addr.arpa"
       zonefile: "db.dd-empty"
       provide-xfr: 0.0.0.0/0 BLOCKED
       notify-retry: 0


# DNAME redirection AS112 Service
zone:
	name: "empty.as112.arpa"
	zonefile: "db.dr-empty"
	provide-xfr: 0.0.0.0/0 BLOCKED
	notify-retry: 0

# Also answer authoritatively for the HOSTNAME.AS112.NET and
# HOSTNAME.AS112.ARPA zones, which contain data of operational
# relevance.
zone:
       name: "hostname.as112.net"
       zonefile: "db.hostname.as112.net"

zone:
	name: "hostname.as112.arpa"
	zonefile: "db.hostname.as112.arpa"

# https://tools.ietf.org/html/draft-ietf-homenet-dot-14
zone:
	name: "home.arpa"
	zonefile: "db.dd-empty"

# Unlike the sample BIND configuration in RFC 6304, we do not log
# requests: NSD cannot do it and, anyway, it is better done outside of
# the name server, for instance with dnscap
# .

db.dd-empty


; db.empty
;
; Empty zone for AS112 server.
;
$TTL	1W
@	IN	SOA	prisoner.iana.org. hostmaster.root-servers.org. (
                		1       ; serial number
		             	1W      ; refresh
        	             	1M      ; retry
                	     	1W      ; expire
                     		1W )    ; negative caching TTL
;
		NS	blackhole-1.iana.org.
		NS	blackhole-2.iana.org.
;
; There should be no other resource records included in this zone.
;
; Records that relate to RFC 1918-numbered resources within the
; site hosting this AS112 node should not be hosted on this
; nameserver.

db.dr-empty


; db.dr-empty
;
; Empty zone for DNAME redirection AS112 service.
;
$TTL    1W
@  IN	SOA  blackhole.as112.arpa. noc.dns.icann.org. (
                                  1       ; serial number
                                  1W      ; refresh
                                  1M      ; retry
                                  1W      ; expire
                                  1W )    ; negative caching TTL
;
	NS     blackhole.as112.arpa.
;
; There should be no other resource records included in this zone.
;
; Records that relate to RFC 1918-numbered resources within the
; site hosting this AS112 node should not be hosted on this
; nameserver.

db.hostname.as112.arpa


; db.hostname.as112.net
;
$TTL    1W
@       SOA	as112.grifon.fr. adminsys.grifon.fr. (
                	1               ; serial number
                        1W              ; refresh
                        1M              ; retry
                        1W              ; expire
                        1W )            ; negative caching TTL
;
	NS 	blackhole-2.iana.org.
        NS      blackhole-1.iana.org.
;
	TXT     "grifon" "Rennes, FR"
        TXT     "See http://www.as112.net/ for more information."
;
	LOC     48 51 29.520 N 2 20 19.320 E 0.00m 1m 10000m 10m

db.hostname.as112.net


; db.hostname.as112.net
;
$TTL    1W
@       SOA	as112.grifon.fr. adminsys.grifon.fr. (
                	2017120900      ; serial number
                        1W              ; refresh
                        1M              ; retry
                        1W              ; expire
                        1W )            ; negative caching TTL
;
	NS 	blackhole-2.iana.org.
        NS      blackhole-1.iana.org.
;
	TXT     "grifon" "Rennes, FR"
        TXT     "See http://www.as112.net/ for more information."
	TXT	"See https://monitoring.grifon.fr/munin/grifon.fr/as112.grifon.fr/index.html#dns for statistics."
	TXT	"Unicast IP: 89.234.186.134"
;
	LOC     48 51 29.520 N 2 20 19.320 E 0.00m 1m 10000m 10m

BGP

Le nœud est connecté aux deux routeurs de bordure de grifon afin d’obtenir une vue complète d’Internet. Ces routeurs ne relaient pas encore l’annonce, ça viendra sûrement un jour, quand je me serai fait relire ;).
Le nœud est également connecté au serveur de routes de Breizh-IX afin d’annoncer l’AS sur cet IX.

Les filtres d’AS sont commentés car ils contiennent des routes légitimes, comme 199.71.168.0/21 et 199.71.172.0/22.


root@as112:~ # bgpctl show rib transit-as 64500
flags: * = Valid, > = Selected, I = via IBGP, A = Announced, S = Stale
origin: i = IGP, e = EGP, ? = Incomplete

flags destination          gateway          lpref   med aspath origin
*>    199.71.168.0/21      89.234.186.130     100     0 3.7484 174 19752 21992 64499 64500 3411 i
*     199.71.168.0/21      89.234.186.129     100     0 3.7484 174 19752 21992 64499 64500 3411 i
*>    199.71.168.0/23      89.234.186.130     100     0 3.7484 174 19752 21992 64499 64500 3411 i
*     199.71.168.0/23      89.234.186.129     100     0 3.7484 174 19752 21992 64499 64500 3411 i
*>    199.71.172.0/22      89.234.186.130     100     0 3.7484 174 19752 21992 64499 64500 3411 i
*     199.71.172.0/22      89.234.186.129     100     0 3.7484 174 19752 21992 64499 64500 3411 i

bgpd.conf


router-id 89.234.186.134
AS 112
fib-update yes

network 192.175.48.0/24
network 192.31.196.0/24
network 2620:4f:8000::/48
network 2001:4:112::/48

group "peering" {
	softreconfig in	yes
	softreconfig out yes
	announce	all

	neighbor 89.234.186.129 {
		remote-as	204092
		descr		"Grifon nominoe IPv4"
	}

	neighbor 2a00:5884:0:100::1:1 {
		remote-as	204092
		descr		"Grifon nominoe IPv6"
	}

	neighbor 89.234.186.130 {
		remote-as	204092
		descr		"Grifon budic IPv4"
	}

	neighbor 2a00:5884:0:100::1:2 {
		remote-as	204092
		descr		"Grifon budic IPv6"
	}

	neighbor 185.1.89.1 {
		remote-as	206165
		descr		"Breizh-IX RS1"
		enforce neighbor-as no
		set localpref	150
	}

	neighbor 2001:7f8:b1::1 {
		remote-as	206165
		descr		"Breizh-IX RS1"
		enforce neighbor-as no
		set localpref	150
	}
}

# do not send or use routes from neighbors without further explicit
# configuration
deny from any
deny to any

# filter out prefixes longer than 24 or shorter than 8 bits for IPv4
# and longer than 48 or shorter than 16 bits for IPv6.
allow from any inet prefixlen 8 - 24
allow from any inet6 prefixlen 16 - 48

# filter bogus networks according to RFC5735
deny from any prefix 0.0.0.0/8 prefixlen >= 8		# 'this' network [RFC1122]
deny from any prefix 10.0.0.0/8 prefixlen >= 8		# private space [RFC1918]
deny from any prefix 100.64.0.0/10 prefixlen >= 10	# CGN Shared [RFC6598]
deny from any prefix 127.0.0.0/8 prefixlen >= 8 	# localhost [RFC1122]
deny from any prefix 169.254.0.0/16 prefixlen >= 16	# link local [RFC3927]
deny from any prefix 172.16.0.0/12 prefixlen >= 12	# private space [RFC1918]
deny from any prefix 192.0.2.0/24 prefixlen >= 24	# TEST-NET-1 [RFC5737]
deny from any prefix 192.168.0.0/16 prefixlen >= 16	# private space [RFC1918]
deny from any prefix 198.18.0.0/15 prefixlen >= 15	# benchmarking [RFC2544]
deny from any prefix 198.51.100.0/24 prefixlen >= 24	# TEST-NET-2 [RFC5737]
deny from any prefix 203.0.113.0/24 prefixlen >= 24	# TEST-NET-3 [RFC5737]
deny from any prefix 224.0.0.0/4 prefixlen >= 4 	# multicast
deny from any prefix 240.0.0.0/4 prefixlen >= 4		# reserved

# filter bogus IPv6 networks according to IANA
deny from any prefix ::/8 prefixlen >= 8
deny from any prefix 0100::/64 prefixlen >= 64          # Discard-Only [RFC6666]
deny from any prefix 2001:2::/48 prefixlen >= 48        # BMWG [RFC5180]
deny from any prefix 2001:10::/28 prefixlen >= 28       # ORCHID [RFC4843]
deny from any prefix 2001:db8::/32 prefixlen >= 32      # docu range [RFC3849]
deny from any prefix 3ffe::/16 prefixlen >= 16          # old 6bone
deny from any prefix fc00::/7 prefixlen >= 7            # unique local unicast
deny from any prefix fe80::/10 prefixlen >= 10          # link local unicast
deny from any prefix fec0::/10 prefixlen >= 10          # old site local unicast
deny from any prefix ff00::/8 prefixlen >= 8            # multicast

## filter bogon AS numbers
## http://www.iana.org/assignments/as-numbers/as-numbers.xhtml
#deny from any AS 23456				# AS_TRANS
#deny from any AS 64496 - 64511			# Reserved for use in docs and code RFC5398
#deny from any AS 64512 - 65534		# Reserved for Private Use RFC6996
#deny from any AS 65535				# Reserved RFC7300
#deny from any AS 65536 - 65551			# Reserved for use in docs and code RFC5398
#deny from any AS 65552 - 131071		# Reserved
#deny from any AS 4200000000 - 4294967294	# Reserved for Private Use RFC6996
#deny from any AS 4294967295			# Reserved RFC7300

allow to any prefix 2620:4f:8000::/48
allow to any prefix 2001:4:112::/48
allow to any prefix 192.175.48.0/24
allow to any prefix 192.31.196.0/24

Post-installation

Statistiques

Si on a compilé NSD avec le support des statistiques bind8 et que l’on a configuré le support des dites statistiques et de nsd-control, on peut utiliser un plugin munin qui nous fera de (presque) jolis graphes.
Pour cela, on l’active : for i in hits memory by_type by_class by_opcode by_rcode zones; do ln -s /usr/local/share/munin/plugins/nsd_munin_ /usr/local/etc/munin/plugins/nsd_munin_${i}; done et on ajoute les lignes demandées dans le code à /usr/local/etc/munin/plugin-conf.d/plugins.conf.
Les graphes de ce nœud sont visibles sur le munin de grifon.

J’ai également installé net-snmp afin de collecter les métriques SNMP depuis le LibreNMS et ainsi intégrer le nœud à la weathermap.

Monitoring

Je monitore ce nœud de deux façons : la résolution du SOA de hostname.as112.arpa sur l’IP unicast de façon distante et la résolution du SOA de toutes les zones en utilisant NRPE. Je ne peux pas monitorer les IPs anycast de façon distante car l’icinga tourne chez hivane, je monitorerais alors le nœud d’hivane et non celui que je mets en place.
Cela nous fait beaucoup trop de tests pour les écrire à la main, j’ai généré le fichier de conf d’icinga qui va aller taper sur le NRPE avec un onliner en parsant le fichier de conf de NSD : [root@as112 ~]# for address in prisoner.iana.org blackhole-1.iana.org blackhole-2.iana.org blackhole.as112.arpa; do awk -F '"' '/name:/ { print $2 }' /usr/local/etc/nsd/nsd.conf | grep -v '^$' | while read zone; do printf "object Service \"nrpe-as112-${zone}-${address}\" {\n\timport \"generic-service\"\n\n\thost_name = \"as112.grifon.fr\"\n\tcheck_command = \"nrpe\"\n\tvars.nrpe_command = \"check_as112"\!"${zone}"\!"${address}\"\n\tvars.sla = \"24x7\"\n}\n\n"; done; done > nrpe.conf. (et non, je n’ai même pas honte, j’ai pas l’intention de réutiliser cette ligne un jour). Et j’ai écrit une bête ligne dans le fichier de configuration du serveur NRPE : command[check_as112]=/usr/local/libexec/nagios/check_dig -l '$ARG1$' -H '$ARG2$' -T SOA.

Annonces

Une fois que j’aurai reçu des retours sur cet article m’indiquant que je n’ai rien raté, ce nœud sera d’abord mis en production uniquement chez grifon afin de le tester. J’ai la main sur à peu près tout, ce sera donc assez facile de débugguer. À ce moment je ferai une annonce sur as112-ops en disant qu’il n’est pas visible d’Internet et sur la ML d’annonces de grifon.
Ensuite, il sera mis en production sur Breizh-IX, une annonce sera alors faite sur la ML de l’IX.
Enfin, si tout se passe bien, il sera peut-être annoncé publiquement, je répondrai alors à mon premier mail sur as112-ops afin de prévenir du changement de statut.

Remerciements

Merci à Pierre Emeriaud et à Stéphane Bortzmeyer pour leurs relectures.

Sources