L'incident avec AdGuard pour Windows en octobre : Post Mortem
Certains utilisateurs d'AdGuard pour Windows ont récemment éprouvé des difficultés avec leur application. Après avoir publié la version 7.22, nous avons constaté que la mise à jour provoquait parfois des problèmes de chargement des pages dans les navigateurs. Si le problème a été rapidement résolu pour Chrome, il a persisté plus longtemps dans Firefox, car le bug s'est avéré rare et difficile à reproduire, résultant d'une combinaison inhabituelle de facteurs qui n'avaient pas été détectés lors des tests.
À la date de publication de cet article, nous avons publié un correctif — AdGuard pour Windows v7.22.1 — qui résout complètement le problème. Veuillez vous assurer que votre application est mise à jour vers la dernière version pour une expérience fluide. Si vous utilisez AdGuard sur d'autres plateformes, aucune action n'est nécessaire, tout devrait fonctionner comme prévu.
Nous vous prions de nous excuser pour la gêne occasionnée et espérons que cet incident n'aura pas d'incidence sur votre expérience globale avec AdGuard. Il s'agit d'un incident isolé qui ne se reproduira plus. Au-delà de la résolution du problème technique, nous avons également revu nos processus internes et avons déjà mis en œuvre plusieurs améliorations afin d'éviter que des situations similaires ne se reproduisent à l'avenir.
Vous trouverez ci-dessous la chronologie des événements qui ont conduit à l'incident, après quoi nous vous fournirons plus de détails techniques et dresserons la liste des mesures que nous prenons pour éviter que cela ne se reproduise à l'avenir.
L'historique de la situation
2 octobre
Nous avons publié AdGuard pour Windows v7.22.
4 octobre
Un utilisateur a ouvert un ticket GitHub signalant des problèmes de chargement des pages et, finalement, une erreur Timed out après la mise à jour vers la version 7.22.
6 octobre
Notre équipe d'assurance qualité a commencé à enquêter sur le problème, mais n'a pas réussi à le reproduire. L'équipe a transmis le problème aux développeurs le jour même, et des discussions internes ont commencé.
16 octobre
Au fur et à mesure que de nouveaux utilisateurs rejoignaient la discussion GitHub, les rapports et les votes positifs s'accumulaient. Malheureusement, à ce stade, l'équipe d'assurance qualité n'a pas suivi les directives internes d'escalade pour les problèmes de ce niveau. Nous avons rencontré de graves difficultés pour reproduire le bug, en partie à cause du caractère incohérent des rapports des utilisateurs. L'équipe en a donc conclu qu'il avait été introduit il y a plusieurs versions et qu'il ne nécessitait donc pas de correctif. Nous avons donc reporté son traitement à la prochaine version prévue et, bien que la tâche ait été marquée P1 : Critique, elle n'a pas été correctement transmise et nous avons perdu un temps précieux.
30 octobre
Après 24 jours, le problème a refait surface en interne, révélant l'ampleur réelle de son impact sur les utilisateurs. Une fois que nous avons réussi à reproduire le problème, nous avons pu estimer plus précisément l'étendue globale des dommages. Nous avons immédiatement commencé à travailler sur un correctif (v7.22.1). Cependant, une grande partie du temps et des efforts a été consacrée à reproduire le problème de manière fiable et à en comprendre la cause principale. Plusieurs hypothèses ont été testées et écartées au cours de ce processus.
Au cours de l'enquête, nous avons également découvert un bug Firefox lié aux connexions QUIC, qui ralentissait encore plus le chargement des pages et compliquait le débogage. De plus, un problème a été détecté lié à l'absence de filtrage des connexions QUIC lorsque AdGuard fonctionnait en parallèle avec AdGuard VPN en mode compatibilité avec Wintun désactivé.
1er novembre
Nous avons partiellement identifié la cause du problème et trouvé un moyen de le reproduire. Une correction a été mise en œuvre dans DnsLibs, notre moteur de filtrage DNS, et une version nocturne a été publiée à des fins de test.
5 novembre
Nous avons identifié la cause principale : un bug dans le composant de détection de boucle de routage de CoreLibs, le moteur de filtrage d'AdGuard. Le problème a été rapidement corrigé et une deuxième version nocturne a été publiée.
6 novembre
Les tests des versions nightly ont montré que les correctifs initiaux résolvaient la plupart des problèmes liés aux connexions TCP, mais que certains problèmes liés au protocole UDP persistaient. Afin de minimiser l'impact sur les utilisateurs, nous avons décidé de déployer les correctifs en deux phases. Tout d'abord, une troisième version nocturne a corrigé ces problèmes supplémentaires, notamment les correctifs finaux de la bibliothèque et les mises à jour des instructions du pilote. Nous avons ensuite préparé et testé de manière approfondie le correctif v7.22.1, qui a été publié le jour même.
Détails techniques
Le bug
Le bug dans AdGuard pour Windows v7.22 provoquait des blocages occasionnels et imprévisibles lors du chargement de certaines pages dans Firefox. Il n'affectait pas autant les utilisateurs de Chrome. Le problème a commencé après l'introduction dans CoreLibs v1.19 d'une protection contre les boucles de routage, un mécanisme conçu pour empêcher le trafic de revenir en boucle sur lui-même.
Le bug lui-même avait deux causes principales. Tout d'abord, une erreur de programmation excluait un port de la vérification des boucles de routage, ce qui signifiait que certaines connexions filtrées légitimes, telles que les requêtes du navigateur, pouvaient être bloquées. Cela était déclenché par certaines requêtes de service provenant d'AdGuard, telles que les requêtes OCSP. Après de telles requêtes, la connexion suivante du navigateur était interrompue.
Deuxièmement, la vérification était appliquée au mauvais endroit pour les connexions déjà établies, ce qui entraînait des blocages de connexion inutiles.
Pourquoi avons-nous besoin d'une protection contre les boucles de routage ?
Une boucle de routage se produit lorsque le trafic revient à son application source. Ces boucles peuvent ralentir les connexions et entraîner une utilisation élevée du processeur. Normalement, ces situations ne se produisent pas, mais en raison d'interactions avec d'autres logiciels, des boucles de routage peuvent tout de même se produire. Pour les éviter, AdGuard suit les connexions sortantes en fonction de leur adresse source et met fin à celles qui reviennent à la même adresse.
Pourquoi cela n'a-t-il eu qu'un impact limité sur Chrome ?
Comme seule la connexion suivant immédiatement celle du service était interrompue, les utilisateurs de Chrome étaient beaucoup moins susceptibles de remarquer le problème. En effet, Chrome tente automatiquement de réitérer la même requête réseau après une réinitialisation de la connexion.
Les utilisateurs de Firefox ont toutefois été affectés de manière plus directe : la conception du navigateur ne prévoit pas de nouvelles tentatives automatiques après une erreur réseau, ce qui a rendu le problème plus apparent pour eux.
Qu'en est-il d'AdGuard pour Linux et Android ?
Le problème en question n'a pas été détecté pendant la phase CLI avec la version 1.19, même si les nouvelles fonctionnalités sont toujours introduites en premier dans AdGuard CLI, afin que les problèmes majeurs puissent être détectés et corrigés avant leur intégration dans les applications basées sur l'interface utilisateur. Dans ce cas, le problème ne s'est produit qu'en mode automatique sous Linux, et principalement dans Firefox. En conséquence, très peu d'utilisateurs répondaient à ces critères, et aucun rapport d'utilisateur n'a donc été reçu.
Le problème n'est pas non plus apparu dans AdGuard pour Android v4.12, qui utilise la même CoreLibs 1.19, car les adresses de connexion entrantes et sortantes étaient différentes, ce qui empêchait les mêmes conditions qui ont déclenché le bug ailleurs.
Le diagnostic
Le diagnostic du problème s'est avéré particulièrement difficile. AdGuard ouvre relativement peu de connexions de service, et les tentatives répétées pour reproduire le problème utilisaient souvent des requêtes OCSP mises en cache, empêchant ainsi l'apparition du bug. De plus, le problème n'affectait qu'une seule connexion en aval à la fois. Les utilisateurs de Chrome n'étaient généralement pas affectés, car le navigateur réessaie automatiquement les connexions qui ont échoué, tandis que les utilisateurs de Firefox étaient directement touchés, car celui-ci ne tente pas de se reconnecter lorsqu'une erreur réseau se produit.
Un bug Firefox associé a été découvert au cours de nos recherches
Alors que nous recherchions ce bug difficile à trouver, nous avons découvert que la moitié des rapports présentaient d'autres symptômes et que les problèmes décrits commençaient à se reproduire également sur les versions précédentes d'AdGuard. C'est ainsi que nous avons également découvert un autre bug dans Firefox pour Windows affectant les connexions HTTP/3.
En bref, Firefox tente immédiatement d'établir des connexions HTTP/3 lorsqu'un site annonce qu'il prend en charge ce protocole, même si la connexion n'est pas encore disponible. AdGuard ne filtre actuellement pas HTTP/3 par défaut, donc HTTP/3 est bloqué pour les applications avec le filtrage HTTPS activé.
En général, les navigateurs intègrent un algorithme tel que Happy Eyeballs qui vous permet de choisir le protocole le plus adapté, mais Firefox pour Windows tente immédiatement d'établir une connexion HTTP/3 lorsqu'il reçoit l'information qu'un site dispose de HTTP/3 (par exemple, à partir d'un enregistrement DNS tel que HTTPS), et attribue les requêtes à une connexion HTTP/3 qui n'est pas encore établie, malgré la présence d'une connexion HTTP/2 active. Si HTTP/3 n'est pas disponible, cela entraîne des pauses dans le chargement du site pendant 20 à 30 secondes, après quoi les requêtes sont « réattribuées » à une connexion HTTP/2 active.
Un rapport de bogue concernant ce comportement a été rempli. À titre préventif, AdGuard a introduit une modification des enregistrements DNS de type HTTPS afin d'exclure le paramètre h3 ALPN lorsque le filtrage HTTP/3 est désactivé. Cela masque le fait que HTTP/3 est disponible depuis le navigateur dans les cas où il serait de toute façon bloqué par AdGuard.
Le correctif
Le correctif a été appliqué en deux phases.
La première phase a corrigé la logique de correspondance des connexions de manière à inclure correctement le port, ce qui a résolu la plupart des problèmes, même si certains faux positifs persistaient en raison de la réutilisation par Windows des ports de connexions récemment fermées. Une version nightly publiée dans la soirée du 5 novembre a aidé la plupart des utilisateurs.
Cependant, des traces du problème étaient encore visibles dans les fichiers journaux d'AdGuard. Il s'est avéré que le problème n'était que partiellement résolu : la correction de l'algorithme de correspondance des connexions n'était pas suffisante, car Windows peut réutiliser le port d'une connexion sortante dans la seconde qui suit la libération du socket. Cela a provoqué un autre type de faux positif, quand des connexions sans rapport avec la même adresse et le même port ont été identifiées à tort comme des boucles.
Il n'y a pas eu de nouveaux incidents évidents (tout le monde a signalé que tout fonctionnait bien), mais de nombreux utilisateurs pouvaient encore être affectés. C'est ainsi que nous sommes passés à la deuxième phase : elle a permis de traiter ces cas, aboutissant au correctif final, v7.22.1, qui a complètement résolu le problème.
Mesures préventives
Ce problème n'a pas été détecté plus tôt principalement en raison de la difficulté à le reproduire dans des conditions de test normales, combinée à une attention insuffisante accordée aux commentaires des utilisateurs.
Nous mettons actuellement à jour nos processus d'assurance qualité et de développement, en mettant particulièrement l'accent sur la combinaison d'un contrôle plus strict des processus, d'une automatisation améliorée et de tests et d'une communication plus rigoureux au sein des équipes. Nous visons ainsi à prévenir des incidents similaires à l'avenir et à garantir la fiabilité d'AdGuard pour tous les utilisateurs.
La modification du flux de travail de l'équipe QA
L'équipe d'assurance qualité commencera à accorder une attention particulière au nombre de commentaires et de votes positifs sur GitHub Issues. Afin de minimiser le facteur humain, cette surveillance ne reposera pas uniquement sur un examen manuel : l'automatisation sera introduite pour suivre l'activité et le nombre de votes positifs dans les problèmes publics. Si cette approche s'avère efficace, elle pourra être étendue et appliquée à toutes les équipes d'assurance qualité de tous les projets AdGuard.
Une réunion d'information supplémentaire sera organisée sur la base de nos directives de triage, et une pratique obligatoire sera mise en place pour l'évaluation interne des tickets dans Jira. Ce processus nécessitera une justification basée sur des directives de triage internes structurées, ce qui permettra de garantir la cohérence et la transparence des décisions de hiérarchisation.
L'équipe préparera également une liste de questions diagnostiques pour les utilisateurs, ce qui facilitera l'identification et l'analyse des problèmes liés au filtrage sur la base des commentaires des utilisateurs.
Enfin, plusieurs nouveaux tests automatisés seront mis en place afin d'éviter que des problèmes similaires ne se reproduisent à l'avenir. Un script de test de référence est en cours de développement afin d'évaluer la vitesse de filtrage des pages sur différents navigateurs. Une fois qu'une base de référence en matière de performances aura été définie, toutes les versions ultérieures seront évaluées par rapport à celle-ci. Actuellement, les tests automatisés ne sont utilisés que dans Google Chrome, mais nous prévoyons de les étendre également à Firefox. De plus, des tests seront écrits pour mesurer la vitesse de chargement d'un ensemble défini de pages « problématiques » dans ces navigateurs. Cette liste sera basée sur les sites web connus pour être problématiques et continuera à s'allonger, en commençant par ceux identifiés dans le cadre de l'enquête sur ce problème, par exemple discord.com.
La modification du flux de travail de l'équipe de développement
Les équipes de développement consacreront davantage d'attention à l'ajout de nouveaux tests, y compris des tests d'intégration, pour les nouvelles fonctionnalités, dans la mesure du possible, afin de réduire le risque d'apparition d'erreurs dans les versions futures. L'accent sera également mis sur la fourniture d'une documentation technique détaillée pour les nouvelles fonctionnalités et sur la nécessité d'informer correctement toutes les équipes concernées de la nécessité de tester les nouvelles fonctionnalités afin de détecter les problèmes potentiels et les cas limites.
Lors de l'intégration de nouvelles versions des CoreLibs dans les produits, les équipes attendront désormais l'accord explicite de l'équipe CoreLibs avant de poursuivre. À l'heure actuelle, ce processus d'intégration est mené de manière quelque peu « isolée », ce qui augmente le risque de passer à côté de certains problèmes.
En conclusion
Nous tenons à présenter une nouvelle fois nos excuses à tous les utilisateurs concernés par cet incident et à remercier sincèrement tous ceux qui nous ont fait part de leurs commentaires et nous ont aidés à surmonter cette situation difficile. À l'avenir, nous communiquerons plus rapidement et de manière plus transparente avec nos utilisateurs sur toute question critique susceptible d'avoir un impact significatif.