Skip to content

Instantly share code, notes, and snippets.

@gmcquillan
Created June 22, 2011 20:15
Show Gist options
  • Save gmcquillan/1041032 to your computer and use it in GitHub Desktop.
Save gmcquillan/1041032 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from twisted.internet import defer
from twisted.internet import reactor
from twisted.internet import protocol
from twisted.internet import 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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment