Forum Linux.général Sélection du DNS en fonction du nom à résoudre

Posté par  .
Étiquettes : aucune
1
27
oct.
2010
Bonsoir,

Je me doute bien que le sujet n'est pas vraiment compréhensible mais je n'arrive pas à résumer ce que je veux faire, ce qui m'empêche de faire une requête Google pertinente et obtenir la réponse à ma question.

Je voudrais que les requêtes DNS soient envoyées à des serveurs différents en fonction du nom à résoudre. Par exemple:
  • Les requêtes contenant xyz sont envoyés à serveurdns_1
  • Les requêtes contenant abc sont envoyées à serveurdns_2
  • Les autres requêtes sont envoyées à 8.8.8.8, 156.154.70.22, 156.154.71.22, 208.67.222.222, 208.67.220.220, 63.251.62.33, 69.111.95.106 etc...
Exactement comme le permet l'option -S de dnsmasq : http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html

Je trouve dommage de devoir installer un serveur DNS en local pour faire ça.

Existe-t-il d'autres solutions pour obtenir ce résultat ?
  • # champ NS dans ton nom de domaine

    Posté par  . Évalué à 3.

    le champ NS va determiner quel DNS gere le nom de domaine visée

    ca ne dira pas quel DNS doit etre interrogé, mais ca dira qui est depositaire de la gestion de ce nom de domaine.

    ex :

    mondomaine.com IN NS dns.ovh.net

    nous dit que mondomaine.com est gere par OVH

    maintenant, je ne sais pas ce que tu veux faire plus en detail, mais si tu nous l'expliques, on trouvera peut-etre d'autres options
  • # qhookjk

    Posté par  (site web personnel) . Évalué à 10.

    Alors c'est pas vraiment documenté mais le resolver de la glibc donne accès à des hooks pré et post-résolution. Dans res_send.c :
     503                                 res_sendhookact act;
     504 
     505                                 struct sockaddr_in *nsap4;
     506                                 nsap4 = (struct sockaddr_in *) nsap;
     507                                 act = (*statp->qhook)(&nsap4, &buf, &buflen,
     508                                                       ans, anssiz, &resplen);
     509                                 nsap = (struct sockaddr_in6 *) nsap4;
     510                                 switch (act) {
     511                                 case res_goahead:
     512                                         done = 1;
     513                                         break;
     514                                 case res_nextns:
     515                                         __res_iclose(statp, false);
     516                                         goto next_ns;
     517                                 case res_done:
     518                                         return (resplen);
     519                                 case res_modified:
     520                                         /* give the hook another try */
     521                                         if (++loops < 42) /*doug adams*/
     522                                                 break;
     523                                         /*FALLTHROUGH*/
     524                                 case res_error:
     525                                         /*FALLTHROUGH*/
     526                                 default:
     527                                         return (-1);
     528                                 }
    Donc le truc c'est de placer le pointeur vers ta fonction qui va pouvoir faire un peu ce qu'elle veut, y compris décider d'utiliser l'un ou l'autre serveur de nom selon des critères arbitraires tels que le contenu de la requête. Soit tu va écrire dans _res.qhook directement, soit tu utilises res_send_setqhook() :
    197 void
    198 res_send_setqhook(res_send_qhook hook) {
    199         _res.qhook = hook;
    200 }
    Pour la déclaration de la fonction que tu vas écrire, voir resolv.h :
     71 typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
     72         res_sendhookact;
     73 
     74 typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *__ns,
     75                                            const u_char **__query,
     76                                            int *__querylen,
     77                                            u_char *__ans,
     78                                            int __anssiz,
     79                                            int *__resplen);
     ..
    104 struct __res_state {
    ...
    126         res_send_qhook qhook;           /* query hook */
    Donc une fois que tu as écrit ton myresolvhook.so, tu peux l'injecter partout avec LD_PRELOAD. Une alternative sur un système qui dispose du patch utrace serait d'utiliser stap -g. Et si t'as rien compris, utilise juste un serveur DNS.

    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: qhookjk

      Posté par  . Évalué à 1.

      Merci beaucoup pour ta réponse, je n'aurais jamais trouvé ça tout seul.

      Ce que je trouve étrange est que personne n'ai jamais écrit une petit bibliothèque qui fait ça. C'est vraiment un besoin si particulier que ça ?

      Donc, j'écris une petite fonction dont le prototype correspond à celui déclaré dans resolv.h qui va me lire mon petit fichier de config avec les associations requêtes/serveur DNS et me crée la structure qui va bien. Je suis pas couché mais ça à l'air faisable !

      Je n'ai jamais écrit de bibliothèque partagée, il suffit de compiler avec -fPIC sous gcc ?

      Le point qui me parait compliqué est le déploiement de la bibliothèque partagée... Un export LD_PRELOAD suffira pour le shell courant et ses enfants, mais ça ne fonctionnera pas pour tout le système. Je peux éventuellement le placer dans /etc/profile mais dans ce cas Apache (par exemple) n'utilisera pas le hook.
      • [^] # Re: qhookjk

        Posté par  . Évalué à 4.

        avant de te lancer dans le recodage de bibliotheque,

        expliques un peu plus en details ce que tu veux faire ?

        parce que :
        interroger le serveur DNS A quand on demande toto.domaineA.com ou titi.domaineA.com
        et
        interroger le serveur DNS B quand on demande tutu.domaineB.com ou tyty.domaineB.com

        et interroger le dns de ton FAI pour les autres domaines.

        ca ressemble quand meme grandement au besoin d'un DNS LOCAL à ton infrastructure
        pour servir des noms de domaines en interne de ta maison/société.

        Meme si le DNS ne fait que "forwarder" à google ou ton fai pour les domaines qu'il ne connait pas (autre que domaineA.com et domaineB.com)
        • [^] # Re: qhookjk

          Posté par  . Évalué à 1.

          En fait, j'ai un mini-"serveur" chez moi qui est connecté au réseau de mon école via un VPN (donc y'a aussi un "serveur" de l'autre côté). J'arrive sans problèmes à me connecter depuis le serveur chez moi vers des machines du réseau de mon école en spécifiant leurs adresses IP. Je voudrais pouvoir faire la même chose en spécifiant leur nom (qui appartient soit au domaine educ.nom_de_lecole soit res.nom_de_lecole).

          Jusqu'ici j'avais trois solutions:
          - Remplir le /etc/hosts du serveur chez-moi avec les noms des machines de l'école, ce qui est assez chiant.
          - Mettre uniquement le DNS de l'école dans /etc/resolv.conf mais dans ce cas, je leur envoie toutes mes requêtes DNS ce que je ne veux pas.
          - Installer dnsmasq (ou autre serveur DNS) en local sur la machine et spécifier des "forwarders" à la main. Ce qui fonctionne bien mais est un peu lourd.
          • [^] # Re: qhookjk

            Posté par  . Évalué à 1.

            Une alternative assez simple, consiste à mettre à jour /etc/resolv.conf quand le VPN fonctionne et à restaurer l'ancien fichier quand le VPN s’arrête. Si tu utilises openvpn tu peux très facilement le faire avec les commandes "up" et "down"
            # Shell command to run after successful TUN/TAP device open
            up /etc/openvpn/up.sh

            # Shell command to run after TUN/TAP device close
            down /etc/openvpn/down.sh

            C'est ce qu'on utilise sur les laptops du boulot.
            • [^] # Re: qhookjk

              Posté par  . Évalué à 1.

              Et du coup, tu me proposes de faire passer toutes mes requêtes par le DNS de l'école lorsque le VPN est connecté, je suppose.

              C'est a moitié chiant comme solution puisque ça voudrait dire qu'il faut que je sois constamment en train de connecter/déconnecter le VPN dès que j'en ai besoin ou pas. En plus, le VPN ne me sert pas qu'à accéder au réseau de l'école depuis chez moi, il sert également à router tous les protocoles interdits à l'école (SSH et svnserve surtout). Du coup, c'est vraiment pas pratique si je le déconnecte n'importe quand.

              Merci à tout le monde de m'avoir indiqué les différentes solutions envisageables (je pense qu'on doit avoir fait le tour maintenant), je voulais être sur qu'il n'existait pas une solution simple permettant de faire ce que je veux.

              Je pense que ca n'existe pas car, comme le dit NeoX, en général lorsqu'on a besoin d'avoir différents "forwarders" en fonction du nom de domaine, on installe un serveur DNS qui est utilisé par tout un réseau. Dans mon cas, il y a juste un hôte qui a besoin d'avoir une configuration aussi tordue donc le serveur DNS est inutile et une petite bidouille avec le resolver de la glibc fera amplement l'affaire.
              • [^] # Re: qhookjk

                Posté par  . Évalué à 3.

                on doit pas avoir la meme notion de facile à faire

                Dans mon cas, il y a juste un hôte qui a besoin d'avoir une configuration aussi tordue donc le serveur DNS est inutile et une petite bidouille avec le resolver de la glibc fera amplement l'affaire.

                1°°)Installer un DNS, suivant la distribution c'est :
                aptitude install bind9
                yum install bind9

                ou dans le gestionnaire de paquet, chercher bind9/dnsmasq/djbdns

                2°) alors que creer un programme, qui va surcharger une librairie (.so)
                qu'il faudra ensuite charger avec un LD_PRELOAD avant de lancer le programme qui va faire sa requete DNS.


                Perso je trouve qu'installer le DNS est plus facile et moins contraignant
                • [^] # Re: qhookjk

                  Posté par  . Évalué à 1.

                  Évidemment qu'en termes de temps, la solution du serveur DNS est clairement la plus rapide à mettre en œuvre. Enfin on sera d'accord qu'installer un serveur DNS juste pour un hôte c'est clairement excessif, non ?

                  Je suis bien conscient que la solution de la bibliothèque partagée chargée en LD_PRELOAD est moins "propre" et pas du tout académique. Mais après tout, je fais tout ça pour m'amuser, je cherche à améliorer la solution que j'ai déjà, et c'est l'occasion d'apprendre de nouvelles choses (Et pour te conforter dans ton idée, ça fait 4 heures que j'ai commencé à regarder le truc et ça marche toujours pas...)

                  Je suis pas dans une boite avec des délais à tenir, ce qui explique qu'on ait pas le même point de vue.
                  • [^] # Re: qhookjk

                    Posté par  (site web personnel) . Évalué à 3.

                    > Enfin on sera d'accord qu'installer un serveur DNS juste pour un hôte c'est clairement excessif, non ?

                    Non.

                    Le hook de la glibc est certes plus amusant à mettre en place.

                    pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

              • [^] # Re: qhookjk

                Posté par  . Évalué à 2.

                Exactement, la solution que je te proposais n'est valable que si le VPN ne sert qu'à accéder au réseau de l'école, et dans ce cas on redirige tout vers le VPN. C'est une méthode classique et simple qui convient pour la majorité des usages. (permettre aux utilisateurs distants d'accéder à l'intranet). Mais effectivement ça ne convient pas du tout à ton usage, car tu as besoin d'un routage bien plus complexe, et donc d'une solution sur-mesure.
          • [^] # Re: qhookjk

            Posté par  . Évalué à 2.

            Juste pour bien comprendre : le réseau de ton école présente des noms de domaine avec des TLD « maison » ? Et ne résout rien d'autre ?
            C'est complètement pourri comme archi réseau, tu m'étonnes qu'il faille contourner ce bordel…
            • [^] # Re: qhookjk

              Posté par  . Évalué à 2.

              Le réseau de mon école présente des TLD maison. Par contre, le serveur DNS résout tout (il résout www.google.fr par exemple), mais je n'ai pas envie de leur filer toutes mes requêtes DNS.
              • [^] # Re: qhookjk

                Posté par  . Évalué à 1.

                et tu as essayé en mettant deux nameservers dans ton resolv.conf

                le premier celui de ton fournisseur
                le deuxieme celui de ton ecole


                de memoire quand on tente de resoudre avec le premier et que ca echoue, ca tente de resoudre avec le second

                du coup ca le ferait pour tes domaines educ.monecole et res.monecole qui sont inconnus de ton fournisseur
                • [^] # Re: qhookjk

                  Posté par  . Évalué à 1.

                  Non, cette solution ne marche pas.

                  Le deuxième n'est utilisé que si le premier ne répond pas.
                  Si le premier répond que le nom demandé n'existe pas, c'est une réponse valide; et donc, pas d'interrogation du second.
  • # Deux idées

    Posté par  (site web personnel) . Évalué à 4.

    Je présume que tu cherches à faire cela de manière régulière, et pas au coup par coup.

    Cela dit, au moins pour faire des tests, il est possible d'interroger un serveur DNS particulier lors d'une requête avec dig :

    dig @192.168.0.1 A linuxfr.org

    Permet d'interroger spécifiquement le serveur DNS ayant l'adresse IP 192.168.0.1.

    Sinon de manière pérenne, il faudrait effectivement installer un serveur de noms local. BIND permet de préciser les adresses de serveurs à consulter pour un domaine particulier :

    zone "exemple.com" {
    type forward;
    forwarders { 192.168.0.1; 192.168.0.2; };
    };

    C'est similaire aux directives utilisées pour monter un DNS cache, sauf que c'est pour un domaine particulier.

    Mais il faudrait effectivement que tes requêtes 'xyz" et 'abc' correspondent à des domaines.
    • [^] # Re: Deux idées

      Posté par  . Évalué à 1.

      Oui, mais je voulais éviter d'avoir à installer un DNS cache qui ne sert qu'à la machine locale.

      Je voulais savoir si il existait une solution plus simple et apparemment ce n'est pas le cas.
      Je vais faire une petite bibliothèque comme le suggère Krunch.
      • [^] # Re: Deux idées

        Posté par  . Évalué à 3.

        En gros tu vas réinventer la roue, plutôt que d'utiliser une solution qui marche ? :)

        (Solution que j'utilise aussi, sans soucis particulier)

        D'ailleurs, tu disais que tu voulais pas filer à ton réseau, toutes tes requetes DNS et que tu preferais les filer à 8.8.8.8. C'est assez curieux comme choix (avoir plus confiance en google pour la vie privée qu'en son admin local...). Si tu montes un resolver local, tu bypasses les 2.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.