예제 #1
0
파일: nat.py 프로젝트: wil/pyroman
class Nat:
	"""
	Represents a Network Address Translation rule.
	"""
	def __init__(self, client, server, ip, port, dport, dir, loginfo):
		"""
		Create a new NAT rule

		client -- clients allowed to access this NAT rule
		server -- host nick the NAT is applied to
		ip -- IP that is used in NAT
		port -- Ports that are used in NAT
		dport -- Destination port for single port redirections
		dir -- incoming, outgoing or bidirecitonal NAT

		Note that the NAT is always applied to the "server" host, the UI
		accessible function is responsible to eventually exchange client
		and server for "outgoing" NATs (where the naming of client, server
		makes more sense the other way, think of workstations accessing
		web server via a NAT)
		"""
		if server == "":
			raise PyromanException("Nat lacking a server host (client: %s, server: %s, ip: %s) at %s" % (client, server, ip, loginfo))
		if ip == "":
			raise PyromanException("Nat lacking IP address: (client: %s, server: %s) at %s" % (client, server, loginfo))
		if dir not in ["in", "out", "both"]:
			raise PyromanException("Nat with invalid direction: (client: %s, server: %s, ip: %s, dir: %s) at %s" % (client, server, ip, dir, loginfo))
		if not Util.verify_ip4(ip):
			raise PyromanException("Nat with invalid IP address: (client: %s, server: %s, ip: %s) at %s" % (client, server, ip, loginfo))
		if port:
			try:
				self.port = Port(port)
			except PortInvalidSpec:
				raise PyromanException("Nat port specification invalid: (client: %s, server: %s, ip: %s, port: %s) at %s " % (client, server, ip, port, loginfo))
			if not self.port.forIPv4():
				raise PyromanException("Non-IPv4 port specified: "+port)
		else:
			self.port = None
		if dport:
			try:
				self.dport = Port(dport)
			except PortInvalidSpec:
				raise PyromanException("Nat dport specification invalid: (client: %s, server: %s, ip: %s, port: %s, dport: %s) at %s " % (client, server, ip, port, dport, loginfo))
			if not self.dport.forIPv4():
				raise PyromanException("Non-IPv4 port specified: "+dport)
		else:
			self.dport = None
		if self.dport and not (self.port.proto == self.dport.proto):
			raise PyromanException("Nat ports have different protocols: (client: %s, server: %s, ip: %s, port: %s, dport: %s) at %s" % (client, server, ip, port, dport, loginfo))
		if dport and not port:
			raise PyromanException("Nat with destination port, but no source port: (client: %s, server: %s, ip: %s, dport: %s) at %s" % (client, server, ip, dport, loginfo))
		self.client = Util.splitter.split(client)
		self.server = Util.splitter.split(server)
		self.ip = ip
		# port, dport are set above
		self.dir = dir
		self.loginfo = loginfo

	def gen_snat(self, client, server):
		"""
		Internal helper function, with client, server objects
		"""
		iff = client.iface.get_filter("d")
		target = "SNAT --to-source %s" % self.ip
		# do we have a port restriction?
		pfilter = ""
		if self.port and self.dport:
			pfilter = self.dport.get_filter_proto() + " " + self.dport.get_filter_port("s")
			target = target + ":%s" % self.port.port
		elif self.port:
			pfilter = self.port.get_filter_proto() + " " + self.port.get_filter_port("s")

		c = Firewall.chains["natPOST"]
		for sip in server.ip:
			filter = iff[0] + " -s %s" % sip
			c.append4("%s %s -j %s" % (filter, pfilter, target), self.loginfo)

	def gen_dnat(self, client, server):
		"""
		Internal helper function, with client, server objects
		"""
		iff = client.iface.get_filter("s")
		filter = iff[0] + " -d %s" % self.ip
		# do we have a port restriction?
		pfilter = ""
		if self.port:
			pfilter = self.port.get_filter_proto() + " " + self.port.get_filter_port("d")

		c = Firewall.chains["natPRE"]
		for sip in server.ip:
			target = "DNAT --to-destination %s" % sip
			if self.dport:
				target = target + ":%s" % self.dport.port
			c.append4("%s %s -j %s" % (filter, pfilter, target), self.loginfo)

	def generate(self):
		for c in self.client:
			for s in self.server:
				client = Firewall.hosts[c]
				server = Firewall.hosts[s]
				# sanity checks, that should be moved to "verify"
				if not client or not server:
					raise PyromanException("Client or server not found for NAT defined at %s" % self.loginfo)
				if client.iface == server.iface:
					raise PyromanException("client interface and server interface match (i.e. cannot NAT!) for NAT defined at %s" % self.loginfo)

				if self.dir in ["in", "both"]:
					self.gen_dnat(client, server)
				if self.dir in ["out", "both"]:
					self.gen_snat(client, server)
예제 #2
0
파일: nat.py 프로젝트: wil/pyroman
class Nat:
    """
	Represents a Network Address Translation rule.
	"""
    def __init__(self, client, server, ip, port, dport, dir, loginfo):
        """
		Create a new NAT rule

		client -- clients allowed to access this NAT rule
		server -- host nick the NAT is applied to
		ip -- IP that is used in NAT
		port -- Ports that are used in NAT
		dport -- Destination port for single port redirections
		dir -- incoming, outgoing or bidirecitonal NAT

		Note that the NAT is always applied to the "server" host, the UI
		accessible function is responsible to eventually exchange client
		and server for "outgoing" NATs (where the naming of client, server
		makes more sense the other way, think of workstations accessing
		web server via a NAT)
		"""
        if server == "":
            raise PyromanException(
                "Nat lacking a server host (client: %s, server: %s, ip: %s) at %s"
                % (client, server, ip, loginfo))
        if ip == "":
            raise PyromanException(
                "Nat lacking IP address: (client: %s, server: %s) at %s" %
                (client, server, loginfo))
        if dir not in ["in", "out", "both"]:
            raise PyromanException(
                "Nat with invalid direction: (client: %s, server: %s, ip: %s, dir: %s) at %s"
                % (client, server, ip, dir, loginfo))
        if not Util.verify_ip4(ip):
            raise PyromanException(
                "Nat with invalid IP address: (client: %s, server: %s, ip: %s) at %s"
                % (client, server, ip, loginfo))
        if port:
            try:
                self.port = Port(port)
            except PortInvalidSpec:
                raise PyromanException(
                    "Nat port specification invalid: (client: %s, server: %s, ip: %s, port: %s) at %s "
                    % (client, server, ip, port, loginfo))
            if not self.port.forIPv4():
                raise PyromanException("Non-IPv4 port specified: " + port)
        else:
            self.port = None
        if dport:
            try:
                self.dport = Port(dport)
            except PortInvalidSpec:
                raise PyromanException(
                    "Nat dport specification invalid: (client: %s, server: %s, ip: %s, port: %s, dport: %s) at %s "
                    % (client, server, ip, port, dport, loginfo))
            if not self.dport.forIPv4():
                raise PyromanException("Non-IPv4 port specified: " + dport)
        else:
            self.dport = None
        if self.dport and not (self.port.proto == self.dport.proto):
            raise PyromanException(
                "Nat ports have different protocols: (client: %s, server: %s, ip: %s, port: %s, dport: %s) at %s"
                % (client, server, ip, port, dport, loginfo))
        if dport and not port:
            raise PyromanException(
                "Nat with destination port, but no source port: (client: %s, server: %s, ip: %s, dport: %s) at %s"
                % (client, server, ip, dport, loginfo))
        self.client = Util.splitter.split(client)
        self.server = Util.splitter.split(server)
        self.ip = ip
        # port, dport are set above
        self.dir = dir
        self.loginfo = loginfo

    def gen_snat(self, client, server):
        """
		Internal helper function, with client, server objects
		"""
        iff = client.iface.get_filter("d")
        target = "SNAT --to-source %s" % self.ip
        # do we have a port restriction?
        pfilter = ""
        if self.port and self.dport:
            pfilter = self.dport.get_filter_proto(
            ) + " " + self.dport.get_filter_port("s")
            target = target + ":%s" % self.port.port
        elif self.port:
            pfilter = self.port.get_filter_proto(
            ) + " " + self.port.get_filter_port("s")

        c = Firewall.chains["natPOST"]
        for sip in server.ip:
            filter = iff[0] + " -s %s" % sip
            c.append4("%s %s -j %s" % (filter, pfilter, target), self.loginfo)

    def gen_dnat(self, client, server):
        """
		Internal helper function, with client, server objects
		"""
        iff = client.iface.get_filter("s")
        filter = iff[0] + " -d %s" % self.ip
        # do we have a port restriction?
        pfilter = ""
        if self.port:
            pfilter = self.port.get_filter_proto(
            ) + " " + self.port.get_filter_port("d")

        c = Firewall.chains["natPRE"]
        for sip in server.ip:
            target = "DNAT --to-destination %s" % sip
            if self.dport:
                target = target + ":%s" % self.dport.port
            c.append4("%s %s -j %s" % (filter, pfilter, target), self.loginfo)

    def generate(self):
        for c in self.client:
            for s in self.server:
                client = Firewall.hosts[c]
                server = Firewall.hosts[s]
                # sanity checks, that should be moved to "verify"
                if not client or not server:
                    raise PyromanException(
                        "Client or server not found for NAT defined at %s" %
                        self.loginfo)
                if client.iface == server.iface:
                    raise PyromanException(
                        "client interface and server interface match (i.e. cannot NAT!) for NAT defined at %s"
                        % self.loginfo)

                if self.dir in ["in", "both"]:
                    self.gen_dnat(client, server)
                if self.dir in ["out", "both"]:
                    self.gen_snat(client, server)