Python DNS 服务器
我正在给我的项目添加一个新功能,这个功能可以让网络管理员把软件安装到网络上。我需要用Python编写一个DNS服务器,这样当请求的地址在我的列表里时,就可以把请求重定向到某个特定的页面。我已经写好了服务器,只是不太确定怎么进行重定向。
谢谢!我在Windows XP上使用Python 2.6。
4 个回答
1
这里有一个用Python写的DNS服务器/代理,对我来说很好用:
2
这里有一个用 circuits 和 dnslib 写的完整递归 DNS 服务器,代码只有 143 行,都是用 Python 写的:
#!/usr/bin/env python
from __future__ import print_function
from uuid import uuid4 as uuid
from dnslib import CLASS, QR, QTYPE
from dnslib import DNSHeader, DNSQuestion, DNSRecord
from circuits.net.events import write
from circuits import Component, Debugger, Event
from circuits.net.sockets import UDPClient, UDPServer
class lookup(Event):
"""lookup Event"""
class query(Event):
"""query Event"""
class response(Event):
"""response Event"""
class DNS(Component):
def read(self, peer, data):
record = DNSRecord.parse(data)
if record.header.qr == QR["QUERY"]:
return self.fire(query(peer, record))
return self.fire(response(peer, record))
class ReturnResponse(Component):
def response(self, peer, response):
return response
class Client(Component):
channel = "client"
def init(self, server, port, channel=channel):
self.server = server
self.port = int(port)
self.transport = UDPClient(0, channel=self.channel).register(self)
self.protocol = DNS(channel=self.channel).register(self)
self.handler = ReturnResponse(channel=self.channel).register(self)
class Resolver(Component):
def init(self, server, port):
self.server = server
self.port = port
def lookup(self, qname, qclass="IN", qtype="A"):
channel = uuid()
client = Client(
self.server,
self.port,
channel=channel
).register(self)
yield self.wait("ready", channel)
self.fire(
write(
(self.server, self.port),
DNSRecord(
q=DNSQuestion(
qname,
qclass=CLASS[qclass],
qtype=QTYPE[qtype]
)
).pack()
)
)
yield (yield self.wait("response", channel))
client.unregister()
yield self.wait("unregistered", channel)
del client
class ProcessQuery(Component):
def query(self, peer, query):
qname = query.q.qname
qtype = QTYPE[query.q.qtype]
qclass = CLASS[query.q.qclass]
response = yield self.call(lookup(qname, qclass=qclass, qtype=qtype))
record = DNSRecord(
DNSHeader(id=query.header.id, qr=1, aa=1, ra=1),
q=query.q,
)
for rr in response.value.rr:
record.add_answer(rr)
yield record.pack()
class Server(Component):
def init(self, bind=("0.0.0.0", 53)):
self.bind = bind
self.transport = UDPServer(self.bind).register(self)
self.protocol = DNS().register(self)
self.handler = ProcessQuery().register(self)
class App(Component):
def init(self, bind=("0.0.0.0", 53), server="8.8.8.8", port=53,
verbose=False):
if verbose:
Debugger().register(self)
self.resolver = Resolver(server, port).register(self)
self.server = Server(bind).register(self)
def main():
App().run()
if __name__ == "__main__":
main()
使用方法:
默认情况下,这个例子会绑定到 0.0.0.0:53
,所以你需要做一些类似于以下的操作:
sudo ./dnsserver.py
如果不想这样,可以修改 bind
参数。
5
这里有一个简单的小例子,可以在这里找到,你可以很容易地把它改造成各种“迷你假DNS服务器”。需要注意的是,这里完全没有涉及“重定向”(这不是DNS的工作方式):请求的是一个域名,而这个请求的结果是一个IP地址。如果你想做的事情和把名字翻译成地址有很大不同,那么也许你需要的并不是真正的DNS服务器…?