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":
|
elif rule["type"] == "staticnat":
|
||||||
self.processStaticNatRule(rule)
|
self.processStaticNatRule(rule)
|
||||||
|
|
||||||
def getDeviceByIp(self, ip):
|
def getDeviceByIp(self, ipa):
|
||||||
ips = CsDataBag("ips")
|
for ip in self.config.address().get_ips():
|
||||||
dbag = ips.get_bag()
|
if ip.ip_in_subnet(ipa):
|
||||||
for device in dbag:
|
return ip.get_device()
|
||||||
if device == "id":
|
return None
|
||||||
continue
|
|
||||||
for addy in dbag[device]:
|
def getNetworkByIp(self, ipa):
|
||||||
if addy["public_ip"] == ip:
|
for ip in self.config.address().get_ips():
|
||||||
return device
|
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
|
return None
|
||||||
|
|
||||||
def portsToString(self, ports, delimiter):
|
def portsToString(self, ports, delimiter):
|
||||||
@ -515,7 +522,70 @@ class CsForwardingRules(CsDataBag):
|
|||||||
return "%s%s%s" % (ports_parts[0], delimiter, ports_parts[1])
|
return "%s%s%s" % (ports_parts[0], delimiter, ports_parts[1])
|
||||||
|
|
||||||
def processForwardRule(self, rule):
|
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"]
|
fwrule = "-A PREROUTING -d %s/32" % rule["public_ip"]
|
||||||
if not rule["protocol"] == "any":
|
if not rule["protocol"] == "any":
|
||||||
fwrule += " -m %s -p %s" % (rule["protocol"], rule["protocol"])
|
fwrule += " -m %s -p %s" % (rule["protocol"], rule["protocol"])
|
||||||
|
|||||||
@ -19,6 +19,7 @@ from CsDatabag import CsDataBag, CsCmdLine
|
|||||||
from CsApp import CsApache, CsDnsmasq, CsPasswdSvc
|
from CsApp import CsApache, CsDnsmasq, CsPasswdSvc
|
||||||
import CsHelper
|
import CsHelper
|
||||||
import logging
|
import logging
|
||||||
|
from netaddr import IPAddress, IPNetwork
|
||||||
import CsHelper
|
import CsHelper
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
@ -118,6 +119,9 @@ class CsInterface:
|
|||||||
def get_ip(self):
|
def get_ip(self):
|
||||||
return self.get_attr("public_ip")
|
return self.get_attr("public_ip")
|
||||||
|
|
||||||
|
def get_network(self):
|
||||||
|
return self.get_attr("network")
|
||||||
|
|
||||||
def get_netmask(self):
|
def get_netmask(self):
|
||||||
return self.get_attr("netmask")
|
return self.get_attr("netmask")
|
||||||
|
|
||||||
@ -125,7 +129,15 @@ class CsInterface:
|
|||||||
if self.config.is_vpc():
|
if self.config.is_vpc():
|
||||||
return self.get_attr("gateway")
|
return self.get_attr("gateway")
|
||||||
else:
|
else:
|
||||||
|
if self.config.cmdline().is_redundant():
|
||||||
return self.config.cmdline().get_guest_gw()
|
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):
|
def get_gateway_cidr(self):
|
||||||
return "%s/%s" % (self.get_gateway(), self.get_size())
|
return "%s/%s" % (self.get_gateway(), self.get_size())
|
||||||
@ -185,7 +197,7 @@ class CsDevice:
|
|||||||
self.table = ''
|
self.table = ''
|
||||||
self.tableNo = ''
|
self.tableNo = ''
|
||||||
if dev != '':
|
if dev != '':
|
||||||
self.tableNo = dev[3]
|
self.tableNo = dev[3:]
|
||||||
self.table = "Table_%s" % dev
|
self.table = "Table_%s" % dev
|
||||||
self.fw = config.get_fw()
|
self.fw = config.get_fw()
|
||||||
self.cl = config.cmdline()
|
self.cl = config.cmdline()
|
||||||
@ -228,7 +240,7 @@ class CsIP:
|
|||||||
|
|
||||||
def __init__(self, dev, config):
|
def __init__(self, dev, config):
|
||||||
self.dev = dev
|
self.dev = dev
|
||||||
self.dnum = dev[3]
|
self.dnum = hex(int(dev[3:]))
|
||||||
self.iplist = {}
|
self.iplist = {}
|
||||||
self.address = {}
|
self.address = {}
|
||||||
self.list()
|
self.list()
|
||||||
@ -275,8 +287,8 @@ class CsIP:
|
|||||||
CsHelper.execute(cmd2)
|
CsHelper.execute(cmd2)
|
||||||
|
|
||||||
def set_mark(self):
|
def set_mark(self):
|
||||||
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-xmark 0x%s/0xffffffff" % \
|
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-xmark %s/0xffffffff" % \
|
||||||
(self.getDevice(), self.getDevice()[3])
|
(self.getDevice(), self.dnum)
|
||||||
self.fw.append(["mangle", "", cmd])
|
self.fw.append(["mangle", "", cmd])
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
@ -327,7 +339,7 @@ class CsIP:
|
|||||||
"-A POSTROUTING -o eth2 -j SNAT --to-source %s" % self.address['public_ip']])
|
"-A POSTROUTING -o eth2 -j SNAT --to-source %s" % self.address['public_ip']])
|
||||||
self.fw.append(["mangle", "",
|
self.fw.append(["mangle", "",
|
||||||
"-A PREROUTING -i %s -m state --state NEW " % self.dev +
|
"-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(["mangle", "", "-A FIREWALL_%s -j DROP" % self.address['public_ip']])
|
||||||
|
|
||||||
self.fw.append(["filter", "", "-A INPUT -d 224.0.0.18/32 -j ACCEPT"])
|
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(["filter", "", "-A FORWARD -i eth0 -o eth2 -j FW_OUTBOUND"])
|
||||||
self.fw.append(["mangle", "",
|
self.fw.append(["mangle", "",
|
||||||
"-A PREROUTING -i %s -m state --state NEW " % self.dev +
|
"-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"]:
|
if self.get_type() in ["control"]:
|
||||||
self.fw.append(["filter", "", "-A FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT"])
|
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 self.idata()['router_pr']
|
||||||
return 99
|
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):
|
def set_priority(self, val):
|
||||||
self.idata()['router_pr'] = val
|
self.idata()['router_pr'] = val
|
||||||
|
|
||||||
@ -73,21 +81,6 @@ class CsCmdLine(CsDataBag):
|
|||||||
def set_redundant(self, val="true"):
|
def set_redundant(self, val="true"):
|
||||||
self.idata()['redundant_router'] = val
|
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):
|
def get_name(self):
|
||||||
if "name" in self.idata():
|
if "name" in self.idata():
|
||||||
return self.idata()['name']
|
return self.idata()['name']
|
||||||
|
|||||||
@ -98,7 +98,7 @@ class CsDhcp(CsDataBag):
|
|||||||
to = {"device": bits[0],
|
to = {"device": bits[0],
|
||||||
"mac": bits[1],
|
"mac": bits[1],
|
||||||
"ip": bits[2],
|
"ip": bits[2],
|
||||||
"host": bits[3],
|
"host": bits[3:],
|
||||||
"del": False
|
"del": False
|
||||||
}
|
}
|
||||||
changed.append(to)
|
changed.append(to)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class CsRoute:
|
|||||||
|
|
||||||
def __init__(self, dev):
|
def __init__(self, dev):
|
||||||
self.dev = dev
|
self.dev = dev
|
||||||
self.tableNo = dev[3]
|
self.tableNo = dev[3:]
|
||||||
self.table = "Table_%s" % (dev)
|
self.table = "Table_%s" % (dev)
|
||||||
|
|
||||||
def routeTable(self):
|
def routeTable(self):
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class CsRule:
|
|||||||
|
|
||||||
def __init__(self, dev):
|
def __init__(self, dev):
|
||||||
self.dev = dev
|
self.dev = dev
|
||||||
self.tableNo = dev[3]
|
self.tableNo = int(dev[3:])
|
||||||
self.table = "Table_%s" % (dev)
|
self.table = "Table_%s" % (dev)
|
||||||
|
|
||||||
def addMark(self):
|
def addMark(self):
|
||||||
@ -37,7 +37,7 @@ class CsRule:
|
|||||||
logging.info("Added fwmark rule for %s" % (self.table))
|
logging.info("Added fwmark rule for %s" % (self.table))
|
||||||
|
|
||||||
def findMark(self):
|
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"):
|
for i in CsHelper.execute("ip rule show"):
|
||||||
if srch in i.strip():
|
if srch in i.strip():
|
||||||
return True
|
return True
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user