(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
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.)