[Twisted-Python] Implementing a syslog-deamon ??

Skinny Puppy skin_pup-twisted at damnable.happypoo.com
Thu Jul 10 08:42:49 EDT 2003


Attached is a basic quick easy syslog listener (best name I could come up
with).  In our environment we user deamontools for all daemons and us
multilog to handle logging this is no different. 

Jeremy

Thomas Weholt ( PRIVAT ) [2002 at weholt.org] wrote:
> Hi,
> 
> I was wondering if I could implement a fully syslog-compatible
> syslog-deamon/server using Twisted? We need a syslog up and running as soon
> as possible to let our firewall use it, due to some suspicion about hacking
> etc. It would help alot of I could implement a syslog-deamon that put data
> sent to it into a database, instead of to a file. The server must be able to
> run on Windows.
> 
> This would also be a perfect oppertunity to show of Python, open-source and
> Twisted to a group of people who adore Microsoft and Borland and think
> python and all other scripting-languages are for kids and trivial,
> non-critical things.
> 
> Anyway, any hint you can give me will be appreciated.
> 
> Best regards,
> Thomas
> 
> 
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-------------- next part --------------
#!/usr/local/bin/pythonN)
from twisted.internet import defer, reactor, protocol, ssl
from twisted.python import usage
from OpenSSL import SSL
import sys, os.path

LOG_PRIMASK = 0x07
PRIMASK = { 
0 : "emerg", 
1 : "alert",
2 : "crit",
3 : "err",
4 : "warning",
5 : "notice",
6 : "info",
7 : "debug"
}

FACILITYMASK = {
      0  : "kern",
      1  : "user",
      2  : "mail",
      3  : "daemon",
      4  : "auth",
      5  : "syslog",
      6  : "lpr",
      7  : "news",
      8  : "uucp",
      9  : "cron",
      10 : "authpriv",
      11 : "ftp",
      12 : "ntp",
      13 : "security",
      14 : "console",
      15 : "mark",
      16 : "local0",
      17 : "local1",
      18 : "local2",
      19 : "local3",
      20 : "local4",
      21 : "local5",
      22 : "local6",
      23 : "local7",
}

def bit2string(number):
    try: return "%s.%s"%(FACILITYMASK[number>>3] , PRIMASK[number & LOG_PRIMASK])
    except: return "unknown.unknown"
        

class syslogOptions(usage.Options):
    optParameters = [['cert', 'c', './server.pem','SSL Server certificate'],
                     ['ip',   'i', None, 'IP Address to listen on']]
    def postOptions_cert(self):
        if (not self.opts['cert']) or (not os.path.isfile(self.opts['cert'])):
            raise usage.UsageError, "%s: is not a file"
    def portOptions_ip(self):
        if (not self.opts['ip']):
            raise usage.UsageError, "IP Address is required"
    
class outputUPD(protocol.DatagramProtocol):
    def datagramReceived(self, data, (ip, port)):
        if data[2] == ">":
            other = " ".join([ip, bit2string(int(data[1]))])
            sys.stdout.write(" ".join([other, data[3:], "\n"]))
        elif data[3] == ">":
            other = " ".join([ip, bit2string(int(data[1:2]))])
            sys.stdout.write(" ".join([other, data[4:], "\n"]))
        else:
            other = " ".join([ip, "unknown.unknown"])
            sys.stdout.write(" ".join([other, data, "\n"]))

class outputTCP(protocol.Protocol):
    def connectionMade(self):
        self.factory.numberConnections += 1
        if self.factory.numberConnections > self.factory.maxNumberConnections:
            self.transport.loseConnection()

    def connectionLost(self, reason):
        self.factory.numberConnections -= 1

    def dataReceived(self, data):
        ip = self.transport.getPeer()[1]
        if data[2] == ">":
            other = " ".join([ip, bit2string(int(data[1]))])
            self.factory.write(" ".join([other, data[3:], "\n"]))
        elif data[3] == ">":
            other = " ".join([ip, bit2string(int(data[1:2]))])
            self.factory.write(" ".join([other, data[4:], "\n"]))
        else:
            other = " ".join([ip, "unknown.unknown"])
            self.factory.write(" ".join([other, data, "\n"]))

class syslogFactory(protocol.Factory):
    noisy = 0
    numberConnections = 0
    maxNumberConnections = 256
    write = sys.stdout.write
    
    

if __name__ == "__main__":
    import sys, os
    from twisted.python import log
    log.logfile=sys.stderr
    try:
        config = syslogOptions()
        config.parseOptions()
    except usage.UsageError, ue:
        print >>sys.stderr, '%s:'%sys.argv[0], ue
        sys.exit(1)
    syslogTCP = syslogFactory()
    syslogTCP.protocol = outputTCP
    syslogSSL = syslogFactory()
    syslogSSL.protocol = outputTCP
    ctx = ssl.DefaultOpenSSLContextFactory(config.opts['cert'], config.opts['cert'])
    reactor.listenUDP(514, outputUPD(), interface=config.opts['ip'])
    reactor.listenTCP(514, syslogTCP,   interface=config.opts['ip'])
    reactor.listenSSL(728, syslogSSL , ctx, interface=config.opts['ip'])
    reactor.run()


More information about the Twisted-Python mailing list