2007-02-14 16:26:42 +00:00
|
|
|
/*
|
2012-12-12 17:42:44 +00:00
|
|
|
* viriptables.c: helper APIs for managing iptables
|
|
|
|
*
|
2014-02-20 00:32:19 +00:00
|
|
|
* Copyright (C) 2007-2014 Red Hat, Inc.
|
2007-02-14 16:26:42 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2007-02-14 16:26:42 +00:00
|
|
|
*/
|
|
|
|
|
2008-01-29 18:15:54 +00:00
|
|
|
#include <config.h>
|
2007-02-14 16:26:42 +00:00
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2007-12-07 14:45:39 +00:00
|
|
|
|
2007-03-30 16:25:02 +00:00
|
|
|
#include "internal.h"
|
2012-12-12 17:42:44 +00:00
|
|
|
#include "viriptables.h"
|
2012-12-12 16:27:01 +00:00
|
|
|
#include "vircommand.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2013-05-09 18:59:04 +00:00
|
|
|
#include "virfile.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2012-12-13 15:49:48 +00:00
|
|
|
#include "virthread.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
|
|
|
#include "virutil.h"
|
util: create private chains for virtual network firewall rules
Historically firewall rules for virtual networks were added straight
into the base chains. This works but has a number of bugs and design
limitations:
- It is inflexible for admins wanting to add extra rules ahead
of libvirt's rules, via hook scripts.
- It is not clear to the admin that the rules were created by
libvirt
- Each rule must be deleted by libvirt individually since they
are all directly in the builtin chains
- The ordering of rules in the forward chain is incorrect
when multiple networks are created, allowing traffic to
mistakenly flow between networks in one direction.
To address all of these problems, libvirt needs to move to creating
rules in its own private chains. In the top level builtin chains,
libvirt will add links to its own private top level chains.
Addressing the traffic ordering bug requires some extra steps. With
everything going into the FORWARD chain there was interleaving of rules
for outbound traffic and inbound traffic for each network:
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
The rule allowing outbound traffic from virbr1 would mistakenly
allow packets from virbr1 to virbr0, before the rule denying input
to virbr0 gets a chance to run.
What we really need todo is group the forwarding rules into three
distinct sets:
* Cross rules - LIBVIRT_FWX
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
* Incoming rules - LIBVIRT_FWI
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
* Outgoing rules - LIBVIRT_FWO
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
There is thus no risk of outgoing rules for one network mistakenly
allowing incoming traffic for another network, as all incoming rules
are evalated first.
With this in mind, we'll thus need three distinct chains linked from
the FORWARD chain, so we end up with:
INPUT --> LIBVIRT_INP (filter)
OUTPUT --> LIBVIRT_OUT (filter)
FORWARD +-> LIBVIRT_FWX (filter)
+-> LIBVIRT_FWO
\-> LIBVIRT_FWI
POSTROUTING --> LIBVIRT_PRT (nat & mangle)
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-10-31 19:33:21 +00:00
|
|
|
#include "virhash.h"
|
network: use firewalld instead of iptables, when available
* configure.ac, spec file: firewalld defaults to enabled if dbus is
available, otherwise is disabled. If --with_firewalld is explicitly
requested and dbus is not available, configure will fail.
* bridge_driver: add dbus filters to get the FirewallD1.Reloaded
signal and DBus.NameOwnerChanged on org.fedoraproject.FirewallD1.
When these are encountered, reload all the iptables reuls of all
libvirt's virtual networks (similar to what happens when libvirtd is
restarted).
* iptables, ebtables: use firewall-cmd's direct passthrough interface
when available, otherwise use iptables and ebtables commands. This
decision is made once the first time libvirt calls
iptables/ebtables, and that decision is maintained for the life of
libvirtd.
* Note that the nwfilter part of this patch was separated out into
another patch by Stefan in V2, so that needs to be revised and
re-reviewed as well.
================
All the configure.ac and specfile changes are unchanged from Thomas'
V3.
V3 re-ran "firewall-cmd --state" every time a new rule was added,
which was extremely inefficient. V4 uses VIR_ONCE_GLOBAL_INIT to set
up a one-time initialization function.
The VIR_ONCE_GLOBAL_INIT(x) macro references a static function called
vir(Ip|Eb)OnceInit(), which will then be called the first time that
the static function vir(Ip|Eb)TablesInitialize() is called (that
function is defined for you by the macro). This is
thread-safe, so there is no chance of any race.
IMPORTANT NOTE: I've left the VIR_DEBUG messages in these two init
functions (one for iptables, on for ebtables) as VIR_WARN so that I
don't have to turn on all the other debug message just to see
these. Even if this patch doesn't need any other modification, those
messages need to be changed to VIR_DEBUG before pushing.
This one-time initialization works well. However, I've encountered
problems with testing:
1) Whenever I have enabled the firewalld service, *all* attempts to
call firewall-cmd from within libvirtd end with firewall-cmd hanging
internally somewhere. This is *not* the case if firewall-cmd returns
non-0 in response to "firewall-cmd --state" (i.e. *that* command runs
and returns to libvirt successfully.)
2) If I start libvirtd while firewalld is stopped, then start
firewalld later, this triggers libvirtd to reload its iptables rules,
however it also spits out a *ton* of complaints about deletion failing
(I suppose because firewalld has nuked all of libvirt's rules). I
guess we need to suppress those messages (which is a more annoying
problem to fix than you might think, but that's another story).
3) I noticed a few times during this long line of errors that
firewalld made a complaint about "Resource Temporarily
unavailable. Having libvirtd access iptables commands directly at the
same time as firewalld is doing so is apparently problematic.
4) In general, I'm concerned about the "set it once and never change
it" method - if firewalld is disabled at libvirtd startup, causing
libvirtd to always use iptables/ebtables directly, this won't cause
*terrible* problems, but if libvirtd decides to use firewall-cmd and
firewalld is later disabled, libvirtd will not be able to recover.
2012-08-14 18:59:52 +00:00
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("util.iptables");
|
|
|
|
|
2010-10-25 14:10:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2007-02-14 16:26:42 +00:00
|
|
|
enum {
|
|
|
|
ADD = 0,
|
|
|
|
REMOVE
|
|
|
|
};
|
|
|
|
|
2018-12-05 15:53:55 +00:00
|
|
|
static bool deletePrivate = true;
|
2013-11-01 17:36:59 +00:00
|
|
|
|
util: create private chains for virtual network firewall rules
Historically firewall rules for virtual networks were added straight
into the base chains. This works but has a number of bugs and design
limitations:
- It is inflexible for admins wanting to add extra rules ahead
of libvirt's rules, via hook scripts.
- It is not clear to the admin that the rules were created by
libvirt
- Each rule must be deleted by libvirt individually since they
are all directly in the builtin chains
- The ordering of rules in the forward chain is incorrect
when multiple networks are created, allowing traffic to
mistakenly flow between networks in one direction.
To address all of these problems, libvirt needs to move to creating
rules in its own private chains. In the top level builtin chains,
libvirt will add links to its own private top level chains.
Addressing the traffic ordering bug requires some extra steps. With
everything going into the FORWARD chain there was interleaving of rules
for outbound traffic and inbound traffic for each network:
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
The rule allowing outbound traffic from virbr1 would mistakenly
allow packets from virbr1 to virbr0, before the rule denying input
to virbr0 gets a chance to run.
What we really need todo is group the forwarding rules into three
distinct sets:
* Cross rules - LIBVIRT_FWX
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
* Incoming rules - LIBVIRT_FWI
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
* Outgoing rules - LIBVIRT_FWO
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
There is thus no risk of outgoing rules for one network mistakenly
allowing incoming traffic for another network, as all incoming rules
are evalated first.
With this in mind, we'll thus need three distinct chains linked from
the FORWARD chain, so we end up with:
INPUT --> LIBVIRT_INP (filter)
OUTPUT --> LIBVIRT_OUT (filter)
FORWARD +-> LIBVIRT_FWX (filter)
+-> LIBVIRT_FWO
\-> LIBVIRT_FWI
POSTROUTING --> LIBVIRT_PRT (nat & mangle)
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-10-31 19:33:21 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *parent;
|
|
|
|
const char *child;
|
|
|
|
} iptablesGlobalChain;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
virFirewallLayer layer;
|
|
|
|
const char *table;
|
|
|
|
iptablesGlobalChain *chains;
|
|
|
|
size_t nchains;
|
|
|
|
bool *changed;
|
|
|
|
} iptablesGlobalChainData;
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
iptablesPrivateChainCreate(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
|
|
|
const char *const *lines,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
iptablesGlobalChainData *data = opaque;
|
|
|
|
virHashTablePtr chains = NULL;
|
|
|
|
virHashTablePtr links = NULL;
|
|
|
|
const char *const *tmp;
|
|
|
|
int ret = -1;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!(chains = virHashCreate(50, NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
if (!(links = virHashCreate(50, NULL)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
tmp = lines;
|
|
|
|
while (tmp && *tmp) {
|
|
|
|
if (STRPREFIX(*tmp, "-N ")) { /* eg "-N LIBVIRT_INP" */
|
|
|
|
if (virHashUpdateEntry(chains, *tmp + 3, (void *)0x1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
} else if (STRPREFIX(*tmp, "-A ")) { /* eg "-A INPUT -j LIBVIRT_INP" */
|
|
|
|
char *sep = strchr(*tmp + 3, ' ');
|
|
|
|
if (sep) {
|
|
|
|
*sep = '\0';
|
|
|
|
if (STRPREFIX(sep + 1, "-j ")) {
|
|
|
|
if (virHashUpdateEntry(links, sep + 4,
|
|
|
|
(char *)*tmp + 3) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < data->nchains; i++) {
|
|
|
|
const char *from;
|
|
|
|
if (!virHashLookup(chains, data->chains[i].child)) {
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", data->table,
|
|
|
|
"--new-chain", data->chains[i].child, NULL);
|
|
|
|
*data->changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
from = virHashLookup(links, data->chains[i].child);
|
|
|
|
if (!from || STRNEQ(from, data->chains[i].parent))
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", data->table,
|
|
|
|
"--insert", data->chains[i].parent,
|
|
|
|
"--jump", data->chains[i].child, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virHashFree(chains);
|
|
|
|
virHashFree(links);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2019-03-18 16:49:32 +00:00
|
|
|
iptablesSetupPrivateChains(virFirewallLayer layer)
|
util: create private chains for virtual network firewall rules
Historically firewall rules for virtual networks were added straight
into the base chains. This works but has a number of bugs and design
limitations:
- It is inflexible for admins wanting to add extra rules ahead
of libvirt's rules, via hook scripts.
- It is not clear to the admin that the rules were created by
libvirt
- Each rule must be deleted by libvirt individually since they
are all directly in the builtin chains
- The ordering of rules in the forward chain is incorrect
when multiple networks are created, allowing traffic to
mistakenly flow between networks in one direction.
To address all of these problems, libvirt needs to move to creating
rules in its own private chains. In the top level builtin chains,
libvirt will add links to its own private top level chains.
Addressing the traffic ordering bug requires some extra steps. With
everything going into the FORWARD chain there was interleaving of rules
for outbound traffic and inbound traffic for each network:
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
The rule allowing outbound traffic from virbr1 would mistakenly
allow packets from virbr1 to virbr0, before the rule denying input
to virbr0 gets a chance to run.
What we really need todo is group the forwarding rules into three
distinct sets:
* Cross rules - LIBVIRT_FWX
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
* Incoming rules - LIBVIRT_FWI
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
* Outgoing rules - LIBVIRT_FWO
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
There is thus no risk of outgoing rules for one network mistakenly
allowing incoming traffic for another network, as all incoming rules
are evalated first.
With this in mind, we'll thus need three distinct chains linked from
the FORWARD chain, so we end up with:
INPUT --> LIBVIRT_INP (filter)
OUTPUT --> LIBVIRT_OUT (filter)
FORWARD +-> LIBVIRT_FWX (filter)
+-> LIBVIRT_FWO
\-> LIBVIRT_FWI
POSTROUTING --> LIBVIRT_PRT (nat & mangle)
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-10-31 19:33:21 +00:00
|
|
|
{
|
2020-07-04 20:35:10 +00:00
|
|
|
g_autoptr(virFirewall) fw = virFirewallNew();
|
util: create private chains for virtual network firewall rules
Historically firewall rules for virtual networks were added straight
into the base chains. This works but has a number of bugs and design
limitations:
- It is inflexible for admins wanting to add extra rules ahead
of libvirt's rules, via hook scripts.
- It is not clear to the admin that the rules were created by
libvirt
- Each rule must be deleted by libvirt individually since they
are all directly in the builtin chains
- The ordering of rules in the forward chain is incorrect
when multiple networks are created, allowing traffic to
mistakenly flow between networks in one direction.
To address all of these problems, libvirt needs to move to creating
rules in its own private chains. In the top level builtin chains,
libvirt will add links to its own private top level chains.
Addressing the traffic ordering bug requires some extra steps. With
everything going into the FORWARD chain there was interleaving of rules
for outbound traffic and inbound traffic for each network:
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
The rule allowing outbound traffic from virbr1 would mistakenly
allow packets from virbr1 to virbr0, before the rule denying input
to virbr0 gets a chance to run.
What we really need todo is group the forwarding rules into three
distinct sets:
* Cross rules - LIBVIRT_FWX
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
* Incoming rules - LIBVIRT_FWI
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
* Outgoing rules - LIBVIRT_FWO
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
There is thus no risk of outgoing rules for one network mistakenly
allowing incoming traffic for another network, as all incoming rules
are evalated first.
With this in mind, we'll thus need three distinct chains linked from
the FORWARD chain, so we end up with:
INPUT --> LIBVIRT_INP (filter)
OUTPUT --> LIBVIRT_OUT (filter)
FORWARD +-> LIBVIRT_FWX (filter)
+-> LIBVIRT_FWO
\-> LIBVIRT_FWI
POSTROUTING --> LIBVIRT_PRT (nat & mangle)
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-10-31 19:33:21 +00:00
|
|
|
int ret = -1;
|
|
|
|
iptablesGlobalChain filter_chains[] = {
|
|
|
|
{"INPUT", "LIBVIRT_INP"},
|
|
|
|
{"OUTPUT", "LIBVIRT_OUT"},
|
|
|
|
{"FORWARD", "LIBVIRT_FWO"},
|
|
|
|
{"FORWARD", "LIBVIRT_FWI"},
|
|
|
|
{"FORWARD", "LIBVIRT_FWX"},
|
|
|
|
};
|
|
|
|
iptablesGlobalChain natmangle_chains[] = {
|
|
|
|
{"POSTROUTING", "LIBVIRT_PRT"},
|
|
|
|
};
|
|
|
|
bool changed = false;
|
|
|
|
iptablesGlobalChainData data[] = {
|
2019-03-18 16:49:32 +00:00
|
|
|
{ layer, "filter",
|
2019-10-15 11:55:26 +00:00
|
|
|
filter_chains, G_N_ELEMENTS(filter_chains), &changed },
|
2019-03-18 16:49:32 +00:00
|
|
|
{ layer, "nat",
|
2019-10-15 11:55:26 +00:00
|
|
|
natmangle_chains, G_N_ELEMENTS(natmangle_chains), &changed },
|
2019-03-18 16:49:32 +00:00
|
|
|
{ layer, "mangle",
|
2019-10-15 11:55:26 +00:00
|
|
|
natmangle_chains, G_N_ELEMENTS(natmangle_chains), &changed },
|
util: create private chains for virtual network firewall rules
Historically firewall rules for virtual networks were added straight
into the base chains. This works but has a number of bugs and design
limitations:
- It is inflexible for admins wanting to add extra rules ahead
of libvirt's rules, via hook scripts.
- It is not clear to the admin that the rules were created by
libvirt
- Each rule must be deleted by libvirt individually since they
are all directly in the builtin chains
- The ordering of rules in the forward chain is incorrect
when multiple networks are created, allowing traffic to
mistakenly flow between networks in one direction.
To address all of these problems, libvirt needs to move to creating
rules in its own private chains. In the top level builtin chains,
libvirt will add links to its own private top level chains.
Addressing the traffic ordering bug requires some extra steps. With
everything going into the FORWARD chain there was interleaving of rules
for outbound traffic and inbound traffic for each network:
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
The rule allowing outbound traffic from virbr1 would mistakenly
allow packets from virbr1 to virbr0, before the rule denying input
to virbr0 gets a chance to run.
What we really need todo is group the forwarding rules into three
distinct sets:
* Cross rules - LIBVIRT_FWX
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
* Incoming rules - LIBVIRT_FWI
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
* Outgoing rules - LIBVIRT_FWO
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
There is thus no risk of outgoing rules for one network mistakenly
allowing incoming traffic for another network, as all incoming rules
are evalated first.
With this in mind, we'll thus need three distinct chains linked from
the FORWARD chain, so we end up with:
INPUT --> LIBVIRT_INP (filter)
OUTPUT --> LIBVIRT_OUT (filter)
FORWARD +-> LIBVIRT_FWX (filter)
+-> LIBVIRT_FWO
\-> LIBVIRT_FWI
POSTROUTING --> LIBVIRT_PRT (nat & mangle)
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-10-31 19:33:21 +00:00
|
|
|
};
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
virFirewallStartTransaction(fw, 0);
|
|
|
|
|
2019-10-15 11:55:26 +00:00
|
|
|
for (i = 0; i < G_N_ELEMENTS(data); i++)
|
util: create private chains for virtual network firewall rules
Historically firewall rules for virtual networks were added straight
into the base chains. This works but has a number of bugs and design
limitations:
- It is inflexible for admins wanting to add extra rules ahead
of libvirt's rules, via hook scripts.
- It is not clear to the admin that the rules were created by
libvirt
- Each rule must be deleted by libvirt individually since they
are all directly in the builtin chains
- The ordering of rules in the forward chain is incorrect
when multiple networks are created, allowing traffic to
mistakenly flow between networks in one direction.
To address all of these problems, libvirt needs to move to creating
rules in its own private chains. In the top level builtin chains,
libvirt will add links to its own private top level chains.
Addressing the traffic ordering bug requires some extra steps. With
everything going into the FORWARD chain there was interleaving of rules
for outbound traffic and inbound traffic for each network:
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
The rule allowing outbound traffic from virbr1 would mistakenly
allow packets from virbr1 to virbr0, before the rule denying input
to virbr0 gets a chance to run.
What we really need todo is group the forwarding rules into three
distinct sets:
* Cross rules - LIBVIRT_FWX
-A FORWARD -i virbr1 -o virbr1 -j ACCEPT
-A FORWARD -i virbr0 -o virbr0 -j ACCEPT
* Incoming rules - LIBVIRT_FWI
-A FORWARD -d 192.168.3.0/24 -o virbr1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -d 192.168.2.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable
* Outgoing rules - LIBVIRT_FWO
-A FORWARD -s 192.168.3.0/24 -i virbr1 -j ACCEPT
-A FORWARD -i virbr1 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 192.168.2.0/24 -i virbr0 -j ACCEPT
-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable
There is thus no risk of outgoing rules for one network mistakenly
allowing incoming traffic for another network, as all incoming rules
are evalated first.
With this in mind, we'll thus need three distinct chains linked from
the FORWARD chain, so we end up with:
INPUT --> LIBVIRT_INP (filter)
OUTPUT --> LIBVIRT_OUT (filter)
FORWARD +-> LIBVIRT_FWX (filter)
+-> LIBVIRT_FWO
\-> LIBVIRT_FWI
POSTROUTING --> LIBVIRT_PRT (nat & mangle)
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-10-31 19:33:21 +00:00
|
|
|
virFirewallAddRuleFull(fw, data[i].layer,
|
|
|
|
false, iptablesPrivateChainCreate,
|
|
|
|
&(data[i]), "--table", data[i].table,
|
|
|
|
"--list-rules", NULL);
|
|
|
|
|
|
|
|
if (virFirewallApply(fw) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = changed ? 1 : 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-05 15:53:55 +00:00
|
|
|
void
|
|
|
|
iptablesSetDeletePrivate(bool pvt)
|
|
|
|
{
|
|
|
|
deletePrivate = pvt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
static void
|
|
|
|
iptablesInput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2007-02-14 16:26:42 +00:00
|
|
|
const char *iface,
|
|
|
|
int port,
|
|
|
|
int action,
|
|
|
|
int tcp)
|
|
|
|
{
|
|
|
|
char portstr[32];
|
|
|
|
|
2019-11-13 13:53:42 +00:00
|
|
|
g_snprintf(portstr, sizeof(portstr), "%d", port);
|
2007-02-14 16:26:42 +00:00
|
|
|
portstr[sizeof(portstr) - 1] = '\0';
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_INP" : "INPUT",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--in-interface", iface,
|
|
|
|
"--protocol", tcp ? "tcp" : "udp",
|
|
|
|
"--destination-port", portstr,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
static void
|
|
|
|
iptablesOutput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2013-12-17 17:56:28 +00:00
|
|
|
const char *iface,
|
|
|
|
int port,
|
|
|
|
int action,
|
|
|
|
int tcp)
|
|
|
|
{
|
|
|
|
char portstr[32];
|
|
|
|
|
2019-11-13 13:53:42 +00:00
|
|
|
g_snprintf(portstr, sizeof(portstr), "%d", port);
|
2013-12-17 17:56:28 +00:00
|
|
|
portstr[sizeof(portstr) - 1] = '\0';
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_OUT" : "OUTPUT",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--out-interface", iface,
|
|
|
|
"--protocol", tcp ? "tcp" : "udp",
|
|
|
|
"--destination-port", portstr,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
2013-12-17 17:56:28 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddTcpInput:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the TCP port to add
|
|
|
|
*
|
|
|
|
* Add an input to the IP table allowing access to the given @port on
|
|
|
|
* the given @iface interface for TCP packets
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddTcpInput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-02-14 16:26:42 +00:00
|
|
|
const char *iface,
|
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesInput(fw, layer, true, iface, port, ADD, 1);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveTcpInput:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the TCP port to remove
|
|
|
|
*
|
2008-02-27 10:37:19 +00:00
|
|
|
* Removes an input from the IP table, hence forbidding access to the given
|
2007-06-29 13:23:13 +00:00
|
|
|
* @port on the given @iface interface for TCP packets
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveTcpInput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-02-14 16:26:42 +00:00
|
|
|
const char *iface,
|
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesInput(fw, layer, deletePrivate, iface, port, REMOVE, 1);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddUdpInput:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the UDP port to add
|
|
|
|
*
|
|
|
|
* Add an input to the IP table allowing access to the given @port on
|
|
|
|
* the given @iface interface for UDP packets
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddUdpInput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-02-14 16:26:42 +00:00
|
|
|
const char *iface,
|
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesInput(fw, layer, true, iface, port, ADD, 0);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveUdpInput:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the UDP port to remove
|
|
|
|
*
|
2008-02-27 10:37:19 +00:00
|
|
|
* Removes an input from the IP table, hence forbidding access to the given
|
2007-06-29 13:23:13 +00:00
|
|
|
* @port on the given @iface interface for UDP packets
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveUdpInput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-02-14 16:26:42 +00:00
|
|
|
const char *iface,
|
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesInput(fw, layer, deletePrivate, iface, port, REMOVE, 0);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2019-09-27 16:10:34 +00:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2013-12-17 17:56:28 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddUdpOutput:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the UDP port to add
|
|
|
|
*
|
|
|
|
* Add an output to the IP table allowing access to the given @port from
|
|
|
|
* the given @iface interface for UDP packets
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddUdpOutput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2013-12-17 17:56:28 +00:00
|
|
|
const char *iface,
|
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesOutput(fw, layer, true, iface, port, ADD, 0);
|
2013-12-17 17:56:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iptablesRemoveUdpOutput:
|
|
|
|
* @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 UDP packets
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveUdpOutput(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2013-12-17 17:56:28 +00:00
|
|
|
const char *iface,
|
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesOutput(fw, layer, deletePrivate, iface, port, REMOVE, 0);
|
2013-12-17 17:56:28 +00:00
|
|
|
}
|
|
|
|
|
2007-02-14 16:26:42 +00:00
|
|
|
|
2010-10-25 14:10:33 +00:00
|
|
|
static char *iptablesFormatNetwork(virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix)
|
2010-10-25 14:10:33 +00:00
|
|
|
{
|
|
|
|
virSocketAddr network;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *netstr = NULL;
|
2010-10-25 14:10:33 +00:00
|
|
|
char *ret;
|
|
|
|
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (!(VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET) ||
|
|
|
|
VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET6))) {
|
2012-07-18 10:26:24 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
|
_("Only IPv4 or IPv6 addresses can be used with iptables"));
|
2010-10-25 14:10:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-12-31 11:20:43 +00:00
|
|
|
if (virSocketAddrMaskByPrefix(netaddr, prefix, &network) < 0) {
|
2012-07-18 10:26:24 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Failure to mask address"));
|
2010-11-30 19:35:58 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-10-25 14:10:33 +00:00
|
|
|
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
netstr = virSocketAddrFormat(&network);
|
2010-10-25 14:10:33 +00:00
|
|
|
|
|
|
|
if (!netstr)
|
|
|
|
return NULL;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
ret = g_strdup_printf("%s/%d", netstr, prefix);
|
2010-10-25 14:10:33 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-10 23:17:46 +00:00
|
|
|
/* Allow all traffic coming from the bridge, with a valid network address
|
|
|
|
* to proceed to WAN
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
static int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesForwardAllowOut(virFirewallPtr fw,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2014-03-06 17:01:13 +00:00
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev,
|
|
|
|
int action)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *networkstr = NULL;
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ?
|
|
|
|
VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2010-11-30 19:35:58 +00:00
|
|
|
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
return -1;
|
|
|
|
|
2013-02-04 09:45:23 +00:00
|
|
|
if (physdev && physdev[0])
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWO" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--source", networkstr,
|
|
|
|
"--in-interface", iface,
|
|
|
|
"--out-interface", physdev,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
|
|
|
else
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWO" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--source", networkstr,
|
|
|
|
"--in-interface", iface,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
2013-02-04 09:45:23 +00:00
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
return 0;
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardAllowOut:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @iface: the source interface name
|
|
|
|
* @physdev: the physical output device
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-06-29 13:23:13 +00:00
|
|
|
* Add a rule to the IP table context to allow the traffic for the
|
|
|
|
* network @network via interface @iface to be forwarded to
|
|
|
|
* @physdev device. This allow the outbound traffic on a bridge.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesAddForwardAllowOut(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardAllowOut(fw, true, netaddr, prefix, iface, physdev, ADD);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardAllowOut:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @iface: the source interface name
|
|
|
|
* @physdev: the physical output device
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-06-29 13:23:13 +00:00
|
|
|
* Remove a rule from the IP table context hence forbidding forwarding
|
|
|
|
* of the traffic for the network @network via interface @iface
|
|
|
|
* to the @physdev device output. This stops the outbound traffic on a bridge.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesRemoveForwardAllowOut(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardAllowOut(fw, deletePrivate, netaddr, prefix, iface, physdev, REMOVE);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-04-10 23:17:46 +00:00
|
|
|
|
|
|
|
/* Allow all traffic destined to the bridge, with a valid network address
|
|
|
|
* and associated with an existing connection
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
static int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesForwardAllowRelatedIn(virFirewallPtr fw,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2014-03-06 17:01:13 +00:00
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev,
|
|
|
|
int action)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ?
|
|
|
|
VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *networkstr = NULL;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2010-11-30 19:35:58 +00:00
|
|
|
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
if (physdev && physdev[0])
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWI" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--destination", networkstr,
|
|
|
|
"--in-interface", physdev,
|
|
|
|
"--out-interface", iface,
|
|
|
|
"--match", "conntrack",
|
|
|
|
"--ctstate", "ESTABLISHED,RELATED",
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
|
|
|
else
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWI" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--destination", networkstr,
|
|
|
|
"--out-interface", iface,
|
|
|
|
"--match", "conntrack",
|
|
|
|
"--ctstate", "ESTABLISHED,RELATED",
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return 0;
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2008-03-28 20:38:21 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardAllowRelatedIn:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @iface: the output interface name
|
|
|
|
* @physdev: the physical input device or NULL
|
|
|
|
*
|
|
|
|
* Add rules to the IP table context to allow the traffic for the
|
|
|
|
* network @network on @physdev device to be forwarded to
|
|
|
|
* interface @iface, if it is part of an existing connection.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesAddForwardAllowRelatedIn(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev)
|
2008-03-28 20:38:21 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardAllowRelatedIn(fw, true, netaddr, prefix, iface, physdev, ADD);
|
2008-03-28 20:38:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardAllowRelatedIn:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @iface: the output interface name
|
|
|
|
* @physdev: the physical input device or NULL
|
|
|
|
*
|
|
|
|
* Remove rules from the IP table context hence forbidding the traffic for
|
|
|
|
* network @network on @physdev device to be forwarded to
|
|
|
|
* interface @iface, if it is part of an existing connection.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesRemoveForwardAllowRelatedIn(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev)
|
2008-03-28 20:38:21 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardAllowRelatedIn(fw, deletePrivate, netaddr, prefix, iface, physdev, REMOVE);
|
2008-03-28 20:38:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow all traffic destined to the bridge, with a valid network address
|
|
|
|
*/
|
|
|
|
static int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesForwardAllowIn(virFirewallPtr fw,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2014-03-06 17:01:13 +00:00
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2008-03-28 20:38:21 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev,
|
|
|
|
int action)
|
|
|
|
{
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ?
|
|
|
|
VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *networkstr = NULL;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2010-11-30 19:35:58 +00:00
|
|
|
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
if (physdev && physdev[0])
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWI" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--destination", networkstr,
|
|
|
|
"--in-interface", physdev,
|
|
|
|
"--out-interface", iface,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
|
|
|
else
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWI" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--destination", networkstr,
|
|
|
|
"--out-interface", iface,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
|
|
|
return 0;
|
2008-03-28 20:38:21 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardAllowIn:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @iface: the output interface name
|
|
|
|
* @physdev: the physical input device or NULL
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-06-29 13:23:13 +00:00
|
|
|
* Add rules to the IP table context to allow the traffic for the
|
|
|
|
* network @network on @physdev device to be forwarded to
|
|
|
|
* interface @iface. This allow the inbound traffic on a bridge.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesAddForwardAllowIn(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2007-04-10 23:17:46 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardAllowIn(fw, true, netaddr, prefix, iface, physdev, ADD);
|
2007-04-10 23:17:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardAllowIn:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @iface: the output interface name
|
|
|
|
* @physdev: the physical input device or NULL
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-06-29 13:23:13 +00:00
|
|
|
* Remove rules from the IP table context hence forbidding the traffic for
|
|
|
|
* network @network on @physdev device to be forwarded to
|
|
|
|
* interface @iface. This stops the inbound traffic on a bridge.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2007-04-10 23:17:46 +00:00
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesRemoveForwardAllowIn(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2007-04-10 23:17:46 +00:00
|
|
|
const char *iface,
|
|
|
|
const char *physdev)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardAllowIn(fw, deletePrivate, netaddr, prefix, iface, physdev, REMOVE);
|
2007-04-10 23:17:46 +00:00
|
|
|
}
|
|
|
|
|
2018-10-31 18:51:34 +00:00
|
|
|
static void
|
|
|
|
iptablesForwardAllowCross(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2018-10-31 18:51:34 +00:00
|
|
|
const char *iface,
|
|
|
|
int action)
|
|
|
|
{
|
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWX" : "FORWARD",
|
2018-10-31 18:51:34 +00:00
|
|
|
"--in-interface", iface,
|
|
|
|
"--out-interface", iface,
|
|
|
|
"--jump", "ACCEPT",
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardAllowCross:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the input/output interface name
|
|
|
|
*
|
|
|
|
* Add rules to the IP table context to allow traffic to cross that
|
|
|
|
* interface. It allows all traffic between guests on the same bridge
|
|
|
|
* represented by that interface.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddForwardAllowCross(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2010-12-08 19:09:25 +00:00
|
|
|
const char *iface)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesForwardAllowCross(fw, layer, true, iface, ADD);
|
2007-04-10 23:17:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardAllowCross:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the input/output interface name
|
|
|
|
*
|
|
|
|
* Remove rules to the IP table context to block traffic to cross that
|
|
|
|
* interface. It forbids traffic between guests on the same bridge
|
|
|
|
* represented by that interface.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveForwardAllowCross(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2010-12-08 19:09:25 +00:00
|
|
|
const char *iface)
|
2018-10-31 18:51:34 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesForwardAllowCross(fw, layer, deletePrivate, iface, REMOVE);
|
2018-10-31 18:51:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
iptablesForwardRejectOut(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2018-10-31 18:51:34 +00:00
|
|
|
const char *iface,
|
|
|
|
int action)
|
2010-12-08 19:09:25 +00:00
|
|
|
{
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWO" : "FORWARD",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--in-interface", iface,
|
2018-10-31 18:51:34 +00:00
|
|
|
"--jump", "REJECT",
|
2014-03-06 17:01:13 +00:00
|
|
|
NULL);
|
2007-04-10 23:17:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardRejectOut:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the output interface name
|
|
|
|
*
|
|
|
|
* Add rules to the IP table context to forbid all traffic to that
|
|
|
|
* interface. It forbids forwarding from the bridge to that interface.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddForwardRejectOut(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-04-10 23:17:46 +00:00
|
|
|
const char *iface)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesForwardRejectOut(fw, layer, true, iface, ADD);
|
2007-04-10 23:17:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardRejectOut:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the output interface name
|
|
|
|
*
|
|
|
|
* Remove rules from the IP table context forbidding all traffic to that
|
|
|
|
* interface. It reallow forwarding from the bridge to that interface.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveForwardRejectOut(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-04-10 23:17:46 +00:00
|
|
|
const char *iface)
|
2018-10-31 18:51:34 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesForwardRejectOut(fw, layer, deletePrivate, iface, REMOVE);
|
2018-10-31 18:51:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
iptablesForwardRejectIn(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2018-10-31 18:51:34 +00:00
|
|
|
const char *iface,
|
|
|
|
int action)
|
2007-04-10 23:17:46 +00:00
|
|
|
{
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
|
|
|
"--table", "filter",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_FWI" : "FORWARD",
|
2018-10-31 18:51:34 +00:00
|
|
|
"--out-interface", iface,
|
2014-03-06 17:01:13 +00:00
|
|
|
"--jump", "REJECT",
|
|
|
|
NULL);
|
2007-04-10 23:17:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardRejectIn:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the input interface name
|
|
|
|
*
|
|
|
|
* Add rules to the IP table context to forbid all traffic from that
|
|
|
|
* interface. It forbids forwarding from that interface to the bridge.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddForwardRejectIn(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-04-10 23:17:46 +00:00
|
|
|
const char *iface)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesForwardRejectIn(fw, layer, true, iface, ADD);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardRejectIn:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the input interface name
|
|
|
|
*
|
|
|
|
* Remove rules from the IP table context forbidding all traffic from that
|
|
|
|
* interface. It allows forwarding from that interface to the bridge.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveForwardRejectIn(virFirewallPtr fw,
|
|
|
|
virFirewallLayer layer,
|
2007-04-10 23:17:46 +00:00
|
|
|
const char *iface)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesForwardRejectIn(fw, layer, deletePrivate, iface, REMOVE);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-04-10 23:17:46 +00:00
|
|
|
|
|
|
|
/* Masquerade all traffic coming from the network associated
|
|
|
|
* with the bridge
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
static int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesForwardMasquerade(virFirewallPtr fw,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2014-03-06 17:01:13 +00:00
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-06-10 16:50:38 +00:00
|
|
|
const char *physdev,
|
2013-02-19 10:44:16 +00:00
|
|
|
virSocketAddrRangePtr addr,
|
|
|
|
virPortRangePtr port,
|
2010-06-10 16:50:38 +00:00
|
|
|
const char *protocol,
|
|
|
|
int action)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *networkstr = NULL;
|
|
|
|
g_autofree char *addrStartStr = NULL;
|
|
|
|
g_autofree char *addrEndStr = NULL;
|
|
|
|
g_autofree char *portRangeStr = NULL;
|
|
|
|
g_autofree char *natRangeStr = NULL;
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallRulePtr rule;
|
2020-06-08 13:28:20 +00:00
|
|
|
int af = VIR_SOCKET_ADDR_FAMILY(netaddr);
|
|
|
|
virFirewallLayer layer = af == AF_INET ?
|
|
|
|
VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2010-11-30 19:35:58 +00:00
|
|
|
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
return -1;
|
|
|
|
|
2020-06-08 13:28:20 +00:00
|
|
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->start, af)) {
|
2013-02-19 10:44:16 +00:00
|
|
|
if (!(addrStartStr = virSocketAddrFormat(&addr->start)))
|
2018-07-24 15:52:36 +00:00
|
|
|
return -1;
|
2020-06-08 13:28:20 +00:00
|
|
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->end, af)) {
|
2013-02-19 10:44:16 +00:00
|
|
|
if (!(addrEndStr = virSocketAddrFormat(&addr->end)))
|
2018-07-24 15:52:36 +00:00
|
|
|
return -1;
|
2013-02-19 10:44:14 +00:00
|
|
|
}
|
2011-01-04 17:31:40 +00:00
|
|
|
}
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
if (protocol && protocol[0]) {
|
2020-06-08 13:28:20 +00:00
|
|
|
rule = virFirewallAddRule(fw, layer,
|
2014-03-06 17:01:13 +00:00
|
|
|
"--table", "nat",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_PRT" : "POSTROUTING",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--source", networkstr,
|
|
|
|
"-p", protocol,
|
|
|
|
"!", "--destination", networkstr,
|
|
|
|
NULL);
|
|
|
|
} else {
|
2020-06-08 13:28:20 +00:00
|
|
|
rule = virFirewallAddRule(fw, layer,
|
2014-03-06 17:01:13 +00:00
|
|
|
"--table", "nat",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_PRT" : "POSTROUTING",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--source", networkstr,
|
|
|
|
"!", "--destination", networkstr,
|
|
|
|
NULL);
|
|
|
|
}
|
2013-02-04 09:45:23 +00:00
|
|
|
|
|
|
|
if (physdev && physdev[0])
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallRuleAddArgList(fw, rule, "--out-interface", physdev, NULL);
|
2013-02-04 09:45:23 +00:00
|
|
|
|
2013-02-19 10:44:15 +00:00
|
|
|
if (protocol && protocol[0]) {
|
2013-02-19 10:44:16 +00:00
|
|
|
if (port->start == 0 && port->end == 0) {
|
|
|
|
port->start = 1024;
|
|
|
|
port->end = 65535;
|
2013-02-19 10:44:15 +00:00
|
|
|
}
|
|
|
|
|
2013-02-19 10:44:16 +00:00
|
|
|
if (port->start < port->end && port->end < 65536) {
|
2019-10-22 13:26:14 +00:00
|
|
|
portRangeStr = g_strdup_printf(":%u-%u", port->start, port->end);
|
2013-02-19 10:44:15 +00:00
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Invalid port range '%u-%u'."),
|
2013-02-19 10:44:16 +00:00
|
|
|
port->start, port->end);
|
2019-10-22 13:26:14 +00:00
|
|
|
return -1;
|
2013-02-19 10:44:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 10:44:14 +00:00
|
|
|
/* Use --jump SNAT if public addr is specified */
|
|
|
|
if (addrStartStr && addrStartStr[0]) {
|
|
|
|
if (addrEndStr && addrEndStr[0]) {
|
2019-10-22 13:26:14 +00:00
|
|
|
natRangeStr = g_strdup_printf("%s-%s%s", addrStartStr, addrEndStr,
|
|
|
|
portRangeStr ? portRangeStr : "");
|
2013-02-19 10:44:14 +00:00
|
|
|
} else {
|
2019-10-22 13:26:14 +00:00
|
|
|
natRangeStr = g_strdup_printf("%s%s", addrStartStr,
|
|
|
|
portRangeStr ? portRangeStr : "");
|
2013-02-19 10:44:14 +00:00
|
|
|
}
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallRuleAddArgList(fw, rule,
|
|
|
|
"--jump", "SNAT",
|
2013-02-19 10:44:14 +00:00
|
|
|
"--to-source", natRangeStr, NULL);
|
2014-03-06 17:01:13 +00:00
|
|
|
} else {
|
|
|
|
virFirewallRuleAddArgList(fw, rule,
|
|
|
|
"--jump", "MASQUERADE", NULL);
|
2013-02-19 10:44:14 +00:00
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
if (portRangeStr && portRangeStr[0])
|
|
|
|
virFirewallRuleAddArgList(fw, rule,
|
|
|
|
"--to-ports", &portRangeStr[1], NULL);
|
|
|
|
}
|
2013-02-19 10:44:14 +00:00
|
|
|
|
2018-07-24 15:52:36 +00:00
|
|
|
return 0;
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesAddForwardMasquerade:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @physdev: the physical input device or NULL
|
2010-06-10 16:50:38 +00:00
|
|
|
* @protocol: the network protocol or NULL
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-06-29 13:23:13 +00:00
|
|
|
* Add rules to the IP table context to allow masquerading
|
|
|
|
* network @network on @physdev. This allow the bridge to
|
|
|
|
* masquerade for that network (on @physdev).
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesAddForwardMasquerade(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-06-10 16:50:38 +00:00
|
|
|
const char *physdev,
|
2013-02-19 10:44:16 +00:00
|
|
|
virSocketAddrRangePtr addr,
|
|
|
|
virPortRangePtr port,
|
2010-06-10 16:50:38 +00:00
|
|
|
const char *protocol)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardMasquerade(fw, true, netaddr, prefix,
|
|
|
|
physdev, addr, port, protocol, ADD);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 13:23:13 +00:00
|
|
|
/**
|
|
|
|
* iptablesRemoveForwardMasquerade:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @network: the source network name
|
|
|
|
* @physdev: the physical input device or NULL
|
2010-06-10 16:50:38 +00:00
|
|
|
* @protocol: the network protocol or NULL
|
2008-02-05 19:27:37 +00:00
|
|
|
*
|
2007-06-29 13:23:13 +00:00
|
|
|
* Remove rules from the IP table context to stop masquerading
|
|
|
|
* network @network on @physdev. This stops the bridge from
|
|
|
|
* masquerading for that network (on @physdev).
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise
|
|
|
|
*/
|
2007-02-14 16:26:42 +00:00
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesRemoveForwardMasquerade(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2010-11-30 19:35:58 +00:00
|
|
|
unsigned int prefix,
|
2010-06-10 16:50:38 +00:00
|
|
|
const char *physdev,
|
2013-02-19 10:44:16 +00:00
|
|
|
virSocketAddrRangePtr addr,
|
|
|
|
virPortRangePtr port,
|
2010-06-10 16:50:38 +00:00
|
|
|
const char *protocol)
|
2007-02-14 16:26:42 +00:00
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardMasquerade(fw, deletePrivate, netaddr, prefix,
|
|
|
|
physdev, addr, port, protocol, REMOVE);
|
2007-02-14 16:26:42 +00:00
|
|
|
}
|
2010-07-13 02:59:58 +00:00
|
|
|
|
|
|
|
|
2013-09-25 10:45:25 +00:00
|
|
|
/* Don't masquerade traffic coming from the network associated with the bridge
|
|
|
|
* if said traffic targets @destaddr.
|
|
|
|
*/
|
|
|
|
static int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesForwardDontMasquerade(virFirewallPtr fw,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2014-03-06 17:01:13 +00:00
|
|
|
virSocketAddr *netaddr,
|
2013-09-25 10:45:25 +00:00
|
|
|
unsigned int prefix,
|
|
|
|
const char *physdev,
|
|
|
|
const char *destaddr,
|
|
|
|
int action)
|
|
|
|
{
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *networkstr = NULL;
|
2020-06-08 13:28:20 +00:00
|
|
|
virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ?
|
|
|
|
VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6;
|
2013-09-25 10:45:25 +00:00
|
|
|
|
|
|
|
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (physdev && physdev[0])
|
2020-06-08 13:28:20 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
2014-03-06 17:01:13 +00:00
|
|
|
"--table", "nat",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_PRT" : "POSTROUTING",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--out-interface", physdev,
|
|
|
|
"--source", networkstr,
|
|
|
|
"--destination", destaddr,
|
|
|
|
"--jump", "RETURN",
|
|
|
|
NULL);
|
|
|
|
else
|
2020-06-08 13:28:20 +00:00
|
|
|
virFirewallAddRule(fw, layer,
|
2014-03-06 17:01:13 +00:00
|
|
|
"--table", "nat",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_PRT" : "POSTROUTING",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--source", networkstr,
|
|
|
|
"--destination", destaddr,
|
|
|
|
"--jump", "RETURN",
|
|
|
|
NULL);
|
|
|
|
|
2018-07-24 15:52:36 +00:00
|
|
|
return 0;
|
2013-09-25 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iptablesAddDontMasquerade:
|
|
|
|
* @netaddr: the source network name
|
|
|
|
* @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
|
|
|
|
* @physdev: the physical output device or NULL
|
|
|
|
* @destaddr: the destination network not to masquerade for
|
|
|
|
*
|
|
|
|
* Add rules to the IP table context to avoid masquerading from
|
|
|
|
* @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
|
|
|
|
* directly consumable by iptables, it must not depend on user input or
|
|
|
|
* configuration.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise.
|
|
|
|
*/
|
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesAddDontMasquerade(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2013-09-25 10:45:25 +00:00
|
|
|
unsigned int prefix,
|
|
|
|
const char *physdev,
|
|
|
|
const char *destaddr)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardDontMasquerade(fw, true, netaddr, prefix,
|
|
|
|
physdev, destaddr, ADD);
|
2013-09-25 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iptablesRemoveDontMasquerade:
|
|
|
|
* @netaddr: the source network name
|
|
|
|
* @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
|
|
|
|
* @physdev: the physical output device or NULL
|
|
|
|
* @destaddr: the destination network not to masquerade for
|
|
|
|
*
|
|
|
|
* Remove rules from the IP table context that prevent masquerading from
|
|
|
|
* @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
|
|
|
|
* directly consumable by iptables, it must not depend on user input or
|
|
|
|
* configuration.
|
|
|
|
*
|
|
|
|
* Returns 0 in case of success or an error code otherwise.
|
|
|
|
*/
|
|
|
|
int
|
2014-03-06 17:01:13 +00:00
|
|
|
iptablesRemoveDontMasquerade(virFirewallPtr fw,
|
|
|
|
virSocketAddr *netaddr,
|
2013-09-25 10:45:25 +00:00
|
|
|
unsigned int prefix,
|
|
|
|
const char *physdev,
|
|
|
|
const char *destaddr)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
return iptablesForwardDontMasquerade(fw, deletePrivate, netaddr, prefix,
|
|
|
|
physdev, destaddr, REMOVE);
|
2013-09-25 10:45:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
static void
|
|
|
|
iptablesOutputFixUdpChecksum(virFirewallPtr fw,
|
2018-12-05 15:53:55 +00:00
|
|
|
bool pvt,
|
2014-03-06 17:01:13 +00:00
|
|
|
const char *iface,
|
2010-07-13 02:59:58 +00:00
|
|
|
int port,
|
|
|
|
int action)
|
|
|
|
{
|
|
|
|
char portstr[32];
|
|
|
|
|
2019-11-13 13:53:42 +00:00
|
|
|
g_snprintf(portstr, sizeof(portstr), "%d", port);
|
2010-07-13 02:59:58 +00:00
|
|
|
portstr[sizeof(portstr) - 1] = '\0';
|
|
|
|
|
2014-03-06 17:01:13 +00:00
|
|
|
virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4,
|
|
|
|
"--table", "mangle",
|
2018-12-05 15:53:55 +00:00
|
|
|
action == ADD ? "--insert" : "--delete",
|
|
|
|
pvt ? "LIBVIRT_PRT" : "POSTROUTING",
|
2014-03-06 17:01:13 +00:00
|
|
|
"--out-interface", iface,
|
|
|
|
"--protocol", "udp",
|
|
|
|
"--destination-port", portstr,
|
|
|
|
"--jump", "CHECKSUM", "--checksum-fill",
|
|
|
|
NULL);
|
2010-07-13 02:59:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iptablesAddOutputFixUdpChecksum:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the UDP port to match
|
|
|
|
*
|
2011-12-04 00:06:07 +00:00
|
|
|
* Add a rule to the mangle table's POSTROUTING chain that fixes up the
|
2010-07-13 02:59:58 +00:00
|
|
|
* checksum of packets with the given destination @port.
|
|
|
|
* the given @iface interface for TCP packets.
|
|
|
|
*
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesAddOutputFixUdpChecksum(virFirewallPtr fw,
|
|
|
|
const char *iface,
|
2010-07-13 02:59:58 +00:00
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesOutputFixUdpChecksum(fw, true, iface, port, ADD);
|
2010-07-13 02:59:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* iptablesRemoveOutputFixUdpChecksum:
|
|
|
|
* @ctx: pointer to the IP table context
|
|
|
|
* @iface: the interface name
|
|
|
|
* @port: the UDP port of the rule to remove
|
|
|
|
*
|
|
|
|
* Removes the checksum fixup rule that was previous added with
|
|
|
|
* iptablesAddOutputFixUdpChecksum.
|
|
|
|
*/
|
2014-03-06 17:01:13 +00:00
|
|
|
void
|
|
|
|
iptablesRemoveOutputFixUdpChecksum(virFirewallPtr fw,
|
|
|
|
const char *iface,
|
2010-07-13 02:59:58 +00:00
|
|
|
int port)
|
|
|
|
{
|
2018-12-05 15:53:55 +00:00
|
|
|
iptablesOutputFixUdpChecksum(fw, deletePrivate, iface, port, REMOVE);
|
2010-07-13 02:59:58 +00:00
|
|
|
}
|