Traffic Analysis in Qubes OS

One of the best thing in Qubes OS that you can use special type of VMs called ProxyVM (or FirewallVM). The special thing is that your AppVMs see this as a NetVM, and the NetVMs see it as an AppVM.

Because of that You can place a ProxyVM between your AppVMs and Your NetVM. This way we can create an ideal topology for traffic analysis. One of the best applications for such task is Suricata. The free and open source, mature, fast and robust network threat detection engine. The Suricata engine is capable of real time intrusion detection (IDS), inline intrusion prevention (IPS), network security monitoring (NSM) and offline pcap processing – however this article only covers the Qubes integration of this product.


The recommended way is to create a new, separate template based on fedora-minimal. You need to install the following packages beside the optional  standard utilities:

suricata mate-notification-daemon dejavu-sans-fonts jq

If the template is ready (don’t forget the shutdown) let’s create a new virtual machine called ‘IDS’. It is important to choose the ProxyVM type, and have to be based on your newly created template. 2 vCPU, 1Gb of RAM, and the default 2Gb  private storage should be enough for getting started.

All of the further operations should be take place in you new ‘IDS’ ProxyVM!


Rules (or signatures) play a very important role in Suricata. In most occasions people are using existing rulesets. The most used are Emerging Threats and Sourcefire’s VRT. Suricata Rules document explains all about signatures; how to read-, adjust-and create them.

The Qubes specific part is that the default locations are non permanent, because we are using template based VM’s. So you have to download them on every boot, or move them to a the private storage. The /home/user/.config/ folder is a good place for that, and this will apply for the rest of my example configs.

Packet Filter

Even if we are having an ideal topology for traffic inspection we need some support from the packetfilter to be able to inspect all the forwarded packages. To be compatible with Qubes OS dynamic internal networking solution we have to add some new IPtables rules to this file: /rw/config/qubes-firewall-user-script

# NFQ rule for Suricata
iptables -I FORWARD -j NFQUEUE

We also have to ‘enable’ this script by making it executable:

$ sudo chmod +x /rw/config/qubes-firewall-user-script


Suricata uses the Yaml format for configuration. The Suricata.yaml file included in the installed package, is the example configuration of Suricata. It is wise to copy this file (too) to a folder on our private storage: /home/user/.config/suricata/ and modify at least the following lines:

HOME_NET: "[]"

default-rule-path: /home/user/.config/suricata/rules

classification-file: /home/user/.config/suricata/classification.config
reference-config-file: /home/user/.config/suricata/reference.config

default-log-dir: /home/user/.local/var/log/suricata/

Optionally you can enable some other logging options too:

 # a line based log of HTTP requests (no alerts)
  - http-log:
      enabled: yes
      filename: http.log
      append: yes

 # a line based log of TLS handshake parameters (no alerts)
  - tls-log:
      enabled: yes
      filename: tls.log
      append: yes

# a line based log of DNS requests and/or replies (no alerts)
  - dns-log:
      enabled: yes
      filename: dns.log

Of course those are just the bare minimum settings to be able to getting started. For more detailed configuration options can be found in the official documentation.

Running Suricata

For the first try we just start the suricata process from a terminal.

$ sudo suricata -c /home/user/.config/suricata/suricata.yaml -q 0 &

Later we would need a real service for the easy “auto start” – using Qubes Manager.

Receiving Alerts

If we successfully followed the instructions the suricata engine are already analyzing all the forwarded traffic. Of course we need at least one AppVM connected to our IDS ProxyVM to generate some actual traffic. Using this example config the results are collected in a single JSON file called eve.json. In general these data should be sent to a SIEM system for further correlation, however in our case we would like to see what happens right on our desktop. To achieve this we have to start the following monitoring “command”

$ sudo tail -f /home/.local/var/log/suricata/eve.json \
| jq --unbuffered -r -c 'select(.event_type=="alert")' \
| jq --unbuffered -r '@sh  "signature=\(.alert.signature) SRC=\(.src_ip) action=\(.alert.action)"' \
| while read -r line; \
do \
 eval $line; \
 notify-send  "$signature"  "$(echo -e "source:\t$SRC\naction:\t$action")" -t 50000 -i /usr/share/icons/Adwaita/48x48/status/software-update-urgent.png ;\
done &

Yeah it is pretty raw – but easy to understand. The main part is the jq command, which is parsing the JSON output. Then the notify-send will pop-up a visible alert with a brief description of the actual offense.

Of course this also should go into an easy switchable service – hopefully in the near future.

If we succeeding – and start browsing through this IDS ProxyVM – we gonna receive some DNS related offense for sure. Our next task is to eliminate this false alert caused by the way how  Qubes OS handles the DNS request inside the virtual network – but this gonna be documented in a separate article.