You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@thrift.apache.org by Aaron Bernard <aa...@gmail.com> on 2010/01/14 21:29:52 UTC

Python server only registers tcp6 (IPv6) socket in FreeBSD

I coded up a test program in Thrift with a python client and server.

When the server is on my Mac OSX machine and the client is on FreeBSD, everything works as expected.  I can see the server side print statements and the return data on the client.

However, if I try to serve from the FreeBSD machine, the client cannot connect with the following error:

-----------------
python test_client.py 
/usr/lib/python2.6/site-packages/thrift/Thrift.py:58: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
  self.message = message
test_client.py:32: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
  print '%s' % (tx.message)
Could not connect to 192.168.50.79:9090
-----------------

The server code is almost identical to the tutorial PythonServer.py code, with the TServerSocket registered on port 9090 as well.  The code is identical on both machines, with the exception of swapped IPs in the TSocket call:

test_client.py:
-----------------
... imports, sys.path, etc. .....

try:
  transport = TSocket.TSocket('192.168.50.79', 9090) # this IP is switched on the other machine
  transport = TTransport.TBufferedTransport(transport)
  protocol = TBinaryProtocol.TBinaryProtocol(transport)
  client = Test.Client(protocol)
  transport.open()

  client.ping()
  print 'ping()'

  val = client.number(5)
  print 'number back: %d' % (val)

  transport.close()

except Thrift.TException, tx:
  print '%s' % (tx.message)
-----------------

I ran a FreeBSD `sockstat -4 -l' to confirm that the socket was running under the right port (or at all), but saw nothing.  When I removed the -4 flag to see all sockets, not just IPv4, the service showed up.

When I run `netstat -an' on the FreeBSD machine, here is the relevant output:

netstat -an | grep 9090
-----------------
tcp6       0      0 *.9090                 *.*                    LISTEN          
-----------------

 As you can see, the server is running tcp6 sockets on the 9090 python server.

However, when I run this command on my Mac OSX machine, I get the following:

netstat -an | grep 9090
-----------------
tcp46      0      0  *.9090                 *.*                    LISTEN
-----------------

The Mac OSX is flexibly serving sockets on both IPv4 and IPv6.

I have no firewall running on the FreeBSD machine.  As bi-directional communication works just fine when the server roles are reversed, I don't think it has anything to do with that.

So, my question is: is this expected behavior? Am I doing something wrong?  Or is this perhaps a platform bug involving the generated python TSocket code and FreeBSD?  Is this even relevant?

Any help would be much appreciated.

Thanks,
Aaron

Re: Python server only registers tcp6 (IPv6) socket in FreeBSD

Posted by Jon Dugan <jd...@x1024.net>.
Excerpts from David Reiss's message of Thu Jan 14 14:47:20 -0600 2010:
> It's not expected behavior.  It is highly unlikely to be related to the
> generated code
> (TSocket is not generated).  I assume the TServerSocket code is doing something
> to make
> FreeBSD think it only wants IPv6.  I'm not sure what the fix is, though.

I ran into this a long time ago and never got around to filing a bug report.

One work around is to change the sysctl variable that prohibits v6 sockets
from also listening on v4:

sysctl -w net.inet6.ip6.v6only=0

This has security implications that I can't recall the full details of, so I
came up with a more flexible solution.

However I think this might be due to some strange behavior in TSocket.py.  The
listen method for TServerSocket has this odd bit in it (lines 121-125 of
TSocket.py from trunk):

  def listen(self):
    res0 = self._resolveAddr()
    for res in res0:
      if res[0] is socket.AF_INET6 or res is res0[-1]:
        break

I read this as take the first v6 address you find or the last address you
find.  Seems kind of weird to prefer IPv6 at this point.

I have a subclass of TServerSocket that I use that allows me to specify hints
for what kind of socket to listen on.  So in my code I call MyTServerSocket
with hints={'family': socket.AF_INET} so that I bind the the v4 address.

Hope that helps.  FWIW I think the TServerSocket class should implement
something like this.  With a little arm twisting I could probably submit a
patch...

Jon

-- snip --

class MyTServerSocket(TServerSocket):
    def __init__(self, port, host='0.0.0.0', hints={}):
    
        self.host = host
        self.port = port
        self.hints = { 
            'family': socket.AF_UNSPEC,
            'socktype': socket.SOCK_STREAM,
            'proto': 0,
            'flags': socket.AI_PASSIVE}
        self.hints.update(hints)
        TServerSocket.__init__(self, port)

    def listen(self):
        res0 = socket.getaddrinfo(None, self.port, self.hints['family'],
                self.hints['socktype'], self.hints['proto'],
                self.hints['flags'])
        for res in res0:
            if res[0] is socket.AF_INET6 or res is res0[-1]:
                break

        self.handle = socket.socket(res[0], res[1])
        self.handle.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        if hasattr(self.handle, 'set_timeout'):
            self.handle.set_timeout(None)
        self.handle.bind(res[4])
        self.handle.listen(128)

Re: Python server only registers tcp6 (IPv6) socket in FreeBSD

Posted by Aaron Bernard <aa...@gmail.com>.
Fixed it.  It seems this is just a zealous security quirk with FreeBSD, due to a security risk mentioned here: http://tools.ietf.org/id/draft-itojun-v6ops-v4mapped-harmful-02.txt

Because of this, IPv4 socket mapping on IPv6 with AF_INET6 is disallowed by default in FreeBSD.  

I added  ipv6_ipv4mapping="YES" in /etc/rc.conf (which a /etc/netstart to reload changes) and everything works now.  The socket shows up as tcp46.

Here is my reference: http://www.trend-watcher.org/post/1/115

-A

On Jan 14, 2010, at 2:47 PM, David Reiss wrote:

> It's not expected behavior.  It is highly unlikely to be related to the generated code
> (TSocket is not generated).  I assume the TServerSocket code is doing something to make
> FreeBSD think it only wants IPv6.  I'm not sure what the fix is, though.
> 
> --David
> 
> Aaron Bernard wrote:
>> I coded up a test program in Thrift with a python client and server.
>> 
>> When the server is on my Mac OSX machine and the client is on FreeBSD, everything works as expected.  I can see the server side print statements and the return data on the client.
>> 
>> However, if I try to serve from the FreeBSD machine, the client cannot connect with the following error:
>> 
>> -----------------
>> python test_client.py 
>> /usr/lib/python2.6/site-packages/thrift/Thrift.py:58: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
>>  self.message = message
>> test_client.py:32: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
>>  print '%s' % (tx.message)
>> Could not connect to 192.168.50.79:9090
>> -----------------
>> 
>> The server code is almost identical to the tutorial PythonServer.py code, with the TServerSocket registered on port 9090 as well.  The code is identical on both machines, with the exception of swapped IPs in the TSocket call:
>> 
>> test_client.py:
>> -----------------
>> ... imports, sys.path, etc. .....
>> 
>> try:
>>  transport = TSocket.TSocket('192.168.50.79', 9090) # this IP is switched on the other machine
>>  transport = TTransport.TBufferedTransport(transport)
>>  protocol = TBinaryProtocol.TBinaryProtocol(transport)
>>  client = Test.Client(protocol)
>>  transport.open()
>> 
>>  client.ping()
>>  print 'ping()'
>> 
>>  val = client.number(5)
>>  print 'number back: %d' % (val)
>> 
>>  transport.close()
>> 
>> except Thrift.TException, tx:
>>  print '%s' % (tx.message)
>> -----------------
>> 
>> I ran a FreeBSD `sockstat -4 -l' to confirm that the socket was running under the right port (or at all), but saw nothing.  When I removed the -4 flag to see all sockets, not just IPv4, the service showed up.
>> 
>> When I run `netstat -an' on the FreeBSD machine, here is the relevant output:
>> 
>> netstat -an | grep 9090
>> -----------------
>> tcp6       0      0 *.9090                 *.*                    LISTEN          
>> -----------------
>> 
>> As you can see, the server is running tcp6 sockets on the 9090 python server.
>> 
>> However, when I run this command on my Mac OSX machine, I get the following:
>> 
>> netstat -an | grep 9090
>> -----------------
>> tcp46      0      0  *.9090                 *.*                    LISTEN
>> -----------------
>> 
>> The Mac OSX is flexibly serving sockets on both IPv4 and IPv6.
>> 
>> I have no firewall running on the FreeBSD machine.  As bi-directional communication works just fine when the server roles are reversed, I don't think it has anything to do with that.
>> 
>> So, my question is: is this expected behavior? Am I doing something wrong?  Or is this perhaps a platform bug involving the generated python TSocket code and FreeBSD?  Is this even relevant?
>> 
>> Any help would be much appreciated.
>> 
>> Thanks,
>> Aaron


Re: Python server only registers tcp6 (IPv6) socket in FreeBSD

Posted by David Reiss <dr...@facebook.com>.
It's not expected behavior.  It is highly unlikely to be related to the generated code
(TSocket is not generated).  I assume the TServerSocket code is doing something to make
FreeBSD think it only wants IPv6.  I'm not sure what the fix is, though.

--David

Aaron Bernard wrote:
> I coded up a test program in Thrift with a python client and server.
> 
> When the server is on my Mac OSX machine and the client is on FreeBSD, everything works as expected.  I can see the server side print statements and the return data on the client.
> 
> However, if I try to serve from the FreeBSD machine, the client cannot connect with the following error:
> 
> -----------------
> python test_client.py 
> /usr/lib/python2.6/site-packages/thrift/Thrift.py:58: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
>   self.message = message
> test_client.py:32: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
>   print '%s' % (tx.message)
> Could not connect to 192.168.50.79:9090
> -----------------
> 
> The server code is almost identical to the tutorial PythonServer.py code, with the TServerSocket registered on port 9090 as well.  The code is identical on both machines, with the exception of swapped IPs in the TSocket call:
> 
> test_client.py:
> -----------------
> ... imports, sys.path, etc. .....
> 
> try:
>   transport = TSocket.TSocket('192.168.50.79', 9090) # this IP is switched on the other machine
>   transport = TTransport.TBufferedTransport(transport)
>   protocol = TBinaryProtocol.TBinaryProtocol(transport)
>   client = Test.Client(protocol)
>   transport.open()
> 
>   client.ping()
>   print 'ping()'
> 
>   val = client.number(5)
>   print 'number back: %d' % (val)
> 
>   transport.close()
> 
> except Thrift.TException, tx:
>   print '%s' % (tx.message)
> -----------------
> 
> I ran a FreeBSD `sockstat -4 -l' to confirm that the socket was running under the right port (or at all), but saw nothing.  When I removed the -4 flag to see all sockets, not just IPv4, the service showed up.
> 
> When I run `netstat -an' on the FreeBSD machine, here is the relevant output:
> 
> netstat -an | grep 9090
> -----------------
> tcp6       0      0 *.9090                 *.*                    LISTEN          
> -----------------
> 
>  As you can see, the server is running tcp6 sockets on the 9090 python server.
> 
> However, when I run this command on my Mac OSX machine, I get the following:
> 
> netstat -an | grep 9090
> -----------------
> tcp46      0      0  *.9090                 *.*                    LISTEN
> -----------------
> 
> The Mac OSX is flexibly serving sockets on both IPv4 and IPv6.
> 
> I have no firewall running on the FreeBSD machine.  As bi-directional communication works just fine when the server roles are reversed, I don't think it has anything to do with that.
> 
> So, my question is: is this expected behavior? Am I doing something wrong?  Or is this perhaps a platform bug involving the generated python TSocket code and FreeBSD?  Is this even relevant?
> 
> Any help would be much appreciated.
> 
> Thanks,
> Aaron