diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index aba447c77..74fb286f9 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -141,6 +141,12 @@ def install_firewall_rules(dns): if old_rules == rules: 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_} }}") + os.execvp("nft", ("nft", "--", "\n".join(preamble + rules))) if __name__ == '__main__': diff --git a/qubesagent/firewall.py b/qubesagent/firewall.py index 9ffc5f9d3..5a43faaab 100755 --- a/qubesagent/firewall.py +++ b/qubesagent/firewall.py @@ -484,8 +484,6 @@ def prepare_rules(self, chain, rules, family): fullmask = '/128' if family == 6 else '/32' - dns = list(addr + fullmask for addr in self.dns_addresses(family)) - ret_dns = {} for rule in rules: @@ -541,10 +539,7 @@ def prepare_rules(self, chain, rules, family): continue else: dstports = '53' - if not dns: - continue - nft_rule += ' {} daddr {{ {} }}'.format(ip_match, ', '.join( - dns)) + nft_rule += ' {} daddr @dns-addr'.format(ip_match) if 'icmptype' in rule: if family == 4: @@ -570,7 +565,11 @@ def prepare_rules(self, chain, rules, family): else: nft_rules.append(nft_rule + ' ' + action) + dns = list(self.dns_addresses(family)) + return ( + 'flush set {family} {table} dns-addr\n' + '{add_dns_c}add element {family} {table} dns-addr {{ {add_dns_addrs} }}\n' 'flush chain {family} {table} {chain}\n' 'table {family} {table} {{\n' ' chain {chain} {{\n' @@ -580,7 +579,9 @@ def prepare_rules(self, chain, rules, family): family=('ip6' if family == 6 else 'ip'), table='qubes-firewall', chain=chain, - rules='\n '.join(nft_rules) + rules='\n '.join(nft_rules), + add_dns_c='#' if len(dns) == 0 else '', + add_dns_addrs=', '.join(dns) ), ret_dns) def apply_rules_family(self, source, rules, family): @@ -617,6 +618,9 @@ def apply_rules(self, source, rules): def init(self): nft_init = ( 'table {family} qubes-firewall {{\n' + ' set dns-addr {{\n' + ' type ipv{family_num}_addr\n' + ' }}\n' ' chain qubes-forward {{\n' ' }}\n' ' chain forward {{\n' @@ -637,7 +641,10 @@ def init(self): '}}\n' ) nft_init = ''.join( - nft_init.format(family=family) for family in ('ip', 'ip6')) + nft_init.format( + family_num=family_num, + family='ip6' if family_num == 6 else 'ip') + for family_num in (4, 6)) self.run_nft(nft_init) def cleanup(self): diff --git a/qubesagent/test_firewall.py b/qubesagent/test_firewall.py index e6100dbbc..a949ef1be 100644 --- a/qubesagent/test_firewall.py +++ b/qubesagent/test_firewall.py @@ -232,15 +232,17 @@ def test_002_prepare_rules4(self): {'action': 'drop'}, ] expected_nft = ( + 'flush set ip qubes-firewall dns-addr\n' + 'add element ip qubes-firewall dns-addr { 1.1.1.1, 2.2.2.2 }\n' 'flush chain ip qubes-firewall chain\n' 'table ip qubes-firewall {\n' ' chain chain {\n' ' ip protocol tcp ip daddr 1.2.3.0/24 tcp dport 80 accept\n' ' ip protocol udp ip daddr { 193.219.28.150/32 } ' 'udp dport 443-1024 accept\n' - ' ip daddr { 1.1.1.1/32, 2.2.2.2/32 } tcp dport 53 accept\n' - ' ip daddr { 1.1.1.1/32, 2.2.2.2/32 } udp dport 53 accept\n' - ' ip protocol udp ip daddr { 1.1.1.1/32, 2.2.2.2/32 } udp dport ' + ' ip daddr @dns-addr tcp dport 53 accept\n' + ' ip daddr @dns-addr udp dport 53 accept\n' + ' ip protocol udp ip daddr @dns-addr udp dport ' '53 reject with icmp type admin-prohibited\n' ' ip protocol icmp reject with icmp type admin-prohibited\n' ' reject with icmp type admin-prohibited\n' @@ -269,15 +271,17 @@ def test_003_prepare_rules6(self): {'action': 'drop'}, ] expected_nft = ( + 'flush set ip6 qubes-firewall dns-addr\n' + 'add element ip6 qubes-firewall dns-addr { 2001::1, 2001::2 }\n' 'flush chain ip6 qubes-firewall chain\n' 'table ip6 qubes-firewall {\n' ' chain chain {\n' ' ip6 nexthdr tcp ip6 daddr a::b/128 tcp dport 80 accept\n' ' ip6 nexthdr tcp ip6 daddr { 2001:67c:2e8:25::c100:b33/128 } ' 'accept\n' - ' ip6 daddr { 2001::1/128, 2001::2/128 } tcp dport 53 accept\n' - ' ip6 daddr { 2001::1/128, 2001::2/128 } udp dport 53 accept\n' - ' ip6 nexthdr udp ip6 daddr { 2001::1/128, 2001::2/128 } ' + ' ip6 daddr @dns-addr tcp dport 53 accept\n' + ' ip6 daddr @dns-addr udp dport 53 accept\n' + ' ip6 nexthdr udp ip6 daddr @dns-addr ' 'udp dport 53 reject with icmpv6 type admin-prohibited\n' ' ip6 nexthdr icmpv6 icmpv6 type 128 reject with icmpv6 type ' 'admin-prohibited\n' @@ -314,6 +318,9 @@ def test_006_init(self): self.assertEqual(self.obj.loaded_rules, [ 'table ip qubes-firewall {\n' + ' set dns-addr {\n' + ' type ipv4_addr\n' + ' }\n' ' chain qubes-forward {\n' ' }\n' ' chain forward {\n' @@ -333,6 +340,9 @@ def test_006_init(self): ' }\n' '}\n' 'table ip6 qubes-firewall {\n' + ' set dns-addr {\n' + ' type ipv6_addr\n' + ' }\n' ' chain qubes-forward {\n' ' }\n' ' chain forward {\n'