[PYTHON] Erstellen Sie mit Twisted Ihren eigenen DNS-Server

Einführung

Haben Sie jemals gedacht "Ich möchte meinen eigenen DNS-Server erstellen"? Es geht nicht um "apt-get install bind9", sondern darum, ein DNS-Serverprogramm zu erstellen.

"Ich brauche das nicht, ich muss meine eigene Zugriff auf unnötige Ressourcen auf Webseiten blockieren und [Arbeitsproduktivität" erstellen. [Http://engineer.typemag.jp/article/fukuyuki41] Es ist ungefähr die Zeit, in der Sie nicht auf die Site zugreifen können, auf der Sie sie ablegen, oder? "

Wenn Sie jedoch die DNS-Antwort mit Python frei steuern könnten, könnten Sie etwas Interessanteres tun.

Erstellen Sie einen DNS-Server mit Twisted

Plötzlich googelte ich, wie ich mit Python meinen eigenen DNS-Server erstellen kann.

In dem Artikel in Qiita finden Sie eine Methode zum Erstellen eines DNS-Servers mit Twisted. http://qiita.com/futoase/items/174883d7fa8d2dd4240a

Nach Durchsicht der neuesten Dokumentation stellte ich fest, dass es einfacher als erwartet war, einen benutzerdefinierten DNS-Server zu erstellen, der Antworten dynamisch zusammenstellt.

http://twistedmatrix.com/documents/current/names/howto/custom-server.html

Das ist fantastisch! Deine Träume werden sich verbreiten!

Wofür kann es verwendet werden

Da der Antwortinhalt mit Python-Code zusammengestellt werden kann, scheinen verschiedene interessante Dinge getan werden zu können.

Beispielsweise hat Retty seinen eigenen DNS-Server erstellt, um den Wechsel zu einer Testumgebung zu vereinfachen. Durch die Kombination mit den WLAN-Einstellungen wird dieselbe Anforderung wie bei der Produktion an die Testumgebung gesendet, indem lediglich eine Verbindung zu einem bestimmten Zugriffspunkt hergestellt wird.

Im Unternehmensnetzwerk wird ein DNS-Server für die von Twisted erstellte Testumgebung ausgeführt. Wenn Sie den Hostnamen der Produktionsumgebung abfragen, wird die IP-Adresse des Ergebnisses der Abfrage des Hostnamens der Testumgebung zurückgegeben. Durch die Verwendung eines WLANs, das VLANs und mehrere ESSIDs unterstützt, fragen Clients, die mit einem bestimmten Zugriffspunktnamen verbunden sind, automatisch den DNS-Server nach der Testumgebung ab. Selbst wenn sich die Anforderung auf dieselbe URL wie die Produktionsumgebung bezieht und Sie sich an den DNS-Server für die Testumgebung wenden, werden Sie zur Testumgebung weitergeleitet. Das ist DNS Spoo ... Oh, es sieht so aus, als wäre jemand gekommen.

Darüber hinaus kann möglicherweise eine Verbindung mit anderen Diensten wie AWS hergestellt werden, um einen DNS-Server zu erstellen, der je nach Konfiguration und Status des Dienstes eine entsprechende Antwort zurückgibt.

Lass es uns sofort tun

Erstellen wir also einen DNS-Server, der mit der AWS-API funktioniert.

Wenn Sie nach der ID einer EC2-Instanz wie "i-abcd1234.ec2.local" fragen, versuchen Sie, die der Instanz zugewiesene IP-Adresse zurückzugeben.

Paketvorbereitung

Nachdem Sie Python 2 und pip verfügbar gemacht haben, setzen Sie Twisted ein. Ab Twisted-15.5.0 schien es nicht zu funktionieren, da einige der DNS-Server-bezogenen Codes Python 3 nicht unterstützten.

[user@localhost]$ pip2 install twisted

In diesem Beispiel greifen wir auf AWS zu. Installieren Sie daher Boto 3 und die AWS-CLI und legen Sie die Anmeldeinformationen fest.

[user@localhost]$ pip2 install boto3 awscli
[user@localhost]$ aws configure

Es wurde bestätigt, dass die folgenden Beispiele mit Python-2.7.10, Twisted-15.5.0 und boto3-1.2.3 funktionieren.

Machen Sie einen Resolver

Laut Twisted Documents (http://twistedmatrix.com/documents/current/names/howto/custom-server.html#a-server-which-computes-responses-dynamically) dynamische Namensauflösung Es scheint, dass der schnellste Weg, dies zu erreichen, darin besteht, einen benutzerdefinierten Resolver zu erstellen und zu registrieren. Twisted übernimmt die Protokollverarbeitung, ist also sehr einfach.

Daher wird als Antwort auf eine Abfrage an die Domäne "ec2.local" das erste Label als EC2-Instanz-ID betrachtet und ein Resolver erstellt, der mit dieser IP-Adresse antwortet.

Sie können dies tun, indem Sie "twisted.names.common.ResolverBase" erben und "lookupAddress ()" überschreiben.

resolver.py


# coding=utf-8

import boto3
import botocore
from twisted.internet import defer
from twisted.logger import Logger
from twisted.names import common, dns, error

log = Logger()

ec2 = boto3.resource('ec2')


def find_ec2_address(instance_id):
    if instance_id:
        try:
            instance = ec2.Instance(instance_id)
            #Instanz, wenn Sie eine öffentliche IP-Adresse benötigen.public_ip_Kann von der Adresse erhalten werden.
            address = instance.private_ip_address
            log.debug('Found {instance!r} address={address}', instance=instance, address=address)
            return address
        except botocore.exceptions.ClientError:
            log.failure('Failed to find {instance_id}', instance_id=instance_id)


class EC2ResourceResolver(common.ResolverBase):
    #Domäne, die dynamisch umbenannt werden soll
    _suffix = '.ec2.local'
    _ttl = 30

    def _should_resolve(self, name):
        return name.lower().endswith(self._suffix)

    def lookupAddress(self, name, timeout=None):
        log.debug('Looking up address {name}', name=name)

        if self._should_resolve(name):
            #Betrachten Sie das erste Label als EC2-Instanz-ID.
            instance_id = name.split('.', 1)[0]
            address = find_ec2_address(instance_id)

            answer, authority, additional = common.EMPTY_RESULT
            if address:
                answer = [
                    dns.RRHeader(
                            name=name,
                            ttl=self._ttl,
                            payload=dns.Record_A(address=b'%s' % (address,), ttl=self._ttl),
                            auth=True)
                ]

            return defer.succeed((answer, authority, additional))

        # error.DomainError()Wenn Sie mit fehlschlagen, wird der nächste Resolver kontaktiert.
        return defer.fail(error.DomainError(name))

    lookupAllRecords = lookupAddress

    #Um wiederholte Abfragen an andere Resolver zu vermeiden
    #Andere Abfragetypen werden ebenfalls als leere Ergebnisse in der Zieldomäne aufgelöst.
    def _lookup(self, name, cls, type, timeout):
        if self._should_resolve(name):
            return defer.succeed(common.EMPTY_RESULT)
        return defer.fail(error.DomainError(name))

Hoppla, Twisted ist ein asynchrones Programmierframework, das jedoch durch Aufrufen von boto ... Ich mache mir Sorgen, dass es sich nicht gut benimmt, aber diesmal ist es eine Probe, also lasst uns weitermachen.

Machen Sie den Serverkörper

Erstellen Sie als Nächstes einen DNS-Cache-Server, der diesen Resolver zur Namensauflösung verwendet.

ec2-dns-server.py


#!/usr/bin/env python2
# coding=utf-8

import sys

from twisted.internet import reactor
from twisted.names import client, dns, server
from twisted.python import log

from resolver import EC2ResourceResolver


def main():
    log.startLogging(sys.stderr)

    factory = server.DNSServerFactory(
        clients=[
            EC2ResourceResolver(),
            client.Resolver(servers=[('8.8.8.8', 53), ('8.8.4.4', 53)])
        ]
    )
    protocol = dns.DNSDatagramProtocol(factory)

    reactor.listenUDP(10053, protocol)
    reactor.listenTCP(10053, factory)

    reactor.run()


if __name__ == '__main__':
    raise SystemExit(main())

In diesem Beispiel wird die DNS-Abfrage an Port 10053 abgehört und die nicht aufgelöste Abfrage an Google Public DNS weitergeleitet (8.8.8.8, 8.8.4.4).

Wenn Sie dieses Relay-Ziel von / etc / resolv.conf erhalten möchten

            client.Resolver(servers=[('8.8.8.8', 53), ('8.8.4.4', 53)])

Teil von

            client.Resolver(resolv='/etc/resolv.conf')

Es ist in Ordnung, wenn Sie es umschreiben.

Versuche dich zu bewegen

Lass es uns bewegen.

[user@localhost]$ python2 ec2-dns-server.py
2015-12-24 20:35:49+0900 [-] Log opened.
2015-12-24 20:35:49+0900 [-] DNSDatagramProtocol starting on 10053
2015-12-24 20:35:49+0900 [-] Starting protocol <twisted.names.dns.DNSDatagramProtocol object at 0x6fffe4bccd0>
2015-12-24 20:35:49+0900 [-] DNSServerFactory starting on 10053
2015-12-24 20:35:49+0900 [-] Starting factory <twisted.names.server.DNSServerFactory instance at 0x6fffe4c61b8>

Ich werde es mit dig testen, um zu sehen, ob es richtig funktioniert

[user@localhost]$ dig -p 10053 @localhost i-abcd1234.ec2.local +norecurse +short
10.11.25.25

Wenn die Adresse der EC2-Instanz wie folgt zurückgegeben wird, funktioniert sie ordnungsgemäß.

Die Möglichkeiten sind endlos

DNS kann ein erschwinglicher Dienst sein, der als Diensterkennungsfenster verwendet werden kann, da AWS-Endpunkte verschiedene DNS-Namen bereitstellen (xxxx.amazonaws.com).

[RFC 2782](https: // www.) Mit Active Directory können Sie den Speicherort eines Dienstes anhand eines abstrakten Namens mithilfe von DNS ermitteln. Aliase mit SRV-Datensatz (ietf.org/rfc/rfc2782.txt) oder genauer CNAME wie in RFC 2219 Es scheint einen Weg zu geben. Die Methode zum Zuweisen eines Alias mit CNAME hat den Vorteil, dass sie sehr vielseitig ist, und zwar in AWS [RDS für Oracle Database Multi-AZ](http://aws.typepad.com/aws_japan/2012/05/multi-az- option-for-amazon-rds-for-oracle-database.html) und Automatische Erkennung des ElastiCache-Knotens ) Scheint verwendet zu werden.

Selbst wenn Sie versuchen, den Speicherort des Dienstes mit CNAME zu abstrahieren, gibt es mit CNAME verschiedene Einschränkungen. Beispielsweise bleibt in einer Konfiguration, in der sich die Umgebung durch Anheben oder Absenken der Instanz dynamisch ändert, das Problem der Verwaltung und Verwaltung der Korrespondenz mit dem realen Host bestehen.

Daher ["Begriffe aus Einstellungen"](https://ja.wikipedia.org/wiki/%E8%A8%AD%E5%AE%9A%E3%82%88%E3%82%8A%E8%A6% 8F% E7% B4% 84) Wenn Sie einer Ressource wie einer EC2-Instanz einen Namen geben, der über das Programm einfach zu handhaben ist, können Sie einen DNS-Dienst erstellen, der mithilfe der Metadaten der Ressource dynamisch reagiert. Korrekt. Schließen Sie Slaves mit Replikationsverzögerungen wie MySQL aus und verursachen Sie ein Failover (das kann ich mit HAProxy tun) Ihre Träume können sich ausbreiten.

Recommended Posts

Erstellen Sie mit Twisted Ihren eigenen DNS-Server
Erstellen Sie mit SQLAlchemy Ihren eigenen zusammengesetzten Wert
Memo zum Erstellen einer eigenen Box mit Peppers Python
Erstellen Sie Ihre eigene Django-Middleware
Reinforcement Learning 23 Erstellen und verwenden Sie Ihr eigenes Modul mit Colaboratory
Löse dein eigenes Labyrinth mit Q-Lernen
Erstellen Sie Ihren eigenen Namensauflösungsdienst
[Django] Erstellen Sie Ihre eigene 403, 404, 500-Fehlerseite
Trainiere UGATIT mit deinem eigenen Datensatz
Löse dein eigenes Labyrinth mit DQN
Ihr eigener Twitter-Client mit Django
Erstellen Sie Ihre eigenen Linux-Befehle in Python
Erstellen Sie einfach einen DNS-Server mit Twisted
[Stärkung des Lernens] DQN mit Ihrer eigenen Bibliothek
Erstellen Sie mit python3 eine Wortwolke aus Ihrem Tweet
[LLDB] Erstellen Sie Ihren eigenen Befehl mit Python
So importieren Sie Ihr eigenes Modul mit jupyter
Erstellen der ersten App mit Django Startprojekt
Veröffentlichen Sie Ihre eigene Python-Bibliothek auf Homebrew
Erstellen Sie mit Python + OpenCV Ihre eigene virtuelle Kamera und wenden Sie Originaleffekte an
Versuchen Sie, Ihr eigenes AWS-SDK mit bash zu erstellen
Erstellen Sie schnell Ihr eigenes Modul mit setuptools (Python)
Trainieren Sie Stanford NER Tagger mit Ihren eigenen Daten
[Maschinelles Lernen] Erstellen Sie ein Modell für maschinelles Lernen, indem Sie Transferlernen mit Ihrem eigenen Datensatz durchführen
Erstellen Sie ein Rad Ihres eigenen OpenCV-Moduls
Erstellen Sie in Tornado einen HTTP-Server (Hello World)
Erstellen Sie schnell einen API-Server mit Python + Falcon
Erstelle deinen eigenen Musik-Player mit Bottle0.13 + jPlayer2.5!
Schritte zum Installieren Ihrer eigenen Bibliothek mit pip
Ablauf beim Erstellen eines eigenen Pakets mit setup.py mit Python
Rufen Sie mit Go mit cgo Ihre eigene C-Sprachbibliothek auf
Erstellen Sie Ihre eigenen Big Data in Python zur Validierung
Erstellen Sie Ihr eigenes Random Dot Stereogram (RDS) in Python.
Schreiben Sie Ihre eigene Aktivierungsfunktion mit Pytorch (hartes Sigmoid)
Rufen wir Ihre eigene C ++ - Bibliothek mit Python auf (Einstellungen)
Definieren Sie Ihre eigene Distanzfunktion mit k-Mitteln des Scikit-Lernens
[Blender x Python] Erstellen Sie Ihre eigene Funktion und Zusammenfassung
Erstellen Sie einen Home Music Server mit Centos8 + Universal Media Server
Erstellen Sie mit Quarry einen gefälschten Minecraft-Server in Python
Erstelle Spiele mit Pygame
Proxyserver mit Docker
Erstellen Sie einen Filter mit scipy
DNS-Server in Python ....
Lokaler Server mit Python
Bis Sie Ihre eigene Python-Bibliothek mit pip installieren können
Versuchen Sie, Ihre eigenen Objekte mit Prioritätswarteschlangen in Python zu sortieren
Führen Sie die Intelligenz Ihrer eigenen Python-Bibliothek mit VScode aus.
Richten Sie Ihren eigenen Webserver in Ihrem Pepper-App-Projekt ein
Lernen Sie "x86-Architektur mit Ihrem eigenen Emulator" mit Manjaro (Linux)