From cb2858c0fc1df1c4fa2101a18dae7edb74f56c64 Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Thu, 5 Oct 2023 18:34:05 +0000 Subject: [PATCH 1/9] Add support for IPv6 Virtual DNS --- network/qubes-setup-dnat-to-ns | 36 +++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index 7a760a91..77ec34f8 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -23,7 +23,7 @@ from __future__ import annotations import dbus import qubesdb from typing import List -from ipaddress import IPv4Address +from ipaddress import ip_address, IPv4Address, IPv6Address import os def get_dns_resolv_conf(): @@ -38,7 +38,7 @@ def get_dns_resolv_conf(): if len(tokens) < 2 or tokens[0] != "nameserver": continue try: - nameservers.append(IPv4Address(tokens[1])) + nameservers.append(ip_address(tokens[1])) except ValueError: pass return nameservers @@ -69,9 +69,7 @@ def get_dns_resolved(): raise # Use global entries first dns.sort(key=lambda x: x[0] != 0) - # Only keep IPv4 entries. systemd-resolved is trusted to return valid - # addresses. - return [IPv4Address(bytes(addr)) for _g, family, addr in dns if family == 2] + return [IPv4Address(bytes(addr)) for _g, addr in dns] def install_firewall_rules(dns): qdb = qubesdb.QubesDB() @@ -81,7 +79,7 @@ def install_firewall_rules(dns): if ns_maybe is None: continue try: - qubesdb_dns.append(IPv4Address(ns_maybe.decode("ascii", "strict"))) + qubesdb_dns.append(ip_address(ns_maybe.decode("ascii", "strict"))) except (UnicodeDecodeError, ValueError): pass res = [ @@ -98,13 +96,37 @@ def install_firewall_rules(dns): 'chain dnat-dns {', 'type nat hook prerouting priority dstnat; policy accept;', ] - for vm_nameserver, dest in zip(qubesdb_dns, get_dns_resolved()): + for vm_nameserver, dest in zip([dns_ip for dns_ip in qubesdb_dns if type(dns_ip) is IPv4Address], + [dns_ip for dns_ip in dns if type(dns_ip) is IPv4Address]): dns_ = str(dest) res += [ f"ip daddr {vm_nameserver} udp dport 53 dnat to {dns_}", f"ip daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", ] res += ["}\n}\n"] + if qdb.read('/qubes-ip6') is not None: + res += [ + 'add table ip6 qubes', + # Add the chain so that the subsequent delete will work. If the chain already + # exists this is a harmless no-op. + 'add chain ip6 qubes dnat-dns', + # Delete the chain so that if the chain already exists, it will be removed. + # The removal of the old chain and addition of the new one happen as a single + # atomic operation, so there is no period where neither chain is present or + # where both are present. + 'delete chain ip6 qubes dnat-dns', + 'table ip6 qubes {', + 'chain dnat-dns {', + 'type nat hook prerouting priority dstnat; policy accept;', + ] + for vm_nameserver, dest in zip([dns_ip for dns_ip in qubesdb_dns if type(dns_ip) is IPv6Address], + [dns_ip for dns_ip in dns if type(dns_ip) is IPv6Address]): + dns_ = str(dest) + res += [ + f"ip6 daddr {vm_nameserver} udp dport 53 dnat to {dns_}", + f"ip6 daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", + ] + res += ["}\n}\n"] os.execvp("nft", ("nft", "--", "\n".join(res))) if __name__ == '__main__': From 0aaad6a9a1bb011be0b065289814d952f5c114fd Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Fri, 6 Oct 2023 20:21:05 +0000 Subject: [PATCH 2/9] A small fix and add reject rules for forwarded DNS queries if there is nowhere to forward them to avoid DNS query timeouts. There are hardcoded Qubes OS Virtual DNS addresses which is bad but I couldn't think of an easy way out. --- network/qubes-setup-dnat-to-ns | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index 77ec34f8..7efcc9a1 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -26,6 +26,10 @@ from typing import List from ipaddress import ip_address, IPv4Address, IPv6Address import os +QUBES_IPV4_VIRT_NS1 = "10.139.1.1" +QUBES_IPV4_VIRT_NS2 = "10.139.1.2" +QUBES_IPV6_VIRT_NS1 = "fd09:24ef:4179::a8b:1" + def get_dns_resolv_conf(): nameservers = [] try: @@ -69,7 +73,7 @@ def get_dns_resolved(): raise # Use global entries first dns.sort(key=lambda x: x[0] != 0) - return [IPv4Address(bytes(addr)) for _g, addr in dns] + return [ip_address(bytes(addr)) for _g, addr in dns] def install_firewall_rules(dns): qdb = qubesdb.QubesDB() @@ -82,6 +86,8 @@ def install_firewall_rules(dns): qubesdb_dns.append(ip_address(ns_maybe.decode("ascii", "strict"))) except (UnicodeDecodeError, ValueError): pass + dns_ipv4_found = False + dns_ipv6_found = False res = [ 'add table ip qubes', # Add the chain so that the subsequent delete will work. If the chain already @@ -98,11 +104,19 @@ def install_firewall_rules(dns): ] for vm_nameserver, dest in zip([dns_ip for dns_ip in qubesdb_dns if type(dns_ip) is IPv4Address], [dns_ip for dns_ip in dns if type(dns_ip) is IPv4Address]): + dns_ipv4_found = True dns_ = str(dest) res += [ f"ip daddr {vm_nameserver} udp dport 53 dnat to {dns_}", f"ip daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", ] + if not dns_ipv4_found: + res += [ + f"ip daddr {QUBES_IPV4_VIRT_NS1} tcp dport 53 reject with icmp type host-unreachable", + f"ip daddr {QUBES_IPV4_VIRT_NS1} udp dport 53 reject with icmp type host-unreachable", + f"ip daddr {QUBES_IPV4_VIRT_NS2} tcp dport 53 reject with icmp type host-unreachable", + f"ip daddr {QUBES_IPV4_VIRT_NS2} udp dport 53 reject with icmp type host-unreachable", + ] res += ["}\n}\n"] if qdb.read('/qubes-ip6') is not None: res += [ @@ -121,11 +135,17 @@ def install_firewall_rules(dns): ] for vm_nameserver, dest in zip([dns_ip for dns_ip in qubesdb_dns if type(dns_ip) is IPv6Address], [dns_ip for dns_ip in dns if type(dns_ip) is IPv6Address]): + dns_ipv6_found = True dns_ = str(dest) res += [ f"ip6 daddr {vm_nameserver} udp dport 53 dnat to {dns_}", f"ip6 daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", ] + if not dns_ipv6_found: + res += [ + f"ip6 daddr {QUBES_IPV6_VIRT_NS1} tcp dport 53 reject with icmpv6 type addr-unreachable", + f"ip6 daddr {QUBES_IPV6_VIRT_NS1} udp dport 53 reject with icmpv6 type addr-unreachable", + ] res += ["}\n}\n"] os.execvp("nft", ("nft", "--", "\n".join(res))) From d659bfbdcaf65262c4678e9ff8f5705abb912096 Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Fri, 6 Oct 2023 20:42:29 +0000 Subject: [PATCH 3/9] Don't fail if there are no DNS available. This is a necessary part for code that only add Virtual DNS servers to qubes that have netvm set and don't add DNS to every qube that provides network (sys-net/sys-usb/etc). --- network/vif-route-qubes | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/vif-route-qubes b/network/vif-route-qubes index 1bcb26d1..3f812845 100755 --- a/network/vif-route-qubes +++ b/network/vif-route-qubes @@ -70,8 +70,8 @@ if [ "${ip}" ]; then netvm_ip="$ip4" netvm_gw_ip=$(qubesdb-read /qubes-netvm-gateway) netvm_gw_ip6=$(qubesdb-read /qubes-netvm-gateway6 || :) - netvm_dns1_ip=$(qubesdb-read /qubes-netvm-primary-dns) - netvm_dns2_ip=$(qubesdb-read /qubes-netvm-secondary-dns) + netvm_dns1_ip=$(qubesdb-read /qubes-netvm-primary-dns || :) + netvm_dns2_ip=$(qubesdb-read /qubes-netvm-secondary-dns || :) back_ip="$netvm_gw_ip" back_ip6="$netvm_gw_ip6" From c44f02c9daef9120355f5de1678ea1acd6a28169 Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Tue, 10 Oct 2023 08:44:17 +0000 Subject: [PATCH 4/9] Add IPv6 Virtual DNS support. Also some IPv6 fixes. --- network/qubes-setup-dnat-to-ns | 99 ++++++++++--------- network/setup-ip | 47 ++++++--- network/vif-route-qubes | 6 +- .../10-qubes-core-agent-features.sh | 5 + vm-systemd/network-proxy-setup.sh | 13 ++- 5 files changed, 108 insertions(+), 62 deletions(-) diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index 7efcc9a1..8b61ce80 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -23,13 +23,10 @@ from __future__ import annotations import dbus import qubesdb from typing import List +from itertools import zip_longest from ipaddress import ip_address, IPv4Address, IPv6Address import os -QUBES_IPV4_VIRT_NS1 = "10.139.1.1" -QUBES_IPV4_VIRT_NS2 = "10.139.1.2" -QUBES_IPV6_VIRT_NS1 = "fd09:24ef:4179::a8b:1" - def get_dns_resolv_conf(): nameservers = [] try: @@ -78,16 +75,23 @@ def get_dns_resolved(): def install_firewall_rules(dns): qdb = qubesdb.QubesDB() qubesdb_dns = [] + qubesdb_dns6 = [] for i in ('/qubes-netvm-primary-dns', '/qubes-netvm-secondary-dns'): ns_maybe = qdb.read(i) if ns_maybe is None: continue try: - qubesdb_dns.append(ip_address(ns_maybe.decode("ascii", "strict"))) + qubesdb_dns.append(IPv4Address(ns_maybe.decode("ascii", "strict"))) + except (UnicodeDecodeError, ValueError): + pass + for i in ('/qubes-netvm-primary-dns6', '/qubes-netvm-secondary-dns6'): + ns_maybe = qdb.read(i) + if ns_maybe is None: + continue + try: + qubesdb_dns6.append(IPv6Address(ns_maybe.decode("ascii", "strict"))) except (UnicodeDecodeError, ValueError): pass - dns_ipv4_found = False - dns_ipv6_found = False res = [ 'add table ip qubes', # Add the chain so that the subsequent delete will work. If the chain already @@ -102,51 +106,54 @@ def install_firewall_rules(dns): 'chain dnat-dns {', 'type nat hook prerouting priority dstnat; policy accept;', ] - for vm_nameserver, dest in zip([dns_ip for dns_ip in qubesdb_dns if type(dns_ip) is IPv4Address], - [dns_ip for dns_ip in dns if type(dns_ip) is IPv4Address]): - dns_ipv4_found = True + for i, (vm_nameserver, dest) in enumerate(zip_longest(qubesdb_dns, + [dns_ip for dns_ip in dns if type(dns_ip) is IPv4Address])): + if i >= len(qubesdb_dns): + break dns_ = str(dest) - res += [ - f"ip daddr {vm_nameserver} udp dport 53 dnat to {dns_}", - f"ip daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", - ] - if not dns_ipv4_found: - res += [ - f"ip daddr {QUBES_IPV4_VIRT_NS1} tcp dport 53 reject with icmp type host-unreachable", - f"ip daddr {QUBES_IPV4_VIRT_NS1} udp dport 53 reject with icmp type host-unreachable", - f"ip daddr {QUBES_IPV4_VIRT_NS2} tcp dport 53 reject with icmp type host-unreachable", - f"ip daddr {QUBES_IPV4_VIRT_NS2} udp dport 53 reject with icmp type host-unreachable", - ] + if dest is None or (vm_nameserver == dest and + qdb.read('/qubes-ip') is None): + res += [ + f"ip daddr {vm_nameserver} tcp dport 53 reject with icmp type host-unreachable", + f"ip daddr {vm_nameserver} udp dport 53 reject with icmp type host-unreachable", + ] + else: + res += [ + f"ip daddr {vm_nameserver} udp dport 53 dnat to {dns_}", + f"ip daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", + ] res += ["}\n}\n"] - if qdb.read('/qubes-ip6') is not None: - res += [ - 'add table ip6 qubes', - # Add the chain so that the subsequent delete will work. If the chain already - # exists this is a harmless no-op. - 'add chain ip6 qubes dnat-dns', - # Delete the chain so that if the chain already exists, it will be removed. - # The removal of the old chain and addition of the new one happen as a single - # atomic operation, so there is no period where neither chain is present or - # where both are present. - 'delete chain ip6 qubes dnat-dns', - 'table ip6 qubes {', - 'chain dnat-dns {', - 'type nat hook prerouting priority dstnat; policy accept;', - ] - for vm_nameserver, dest in zip([dns_ip for dns_ip in qubesdb_dns if type(dns_ip) is IPv6Address], - [dns_ip for dns_ip in dns if type(dns_ip) is IPv6Address]): - dns_ipv6_found = True - dns_ = str(dest) + res += [ + 'add table ip6 qubes', + # Add the chain so that the subsequent delete will work. If the chain already + # exists this is a harmless no-op. + 'add chain ip6 qubes dnat-dns', + # Delete the chain so that if the chain already exists, it will be removed. + # The removal of the old chain and addition of the new one happen as a single + # atomic operation, so there is no period where neither chain is present or + # where both are present. + 'delete chain ip6 qubes dnat-dns', + 'table ip6 qubes {', + 'chain dnat-dns {', + 'type nat hook prerouting priority dstnat; policy accept;', + ] + for i, (vm_nameserver, dest) in enumerate(zip_longest(qubesdb_dns6, + [dns_ip for dns_ip in dns if type(dns_ip) is IPv6Address])): + if i >= len(qubesdb_dns6): + break + dns_ = str(dest) + if dest is None or (vm_nameserver == dest and + qdb.read('/qubes-primary-dns6') is None): res += [ - f"ip6 daddr {vm_nameserver} udp dport 53 dnat to {dns_}", - f"ip6 daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", + f"ip6 daddr {vm_nameserver} tcp dport 53 reject with icmpv6 type addr-unreachable", + f"ip6 daddr {vm_nameserver} udp dport 53 reject with icmpv6 type addr-unreachable", ] - if not dns_ipv6_found: + else: res += [ - f"ip6 daddr {QUBES_IPV6_VIRT_NS1} tcp dport 53 reject with icmpv6 type addr-unreachable", - f"ip6 daddr {QUBES_IPV6_VIRT_NS1} udp dport 53 reject with icmpv6 type addr-unreachable", + f"ip6 daddr {vm_nameserver} udp dport 53 dnat to {dns_}", + f"ip6 daddr {vm_nameserver} tcp dport 53 dnat to {dns_}", ] - res += ["}\n}\n"] + res += ["}\n}\n"] os.execvp("nft", ("nft", "--", "\n".join(res))) if __name__ == '__main__': diff --git a/network/setup-ip b/network/setup-ip index 9ca34b2f..5b2d599e 100755 --- a/network/setup-ip +++ b/network/setup-ip @@ -25,7 +25,9 @@ configure_network () { local gateway6="$8" local primary_dns="$9" local secondary_dns="${10}" - local custom="${11}" + local primary_dns6="${11}" + local secondary_dns6="${12}" + local custom="${13}" /sbin/ip -- address replace "$ip/$netmask" dev "$INTERFACE" if [[ "$custom" = false ]]; then @@ -34,7 +36,7 @@ configure_network () { fi if [ -n "$ip6" ]; then /sbin/ip -- address replace "$ip6/$netmask6" dev "$INTERFACE" - if [[ "$custom" = false ]]; then + if [[ "$custom" = false ]] && [ -n "$gateway6" ]; then /sbin/ip -- neighbour replace to "$gateway6" dev "$INTERFACE" \ lladdr "$netvm_mac" nud permanent fi @@ -64,16 +66,21 @@ configure_network () { if [ -h /etc/resolv.conf ]; then rm -f /etc/resolv.conf fi - echo > /etc/resolv.conf + echo -n > /etc/resolv.conf if ! qsvc disable-dns-server ; then - echo "nameserver $primary_dns" > /etc/resolv.conf + if [ -n "$primary_dns6" ]; then + echo "nameserver $primary_dns6" >> /etc/resolv.conf + echo "nameserver $secondary_dns6" >> /etc/resolv.conf + fi + echo "nameserver $primary_dns" >> /etc/resolv.conf echo "nameserver $secondary_dns" >> /etc/resolv.conf fi fi if [ -x /usr/bin/resolvectl ] && \ systemctl is-enabled -q systemd-resolved.service && \ ! qsvc disable-dns-server ; then - resolvectl dns "$INTERFACE" "$primary_dns" "$secondary_dns" + resolvectl dns "$INTERFACE" "$primary_dns6" "$secondary_dns6" \ + "$primary_dns" "$secondary_dns" fi } @@ -88,7 +95,9 @@ configure_network_nm () { local gateway6="$8" local primary_dns="$9" local secondary_dns="${10}" - local custom="${11}" + local primary_dns6="${11}" + local secondary_dns6="${12}" + local custom="${13}" local prefix local prefix6 @@ -119,6 +128,9 @@ __EOF__ if ! qsvc disable-dns-server ; then ip4_nm_config="${ip4_nm_config} dns=${primary_dns};${secondary_dns}" + if [ -n "$primary_dns6" ]; then + ip6_nm_config="${ip6_nm_config} +dns=${primary_dns6};${secondary_dns6}" fi if ! qsvc disable-default-route ; then ip4_nm_config="${ip4_nm_config} @@ -171,7 +183,7 @@ __EOF__ lladdr "$netvm_mac" nud permanent fi if [ -n "$ip6" ]; then - if [[ "$custom" = false ]]; then + if [[ "$custom" = false ]] && [ -n "$gateway6" ]; then /sbin/ip -- neighbour replace to "$gateway6" dev "$INTERFACE" \ lladdr "$netvm_mac" nud permanent fi @@ -183,8 +195,17 @@ configure_qubes_ns() { #netmask=$(qubesdb-read /qubes-netvm-netmask) primary_dns=$(qubesdb-read /qubes-netvm-primary-dns 2>/dev/null || echo "$gateway") secondary_dns=$(qubesdb-read /qubes-netvm-secondary-dns) - echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns - echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns + primary_dns6=$(qubesdb-read /qubes-netvm-primary-dns6 ||:) + secondary_dns6=$(qubesdb-read /qubes-netvm-secondary-dns6 ||:) + if [ -n "$primary_dns6" ]; then + echo "NS1=$primary_dns6" > /var/run/qubes/qubes-ns + echo "NS2=$secondary_dns6" >> /var/run/qubes/qubes-ns + echo "NS3=$primary_dns" >> /var/run/qubes/qubes-ns + echo "NS4=$secondary_dns" >> /var/run/qubes/qubes-ns + else + echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns + echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns + fi /usr/lib/qubes/qubes-setup-dnat-to-ns } @@ -234,7 +255,7 @@ if [ "$ACTION" == "add" ]; then gateway=$(exec /usr/bin/qubesdb-read "${prefix}gateway") if ip6=$(exec /usr/bin/qubesdb-read "${prefix}ip6" 2>/dev/null); then netmask6=$(exec /usr/bin/qubesdb-read --default=128 "${prefix}netmask6") - gateway6=$(exec /usr/bin/qubesdb-read "${prefix}gateway6") + gateway6=$(/usr/bin/qubesdb-read "${prefix}gateway6" 2>/dev/null ||:) elif [[ "$?" != '2' ]]; then echo 'Could not check if IPv6 is enabled' >&2 exit 1 @@ -244,6 +265,8 @@ if [ "$ACTION" == "add" ]; then primary_dns=$(/usr/bin/qubesdb-read /qubes-primary-dns 2>/dev/null) || primary_dns= secondary_dns=$(/usr/bin/qubesdb-read /qubes-secondary-dns 2>/dev/null) || secondary_dns= + primary_dns6=$(/usr/bin/qubesdb-read /qubes-primary-dns6 2>/dev/null ||:) || primary_dns6= + secondary_dns6=$(/usr/bin/qubesdb-read /qubes-secondary-dns6 2>/dev/null ||:) || secondary_dns6= /usr/lib/systemd/systemd-sysctl \ "--prefix=/net/ipv4/conf/all" \ "--prefix=/net/ipv4/neigh/all" \ @@ -257,9 +280,9 @@ if [ "$ACTION" == "add" ]; then if [ -n "$ip4" ]; then # If NetworkManager is enabled, let it configure the network if qsvc network-manager && [ -e /usr/bin/nmcli ]; then - configure_network_nm "$MAC" "$INTERFACE" "$ip4" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" "$custom" + configure_network_nm "$MAC" "$INTERFACE" "$ip4" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" "$primary_dns6" "$secondary_dns6" "$custom" else - configure_network "$MAC" "$INTERFACE" "$ip4" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" "$custom" + configure_network "$MAC" "$INTERFACE" "$ip4" "$ip6" "$netmask" "$netmask6" "$gateway" "$gateway6" "$primary_dns" "$secondary_dns" "$primary_dns6" "$secondary_dns6" "$custom" fi network=$(qubesdb-read /qubes-netvm-network 2>/dev/null) || network= diff --git a/network/vif-route-qubes b/network/vif-route-qubes index 3f812845..34968cbd 100755 --- a/network/vif-route-qubes +++ b/network/vif-route-qubes @@ -70,8 +70,10 @@ if [ "${ip}" ]; then netvm_ip="$ip4" netvm_gw_ip=$(qubesdb-read /qubes-netvm-gateway) netvm_gw_ip6=$(qubesdb-read /qubes-netvm-gateway6 || :) - netvm_dns1_ip=$(qubesdb-read /qubes-netvm-primary-dns || :) - netvm_dns2_ip=$(qubesdb-read /qubes-netvm-secondary-dns || :) + netvm_dns1_ip=$(qubesdb-read /qubes-netvm-primary-dns) + netvm_dns2_ip=$(qubesdb-read /qubes-netvm-secondary-dns) + netvm_dns61_ip=$(qubesdb-read /qubes-netvm-primary-dns || :) + netvm_dns62_ip=$(qubesdb-read /qubes-netvm-secondary-dns || :) back_ip="$netvm_gw_ip" back_ip6="$netvm_gw_ip6" diff --git a/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh b/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh index 5104ca41..b7204e1a 100755 --- a/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh +++ b/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh @@ -37,6 +37,11 @@ advertise_systemd_service() { done } +if [ "$(cat /sys/module/ipv6/parameters/disable_ipv6 2>/dev/null)" == "0" ] && + [ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" == "0" ] ; then + qvm-features-request supported-feature.ipv6=1 +fi + advertise_systemd_service network-manager NetworkManager.service \ network-manager.service advertise_systemd_service modem-manager ModemManager.service diff --git a/vm-systemd/network-proxy-setup.sh b/vm-systemd/network-proxy-setup.sh index 0e20b4f5..e385196b 100755 --- a/vm-systemd/network-proxy-setup.sh +++ b/vm-systemd/network-proxy-setup.sh @@ -19,9 +19,18 @@ if [ "x$network" != "x" ]; then #netmask=$(qubesdb-read /qubes-netvm-netmask) primary_dns=$(qubesdb-read /qubes-netvm-primary-dns 2>/dev/null || echo "$gateway") secondary_dns=$(qubesdb-read /qubes-netvm-secondary-dns) + primary_dns6=$(qubesdb-read /qubes-netvm-primary-dns6 ||:) + secondary_dns6=$(qubesdb-read /qubes-netvm-secondary-dns6 ||:) modprobe netbk 2> /dev/null || modprobe xen-netback || "${modprobe_fail_cmd}" - echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns - echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns + if [ -n "$primary_dns6" ]; then + echo "NS1=$primary_dns6" > /var/run/qubes/qubes-ns + echo "NS2=$secondary_dns6" >> /var/run/qubes/qubes-ns + echo "NS3=$primary_dns" >> /var/run/qubes/qubes-ns + echo "NS4=$secondary_dns" >> /var/run/qubes/qubes-ns + else + echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns + echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns + fi /usr/lib/qubes/qubes-setup-dnat-to-ns echo "1" > /proc/sys/net/ipv4/ip_forward # enable also IPv6 forwarding, if IPv6 is enabled From 719b3933b51ae010037c0cb0e54768e55bc86fc3 Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Tue, 10 Oct 2023 10:19:58 +0000 Subject: [PATCH 5/9] Fix errors --- network/setup-ip | 17 +++++++++++------ network/vif-route-qubes | 2 -- .../10-qubes-core-agent-features.sh | 4 ++-- vm-systemd/network-proxy-setup.sh | 16 ++++++++++------ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/network/setup-ip b/network/setup-ip index cfc0fc21..8836d822 100755 --- a/network/setup-ip +++ b/network/setup-ip @@ -131,6 +131,7 @@ dns=${primary_dns};${secondary_dns}" if [ -n "$primary_dns6" ]; then ip6_nm_config="${ip6_nm_config} dns=${primary_dns6};${secondary_dns6}" + fi fi if ! qsvc disable-default-route ; then ip4_nm_config="${ip4_nm_config} @@ -198,13 +199,17 @@ configure_qubes_ns() { primary_dns6=$(qubesdb-read /qubes-netvm-primary-dns6 ||:) secondary_dns6=$(qubesdb-read /qubes-netvm-secondary-dns6 ||:) if [ -n "$primary_dns6" ]; then - echo "NS1=$primary_dns6" > /var/run/qubes/qubes-ns - echo "NS2=$secondary_dns6" >> /var/run/qubes/qubes-ns - echo "NS3=$primary_dns" >> /var/run/qubes/qubes-ns - echo "NS4=$secondary_dns" >> /var/run/qubes/qubes-ns + cat > /var/run/qubes/qubes-ns<< EOF +NS1=$primary_dns6 +NS1=$secondary_dns6 +NS3=$primary_dns +NS4=$secondary_dns +EOF else - echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns - echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns + cat > /var/run/qubes/qubes-ns<< EOF +NS1=$primary_dns +NS1=$secondary_dns +EOF fi /usr/lib/qubes/qubes-setup-dnat-to-ns } diff --git a/network/vif-route-qubes b/network/vif-route-qubes index 34968cbd..1bcb26d1 100755 --- a/network/vif-route-qubes +++ b/network/vif-route-qubes @@ -72,8 +72,6 @@ if [ "${ip}" ]; then netvm_gw_ip6=$(qubesdb-read /qubes-netvm-gateway6 || :) netvm_dns1_ip=$(qubesdb-read /qubes-netvm-primary-dns) netvm_dns2_ip=$(qubesdb-read /qubes-netvm-secondary-dns) - netvm_dns61_ip=$(qubesdb-read /qubes-netvm-primary-dns || :) - netvm_dns62_ip=$(qubesdb-read /qubes-netvm-secondary-dns || :) back_ip="$netvm_gw_ip" back_ip6="$netvm_gw_ip6" diff --git a/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh b/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh index b7204e1a..9e3a8e0b 100755 --- a/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh +++ b/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh @@ -37,8 +37,8 @@ advertise_systemd_service() { done } -if [ "$(cat /sys/module/ipv6/parameters/disable_ipv6 2>/dev/null)" == "0" ] && - [ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" == "0" ] ; then +if [ "$(cat /sys/module/ipv6/parameters/disable_ipv6 2>/dev/null)" = "0" ] && + [ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" = "0" ] ; then qvm-features-request supported-feature.ipv6=1 fi diff --git a/vm-systemd/network-proxy-setup.sh b/vm-systemd/network-proxy-setup.sh index e385196b..87b34c79 100755 --- a/vm-systemd/network-proxy-setup.sh +++ b/vm-systemd/network-proxy-setup.sh @@ -23,13 +23,17 @@ if [ "x$network" != "x" ]; then secondary_dns6=$(qubesdb-read /qubes-netvm-secondary-dns6 ||:) modprobe netbk 2> /dev/null || modprobe xen-netback || "${modprobe_fail_cmd}" if [ -n "$primary_dns6" ]; then - echo "NS1=$primary_dns6" > /var/run/qubes/qubes-ns - echo "NS2=$secondary_dns6" >> /var/run/qubes/qubes-ns - echo "NS3=$primary_dns" >> /var/run/qubes/qubes-ns - echo "NS4=$secondary_dns" >> /var/run/qubes/qubes-ns + cat > /var/run/qubes/qubes-ns<< EOF +NS1=$primary_dns6 +NS1=$secondary_dns6 +NS3=$primary_dns +NS4=$secondary_dns +EOF else - echo "NS1=$primary_dns" > /var/run/qubes/qubes-ns - echo "NS2=$secondary_dns" >> /var/run/qubes/qubes-ns + cat > /var/run/qubes/qubes-ns<< EOF +NS1=$primary_dns +NS1=$secondary_dns +EOF fi /usr/lib/qubes/qubes-setup-dnat-to-ns echo "1" > /proc/sys/net/ipv4/ip_forward From 517fb4b7116f65c02027d91259205368fe95a0e4 Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Tue, 10 Oct 2023 14:23:07 +0000 Subject: [PATCH 6/9] Remove feature supported-feature.ipv6 and add feature supported-feature.ipv6dns --- qubes-rpc/post-install.d/10-qubes-core-agent-features.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh b/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh index 9e3a8e0b..d6a99e1b 100755 --- a/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh +++ b/qubes-rpc/post-install.d/10-qubes-core-agent-features.sh @@ -37,10 +37,7 @@ advertise_systemd_service() { done } -if [ "$(cat /sys/module/ipv6/parameters/disable_ipv6 2>/dev/null)" = "0" ] && - [ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" = "0" ] ; then - qvm-features-request supported-feature.ipv6=1 -fi +qvm-features-request supported-feature.ipv6dns=1 advertise_systemd_service network-manager NetworkManager.service \ network-manager.service From 41a13ceeb202c42db97e8b1473ffb16a2e1f69ba Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Tue, 10 Oct 2023 18:24:30 +0000 Subject: [PATCH 7/9] Add custom-dnat-dns chain --- network/qubes-setup-dnat-to-ns | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index 8b61ce80..683ef1d5 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -103,8 +103,10 @@ def install_firewall_rules(dns): # where both are present. 'delete chain ip qubes dnat-dns', 'table ip qubes {', + 'chain custom-dnat-dns {}', 'chain dnat-dns {', 'type nat hook prerouting priority dstnat; policy accept;', + 'jump custom-dnat-dns', ] for i, (vm_nameserver, dest) in enumerate(zip_longest(qubesdb_dns, [dns_ip for dns_ip in dns if type(dns_ip) is IPv4Address])): @@ -134,8 +136,10 @@ def install_firewall_rules(dns): # where both are present. 'delete chain ip6 qubes dnat-dns', 'table ip6 qubes {', + 'chain custom-dnat-dns {}', 'chain dnat-dns {', 'type nat hook prerouting priority dstnat; policy accept;', + 'jump custom-dnat-dns', ] for i, (vm_nameserver, dest) in enumerate(zip_longest(qubesdb_dns6, [dns_ip for dns_ip in dns if type(dns_ip) is IPv6Address])): From 3f2f25c1c6b1d4f7cbaedbd21768e13274fdc929 Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Sun, 29 Oct 2023 08:30:45 +0000 Subject: [PATCH 8/9] Fix getting dns from systemd-resolved --- network/qubes-setup-dnat-to-ns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index 683ef1d5..764cb407 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -70,7 +70,7 @@ def get_dns_resolved(): raise # Use global entries first dns.sort(key=lambda x: x[0] != 0) - return [ip_address(bytes(addr)) for _g, addr in dns] + return [ip_address(bytes(addr)) for _g, family, addr in dns] def install_firewall_rules(dns): qdb = qubesdb.QubesDB() From 7a1ed15b93c1af72a6230e5fbd123b869f64788b Mon Sep 17 00:00:00 2001 From: 1cho1ce <1choice4u@proton.me> Date: Sun, 29 Oct 2023 08:48:10 +0000 Subject: [PATCH 9/9] Restore removed comment --- network/qubes-setup-dnat-to-ns | 1 + 1 file changed, 1 insertion(+) diff --git a/network/qubes-setup-dnat-to-ns b/network/qubes-setup-dnat-to-ns index 764cb407..0f639da8 100755 --- a/network/qubes-setup-dnat-to-ns +++ b/network/qubes-setup-dnat-to-ns @@ -70,6 +70,7 @@ def get_dns_resolved(): raise # Use global entries first dns.sort(key=lambda x: x[0] != 0) + # systemd-resolved is trusted to return valid addresses. return [ip_address(bytes(addr)) for _g, family, addr in dns] def install_firewall_rules(dns):