Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions network/qubes-setup-dnat-to-ns
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ def install_firewall_rules(dns):
sys.exit(100)

if os.path.exists('/run/qubes-service/qubes-firewall'):
rules.append("flush set ip qubes-firewall dns-addr")
if len(dns_resolved) > 0:
dns_ = ", ".join(str(addr) for addr in dns_resolved)
rules.append(f"add element ip qubes-firewall dns-addr {{ {dns_} }}")
subprocess.call(["systemctl",
"--no-block",
"try-reload-or-restart",
"qubes-firewall.service"
])

os.execvp("nft", ("nft", "--", "\n".join(preamble + rules)))

Expand Down
47 changes: 33 additions & 14 deletions qubesagent/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import subprocess
import pwd
import shutil
import time

import qubesdb
import sys
Expand Down Expand Up @@ -342,6 +343,7 @@ def dns_addresses(family=None):

def main(self):
self.terminate_requested = False
self.reload_requested = False
self.init()
self.run_firewall_dir()
if not self.is_custom_persist_enabled():
Expand All @@ -355,29 +357,45 @@ def main(self):
self.handle_addr(source_addr)
self.update_connected_ips(4)
self.update_connected_ips(6)
try:
for watch_path in iter(self.qdb.read_watch, None):
if watch_path == '/connected-ips':
self.update_connected_ips(4)
while not self.terminate_requested:
if self.reload_requested:
clock_monotonic = time.clock_gettime(time.CLOCK_MONOTONIC)
clock_monotonic = int(clock_monotonic * 1_000_000)
self.sd_notify(f'RELOADING=1\nMONOTONIC_USEC={clock_monotonic}')
for source_addr in self.list_targets():
self.handle_addr(source_addr)
self.reload_requested = False
self.sd_notify('READY=1')
try:
watch_path = self.qdb.read_watch()
except OSError: # EINTR
# signal received, re-check loop condition
continue

if watch_path == '/connected-ips6':
self.update_connected_ips(6)
if watch_path is None:
break

# ignore writing rules itself - wait for final write at
# source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
if watch_path.startswith('/qubes-firewall/') and watch_path.count('/') == 2:
source_addr = watch_path.split('/')[2]
self.handle_addr(source_addr)
if watch_path == '/connected-ips':
self.update_connected_ips(4)

if watch_path == '/connected-ips6':
self.update_connected_ips(6)

# ignore writing rules itself - wait for final write at
# source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
if watch_path.startswith('/qubes-firewall/') and watch_path.count('/') == 2:
source_addr = watch_path.split('/')[2]
self.handle_addr(source_addr)

except OSError: # EINTR
# signal received, don't continue the loop
pass

self.cleanup()

def terminate(self):
self.terminate_requested = True

def reload(self):
self.reload_requested = True

class NftablesWorker(FirewallWorker):
supported_rule_opts = ['action', 'proto', 'dst4', 'dst6', 'dsthost',
'dstports', 'specialtarget', 'icmptype']
Expand Down Expand Up @@ -662,6 +680,7 @@ def main():
print('Sorry, iptables no longer supported', file=sys.stderr)
sys.exit(1)
signal.signal(signal.SIGTERM, lambda _signal, _stack: worker.terminate())
signal.signal(signal.SIGHUP, lambda _signal, _stack: worker.reload())
worker.main()


Expand Down
2 changes: 1 addition & 1 deletion vm-systemd/qubes-firewall.service
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ After=qubes-iptables.service
Before=qubes-network.service

[Service]
Type=notify
Type=notify-reload
ExecStart=/usr/bin/qubes-firewall

[Install]
Expand Down