If you want to prevent in the qube from being able to do anything to enable the network, then you can do override the xen config and remove the network interface for qubes with specific feature set:
Create the /etc/qubes/templates/libvirt/xen-user.xml file in dom0 with this content:
{% extends 'libvirt/xen.xml' %}
{% block devices %}
{% if vm.features.get('disable_network', '0') != '1' %}
{{ super() }}
{% else -%}
{#
HACK: The letter counter is implemented in this way because
Jinja does not allow you to increment variables in a loop
anymore. As of Jinja 2.10, we will be able to replace this
with:
{% set counter = namespace(i=0) %}
{% set counter.i = counter.i + 1 %}
#}
{% set counter = {'i': 0} %}
{# TODO Allow more volumes out of the box #}
{% set dd = ['e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']
%}
{% for device in vm.block_devices %}
<disk type="block" device="{{ device.devtype }}">
<driver name="phy" />
<source dev="{{ device.path }}" />
{% if device.name == 'root' %}
<target dev="xvda" />
{% elif device.name == 'private' %}
<target dev="xvdb" />
{% elif device.name == 'volatile' %}
<target dev="xvdc" />
{% elif device.name == 'kernel' %}
<target dev="xvdd" />
{% else %}
<target dev="xvd{{dd[counter.i]}}" />
{% if counter.update({'i': counter.i + 1}) %}{% endif %}
{% endif %}
{% if not device.rw %}
<readonly />
{% endif %}
{% if device.domain %}
<backenddomain name="{{ device.domain }}" />
{% endif %}
<script path="/etc/xen/scripts/qubes-block" />
</disk>
{% endfor %}
{# start external devices from xvdi #}
{% set counter = {'i': 4} %}
{% for assignment in vm.devices.block.assignments(True) %}
{% set device = assignment.device %}
{% set options = assignment.options %}
{% include 'libvirt/devices/block.xml' %}
{% endfor %}
{% for assignment in vm.devices.pci.assignments(True) %}
{% set device = assignment.device %}
{% set options = assignment.options %}
{% set power_mgmt =
vm.app.domains[0].features.get('suspend-s0ix', False) %}
{% include 'libvirt/devices/pci.xml' %}
{% endfor %}
{% if vm.virt_mode == 'hvm' %}
<!-- server_ip is the address of stubdomain. It hosts it's own DNS server. -->
<emulator
{% if vm.features.check_with_template('linux-stubdom', True) %}
type="stubdom-linux"
{% else %}
type="stubdom"
{% endif %}
{% if vm.netvm %}
{% if vm.features.check_with_template('linux-stubdom', True) %}
cmdline="-qubes-audio:audiovm_xid={{ audiovm_xid }} -qubes-net:client_ip={{ vm.ip -}}
,dns_0={{ vm.dns[0] -}}
,dns_1={{ vm.dns[1] -}}
,gw={{ vm.netvm.gateway -}}
,netmask={{ vm.netmask }}"
{% else %}
cmdline="-qubes-audio:audiovm_xid={{ audiovm_xid }} -net lwip,client_ip={{ vm.ip -}}
,server_ip={{ vm.dns[1] -}}
,dns={{ vm.dns[0] -}}
,gw={{ vm.netvm.gateway -}}
,netmask={{ vm.netmask }}"
{% endif %}
{% else %}
cmdline="-qubes-audio:audiovm_xid={{ audiovm_xid }}"
{% endif %}
{% if vm.stubdom_mem %}
memory="{{ vm.stubdom_mem * 1024 -}}"
{% endif %}
{% if vm.features.check_with_template('audio-model', False)
or vm.features.check_with_template('stubdom-qrexec', False) %}
kernel="/usr/libexec/xen/boot/qemu-stubdom-linux-full-kernel"
ramdisk="/usr/libexec/xen/boot/qemu-stubdom-linux-full-rootfs"
{% endif %}
/>
<input type="tablet" bus="usb"/>
{% if vm.features.check_with_template('audio-model', False) %}
<sound model="{{ vm.features.check_with_template('audio-model', False) }}"/>
{% endif %}
{% if vm.features.check_with_template('video-model', 'vga') != 'none' %}
<video>
<model type="{{ vm.features.check_with_template('video-model', 'vga') }}"/>
</video>
{% if vm.features.check_with_template('linux-stubdom', True) %}
{# TODO only add qubes gui if gui-agent is not installed in HVM #}
<graphics type="qubes"/>
{% endif %}
{% endif %}
{% endif %}
<console type="pty">
<target type="xen" port="0"/>
</console>
{% endif %}
{% endblock %}
Then enable disable_network feature for your offline qube:
qvm-features my-offline-qube disable_network 1
The downside is that you’ll need to update the /etc/qubes/templates/libvirt/xen-user.xml file if the /etc/qubes/templates/libvirt/xen.xml will be changed in the future.
You’ll need to replace the {% block devices %} ... {% endblock %} content and remove these lines from it:
{% if vm.netvm %}
{% include 'libvirt/devices/net.xml' with context %}
{% endif %}
It won’t block traffic if the net qube doesn’t support Qubes OS firewall, for example, sys-whonix.