ssh reverse tunnel for PXE, NFS and DHCP setup on Qubes OS

At some point I stuck in the forest with WiFi connection and no physical access to router to create nice networking for my coreboot development needs. Recently I switched my laptop to Qubes OS what give interesting flexibility, but also additional problems. My key requirement is to boot system over PXE, so I can easily do kernel development and play with Xen. Because only available connection for my apu2 platform was directly to my laptop I had to provide configured DHCP server and PXE server on it. Qubes OS networking is quite complex and to get to VM you have to pass-through at least sys-net VMs. Those VMs requires iptables configuration to correctly pass traffic or some tricks as I presented below. I don’t think much people will face so weird configuration, but I need following notes for myself and there is some chance that someone will face similar issues. To summarize my target configuration was like that:


My initial idea was to have servers on AppVMs, but I didn’t have enough time to get through Qubes OS iptables rules. That led to discover interesting alternative with proxychains, which I will describe later in this article.

Qubes OS network configuration

Let’s start with putting together DHCP server:

git clone
cd dhcp-server
 Please change your network interface in it doesn’t match. Currently set is eno1 what may be good for Ubuntu users. The only port that we have to forward for DHCP is 67.

sys-net setup My routing table look like that:

default via dev wls6 proto static metric 600 dev vif27.0 scope link metric 32725 dev docker0 proto kernel scope link src linkdown dev wls6 proto kernel scope link src metric 600

wls6 is my wireless interface. apu2 is connected over Ethernet cable using ens5 interface. Let’s assign static IP to it:

sudo ip addr add dev ens5
 Routing was added automatically:

default via dev wls6 proto static metric 600 dev vif27.0 scope link metric 32725 dev docker0 proto kernel scope link src linkdown dev wls6 proto kernel scope link src metric 600 dev ens5 proto kernel scope link src

After trying to correctly setup iptables in Qubes OS to forward traffic to vm where DHCP and PXE/NFS containers were started I decided to give up. It would be much easier to correctly setup sys-net for my development needs then spending hours on figuring out what is wrong with my IP tables.

git clone
cd dhcp-server
 Adjust your

dhcp.conf and to network configuration. In my case it was modified like below:

diff --git a/ b/
index fb257be..6de7283 100755
--- a/
+++ b/
@@ -14,6 +14,6 @@ docker run --rm --name dhcpserver --privileged --net=host
         -p 67:67/udp -p 67:67/tcp
         -v ${PWD}/data:/data
         -t -i 3mdeb/dhcp-server /bin/bash -c
-        "bash / eno1;/bin/bash"
+        "bash / ens5;/bin/bash"

diff --git a/data/dhcpd.conf b/data/dhcpd.conf
index 961aef58068d..788d80577c1d 100644
--- a/data/dhcpd.conf
+++ b/data/dhcpd.conf
@@ -1,4 +1,4 @@
-subnet netmask {
+subnet netmask {

        allow booting;
        allow bootp;
@@ -7,29 +7,33 @@ subnet netmask {

        option domain-name "";
        option subnet-mask;
-   option broadcast-address;
+ option broadcast-address;
        option domain-name-servers;
-   option routers;
+ option routers;

        # Group the PXE bootable hosts together
        group {
                # PXE-specific configuration directives...
-           next-server;
-           filename "pxelinux.0";
-           option root-path "/srv/nfs/freebsd";    
+         # next-server;
+         # filename "pxelinux.0";
+         # option root-path "/srv/nfs/freebsd";        
                # You need an entry like this for every host
                # unless you're using dynamic addresses
                host router {
                        hardware ethernet 00:02:72:41:35:87;
-                   fixed-address;
+                 fixed-address;
                host pxeserver {
                        hardware ethernet B8:CA:3A:A2:1B:3E;
-                   fixed-address;    
+                 fixed-address;
                host apu2 {
                        hardware ethernet 00:0D:B9:43:3F:BC;
-                   fixed-address;
+                 fixed-address;
+         }
+         host dhcp-server {
+                 hardware ethernet C8:5B:76:D0:FD:62;
+                 fixed-address;

On apu2 I booted to iPXE. I’m using v4.6.3.

iPXE> dhcp net0
Configuring (net0 00:0d:b9:43:3f:bc).................. ok
PXE> show net0/ip
net0.dhcp/ip:ipv4 =

Please note that MAC of my apu2 was already added to dhcp.conf. From that place I can go to run my PXE and NFS container.

PXE and NFS server

git clone
cd pxe-server

On iPXE side:


This gives couple options during boot:

---------------- iPXE boot menu ----------------
ipxe shell                                                                  
Debian stable netboot                                                       
TODO:Debian stable netinst                                                  
TODO:Debian testing netinst                                                 
TODO:Debian testing netinst (UEFI-aware)

Probably more will be available overtime.

Qubes OS ssh reverse tunnel and port forwarding

I had to resolve that problem just because of my lack of deep understanding of iptables and ability to reconfigure Qubes OS sys-net routing to handle that case. On the other hand below exercise was very engaging and for sure this solution can be used in some situations in future. Problem is that my apu2 cannot access outside world. This is because its only connection is to my laptop Ethernet port which is managed by sys-net VM and bunch of iptables rules. Flushing whole iptables configuration was not a solution, so I figured out how to create reverse ssh tunnel and use it to proxy whole traffic from apu2. The solution came with this stackoverflow answer. What we doing here is setting up SOCKS proxy and reverse SSH tunnel for apu2 traffic. On sys-net I did:

sudo passwd user #provide password
ssh -f -N -D 54321 localhost
ssh root@ -R 6666:localhost:54321

Then on apu2:

root@apu2:~# proxychains apt-get update
ProxyChains-3.1 (
0% [Working]|DNS-request|
|DNS-response| is
Ign:1 stable InRelease
Hit:2 stable Release
Reading package lists... Done

Please note that if, for some reason connection on sys-net will break then you will have problem resolving DNS. To fix that you have to remove incorrect default gateway. This have to be automated somehow on sys-net:

sudo ip r del default via

What we can do now?

You can use that configuration for many purposes, but my idea was to have Xen dom0 booting over PXE and NFS. I will describe that in other blog post.


I’m huge fan of Qubes OS and its approach to security. Unfortunately security typically came with less convenience, what can be problem in some situations. Nevertheless if you face some problems with Qubes OS, you need configuration or enabling support or you are interested in freeing your hardware setup, please do not hesitate to contact us. If you know how to reliably setup iptables in above situation we would be glad to test it.

Piotr Król
Founder and Embedded Systems Consultant at 3mdeb as well as freelance CTO of Vitro Technology and CEO of LPN Plant. Passionate about building firmware that enables advanced hardware features in modern products. Dedicated to customers that treat embedded software security and upgradeability as forethought. Open source firmware evangelist interested in platform security and trusted computing. In favor of fixed price projects with a clear definition of success.