Add support for option 'prefer-ipv6'

This commit is contained in:
htc 2016-02-20 10:37:25 +08:00
parent b9766ce5df
commit b276d52735
4 changed files with 28 additions and 16 deletions

3
debian/config.json vendored
View file

@ -7,5 +7,6 @@
"timeout":300, "timeout":300,
"method":"aes-256-cfb", "method":"aes-256-cfb",
"fast_open": false, "fast_open": false,
"workers": 1 "workers": 1,
"prefer_ipv6": false
} }

View file

@ -242,13 +242,13 @@ class DNSResponse(object):
return '%s: %s' % (self.hostname, str(self.answers)) return '%s: %s' % (self.hostname, str(self.answers))
STATUS_IPV4 = 0 STATUS_FIRST = 0
STATUS_IPV6 = 1 STATUS_SECOND = 1
class DNSResolver(object): class DNSResolver(object):
def __init__(self, server_list=None): def __init__(self, server_list=None, prefer_ipv6=False):
self._loop = None self._loop = None
self._hosts = {} self._hosts = {}
self._hostname_status = {} self._hostname_status = {}
@ -261,6 +261,10 @@ class DNSResolver(object):
self._parse_resolv() self._parse_resolv()
else: else:
self._servers = server_list self._servers = server_list
if prefer_ipv6:
self._QTYPES = [QTYPE_AAAA, QTYPE_A]
else:
self._QTYPES = [QTYPE_A, QTYPE_AAAA]
self._parse_hosts() self._parse_hosts()
# TODO monitor hosts change and reload hosts # TODO monitor hosts change and reload hosts
# TODO parse /etc/gai.conf and follow its rules # TODO parse /etc/gai.conf and follow its rules
@ -341,17 +345,18 @@ class DNSResolver(object):
answer[2] == QCLASS_IN: answer[2] == QCLASS_IN:
ip = answer[0] ip = answer[0]
break break
if not ip and self._hostname_status.get(hostname, STATUS_IPV6) \ if not ip and self._hostname_status.get(hostname, STATUS_SECOND) \
== STATUS_IPV4: == STATUS_FIRST:
self._hostname_status[hostname] = STATUS_IPV6 self._hostname_status[hostname] = STATUS_SECOND
self._send_req(hostname, QTYPE_AAAA) self._send_req(hostname, self._QTYPES[1])
else: else:
if ip: if ip:
self._cache[hostname] = ip self._cache[hostname] = ip
self._call_callback(hostname, ip) self._call_callback(hostname, ip)
elif self._hostname_status.get(hostname, None) == STATUS_IPV6: elif self._hostname_status.get(hostname, None) \
== STATUS_SECOND:
for question in response.questions: for question in response.questions:
if question[1] == QTYPE_AAAA: if question[1] == self._QTYPES[1]:
self._call_callback(hostname, None) self._call_callback(hostname, None)
break break
@ -417,14 +422,14 @@ class DNSResolver(object):
return return
arr = self._hostname_to_cb.get(hostname, None) arr = self._hostname_to_cb.get(hostname, None)
if not arr: if not arr:
self._hostname_status[hostname] = STATUS_IPV4 self._hostname_status[hostname] = STATUS_FIRST
self._send_req(hostname, QTYPE_A) self._send_req(hostname, self._QTYPES[0])
self._hostname_to_cb[hostname] = [callback] self._hostname_to_cb[hostname] = [callback]
self._cb_to_hostname[callback] = hostname self._cb_to_hostname[callback] = hostname
else: else:
arr.append(callback) arr.append(callback)
# TODO send again only if waited too long # TODO send again only if waited too long
self._send_req(hostname, QTYPE_A) self._send_req(hostname, self._QTYPES[0])
def close(self): def close(self):
if self._sock: if self._sock:

View file

@ -58,9 +58,10 @@ def main():
udp_servers = [] udp_servers = []
if 'dns_server' in config: # allow override settings in resolv.conf if 'dns_server' in config: # allow override settings in resolv.conf
dns_resolver = asyncdns.DNSResolver(config['dns_server']) dns_resolver = asyncdns.DNSResolver(config['dns_server'],
config['prefer_ipv6'])
else: else:
dns_resolver = asyncdns.DNSResolver() dns_resolver = asyncdns.DNSResolver(prefer_ipv6=config['prefer_ipv6'])
port_password = config['port_password'] port_password = config['port_password']
del config['port_password'] del config['port_password']

View file

@ -137,7 +137,8 @@ def get_config(is_local):
else: else:
shortopts = 'hd:s:p:k:m:c:t:vqa' shortopts = 'hd:s:p:k:m:c:t:vqa'
longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=', longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=',
'forbidden-ip=', 'user=', 'manager-address=', 'version'] 'forbidden-ip=', 'user=', 'manager-address=', 'version',
'prefer-ipv6']
try: try:
config_path = find_config() config_path = find_config()
optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts) optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
@ -207,6 +208,8 @@ def get_config(is_local):
elif key == '-q': elif key == '-q':
v_count -= 1 v_count -= 1
config['verbose'] = v_count config['verbose'] = v_count
elif key == '--prefer-ipv6':
config['prefer_ipv6'] = True
except getopt.GetoptError as e: except getopt.GetoptError as e:
print(e, file=sys.stderr) print(e, file=sys.stderr)
print_help(is_local) print_help(is_local)
@ -229,6 +232,7 @@ def get_config(is_local):
config['local_address'] = to_str(config.get('local_address', '127.0.0.1')) config['local_address'] = to_str(config.get('local_address', '127.0.0.1'))
config['local_port'] = config.get('local_port', 1080) config['local_port'] = config.get('local_port', 1080)
config['one_time_auth'] = config.get('one_time_auth', False) config['one_time_auth'] = config.get('one_time_auth', False)
config['prefer_ipv6'] = config.get('prefer_ipv6', False)
if is_local: if is_local:
if config.get('server', None) is None: if config.get('server', None) is None:
logging.error('server addr not specified') logging.error('server addr not specified')
@ -324,6 +328,7 @@ Proxy options:
--workers WORKERS number of workers, available on Unix/Linux --workers WORKERS number of workers, available on Unix/Linux
--forbidden-ip IPLIST comma seperated IP list forbidden to connect --forbidden-ip IPLIST comma seperated IP list forbidden to connect
--manager-address ADDR optional server manager UDP address, see wiki --manager-address ADDR optional server manager UDP address, see wiki
--prefer-ipv6 resolve ipv6 address first
General options: General options:
-h, --help show this help message and exit -h, --help show this help message and exit