/* Allow all traffic destined to the bridge, with a valid network address */ static int iptablesForwardAllowIn(virFirewallPtr fw, virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev, int action) { virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ? VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; VIR_AUTOFREE(char *) networkstr = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; if (physdev && physdev[0]) virFirewallAddRule(fw, layer, "--table", "filter", action == ADD ? "--insert" : "--delete", "FORWARD", "--destination", networkstr, "--in-interface", physdev, "--out-interface", iface, "--jump", "ACCEPT", NULL); else virFirewallAddRule(fw, layer, "--table", "filter", action == ADD ? "--insert" : "--delete", "FORWARD", "--destination", networkstr, "--out-interface", iface, "--jump", "ACCEPT", NULL); return 0; }
int ebtablesAddForwardPolicyReject(ebtablesContext *ctx) { virFirewallPtr fw = NULL; int ret = -1; fw = virFirewallNew(); virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, "--new-chain", ctx->chain, NULL); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, "--insert", "FORWARD", "--jump", ctx->chain, NULL); virFirewallStartTransaction(fw, 0); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, "-P", ctx->chain, "DROP", NULL); if (virFirewallApply(fw) < 0) goto cleanup; ret = 0; cleanup: virFirewallFree(fw); return ret; }
static int testFirewallSingleGroup(const void *opaque) { virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; virFirewallPtr fw = NULL; int ret = -1; const char *actual = NULL; const char *expected = IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; const struct testFirewallData *data = opaque; fwDisabled = data->fwDisabled; if (virFirewallSetBackend(data->tryBackend) < 0) goto cleanup; if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) virCommandSetDryRun(&cmdbuf, NULL, NULL); else fwBuf = &cmdbuf; fw = virFirewallNew(); virFirewallStartTransaction(fw, 0); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "-A", "INPUT", "--source-host", "192.168.122.1", "--jump", "ACCEPT", NULL); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "-A", "INPUT", "--source-host", "!192.168.122.1", "--jump", "REJECT", NULL); if (virFirewallApply(fw) < 0) goto cleanup; if (virBufferError(&cmdbuf)) goto cleanup; actual = virBufferCurrentContent(&cmdbuf); if (STRNEQ_NULLABLE(expected, actual)) { fprintf(stderr, "Unexected command execution\n"); virTestDifference(stderr, expected, actual); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(&cmdbuf); fwBuf = NULL; virCommandSetDryRun(NULL, NULL, NULL); virFirewallFree(fw); return ret; }
/* * Allow all traffic destined to the bridge, with a valid network address */ static int ebtablesForwardAllowIn(ebtablesContext *ctx, const char *iface, const char *macaddr, int action) { virFirewallPtr fw = NULL; int ret = -1; fw = virFirewallNew(); virFirewallStartTransaction(fw, 0); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET, action == ADD ? "--insert" : "--delete", ctx->chain, "--in-interface", iface, "--source", macaddr, "--jump", "ACCEPT", NULL); if (virFirewallApply(fw) < 0) goto cleanup; ret = 0; cleanup: virFirewallFree(fw); return ret; }
/* Don't masquerade traffic coming from the network associated with the bridge * if said traffic targets @destaddr. */ static int iptablesForwardDontMasquerade(virFirewallPtr fw, virSocketAddr *netaddr, unsigned int prefix, const char *physdev, const char *destaddr, int action) { VIR_AUTOFREE(char *) networkstr = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) { /* Higher level code *should* guaranteee it's impossible to get here. */ virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempted to NAT '%s'. NAT is only supported for IPv4."), networkstr); return -1; } if (physdev && physdev[0]) virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "nat", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--out-interface", physdev, "--source", networkstr, "--destination", destaddr, "--jump", "RETURN", NULL); else virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "nat", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--source", networkstr, "--destination", destaddr, "--jump", "RETURN", NULL); return 0; }
/** * 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 */ void iptablesRemoveForwardRejectIn(virFirewallPtr fw, virFirewallLayer layer, const char *iface) { virFirewallAddRule(fw, layer, "--table", "filter", "--delete", "FORWARD", "--out-interface", iface, "--jump", "REJECT", NULL); }
/** * 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 */ void iptablesAddForwardRejectOut(virFirewallPtr fw, virFirewallLayer layer, const char *iface) { virFirewallAddRule(fw, layer, "--table", "filter", "--insert", "FORWARD", "--in-interface", iface, "--jump", "REJECT", NULL); }
/** * 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 */ void iptablesRemoveForwardAllowCross(virFirewallPtr fw, virFirewallLayer layer, const char *iface) { virFirewallAddRule(fw, layer, "--table", "filter", "--delete", "FORWARD", "--in-interface", iface, "--out-interface", iface, "--jump", "ACCEPT", NULL); }
static void iptablesOutputFixUdpChecksum(virFirewallPtr fw, const char *iface, int port, int action) { char portstr[32]; snprintf(portstr, sizeof(portstr), "%d", port); portstr[sizeof(portstr) - 1] = '\0'; virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "mangle", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--out-interface", iface, "--protocol", "udp", "--destination-port", portstr, "--jump", "CHECKSUM", "--checksum-fill", NULL); }
static void iptablesOutput(virFirewallPtr fw, virFirewallLayer layer, const char *iface, int port, int action, int tcp) { char portstr[32]; snprintf(portstr, sizeof(portstr), "%d", port); portstr[sizeof(portstr) - 1] = '\0'; virFirewallAddRule(fw, layer, "--table", "filter", action == ADD ? "--insert" : "--delete", "OUTPUT", "--out-interface", iface, "--protocol", tcp ? "tcp" : "udp", "--destination-port", portstr, "--jump", "ACCEPT", NULL); }
/* Masquerade all traffic coming from the network associated * with the bridge */ static int iptablesForwardMasquerade(virFirewallPtr fw, virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, virPortRangePtr port, const char *protocol, int action) { VIR_AUTOFREE(char *) networkstr = NULL; VIR_AUTOFREE(char *) addrStartStr = NULL; VIR_AUTOFREE(char *) addrEndStr = NULL; VIR_AUTOFREE(char *) portRangeStr = NULL; VIR_AUTOFREE(char *) natRangeStr = NULL; virFirewallRulePtr rule; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) { /* Higher level code *should* guaranteee it's impossible to get here. */ virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempted to NAT '%s'. NAT is only supported for IPv4."), networkstr); return -1; } if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->start, AF_INET)) { if (!(addrStartStr = virSocketAddrFormat(&addr->start))) return -1; if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->end, AF_INET)) { if (!(addrEndStr = virSocketAddrFormat(&addr->end))) return -1; } } if (protocol && protocol[0]) { rule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "nat", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--source", networkstr, "-p", protocol, "!", "--destination", networkstr, NULL); } else { rule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "nat", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--source", networkstr, "!", "--destination", networkstr, NULL); } if (physdev && physdev[0]) virFirewallRuleAddArgList(fw, rule, "--out-interface", physdev, NULL); if (protocol && protocol[0]) { if (port->start == 0 && port->end == 0) { port->start = 1024; port->end = 65535; } if (port->start < port->end && port->end < 65536) { if (virAsprintf(&portRangeStr, ":%u-%u", port->start, port->end) < 0) return -1; } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid port range '%u-%u'."), port->start, port->end); } } /* Use --jump SNAT if public addr is specified */ if (addrStartStr && addrStartStr[0]) { int r = 0; if (addrEndStr && addrEndStr[0]) { r = virAsprintf(&natRangeStr, "%s-%s%s", addrStartStr, addrEndStr, portRangeStr ? portRangeStr : ""); } else { r = virAsprintf(&natRangeStr, "%s%s", addrStartStr, portRangeStr ? portRangeStr : ""); } if (r < 0) return -1; virFirewallRuleAddArgList(fw, rule, "--jump", "SNAT", "--to-source", natRangeStr, NULL); } else { virFirewallRuleAddArgList(fw, rule, "--jump", "MASQUERADE", NULL); if (portRangeStr && portRangeStr[0]) virFirewallRuleAddArgList(fw, rule, "--to-ports", &portRangeStr[1], NULL); } return 0; }