예제 #1
0
파일: veth.py 프로젝트: TOSPIO/dockerfly
    def attach_to_container(self, container_pid, is_route=False, gateway=None):
        self._is_attach_to_container = True
        self._attach_to_container_pid = container_pid

        try:
            ip('link', 'set', 'netns', self._attach_to_container_pid, self._veth_name)
            nsenter('-t', self._attach_to_container_pid,
                    '-n', 'ip', 'link', 'set', self._veth_name, 'up')

            if '0.0.0.0' not in self._ip_netmask:
                nsenter('-t', self._attach_to_container_pid,
                    '-n', 'ip', 'addr', 'add', self._ip_netmask, 'dev', self._veth_name)
        except Exception as e:
            raise VEthAttachException("attach macvlan eth error:\n{}".format(e.message))

        if is_route:
            if not gateway:
                raise ValueError("Please set the gateway for %s" % self._veth_name)
            else:
                nsenter('-t', self._attach_to_container_pid,
                        '-n', 'ip', 'route', 'del', 'default')
                nsenter('-t', self._attach_to_container_pid,
                        '-n', 'ip', 'route', 'add', 'default', 'via', gateway, 'dev', self._veth_name)
                #arping my gateway, cause the gateway to flush the ARP cache for my IP address
                try:
                    nsenter('-t', self._attach_to_container_pid,
                            '-n', 'ping', '-c', '1', gateway)
                except Exception as e:
                    logger.warning(e.message)

        return self
예제 #2
0
파일: veth.py 프로젝트: TOSPIO/dockerfly
 def create(self):
     try:
         ip('link', 'add', self._veth_name,
             'link', self._link_to, 'address', self.gen_mac_address(), 'type', 'macvlan', 'mode', 'bridge')
     except Exception as e:
         raise VEthCreateException("create macvlan eth error:\n{}".format(e.message))
     return self
예제 #3
0
def ndp_proxy(method, vm):
    validate_method(method)
    vm_info = hedron.virtual_machine_info(vm)
    ip6 = vm_info['network_interfaces'][0]['ipv6']
    device = get_default_v6_route_device()

    sh.ip('-6', 'neigh', method, 'proxy', ip6, 'dev', device)
    return True
예제 #4
0
def delete(network="default"):
    """
    Delete a routing rule
    """
    try:
        sh.ip("route", "del", network)
    except sh.ErrorReturnCode_2:
        pass
예제 #5
0
파일: veth.py 프로젝트: TOSPIO/dockerfly
 def delete(self):
     try:
         if self._is_attach_to_container:
             nsenter('-t', self._attach_to_container_pid,
                     '-n', 'ip', 'link', 'del', self._veth_name)
         else:
             ip('link', 'del', self._veth_name)
     except Exception as e:
         raise VEthDeleteException("delete macvlan eth error:\n{}".format(e.message))
예제 #6
0
 def create(self):
     try:
         ip('link', 'add',
            self._veth_name, 'link', self._link_to, 'address',
            self.gen_mac_address(), 'type', 'macvlan', 'mode', 'bridge')
     except Exception as e:
         raise VEthCreateException("create macvlan eth error:\n{}".format(
             e.message))
     return self
예제 #7
0
 def delete(self):
     try:
         if self._is_attach_to_container:
             nsenter('-t', self._attach_to_container_pid, '-n', 'ip',
                     'link', 'del', self._veth_name)
         else:
             ip('link', 'del', self._veth_name)
     except Exception as e:
         raise VEthDeleteException("delete macvlan eth error:\n{}".format(
             e.message))
예제 #8
0
파일: veth.py 프로젝트: TOSPIO/dockerfly
 def down(self):
     try:
         if self._is_attach_to_container:
             nsenter('-t', self._attach_to_container_pid,
                     '-n', 'ip', 'link', self._veth_name, 'down')
         else:
             ip('link', 'set', self._veth_name, 'down')
     except Exception as e:
         raise VEthDownException("down macvlan eth error:\n{}".format(e.message))
     return self
예제 #9
0
def route(method, vm):
    """
    Not needed if using primary is bridged with the public interface,
    but doesn't hurt, either.
    """
    validate_method(method)
    vm_info = hedron.virtual_machine_info(vm)
    ip6 = vm_info['network_interfaces'][0]['ipv6']
    arguments = _route_command(method, ip6)
    sh.ip(arguments)
    return True
예제 #10
0
 def up(self):
     try:
         if self._is_attach_to_container:
             docker('exec', self._attach_to_container_id, 'ip', 'link',
                    'del', self._veth_name)
         else:
             ip('link', 'set', self._veth_name, 'up')
     except Exception as e:
         raise VEthUpException("up macvlan eth error:\n{}".format(
             e.message))
     return self
예제 #11
0
 def down(self):
     try:
         if self._is_attach_to_container:
             nsenter('-t', self._attach_to_container_pid, '-n', 'ip',
                     'link', self._veth_name, 'down')
         else:
             ip('link', 'set', self._veth_name, 'down')
     except Exception as e:
         raise VEthDownException("down macvlan eth error:\n{}".format(
             e.message))
     return self
예제 #12
0
 def create(self):
     try:
         veth_lockfile = join(settings.RUN_ROOT, self._veth_name + '.lock')
         with FileLock(veth_lockfile).acquire(
                 timeout=settings.LOCK_TIMEOUT):
             ip('link', 'add',
                self._veth_name, 'link', self._link_to, 'address',
                self.gen_mac_address(), 'type', 'macvlan', 'mode', 'bridge')
     except Exception as e:
         raise VEthCreateException("create macvlan eth error:\n{}".format(
             e.message))
     return self
예제 #13
0
def delete(network="default"):
    """Delete a routing rule.

    Args:
        network: destination of the routing rule to be delete

    Raises:
        FIXME
    """
    try:
        sh.ip("route", "del", network)
    except sh.ErrorReturnCode_2:
        pass
예제 #14
0
def ifupdown(iface, up):
    """Set an interface to up or down status.

    Args:
        iface: interface name.
        up: status for the interface, True for up and False for down.

    Raises:
        ValueError
    """
    if not up:
        dhclient(iface, False)
    try:
        sh.ip("link", "set", iface, "up" if up else "down")
    except Exception:
        raise ValueError("Cannot update the link status for \"%s\"." % iface)
예제 #15
0
def ifupdown(iface, up):
    """Set an interface to up or down status.

    Args:
        iface: interface name.
        up: status for the interface, True for up and False for down.

    Raises:
        ValueError
    """
    if not up:
        dhclient(iface, False)
    try:
        sh.ip("link", "set", iface, "up" if up else "down")
    except:
        raise ValueError("Cannot update the link status for \"%s\"."
                         % iface)
예제 #16
0
def add(dest, dev="", src="", nexthop=None):
    """
    Add a routing rule

    Args:
        dest: destination for the routing rule, "default" for default route
            ex. "192.168.4.0/24" or "default"
        dev: routing device, could be empty
            ex. "wwan0", "eth0"
        src: source for the routing rule, fill "gateway" if dest is "default"
            ex. "192.168.4.127", "192.168.4.254"
        nexthop: nexthop info. for load balance
            [
                {
                    "via": "10.94.87.78",
                    "dev": "wwan0",
                    "weight": 1
                },
                {
                    "via": "10.144.7.254",
                    "dev": "eth0",
                    "weight": 1
                }
            ]
    """
    if "default" == dest:
        if nexthop:
            param = ["route", "add", dest]
            for nh in nexthop:
                param.append("nexthop")
                for k, v in nh.iteritems():
                    param.extend([k, v])
            sh.ip(*param)
        elif dev:
            sh.ip("route", "add", dest, "dev", dev, "via", src)
        else:
            sh.ip("route", "add", dest, "via", src)
    elif "" == src:
        sh.ip("route", "add", dest, "dev", dev)
    else:
        sh.ip("route", "add", dest, "dev", dev, "proto", "kernel", "scope",
              "link", "src", src)
예제 #17
0
def get_vpn_gateway(_output_level=2):
    # TODO: We could just parse this from the `remote` options in the `openvpn`
    #       conf and check against an existing route.
    # TODO: Extract the corresponding port for the firewall rule too, while
    #       you're at it!
    external_ip = get_connection_info()['ip']

    ip_r = sh.ip('r', _bg=True)

    with output.Attempts(
        'Resolving IP of VPN gateway',
        num_attempts=20,
        _output_level=_output_level
    ) as attempts:
        for attempt in attempts:
            if ip_r.process.is_alive():
                attempt.passed()
            else:
                attempt.successful = True

        if not attempts.successful:
            raise NetworkError('Failed to resolve IP of VPN gateway')

    gateway_ip_candidates = difflib.get_close_matches(
        external_ip,
        ip_r.stdout.split(),
    )

    if not gateway_ip_candidates:
        raise NetworkError(
            'No candidates for VPN gateway IP identified. Nothing is similar'
            ' to {} in {}'.format(external_ip, ip_r.stdout))
    elif len(gateway_ip_candidates) > 1:
        raise NetworkError(
            'Multiple candidates for VPN gateway IPs identified: {} are'
            ' similar to {}'.format(gateway_ip_candidates, external_ip)
        )
    else:
        gateway_ip = gateway_ip_candidates.pop()

    row = re.search(
        '^{} via .+ dev (?P<device>\S+) $'.format(gateway_ip),
        ip_r.stdout,
        re.MULTILINE
    )
    if not row:
        raise NetworkError('No route to VPN gateway detected.')

    return row.group('device'), gateway_ip
예제 #18
0
    def attach_to_container(self, container_pid, is_route=False, gateway=None):
        self._is_attach_to_container = True
        self._attach_to_container_pid = container_pid

        try:
            ip('link', 'set', 'netns', self._attach_to_container_pid,
               self._veth_name)
            nsenter('-t', self._attach_to_container_pid, '-n', 'ip', 'link',
                    'set', self._veth_name, 'up')

            if '0.0.0.0' not in self._ip_netmask:
                nsenter('-t', self._attach_to_container_pid, '-n', 'ip',
                        'addr', 'add', self._ip_netmask, 'dev',
                        self._veth_name)
        except Exception as e:
            raise VEthAttachException("attach macvlan eth error:\n{}".format(
                e.message))

        if is_route:
            if not gateway:
                raise ValueError("Please set the gateway for %s" %
                                 self._veth_name)
            else:
                nsenter('-t', self._attach_to_container_pid, '-n', 'ip',
                        'route', 'del', 'default')
                nsenter('-t', self._attach_to_container_pid, '-n', 'ip',
                        'route', 'add', 'default', 'via', gateway, 'dev',
                        self._veth_name)
                #arping my gateway, cause the gateway to flush the ARP cache for my IP address
                try:
                    nsenter('-t', self._attach_to_container_pid, '-n', 'ping',
                            '-c', '1', gateway)
                except Exception as e:
                    logger.warning(e.message)

        return self
예제 #19
0
def compareIp():
    logging.debug("Comparing ip...")
    #ip a s eth0 | egrep -o 'inet [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d' ' -f2
    curIp = str(cut(egrep(ip('a', 's', 'eth0'), '-o', 'inet [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'), '-d', ' ', '-f2')).strip()
    masterNetworkCfg = cat('/etc/systemd/network/000-master.network').split('\n')
    for i in range(len(masterNetworkCfg)):
        if masterNetworkCfg[i] == '[Address]':
            masterIp = masterNetworkCfg[i+1].split('=')[1].strip()
            logging.debug("Master ip found, breaking the loop...")
            break 
    if curIp==masterIp:
        logging.debug("Master IP == cur IP...")
        return True, masterIp
    logging.debug("Master IP != cur IP...")
    return False, masterIp
예제 #20
0
def build_network(_server):
    network = _server['meta']['network']
    sort_order = ['physical', 'symlink', 'bond', 'tagged']
    networks = sorted(network.items(),
                      key=lambda x: sort_order.index(x[1]['type']))

    for name, net in networks:
        if net['type'] == 'symlink':
            continue
        elif net['type'] == 'bond':
            sh.modprobe('bonding', 'mode=4', 'miimon=100',
                        'xmit_hash_policy=1')
            sh.ifconfig(name, 'up')
            for iface in net['interfaces']:
                sh.ifenslave(name, iface)
        elif net['type'] == 'tagged':
            iface = net['interfaces'][0]
            sh.vconfig('add', iface, net['vlan'])
            sh.ifconfig(name, 'up')
        # Assign ip if required
        if net.get('ip'):
            ip = netaddr.IPNetwork('/'.join((net['ip'], net['mask'])))
            sh.ip('addr', 'add', str(ip), 'brd', str(ip.broadcast), 'dev',
                  name)
예제 #21
0
def build_network(_server):
    network = _server['meta']['network']
    sort_order = ['physical', 'symlink', 'bond', 'tagged']
    networks = sorted(network.items(),
                      key=lambda x: sort_order.index(x[1]['type']))

    for name, net in networks:
        if net['type'] == 'symlink':
            continue
        elif net['type'] == 'bond':
            sh.modprobe('bonding', 'mode=4', 'miimon=100',
                        'xmit_hash_policy=1')
            sh.ifconfig(name, 'up')
            for iface in net['interfaces']:
                sh.ifenslave(name, iface)
        elif net['type'] == 'tagged':
            iface = net['interfaces'][0]
            sh.vconfig('add', iface, net['vlan'])
            sh.ifconfig(name, 'up')
        # Assign ip if required
        if net.get('ip'):
            ip = netaddr.IPNetwork('/'.join((net['ip'], net['mask'])))
            sh.ip('addr', 'add', str(ip),
                  'brd', str(ip.broadcast), 'dev', name)
예제 #22
0
def add(dest, dev="", src=""):
    """Add a routing rule.

    Args:
        dest: destination for the routing rule, default for default route.
        dev: routing device, could be empty
        src: source for the routing rule, fill "gateway" if dest is "default"

    Raises:
        FIXME
    """
    if "" == src:
        sh.ip("route", "add", dest, "dev", dev)
    elif "default" == dest:
        if dev:
            sh.ip("route", "add", dest, "dev", dev, "via", src)
        else:
            sh.ip("route", "add", dest, "via", src)
    else:
        sh.ip("route", "add", dest, "dev", dev, "proto", "kernel", "scope",
              "link", "src", src)
예제 #23
0
def show():
    """List all routing rules.

    Returns:
        A list of dict for each routing rule.

        [
            {"dest": "",
                "src": "",
                "dev": ""},
            {"default": "",
                "dev": ""}
        ]
    """
    rules = []
    routes = sh.ip("route", "show")
    for route in routes:
        rule = dict()
        route = route.split()
        if "default" == route[0]:
            rule["default"] = ""
            if "via" in route:
                rule["default"] = route[route.index("via")+1]
            rule["dev"] = route[route.index("dev")+1]
        else:
            rule["dest"] = route[0]
            rule["dev"] = route[route.index("dev")+1]
            if "src" in route:
                src = route.index("src")
            elif "via" in route:
                src = route.index("via")
            else:
                src = -1
            if -1 != src:
                rule["src"] = route[src+1]
        rules.append(rule)
    return rules
예제 #24
0
    def tearDown(self):
        # Create a network namespace
        ns = ip("netns", "show", self.pid)
        if ns and (str(self.pid) in ns.stdout):
            try:
                ip("netns", "delete", self.pid)
            except (ErrorReturnCode, ErrorReturnCode_1) as e:
                print "Didn't delete ns: %s" % e

        try:
            os.remove("/var/run/netns/%s" % self.pid)
        except OSError:
            pass

        # Wipe all cali interfaces
        regex = r'((?:cali)[0-9a-f]+):'
        interface_names = re.findall(regex, ip('link').stdout)
        for interface in interface_names:
            ip('link', 'del', 'dev', interface)
예제 #25
0
    def tearDown(self):
        # Create a network namespace
        ns = ip("netns", "show", self.pid)
        if ns and (str(self.pid) in ns.stdout):
            try:
                ip("netns", "delete", self.pid)
            except (ErrorReturnCode, ErrorReturnCode_1) as e:
                print "Didn't delete ns: %s" % e

        try:
            os.remove("/var/run/netns/%s" % self.pid)
        except OSError:
            pass

        # Wipe all cali interfaces
        regex = r'((?:cali)[0-9a-f]+):'
        interface_names = re.findall(regex, ip('link').stdout)
        for interface in interface_names:
            ip('link', 'del', 'dev', interface)
예제 #26
0
def ifconfig(iface, dhcpc, ip="", netmask="24", gateway="", script=None):
    """Set the interface to static IP or dynamic IP (by dhcpclient).

    Args:
        iface: interface name.
        dhcpc: True for using dynamic IP and False for static.
        ip: IP address for static IP
        netmask:
        gateway:

    Raises:
        ValueError
    """
    # TODO(aeluin) catch the exception?
    # Check if interface exist
    try:
        sh.ip("addr", "show", iface)
    except sh.ErrorReturnCode_1:
        raise ValueError("Device \"%s\" does not exist." % iface)
    except Exception:
        raise ValueError("Unknown error for \"%s\"." % iface)

    # Disable the dhcp client and flush interface
    dhclient(iface, False)

    try:
        sh.ip("-4", "addr", "flush", "label", iface)
    except Exception:
        raise ValueError("Unknown error for \"%s\"." % iface)

    if dhcpc:
        dhclient(iface, True, script)
    else:
        if ip:
            net = ipcalc.Network("%s/%s" % (ip, netmask))
            sh.ip("addr", "add", "%s/%s" % (ip, net.netmask()), "broadcast",
                  net.broadcast(), "dev", iface)
예제 #27
0
def ifconfig(iface, dhcpc, ip="", netmask="24", gateway="", script=None):
    """Set the interface to static IP or dynamic IP (by dhcpclient).

    Args:
        iface: interface name.
        dhcpc: True for using dynamic IP and False for static.
        ip: IP address for static IP
        netmask:
        gateway:

    Raises:
        ValueError
    """
    # TODO(aeluin) catch the exception?
    # Check if interface exist
    try:
        sh.ip("addr", "show", iface)
    except sh.ErrorReturnCode_1:
        raise ValueError("Device \"%s\" does not exist." % iface)
    except:
        raise ValueError("Unknown error for \"%s\"." % iface)

    # Disable the dhcp client and flush interface
    dhclient(iface, False)

    try:
        sh.ip("-4", "addr", "flush", "label", iface)
    except:
        raise ValueError("Unknown error for \"%s\"." % iface)

    if dhcpc:
        dhclient(iface, True, script)
    else:
        if ip:
            net = ipcalc.Network("%s/%s" % (ip, netmask))
            sh.ip("addr", "add", "%s/%s" % (ip, net.netmask()), "broadcast",
                  net.broadcast(), "dev", iface)
예제 #28
0
#!/usr/bin/env python
import os
import sys
import re
from sh import ip

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "yads.settings")

    primary_ip = re.sub(r'(?s).*? src\s(.*?)\s.*', r'\1',
                        str(ip("route", "get", "8.8.8.8")))
    if not primary_ip:
        primary_ip = "127.0.0.1"
    os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = primary_ip + ':15000-16000'

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)
예제 #29
0
    if option == "nslookup":
        print(Fore.YELLOW + "enter the website to nslookup: ")
        webar = raw_input()
        print bada.nslookup(webar)

    elif option == "whois":
        print(Fore.YELLOW + "Enter the website to find its public data: ")

        whois_ar = raw_input()
        print bada.whois(whois_ar)

    elif option == "ip":
        print(Fore.YELLOW + "Finding your system ip address ")

        print bada.ip("addr")

    elif option == "dig":
        print(Fore.YELLOW + "enter the website to find its DNS servers ......")
        dig_ar = raw_input()
        print bada.dig(dig_ar)

    elif option == "nmcli":
        print(Fore.YELLOW +
              "To check the information about your connection ..............")
        print bada.nmcli.dev.wifi()

    elif option == "scan":

        print(
            Fore.YELLOW +
예제 #30
0
import threading
from http.server import HTTPServer
import socket
import logging as log
import atexit
# get_ip_address
from sh import ip, awk, cut

import prometheus_client
import consul


# Do not use addr and remove the address option from the register function
# if you are running this on a regular instance with a local Consul agent
addr = cut(awk(ip("addr", "show", "dev", "eth0"), "/inet / { print $2 }"), "-d/", "-f1").strip()
print(addr)

# consul should be a hostname that is accessible from the clever app container
c = consul.Consul(host="consul")

def deregister_id(service_id):
    def dereg():
        c.agent.service.deregister(service_id)
    return dereg

def start_prometheus_server(name, port_range):
    for port in range(*port_range):
        try:
            httpd = HTTPServer(("0.0.0.0", port), prometheus_client.MetricsHandler)
        except (OSError, socket.error):
            # Python 2 raises socket.error, in Python 3 socket.error is an
예제 #31
0
def ip_a():
    out: sh.RunningCommand = sh.ip('--json', 'a')
    doc = json.loads(out.stdout)
    return doc
예제 #32
0
from sh import ifconfig
from sh import ip

import base64
import json
import socket
import struct

GATD_HOST = 'inductor.eecs.umich.edu'
GATD_PORT = 16284

#Create a tun device and setup the configuration to it
tun = pytun.TunTapDevice(name='ipv6gatd')
ifconfig(tun.name, 'up')
ifconfig(tun.name, 'mtu', '1280')
ip('-6', 'route', 'add', '2001:470:1f10:1320::2/128', 'dev', tun.name)

# Parameters for the ipv4 connection to gatd
gatdsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
gatdaddr = (GATD_HOST, GATD_PORT)

# Loop waiting for packets to get routed to this tun interface, strip them,
# and send the import bits back to gatd
while True:
	buf = tun.read(1280)
	pkt = dpkt.ip6.IP6(buf[4:])

	if type(pkt.data) != dpkt.udp.UDP:
		continue

	gatdpkt = {}
예제 #33
0
def show():
    """
    List routing rules

    Returns:
        A list of dict of each routing rule.

        [
            ...,
            {
                "dest": "192.168.4.0/24",
                "dev": "eth1",
                "src": "192.168.4.254"
            },
            {
                "default": "10.94.87.78",
                "dev": "wwan0",
                "weight": 1,
                "priority": 1
            },
            {
                "default": "10.144.7.254",
                "dev": "eth0",
                "weight": 1,
                "priority": 2
            }
        ]
    """
    rules = []
    """
    ip route show

    default
        nexthop via 10.94.87.78  dev wwan0 weight 1
        nexthop via 10.144.7.254  dev eth0 weight 1
    10.94.87.76/30 dev wwan0  proto kernel  scope link  src 10.94.87.77
    10.144.4.0/22 dev eth0  proto kernel  scope link  src 10.144.4.80
    192.168.4.0/24 dev eth1  proto kernel  scope link  src 192.168.4.127
    """
    routes = sh.ip("route", "show")

    nexthop_priority = 1
    for route in routes:
        rule = {}
        spec = route.split()
        if "default" in route:
            if "via" in spec:
                rule["default"] = spec[spec.index("via") + 1]
            if "dev" in spec:
                rule["dev"] = spec[spec.index("dev") + 1]
        elif "nexthop" in route:
            rule["default"] = spec[spec.index("via") + 1]
            rule["dev"] = spec[spec.index("dev") + 1]
            rule["weight"] = int(spec[spec.index("weight") + 1])
            rule["priority"] = nexthop_priority
            nexthop_priority += 1
        else:
            rule["dest"] = spec[0]
            if "dev" in spec:
                rule["dev"] = spec[spec.index("dev") + 1]
            if "src" in spec:
                src_idx = spec.index("src")
            elif "via" in spec:
                src_idx = spec.index("via")
            else:
                src_idx = -1
            if -1 != src_idx:
                rule["src"] = spec[src_idx + 1]

        # empty dict
        if len(rule) == 0:
            continue

        rules.append(rule)

    return rules
예제 #34
0
def get_ip_by_interface(iface):
    ip = sh.awk(
        sh.grep(sh.grep(sh.ip("addr", "show", iface), "inet"), "-v", "inet6"),
        "{print $2}").split("/")[0]
    return ip
예제 #35
0
def get_default_v6_route_device():
    ip_ro_output = sh.ip('-6', 'ro')
    device = _default_route_parse(ip_ro_output)
    return device
예제 #36
0
def setup_networking(ob_num: int):
    """Sets up networking.

    Installs some debs manually that are required for configuring networking,
    since we don't yet have networking and can't apt install them. Then configures
    DNS and network interfaces, then bounces the network interfaces.
    """
    print(" === Setting up networking === ")

    # Install network management packages manually via dpkg, since we can't apt
    # install them without networking already setup.
    print("Installing dependencies for setting up networking...")
    dpkg("-i", *glob("./*.deb"))

    print("Configuring resolved...")
    # Default to the Mikrotik router for DNS, with a fallback of Google's DNS
    sed("-i", "s/^#DNS=$/DNS=172.27.31.254 8.8.8.8/g",
        "/etc/systemd/resolved.conf")
    sed("-i", "s/^#FallbackDNS=$/FallbackDNS=8.8.8.8 8.8.4.4/g",
        "/etc/systemd/resolved.conf")
    systemctl("restart", "systemd-resolved")

    # Not sure if still used, but some things might be expecting orange boxen to
    # have this configuration file.
    with open("/etc/orange-box.conf", "w") as f:
        f.writelines([f"orangebox_number={ob_num}"])

    # Disable the external ethernet port (en*) and use both of the internal
    # ones (enx*). The enx* interfaces map to vlan1 and vlan2, which in turn
    # get mapped to `172.27.{orange box #}.X` and `172.27.{orange box # + 2}.X`,
    # respectively. They are both bridged to the wireless network that the
    # orange box is connected to, hence not needing en* connected.
    print("Writing network configuration...")
    interfaces = list(
        sorted(
            Path(iface).name for iface in glob("/sys/class/net/*")
            if Path(iface).name.startswith("en")))
    internal_ips = [f"172.27.{ob_num}.1", f"172.27.{ob_num + 2}.1"]
    gateway_ips = [f"172.27.{ob_num + 1}.254", f"172.27.{ob_num + 3}.254"]
    sh.ip("addr", "flush", "dev", interfaces[1])
    sh.ifconfig(interfaces[1], f"{internal_ips[1]}/23")
    systemctl("stop", "NetworkManager")
    systemctl("disable", "NetworkManager")

    with open("/etc/network/interfaces", "w") as f:
        f.write(
            textwrap.dedent(f"""
            # These are generated by orange-box build scripts
            auto lo
            iface lo inet loopback

            auto {interfaces[0]}
            iface {interfaces[0]} inet manual

            auto {interfaces[1]}
            iface {interfaces[1]} inet manual

            auto {interfaces[2]}
            iface {interfaces[2]} inet manual

            auto br0
            iface br0 inet static
              address {internal_ips[0]}
              netmask 255.255.254.0
              gateway {gateway_ips[0]}
              dns-nameservers {internal_ips[0]} {gateway_ips[0]}
              bridge_ports {interfaces[1]}
              bridge_stp off
              bridge_fd 0
              bridge_maxwait 0

            auto br1
            iface br1 inet static
              address {internal_ips[1]}
              netmask 255.255.254.0
              bridge_ports {interfaces[2]}
              bridge_stp off
              bridge_fd 0
              bridge_maxwait 0"""))

    print("Restarting network interfaces...")
    bridges = ["br0", "br1"]

    # Take down all of the interfaces
    for iface in interfaces + bridges:
        sh.ifdown("--force", iface)

    # Bring up all interfaces except enp*
    for iface in interfaces[1:] + bridges:
        sh.ifup("--force", iface)

    print("Waiting for network to come up...")
    for _ in range(60):
        try:
            ping("-c1", "8.8.8.8")
            break
        except sh.ErrorReturnCode_1:
            print(" - Still waiting for 8.8.8.8...")
    else:
        print("Waited too long for network to come up.")
        print("Please fix the network.")
        sys.exit(1)

    print("Waiting for DNS to come up...")
    for _ in range(60):
        try:
            ping("-c1", "launchpad.net")
            break
        except (sh.ErrorReturnCode_1, sh.ErrorReturnCode_2):
            print(" - Still waiting for launchpad.net...")
    else:
        print("Waited too long for DNS to come up.")
        print("Please fix the DNS.")
        sys.exit(1)