mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fixed Port forwarding (DNAT/SNAT) for isolated networks
Fixed failure on using eth10 (which CS now supports) Refactored CSForward to us CsInterface object instead of teh way it was kludged together Fixed hex conversion for device numbers and iptables marks
This commit is contained in:
parent
6fc680be71
commit
7bfccd699b
@ -496,15 +496,22 @@ class CsForwardingRules(CsDataBag):
|
||||
elif rule["type"] == "staticnat":
|
||||
self.processStaticNatRule(rule)
|
||||
|
||||
def getDeviceByIp(self, ip):
|
||||
ips = CsDataBag("ips")
|
||||
dbag = ips.get_bag()
|
||||
for device in dbag:
|
||||
if device == "id":
|
||||
continue
|
||||
for addy in dbag[device]:
|
||||
if addy["public_ip"] == ip:
|
||||
return device
|
||||
def getDeviceByIp(self, ipa):
|
||||
for ip in self.config.address().get_ips():
|
||||
if ip.ip_in_subnet(ipa):
|
||||
return ip.get_device()
|
||||
return None
|
||||
|
||||
def getNetworkByIp(self, ipa):
|
||||
for ip in self.config.address().get_ips():
|
||||
if ip.ip_in_subnet(ipa):
|
||||
return ip.get_network()
|
||||
return None
|
||||
|
||||
def getGatewayByIp(self, ipa):
|
||||
for ip in self.config.address().get_ips():
|
||||
if ip.ip_in_subnet(ipa):
|
||||
return ip.get_gateway()
|
||||
return None
|
||||
|
||||
def portsToString(self, ports, delimiter):
|
||||
@ -515,7 +522,70 @@ class CsForwardingRules(CsDataBag):
|
||||
return "%s%s%s" % (ports_parts[0], delimiter, ports_parts[1])
|
||||
|
||||
def processForwardRule(self, rule):
|
||||
# FIXME this seems to be different for regular VRs?
|
||||
if self.config.is_vpc():
|
||||
self.forward_vpc(rule)
|
||||
else:
|
||||
self.forward_vr(rule)
|
||||
|
||||
def forward_vr(self, rule):
|
||||
fw1 = "-A PREROUTING -d %s/32 -i %s -p %s -m %s --dport %s -j DNAT --to-destination %s:%s" % \
|
||||
( rule['public_ip'],
|
||||
self.getDeviceByIp(rule['public_ip']),
|
||||
rule['protocol'],
|
||||
rule['protocol'],
|
||||
self.portsToString(rule['public_ports'], ':'),
|
||||
rule['internal_ip'],
|
||||
self.portsToString(rule['internal_ports'], '-')
|
||||
)
|
||||
fw2 = "-A PREROUTING -d %s/32 -i %s -p %s -m %s --dport %s -j DNAT --to-destination %s:%s" % \
|
||||
( rule['public_ip'],
|
||||
self.getDeviceByIp(rule['internal_ip']),
|
||||
rule['protocol'],
|
||||
rule['protocol'],
|
||||
self.portsToString(rule['public_ports'], ':'),
|
||||
rule['internal_ip'],
|
||||
self.portsToString(rule['internal_ports'], '-')
|
||||
)
|
||||
fw3 = "-A OUTPUT -d %s/32 -p %s -m %s --dport %s -j DNAT --to-destination %s:%s" % \
|
||||
( rule['public_ip'],
|
||||
rule['protocol'],
|
||||
rule['protocol'],
|
||||
self.portsToString(rule['public_ports'], ':'),
|
||||
rule['internal_ip'],
|
||||
self.portsToString(rule['internal_ports'], '-')
|
||||
)
|
||||
fw4 = "-j SNAT --to-source %s -A POSTROUTING -s %s -d %s/32 -o %s -p %s -m %s --dport %s" % \
|
||||
( self.getGatewayByIp(rule['internal_ip']),
|
||||
self.getNetworkByIp(rule['internal_ip']),
|
||||
rule['internal_ip'],
|
||||
self.getDeviceByIp(rule['internal_ip']),
|
||||
rule['protocol'],
|
||||
rule['protocol'],
|
||||
self.portsToString(rule['internal_ports'], ':')
|
||||
)
|
||||
fw5 = "-A PREROUTING -d %s/32 -i %s -p %s -m %s --dport %s -j MARK --set-xmark %s/0xffffffff" % \
|
||||
( rule['public_ip'],
|
||||
self.getDeviceByIp(rule['public_ip']),
|
||||
rule['protocol'],
|
||||
rule['protocol'],
|
||||
self.portsToString(rule['public_ports'], ':'),
|
||||
hex(int(self.getDeviceByIp(rule['public_ip'])[3:]))
|
||||
)
|
||||
fw6 = "-A PREROUTING -d %s/32 -i %s -p %s -m %s --dport %s -m state --state NEW -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff" % \
|
||||
( rule['public_ip'],
|
||||
self.getDeviceByIp(rule['public_ip']),
|
||||
rule['protocol'],
|
||||
rule['protocol'],
|
||||
self.portsToString(rule['public_ports'], ':'),
|
||||
)
|
||||
self.fw.append(["nat", "", fw1])
|
||||
self.fw.append(["nat", "", fw2])
|
||||
self.fw.append(["nat", "", fw3])
|
||||
self.fw.append(["nat", "", fw4])
|
||||
self.fw.append(["nat", "", fw5])
|
||||
self.fw.append(["nat", "", fw6])
|
||||
|
||||
def forward_vpc(self, rule):
|
||||
fwrule = "-A PREROUTING -d %s/32" % rule["public_ip"]
|
||||
if not rule["protocol"] == "any":
|
||||
fwrule += " -m %s -p %s" % (rule["protocol"], rule["protocol"])
|
||||
|
||||
@ -19,6 +19,7 @@ from CsDatabag import CsDataBag, CsCmdLine
|
||||
from CsApp import CsApache, CsDnsmasq, CsPasswdSvc
|
||||
import CsHelper
|
||||
import logging
|
||||
from netaddr import IPAddress, IPNetwork
|
||||
import CsHelper
|
||||
|
||||
import subprocess
|
||||
@ -118,6 +119,9 @@ class CsInterface:
|
||||
def get_ip(self):
|
||||
return self.get_attr("public_ip")
|
||||
|
||||
def get_network(self):
|
||||
return self.get_attr("network")
|
||||
|
||||
def get_netmask(self):
|
||||
return self.get_attr("netmask")
|
||||
|
||||
@ -125,7 +129,15 @@ class CsInterface:
|
||||
if self.config.is_vpc():
|
||||
return self.get_attr("gateway")
|
||||
else:
|
||||
return self.config.cmdline().get_guest_gw()
|
||||
if self.config.cmdline().is_redundant():
|
||||
return self.config.cmdline().get_guest_gw()
|
||||
else:
|
||||
return self.get_ip()
|
||||
|
||||
def ip_in_subnet(self, ip):
|
||||
ipo = IPAddress(ip)
|
||||
net = IPNetwork("%s/%s" % (self.get_ip(), self.get_size()))
|
||||
return ipo in list(net)
|
||||
|
||||
def get_gateway_cidr(self):
|
||||
return "%s/%s" % (self.get_gateway(), self.get_size())
|
||||
@ -185,7 +197,7 @@ class CsDevice:
|
||||
self.table = ''
|
||||
self.tableNo = ''
|
||||
if dev != '':
|
||||
self.tableNo = dev[3]
|
||||
self.tableNo = dev[3:]
|
||||
self.table = "Table_%s" % dev
|
||||
self.fw = config.get_fw()
|
||||
self.cl = config.cmdline()
|
||||
@ -228,7 +240,7 @@ class CsIP:
|
||||
|
||||
def __init__(self, dev, config):
|
||||
self.dev = dev
|
||||
self.dnum = dev[3]
|
||||
self.dnum = hex(int(dev[3:]))
|
||||
self.iplist = {}
|
||||
self.address = {}
|
||||
self.list()
|
||||
@ -275,8 +287,8 @@ class CsIP:
|
||||
CsHelper.execute(cmd2)
|
||||
|
||||
def set_mark(self):
|
||||
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-xmark 0x%s/0xffffffff" % \
|
||||
(self.getDevice(), self.getDevice()[3])
|
||||
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-xmark %s/0xffffffff" % \
|
||||
(self.getDevice(), self.dnum)
|
||||
self.fw.append(["mangle", "", cmd])
|
||||
|
||||
def get_type(self):
|
||||
@ -327,7 +339,7 @@ class CsIP:
|
||||
"-A POSTROUTING -o eth2 -j SNAT --to-source %s" % self.address['public_ip']])
|
||||
self.fw.append(["mangle", "",
|
||||
"-A PREROUTING -i %s -m state --state NEW " % self.dev +
|
||||
"-j CONNMARK --set-xmark 0x%s/0xffffffff" % self.dnum])
|
||||
"-j CONNMARK --set-xmark %s/0xffffffff" % self.dnum])
|
||||
self.fw.append(["mangle", "", "-A FIREWALL_%s -j DROP" % self.address['public_ip']])
|
||||
|
||||
self.fw.append(["filter", "", "-A INPUT -d 224.0.0.18/32 -j ACCEPT"])
|
||||
@ -350,7 +362,7 @@ class CsIP:
|
||||
self.fw.append(["filter", "", "-A FORWARD -i eth0 -o eth2 -j FW_OUTBOUND"])
|
||||
self.fw.append(["mangle", "",
|
||||
"-A PREROUTING -i %s -m state --state NEW " % self.dev +
|
||||
"-j CONNMARK --set-xmark 0x%s/0xffffffff" % self.dnum])
|
||||
"-j CONNMARK --set-xmark %s/0xffffffff" % self.dnum])
|
||||
|
||||
if self.get_type() in ["control"]:
|
||||
self.fw.append(["filter", "", "-A FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT"])
|
||||
|
||||
@ -62,6 +62,14 @@ class CsCmdLine(CsDataBag):
|
||||
return self.idata()['router_pr']
|
||||
return 99
|
||||
|
||||
def set_guest_gw(self, val):
|
||||
self.idata()['guestgw'] = val
|
||||
|
||||
def get_guest_gw(self):
|
||||
if "guestgw" in self.idata():
|
||||
return self.idata()['guestgw']
|
||||
return False
|
||||
|
||||
def set_priority(self, val):
|
||||
self.idata()['router_pr'] = val
|
||||
|
||||
@ -73,21 +81,6 @@ class CsCmdLine(CsDataBag):
|
||||
def set_redundant(self, val="true"):
|
||||
self.idata()['redundant_router'] = val
|
||||
|
||||
def set_guest_gw(self, val):
|
||||
self.idata()['guestgw'] = val
|
||||
|
||||
def get_guest_gw(self):
|
||||
if "guestgw" in self.idata():
|
||||
return self.idata()['guestgw']
|
||||
else:
|
||||
return "1.2.3.4"
|
||||
|
||||
def get_guest_gw_cidr(self):
|
||||
if "guestgw" in self.idata():
|
||||
return "%s/%s" % (self.idata()['guestgw'], self.idata()['guestcidrsize'])
|
||||
else:
|
||||
return "1.2.3.4/8"
|
||||
|
||||
def get_name(self):
|
||||
if "name" in self.idata():
|
||||
return self.idata()['name']
|
||||
|
||||
@ -98,7 +98,7 @@ class CsDhcp(CsDataBag):
|
||||
to = {"device": bits[0],
|
||||
"mac": bits[1],
|
||||
"ip": bits[2],
|
||||
"host": bits[3],
|
||||
"host": bits[3:],
|
||||
"del": False
|
||||
}
|
||||
changed.append(to)
|
||||
|
||||
@ -24,7 +24,7 @@ class CsRoute:
|
||||
|
||||
def __init__(self, dev):
|
||||
self.dev = dev
|
||||
self.tableNo = dev[3]
|
||||
self.tableNo = dev[3:]
|
||||
self.table = "Table_%s" % (dev)
|
||||
|
||||
def routeTable(self):
|
||||
|
||||
@ -27,7 +27,7 @@ class CsRule:
|
||||
|
||||
def __init__(self, dev):
|
||||
self.dev = dev
|
||||
self.tableNo = dev[3]
|
||||
self.tableNo = int(dev[3:])
|
||||
self.table = "Table_%s" % (dev)
|
||||
|
||||
def addMark(self):
|
||||
@ -37,7 +37,7 @@ class CsRule:
|
||||
logging.info("Added fwmark rule for %s" % (self.table))
|
||||
|
||||
def findMark(self):
|
||||
srch = "from all fwmark 0x%s lookup %s" % (self.tableNo, self.table)
|
||||
srch = "from all fwmark %s lookup %s" % (hex(self.tableNo), self.table)
|
||||
for i in CsHelper.execute("ip rule show"):
|
||||
if srch in i.strip():
|
||||
return True
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user