Add support for reload endpoint dns

master
Kirigaya Kazuto 2022-03-16 13:22:21 +00:00
parent ac6e411529
commit bb27ff9de4
2 changed files with 67 additions and 1 deletions

View File

@ -100,6 +100,7 @@ class Parser:
self.path_get_gateway = os.path.join(wgop_basepath, 'tools/get-gateway.py')
self.path_get_ip = os.path.join(wgop_basepath, 'tools/get-ip.py')
self.path_get_lan_ip = os.path.join(wgop_basepath, 'tools/get-lan-ip.py')
self.path_reload_dns = os.path.join(wgop_basepath, 'tools/reload-dns.py')
self.path_bin_dir = os.path.join(wgop_basepath, 'bin')
self.path_app_dir = os.path.join(wgop_basepath, 'app')
@ -127,6 +128,8 @@ class Parser:
self.flag_is_route_lookup = False
self.flag_container_must_host = False
self.flag_require_registry = False
self.flag_enable_dns_reload = False
self.flag_require_systemd_clean = False
# vars
self.wg_name = '%i'
@ -607,6 +610,8 @@ class Parser:
elif line.startswith('#iptables-gateway'):
self.result_postup.append('iptables -t nat -A POSTROUTING -o {} -j MASQUERADE'.format(self.wg_name))
self.result_postdown.append('iptables -t nat -D POSTROUTING -o {} -j MASQUERADE'.format(self.wg_name))
elif line.startswith('#enable-dns-reload'):
self.flag_enable_dns_reload = True
elif line.startswith('#route-to'):
self.flag_is_route_forward = True
@ -846,6 +851,7 @@ class Parser:
for this_peer_idx, this_peer_lines in enumerate(self.input_peer):
current_pubkey = ''
current_allowed = ''
current_endpoint = ''
if self.flag_is_route_lookup:
current_lookup = self.lookup_table
else:
@ -856,7 +862,9 @@ class Parser:
if line.startswith('PublicKey'):
current_pubkey = '='.join(line.split('=')[1:]).strip()
if line.startswith('AllowedIPs'):
current_allowed = line.split('=')[1].strip().split(',')
current_allowed = line.split('=')[1].strip().split(',')
if line.startswith('Endpoint'):
current_endpoint = line.split('=')[1].strip().split(',')
self.result_peers.append('[Peer]')
@ -866,6 +874,8 @@ class Parser:
continue
if line.startswith('#use-tunnel'):
current_endpoint = ''
parts = line.split(' ')[1:]
tunnel_name = parts[0]
@ -899,6 +909,12 @@ class Parser:
else:
errprint('[WARN] comment or unknown hint: {}'.format(line))
if self.flag_enable_dns_reload and current_endpoint:
task_uuid = str(uuid.uuid4())
self.result_postup.append('systemd-run -u wg-ops-task-{}-dnsreload-{} --timer-property AccuracySec=10 --on-calendar *:*:0/30 /usr/bin/python3 {} {} {} {}'.format(
self.wg_name, task_uuid, self.path_reload_dns, self.wg_name, current_pubkey, current_endpoint))
self.flag_require_systemd_clean = True
if self.flag_is_route_forward and this_peer_idx == 0:
self.result_postup.insert(0, 'wg set {} peer {} allowed-ips 0.0.0.0/0'.format(self.wg_name, current_pubkey))
@ -907,6 +923,9 @@ class Parser:
self.result_postup.append('ip rule add from {} lookup {}'.format(ip_cidr, current_lookup))
self.result_postdown.append('ip rule del from {} lookup {}'.format(ip_cidr, current_lookup))
if self.flag_require_systemd_clean:
self.result_postdown.insert(0, 'systemctl stop wg-ops-task-{}-*'.format(self.wg_name))
def get_result(self):
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
gen_result_postup = ["PostUp={}".format(line) for line in self.result_postup]

47
tools/reload-dns.py Normal file
View File

@ -0,0 +1,47 @@
# DNS reloader
# WARN: IPv6 style address not supported yet.
import sys
import subprocess
import traceback
if __name__ == "__main__":
if len(sys.argv) < 2:
sys.stderr.write('python3 reload-dns.py <interface> <peer> <target>\n')
exit(1)
interface_name = sys.argv[1]
peer_pubkey = sys.argv[2]
target_addr = sys.argv[3]
# resolve dns
target_parts = target_addr.split(':')[0]
target_host = target_parts[0]
target_port = target_parts[1]
target_ip = subprocess.check_output(["dig", "+short", target_host]).decode().strip()
target_endpoint = "{}:{}".format(target_ip, target_port)
# dump interface
wg_raw_info = subprocess.check_output(["wg", "show", interface_name, "dump"]).decode().strip().split('\n')
if not wg_raw_info:
print('wireguard interface {} not found'.format(interface_name))
exit(1)
wg_raw_info = wg_raw_info[1:]
wg_info = [line.split('\t') for line in wg_raw_info]
wg_info = [x for x in wg_info if x[0] == peer_pubkey]
if not wg_info:
print('wireguard interface {} peer {} not found.'.format(interface_name, peer_pubkey))
exit(1)
peer_info = wg_info[0]
peer_endpoint = peer_info[2]
# check and update
if peer_endpoint != target_endpoint:
print('Updating endpoint from {} to {}...'.format(peer_endpoint, target_endpoint))
try:
subprocess.check_call(["wg", "set", interface_name, "peer", peer_pubkey, "endpoint", target_endpoint])
except Exception:
print(traceback.format_exc())