33# version
44__version__ = '1.0.1.1'
55
6- import socket
7- import time
8- import signal
96import sys
107import os
118import yaml
1815from twisted .application import service , internet
1916from twisted .names import dns , server , client , cache , common , resolve
2017from twisted .internet import reactor
18+ from multiprocessing import cpu_count , Process
2119from . import dnsserver , ippool , monitor
2220
2321
@@ -32,74 +30,51 @@ def loadconfig(path):
3230 return yaml .load (f , Loader = yaml .FullLoader )
3331
3432
35- def get_local_ip ():
36- import sys
37- import socket
38- import fcntl
39- import array
40- import struct
41- is_64bits = sys .maxsize > 2 ** 32
42- struct_size = 40 if is_64bits else 32
43- s = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
44- max_possible = 8 # initial value
45- while True :
46- bytes = max_possible * struct_size
47- names = array .array ('B' , b'\0 ' * bytes )
48- outbytes = struct .unpack ('iL' , fcntl .ioctl (
49- s .fileno (),
50- 0x8912 , # SIOCGIFCONF
51- struct .pack ('iL' , bytes , names .buffer_info ()[0 ])
52- ))[0 ]
53- if outbytes == bytes :
54- max_possible *= 2
55- else :
56- break
57- namestr = names .tostring ()
58- return [(namestr [i :i + 16 ].split (b'\0 ' , 1 )[0 ],
59- socket .inet_ntoa (namestr [i + 20 :i + 24 ]))
60- for i in range (0 , outbytes , struct_size )]
61-
62-
6333def prepare_run (run_env ):
64- # load main config
34+ # load main config
6535 logger .info ('start to load %s ......' % run_env ['conf' ])
6636 conf = loadconfig (os .path .join (run_env ['conf' ], 'sdns.yaml' ))
67-
6837 logger .info ('start to load A,SOA,NS record ......' )
69- Amapping = loadconfig (os .path .join (run_env ['conf' ], 'a.yaml' ))
70- NSmapping = loadconfig (os .path .join (run_env ['conf' ], 'ns.yaml' ))
71- SOAmapping = loadconfig (os .path .join (run_env ['conf' ], 'soa.yaml' ))
38+ a_mapping = loadconfig (os .path .join (run_env ['conf' ], 'a.yaml' ))
39+ ns_mapping = loadconfig (os .path .join (run_env ['conf' ], 'ns.yaml' ))
40+ soa_mapping = loadconfig (os .path .join (run_env ['conf' ], 'soa.yaml' ))
7241
7342 # start monitor
7443 monitor_config = loadconfig (os .path .join (run_env ['conf' ], 'monitor.yaml' ))
75- monitor_mapping = monitor .MonitorMapping (monitor_config , Amapping )
44+ monitor_mapping = monitor .MonitorMapping (monitor_config , a_mapping )
7645 # load dns record config file
7746 logger .info ('start to init IP pool ......' )
78- Finder = ippool .IPPool (
47+ finder = ippool .IPPool (
7948 os .path .join (run_env ['conf' ], 'ip.csv' ),
8049 os .path .join (run_env ['conf' ], 'a.yaml' ),
8150 monitor_mapping )
8251
83- run_env ['finder' ] = Finder
84-
85- listen_tcp_port = conf ['listen' ]['tcp' ]
86- listen_udp_port = conf ['listen' ]['udp' ]
52+ run_env ['finder' ] = finder
8753
8854 # set up a resolver that uses the mapping or a secondary nameserver
8955 dnsforward = []
90- for i in conf ['dnsforward_ip' ]:
91- dnsforward .append ((i , conf ['dnsforward_port' ]))
56+ for i in conf ['dnsforward' ]:
57+ dnsforward_ip , dnsforward_port = i .split (":" )
58+ dnsforward .append ((dnsforward_ip , int (dnsforward_port )))
9259
93- for ifc , ip in get_local_ip ():
94- # create the protocols
95- SmartResolver = dnsserver .MapResolver (
96- Finder , Amapping , NSmapping , SOAmapping , servers = dnsforward )
60+ # create the protocols
61+ for listen_tcp in conf ['listen' ]['tcp' ]:
62+ listen_tcp_ip , listen_tcp_port = listen_tcp .split (":" )
9763 f = dnsserver .SmartDNSFactory (
98- caches = [cache .CacheResolver ()], clients = [SmartResolver ])
99- p = dns .DNSDatagramProtocol (f )
100- f .noisy = p .noisy = False
101- run_env ['tcp' ].append ([listen_tcp_port , f , ip ])
102- run_env ['udp' ].append ([listen_udp_port , p , ip ])
64+ caches = [cache .CacheResolver ()], clients = [
65+ dnsserver .MapResolver (
66+ finder , a_mapping , ns_mapping , soa_mapping , servers = dnsforward )])
67+ f .noisy = False
68+ run_env ['tcp' ].append ([int (listen_tcp_port ), f , listen_tcp_ip ])
69+ for listen_udp in conf ['listen' ]['tcp' ]:
70+ listen_udp_ip , listen_udp_port = listen_udp .split (":" )
71+ p = dns .DNSDatagramProtocol (dnsserver .SmartDNSFactory (
72+ caches = [cache .CacheResolver ()], clients = [
73+ dnsserver .MapResolver (
74+ finder , a_mapping , ns_mapping , soa_mapping , servers = dnsforward )]))
75+ p .noisy = False
76+ run_env ['udp' ].append ([int (listen_udp_port ), p , listen_udp_ip ])
77+ return conf
10378
10479
10580def main ():
@@ -109,10 +84,16 @@ def main():
10984 run_env ['conf' ] = sys .argv [1 ]
11085 else :
11186 run_env ['conf' ] = '/etc/smartdns'
112-
113- prepare_run (run_env )
87+
88+ conf = prepare_run (run_env )
11489 for e in run_env ['tcp' ]:
11590 reactor .listenTCP (e [0 ], e [1 ], interface = e [2 ])
11691 for e in run_env ['udp' ]:
11792 reactor .listenUDP (e [0 ], e [1 ], interface = e [2 ])
118- reactor .run ()
93+ workers = []
94+ for _ in range (conf .get ("workers" , cpu_count () * 2 )):
95+ process = Process (target = reactor .run )
96+ process .daemon = True
97+ process .start ()
98+ workers .append (process )
99+ [worker .join () for worker in workers ]
0 commit comments