mirror of https://github.com/apache/cloudstack.git
Merge 6d8746f15a into b7d4df0a11
This commit is contained in:
commit
9c293ee8f6
|
|
@ -28,6 +28,7 @@ import com.cloud.network.rules.StaticNatRule;
|
|||
|
||||
public class StaticNatRuleTO extends FirewallRuleTO {
|
||||
String dstIp;
|
||||
boolean shouldApplyCrossNetworkSnat = false;
|
||||
|
||||
protected StaticNatRuleTO() {
|
||||
}
|
||||
|
|
@ -79,4 +80,12 @@ public class StaticNatRuleTO extends FirewallRuleTO {
|
|||
return dstIp;
|
||||
}
|
||||
|
||||
public boolean isShouldApplyCrossNetworkSnat() {
|
||||
return shouldApplyCrossNetworkSnat;
|
||||
}
|
||||
|
||||
public void setShouldApplyCrossNetworkSnat(boolean shouldApplyCrossNetworkSnat) {
|
||||
this.shouldApplyCrossNetworkSnat = shouldApplyCrossNetworkSnat;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ public class SetStaticNatRulesConfigItem extends AbstractConfigItemFacade {
|
|||
|
||||
final LinkedList<StaticNatRule> rules = new LinkedList<>();
|
||||
for (final StaticNatRuleTO rule : command.getRules()) {
|
||||
final StaticNatRule staticNatRule = new StaticNatRule(rule.revoked(), rule.getProtocol(), rule.getSrcIp(), rule.getStringSrcPortRange(), rule.getDstIp());
|
||||
final StaticNatRule staticNatRule = new StaticNatRule(rule.revoked(), rule.getProtocol(), rule.getSrcIp(),
|
||||
rule.getStringSrcPortRange(), rule.getDstIp(), rule.isShouldApplyCrossNetworkSnat());
|
||||
rules.add(staticNatRule);
|
||||
}
|
||||
final StaticNatRules staticNatRules = new StaticNatRules(rules);
|
||||
|
|
|
|||
|
|
@ -25,18 +25,25 @@ public class StaticNatRule {
|
|||
private String sourceIpAddress;
|
||||
private String sourcePortRange;
|
||||
private String destinationIpAddress;
|
||||
private boolean shouldApplyCrossNetworkSnat = false;
|
||||
|
||||
public StaticNatRule() {
|
||||
// Empty constructor for (de)serialization
|
||||
}
|
||||
|
||||
public StaticNatRule(boolean revoke, String protocol, String sourceIpAddress, String sourcePortRange, String destinationIpAddress) {
|
||||
this(revoke, protocol, sourceIpAddress, sourcePortRange, destinationIpAddress, false);
|
||||
}
|
||||
|
||||
public StaticNatRule(boolean revoke, String protocol, String sourceIpAddress, String sourcePortRange,
|
||||
String destinationIpAddress, boolean shouldApplyCrossNetworkSnat) {
|
||||
super();
|
||||
this.revoke = revoke;
|
||||
this.protocol = protocol;
|
||||
this.sourceIpAddress = sourceIpAddress;
|
||||
this.sourcePortRange = sourcePortRange;
|
||||
this.destinationIpAddress = destinationIpAddress;
|
||||
this.shouldApplyCrossNetworkSnat = shouldApplyCrossNetworkSnat;
|
||||
}
|
||||
|
||||
public boolean isRevoke() {
|
||||
|
|
@ -79,4 +86,12 @@ public class StaticNatRule {
|
|||
this.destinationIpAddress = destinationIpAddress;
|
||||
}
|
||||
|
||||
public boolean isShouldApplyCrossNetworkSnat() {
|
||||
return shouldApplyCrossNetworkSnat;
|
||||
}
|
||||
|
||||
public void setShouldApplyCrossNetworkSnat(boolean shouldApplyCrossNetworkSnat) {
|
||||
this.shouldApplyCrossNetworkSnat = shouldApplyCrossNetworkSnat;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -446,6 +446,7 @@ public class CommandSetupHelper {
|
|||
for (final StaticNatRule rule : rules) {
|
||||
final IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
|
||||
final StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule, null, sourceIp.getAddress().addr(), rule.getDestIpAddress());
|
||||
ruleTO.setShouldApplyCrossNetworkSnat(requiresReturnPathSnat(guestNetworkId, rule.getDestIpAddress()));
|
||||
rulesTO.add(ruleTO);
|
||||
}
|
||||
}
|
||||
|
|
@ -459,6 +460,25 @@ public class CommandSetupHelper {
|
|||
cmds.addCommand(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method determines whether to use network-wide SNAT or NIC aware SNAT
|
||||
* @param networkId
|
||||
* @param destinationIp
|
||||
* @return
|
||||
*/
|
||||
private boolean requiresReturnPathSnat(final long networkId, final String destinationIp) {
|
||||
if (!VirtualNetworkApplianceManager.NicSnatEnabled.value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final NicVO destinationNic = _nicDao.findByIp4AddressAndNetworkId(destinationIp, networkId);
|
||||
if (destinationNic == null) {
|
||||
logger.debug("Unable to find destination NIC for ip [{}] in network [{}], assuming default NIC.", destinationIp, networkId);
|
||||
return false;
|
||||
}
|
||||
return !destinationNic.isDefaultNic();
|
||||
}
|
||||
|
||||
public void createApplyFirewallRulesCommands(final List<? extends FirewallRule> rules, final VirtualRouter router, final Commands cmds, final long guestNetworkId) {
|
||||
final List<FirewallRuleTO> rulesTO = new ArrayList<>();
|
||||
String systemRule = null;
|
||||
|
|
@ -697,6 +717,7 @@ public class CommandSetupHelper {
|
|||
final IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
|
||||
final StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(),
|
||||
false);
|
||||
ruleTO.setShouldApplyCrossNetworkSnat(requiresReturnPathSnat(guestNetworkId, rule.getDestIpAddress()));
|
||||
rulesTO.add(ruleTO);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
|
|||
String RouterHealthChecksResultFetchIntervalCK = "router.health.checks.results.fetch.interval";
|
||||
String RouterHealthChecksFailuresToRecreateVrCK = "router.health.checks.failures.to.recreate.vr";
|
||||
String RemoveControlIpOnStopCK = "systemvm.release.control.ip.on.stop";
|
||||
String UseNicAwareSnat = "network.nic.snat.enabled";
|
||||
|
||||
ConfigKey<String> RouterTemplateXen = new ConfigKey<>(String.class, RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)",
|
||||
"Name of the default router template on Xenserver.", true, ConfigKey.Scope.Zone, null);
|
||||
|
|
@ -131,6 +132,17 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
|
|||
ConfigKey<Boolean> RemoveControlIpOnStop = new ConfigKey<>(Boolean.class, RemoveControlIpOnStopCK, "Advanced", "true",
|
||||
"on stopping routers and system VMs the IP will be released to preserve IPv4 space.", true, ConfigKey.Scope.Zone, null);
|
||||
|
||||
ConfigKey<Boolean> NicSnatEnabled = new ConfigKey<>(Boolean.class,
|
||||
UseNicAwareSnat,
|
||||
"Advanced",
|
||||
"false",
|
||||
"When enabled, Virtual Router overwrites the SNAT source IP in POSTROUTING for traffic exiting " +
|
||||
"non-default NICs. The SNAT source is selected based on the egress interface to preserve return path " +
|
||||
"consistency in multi-NIC configurations.",
|
||||
true,
|
||||
ConfigKey.Scope.Global,
|
||||
null);
|
||||
|
||||
int DEFAULT_ROUTER_VM_RAMSIZE = 256; // 256M
|
||||
int DEFAULT_ROUTER_CPU_MHZ = 500; // 500 MHz
|
||||
boolean USE_POD_VLAN = false;
|
||||
|
|
|
|||
|
|
@ -3382,7 +3382,8 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
|||
ExposeDnsAndBootpServer,
|
||||
RouterLogrotateFrequency,
|
||||
RemoveControlIpOnStop,
|
||||
VirtualRouterUserData
|
||||
VirtualRouterUserData,
|
||||
NicSnatEnabled
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1448,7 +1448,7 @@ class CsForwardingRules(CsDataBag):
|
|||
)
|
||||
fw4 = "-j SNAT --to-source %s -A POSTROUTING -s %s -d %s/32 -o %s -p %s -m %s --dport %s" % \
|
||||
(
|
||||
self.getGuestIp(),
|
||||
self.getGuestIpByIp(rule['internal_ip']),
|
||||
self.getNetworkByIp(rule['internal_ip']),
|
||||
rule['internal_ip'],
|
||||
internal_fwinterface,
|
||||
|
|
@ -1563,11 +1563,20 @@ class CsForwardingRules(CsDataBag):
|
|||
self.fw.append(["filter", "",
|
||||
"-A FORWARD -i %s -o eth0 -d %s -m state --state NEW -j ACCEPT " % (device, rule["internal_ip"])])
|
||||
|
||||
# Configure the hairpin snat
|
||||
self.fw.append(["nat", "front", "-A POSTROUTING -s %s -d %s -j SNAT -o %s --to-source %s" %
|
||||
# Configure the hairpin snat for default nic or nic-aware snat for non-default
|
||||
apply_cross_network_snat = rule.get("should_apply_cross_network_snat", False)
|
||||
if apply_cross_network_snat:
|
||||
internal_device = self.getDeviceByIp(rule["internal_ip"])
|
||||
internal_vr_ip = self.getGuestIpByIp(rule["internal_ip"])
|
||||
if internal_device and internal_vr_ip and internal_device != device:
|
||||
self.fw.append(["nat", "front",
|
||||
"-A POSTROUTING -o %s -d %s/32 -j SNAT --to-source %s" % (internal_device, rule["internal_ip"], internal_vr_ip)])
|
||||
else:
|
||||
self.fw.append(["nat", "front", "-A POSTROUTING -s %s -d %s -j SNAT -o %s --to-source %s" %
|
||||
(self.getNetworkByIp(rule['internal_ip']), rule["internal_ip"], self.getDeviceByIp(rule["internal_ip"]), self.getGuestIpByIp(rule["internal_ip"]))])
|
||||
|
||||
|
||||
|
||||
class IpTablesExecutor:
|
||||
|
||||
config = None
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ def merge(dbag, rules):
|
|||
newrule = dict()
|
||||
newrule["public_ip"] = source_ip
|
||||
newrule["internal_ip"] = destination_ip
|
||||
if "should_apply_cross_network_snat" in rule:
|
||||
newrule["should_apply_cross_network_snat"] = rule["should_apply_cross_network_snat"]
|
||||
|
||||
if rules["type"] == "staticnatrules":
|
||||
newrule["type"] = "staticnat"
|
||||
|
|
|
|||
Loading…
Reference in New Issue