From b49ae50ad571554c379dd79223e8466a669591d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 26 May 2017 03:07:47 +0200 Subject: [PATCH] Implement qrexec-based connection to updates proxy Configure package manager to use 127.0.0.1:8082 as proxy instead of "magic" IP intercepted later. The listen on this port and whenever new connection arrives, spawn qubes.UpdatesProxy service call (to default target domain - subject to configuration in dom0) and connect its stdin/out to the local TCP connection. This part use systemd.socket unit in case of systemd, and ncat --exec otherwise. On the other end - in target domain - simply pass stdin/out to updates proxy (tinyproxy) running locally. It's important to _not_ configure the same VM to both be updates proxy and use it. In practice such configuration makes little sense - if VM can access network (which is required to run updates proxy), package manager can use it directly. Even if this network access is through some VPN/Tor. If a single VM would be configured as both proxy provider and proxy user, connection would loop back to itself. Because of this, proxy connection redirection (to qrexec service) is disabled when the same VM also run updates proxy. Fixes QubesOS/qubes-issues#1854 --- Makefile | 3 + debian/qubes-core-agent.install | 3 + network/update-proxy-configs | 2 +- qubes-rpc/qubes.UpdatesProxy | 2 + rpm_spec/core-vm.spec | 7 +- vm-init.d/qubes-updates-proxy-forwarder | 115 ++++++++++++++++++ vm-systemd/75-qubes-vm.preset | 1 + .../qubes-updates-proxy-forwarder.socket | 14 +++ .../qubes-updates-proxy-forwarder@.service | 7 ++ 9 files changed, 152 insertions(+), 2 deletions(-) create mode 100755 qubes-rpc/qubes.UpdatesProxy create mode 100755 vm-init.d/qubes-updates-proxy-forwarder create mode 100644 vm-systemd/qubes-updates-proxy-forwarder.socket create mode 100644 vm-systemd/qubes-updates-proxy-forwarder@.service diff --git a/Makefile b/Makefile index 5e5a8d0..5a4476f 100644 --- a/Makefile +++ b/Makefile @@ -119,6 +119,7 @@ install-systemd: install-init install -d $(DESTDIR)$(SYSLIBDIR)/systemd/system{,-preset} $(DESTDIR)$(LIBDIR)/qubes/init $(DESTDIR)$(SYSLIBDIR)/modules-load.d install -m 0644 vm-systemd/qubes-*.service $(DESTDIR)$(SYSLIBDIR)/systemd/system/ install -m 0644 vm-systemd/qubes-*.timer $(DESTDIR)$(SYSLIBDIR)/systemd/system/ + install -m 0644 vm-systemd/qubes-*.socket $(DESTDIR)$(SYSLIBDIR)/systemd/system/ install -m 0644 vm-systemd/75-qubes-vm.preset $(DESTDIR)$(SYSLIBDIR)/systemd/system-preset/ install -m 0644 vm-systemd/qubes-core.conf $(DESTDIR)$(SYSLIBDIR)/modules-load.d/ install -m 0644 vm-systemd/qubes-misc.conf $(DESTDIR)$(SYSLIBDIR)/modules-load.d/ @@ -136,6 +137,7 @@ install-sysvinit: install-init install vm-init.d/qubes-qrexec-agent $(DESTDIR)/etc/init.d/ install vm-init.d/qubes-updates-proxy $(DESTDIR)/etc/init.d/ install vm-init.d/qubes-dvm $(DESTDIR)/etc/init.d/ + install vm-init.d/qubes-updates-proxy-forwarder $(DESTDIR)/etc/init.d/ install -D vm-init.d/qubes-core.modules $(DESTDIR)/etc/sysconfig/modules/qubes-core.modules install -D vm-init.d/qubes-misc.modules $(DESTDIR)/etc/sysconfig/modules/qubes-misc.modules install network/qubes-iptables $(DESTDIR)/etc/init.d/ @@ -268,6 +270,7 @@ install-common: install -m 0755 qubes-rpc/qubes.InstallUpdatesGUI $(DESTDIR)/etc/qubes-rpc install -m 0755 qubes-rpc/qubes.ResizeDisk $(DESTDIR)/etc/qubes-rpc install -m 0755 qubes-rpc/qubes.StartApp $(DESTDIR)/etc/qubes-rpc + install -m 0755 qubes-rpc/qubes.UpdatesProxy $(DESTDIR)/etc/qubes-rpc install -d $(DESTDIR)/etc/qubes/suspend-pre.d install -m 0644 qubes-rpc/suspend-pre.README $(DESTDIR)/etc/qubes/suspend-pre.d/README diff --git a/debian/qubes-core-agent.install b/debian/qubes-core-agent.install index 2f2c07e..7622fc6 100644 --- a/debian/qubes-core-agent.install +++ b/debian/qubes-core-agent.install @@ -30,6 +30,7 @@ etc/qubes-rpc/qubes.SuspendPostAll etc/qubes-rpc/qubes.SuspendPre etc/qubes-rpc/qubes.SuspendPreAll etc/qubes-rpc/qubes.SyncNtpClock +etc/qubes-rpc/qubes.UpdatesProxy etc/qubes-rpc/qubes.VMShell etc/qubes-rpc/qubes.WaitForSession etc/qubes-suspend-module-blacklist @@ -83,6 +84,8 @@ lib/systemd/system/qubes-sysinit.service lib/systemd/system/qubes-update-check.service lib/systemd/system/qubes-update-check.timer lib/systemd/system/qubes-updates-proxy.service +lib/systemd/system/qubes-updates-proxy-forwarder@.service +lib/systemd/system/qubes-updates-proxy-forwarder.socket lib/systemd/system/systemd-random-seed.service.d/30_qubes.conf lib/systemd/system/tinyproxy.service.d/30_not_needed_in_qubes_by_default.conf lib/systemd/system/tmp.mount.d/30_qubes.conf diff --git a/network/update-proxy-configs b/network/update-proxy-configs index 328b2b0..c5c7e50 100755 --- a/network/update-proxy-configs +++ b/network/update-proxy-configs @@ -75,7 +75,7 @@ EOF # Determine whether the proxy should be used if qsvc yum-proxy-setup || qsvc updates-proxy-setup ; then - PROXY_ADDR="http://10.137.255.254:8082/" + PROXY_ADDR="http://127.0.0.1:8082/" PROXY_CONF_ENTRY="proxy=$PROXY_ADDR" else PROXY_ADDR="" diff --git a/qubes-rpc/qubes.UpdatesProxy b/qubes-rpc/qubes.UpdatesProxy new file mode 100755 index 0000000..072eba8 --- /dev/null +++ b/qubes-rpc/qubes.UpdatesProxy @@ -0,0 +1,2 @@ +#!/bin/sh +exec nc localhost 8082 diff --git a/rpm_spec/core-vm.spec b/rpm_spec/core-vm.spec index 8f6d76d..6f97811 100644 --- a/rpm_spec/core-vm.spec +++ b/rpm_spec/core-vm.spec @@ -20,7 +20,7 @@ # # -%define qubes_services qubes-core qubes-core-netvm qubes-core-early qubes-firewall qubes-iptables qubes-updates-proxy qubes-qrexec-agent qubes-dvm +%define qubes_services qubes-core qubes-core-netvm qubes-core-early qubes-firewall qubes-iptables qubes-updates-proxy qubes-qrexec-agent qubes-dvm qubes-updates-proxy-forwarder %define qubes_preset_file 75-qubes-vm.preset %{!?version: %define version %(cat version)} @@ -124,6 +124,7 @@ Conflicts: firewalld Requires: xdg-utils Requires: ethtool Requires: tinyproxy +Requires: nmap-ncat Requires: ntpdate Requires: net-tools Requires: qubes-utils >= 3.1.3 @@ -440,6 +441,7 @@ rm -f %{name}-%{version} %config(noreplace) /etc/qubes-rpc/qubes.InstallUpdatesGUI %config(noreplace) /etc/qubes-rpc/qubes.ResizeDisk %config(noreplace) /etc/qubes-rpc/qubes.StartApp +%config(noreplace) /etc/qubes-rpc/qubes.UpdatesProxy %dir /etc/qubes/autostart /etc/qubes/autostart/README.txt %config /etc/qubes/autostart/*.desktop.d/30_qubes.conf @@ -576,6 +578,7 @@ The Qubes core startup configuration for SysV init (or upstart). /etc/init.d/qubes-iptables /etc/init.d/qubes-updates-proxy /etc/init.d/qubes-qrexec-agent +/etc/init.d/qubes-updates-proxy-forwarder /etc/sysconfig/modules/qubes-core.modules /etc/sysconfig/modules/qubes-misc.modules @@ -650,6 +653,8 @@ The Qubes core startup configuration for SystemD init. /lib/systemd/system/qubes-update-check.timer /lib/systemd/system/qubes-updates-proxy.service /lib/systemd/system/qubes-qrexec-agent.service +/lib/systemd/system/qubes-updates-proxy-forwarder@.service +/lib/systemd/system/qubes-updates-proxy-forwarder.socket /lib/systemd/system-preset/%qubes_preset_file /lib/modules-load.d/qubes-core.conf /lib/modules-load.d/qubes-misc.conf diff --git a/vm-init.d/qubes-updates-proxy-forwarder b/vm-init.d/qubes-updates-proxy-forwarder new file mode 100755 index 0000000..0c397ab --- /dev/null +++ b/vm-init.d/qubes-updates-proxy-forwarder @@ -0,0 +1,115 @@ +#!/bin/bash +# +# Updates proxy forwarder Startup script for the updates proxy forwarder +# +# chkconfig: 345 85 15 +# description: forwards connection to updates proxy over Qubes RPC +# +# processname: ncat +# pidfile: /var/run/qubes-updates-proxy-forwarder.pid +# + +# Source function library. +. /etc/rc.d/init.d/functions + +# Source Qubes library. +. /usr/lib/qubes/init/functions + +# Source networking configuration. +. /etc/sysconfig/network + +# Check that networking is up. +[ "$NETWORKING" = "no" ] && exit 0 + +exec="/usr/bin/ncat" +prog=$(basename $exec) +pidfile="/var/run/qubes-updates-proxy-forwarder.pid" + +[ -e /etc/sysconfig/qubes-updates-proxy-forwarder ] && . /etc/sysconfig/qubes-updates-proxy-forwarder + +lockfile=/var/lock/subsys/qubes-updates-proxy-forwarder + +start() { + have_qubesdb || return + + if ! qsvc updates-proxy-setup ; then + # updates proxy configuration disabled + exit 0 + fi + + if qsvc qubes-updates-proxy ; then + # updates proxy running here too, avoid looping traffic back to itself + exit 0 + fi + + [ -x $exec ] || exit 5 + + echo -n $"Starting $prog (as Qubes updates proxy forwarder): " + start-stop-daemon \ + --exec $exec \ + --pidfile "$pidfile" \ + --make-pidfile \ + --background \ + --start \ + -- \ + -k -l -e 'qrexec-client-vm $default qubes.UpdatesProxy' + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + killproc -p $pidfile $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +force_reload() { + restart +} + +rh_status() { + status $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|force-reload}" + exit 2 +esac +exit $? + diff --git a/vm-systemd/75-qubes-vm.preset b/vm-systemd/75-qubes-vm.preset index b411609..b6850bd 100644 --- a/vm-systemd/75-qubes-vm.preset +++ b/vm-systemd/75-qubes-vm.preset @@ -90,6 +90,7 @@ enable qubes-mount-dirs.service enable qubes-firewall.service enable qubes-meminfo-writer.service enable qubes-iptables.service +enable qubes-updates-proxy-forwarder.socket enable haveged.service enable chronyd.service enable xendriverdomain.service diff --git a/vm-systemd/qubes-updates-proxy-forwarder.socket b/vm-systemd/qubes-updates-proxy-forwarder.socket new file mode 100644 index 0000000..86f1e2b --- /dev/null +++ b/vm-systemd/qubes-updates-proxy-forwarder.socket @@ -0,0 +1,14 @@ +[Unit] +Description=Forward connection to updates proxy over Qubes RPC +ConditionPathExists=/var/run/qubes-service/updates-proxy-setup +# don't start the forwarder when updates proxy itself is also enabled here, +# otherwise it would most likely loop back to itself +ConditionPathExists=!/var/run/qubes-service/qubes-updates-proxy + +[Socket] +ListenStream=127.0.0.1:8082 +BindToDevice=lo +Accept=true + +[Install] +WantedBy=multi-user.target diff --git a/vm-systemd/qubes-updates-proxy-forwarder@.service b/vm-systemd/qubes-updates-proxy-forwarder@.service new file mode 100644 index 0000000..01d0658 --- /dev/null +++ b/vm-systemd/qubes-updates-proxy-forwarder@.service @@ -0,0 +1,7 @@ +[Unit] +Description=Forward connection to updates proxy over Qubes RPC + +[Service] +ExecStart=/usr/bin/qrexec-client-vm '' qubes.UpdatesProxy +StandardInput=socket +StandardOutput=inherit