PowerDNS issueshttps://forge.tedomum.net/tedomum/docker-pdns/-/issues2024-03-28T07:49:23Zhttps://forge.tedomum.net/tedomum/docker-pdns/-/issues/2Scan effondrant l'infrastructure DNS2024-03-28T07:49:23Zkaiyoupierre@jaury.euScan effondrant l'infrastructure DNSJ'écris cette issue en guise de postmortem, l'incident évoqué étant terminé. C'est aussi l'occasion d'identifier les enseignements et les points à améliorer en conséquence, qui produiront d'autres issues. En somme : un incident assez bre...J'écris cette issue en guise de postmortem, l'incident évoqué étant terminé. C'est aussi l'occasion d'identifier les enseignements et les points à améliorer en conséquence, qui produiront d'autres issues. En somme : un incident assez bref mais stressant, et enrichissant entre autres pour ce qu'il a révélé de manquements. Avec les bonnes mesures on pourrait probablement éviter le prochain du même goût.
# Alerte générale
A partir de 20h52 notre monitoring s'affole, impossible de joindre la majorité des services. Environ dans le même temps, Angedestenebres indique qu'il ne charge plus les média sur Matrix.
Le constat est assez rapide : la majorité des services semble down principalement parce que nos DNS ne répondent plus. Difficile de savoir si tous les services sont bien up derrière le DNS, mais au minimum jusque là Matrix continue de fonctionner puisque la session HTTP est active. On peut donc continuer de se synchroniser un certain temps comme ça.
20h57 on prend acte de la situation, 21h10 on avait communiqué sur le seul canal encore bien disponible donc, Matrix.
**Enseignement 1** : disposer d'un compte Mastodon de secours pour communiquer au nom de l'association ne serait peut être pas un luxe.
# Enfermés dehors
Il faut l'admettre, perdre notre infra DNS arrive rarement. Pour ne pas dire très rarement, peut-être était-ce la troisième fois de la vie de TeDomum. On est donc très mal préparé à ce type d'incident.
Premier réflexe, se connecter au serveur qui héberge le DNS1 : `ssh aegir.tech.tedomum.net`. Sans résolution DNS ça fonctionne moins bien.
Seconde tentative, se connecter au serveur qui héberge le DNS2. C'est sur Kity, donc il faut deviner sur quel noeud il tourne. A l'aveugle éventuellement, mais quel que soit le nœud on. le même problème : `ssh servername.kaiyou.fr`. Pas de résolution, oups.
Si la démarche est peu documentée, on a bien des moyens out of band pour récupérer tout cela, inscrits comme des habitudes lorsqu'on perd l'accès aux machines. Pour le DNS1 qui est toujours chez OVH, le chemin de secours passe par la console. Il est 21h10, on est confiant jusqu'à la douche froide : OVH demande maintenant systématiquement une double authentification avec un code par e-mail. Sur ... `bureau@tedomum.net`. Sans DNS, pas de mail, pas de double authentification, pas d'accès.
**Enseignement 2** : dans la doc clonée chez tout le monde, une copie du plan d'adressage de l'infra pour quand le DNS est down, ce n'est pas un luxe du tout.
**Enseignement 2 bis** : partout où c'est possible pour les fournisseurs d'infra, configurer une authentification forte par TOTP et non par email
Heureusement, après 3 minutes la tête dans les mains pour réfléchir :
- pour le DNS2, les IP des serveurs sont connues, par coeur, modulo un exercice de mémoire ;
- pour le DNS1, les IP des serveurs sont cachées au fond de la conf si on y regarde bien.
Rien de satisfaisant, mais ça nous a sauvé cette fois.
# Le DNS se suicide
21h11 donc, et les logs du serveur DNS sont sans appel :
```
dns-1 | Mar 26 20:11:19 Limit of simultaneous TCP connections reached - raise max-tcp-connections
dns-1 | Mar 26 20:11:19 Limit of simultaneous TCP connections reached - raise max-tcp-connections
dns-1 | Mar 26 20:11:19 Limit of simultaneous TCP connections reached - raise max-tcp-connections
dns-1 | Mar 26 20:11:19 Limit of simultaneous TCP connections reached - raise max-tcp-connections
dns-1 | Mar 26 20:11:19 5001 questions waiting for database/backend attention. Limit is 5000, respawning
```
L'implémentation PowerDNS a une limite hard en nombre de connexions TCP simultanées, et la limite est éclatée. Pire, lorsque le nombre de requêtes en cours auprès de la base de données (SQLite) dépasse 5000, il se suicide par sécurité. Problème, comme il met bien 10 secondes à se relancer et moins de 1s à retomber, ça fait tout de suite 90% d'indisponibilité.
Soit le serveur a un défaut, soit le trafic est anormal. Après restart même constat, et donc `tcpdump` cette fois sans appel :
```
20:16:07.540492 IP 85.91.156.254.60874 > 51.255.128.50.53: Flags [S], seq 3008365075, win 29200, options [mss 1460,sackOK,TS val 3849076242 ecr 0,nop,wscale 7], length 0
20:16:07.540506 IP 85.91.156.248.1231 > 51.255.128.48.53: Flags [S], seq 3862767582, win 29200, options [mss 1460,sackOK,TS val 1769371524 ecr 0,nop,wscale 7], length 0
20:16:07.540546 IP6 2001:41d0:d:33ec:6464:0:555b:9cfe.60874 > 2001:41d0:d:33ec:f00::1.53: Flags [S], seq 3008365075, win 29200, options [mss 1460,sackOK,TS val 3849076242 ecr 0,nop,wscale 7], length 0
20:16:07.540588 IP6 2001:41d0:d:33ec:6464:0:555b:9cfe.60874 > 2001:41d0:d:33ec:f00::1.53: Flags [S], seq 3008365075, win 29200, options [mss 1460,sackOK,TS val 3849076242 ecr 0,nop,wscale 7], length 0
20:16:07.540671 IP 85.91.156.253.18530 > 51.255.128.48.53: Flags [S], seq 2076287542, win 29200, options [mss 1460,sackOK,TS val 1769371524 ecr 0,nop,wscale 7], length 0
20:16:07.541447 IP 172.71.181.157.25852 > 51.255.128.48.53: Flags [S], seq 262213462, win 64240, options [mss 1460,sackOK,TS val 611785107 ecr 0,nop,wscale 13], length 0
20:16:07.543957 IP 172.69.202.165.64220 > 51.255.128.48.53: Flags [S], seq 3753286929, win 64240, options [mss 1460,sackOK,TS val 3147405729 ecr 0,nop,wscale 13], length 0
20:16:07.544665 IP 109.233.89.139.46232 > 51.255.128.50.53: Flags [S], seq 764602936, win 29200, options [mss 1460,sackOK,TS val 956122928 ecr 0,nop,wscale 9], length 0
20:16:07.544687 IP6 2001:41d0:d:33ec:6464:0:6de9:598b.46232 > 2001:41d0:d:33ec:f00::1.53: Flags [S], seq 764602936, win 29200, options [mss 1460,sackOK,TS val 956122928 ecr 0,nop,wscale 9], length 0
20:16:07.544795 IP6 2001:41d0:d:33ec:6464:0:6de9:598b.46232 > 2001:41d0:d:33ec:f00::1.53: Flags [S], seq 764602936, win 29200, options [mss 1460,sackOK,TS val 956122928 ecr 0,nop,wscale 9], length 0
20:16:07.546123 IP 172.71.5.64.17764 > 51.255.128.48.53: Flags [S], seq 3601529964, win 64240, options [mss 1460,sackOK,TS val 1956675720 ecr 0,nop,wscale 13], length 0
20:16:07.546898 IP 213.226.0.184.9079 > 51.255.128.48.53: Flags [S], seq 986291426, win 29200, options [mss 1460,sackOK,TS val 3649981890 ecr 0,nop,wscale 7], length 0
20:16:07.548824 IP 109.233.89.139.53522 > 51.255.128.48.53: Flags [S], seq 4233782576, win 29200, options [mss 1460,sackOK,TS val 956122924 ecr 0,nop,wscale 9], length 0
20:16:07.549378 IP 172.71.101.153.12554 > 51.255.128.48.53: Flags [S], seq 3405164474, win 64240, options [mss 1460,sackOK,TS val 1894934868 ecr 0,nop,wscale 13], length 0
20:16:07.549776 IP 149.5.32.2.44057 > 51.255.128.50.53: Flags [S], seq 2497415330, win 64240, options [mss 1250,sackOK,TS val 1410410922 ecr 0,nop,wscale 7], length 0
20:16:07.549805 IP6 2001:41d0:d:33ec:6464:0:9505:2002.44057 > 2001:41d0:d:33ec:f00::1.53: Flags [S], seq 2497415330, win 64240, options [mss 1250,sackOK,TS val 1410410922 ecr 0,nop,wscale 7], length 0
20:16:07.549826 IP6 2001:41d0:d:33ec:6464:0:9505:2002.44057 > 2001:41d0:d:33ec:f00::1.53: Flags [S], seq 2497415330, win 64240, options [mss 1250,sackOK,TS val 1410410922 ecr 0,nop,wscale 7], length 0
```
En IPv4 comme en IPv6, sur toutes les IPs de nos DNS, une petite moyenne de 15-20 SYN TCP par 10ms, soit 1500-2000 par seconde, pas étonnant que ça éclate le nombre de sessions TCP, et donc le backend avec. A ce stade ça ressemble bêtement à un flood, sans bien savoir si c'est malveillant.
Et l'on manque cruellement de supervision bas-niveau. Notamment, la supervision réseau sur `aegir` est inexploitable puisque le `node-exporter` n'accède pas aux interfaces hôte :
![image](/uploads/516ab39942e69cb6ac0097f1b3d31ba7/image.png)
**Enseignement 3** : il nous faut faire un tour de la supervision matérielle et s'assurer qu'on a tous les signaux de base (CPU, RAM, disque, réseau).
# Bloquer l'attaque^W^W faire le mort
Si ça ne touche que TCP pas de souci, TCP est optionnel pour le bon fonctionnement de DNS.
Donc 21h15, suppression du trafic TCP 53 en entrée sur nos DNS. Raté.
```
dns-1 | Mar 26 20:15:23 5001 questions waiting for database/backend attention. Limit is 5000, respawning
```
Sur un vague sentiment que ça pourrait être une file de requête persistée on ne sait où, on redémarre, réinstancie le serveur, puis on augmente le seuil : `--max-queue-length=10000`. Rien n'y fait il se vautre toujours très vite.
Petite suée en se souvenant que nos instances PowerDNS sont tout sauf à jour. Et donc probablement pleines de vulnérabilités déni de service, dont PowerDNS a pas mal souffert les dernières années. La seule idée de mettre à jour le serveur DNS sans infra DNS pour build des images, tester, déployer, etc. n'est pas réjouissante du tout. On tente de se rassurer et l'on poursuit.
**Enseignement 4** : ne plus trop trainer sur les mises à jour d'infrastructure sous prétexte qu'elles ne sont pas critiques ("c'est du dos, on s'en moque") ; on perd trop de temps et d'énergie à douter si un réel dos soit lié à une vulnérabilité ou pas.
Heureusement un rapide `tcpdump` en UDP 53 écarte l'option d'une exploitation de vulnérabilité subtile par une attaque ciblée :
```
20:24:46.276050 IP6 2a00:1e48:99:31::2.37142 > 2001:41d0:d:33ec:f00::1.53: 52826 CNAME? plum-tree.tedomum.net. (39)
20:24:46.276075 IP6 2400:cb00:128:1024::a29e:b4f8.15514 > 2001:41d0:d:33ec:f00::1.53: 17768 [1au] CNAME? PHA.tedomum.net. (44)
20:24:46.276140 IP6 2407:8000:15:2f::185.57772 > 2001:41d0:d:33ec:f00::1.53: 26066 [1au] CNAME? abler.tedomum.net. (58)
20:24:46.276250 IP 213.186.33.99.53 > 51.255.128.48.41936: 53897 0/1/1 (106)
20:24:46.276323 IP 172.71.165.61.61545 > 51.255.128.50.53: 10912 [1au] CNAME? prenative.tedomum.net. (50)
20:24:46.276332 IP6 2400:cb00:113:1024::ac44:b92d.38248 > 2001:41d0:d:33ec::48.53: 35700 [1au] CNAME? bajka.tedomum.net. (46)
20:24:46.276341 IP6 2a00:1450:4025:1807::102.59609 > 2001:41d0:d:33ec:f00::1.53: 7549% [1au] CNAME? COsMEtIX.tedomUm.NET. (49)
20:24:46.276371 IP6 2001:41d0:d:33ec:6464:0:ac47:a53d.61545 > 2001:41d0:d:33ec:f00::1.53: 10912 [1au] CNAME? prenative.tedomum.net. (50)
20:24:46.276394 IP6 2001:41d0:d:33ec:6464:0:ac47:a53d.61545 > 2001:41d0:d:33ec:f00::1.53: 10912 [1au] CNAME? prenative.tedomum.net. (50)
20:24:46.276433 IP6 2001:8000:100::60:219.41004 > 2001:41d0:d:33ec::48.53: 11855% [1au] CNAME? omalgia.tedomum.net. (48)
20:24:46.276462 IP6 2800:3f0:4003:c0b::102.55602 > 2001:41d0:d:33ec::48.53: 11888% [1au] CNAME? fRiTs.tEdOMUM.net. (46)
20:24:46.276544 IP6 2607:f8b0:4004:1000::102.38162 > 2001:41d0:d:33ec::48.53: 11313% [1au] CNAME? SeRIeStv.bLOG.TEdOMum.nEt. (54)
20:24:46.276586 IP6 2607:f8b0:4004:c1d::105.55255 > 2001:41d0:d:33ec::48.53: 811% [1au] CNAME? siLVA0826.tEDoMUM.NeT. (61)
20:24:46.276604 IP6 2a00:1450:4025:804::104.56833 > 2001:41d0:d:33ec:f00::1.53: 30105% [1au] CNAME? eSrAr7.TedoMUM.NeT. (47)
20:24:46.276652 IP6 2400:cb00:447:1024::ac46:d539.13610 > 2001:41d0:d:33ec:f00::1.53: 21792 [1au] CNAME? receptacula.tedomum.net. (52)
20:24:46.276729 IP6 2607:f8b0:4003:c01::102.63823 > 2001:41d0:d:33ec::48.53: 5991% [1au] CNAME? yiNgfEnGHuIyuLEcHEng.TedoMUm.NET. (61)
20:24:46.276774 IP6 2a01:260:1:2::3.13100 > 2001:41d0:d:33ec::48.53: 48165% [1au] A? ksksat.tedomum.net. (47)
20:24:46.276777 IP6 2607:f8b0:400d:c0e::107.45999 > 2001:41d0:d:33ec::48.53: 24945% [1au] CNAME? kYfIRecoMmisSIOn.tEdOMuM.neT. (57)
20:24:46.276780 IP6 2600:1406:3c::1721:5742.44384 > 2001:41d0:d:33ec::48.53: 1178 [1au] CNAME? oracoesdeminhamae.tedomum.net. (58)
20:24:46.276878 IP6 2800:160:1:90::5b:de20.50597 > 2001:41d0:d:33ec:f00::1.53: 30318 CNAME? jackets.tedomum.net. (37)
20:24:46.276878 IP6 2404:6800:4005:c03::102.60316 > 2001:41d0:d:33ec:f00::1.53: 29694% [1au] CNAME? nyLgHAu.tEdOmum.nEt. (48)
20:24:46.276973 IP6 2404:6800:4003:c1c::10a.51489 > 2001:41d0:d:33ec:f00::1.53: 399% [1au] CNAME? city-TV.TedOMuM.nEt. (48)
```
Exit l'interprétation en SYN flood, le trafic TCP est probablement du véritable DNS, et l'arbre qui cachait la forêt de plus de 20kqps TCP et UDP, un bon scan de notre domaine `tedomum.net`. Si ce type de scan n'est pas rare, et constitue même une part amusante du trafic Internet, un taux de à 20kqps est élevé.
Elevé certes, mais à la portée de PowerDNS en théorie, réputé absorber jusque 50kqps sur un coeur d'une machine performante. Assurément notre tuning mérite un petit lifting : https://doc.powerdns.com/authoritative/performance.html On pourrait aussi se tourner vers dnsdist en complément.
**Enseignement 5** : si on tune notre PowerDNS, on doit pouvoir absorber le prochain trafic de ce type et de ce volume.
Il est 21h20, nous sommes down depuis 20 minutes, et il va falloir analyser du trafic.
L'expérience en tant que victime de scan et/ou de flood est assez classique : ou bien quand la solution n'est pas à portée de main (montée en perfs pas triviale, blocage du trafic pas simple), ou bien quand les volumes sont simplement impossibles à gérer, il vaut mieux plier. L'attaquant se lasse, les scanners adaptent leur débit, et il est donc plus productif de couper le service temporairement que de le maintenir en mauvais état. C'est même exactement la démarche des opérateurs : sacrifier le client attaqué pour sauver les autres.
Un dernier pcap pour analyse avant de couper :
```
tcpdump -w trace.cap -nei eno1 tcp port 53 or udp port 53
docker compose down dns
```
Ca n'a pas manqué, 21h25 le trafic a diminué, et 21h30 les services revenaient à la normale doucement. Heureusement une partie de la supervision reste exploitable en postmortem, puisque les restart de conteneur Docker impactent beaucoup la RAM :
![image](/uploads/da489ec2d64de4796a36b465c3c436e9/image.png)
C'est discret, ça pourrait passer inaperçu, mais c'est parlant lorsqu'on sait ce qu'on recherche, et très précieux en analyse.
**Enseignement 6** : faire un peu de formation dans l'association à la bonne exploitation des métriques, même quand on n'a pas les bonnes métriques.
# Tshark, pandas, l'animalerie s'invite au postmortem
Même si l'analyse détaillée du trafic n'offre pas ici la résolution, elle permet de mieux comprendre l'incident, le contexte et le risque de récidive.
D'abord le trafic semble être du DNS légitime, mélangeant de l'UDP et du TCP et portant sur la résolution de noms générés dans `tedomum.net`. On reprend quelques exemples significatifs :
```
20:24:46.276341 IP6 2a00:1450:4025:1807::102.59609 > 2001:41d0:d:33ec:f00::1.53: 7549% [1au] CNAME? COsMEtIX.tedomUm.NET. (49)
20:24:46.276371 IP6 2001:41d0:d:33ec:6464:0:ac47:a53d.61545 > 2001:41d0:d:33ec:f00::1.53: 10912 [1au] CNAME? prenative.tedomum.net. (50)
20:24:46.276394 IP6 2001:41d0:d:33ec:6464:0:ac47:a53d.61545 > 2001:41d0:d:33ec:f00::1.53: 10912 [1au] CNAME? prenative.tedomum.net. (50)
20:24:46.276433 IP6 2001:8000:100::60:219.41004 > 2001:41d0:d:33ec::48.53: 11855% [1au] CNAME? omalgia.tedomum.net. (48)
```
On capture donc une minute complète de trafic UDP DNS, le plus facile à analyser (une trame, une requête) :
```
tcpdump -nei eno1 -w trace.cap udp port 53
```
La trace contient 1.5 millions de requêtes DNS qu'il s'agit donc d'analyser. On charge le fichier de trace dans un RAMFS et l'on débute l'analyse. Sans dégainer de suite d'indexation avancée à la Splunk ou Elastic, plusieurs outils libres permettent une analyse approfondie de PCAP en ligne de commande :
- tcpdump lui-même, pratique pour filtrer mais la sortie est peu configurable ;
- Joy (https://github.com/cisco/joy) et Mercury de Cisco, peu expressifs mais performants ;
- fq (https://github.com/wader/fq) pour l'analyse de binaire, très expressif mais un petit peu lent ;
- tshark, assez complet et polyvalent, dispose des dissecteurs de Wireshark.
Le plus souvent plutôt que `fq`, je préfère `tshark` en mode JSON doublé de `jq`, plus performant :
```
tshark -nr trace.cap -T json > output.json
jq . < output.json
```
Seulement quelques millions de paquets en JSON représentent quelques Go de stockage et sont assez longs à parser. On souhaite analyser très simplement les IP sources et les noms requêtés, on se contente donc de :
```
tshark -nr trace.cap -T fields -e _ws.col.Source -e dns.qry.name > trace.txt
```
Le champ virtuel `_ws.col.Source` représente l'adresse source et évite de requêter séparément `ip.src` et `ipv6.src`, générant des colonnes vides. La sortie est ainsi un CSV valide et traitable directement en flux texte avec la suite GNU.
```
# Nombre de requêtes dans la trace
$ wc -l trace.txt
1454902 trace.txt
# Nombre d'IP source uniques
$ cat trace.txt | cut -f 1 | sort | uniq | wc -l
8266
```
Mais surtout, il est facile de charger les données dans Pandas pour un petit peu d'analyse statistique.
```
>>> import pandas as pd
>>> data = pd.read_csv('trace.txt', delimiter="\t", names=['ip','name'])
>>> data
ip name
0 2a00:1450:400c:c1b::10c PropHEt-FlOwEr.teDoMUm.net
1 2400:cb00:445:1024::ac46:cdc8 salvably.tedomum.net
2 2a00:1450:4025:1007::101 TOnGaRi.TedOMuM.net
3 2404:6800:4005:c00::102 gOKibURitaiZi.teDoMum.NEt
4 2400:cb00:619:1024::a29e:592d aomenjinshaduchangguanfangwangzhaopin.tedomum.net
... ... ...
1454897 2400:cb00:12:1024::ac45:204e yuhuiyulecheng.tedomum.net
1454898 2002:d373:42af::d373:42af baijialeyingqianzhanlue.tedomum.net
1454899 2400:cb00:12:1024::ac45:204d acetite.tedomum.net
1454900 2400:cb00:132:1024::a29e:f857 s1027.tedomum.net
1454901 2a04:c604:409:fe::202 rayxiao92.tedomum.net
[1454902 rows x 2 columns]
```
On commence par compter les IP et observer la répartition du nombre d'occurences : combien de gros émetteurs, de petits émetteurs, etc.
```
>>> histo = data.value_counts('ip').to_frame('count')
>>> histo['bucket'] = pd.cut(histo['count'], 20, precision=-2)
>>> import seaborn
>>> seaborn.countplot(histo, x='bucket')
```
![Figure_1](/uploads/2d47b9a1dd2d12c1d2630744a3b3633c/Figure_1.png)
L'origine des requêtes est très distribuée (la majorité des émetteurs émettent finalement peu de requêtes), quoique certaines sources sont très génératrices. Le top 1% des émetteurs génère le quart des requêtes :
```
>>> histo['count'].cumsum()[:len(histo)//100]
ip
2400:cb00:445:1024::ac46:cdc8 17472
2400:cb00:618:1024::a29e:b914 34737
2400:cb00:445:1024::ac46:cdc7 51863
2400:cb00:618:1024::a29e:b913 68883
2400:cb00:447:1024::ac46:d539 85516
...
2001:8a0:1:1a::210 391638
2a00:1450:4025:1807::104 393347
2a00:1450:4025:1805::105 395056
2a00:1450:4025:1807::105 396764
2001:dc8:0:2::106 398463
Name: count, Length: 82, dtype: int64
```
De même le top 1/3 des émetteurs génère 99% du trafic. C'est un profil très différent d'un déni de service distribué en pur flood, où certes le débit des émetteurs varie, mais où le profil est généralement plus gaussien. Est-ce bien un DOS ou plutôt juste un scan massif ? Difficile de conclure.
# Recursors, recursors everywhere
L'étude rapide des IP source montre très clairement des patterns, en particulier dans le top :
```
>>> print("\n".join(histo[:20].index))
2400:cb00:445:1024::ac46:cdc8
2400:cb00:618:1024::a29e:b914
2400:cb00:445:1024::ac46:cdc7
2400:cb00:618:1024::a29e:b913
2400:cb00:447:1024::ac46:d539
2400:cb00:619:1024::a29e:592d
2400:cb00:619:1024::a29e:592b
2400:cb00:447:1024::ac46:d53a
2400:cb00:446:1024::ac46:d13d
2400:cb00:446:1024::ac46:d13f
2400:cb00:446:1024::ac46:d13e
2400:cb00:12:1024::ac45:20e4
2400:cb00:12:1024::ac45:204d
2400:cb00:12:1024::ac45:204e
2400:cb00:45:1024::c5ea:f167
2400:cb00:193:1024::a29e:e15f
2400:cb00:704:1024::ac45:913b
2400:cb00:132:1024::a29e:f857
2400:cb00:362:1024::ac44:e756
```
La quasi totalité de ces premières IPs relève de... Cloudflare.
```
$ whois 2400:cb00:445:1024::ac46:cdc8
inet6num: 2400:cb00::/36
netname: CLOUDFLARE_2400_CB00_0000_36
descr: Cloudflare, Inc.
descr: 101 Townsend Street, San Francisco CA 94107
country: US
admin-c: CTC17-AP
tech-c: CTC17-AP
abuse-c: AC1914-AP
status: ALLOCATED NON-PORTABLE
mnt-by: MAINT-CLOUDFLARE-AP
mnt-irt: IRT-CLOUDFLARE-AP
last-modified: 2021-01-13T23:48:10Z
source: APNIC
```
Le tour des IP montre en fait des recursors, partout autour du globe. Le trafic proviendrait donc d'un botnet de machines, plausiblement compromises, qui résolvent naturellement à travers leurs recursor. Nous recevons le trafic des recursors et non des émetteurs eux-mêmes.
On remarque au passage que peu de trafic IPv4 est représenté dans la capture. Soit le monde a bien changé, soit... OVH, où nous hébergeons nos points d'entrée publics, a détecté quelque chose. Et en effet la « protection anti-DDOS » de OVH s'est bien déclenchée pendant l'incident. Elle n'a filtré que le trafic IPv4 et nous a laissé sous le flot de trafic IPv6.
**Enseignement 6** : la protection anti ddos des gros hébergeurs ne nous est que modérément utile.
Vu le profil des recursors (Cloudflare, Quad9, Google, mais aussi Telefonica, SFR, etc.) il est probable qu'il s'agisse d'un botnet plutôt gros et plutôt varié, avec du serveur et de la station, ce depuis les providers de nombreux pays :
```
>>> import GeoIP
>>> g = GeoIP.open("/usr/share/GeoIP/GeoIPv6.dat", 0)
>>> histo['country'] = histo.index.map(g.country_code_by_addr_v6)
>>> histo.groupby('country').sum().sort_values('count')[-10:]
count
country
BR 36431
IE 38996
CL 51312
HK 53624
PL 63347
IN 67586
FI 67901
FR 82412
SG 96047
US 427263
```
# Notre cœur balance
L'origine du trafic est distribuée. Nous sommes clairement la cible vu les noms résolus en `tedomum.net`. Mais difficile d'affirmer s'il s'agit d'un scan mal tuné ou d'un déni de service volontaire.
Il y a finalement peu de noms uniques dans la liste :
```
cat trace.txt | cut -f 2 | tr 'A-Z' 'a-z' | sort | uniq | wc -l
47694
```
Donc la même wordlist est jouée encore et encore, à raison de tous les mots toutes les 2 secondes, pendant 30 minutes. Quelques recherches sur des mots très particuliers de la wordlist remontent https://gist.github.com/miguelmota/706ebaeb661e246e1b682c400d49d1c9 comme une source probable, qui couvre la majorité des noms croisés sur la capture.
Il reste que : pourquoi ? Pourquoi sampler en boucle depuis la liste ? Quelle logique de scan ? Probablement aucune. C'est en tout cas notre meilleure conclusion à ce stade : le déni de service est malveillant et ciblé.
Le nombre de requêtes sur une minute depuis un Cloudflare ou Quad9 est de l'ordre de grandeur du nombre de mots dans la wordlist, cohérent avec une mise en cache à leur niveau. On peut imaginer que le trafic initial était bien supérieur. S'il est impossible d'évaluer le nombre réel de machines à l'origine, l'ordre de grandeur est probablement supérieur à 5000 (8000 IP uniques vues, la plupart des recursors ayant plusieurs IP de sorties en uptream mais servant aussi plusieurs clients en downstream).
Mettons 10000 machines pendant les 30 minutes d'attaque, soit 5kbots.h. Au marché c'est quelques dizaines d'euros. La résolution DNS massive pour faire plier nos serveurs autoritaires ressemble à un schéma dit de *water torture*. Seulement pour 20-30 minutes de downtime il serait bien plus efficace d'émettre les 25kqps depuis une poignée de machines à quelques centimes de l'heure.
Plus speculativement donc, ce pourrait être une forme de déni de service malveillant de nos serveurs DNS, employant 3 axes de sophistication :
- des requêtes DNS depuis un botnet pour distribuer le trafic,
- des requêtes à travers les recursors natifs des machines, donc reçues chez nous depuis des recursors représentatifs d'Internet, impossibles à bloquer sans bloquer tout le monde,
- des requêtes variées en bouclant sur un wordlist d'environ 50k mots pour limiter les effets de cache.
Un schéma sophistiqué et cher, peu cohérent avec notre profil de victime de faible intérêt. Ce pourrait être un acte individuel, motivé par une frustration. Ou bien un scénario d'entraînement, dont nous ne sommes la cible que fortuite.
**Enseignement 7** : il faut peut être qu'on se prépare à d'autres scénarios du type, et qu'on partage notre compréhension aux collègues CHATONs qui pourraient être également ciblés.https://forge.tedomum.net/tedomum/docker-pdns/-/issues/1Version 0.2.3 à installer2022-01-19T16:47:38ZAngedestenebresVersion 0.2.3 à installerTout est dans le titre, voir https://github.com/ngoduykhanh/PowerDNS-Admin/releases
Au passage, il serait bien de passer en version `tedomum-prod`Tout est dans le titre, voir https://github.com/ngoduykhanh/PowerDNS-Admin/releases
Au passage, il serait bien de passer en version `tedomum-prod`kaiyoupierre@jaury.eukaiyoupierre@jaury.eu