From: Malina Salina <malina.sal...@protonmail.com> While the default iptables setup used by Fedora/RHEL distros only restricts traffic on the INPUT and/or FORWARD rules, some users might have custom firewalls that restrict the OUTPUT rules too.
These can prevent DHCP/DNS/TFTP responses from dnsmasq from reaching the guest VMs. We should thus whitelist these protocols in the OUTPUT chain, as well as the INPUT chain. Signed-off-by: Malina Salina <malina.sal...@protonmail.com> Initial patch then modified to add unit tests and IPv6 support Signed-off-by: Daniel P. Berrangé <berra...@redhat.com> --- src/libvirt_private.syms | 2 + src/network/bridge_driver_linux.c | 29 ++++++++++--- src/util/viriptables.c | 36 ++++++++++++++++ src/util/viriptables.h | 8 ++++ .../nat-default-linux.args | 21 ++++++++++ .../nat-ipv6-linux.args | 42 +++++++++++++++++++ .../nat-many-ips-linux.args | 21 ++++++++++ .../nat-no-dhcp-linux.args | 42 +++++++++++++++++++ .../nat-tftp-linux.args | 28 +++++++++++++ .../route-default-linux.args | 21 ++++++++++ 10 files changed, 244 insertions(+), 6 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7b681fac64..83b97af364 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2186,6 +2186,7 @@ iptablesAddForwardRejectIn; iptablesAddForwardRejectOut; iptablesAddOutputFixUdpChecksum; iptablesAddTcpInput; +iptablesAddTcpOutput; iptablesAddUdpInput; iptablesAddUdpOutput; iptablesRemoveDontMasquerade; @@ -2198,6 +2199,7 @@ iptablesRemoveForwardRejectIn; iptablesRemoveForwardRejectOut; iptablesRemoveOutputFixUdpChecksum; iptablesRemoveTcpInput; +iptablesRemoveTcpOutput; iptablesRemoveUdpInput; iptablesRemoveUdpOutput; iptablesSetDeletePrivate; diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c index 35459c10d1..0b6ff45b17 100644 --- a/src/network/bridge_driver_linux.c +++ b/src/network/bridge_driver_linux.c @@ -553,18 +553,23 @@ networkAddGeneralIPv4FirewallRules(virFirewallPtr fw, break; } - /* allow DHCP requests through to dnsmasq */ + /* allow DHCP requests through to dnsmasq & back out */ iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); + iptablesAddTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68); iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68); - /* allow DNS requests through to dnsmasq */ + /* allow DNS requests through to dnsmasq & back out */ iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); + iptablesAddTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); + iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); - /* allow TFTP requests through to dnsmasq if necessary */ - if (ipv4def && ipv4def->tftproot) + /* allow TFTP requests through to dnsmasq if necessary & back out*/ + if (ipv4def && ipv4def->tftproot) { iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); + iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); + } /* Catch all rules to block forwarding to/from bridges */ iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); @@ -592,13 +597,18 @@ networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw, iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); - if (ipv4def && ipv4def->tftproot) + if (ipv4def && ipv4def->tftproot) { iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); + iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); + } iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); + iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); + iptablesRemoveTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53); iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68); + iptablesRemoveTcpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68); iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); } @@ -626,10 +636,14 @@ networkAddGeneralIPv6FirewallRules(virFirewallPtr fw, iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge); if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) { - /* allow DNS over IPv6 */ + /* allow DNS over IPv6 & back out */ iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + iptablesAddTcpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + /* allow DHCPv6 & back out */ iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547); + iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 546); } } @@ -643,7 +657,10 @@ networkRemoveGeneralIPv6FirewallRules(virFirewallPtr fw, } if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) { + iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 546); iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547); + iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); + iptablesRemoveTcpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); } diff --git a/src/util/viriptables.c b/src/util/viriptables.c index 0e3c0ad73a..46d0c3df7a 100644 --- a/src/util/viriptables.c +++ b/src/util/viriptables.c @@ -303,6 +303,42 @@ iptablesRemoveUdpInput(virFirewallPtr fw, iptablesInput(fw, layer, deletePrivate, iface, port, REMOVE, 0); } +/** + * iptablesAddTcpOutput: + * @ctx: pointer to the IP table context + * @iface: the interface name + * @port: the TCP port to add + * + * Add an output to the IP table allowing access to the given @port from + * the given @iface interface for TCP packets + */ +void +iptablesAddTcpOutput(virFirewallPtr fw, + virFirewallLayer layer, + const char *iface, + int port) +{ + iptablesOutput(fw, layer, true, iface, port, ADD, 1); +} + +/** + * iptablesRemoveTcpOutput: + * @ctx: pointer to the IP table context + * @iface: the interface name + * @port: the UDP port to remove + * + * Removes an output from the IP table, hence forbidding access to the given + * @port from the given @iface interface for TCP packets + */ +void +iptablesRemoveTcpOutput(virFirewallPtr fw, + virFirewallLayer layer, + const char *iface, + int port) +{ + iptablesOutput(fw, layer, deletePrivate, iface, port, REMOVE, 1); +} + /** * iptablesAddUdpOutput: * @ctx: pointer to the IP table context diff --git a/src/util/viriptables.h b/src/util/viriptables.h index feea988acd..07b4851013 100644 --- a/src/util/viriptables.h +++ b/src/util/viriptables.h @@ -45,6 +45,14 @@ void iptablesRemoveUdpInput (virFirewallPtr fw, const char *iface, int port); +void iptablesAddTcpOutput (virFirewallPtr fw, + virFirewallLayer layer, + const char *iface, + int port); +void iptablesRemoveTcpOutput (virFirewallPtr fw, + virFirewallLayer layer, + const char *iface, + int port); void iptablesAddUdpOutput (virFirewallPtr fw, virFirewallLayer layer, const char *iface, diff --git a/tests/networkxml2firewalldata/nat-default-linux.args b/tests/networkxml2firewalldata/nat-default-linux.args index c9d523d043..ab18f30bd0 100644 --- a/tests/networkxml2firewalldata/nat-default-linux.args +++ b/tests/networkxml2firewalldata/nat-default-linux.args @@ -16,6 +16,13 @@ iptables \ --table filter \ --insert LIBVIRT_OUT \ --out-interface virbr0 \ +--protocol tcp \ +--destination-port 68 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ --protocol udp \ --destination-port 68 \ --jump ACCEPT @@ -35,6 +42,20 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_FWO \ --in-interface virbr0 \ --jump REJECT diff --git a/tests/networkxml2firewalldata/nat-ipv6-linux.args b/tests/networkxml2firewalldata/nat-ipv6-linux.args index a57b9266af..05d9ee33ca 100644 --- a/tests/networkxml2firewalldata/nat-ipv6-linux.args +++ b/tests/networkxml2firewalldata/nat-ipv6-linux.args @@ -16,6 +16,13 @@ iptables \ --table filter \ --insert LIBVIRT_OUT \ --out-interface virbr0 \ +--protocol tcp \ +--destination-port 68 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ --protocol udp \ --destination-port 68 \ --jump ACCEPT @@ -35,6 +42,20 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_FWO \ --in-interface virbr0 \ --jump REJECT @@ -81,11 +102,32 @@ ip6tables \ --jump ACCEPT ip6tables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +ip6tables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +ip6tables \ +--table filter \ --insert LIBVIRT_INP \ --in-interface virbr0 \ --protocol udp \ --destination-port 547 \ --jump ACCEPT +ip6tables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 546 \ +--jump ACCEPT iptables \ --table filter \ --insert LIBVIRT_FWO \ diff --git a/tests/networkxml2firewalldata/nat-many-ips-linux.args b/tests/networkxml2firewalldata/nat-many-ips-linux.args index 1bdc43fd6a..82e1380f51 100644 --- a/tests/networkxml2firewalldata/nat-many-ips-linux.args +++ b/tests/networkxml2firewalldata/nat-many-ips-linux.args @@ -16,6 +16,13 @@ iptables \ --table filter \ --insert LIBVIRT_OUT \ --out-interface virbr0 \ +--protocol tcp \ +--destination-port 68 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ --protocol udp \ --destination-port 68 \ --jump ACCEPT @@ -35,6 +42,20 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_FWO \ --in-interface virbr0 \ --jump REJECT diff --git a/tests/networkxml2firewalldata/nat-no-dhcp-linux.args b/tests/networkxml2firewalldata/nat-no-dhcp-linux.args index 7d359f3824..8954cc5473 100644 --- a/tests/networkxml2firewalldata/nat-no-dhcp-linux.args +++ b/tests/networkxml2firewalldata/nat-no-dhcp-linux.args @@ -16,6 +16,13 @@ iptables \ --table filter \ --insert LIBVIRT_OUT \ --out-interface virbr0 \ +--protocol tcp \ +--destination-port 68 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ --protocol udp \ --destination-port 68 \ --jump ACCEPT @@ -35,6 +42,20 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_FWO \ --in-interface virbr0 \ --jump REJECT @@ -81,11 +102,32 @@ ip6tables \ --jump ACCEPT ip6tables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +ip6tables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +ip6tables \ +--table filter \ --insert LIBVIRT_INP \ --in-interface virbr0 \ --protocol udp \ --destination-port 547 \ --jump ACCEPT +ip6tables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 546 \ +--jump ACCEPT iptables \ --table filter \ --insert LIBVIRT_FWO \ diff --git a/tests/networkxml2firewalldata/nat-tftp-linux.args b/tests/networkxml2firewalldata/nat-tftp-linux.args index b721801b70..88e9929b62 100644 --- a/tests/networkxml2firewalldata/nat-tftp-linux.args +++ b/tests/networkxml2firewalldata/nat-tftp-linux.args @@ -16,6 +16,13 @@ iptables \ --table filter \ --insert LIBVIRT_OUT \ --out-interface virbr0 \ +--protocol tcp \ +--destination-port 68 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ --protocol udp \ --destination-port 68 \ --jump ACCEPT @@ -35,6 +42,20 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_INP \ --in-interface virbr0 \ --protocol udp \ @@ -42,6 +63,13 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 69 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_FWO \ --in-interface virbr0 \ --jump REJECT diff --git a/tests/networkxml2firewalldata/route-default-linux.args b/tests/networkxml2firewalldata/route-default-linux.args index ed3c560f74..c427d9602d 100644 --- a/tests/networkxml2firewalldata/route-default-linux.args +++ b/tests/networkxml2firewalldata/route-default-linux.args @@ -16,6 +16,13 @@ iptables \ --table filter \ --insert LIBVIRT_OUT \ --out-interface virbr0 \ +--protocol tcp \ +--destination-port 68 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ --protocol udp \ --destination-port 68 \ --jump ACCEPT @@ -35,6 +42,20 @@ iptables \ --jump ACCEPT iptables \ --table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol tcp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ +--insert LIBVIRT_OUT \ +--out-interface virbr0 \ +--protocol udp \ +--destination-port 53 \ +--jump ACCEPT +iptables \ +--table filter \ --insert LIBVIRT_FWO \ --in-interface virbr0 \ --jump REJECT -- 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list