[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--