Projet

Général

Profil

Wiki » Historique » Version 31

sacha, 10/12/2023 17:18

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