[Twisted-Python] twisted irc client + packet capturing

Hi,
I've created a script that would log on to an irc server, while capturing packets.
I came across the following link:
http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet...
But I'm using pycap (http://pycap.sourceforge.net/), but I'm having some difficulties with getting it to work.
Here's the code:
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details.
# twisted imports from twisted.words.protocols import irc from twisted.internet import reactor, protocol from twisted.python import log from twisted.internet.defer import Deferred
# system imports import time, sys
import pycap.capture
def run_pcap(f): p = pycap.capture.capture('eth0') p.filter('src host ! 192.168.1.100 and dst host ! 192.168.1.100 and dst port 25') packet = None print "Listening...\n" while 1: if packet: print "Received packet." reactor.callFromThread(f, packet) else: print "no packet\n" packet = p.next()
class LogBot(irc.IRCClient): """A logging IRC bot."""
nickname = "testbot"
def packetShow(self, packet): """ booga """ msg = "Port 25 hit | From:[%s] To:[%s]" % (packet[1].source, packet[1].destination) self.msg(self.channel, msg)
def connectionMade(self): irc.IRCClient.connectionMade(self) print "Setting up callInThread\n" reactor.callInThread(run_pcap, self.packetShow) print "Finished setting up callInThread\n"
def connectionLost(self, reason): irc.IRCClient.connectionLost(self, reason)
# callbacks for events
def signedOn(self): """Called when bot has succesfully signed on to server.""" print "Signing on to %s.\n" % self.factory.channel # self.join(self.factory.channel) self.sendLine("JOIN %s" % (self.factory.channel,))
def joined(self, channel): """This will get called when the bot joins the channel.""" print "Joining channel %s." % channel
def privmsg(self, user, channel, msg): """This will get called when the bot receives a message.""" user = user.split('!', 1)[0]
# Check to see if they're sending me a private message if channel == self.nickname: msg = "It isn't nice to whisper! Play nice with the group." self.msg(user, msg) return
# Otherwise check to see if it is a message directed at me if msg.startswith(self.nickname + ":"): msg = "%s: I am a log bot" % user self.msg(channel, msg)
def action(self, user, channel, msg): """This will get called when the bot sees someone do an action.""" user = user.split('!', 1)[0]
# irc callbacks
def irc_NICK(self, prefix, params): """Called when an IRC user changes their nickname.""" old_nick = prefix.split('!')[0] new_nick = params[0]
# For fun, override the method that determines how a nickname is changed on # collisions. The default method appends an underscore. def alterCollidedNick(self, nickname): """ Generate an altered version of a nickname that caused a collision in an effort to create an unused related name for subsequent registration. """ return nickname + '^'
class LogBotFactory(protocol.ClientFactory): """A factory for LogBots.
A new protocol instance will be created each time we connect to the server. """
def __init__(self, channel): self.channel = channel
def buildProtocol(self, addr): p = LogBot() p.factory = self return p
def clientConnectionLost(self, connector, reason): """If we get disconnected, reconnect to server.""" connector.connect()
def clientConnectionFailed(self, connector, reason): print "connection failed:", reason reactor.stop()
if __name__ == '__main__': # create factory protocol and application f = LogBotFactory("#testx")
# connect factory to this host and port reactor.connectTCP("192.168.1.170", 6667, f)
# run bot reactor.run()
I was told that perhaps I could use twisted.pair, but I have no idea how to use the module. The documentation is lacking and I've only just started programming in Twisted.
Any help appreciated.
Edmund

Hi,
I've created a script that would log on to an irc server, while capturing packets.
I came across the following link:
http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet...
But I'm using pycap (http://pycap.sourceforge.net/), but I'm having some difficulties with getting it to work.
my 'dirty' workaround suggestion :
1. Write a twisted based IRC bot that also have a UDP server function 2. Write a pycap based script that capture packet and other things ...and udp-send itu to #1
Sincerely -bino-

On 08:50 am, ewong@pw-wspx.org wrote:
Hi,
I've created a script that would log on to an irc server, while capturing packets.
I came across the following link:
http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python- packet-sniffer/
But I'm using pycap (http://pycap.sourceforge.net/), but I'm having some difficulties with getting it to work.
Here's the code:
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details.
# twisted imports from twisted.words.protocols import irc from twisted.internet import reactor, protocol from twisted.python import log from twisted.internet.defer import Deferred
# system imports import time, sys
import pycap.capture
def run_pcap(f): p = pycap.capture.capture('eth0') p.filter('src host ! 192.168.1.100 and dst host ! 192.168.1.100 and dst port 25') packet = None print "Listening...\n" while 1: if packet: print "Received packet." reactor.callFromThread(f, packet) else: print "no packet\n" packet = p.next()
class LogBot(irc.IRCClient): """A logging IRC bot."""
nickname = "testbot" def packetShow(self, packet): """ booga """ msg = "Port 25 hit | From:[%s] To:[%s]" % (packet[1].source,
packet[1].destination) self.msg(self.channel, msg)
def connectionMade(self): irc.IRCClient.connectionMade(self) print "Setting up callInThread\n" reactor.callInThread(run_pcap, self.packetShow) print "Finished setting up callInThread\n" def connectionLost(self, reason): irc.IRCClient.connectionLost(self, reason) # callbacks for events def signedOn(self): """Called when bot has succesfully signed on to server.""" print "Signing on to %s.\n" % self.factory.channel # self.join(self.factory.channel) self.sendLine("JOIN %s" % (self.factory.channel,)) def joined(self, channel): """This will get called when the bot joins the channel.""" print "Joining channel %s." % channel def privmsg(self, user, channel, msg): """This will get called when the bot receives a message.""" user = user.split('!', 1)[0] # Check to see if they're sending me a private message if channel == self.nickname: msg = "It isn't nice to whisper! Play nice with the
group." self.msg(user, msg) return
# Otherwise check to see if it is a message directed at me if msg.startswith(self.nickname + ":"): msg = "%s: I am a log bot" % user self.msg(channel, msg) def action(self, user, channel, msg): """This will get called when the bot sees someone do an
action.""" user = user.split('!', 1)[0]
# irc callbacks def irc_NICK(self, prefix, params): """Called when an IRC user changes their nickname.""" old_nick = prefix.split('!')[0] new_nick = params[0] # For fun, override the method that determines how a nickname is
changed on # collisions. The default method appends an underscore. def alterCollidedNick(self, nickname): """ Generate an altered version of a nickname that caused a collision in an effort to create an unused related name for subsequent registration. """ return nickname + '^'
class LogBotFactory(protocol.ClientFactory): """A factory for LogBots.
A new protocol instance will be created each time we connect to the
server. """
def __init__(self, channel): self.channel = channel def buildProtocol(self, addr): p = LogBot() p.factory = self return p def clientConnectionLost(self, connector, reason): """If we get disconnected, reconnect to server.""" connector.connect() def clientConnectionFailed(self, connector, reason): print "connection failed:", reason reactor.stop()
if __name__ == '__main__': # create factory protocol and application f = LogBotFactory("#testx")
# connect factory to this host and port reactor.connectTCP("192.168.1.170", 6667, f) # run bot reactor.run()
I was told that perhaps I could use twisted.pair, but I have no idea how to use the module. The documentation is lacking and I've only just started programming in Twisted.
Any help appreciated.
I don't know if Twisted Pair will work better for you but you can find the start of some documentation about it in this branch:
https://twistedmatrix.com/trac/browser/branches/tuntap-pytun-6169-3
Additionally, this branch removes the Twisted Pair dependency on the "eunuchs" module which is abandoned and difficult to find.
Jean-Paul

I got my sniffer to work in Twisted... but then I'm not using pycap : https://github.com/david415/hushVPN/blob/master/nflog_reader.py
I use the NetLinkFilter socket via this python cffi: https://github.com/mk-fg/scapy-nflog-capture Anyhow this allows me to control which packets my sniffer picks up via iptables rules like this:
iptables -A INPUT -p tcp --dport 22 -j NFLOG
Cheers!
David
On Fri, Nov 8, 2013 at 12:50 AM, Edmund Wong ewong@pw-wspx.org wrote:
Hi,
I've created a script that would log on to an irc server, while capturing packets.
I came across the following link:
http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet...
But I'm using pycap (http://pycap.sourceforge.net/), but I'm having some difficulties with getting it to work.
Here's the code:
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details.
# twisted imports from twisted.words.protocols import irc from twisted.internet import reactor, protocol from twisted.python import log from twisted.internet.defer import Deferred
# system imports import time, sys
import pycap.capture
def run_pcap(f): p = pycap.capture.capture('eth0') p.filter('src host ! 192.168.1.100 and dst host ! 192.168.1.100 and dst port 25') packet = None print "Listening...\n" while 1: if packet: print "Received packet." reactor.callFromThread(f, packet) else: print "no packet\n" packet = p.next()
class LogBot(irc.IRCClient): """A logging IRC bot."""
nickname = "testbot" def packetShow(self, packet): """ booga """ msg = "Port 25 hit | From:[%s] To:[%s]" % (packet[1].source,
packet[1].destination) self.msg(self.channel, msg)
def connectionMade(self): irc.IRCClient.connectionMade(self) print "Setting up callInThread\n" reactor.callInThread(run_pcap, self.packetShow) print "Finished setting up callInThread\n" def connectionLost(self, reason): irc.IRCClient.connectionLost(self, reason) # callbacks for events def signedOn(self): """Called when bot has succesfully signed on to server.""" print "Signing on to %s.\n" % self.factory.channel # self.join(self.factory.channel) self.sendLine("JOIN %s" % (self.factory.channel,)) def joined(self, channel): """This will get called when the bot joins the channel.""" print "Joining channel %s." % channel def privmsg(self, user, channel, msg): """This will get called when the bot receives a message.""" user = user.split('!', 1)[0] # Check to see if they're sending me a private message if channel == self.nickname: msg = "It isn't nice to whisper! Play nice with the group." self.msg(user, msg) return # Otherwise check to see if it is a message directed at me if msg.startswith(self.nickname + ":"): msg = "%s: I am a log bot" % user self.msg(channel, msg) def action(self, user, channel, msg): """This will get called when the bot sees someone do an action.""" user = user.split('!', 1)[0] # irc callbacks def irc_NICK(self, prefix, params): """Called when an IRC user changes their nickname.""" old_nick = prefix.split('!')[0] new_nick = params[0] # For fun, override the method that determines how a nickname is changed
on # collisions. The default method appends an underscore. def alterCollidedNick(self, nickname): """ Generate an altered version of a nickname that caused a collision in an effort to create an unused related name for subsequent registration. """ return nickname + '^'
class LogBotFactory(protocol.ClientFactory): """A factory for LogBots.
A new protocol instance will be created each time we connect to the
server. """
def __init__(self, channel): self.channel = channel def buildProtocol(self, addr): p = LogBot() p.factory = self return p def clientConnectionLost(self, connector, reason): """If we get disconnected, reconnect to server.""" connector.connect() def clientConnectionFailed(self, connector, reason): print "connection failed:", reason reactor.stop()
if __name__ == '__main__': # create factory protocol and application f = LogBotFactory("#testx")
# connect factory to this host and port reactor.connectTCP("192.168.1.170", 6667, f) # run bot reactor.run()
I was told that perhaps I could use twisted.pair, but I have no idea how to use the module. The documentation is lacking and I've only just started programming in Twisted.
Any help appreciated.
Edmund
Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Hello,
1) create a pcapdevice I use pcapy because it can return a file descriptor of the new pcapdevice created
2) Use abstract.FileDescriptor With absbract.FileDescriptor you can wrap the previvous pcapdevice with its file descriptor into some that twisted can use properly into the reactor. With abstract.FileDescriptor you will create an event based pcapdevice which will read data when they income without blocking anything and without using thread.
3) plug you twisted-like pcapdevice into your application. Now with a pcapdevice based on abstract.FileDescriptor you can use it into you twisted application without any problem
I will try to speed up my developpement process to show you a little module that could permit you to do it really easly. I am actually coding the dissector of the packet received.
kinds regards,
Sofiane Akermoun
2013/11/8 David Stainton dstainton415@gmail.com:
I got my sniffer to work in Twisted... but then I'm not using pycap : https://github.com/david415/hushVPN/blob/master/nflog_reader.py
I use the NetLinkFilter socket via this python cffi: https://github.com/mk-fg/scapy-nflog-capture Anyhow this allows me to control which packets my sniffer picks up via iptables rules like this:
iptables -A INPUT -p tcp --dport 22 -j NFLOG
Cheers!
David
On Fri, Nov 8, 2013 at 12:50 AM, Edmund Wong ewong@pw-wspx.org wrote:
Hi,
I've created a script that would log on to an irc server, while capturing packets.
I came across the following link:
http://dound.com/2009/09/integrating-twisted-with-a-pcap-based-python-packet...
But I'm using pycap (http://pycap.sourceforge.net/), but I'm having some difficulties with getting it to work.
Here's the code:
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details.
# twisted imports from twisted.words.protocols import irc from twisted.internet import reactor, protocol from twisted.python import log from twisted.internet.defer import Deferred
# system imports import time, sys
import pycap.capture
def run_pcap(f): p = pycap.capture.capture('eth0') p.filter('src host ! 192.168.1.100 and dst host ! 192.168.1.100 and dst port 25') packet = None print "Listening...\n" while 1: if packet: print "Received packet." reactor.callFromThread(f, packet) else: print "no packet\n" packet = p.next()
class LogBot(irc.IRCClient): """A logging IRC bot."""
nickname = "testbot" def packetShow(self, packet): """ booga """ msg = "Port 25 hit | From:[%s] To:[%s]" % (packet[1].source,
packet[1].destination) self.msg(self.channel, msg)
def connectionMade(self): irc.IRCClient.connectionMade(self) print "Setting up callInThread\n" reactor.callInThread(run_pcap, self.packetShow) print "Finished setting up callInThread\n" def connectionLost(self, reason): irc.IRCClient.connectionLost(self, reason) # callbacks for events def signedOn(self): """Called when bot has succesfully signed on to server.""" print "Signing on to %s.\n" % self.factory.channel # self.join(self.factory.channel) self.sendLine("JOIN %s" % (self.factory.channel,)) def joined(self, channel): """This will get called when the bot joins the channel.""" print "Joining channel %s." % channel def privmsg(self, user, channel, msg): """This will get called when the bot receives a message.""" user = user.split('!', 1)[0] # Check to see if they're sending me a private message if channel == self.nickname: msg = "It isn't nice to whisper! Play nice with the group." self.msg(user, msg) return # Otherwise check to see if it is a message directed at me if msg.startswith(self.nickname + ":"): msg = "%s: I am a log bot" % user self.msg(channel, msg) def action(self, user, channel, msg): """This will get called when the bot sees someone do an action.""" user = user.split('!', 1)[0] # irc callbacks def irc_NICK(self, prefix, params): """Called when an IRC user changes their nickname.""" old_nick = prefix.split('!')[0] new_nick = params[0] # For fun, override the method that determines how a nickname is changed
on # collisions. The default method appends an underscore. def alterCollidedNick(self, nickname): """ Generate an altered version of a nickname that caused a collision in an effort to create an unused related name for subsequent registration. """ return nickname + '^'
class LogBotFactory(protocol.ClientFactory): """A factory for LogBots.
A new protocol instance will be created each time we connect to the
server. """
def __init__(self, channel): self.channel = channel def buildProtocol(self, addr): p = LogBot() p.factory = self return p def clientConnectionLost(self, connector, reason): """If we get disconnected, reconnect to server.""" connector.connect() def clientConnectionFailed(self, connector, reason): print "connection failed:", reason reactor.stop()
if __name__ == '__main__': # create factory protocol and application f = LogBotFactory("#testx")
# connect factory to this host and port reactor.connectTCP("192.168.1.170", 6667, f) # run bot reactor.run()
I was told that perhaps I could use twisted.pair, but I have no idea how to use the module. The documentation is lacking and I've only just started programming in Twisted.
Any help appreciated.
Edmund
Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Another option is to run tcpdump as a sub-process writing to stdout, and write a ProcessProtocol to parse the pcap stream. This is not terribly difficult, and can actually have some advantages - if your python process blocks for too long you can lose captured packets, but by letting tcpdump aggressively drive the reading of the socket, you can (ab)use the pipe() buffers to hold a small backlog.
[If you need even more aggressive buffering, replace tcpdump with gulp]
If you do this you should extract packet timestamps from the pcap stream, not the wall clock.
I have code to do this, if anyone can't figure it out themselves.

Thanks all for your pointers and ways to do this packet capturing. Going to try 'em all, if I can.
Edmund
participants (6)
-
bino@indoakses-online.com
-
David Stainton
-
Edmund Wong
-
exarkun@twistedmatrix.com
-
Phil Mayers
-
Sofiane Akermoun