Search code examples
pythontwisted

Get Twisted server's IP address


If I have a Twisted server, how can I find its public-facing IP address?

Take this trivial echo server example:

from twisted.internet import protocol, reactor, endpoints

class Echo(protocol.Protocol):
    def dataReceived(self, data):
        self.transport.write(data)

class EchoFactory(protocol.Factory):
    def buildProtocol(self, addr):
        return Echo()

server_endpoint = endpoints.serverFromString(reactor, "tcp:1234")
listening_port_deferred = server_endpoint.listen(EchoFactory())
reactor.run()

I was expecting something like server_endpoint.getHost(), but I can't see that TCP4ServerEndpoint offers anything useful.

By adding the following lines before reactor.run(), we can see that the server is listening on all interfaces (0.0.0.0):

def print_host(listening_port):
    print("listening_port.getHost():", listening_port.getHost())
listening_port_deferred.addCallback(print_host)

It outputs listening_port.getHost(): IPv4Address(type='TCP', host='0.0.0.0', port=1234). But that doesn't help us with the IP address of the network interface of the server.

We can get the IP address of the client by adding the following as the first line of buildProtocol():

print("Client's address:", addr.host)

But that only gives us the client's address.

How should I get the server's IP address?


Solution

  • Twisted will tell you the address you've bound the server to using just the method you found, getHost on the listening port. Unfortunately, it has the big limitation that you found which is that when the server is listening on all local addresses (INADDR_ANY) it gives you 0.0.0.0 (the canonical IPv4 dotted-quad representation of INADDR_ANY).

    When this happens, you have to go outside of Twisted. I've found the netifaces package to be pretty good for this. From the docs:

    >>> netifaces.interfaces()
    ['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0']
    >>> >>> addrs = netifaces.ifaddresses('lo0')
    >>> addrs[netifaces.AF_INET]
    [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}]
    

    By combining this information with the observation that 0.0.0.0 means "all local addresses" you can figure out what local addresses the server will accept connections on.