|
@@ -0,0 +1,95 @@ |
|
|
|
|
|
#!/usr/bin/env python |
|
|
|
|
|
# |
|
|
|
|
|
# Copyright 2019 John-Mark Gurney. |
|
|
|
|
|
# All rights reserved. |
|
|
|
|
|
# |
|
|
|
|
|
# Redistribution and use in source and binary forms, with or without |
|
|
|
|
|
# modification, are permitted provided that the following conditions |
|
|
|
|
|
# are met: |
|
|
|
|
|
# 1. Redistributions of source code must retain the above copyright |
|
|
|
|
|
# notice, this list of conditions and the following disclaimer. |
|
|
|
|
|
# 2. Redistributions in binary form must reproduce the above copyright |
|
|
|
|
|
# notice, this list of conditions and the following disclaimer in the |
|
|
|
|
|
# documentation and/or other materials provided with the distribution. |
|
|
|
|
|
# |
|
|
|
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
|
|
|
|
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
|
|
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
|
|
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
|
|
|
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
|
|
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
|
|
|
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
|
|
|
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
|
|
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
|
|
|
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
|
|
|
|
# SUCH DAMAGE. |
|
|
|
|
|
# |
|
|
|
|
|
|
|
|
|
|
|
__author__ = 'John-Mark Gurney' |
|
|
|
|
|
__copyright__ = 'Copyright 2019 John-Mark Gurney. All rights reserved.' |
|
|
|
|
|
__license__ = '2-clause BSD license' |
|
|
|
|
|
__version__ = '0.1.0.dev' |
|
|
|
|
|
|
|
|
|
|
|
import asyncio |
|
|
|
|
|
import unittest |
|
|
|
|
|
|
|
|
|
|
|
from dnslib import DNSRecord, RR, QTYPE, A, digparser |
|
|
|
|
|
from ntunnel import async_test, parsesockstr |
|
|
|
|
|
|
|
|
|
|
|
class DNSProc(asyncio.DatagramProtocol): |
|
|
|
|
|
def connection_made(self, transport): |
|
|
|
|
|
print('cm') |
|
|
|
|
|
self.transport = transport |
|
|
|
|
|
|
|
|
|
|
|
def datagram_received(self, data, addr): |
|
|
|
|
|
print('dr') |
|
|
|
|
|
pkt = DNSRecord.parse(data) |
|
|
|
|
|
print(repr((pkt, addr))) |
|
|
|
|
|
|
|
|
|
|
|
d = pkt.reply() |
|
|
|
|
|
d.add_answer(RR("xxx.abc.com",QTYPE.A,rdata=A("1.2.3.4"))) |
|
|
|
|
|
data = d.pack() |
|
|
|
|
|
self.transport.sendto(data, addr) |
|
|
|
|
|
|
|
|
|
|
|
async def dnsprocessor(sockstr): |
|
|
|
|
|
proto, args = parsesockstr(sockstr) |
|
|
|
|
|
|
|
|
|
|
|
if proto == 'udp': |
|
|
|
|
|
loop = asyncio.get_event_loop() |
|
|
|
|
|
print('pre-cde') |
|
|
|
|
|
trans, protocol = await loop.create_datagram_endpoint(DNSProc, |
|
|
|
|
|
local_addr=(args.get('host', '127.0.0.1'), args['port'])) |
|
|
|
|
|
print('post-cde', repr((trans, protocol)), trans is protocol.transport) |
|
|
|
|
|
else: |
|
|
|
|
|
raise ValueError('unknown protocol: %s' % repr(proto)) |
|
|
|
|
|
|
|
|
|
|
|
class Tests(unittest.TestCase): |
|
|
|
|
|
@async_test |
|
|
|
|
|
async def test_processdnsfailures(self): |
|
|
|
|
|
port = 5 |
|
|
|
|
|
with self.assertRaises(ValueError): |
|
|
|
|
|
dnsproc = await dnsprocessor( |
|
|
|
|
|
'tcp:host=127.0.0.1,port=%d' % port) |
|
|
|
|
|
print('post-dns') |
|
|
|
|
|
|
|
|
|
|
|
@async_test |
|
|
|
|
|
async def test_processdns(self): |
|
|
|
|
|
# start the dns processor |
|
|
|
|
|
port = 38394 |
|
|
|
|
|
dnsproc = await dnsprocessor( |
|
|
|
|
|
'udp:host=127.0.0.1,port=%d' % port) |
|
|
|
|
|
|
|
|
|
|
|
# submit a query to it |
|
|
|
|
|
digproc = await asyncio.create_subprocess_exec('dig', |
|
|
|
|
|
'@127.0.0.1', '-p', str(port), '+dnssec', '+time=1', |
|
|
|
|
|
'www.funkthat.com.', |
|
|
|
|
|
stdout=asyncio.subprocess.PIPE) |
|
|
|
|
|
|
|
|
|
|
|
# make sure it exits successfully |
|
|
|
|
|
self.assertEqual(await digproc.wait(), 0) |
|
|
|
|
|
|
|
|
|
|
|
stdout, stderr = await digproc.communicate() |
|
|
|
|
|
|
|
|
|
|
|
rep = list(digparser.DigParser(stdout)) |
|
|
|
|
|
self.assertEqual(len(rep), 1) |
|
|
|
|
|
print('x', repr(list(rep))) |