Browse Source

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
Marek Marczykowski-Górecki 6 years ago
parent
commit
b49ae50ad5

+ 3 - 0
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

+ 3 - 0
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

+ 1 - 1
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=""

+ 2 - 0
qubes-rpc/qubes.UpdatesProxy

@@ -0,0 +1,2 @@
+#!/bin/sh
+exec nc localhost 8082

+ 6 - 1
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

+ 115 - 0
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 $?
+

+ 1 - 0
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

+ 14 - 0
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

+ 7 - 0
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