network: allow DHCP/DNS/TFTP explicitly in OUTPUT rules

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.salina@protonmail.com>

Initial patch then modified to add unit tests and IPv6
support

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Malina Salina 2019-09-27 17:10:34 +01:00 committed by Daniel P. Berrangé
parent 80f45e65c0
commit 313a71ee7b
10 changed files with 244 additions and 6 deletions

View File

@ -2192,6 +2192,7 @@ iptablesAddForwardRejectIn;
iptablesAddForwardRejectOut; iptablesAddForwardRejectOut;
iptablesAddOutputFixUdpChecksum; iptablesAddOutputFixUdpChecksum;
iptablesAddTcpInput; iptablesAddTcpInput;
iptablesAddTcpOutput;
iptablesAddUdpInput; iptablesAddUdpInput;
iptablesAddUdpOutput; iptablesAddUdpOutput;
iptablesRemoveDontMasquerade; iptablesRemoveDontMasquerade;
@ -2204,6 +2205,7 @@ iptablesRemoveForwardRejectIn;
iptablesRemoveForwardRejectOut; iptablesRemoveForwardRejectOut;
iptablesRemoveOutputFixUdpChecksum; iptablesRemoveOutputFixUdpChecksum;
iptablesRemoveTcpInput; iptablesRemoveTcpInput;
iptablesRemoveTcpOutput;
iptablesRemoveUdpInput; iptablesRemoveUdpInput;
iptablesRemoveUdpOutput; iptablesRemoveUdpOutput;
iptablesSetDeletePrivate; iptablesSetDeletePrivate;

View File

@ -553,18 +553,23 @@ networkAddGeneralIPv4FirewallRules(virFirewallPtr fw,
break; break;
} }
/* allow DHCP requests through to dnsmasq */ /* allow DHCP requests through to dnsmasq & back out */
iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67); iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
iptablesAddUdpInput(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); 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); iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
iptablesAddUdpInput(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 */ /* allow TFTP requests through to dnsmasq if necessary & back out*/
if (ipv4def && ipv4def->tftproot) if (ipv4def && ipv4def->tftproot) {
iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69); 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 */ /* Catch all rules to block forwarding to/from bridges */
iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
@ -592,13 +597,18 @@ networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw,
iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge); iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
iptablesRemoveForwardRejectOut(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); 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); iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
iptablesRemoveTcpInput(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); 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); iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
iptablesRemoveTcpInput(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); iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) { 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); iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
iptablesAddUdpInput(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); 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)) { if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) {
iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 546);
iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547); 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); iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53); iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
} }

View File

@ -303,6 +303,42 @@ iptablesRemoveUdpInput(virFirewallPtr fw,
iptablesInput(fw, layer, deletePrivate, iface, port, REMOVE, 0); 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: * iptablesAddUdpOutput:
* @ctx: pointer to the IP table context * @ctx: pointer to the IP table context

View File

@ -45,6 +45,14 @@ void iptablesRemoveUdpInput (virFirewallPtr fw,
const char *iface, const char *iface,
int port); 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, void iptablesAddUdpOutput (virFirewallPtr fw,
virFirewallLayer layer, virFirewallLayer layer,
const char *iface, const char *iface,

View File

@ -16,6 +16,13 @@ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \ --insert LIBVIRT_OUT \
--out-interface virbr0 \ --out-interface virbr0 \
--protocol tcp \
--destination-port 68 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 68 \ --destination-port 68 \
--jump ACCEPT --jump ACCEPT
@ -35,6 +42,20 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --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 \ --insert LIBVIRT_FWO \
--in-interface virbr0 \ --in-interface virbr0 \
--jump REJECT --jump REJECT

View File

@ -16,6 +16,13 @@ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \ --insert LIBVIRT_OUT \
--out-interface virbr0 \ --out-interface virbr0 \
--protocol tcp \
--destination-port 68 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 68 \ --destination-port 68 \
--jump ACCEPT --jump ACCEPT
@ -35,6 +42,20 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --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 \ --insert LIBVIRT_FWO \
--in-interface virbr0 \ --in-interface virbr0 \
--jump REJECT --jump REJECT
@ -81,11 +102,32 @@ ip6tables \
--jump ACCEPT --jump ACCEPT
ip6tables \ ip6tables \
--table filter \ --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 \ --insert LIBVIRT_INP \
--in-interface virbr0 \ --in-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 547 \ --destination-port 547 \
--jump ACCEPT --jump ACCEPT
ip6tables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \
--destination-port 546 \
--jump ACCEPT
iptables \ iptables \
--table filter \ --table filter \
--insert LIBVIRT_FWO \ --insert LIBVIRT_FWO \

View File

@ -16,6 +16,13 @@ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \ --insert LIBVIRT_OUT \
--out-interface virbr0 \ --out-interface virbr0 \
--protocol tcp \
--destination-port 68 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 68 \ --destination-port 68 \
--jump ACCEPT --jump ACCEPT
@ -35,6 +42,20 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --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 \ --insert LIBVIRT_FWO \
--in-interface virbr0 \ --in-interface virbr0 \
--jump REJECT --jump REJECT

View File

@ -16,6 +16,13 @@ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \ --insert LIBVIRT_OUT \
--out-interface virbr0 \ --out-interface virbr0 \
--protocol tcp \
--destination-port 68 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 68 \ --destination-port 68 \
--jump ACCEPT --jump ACCEPT
@ -35,6 +42,20 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --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 \ --insert LIBVIRT_FWO \
--in-interface virbr0 \ --in-interface virbr0 \
--jump REJECT --jump REJECT
@ -81,11 +102,32 @@ ip6tables \
--jump ACCEPT --jump ACCEPT
ip6tables \ ip6tables \
--table filter \ --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 \ --insert LIBVIRT_INP \
--in-interface virbr0 \ --in-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 547 \ --destination-port 547 \
--jump ACCEPT --jump ACCEPT
ip6tables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \
--destination-port 546 \
--jump ACCEPT
iptables \ iptables \
--table filter \ --table filter \
--insert LIBVIRT_FWO \ --insert LIBVIRT_FWO \

View File

@ -16,6 +16,13 @@ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \ --insert LIBVIRT_OUT \
--out-interface virbr0 \ --out-interface virbr0 \
--protocol tcp \
--destination-port 68 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 68 \ --destination-port 68 \
--jump ACCEPT --jump ACCEPT
@ -35,6 +42,20 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --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 \ --insert LIBVIRT_INP \
--in-interface virbr0 \ --in-interface virbr0 \
--protocol udp \ --protocol udp \
@ -42,6 +63,13 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \
--destination-port 69 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_FWO \ --insert LIBVIRT_FWO \
--in-interface virbr0 \ --in-interface virbr0 \
--jump REJECT --jump REJECT

View File

@ -16,6 +16,13 @@ iptables \
--table filter \ --table filter \
--insert LIBVIRT_OUT \ --insert LIBVIRT_OUT \
--out-interface virbr0 \ --out-interface virbr0 \
--protocol tcp \
--destination-port 68 \
--jump ACCEPT
iptables \
--table filter \
--insert LIBVIRT_OUT \
--out-interface virbr0 \
--protocol udp \ --protocol udp \
--destination-port 68 \ --destination-port 68 \
--jump ACCEPT --jump ACCEPT
@ -35,6 +42,20 @@ iptables \
--jump ACCEPT --jump ACCEPT
iptables \ iptables \
--table filter \ --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 \ --insert LIBVIRT_FWO \
--in-interface virbr0 \ --in-interface virbr0 \
--jump REJECT --jump REJECT