mirror of
https://github.com/Rudd-O/qubes-network-server.git
synced 2025-03-01 14:22:35 +01:00
Blacken.
This commit is contained in:
parent
a057e31578
commit
b92f096dcc
@ -1,54 +1,58 @@
|
|||||||
#!/usr/bin/python2
|
#!/usr/bin/python2
|
||||||
|
|
||||||
'''
|
"""
|
||||||
This program reads the /qubes-firewall/{ip}/qubes-routing-method file
|
This program reads the /qubes-firewall/{ip}/qubes-routing-method file
|
||||||
for any firewall configuration, then configures the network to obey
|
for any firewall configuration, then configures the network to obey
|
||||||
the routing method for the VM. If the routing method is "masquerade",
|
the routing method for the VM. If the routing method is "masquerade",
|
||||||
then nothing happens. If, however, the routing method is "forward",
|
then nothing happens. If, however, the routing method is "forward",
|
||||||
then VM-specific rules are enacted in the VM's attached NetVM to allow
|
then VM-specific rules are enacted in the VM's attached NetVM to allow
|
||||||
traffic coming from other VMs and the outside world to reach this VM.
|
traffic coming from other VMs and the outside world to reach this VM.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import qubesdb
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
|
||||||
import socket
|
import socket
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import qubesdb
|
||||||
|
|
||||||
|
|
||||||
FORWARD_ROUTING_METHOD = 'forward'
|
|
||||||
|
|
||||||
|
FORWARD_ROUTING_METHOD = "forward"
|
||||||
|
|
||||||
|
|
||||||
class AdjunctWorker(object):
|
class AdjunctWorker(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.qdb = qubesdb.QubesDB()
|
self.qdb = qubesdb.QubesDB()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_ip6(addr):
|
def is_ip6(addr):
|
||||||
return addr.count(':') > 0
|
return addr.count(":") > 0
|
||||||
|
|
||||||
def setup_plain_forwarding_for_address(self, source, enable, family):
|
def setup_plain_forwarding_for_address(self, source, enable, family):
|
||||||
|
|
||||||
def find_pos_of_first_rule(table, startswith):
|
def find_pos_of_first_rule(table, startswith):
|
||||||
rules = [n for n, l in enumerate(out) if l.startswith(startswith)]
|
rules = [n for n, l in enumerate(out) if l.startswith(startswith)]
|
||||||
if rules:
|
if rules:
|
||||||
return rules[0]
|
return rules[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
cmd = 'ip6tables' if family == 6 else 'iptables'
|
cmd = "ip6tables" if family == 6 else "iptables"
|
||||||
mask = '/128' if family == 6 else '/32'
|
mask = "/128" if family == 6 else "/32"
|
||||||
def run_ipt(*args):
|
|
||||||
return subprocess.check_call([cmd, '-w'] + list(args))
|
|
||||||
|
|
||||||
out = subprocess.check_output([cmd + '-save'], universal_newlines=True).splitlines()
|
def run_ipt(*args):
|
||||||
|
return subprocess.check_call([cmd, "-w"] + list(args))
|
||||||
|
|
||||||
|
out = subprocess.check_output(
|
||||||
|
[cmd + "-save"], universal_newlines=True
|
||||||
|
).splitlines()
|
||||||
|
|
||||||
if enable:
|
if enable:
|
||||||
# Create necessary prerouting chain.
|
# Create necessary prerouting chain.
|
||||||
if not find_pos_of_first_rule(out, ':PR-PLAIN-FORWARDING - '):
|
if not find_pos_of_first_rule(out, ":PR-PLAIN-FORWARDING - "):
|
||||||
run_ipt('-t', 'nat', '-N', 'PR-PLAIN-FORWARDING')
|
run_ipt("-t", "nat", "-N", "PR-PLAIN-FORWARDING")
|
||||||
|
|
||||||
# Route prerouting traffic to necessary chain.
|
# Route prerouting traffic to necessary chain.
|
||||||
if not find_pos_of_first_rule(out, "-A POSTROUTING -j PR-PLAIN-FORWARDING"):
|
if not find_pos_of_first_rule(out, "-A POSTROUTING -j PR-PLAIN-FORWARDING"):
|
||||||
rule_num = find_pos_of_first_rule(out, "-A POSTROUTING -j MASQUERADE")
|
rule_num = find_pos_of_first_rule(out, "-A POSTROUTING -j MASQUERADE")
|
||||||
@ -59,15 +63,25 @@ class AdjunctWorker(object):
|
|||||||
first_rule_num = find_pos_of_first_rule(out, "-A POSTROUTING")
|
first_rule_num = find_pos_of_first_rule(out, "-A POSTROUTING")
|
||||||
pos = rule_num - first_rule_num + 1
|
pos = rule_num - first_rule_num + 1
|
||||||
logging.info("Adding POSTROUTING chain PR-PLAIN-FORWARDING.")
|
logging.info("Adding POSTROUTING chain PR-PLAIN-FORWARDING.")
|
||||||
run_ipt('-t', 'nat', '-I', 'POSTROUTING', str(pos), '-j', 'PR-PLAIN-FORWARDING')
|
run_ipt(
|
||||||
|
"-t",
|
||||||
|
"nat",
|
||||||
|
"-I",
|
||||||
|
"POSTROUTING",
|
||||||
|
str(pos),
|
||||||
|
"-j",
|
||||||
|
"PR-PLAIN-FORWARDING",
|
||||||
|
)
|
||||||
|
|
||||||
# Create necessary forward chain.
|
# Create necessary forward chain.
|
||||||
if not find_pos_of_first_rule(out, ':PLAIN-FORWARDING - '):
|
if not find_pos_of_first_rule(out, ":PLAIN-FORWARDING - "):
|
||||||
run_ipt('-t', 'filter', '-N', 'PLAIN-FORWARDING')
|
run_ipt("-t", "filter", "-N", "PLAIN-FORWARDING")
|
||||||
|
|
||||||
# Route forward traffic to necessary chain.
|
# Route forward traffic to necessary chain.
|
||||||
if not find_pos_of_first_rule(out, "-A FORWARD -j PLAIN-FORWARDING"):
|
if not find_pos_of_first_rule(out, "-A FORWARD -j PLAIN-FORWARDING"):
|
||||||
rule_num = find_pos_of_first_rule(out, "-A FORWARD -i vif+ -o vif+ -j DROP")
|
rule_num = find_pos_of_first_rule(
|
||||||
|
out, "-A FORWARD -i vif+ -o vif+ -j DROP"
|
||||||
|
)
|
||||||
if not rule_num:
|
if not rule_num:
|
||||||
# This table does not contain the masquerading rule.
|
# This table does not contain the masquerading rule.
|
||||||
# Accordingly, we will not do anything.
|
# Accordingly, we will not do anything.
|
||||||
@ -75,34 +89,43 @@ class AdjunctWorker(object):
|
|||||||
first_rule_num = find_pos_of_first_rule(out, "-A FORWARD")
|
first_rule_num = find_pos_of_first_rule(out, "-A FORWARD")
|
||||||
pos = rule_num - first_rule_num + 1
|
pos = rule_num - first_rule_num + 1
|
||||||
logging.info("Adding FORWARD chain PLAIN-FORWARDING.")
|
logging.info("Adding FORWARD chain PLAIN-FORWARDING.")
|
||||||
run_ipt('-t', 'filter', '-I', 'FORWARD', str(pos), '-j', 'PLAIN-FORWARDING')
|
run_ipt(
|
||||||
|
"-t", "filter", "-I", "FORWARD", str(pos), "-j", "PLAIN-FORWARDING"
|
||||||
|
)
|
||||||
|
|
||||||
rule = find_pos_of_first_rule(
|
rule = find_pos_of_first_rule(
|
||||||
out,
|
out, "-A PR-PLAIN-FORWARDING -s {}{} -j ACCEPT".format(source, mask)
|
||||||
'-A PR-PLAIN-FORWARDING -s {}{} -j ACCEPT'.format(source, mask)
|
|
||||||
)
|
)
|
||||||
if enable:
|
if enable:
|
||||||
if rule:
|
if rule:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logging.info("Adding POSTROUTING rule to forward traffic from %s.", source)
|
logging.info(
|
||||||
|
"Adding POSTROUTING rule to forward traffic from %s.", source
|
||||||
|
)
|
||||||
run_ipt(
|
run_ipt(
|
||||||
'-t', 'nat', '-A',
|
"-t",
|
||||||
'PR-PLAIN-FORWARDING', '-s', '{}{}'.format(source, mask),
|
"nat",
|
||||||
'-j', 'ACCEPT'
|
"-A",
|
||||||
|
"PR-PLAIN-FORWARDING",
|
||||||
|
"-s",
|
||||||
|
"{}{}".format(source, mask),
|
||||||
|
"-j",
|
||||||
|
"ACCEPT",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if rule:
|
if rule:
|
||||||
first_rule = find_pos_of_first_rule(out, '-A PR-PLAIN-FORWARDING')
|
first_rule = find_pos_of_first_rule(out, "-A PR-PLAIN-FORWARDING")
|
||||||
pos = rule - first_rule + 1
|
pos = rule - first_rule + 1
|
||||||
logging.info("Removing POSTROUTING rule forwarding traffic from %s.", source)
|
logging.info(
|
||||||
run_ipt('-t', 'nat', '-D', 'PR-PLAIN-FORWARDING', str(pos))
|
"Removing POSTROUTING rule forwarding traffic from %s.", source
|
||||||
|
)
|
||||||
|
run_ipt("-t", "nat", "-D", "PR-PLAIN-FORWARDING", str(pos))
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
rule = find_pos_of_first_rule(
|
rule = find_pos_of_first_rule(
|
||||||
out,
|
out, "-A PLAIN-FORWARDING -d {}{} -o vif+ -j ACCEPT".format(source, mask)
|
||||||
'-A PLAIN-FORWARDING -d {}{} -o vif+ -j ACCEPT'.format(source, mask)
|
|
||||||
)
|
)
|
||||||
if enable:
|
if enable:
|
||||||
if rule:
|
if rule:
|
||||||
@ -110,16 +133,23 @@ class AdjunctWorker(object):
|
|||||||
else:
|
else:
|
||||||
logging.info("Adding FORWARD rule to allow traffic to %s.", source)
|
logging.info("Adding FORWARD rule to allow traffic to %s.", source)
|
||||||
run_ipt(
|
run_ipt(
|
||||||
'-t', 'filter', '-A',
|
"-t",
|
||||||
'PLAIN-FORWARDING', '-d', '{}{}'.format(source, mask),
|
"filter",
|
||||||
'-o', 'vif+', '-j', 'ACCEPT'
|
"-A",
|
||||||
|
"PLAIN-FORWARDING",
|
||||||
|
"-d",
|
||||||
|
"{}{}".format(source, mask),
|
||||||
|
"-o",
|
||||||
|
"vif+",
|
||||||
|
"-j",
|
||||||
|
"ACCEPT",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if rule:
|
if rule:
|
||||||
logging.info("Removing FORWARD rule allowing traffic to %s.", source)
|
logging.info("Removing FORWARD rule allowing traffic to %s.", source)
|
||||||
first_rule = find_pos_of_first_rule(out, '-A PLAIN-FORWARDING')
|
first_rule = find_pos_of_first_rule(out, "-A PLAIN-FORWARDING")
|
||||||
pos = rule - first_rule + 1
|
pos = rule - first_rule + 1
|
||||||
run_ipt('-t', 'filter', '-D', 'PLAIN-FORWARDING', str(pos))
|
run_ipt("-t", "filter", "-D", "PLAIN-FORWARDING", str(pos))
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -131,32 +161,32 @@ class AdjunctWorker(object):
|
|||||||
# specific IP addresses in question, but it is not clear to me how
|
# specific IP addresses in question, but it is not clear to me how
|
||||||
# to cause this outcome to take place.
|
# to cause this outcome to take place.
|
||||||
if family == 6:
|
if family == 6:
|
||||||
globber = '/proc/sys/net/ipv6/conf/*/proxy_ndp'
|
globber = "/proc/sys/net/ipv6/conf/*/proxy_ndp"
|
||||||
name = 'proxy NDP'
|
name = "proxy NDP"
|
||||||
elif family == 4:
|
elif family == 4:
|
||||||
globber = '/proc/sys/net/ipv4/conf/*/proxy_arp'
|
globber = "/proc/sys/net/ipv4/conf/*/proxy_arp"
|
||||||
name = 'proxy ARP'
|
name = "proxy ARP"
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
if enabled:
|
if enabled:
|
||||||
action = 'Enabling'
|
action = "Enabling"
|
||||||
val = '1\n'
|
val = "1\n"
|
||||||
else:
|
else:
|
||||||
action = 'Disabling'
|
action = "Disabling"
|
||||||
val = '0\n'
|
val = "0\n"
|
||||||
|
|
||||||
matches = glob.glob(globber)
|
matches = glob.glob(globber)
|
||||||
for m in matches:
|
for m in matches:
|
||||||
iface = m.split('/')[6]
|
iface = m.split("/")[6]
|
||||||
if iface in ('all', 'lo') or iface.startswith('vif'):
|
if iface in ("all", "lo") or iface.startswith("vif"):
|
||||||
# No need to enable it for "all", or VIFs, or loopback.
|
# No need to enable it for "all", or VIFs, or loopback.
|
||||||
continue
|
continue
|
||||||
with open(m, 'w+') as f:
|
with open(m, "w+") as f:
|
||||||
oldval = f.read()
|
oldval = f.read()
|
||||||
f.seek(0)
|
|
||||||
if oldval != val:
|
if oldval != val:
|
||||||
logging.info('%s %s on interface %s.', action, name, iface)
|
logging.info("%s %s on interface %s.", action, name, iface)
|
||||||
|
f.seek(0)
|
||||||
f.write(val)
|
f.write(val)
|
||||||
|
|
||||||
def handle_addr(self, addr):
|
def handle_addr(self, addr):
|
||||||
@ -165,7 +195,7 @@ class AdjunctWorker(object):
|
|||||||
self.setup_plain_forwarding_for_address(
|
self.setup_plain_forwarding_for_address(
|
||||||
addr,
|
addr,
|
||||||
routing_method == FORWARD_ROUTING_METHOD,
|
routing_method == FORWARD_ROUTING_METHOD,
|
||||||
6 if self.is_ip6(addr) else 4
|
6 if self.is_ip6(addr) else 4,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Manipulate proxy ARP for all known addresses.
|
# Manipulate proxy ARP for all known addresses.
|
||||||
@ -178,21 +208,20 @@ class AdjunctWorker(object):
|
|||||||
}
|
}
|
||||||
for family, methods in mmethods.items():
|
for family, methods in mmethods.items():
|
||||||
self.setup_proxy_arp_ndp(
|
self.setup_proxy_arp_ndp(
|
||||||
FORWARD_ROUTING_METHOD in methods,
|
FORWARD_ROUTING_METHOD in methods, family,
|
||||||
family,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def list_targets(self):
|
def list_targets(self):
|
||||||
return set(t.split('/')[2] for t in self.qdb.list('/qubes-routing-method/'))
|
return set(t.split('/')[2] for t in self.qdb.list('/qubes-routing-method/'))
|
||||||
|
|
||||||
def sd_notify(self, state):
|
def sd_notify(self, state):
|
||||||
'''Send notification to systemd, if available'''
|
"""Send notification to systemd, if available"""
|
||||||
# based on sdnotify python module
|
# based on sdnotify python module
|
||||||
if not 'NOTIFY_SOCKET' in os.environ:
|
if not "NOTIFY_SOCKET" in os.environ:
|
||||||
return
|
return
|
||||||
addr = os.environ['NOTIFY_SOCKET']
|
addr = os.environ["NOTIFY_SOCKET"]
|
||||||
if addr[0] == '@':
|
if addr[0] == "@":
|
||||||
addr = '\0' + addr[1:]
|
addr = "\0" + addr[1:]
|
||||||
try:
|
try:
|
||||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||||
sock.connect(addr)
|
sock.connect(addr)
|
||||||
@ -203,17 +232,17 @@ class AdjunctWorker(object):
|
|||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
self.qdb.watch('/qubes-routing-method/')
|
self.qdb.watch("/qubes-routing-method/")
|
||||||
for source_addr in self.list_targets():
|
for source_addr in self.list_targets():
|
||||||
self.handle_addr(source_addr)
|
self.handle_addr(source_addr)
|
||||||
self.sd_notify('READY=1')
|
self.sd_notify("READY=1")
|
||||||
try:
|
try:
|
||||||
for watch_path in iter(self.qdb.read_watch, None):
|
for watch_path in iter(self.qdb.read_watch, None):
|
||||||
# ignore writing rules itself - wait for final write at
|
# ignore writing rules itself - wait for final write at
|
||||||
# source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
|
# source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
|
||||||
if watch_path.count('/') != 2:
|
if watch_path.count('/') != 2:
|
||||||
continue
|
continue
|
||||||
source_addr = watch_path.split('/')[2]
|
source_addr = watch_path.split("/")[2]
|
||||||
self.handle_addr(source_addr)
|
self.handle_addr(source_addr)
|
||||||
except OSError: # EINTR
|
except OSError: # EINTR
|
||||||
# signal received, don't continue the loop
|
# signal received, don't continue the loop
|
||||||
|
Loading…
x
Reference in New Issue
Block a user