pythonlinuxiphttp.server

Python http server REMOTE_ADDR returns another local ip (Linux)


(I use Linux)

The local IP of my PC is 172.16.1.2
ip a command returns 172.16.1.2

Then I can add another IP to the same network interface:

ip addr add 192.168.1.10 dev eth0

now ip a command returns 2 IPs

172.16.1.2
192.168.1.10

Then I bind a Python simple http server to 192.168.1.10:

from wsgiref.simple_server import make_server

def hello_world_app(environ, start_response):
    print(environ['REMOTE_ADDR'])  # why not 172.16.1.2
    start_response(status='200 OK', headers=[])
    return [b"Hello World"]


IP = '192.168.1.10'
PORT = 8000
make_server(IP, PORT, hello_world_app).serve_forever()

Then simply open http://192.168.1.10:8000 in a browser or via curl

My question is why it prints 192.168.1.10 and not 172.16.1.2?
Since I access the server from my local IP which is 172.16.1.2 I'd expect it to be the REMOTE_ADDR


Solution

  • If the routing table doesn't have a specific 'preferred source address' hint set, then Linux chooses the local address using "longest prefix match"; that is, it generally tries to pick a source address most similar to the destination.

    In this case, 192.168.1.10 ↔ 192.168.1.10 matches all 32 bits (starting from the left as always), while 172.16.1.2 ↔ 192.168.1.10 only matches 1 bit, so the system selects the former.

    (This is not the complete description – I'm sure there are a few other conditions that I've forgotten, and this also works slightly differently between IPv4 and IPv6.)