Previous Page Next Page

5.4. Internal Python Services

In the previous section, we learned that subsystems can be used to leverage Unix network applications to provide high-performance services for Honeyd. The performance benefit was mostly due to the fact that subsystems do not require to start a new process for every connection, which is the main drawback of service scripts:

action ::= ["tarpit"] "internal" cmd-string

Honeyd offers yet another alternative called Internal Python Services. Internal Python services use a nonblocking I/O model in which the Python service receives callbacks when more data can be read from the network or written to it. It is implemented using libevent, an event notification library default by one of the authors. Because internal Python services are callback based, you need to encapsulate all your states in a single Python object that is being provided as part of the callback. If your Python service handles multiple connections at once, each connection will have its own state object. A simple example of an internal Python service is shown in Figure 5.5. Read the following section for a detailed description of the functions an internal Python service must provide.

Figure 5.5. An example of an internal Python service. Python services do not require a new process and have low communication overhead. However, they are not as flexible as subsystems. The script prints an SSH banner and then echoes back all user input.

import honeyd

def honeyd_init(data):
      mydata = {} # my very own state object
      honeyd.read_selector(honeyd.EVENT_ON) # i am willing to accept data
      honeyd.write_selector(honeyd.EVENT_ON) # i have data to write
      mydata["write"] = "SSH-1.99-OpenSSH_3.6.1\n" # i want to write this
      return mydata

def honeyd_readdata(mydata, data):
      # everything read from network is in the string 'data'.
      honeyd.read_selector(honeyd.EVENT_ON) # we want to read more
      # we don't want to echo comments back to the user
      if data.startswith('#'):
       return 0
      # we have some to write; which is just the data we got
      honeyd.write_selector(honeyd.EVENT_ON)
      mydata["write"] = data
      return 0

def honeyd_writedata(mydata):
      data = mydata["write"]
      del mydata["write"]
      return data

def honeyd_end(mydata):
      del mydata
      return 0

					  

The filename of a Python internal service must end in ".py" and may not have any "-" in it. Every internal Python service needs to make the following four functions available:

To make internal Python services more flexible, additional functionality is available via the Honeyd Python module. The module exports the following functions:

Unlike subsystems, callbacks for Python internal services are invoked only on network events — that is, either when data can be read or when data can be written. The services have no opportunity to compute in the background or initiate any time-dependent activity. You also should never turn off both read_selector and write_selector at the same time because your service will not get control again until the connection has been terminated by the remote site. Furthermore, Python services are not isolated from the rest of Honeyd, and any bugs in them that cause the Python interpreter to crash will also take down Honeyd. However, besides these drawbacks, if you have a problem that can be solved via a Python internal service, the resulting performance is usually very good.

Previous Page Next Page