[zorp-hu] zorp automatikus ipchains

Balazs Scheidler bazsi@balabit.hu
Thu, 21 Mar 2002 13:35:55 +0100


--cWoXeonUoKmBZSoM
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Sziasztok!

Attachmentben talaltok egy patchet, ami nagyban egyszerusitheti a Zorp-hoz
szukseges ipchains letrehozasat. A mukodese kb. annyi, hogy minden egyes
Listener automatikusan felveszi a mukodesehez szukseges rule-t, egy megadott
chain-be. Hasznalata a kovetkezo:

- kell egy skeleton ipchains, ami a Zorptol fuggetlen szabalyokat
tartalmazza (dns, ntp, !-y stb)
- a skeleton ipchains a megfelelo iranybol "hivjon" meg egy olyan lancot,
aminek a neve Z_<peldanynev>
- a Zorp peldany init fuggvenyebol meg kell hivni az enableIPChains() nevu
fuggvenyt (opcionalis parameter a chain neve, ha nem jo a default), ehhez be
kell importalni mindent az IPChains modulbol: from Zorp.IPChains import *
- a Listener-t egy kicsit maskepp kell meghivni:

regebben:  

	Listener(SockAddrInet('1.2.3.4', 50080), 'http')
	# ahol az 50080 az a port, ahova az ipchains redirektalt

mostantol, ha automata ipchains-t szeretnel:

	Listener(SockAddrInet('1.2.3.4', 80), 'http', transparent=TRUE)
	# azaz portkent az eredeti portszamot kell megadni, 
	# a redirektkent hasznalt portot a Zorp automatikusan generalja 
	# portszam+50000 modszerrel.

A letrejovo szabaly a kovetkezo alaku:

ipchains -A Z_<peldany> -s 0/0 0:65535 -d 0/0 80 -j REDIRECT 50080

ha a cel vagy a forras cimtartomanynak nem jo a 0/0, akkor az is megadhato a
Listener-nel:

	Listener(SockAddrInet('1.2.3.4', 80), 'http', transparent=TRUE, 
		transparent_redir_to=50080, 
		transparent_src=InetDomain('0.0.0.0/0'), 
		transparent_dst=InetDomain('192.168.131.5'))

'transparent' nevu parametere eddig is volt a Listenernek, aminek az
ertelmezese ezzel a patchel megvaltozna. Ezert hezitalok, hogy az 1.4-es
branchbe bekeruljon-e ez a patch vagy se.

Az 1.5-os valtozatunk egyenlore szet van bombazva, ezert az most nem
lehetoseg, hogy abban release-ljuk.

Kerdes, hogy a 'transparent' nevu parameter ilyen megvaltozasa zavaro-e
szamotokra, illetve, hogy altalaban mi a velemenyetek egy ilyen feature-rol?

-- 
Bazsi
PGP info: KeyID 9AF8D0A9 Fingerprint CD27 CFB0 802C 0944 9CFD 804E C82C 8EB1

--cWoXeonUoKmBZSoM
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="zorp-auto-ipchains.diff"

Index: lib/ipchains.c
===================================================================
RCS file: /var/cvs/zorp-core/lib/ipchains.c,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 ipchains.c
--- lib/ipchains.c	2001/10/03 11:40:44	1.4.2.1
+++ lib/ipchains.c	2002/03/21 11:48:21
@@ -68,7 +68,7 @@
       /*LOG
         This message indicates that adding a firewall rule failed.
        */
-      z_log(NULL, CORE_ERROR, 0, "Error adding firewall rule, setsockopt(IPPOROT_IP, IP_FW_INSERT) failed; error='%m'");
+      z_log(NULL, CORE_ERROR, 0, "Error adding firewall rule, setsockopt(IPPROTO_IP, IP_FW_INSERT) failed; error='%m'");
       return FALSE;
     }
   cap_restore(oldcaps);
Index: lib/pyipchains.c
===================================================================
RCS file: /var/cvs/zorp-core/lib/pyipchains.c,v
retrieving revision 1.3.2.1
diff -u -r1.3.2.1 pyipchains.c
--- lib/pyipchains.c	2001/10/02 11:12:04	1.3.2.1
+++ lib/pyipchains.c	2002/03/21 11:48:21
@@ -253,7 +253,7 @@
 
 PyMethodDef z_py_zorp_ipchains_funcs[] =
 {
-  { "IPChains",      z_py_zorp_ipchains_new_instance, METH_VARARGS },
+  { "ZorpIPChains",      z_py_zorp_ipchains_new_instance, METH_VARARGS },
   { NULL,            NULL }   /* sentinel*/
 };
 
Index: lib/pysockaddr.c
===================================================================
RCS file: /var/cvs/zorp-core/lib/pysockaddr.c,v
retrieving revision 1.23.2.5
diff -u -r1.23.2.5 pysockaddr.c
--- lib/pysockaddr.c	2002/02/11 14:31:23	1.23.2.5
+++ lib/pysockaddr.c	2002/03/21 11:48:21
@@ -58,7 +58,7 @@
   Py_BEGIN_ALLOW_THREADS
   rc = gethostbyname_r(hostname, &hes, hostbuf, sizeof(hostbuf), &he, &err);
   Py_END_ALLOW_THREADS
-  if (rc == 0)
+  if (rc == 0 && he)
     {
       z_inet_ntoa(buf, sizeof(buf), *((struct in_addr *) he->h_addr));
       return PyString_FromString(buf);
Index: pylib/Zorp/IPChains.py
===================================================================
RCS file: /var/cvs/zorp-core/pylib/Zorp/IPChains.py,v
retrieving revision 1.8.2.1
diff -u -r1.8.2.1 IPChains.py
--- pylib/Zorp/IPChains.py	2001/10/11 08:24:51	1.8.2.1
+++ pylib/Zorp/IPChains.py	2002/03/21 11:48:21
@@ -24,7 +24,7 @@
   calls system calls directly.
 """
 
-import Zorp
+from Zorp import *
 from Domain import InetDomain
 
 CORE_IPCHAINS = 'core.ipchains'
@@ -103,7 +103,7 @@
 		"""
 		# rule: (target, (src, smask), (dst, dmask), mark, proto, flags, inv_flags, (sportmin, sportmax), (dportmin, dportmax), redirport, iface, tosand, tosxor)
 		self.rules = []
-		self.ipchains = Zorp.IPChains()
+		self.ipchains = ZorpIPChains()
 	
 	def __del__(self):
 		"""Destructor to delete rules added by this object.
@@ -131,8 +131,8 @@
 		  rule -- a tuple describing the rule to add in the syntax
                           (target, (src, smask), (dst, dmask), mark, proto, flags, inv_flags, (sportmin, sportmax), (dportmin, dportmax), redirport, iface, tosand, tosxor)
 		"""
+		log(CORE_IPCHAINS, 7, "adding ipchains rule; rule='%s'" % (rule,))
 		apply(self.ipchains.addRule, rule)
-		Zorp.log(CORE_IPCHAINS, 7, 'adding ipchains rule; rule='%s'' % (rule,))
 		self.rules.append(rule)
 	
 	def delRule(self, rule):
@@ -146,7 +146,7 @@
 		  
 		  rule -- rule to delete
 		"""
-		Zorp.log(CORE_IPCHAINS, 7, 'deleting ipchains rule; rule='%s'' % (rule,))
+		log(CORE_IPCHAINS, 7, "deleting ipchains rule; rule='%s'" % (rule,))
 		apply(self.ipchains.delRule, rule)
 		self.rules.remove(rule)
 
@@ -344,4 +344,32 @@
 		rule = (chain, ('RETURN', calcIpMask(sdom), calcIpMask(ddom), 0, proto, flags, inv_flags, sports, dports, redirport, iface, tosand, tosxor))
 		self.addRule(rule)
 		return rule
+
+
+ipchains_name = ''
+ipchains_instance = IPChains()
+	
+def enableIPChains(chain=None):
+	global ipchains_name, ipchains_instance
+
+	def setupRule(listener):
+		global ipchains_name, ipchains_instance
+
+		log(CORE_IPCHAINS, 7, "listen hook; listener='%s'" % (str(listener),))
+		try:
+			if listener.transparent:
+				ipchains_instance.addREDIRECT(ipchains_name, listener.transparent_src, (0, 65535), listener.transparent_dst, (listener.transparent_port, listener.transparent_port), listener.bindto.port)
+			else:
+				ipchains_instance.addACCEPT(ipchains_name, listener.transparent_src, (0, 65535), listener.transparent_dst, (listener.local.port, listener.local.port))
+		except IOError:
+			pass
 	
+	import Listener
+
+	if chain != None:
+		ipchains_name = chain
+	else:
+		ipchains_name = 'Z' + instance_name
+
+	Listener.listen_hook = setupRule
+
Index: pylib/Zorp/Listener.py
===================================================================
RCS file: /var/cvs/zorp-core/pylib/Zorp/Listener.py,v
retrieving revision 1.51.2.5
diff -u -r1.51.2.5 Listener.py
--- pylib/Zorp/Listener.py	2002/01/03 11:30:42	1.51.2.5
+++ pylib/Zorp/Listener.py	2002/03/21 11:48:21
@@ -23,6 +23,7 @@
 from Zorp import *
 from Session import MasterSession
 from Service import services
+from Domain import InetDomain
 from traceback import print_exc
 from string import atoi
 
@@ -31,6 +32,8 @@
 
 client_ips = {}
 
+default_transparent = FALSE
+
 class SimpleListen:
 	"""Class encapsulating a simple Listener.
 	
@@ -45,9 +48,8 @@
 	  
 	  local -- address we are bound to
 	"""
-
 
-	def __init__(self, bindto, accept_one=0, backlog=255):
+	def __init__(self, bindto, accept_one=0, backlog=255, transparent=FALSE, transparent_dst=None, transparent_src=None, transparent_redir_to=None):
 		"""Constructor to initialize a SimpleListen instance
 		
 		This constructor initializes a SimpleListen instance
@@ -67,7 +69,21 @@
 		"""
 		
 		global listen_hook
-		
+
+		if transparent:
+			self.transparent_port = bindto.port
+			if transparent_redir_to == None:
+				bindto.port = bindto.port + 50000
+			else:
+				bindto.port = transparent_redir_to
+			if transparent_dst is None:
+				transparent_dst = InetDomain('0.0.0.0/0')
+			if transparent_src is None:
+				transparent_src = InetDomain('0.0.0.0/0')
+
+		self.transparent = transparent
+		self.transparent_dst = transparent_dst
+		self.transparent_src = transparent_src
 		self.listen = Listen(bindto, self.accepted, accept_one, backlog)
 		self.bindto = bindto
 	        self.local = self.listen.local
@@ -153,8 +169,7 @@
 	except ValueError:
 		max_clients = 3
 
-
-	def __init__(self, bindto, service, transparent=FALSE, backlog=255):
+	def __init__(self, bindto, service, transparent=default_transparent, backlog=255, transparent_src=None, transparent_dst=None, transparent_redir_to=None):
 		"""Constructor to initialize a Listen instance
 		
 		Creates the instance, sets the initial attributes, and
@@ -182,9 +197,8 @@
 				self.service = None
 		except KeyError:
 			raise ServiceException, "Service %s not found" % (service,)
-		self.bindto = bindto
-	        self.transparent = transparent
-	        SimpleListen.__init__(self, bindto, backlog=backlog)
+
+	        SimpleListen.__init__(self, bindto, transparent=transparent, backlog=backlog, transparent_src=transparent_src, transparent_dst=transparent_dst)
 	        self.start()
 	        
 	def accepted(self, client, fd):
@@ -232,7 +246,7 @@
 						client_ips[client.ip_s] = 1
 
 
-			if self.transparent and session.client_local.port == self.local.port:
+			if self.transparent and session.client_dest.port == self.local.port:
 				log(CORE_ERROR, 1, "%s: Transparent listener connected directly, dropping connection; local='%s', client_local='%s'" % (session.session_id, self.local, session.client_local))
 			elif session.isClientPermitted() == Z_ACCEPT:
 				log(CORE_DEBUG, 8, "%s: Connection accepted; client_address='%s'" % (session.session_id, client))
@@ -270,7 +284,6 @@
 		"""
 		return self.service
 
-
 class ZoneListener(Listener):
 	"""Class to listen on the selected address, and start a service based on the client's zone.
 	
@@ -286,7 +299,7 @@
 	  services -- services mapping indexed by zone name
 	"""
 	
-	def __init__(self, bindto, services):
+	def __init__(self, bindto, services, transparent=default_transparent, backlog=255, transparent_src=None, transparent_dst=None, transparent_redir_to=None):
 		"""Constructor to initialize a ZoneListener instance.
 		
 		This constructor initializes a ZoneListener instance and sets
@@ -300,7 +313,7 @@
 		  
 		  services -- a mapping between zone names and services
 		"""
-		Listener.__init__(self, bindto, None)
+		Listener.__init__(self, bindto, None, transparent, backlog, transparent_src, transparent_dst, transparent_redir_to)
 		self.services = services
 	
 	def getService(self, session):
Index: pylib/Zorp/Zorp.py
===================================================================
RCS file: /var/cvs/zorp-core/pylib/Zorp/Zorp.py,v
retrieving revision 1.43.2.1
diff -u -r1.43.2.1 Zorp.py
--- pylib/Zorp/Zorp.py	2001/10/11 08:24:51	1.43.2.1
+++ pylib/Zorp/Zorp.py	2002/03/21 11:48:21
@@ -62,7 +62,9 @@
 LimitException = "Limit error"
 InternalError = "Internal error occured"
 
+instance_name = ''
 
+
 def error(level, msg):
 	"""Logs an error message
 
@@ -131,6 +133,9 @@
 	
 	  name -- name of this instance
 	"""
+	global instance_name
+
+	instance_name = name
 	import __main__
 	try:
 		func = getattr(__main__, name)

--cWoXeonUoKmBZSoM--