Projet

Général

Profil

Wiki » Historique » Version 21

sacha, 10/12/2023 17:01

1 5 sacha
{{>toc}}
2
3 9 sacha
# DNS récursif Ouvert DoH DoT & haute disponibilité
4 15 sacha
**45.67.81.23 - dns.aquilenet.fr**
5 14 sacha
6 1 sacha
7 16 sacha
8 19 sacha
On propos un DNS récursif ouvert cf https://www.aquilenet.fr/services/dns/ https://dns.aquilenet.fr/
9 18 sacha
On a mis aussi un DNS ouvert sur l'IP 45.67.81.23 car facile à retenir, avec l'adresse de dns.aquilenet.fr (voir [http://dns.aquilenet.fr](http://dns.aquilenet.fr)) . Nous en avons profité pour ajouter [DoH](https://fr.wikipedia.org/wiki/DNS_over_HTTPS) et [DoT](https://fr.wikipedia.org/wiki/DNS_over_TLS) et d'avoir cette adresse en IP Virtuelle partagée entre pan1 et pan2.
10
Cette IP virtuelle est portée par Keepalived sur pan1 le primaire et pan2 le secondaire. Si le démon Keepalived est arrêté sur pan1, l'ip bascule sur pan2. Si on redémarre le démon sur pan1, ce dernier reprend l'IP: pratique pour les mises à jour, le service continue à fonctionner.
11 1 sacha
12 19 sacha
Pan[1|2] portent l'ip 45.67.81.23 gracieusement offerte par les copains de https://yaal.coop/fr un vlan est dédié sur ce réseau de l'hyperviseur.
13 6 sacha
14 18 sacha
## Configurations communes à pan1 et pan2
15 1 sacha
16 18 sacha
### Nginx
17 1 sacha
18 19 sacha
* /etc/nginx/sites-enabled/default
19 1 sacha
20
21
~~~
22
server {
23 19 sacha
    listen       45.67.81.23:80 ;
24
    listen       [::]:80 ;
25 1 sacha
26 19 sacha
    location ~ /.well-known/acme-challenge {
27
        allow all;
28
        root /var/www/letsencrypt;
29
    }
30
    location / {
31
        return 301 https://dns.aquilenet.fr;
32
        }
33 1 sacha
34 19 sacha
    server_name dns.aquilenet.fr; # managed by Certbot
35 1 sacha
36 19 sacha
    location ~ /.well-known/acme-challenge {
37
        allow all;
38
        root /var/www/letsencrypt;
39
    }
40
}
41
server {
42
    listen       45.67.81.23:443 ssl http2;
43
    listen       [::]:443 ssl http2;
44
    root /var/www/dns.aquilenet.fr;
45
    index index.htm;
46 1 sacha
47 19 sacha
    ssl_certificate     /etc/unbound/ssl/dns.aquilenet.fr/fullchain.pem;
48
    ssl_certificate_key /etc/unbound/ssl/dns.aquilenet.fr/privkey.pem;
49
location /dns-query {
50
    grpc_pass grpc://127.0.0.1:443;
51
        }
52
}
53 1 sacha
54 19 sacha
root@pan1:/etc/unbound/ssl# vi /var/www/dns.aquilenet.fr/index.htm 
55
root@pan1:/etc/unbound/ssl# ip a
56
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
57
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
58
    inet 127.0.0.1/8 scope host lo
59
       valid_lft forever preferred_lft forever
60
    inet6 ::1/128 scope host noprefixroute 
61
       valid_lft forever preferred_lft forever
62
2: enX0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
63
    link/ether 00:16:3e:01:01:21 brd ff:ff:ff:ff:ff:ff
64
    inet 45.67.81.21/24 brd 45.67.81.255 scope global enX0
65
       valid_lft forever preferred_lft forever
66
    inet 45.67.81.23/32 scope global enX0
67
       valid_lft forever preferred_lft forever
68
    inet6 fe80::216:3eff:fe01:121/64 scope link 
69
       valid_lft forever preferred_lft forever
70
root@pan1:/etc/unbound/ssl# vi /var/www/dns.aquilenet.fr/index.htm 
71
root@pan1:/etc/unbound/ssl# vi /var/www/dns.aquilenet.fr/index.htm 
72
root@pan1:/etc/unbound/ssl# vi /var/www/dns.aquilenet.fr/index.htm 
73
root@pan1:/etc/unbound/ssl# vi /var/www/dns.aquilenet.fr/index.htm 
74
root@pan1:/etc/unbound/ssl# cat /etc/nginx/sites-enabled/default 
75
server {
76
    listen       45.67.81.23:80 ;
77
    listen       [::]:80 ;
78
79
    location ~ /.well-known/acme-challenge {
80
        allow all;
81
        root /var/www/letsencrypt;
82
    }
83
    location / {
84
        return 301 https://dns.aquilenet.fr;
85
        }
86
87
    server_name dns.aquilenet.fr; # managed by Certbot
88
89
    location ~ /.well-known/acme-challenge {
90
        allow all;
91
        root /var/www/letsencrypt;
92
    }
93 1 sacha
}
94 19 sacha
server {
95
    listen       45.67.81.23:443 ssl http2;
96
    listen       [::]:443 ssl http2;
97
    root /var/www/dns.aquilenet.fr;
98
    index index.htm;
99 1 sacha
100 19 sacha
    ssl_certificate     /etc/unbound/ssl/dns.aquilenet.fr/fullchain.pem;
101
    ssl_certificate_key /etc/unbound/ssl/dns.aquilenet.fr/privkey.pem;
102
location /dns-query {
103
    grpc_pass grpc://127.0.0.1:443;
104
        }
105
}
106
107
108 1 sacha
~~~
109
110
### Unbound
111
112
~~~
113 19 sacha
server {
114
    listen       45.67.81.23:80 ;
115
    listen       [::]:80 ;
116 1 sacha
117 19 sacha
    location ~ /.well-known/acme-challenge {
118
        allow all;
119
        root /var/www/letsencrypt;
120
    }
121
    location / {
122
        return 301 https://dns.aquilenet.fr;
123
        }
124
125
    server_name dns.aquilenet.fr; # managed by Certbot
126
127
    location ~ /.well-known/acme-challenge {
128
        allow all;
129
        root /var/www/letsencrypt;
130
    }
131
}
132
server {
133
    listen       45.67.81.23:443 ssl http2;
134
    listen       [::]:443 ssl http2;
135
    root /var/www/dns.aquilenet.fr;
136
    index index.htm;
137
138
    ssl_certificate     /etc/unbound/ssl/dns.aquilenet.fr/fullchain.pem;
139
    ssl_certificate_key /etc/unbound/ssl/dns.aquilenet.fr/privkey.pem;
140
location /dns-query {
141
    grpc_pass grpc://127.0.0.1:443;
142
        }
143
}
144
145
root@pan1:/etc/unbound/ssl# cat /etc/unbound/unbound
146
cat: /etc/unbound/unbound: Aucun fichier ou dossier de ce type
147
root@pan1:/etc/unbound/ssl# cat /etc/unbound/unbound.conf
148
include-toplevel: "/etc/unbound/unbound.conf.d/*.conf"
149
150
server:
151
    verbosity: 1 
152
153
    access-control: 0.0.0.0/0 allow 
154
    interface: 45.67.81.23
155
#    interface: 45.67.81.23@443
156
    interface: 45.67.81.23@853
157
158
http-notls-downstream: yes
159
    interface: 127.0.0.1@443
160
161
    port: 53
162
    tls-port: 853
163
    https-port: 443
164
    
165
    root-hints: "/usr/share/dns/root.hints"
166
 
167
    harden-glue: yes
168
    harden-large-queries: yes
169
    harden-dnssec-stripped: yes
170
    harden-below-nxdomain: yes
171
    harden-referral-path: yes
172
    harden-algo-downgrade: no # false positives with improperly configured zones
173
    use-caps-for-id: no # makes lots of queries fail
174
    edns-buffer-size: 1232
175
    rrset-roundrobin: yes
176
    cache-min-ttl: 300
177
    cache-max-ttl: 86400
178
    serve-expired: yes
179
    harden-algo-downgrade: yes
180
    harden-short-bufsize: yes
181
    hide-identity: yes
182
    identity: "dns.aquilenet.fr"
183
    hide-version: yes
184
    do-daemonize: no
185
    neg-cache-size: 4m
186
    qname-minimisation: yes
187
    deny-any: yes
188
    minimal-responses: yes
189
    prefetch: yes
190
    prefetch-key: yes
191
    num-threads: 2 
192
    msg-cache-size: 50m
193
    rrset-cache-size: 100m
194
    so-reuseport: yes
195
    so-rcvbuf: 4m
196
    so-sndbuf: 4m
197
    unwanted-reply-threshold: 100000
198
    log-queries: no
199
    log-replies: no
200
    log-servfail: no
201
    log-local-actions: no
202
    logfile: /dev/null
203
204
    # imposer la QNAME minimisation (RFC 7816)
205
    qname-minimisation: yes
206
    # même si le serveur faisant autorité ne le veut pas
207
    #   après discussion, il est possible que cette option ne soit
208
    #   pas recommandée dans le cadre d'un résolveur ouvert
209
    qname-minimisation-strict: yes
210
211
   # DoH
212
   tls-service-key: "/etc/letsencrypt/live/dns.aquilenet.fr/privkey.pem"
213
   tls-service-pem: "/etc/letsencrypt/live/dns.aquilenet.fr/cert.pem"
214
215 1 sacha
~~~
216
217
### AppArmor
218
219
*  /etc/apparmor.d/usr.sbin.unbound
220
décomenter:
221
  include <local/usr.sbin.unbound>
222
223
* /etc/apparmor.d/local/usr.sbin.unbound
224
~~~
225
/etc/letsencrypt/archive/** r,
226
/etc/letsencrypt/live/** r,
227
~~~
228
appliquer avec: `apparmor_parser -r /etc/apparmor.d/usr.sbin.unbound`
229
230
### Iptables
231
232
~~~
233 19 sacha
*filter
234
:INPUT DROP
235
:FORWARD DROP
236
:OUTPUT ACCEPT
237
238
-A INPUT ! -i lo -s 127.0.0.0/8 -j DROP
239
-A INPUT -s 0.0.0.0 -i eth0 -j DROP
240
-A INPUT -d 0.0.0.0 -i eth0 -j DROP
241
-A INPUT -s 255.255.255.255 -i eth0 -j DROP
242
-A INPUT -d 255.255.255.255 -i eth0 -j DROP
243
-A INPUT -m conntrack --ctstate INVALID -j DROP
244
245
-A INPUT -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
246
-A INPUT -p udp ! --dport 53 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
247
-A INPUT -i lo -j ACCEPT
248
-A OUTPUT -o lo -j ACCEPT
249
250
# SSH no more 10 attempts in 3 min
251
-A INPUT -i eth0 -p tcp --dport 55555 -m recent --name SSH --update --hitcount 10 --seconds 180 -j DROP
252
-A INPUT -i eth0 -p tcp --dport 55555 -m recent --name SSH --set -j ACCEPT
253
254 1 sacha
# Web
255
-A INPUT -p tcp --dport 80 -j ACCEPT
256 19 sacha
257
# smtp
258
-A INPUT -i eth0 -p tcp --dport 25 -j ACCEPT
259
# smtps
260
-A INPUT -i eth0 -p tcp --dport 465 -j ACCEPT
261
# submission
262
-A INPUT -i eth0 -p tcp --dport 587 -j ACCEPT
263
264
# DNS
265
# récursif, lisible par nos abonnés seulement
266
-N dns_limit
267
-A dns_limit -s 185.233.100.0/22 -j ACCEPT
268 7 sacha
-A INPUT -d 45.67.81.23 -p tcp -m tcp --dport 53 -j dns_limit
269
-A INPUT -d 45.67.81.23 -p udp -m udp --dport 53 -j dns_limit
270
-A INPUT -d 45.67.81.23 -p tcp -m tcp --dport 443 -j dns_limit
271
-A INPUT -d 45.67.81.23 -p tcp -m tcp --dport 853 -j dns_limit
272 19 sacha
273
# mais aussi par le reste d'Internet, mais en rate-limit
274
-A dns_limit -m string --algo bm --hex-string "|00 00 ff 00 01|" --from 28 -m hashlimit --hashlimit-above 1/sec --hashlimit-burst 2 --hashlimit-mode srcip --hashlimit-name RL-DNS-ANY-v4 --hashlimit-srcmask 28 -m comment --comment "RATE-LIMIT DNS ANY QTYPE 1/s burst 2" -j DROP
275
-A dns_limit -m string --algo bm --hex-string "|00 00 ff 00 01|" --from 28 -m hashlimit --hashlimit-above 20/min --hashlimit-mode srcip --hashlimit-name RL-DNS-ANY-v4-LOG --hashlimit-srcmask 28 -m comment --comment "RATE-LIMIT DNS ANY QTYPE 20/min" -j LOG --log-prefix "DNS-FLOOD "
276
-A dns_limit -m hashlimit --hashlimit-above 10/sec --hashlimit-burst 100 --hashlimit-mode srcip --hashlimit-name DNS --hashlimit-srcmask 28 -m comment --comment "RATE-LIMIT DNS 10/src burst 100" -j DROP
277
-A dns_limit -j ACCEPT
278
279
# ICMP
280
-A INPUT -p icmp -j ACCEPT
281
-A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
282
283
# NRPE
284
-A INPUT -s 185.233.100.230 -p tcp --dport 5666 -j ACCEPT
285
286
# Keepalived
287
-A INPUT -s 45.67.81.0/24 -p vrrp -j ACCEPT
288
289
COMMIT
290 20 sacha
~~~
291 3 sacha
292
## Configurations spécifiques
293
294
### Génération du certificat SSL sur Hades
295
296
~~~
297
certbot --apache --agree-tos --email sysop@aquilenet.fr -d dns.aquilenet.fr
298
chgrp bind /etc/letsencrypt/live/dns.aquilenet.fr/privkey.pem
299
chmod 0640 /etc/letsencrypt/live/dns.aquilenet.fr/privkey.pem
300 16 sacha
openssl dhparam -out /etc/bind/dhparam.pem 4096
301
~~~
302
303
Copie du certificat sur gaia
304
305 21 sacha
* /etc/letsencrypt/renewal/dns.aquilenet.fr.conf
306 1 sacha
307 21 sacha
~~~
308
+ post_hook = /root/certificats.sh
309
~~~
310 20 sacha
311 16 sacha
#!/bin/bash
312
rsync -aPHSA /etc/letsencrypt/archive/dns.aquilenet.fr gaia:/etc/letsencrypt/archive/
313
~~~
314
315
### Clée sdns (auth par épinglage de la clé / key pining)
316
317
* A partir de la clé
318
~~~
319 3 sacha
hades|19:21:08|:~# openssl rsa -in /etc/letsencrypt/live/dns.aquilenet.fr/privkey.pem -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64
320
writing RSA key
321
lBk09CRIPJ+J4O9rmbvJkEiGYoH5r9rxOIQdxkYxyII=
322
~~~
323
* ou à partir du certificat
324
~~~
325
hades|19:22:21|:~# openssl x509 -in /etc/letsencrypt/live/dns.aquilenet.fr/cert.pem -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
326
writing RSA key
327
lBk09CRIPJ+J4O9rmbvJkEiGYoH5r9rxOIQdxkYxyII=
328
~~~
329
330
### Keepalived
331
332
#### Hades Master
333
334
* /etc/keepalived/keepalived.conf
335
336
~~~
337
global_defs {
338
  notification_email {
339
    sysop@aquilenet.fr
340
  }
341
  notification_email_from vrrp-dns@aquilenet.fr.fr
342
  smtp_server localhost
343
  smtp_connect_timeout 30
344
}
345
346
vrrp_instance DNS {
347
  state MASTER 
348
  interface eth0
349
  virtual_router_id 101 
350
  priority 100
351
  advert_int 2
352
  smtp_alert
353
  unicast_src_ip 185.233.100.16 
354
  unicast_peer {
355
    185.233.100.2
356
  }
357
  virtual_ipaddress {
358
    45.67.81.23/32 dev eth1 scope global # VIP
359
  }
360
}
361
~~~
362
363
#### Gaia Slave
364
365
* /etc/keepalived/keepalived.conf
366
367
~~~
368
global_defs {
369
  notification_email {
370
    sysop@aquilenet.fr
371
  }
372
  notification_email_from vrrp-dns@aquilenet.fr.fr
373
  smtp_server localhost
374
  smtp_connect_timeout 30
375
}
376
377
vrrp_instance DNS {
378
  state BACKUP
379
  interface eth0
380
  virtual_router_id 101
381
  priority 50
382 1 sacha
  advert_int 2
383 4 sacha
  smtp_alert
384
  unicast_src_ip 185.233.100.2
385
  unicast_peer {
386
    185.233.100.16
387
  }
388 1 sacha
  virtual_ipaddress {
389 13 sacha
    45.67.81.23/32 dev eth1 scope global # VIP
390
  }
391
}
392
393 8 sacha
~~~
394 4 sacha
395
## Validation
396
397 8 sacha
* test du service
398
~~~
399 1 sacha
dig +short dns.aquilenet.fr @45.67.81.23 
400 12 sacha
45.67.81.23
401 9 sacha
dig +https +short dns.aquilenet.fr @45.67.81.23      
402
45.67.81.23
403
dig +tls +short dns.aquilenet.fr @45.67.81.23      
404
45.67.81.23
405 10 sacha
~~~
406
407 9 sacha
* bascule keepalived
408 16 sacha
409 17 sacha
sur hades: `systemctl stop keepalived`
410 16 sacha
sur gaia: `ip a |grep /32`doit donner "inet 45.67.81.23/32 scope global eth1"
411
http://dns.aquilenet.fr/host permet de savoir quel est le serveur qui porte l'IP virtuelle
412
413
## Indexes de serveurs DNS ouverts:
414 1 sacha
415
https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers <= fait
416
https://diyisp.org/dokuwiki/doku.php?id=technical:dnsresolver <= fait
417
https://diyisp.org/dokuwiki/doku.php?id=technical:dnsresolver <= fait
418
https://dnsprivacy.org/public_resolvers/
419
420
## Ressources
421
422
https://www.bortzmeyer.org/doh-bortzmeyer-fr-policy.html
423
https://www.bortzmeyer.org/7858.html
424
https://kb.isc.org/docs/aa-01386