Skip to content

Commit dad5318

Browse files
committed
fix: fix no edns bug
1 parent 9251044 commit dad5318

5 files changed

Lines changed: 144 additions & 85 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ develop-eggs
2121
*.pyc
2222
*.pid
2323
.venv
24+
.idea
25+
.vscode

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
name='smartdns',
2727
description='An Intelligent DNS Similar to DNSPod',
28-
version='3.3.3',
28+
version='3.3.4',
2929
author='duanhongyi',
3030
author_email='duanhyi@gmail.com',
3131
packages=find_packages(),
@@ -38,5 +38,5 @@
3838
license='BSD',
3939
long_description_content_type='text/markdown',
4040
# install
41-
entry_points={'console_scripts': ['sdns=smartdns.sdns:main']}
41+
entry_points={'console_scripts': ['sdns=smartdns.runner:run']}
4242
)

smartdns/runner.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# version
4+
__version__ = '1.0.1.1'
5+
6+
import logging
7+
import os
8+
import sys
9+
import yaml
10+
from multiprocessing import cpu_count, Process
11+
from os.path import isfile
12+
from twisted.internet import reactor
13+
from twisted.names import dns
14+
15+
from . import server, monitor
16+
from .finder import Finder
17+
18+
logger = logging.getLogger(__name__)
19+
20+
21+
def loadconfig(path):
22+
if not isfile(path):
23+
print("[FATAL] can't find config file %s !" % path)
24+
exit(1)
25+
with open(path, 'r') as f:
26+
return yaml.load(f, Loader=yaml.FullLoader)
27+
28+
29+
def prepare_run(run_env):
30+
# load main config
31+
logger.info('start to load %s ......' % run_env['conf'])
32+
conf = loadconfig(os.path.join(run_env['conf'], 'sdns.yaml'))
33+
logger.info('start to load A,SOA,NS record ......')
34+
a_mapping = loadconfig(os.path.join(run_env['conf'], 'a.yaml'))
35+
ns_mapping = loadconfig(os.path.join(run_env['conf'], 'ns.yaml'))
36+
soa_mapping = loadconfig(os.path.join(run_env['conf'], 'soa.yaml'))
37+
38+
# start monitor
39+
monitor_config = loadconfig(os.path.join(run_env['conf'], 'monitor.yaml'))
40+
monitor_mapping = monitor.MonitorMapping(monitor_config, a_mapping)
41+
# load dns record config file
42+
logger.info('start to init IP pool ......')
43+
finder = Finder(
44+
os.path.join(run_env['conf'], 'ip.csv'),
45+
os.path.join(run_env['conf'], 'a.yaml'),
46+
monitor_mapping)
47+
48+
run_env['finder'] = finder
49+
50+
# set up a resolver that uses the mapping or a secondary nameserver
51+
dns_forwards = []
52+
for i in conf['dns_forwards']:
53+
dns_forward_ip, dns_forward_port = i.split(":")
54+
dns_forwards.append((dns_forward_ip, int(dns_forward_port)))
55+
56+
# create the protocols
57+
for listen_tcp in conf['listen']['tcp']:
58+
listen_tcp_ip, listen_tcp_port = listen_tcp.split(":")
59+
f = server.SmartDNSFactory(clients=[
60+
server.MapResolver(
61+
finder, a_mapping, ns_mapping, soa_mapping, servers=dns_forwards)])
62+
f.noisy = False
63+
run_env['tcp'].append([int(listen_tcp_port), f, listen_tcp_ip])
64+
for listen_udp in conf['listen']['tcp']:
65+
listen_udp_ip, listen_udp_port = listen_udp.split(":")
66+
p = dns.DNSDatagramProtocol(server.SmartDNSFactory(clients=[
67+
server.MapResolver(
68+
finder, a_mapping, ns_mapping, soa_mapping, servers=dns_forwards)]))
69+
p.noisy = False
70+
run_env['udp'].append([int(listen_udp_port), p, listen_udp_ip])
71+
return conf
72+
73+
74+
def run():
75+
run_env = {'udp': [], 'tcp': [], 'closed': 0,
76+
'updated': False, 'finder': None}
77+
if len(sys.argv) > 1:
78+
run_env['conf'] = sys.argv[1]
79+
else:
80+
run_env['conf'] = '/etc/smartdns'
81+
82+
conf = prepare_run(run_env)
83+
for e in run_env['tcp']:
84+
reactor.listenTCP(e[0], e[1], interface=e[2])
85+
for e in run_env['udp']:
86+
reactor.listenUDP(e[0], e[1], interface=e[2])
87+
workers = []
88+
for _ in range(conf.get("workers", cpu_count() * 2)):
89+
process = Process(target=reactor.run)
90+
process.daemon = True
91+
process.start()
92+
workers.append(process)
93+
[worker.join() for worker in workers]

smartdns/sdns.py

Lines changed: 42 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,55 @@
1-
# -*- coding: utf-8 -*-
1+
import socket
2+
import struct
3+
from zope.interface import implementer
4+
from twisted.names.dns import str2time, tputil, readPrecisely, IRecord, IEncodable
25

3-
# version
4-
__version__ = '1.0.1.1'
6+
EDNS = 41
57

6-
import logging
7-
import os
8-
import sys
9-
import yaml
10-
from multiprocessing import cpu_count, Process
11-
from os.path import isfile
12-
from twisted.internet import reactor
13-
from twisted.names import dns
8+
@implementer(IEncodable, IRecord)
9+
class Record_EDNS(tputil.FancyEqMixin):
10+
"""
11+
An EDNS
12+
"""
1413

15-
from . import server, monitor
16-
from .finder import Finder
14+
compareAttributes = ('address', 'family', 'opt_code', 'opt_length', 'source_nm', 'scope_nm')
1715

18-
logger = logging.getLogger(__name__)
16+
TYPE = EDNS
17+
address = None
18+
opt_code = None
19+
opt_length = None
20+
family = None
21+
source_nm = None
22+
scope_nm = None
1923

24+
def __init__(self, address='0.0.0.0', ttl=None):
25+
if address is not None:
26+
address = socket.inet_aton(address)
27+
self.address = address
28+
self.ttl = str2time(ttl)
2029

21-
def loadconfig(path):
22-
if not isfile(path):
23-
print("[FATAL] can't find config file %s !" % path)
24-
exit(1)
25-
with open(path, 'r') as f:
26-
return yaml.load(f, Loader=yaml.FullLoader)
2730

31+
def encode(self, strio, compDict = None):
32+
if self.address is not None:
33+
strio.write(struct.pack('!HHHcc', self.opt_code, self.opt_length, self.family, self.source_nm, self.scope_nm))
34+
strio.write(self.address)
2835

29-
def prepare_run(run_env):
30-
# load main config
31-
logger.info('start to load %s ......' % run_env['conf'])
32-
conf = loadconfig(os.path.join(run_env['conf'], 'sdns.yaml'))
33-
logger.info('start to load A,SOA,NS record ......')
34-
a_mapping = loadconfig(os.path.join(run_env['conf'], 'a.yaml'))
35-
ns_mapping = loadconfig(os.path.join(run_env['conf'], 'ns.yaml'))
36-
soa_mapping = loadconfig(os.path.join(run_env['conf'], 'soa.yaml'))
36+
def decode(self, strio, length = None):
37+
if length > 8:
38+
rdata = readPrecisely(strio, 8)
39+
self.opt_code, self.opt_length, self.family, self.source_nm, self.scope_nm = struct.unpack("!HHHcc", rdata)
40+
#hack let scope netmask = source netmask
41+
self.scope_nm = self.source_nm
42+
self.address = readPrecisely(strio, length - 8)
3743

38-
# start monitor
39-
monitor_config = loadconfig(os.path.join(run_env['conf'], 'monitor.yaml'))
40-
monitor_mapping = monitor.MonitorMapping(monitor_config, a_mapping)
41-
# load dns record config file
42-
logger.info('start to init IP pool ......')
43-
finder = Finder(
44-
os.path.join(run_env['conf'], 'ip.csv'),
45-
os.path.join(run_env['conf'], 'a.yaml'),
46-
monitor_mapping)
44+
def __hash__(self):
45+
return hash(self.address)
4746

48-
run_env['finder'] = finder
4947

50-
# set up a resolver that uses the mapping or a secondary nameserver
51-
dns_forwards = []
52-
for i in conf['dns_forwards']:
53-
dns_forward_ip, dns_forward_port = i.split(":")
54-
dns_forwards.append((dns_forward_ip, int(dns_forward_port)))
48+
def __str__(self):
49+
return '<A address=%s ttl=%s>' % (self.address, self.ttl)
50+
__repr__ = __str__
5551

56-
# create the protocols
57-
for listen_tcp in conf['listen']['tcp']:
58-
listen_tcp_ip, listen_tcp_port = listen_tcp.split(":")
59-
f = server.SmartDNSFactory(clients=[
60-
server.MapResolver(
61-
finder, a_mapping, ns_mapping, soa_mapping, servers=dns_forwards)])
62-
f.noisy = False
63-
run_env['tcp'].append([int(listen_tcp_port), f, listen_tcp_ip])
64-
for listen_udp in conf['listen']['tcp']:
65-
listen_udp_ip, listen_udp_port = listen_udp.split(":")
66-
p = dns.DNSDatagramProtocol(server.SmartDNSFactory(clients=[
67-
server.MapResolver(
68-
finder, a_mapping, ns_mapping, soa_mapping, servers=dns_forwards)]))
69-
p.noisy = False
70-
run_env['udp'].append([int(listen_udp_port), p, listen_udp_ip])
71-
return conf
7252

73-
74-
def main():
75-
run_env = {'udp': [], 'tcp': [], 'closed': 0,
76-
'updated': False, 'finder': None}
77-
if len(sys.argv) > 1:
78-
run_env['conf'] = sys.argv[1]
79-
else:
80-
run_env['conf'] = '/etc/smartdns'
81-
82-
conf = prepare_run(run_env)
83-
for e in run_env['tcp']:
84-
reactor.listenTCP(e[0], e[1], interface=e[2])
85-
for e in run_env['udp']:
86-
reactor.listenUDP(e[0], e[1], interface=e[2])
87-
workers = []
88-
for _ in range(conf.get("workers", cpu_count() * 2)):
89-
process = Process(target=reactor.run)
90-
process.daemon = True
91-
process.start()
92-
workers.append(process)
93-
[worker.join() for worker in workers]
53+
def dottedQuad(self):
54+
n = 4 - len(self.address)
55+
return socket.inet_ntoa(self.address + '\x00' * n)

smartdns/server.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from twisted.names import dns, server, client, common, resolve
77
from twisted.python import failure
88

9+
from . import sdns
10+
911
logger = logging.getLogger(__name__)
1012

1113
typeToMethod = {
@@ -81,9 +83,9 @@ def packResult(value):
8183

8284
if edns is not None:
8385
if edns.rdlength > 8:
84-
add.append(dns.RRHeader('', dns.EDNS, 4096, edns.ttl, edns.payload, True))
86+
add.append(dns.RRHeader('', sdns.EDNS, 4096, edns.ttl, edns.payload, True))
8587
else:
86-
add.append(dns.RRHeader('', dns.EDNS, 4096, 0, dns.Record_EDNS(None, 0), True))
88+
add.append(dns.RRHeader('', sdns.EDNS, 4096, 0, sdns.Record_EDNS(None, 0), True))
8789
return [ret, (), add]
8890

8991
result = self.finder.findIP(str(addr[0]), name)
@@ -119,7 +121,7 @@ def packResultSOA(value):
119121
if edns.rdlength > 8:
120122
add.append(dns.RRHeader('', dns.EDNS, 4096, edns.ttl, edns.payload, True))
121123
else:
122-
add.append(dns.RRHeader('', dns.EDNS, 4096, 0, dns.Record_EDNS(None, 0), True))
124+
add.append(dns.RRHeader('', dns.EDNS, 4096, 0, sdns.Record_EDNS(None, 0), True))
123125

124126
return [(dns.RRHeader(name, dns.SOA, dns.IN, value['ttl'],
125127
dns.Record_SOA(value['record'], value['email'], value['serial'], value['refresh'],

0 commit comments

Comments
 (0)