william-os4y/fapws3

Wrong REMOTE_ADDR/fapws.remote_addr reported

yangzhe1990 opened this issue · 4 comments

I find this problem on a heavily loaded web server running python-bottle 0.10.7-1 on Debian, with fapws3 0.10.dev.

At first I post a bug report at bottle: bottlepy/bottle#290, but then I find it's really a fapws3 bug:

I wrote the simple test script:

!/usr/bin/env python

import fapws._evwsgi as evwsgi
from fapws import base

def start():
evwsgi.start('0.0.0.0', '8000')
evwsgi.set_base_module(base)

def hello(environ, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return ['%s\n%s\n' % (environ['REMOTE_ADDR'], environ['fapws.remote_addr'])]

    
evwsgi.wsgi_cb(('/', hello))

evwsgi.set_debug(0)    
evwsgi.run()

if name == 'main':
start()

Then, by frequent execution of curl, I got

~$ curl http://localhost:8000/
127.0.0.1
127.0.0.1
~$ curl http://localhost:8000/
127.0.0.1
127.0.0.1
~$ curl http://localhost:8000/
127.0.0.1
127.0.0.1
~$ curl http://localhost:8000/ & curl http://10.20.1.50:8000
[1] 26257
127.0.0.1
127.0.0.1
127.0.0.1
127.0.0.1
[1]+ DONE curl http://localhost:8000/

and sometimes

~$ curl http://localhost:8000/ & curl http://10.20.1.50:8000
[4] 26331
10.20.1.50
10.20.1.50
10.20.1.50
10.20.1.50

notice the request at port 40363:

host:10.20.1.50,port:40363 accept_cb: cli:0x9b20770, input_header:0x9aea200
host:127.0.0.1,port:42546 accept_cb: cli:0x9b217f8, input_header:0x9af9c38
host=127.0.0.1,port=42546 connection_cb:cli:0x9b217f8, input_header:0x9b10fe0, input_pos:180, r:180
host=127.0.0.1,port=42546:python_handler:HEADER:
GET /a HTTP/1.1
User-Agent: curl/7.24.0 (i486-pc-linux-gnu) libcurl/7.23.1 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.23 libssh2/1.2.8 librtmp/2.3
Host: localhost:8000
Accept: /

**
host=127.0.0.1,port=42546 write_cli:uri=/a,r=102,len=102,c=1
host=127.0.0.1,port=42546 write_cli:uri=/a,r=20,len=20,c=1
host=127.0.0.1,port=42546 close_connection:cli:0x9b217f8, input_header:0x9b10fe0***
host=127.0.0.1,port=40363 connection_cb:cli:0x9b20770, input_header:0x9b10fe0, input_pos:181, r:181
host=127.0.0.1,port=40363:python_handler:HEADER:

Here it is:

cli->remote_addr=inet_ntoa (client_addr.sin_addr);

inet_ntoa use a static char[] to store the string. So that the remote_addr of each clients has the same address! And will change over time!

Please change this line to
cli->remote_addr = strdup(inet_ntoa(client_addr.sin_addr));

and free() it after the connection is closed.

This is linked to the message in the manpages. Correct ?

"
The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string
is returned in a statically allocated buffer, which subsequent calls will overwrite.
"