I am writing a distributed systems program in python, and in this program I need to know the local ip-address... eg. 168.192.... 10.13..... etc, not 127.0.0.1 or hostname.

I have found following solution on stackoverflow

https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib

import socket
socket.gethostbyname(socket.gethostname())

When I run this on my Debian jessie laptop, I get 127.0.0.1, however, my friend who is using Fedora on his machine gets the desired ip address when he runs the same script (eg. 168.192..)

I prefer to use the solution above if possible to get the local ip address, because most of the other proposed solutions are either hacks or incredible long...

Is there something I can setup on my Debian jessie laptop such that python will return the correct local ip-address?

  • using debian jessie
  • python 3
  • is connected to network (.. and computer is turned on)... ;)
  • /etc/hosts currently contains:

127.0.0.1 localhost 127.0.0.1 debianASUS ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters

  • Are you actually connected to a network? What's in /etc/hosts? – Michael Hampton May 7 '15 at 17:19
  • 1
    How should the program behave on a multihomed machine ? What if there is a VPN, or a 6rd tunnel ? Do you care about ipv6 ? – b0fh May 8 '15 at 6:55
  • The program is for a school project so I will only consider IPv4 in this version.. I wish to be able to deploy the program on laptops which change networks regularly and the program should be able to work autonomously without any user interaction. – Michelrandahl May 8 '15 at 12:28

The most reliable way to find the IP address your host will use to communicate is by using getsockname on a connected UDP socket. In case of UDP the connect system call doesn't involve any network communication.

Here is a Python function I have written in the past for a similar purpose. If you don't know in advance which remote IP address you will communicate with, you should be looking for one which will be using the default route. If you already know which remote IP address you will communicate with, then it is better to use that IP address in the connect call.

def my_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('192.0.0.8', 1027))
    except socket.error:
        return None
    return s.getsockname()[0]

With a few minor changes, this function can be adapted to return an IPv6 address rather than IPv4:

def my_ipv6():
    s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    try:
        s.connect(('2001:db8::', 1027))
    except socket.error:
        return None
    return s.getsockname()[0]

Have you considered defering the decision to the end user at runtime, through a configuration parameter ? This is a standard practice for this problem.

The reason is there is no systematic foolproof way to figure "the" local IP address (a host may be multihomed, may be running a v4/v6 dual stack, a VPN, etc..). Runtime configuration will make the sysadmin's job easier !

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.