|
|
397dc2 |
From 4d8a10886f4dffd08fcf6a93694e12f76a2afd66 Mon Sep 17 00:00:00 2001
|
|
|
397dc2 |
Message-Id: <4d8a10886f4dffd08fcf6a93694e12f76a2afd66@dist-git>
|
|
|
397dc2 |
From: Laine Stump <laine@redhat.com>
|
|
|
397dc2 |
Date: Fri, 15 Jan 2021 22:51:51 -0500
|
|
|
397dc2 |
Subject: [PATCH] util: call iptables directly rather than via firewalld
|
|
|
397dc2 |
|
|
|
397dc2 |
When libvirt added support for firewalld, we were unable to use
|
|
|
397dc2 |
firewalld's higher level rules, because they weren't detailed enough
|
|
|
397dc2 |
and could not be applied to the iptables FORWARD or OUTPUT chains
|
|
|
397dc2 |
(only to the INPUT chain). Instead we changed our code so that rather
|
|
|
397dc2 |
than running the iptables/ip6tables/ebtables binaries ourselves, we
|
|
|
397dc2 |
would send these commands to firewalld as "passthrough commands", and
|
|
|
397dc2 |
firewalld would run the appropriate program on our behalf.
|
|
|
397dc2 |
|
|
|
397dc2 |
This was done under the assumption that firewalld was somehow tracking
|
|
|
397dc2 |
all these rules, and that this tracking was benefitting proper
|
|
|
397dc2 |
operation of firewalld and the system in general.
|
|
|
397dc2 |
|
|
|
397dc2 |
Several years later this came up in a discussion on IRC, and we
|
|
|
397dc2 |
learned from the firewalld developers that, in fact, adding iptables
|
|
|
397dc2 |
and ebtables rules with firewalld's passthrough commands actually has
|
|
|
397dc2 |
*no* advantage; firewalld doesn't keep track of these rules in any
|
|
|
397dc2 |
way, and doesn't use them to tailor the construction of its own rules.
|
|
|
397dc2 |
|
|
|
397dc2 |
Meanwhile, users have been complaining for some time that whenever
|
|
|
397dc2 |
firewalld is restarted on a system with libvirt virtual networks
|
|
|
397dc2 |
and/or nwfilter rules active, the system logs would be flooded with
|
|
|
397dc2 |
warning messages whining that [lots of different rules] could not be
|
|
|
397dc2 |
deleted because they didn't exist. For example:
|
|
|
397dc2 |
|
|
|
397dc2 |
firewalld[3536040]: WARNING: COMMAND_FAILED:
|
|
|
397dc2 |
'/usr/sbin/iptables -w10 -w --table filter --delete LIBVIRT_OUT
|
|
|
397dc2 |
--out-interface virbr4 --protocol udp --destination-port 68
|
|
|
397dc2 |
--jump ACCEPT' failed: iptables: Bad rule
|
|
|
397dc2 |
(does a matching rule exist in that chain?).
|
|
|
397dc2 |
|
|
|
397dc2 |
See:
|
|
|
397dc2 |
|
|
|
397dc2 |
https://bugzilla.redhat.com/1607929 (RHEL8)
|
|
|
397dc2 |
https://bugzilla.redhat.com/1790837 (RHEL8-AV)
|
|
|
397dc2 |
|
|
|
397dc2 |
for many more examples and a discussion)
|
|
|
397dc2 |
|
|
|
397dc2 |
Note that these messages are created by iptables, but are logged by
|
|
|
397dc2 |
firewalld - when an iptables/ebtables command fails, firewalld grabs
|
|
|
397dc2 |
whatever is in stderr of the program, and spits it out to the system
|
|
|
397dc2 |
log as a warning. We've requested that firewalld not do this (and
|
|
|
397dc2 |
instead leave it up to the calling application to do the appropriate
|
|
|
397dc2 |
logging), but this request has been respectfully denied.
|
|
|
397dc2 |
|
|
|
397dc2 |
But combining the two problems above ( 1) firewalld doesn't do
|
|
|
397dc2 |
anything useful when you use it as a proxy to add/remove iptables
|
|
|
397dc2 |
rules, 2) firewalld often insists on logging lots of
|
|
|
397dc2 |
annoying/misleading/useless "error" messages when you use it as a
|
|
|
397dc2 |
proxy to remove iptables rules that don't already exist), leads to a
|
|
|
397dc2 |
solution - simply stop using firewalld to add and remove iptables
|
|
|
397dc2 |
rules. Instead, exec iptables/ip6tables/ebtables directly in the same
|
|
|
397dc2 |
way we do when firewalld isn't active.
|
|
|
397dc2 |
|
|
|
397dc2 |
We still need to keep track of whether or not firewalld is active, as
|
|
|
397dc2 |
there are some things that must be done, e.g. we need to add some
|
|
|
397dc2 |
actual firewalld rules in the firewalld "libvirt" zone, and we need to
|
|
|
397dc2 |
take notice when firewalld restarts, so that we can reload all our
|
|
|
397dc2 |
rules.
|
|
|
397dc2 |
|
|
|
397dc2 |
This patch doesn't remove the infrastructure that allows having
|
|
|
397dc2 |
different firewall backends that perform their functions in different
|
|
|
397dc2 |
ways, as that will very possibly come in handy in the future when we
|
|
|
397dc2 |
want to have an nftables direct backend, and possibly a "pure"
|
|
|
397dc2 |
firewalld backend (now that firewalld supports more complex rules, and
|
|
|
397dc2 |
can add those rules to the FORWARD and OUTPUT chains). Instead, it
|
|
|
397dc2 |
just changes the action when the selected backend is "firewalld" so
|
|
|
397dc2 |
that it adds rules directly rather than through firewalld, while
|
|
|
397dc2 |
leaving as much of the existing code intact as possible.
|
|
|
397dc2 |
|
|
|
397dc2 |
In order for tests to still pass, virfirewalltest also had to be
|
|
|
397dc2 |
modified to behave in a different way (i.e. by capturing the generated
|
|
|
397dc2 |
commandline as it does for the DIRECT backend, rather than capturing
|
|
|
397dc2 |
dbus messages using a mocked dbus API).
|
|
|
397dc2 |
|
|
|
397dc2 |
Signed-off-by: Laine Stump <laine@redhat.com>
|
|
|
397dc2 |
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
|
|
|
397dc2 |
(cherry picked from commit b19863640d10b47b7c4a7cbadb21f196d61d96a2)
|
|
|
397dc2 |
Message-Id: <20210116035151.1066734-9-laine@redhat.com>
|
|
|
397dc2 |
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
397dc2 |
---
|
|
|
397dc2 |
src/util/virfirewall.c | 13 +++++++++++--
|
|
|
397dc2 |
tests/virfirewalltest.c | 30 ++++++++++++++++++++----------
|
|
|
397dc2 |
2 files changed, 31 insertions(+), 12 deletions(-)
|
|
|
397dc2 |
|
|
|
397dc2 |
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
|
|
|
397dc2 |
index 66d20d3f17..2ea821ec17 100644
|
|
|
397dc2 |
--- a/src/util/virfirewall.c
|
|
|
397dc2 |
+++ b/src/util/virfirewall.c
|
|
|
397dc2 |
@@ -644,7 +644,7 @@ virFirewallApplyRuleDirect(virFirewallRulePtr rule,
|
|
|
397dc2 |
}
|
|
|
397dc2 |
|
|
|
397dc2 |
|
|
|
397dc2 |
-static int
|
|
|
397dc2 |
+static int G_GNUC_UNUSED
|
|
|
397dc2 |
virFirewallApplyRuleFirewallD(virFirewallRulePtr rule,
|
|
|
397dc2 |
bool ignoreErrors,
|
|
|
397dc2 |
char **output)
|
|
|
397dc2 |
@@ -702,7 +702,16 @@ virFirewallApplyRule(virFirewallPtr firewall,
|
|
|
397dc2 |
return -1;
|
|
|
397dc2 |
break;
|
|
|
397dc2 |
case VIR_FIREWALL_BACKEND_FIREWALLD:
|
|
|
397dc2 |
- if (virFirewallApplyRuleFirewallD(rule, ignoreErrors, &output) < 0)
|
|
|
397dc2 |
+ /* Since we are using raw iptables rules, there is no
|
|
|
397dc2 |
+ * advantage to going through firewalld, so instead just add
|
|
|
397dc2 |
+ * them directly rather that via dbus calls to firewalld. This
|
|
|
397dc2 |
+ * has the useful side effect of eliminating extra unwanted
|
|
|
397dc2 |
+ * warning messages in the system logs when trying to delete
|
|
|
397dc2 |
+ * rules that don't exist (which is something that happens
|
|
|
397dc2 |
+ * often when libvirtd is started, and *always* when firewalld
|
|
|
397dc2 |
+ * is restarted)
|
|
|
397dc2 |
+ */
|
|
|
397dc2 |
+ if (virFirewallApplyRuleDirect(rule, ignoreErrors, &output) < 0)
|
|
|
397dc2 |
return -1;
|
|
|
397dc2 |
break;
|
|
|
397dc2 |
|
|
|
397dc2 |
diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c
|
|
|
397dc2 |
index 40e7f4f00b..1036353579 100644
|
|
|
397dc2 |
--- a/tests/virfirewalltest.c
|
|
|
397dc2 |
+++ b/tests/virfirewalltest.c
|
|
|
397dc2 |
@@ -214,7 +214,8 @@ testFirewallSingleGroup(const void *opaque)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT)
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD)
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, NULL, NULL);
|
|
|
397dc2 |
else
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -271,7 +272,8 @@ testFirewallRemoveRule(const void *opaque)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT)
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD)
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, NULL, NULL);
|
|
|
397dc2 |
else
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -335,7 +337,8 @@ testFirewallManyGroups(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT)
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD)
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, NULL, NULL);
|
|
|
397dc2 |
else
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -426,7 +429,8 @@ testFirewallIgnoreFailGroup(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -498,7 +502,8 @@ testFirewallIgnoreFailRule(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -567,7 +572,8 @@ testFirewallNoRollback(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -634,7 +640,8 @@ testFirewallSingleRollback(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwError = true;
|
|
|
397dc2 |
@@ -717,7 +724,8 @@ testFirewallManyRollback(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -808,7 +816,8 @@ testFirewallChainedRollback(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallRollbackHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
@@ -1007,7 +1016,8 @@ testFirewallQuery(const void *opaque G_GNUC_UNUSED)
|
|
|
397dc2 |
if (virFirewallSetBackend(data->tryBackend) < 0)
|
|
|
397dc2 |
goto cleanup;
|
|
|
397dc2 |
|
|
|
397dc2 |
- if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) {
|
|
|
397dc2 |
+ if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT ||
|
|
|
397dc2 |
+ data->expectBackend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
|
|
397dc2 |
virCommandSetDryRun(&cmdbuf, testFirewallQueryHook, NULL);
|
|
|
397dc2 |
} else {
|
|
|
397dc2 |
fwBuf = &cmdbuf;
|
|
|
397dc2 |
--
|
|
|
397dc2 |
2.30.0
|
|
|
397dc2 |
|