diff --git a/.gitignore b/.gitignore index 6d02285..dd58e6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ +rpm/ +pkgs/ *.pyc +*.pyo *~ *.tar.gz *.rpm +.*.swp diff --git a/Makefile.builder b/Makefile.builder new file mode 100644 index 0000000..ecc662b --- /dev/null +++ b/Makefile.builder @@ -0,0 +1,3 @@ +ifeq ($(PACKAGE_SET),dom0) +RPM_SPEC_FILES=qubes-network-server.spec +endif diff --git a/qubes-network-server.spec b/qubes-network-server.spec index 6bd1205..bf17b00 100644 --- a/qubes-network-server.spec +++ b/qubes-network-server.spec @@ -1,3 +1,5 @@ +%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} + %define debug_package %{nil} %define mybuildnumber %{?build_number}%{?!build_number:1} @@ -37,8 +39,8 @@ make install DESTDIR=$RPM_BUILD_ROOT BINDIR=%{_bindir} LIBDIR=%{_libdir} %files %attr(0755, root, root) %{_bindir}/qvm-static-ip -%attr(0644, root, root) %{_libdir}/python2.7/site-packages/qubes/modules/*.py* -%attr(0644, root, root) %{_libdir}/python2.7/site-packages/qubes/modules/qubes-appvm-firewall +%attr(0644, root, root) %{python_sitearch}/qubes/modules/*.py* +%attr(0644, root, root) %{python_sitearch}/qubes/modules/qubes-appvm-firewall %doc README.md TODO %changelog diff --git a/src/usr/lib64/python2.7/site-packages/qubes/modules/007FortressQubesProxyVm.py b/src/usr/lib64/python2.7/site-packages/qubes/modules/007FortressQubesProxyVm.py index 1e541b5..b73c479 100644 --- a/src/usr/lib64/python2.7/site-packages/qubes/modules/007FortressQubesProxyVm.py +++ b/src/usr/lib64/python2.7/site-packages/qubes/modules/007FortressQubesProxyVm.py @@ -96,35 +96,45 @@ class QubesProxyVm(OriginalQubesProxyVm): rules_action = accept_action for rule in conf["rules"]: - if getattr(vm, "static_ip", None) and rule["address"].startswith("from-"): - ruletext = "-s {0} -d {1}".format(rule["address"][len("from-"):], ip) - if rule["netmask"] != 32: - ruletext += "/{0}".format(rule["netmask"]) + is_inbound = rule["address"].startswith("from-") and getattr(vm, "static_ip", None) + if is_inbound: + src_addr = rule["address"][len("from-"):] + src_mask = rule["netmask"] + dst_addr = ip + dst_mask = 32 + else: + src_addr = ip + src_mask = 32 + dst_addr = rule["address"] + dst_mask = rule["netmask"] - if rule["proto"] is not None and rule["proto"] != "any": - ruletext += " -p {0}".format(rule["proto"]) - if rule["portBegin"] is not None and rule["portBegin"] > 0: - ruletext += " --dport {0}".format(rule["portBegin"]) - if rule["portEnd"] is not None and rule["portEnd"] > rule["portBegin"]: - ruletext += ":{0}".format(rule["portEnd"]) + args = [] - ruletext += " -j {0}\n".format(rules_action) - iptables += "-A PR-QBS-FORWARD " + ruletext - vm_iptables += "-A FORTRESS-INPUT " + ruletext - continue + def constrain(sd, addr, mask): + if mask != 0: + if mask == 32: + args.append("{0} {1}".format(sd, addr)) + else: + args.append("{0} {1}/{2}".format(sd, addr, mask)) - iptables += "-A PR-QBS-FORWARD -s {0} -d {1}".format(ip, rule["address"]) - if rule["netmask"] != 32: - iptables += "/{0}".format(rule["netmask"]) + constrain("-s", src_addr, src_mask) + constrain("-d", dst_addr, dst_mask) if rule["proto"] is not None and rule["proto"] != "any": - iptables += " -p {0}".format(rule["proto"]) + args.append("-p {0}".format(rule["proto"])) if rule["portBegin"] is not None and rule["portBegin"] > 0: - iptables += " --dport {0}".format(rule["portBegin"]) if rule["portEnd"] is not None and rule["portEnd"] > rule["portBegin"]: - iptables += ":{0}".format(rule["portEnd"]) + portrange = "{0}:{1}".format(rule["portBegin"], rule["portEnd"]) + else: + portrange = rule["portBegin"] + args.append("--dport {0}".format(portrange)) - iptables += " -j {0}\n".format(rules_action) + args.append("-j {0}".format(rules_action)) + ruletext = ' '.join(args) + + iptables += "-A PR-QBS-FORWARD {0}\n".format(ruletext) + if is_inbound: + vm_iptables += "-A FORTRESS-INPUT {0}\n".format(ruletext) if conf["allowDns"] and self.netvm is not None: # PREROUTING does DNAT to NetVM DNSes, so we need self.netvm. diff --git a/src/usr/lib64/python2.7/site-packages/qubes/modules/qubes-appvm-firewall b/src/usr/lib64/python2.7/site-packages/qubes/modules/qubes-appvm-firewall index 60dd01f..9d14b6a 100755 --- a/src/usr/lib64/python2.7/site-packages/qubes/modules/qubes-appvm-firewall +++ b/src/usr/lib64/python2.7/site-packages/qubes/modules/qubes-appvm-firewall @@ -1,5 +1,27 @@ #!/usr/bin/env python +''' +This code is intended to replace the very fragile firewall generation code +that currently runs on dom0, by a lightweight daemon that applies the rules +on the AppVM (with static IP), responding to rule changes made by the +administrator on-the-fly. + +This daemon is injected into the VM as soon as qrexec capability becomes +available on the recently-started VM. The daemon: + +1. Reads the QubesDB key /qubes-fortress-iptables-rules. +2. Atomically applies the rules therein saved therein. + +The rules in /qubes-fortress-iptables-rules are generated by the dom0 code +in 007FortressQubesProxyVM, which in turn are based on the firewall rules +that the administrator has configured. These rules are generated and applied +at the same time as the rules generated and applied on the ProxyVM attached to +the AppVM, ensuring that the rules in the VM are kept in sync with the rules +in the ProxyVM at all times. + +FIXME: The previous paragraph is still a work in progress. +''' + import collections import logging import os