mirror of
https://github.com/AuxXxilium/arv-v-dsm.git
synced 2024-11-23 23:10:58 +07:00
a8e258e5e2
For containers with user-defined bridge networks, Docker creates an "embedded" DNS server, that listens on the loopback interface. `generate-dhcpd-conf` was trying to pass this local DNS server to the VM, causing it to fail all DNS queries. This change makes `generate-dhcpd-conf` return static IP addresses, by default `8.8.8.8`,`8.8.4.4`. This seems like a reasonable enough middle ground between "no DNS" and trying to proxy VM DNS requests to the embedded docker DNS server. This has the unfortunate side-effect that the VM cannot resolve the names of containers on the same user-defined network (though it can still connect to them by IP). Hopefully I'll eventually get around to fixing this.
81 lines
2.2 KiB
Python
Executable File
81 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import ipaddress
|
|
import json
|
|
import re
|
|
import socket
|
|
import subprocess
|
|
|
|
from typing import List, Iterable
|
|
|
|
DEFAULT_ROUTE = 'default'
|
|
DEFAULT_DNS_IPS = ('8.8.8.8', '8.8.4.4')
|
|
|
|
DHCP_CONF_TEMPLATE = """
|
|
start {host_addr}
|
|
end {host_addr}
|
|
|
|
# avoid dhcpd complaining that we have
|
|
# too many addresses
|
|
maxleases 1
|
|
|
|
interface {dhcp_intf}
|
|
|
|
option dns {dns}
|
|
option router {gateway}
|
|
option subnet {subnet}
|
|
option hostname {hostname}
|
|
"""
|
|
|
|
def default_route(routes):
|
|
"""Returns the host's default route"""
|
|
for route in routes:
|
|
if route['dst'] == DEFAULT_ROUTE:
|
|
return route
|
|
raise ValueError('no default route')
|
|
|
|
def addr_of(addrs, dev : str) -> ipaddress.IPv4Interface:
|
|
"""Finds and returns the IP address of `dev`"""
|
|
for addr in addrs:
|
|
if addr['ifname'] != dev:
|
|
continue
|
|
if len(addr['addr_info']) != 1:
|
|
raise ValueError('only exactly one address on dev is supported')
|
|
info = addr['addr_info'][0]
|
|
return ipaddress.IPv4Interface((info['local'], info['prefixlen']))
|
|
raise ValueError('dev {0} not found'.format(dev))
|
|
|
|
def generate_conf(intf_name : str, dns : Iterable[str]) -> str:
|
|
"""Generates a dhcpd config. `intf_name` is the interface to listen on."""
|
|
with subprocess.Popen(['ip', '-json', 'route'],
|
|
stdout=subprocess.PIPE) as proc:
|
|
routes = json.load(proc.stdout)
|
|
with subprocess.Popen(['ip', '-json', 'addr'],
|
|
stdout=subprocess.PIPE) as proc:
|
|
addrs = json.load(proc.stdout)
|
|
|
|
droute = default_route(routes)
|
|
host_addr = addr_of(addrs, droute['dev'])
|
|
|
|
return DHCP_CONF_TEMPLATE.format(
|
|
dhcp_intf = intf_name,
|
|
dns = ' '.join(dns),
|
|
gateway = droute['gateway'],
|
|
host_addr = host_addr.ip,
|
|
hostname = socket.gethostname(),
|
|
subnet = host_addr.network.netmask,
|
|
)
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('intf_name')
|
|
parser.add_argument('dns_ips', nargs='*')
|
|
args = parser.parse_args()
|
|
|
|
dns_ips = args.dns_ips
|
|
if not dns_ips:
|
|
dns_ips = DEFAULT_DNS_IPS
|
|
|
|
print(generate_conf(args.intf_name, dns_ips))
|