Găsirea adreselor IP locale folosind stdlib Python sub Debian jessie (Administrarea sistemului, Debian, Ip, Python)

Michelrandahl a intrebat.

Scriu un program de sisteme distribuite în python, iar în acest program am nevoie să știu adresa IP locală… de exemplu 168.192…. 10.13….. etc., nu 127.0.0.1 sau numele de gazdă.

Am găsit următoarea soluție pe stackoverflow

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

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

Când o execut pe laptopul meu Debian jessie, primesc 127.0.0.0.1, însă, , prietenul meu care folosește Fedora pe calculatorul său obține adresa ip dorită atunci când rulează același script (ex. 168.192..)

Prefer să folosesc soluția de mai sus dacă este posibil pentru a obține adresa ip locală, deoarece majoritatea celorlalte soluții propuse sunt fie hack-uri, fie incredibil de lungi…

Există ceva ce pot configura pe laptopul meu Debian jessie astfel încât python să returneze adresa ip locală corectă?

  • folosind Debian jessie
  • python 3
  • este conectat la rețea (.. și calculatorul este pornit)… 😉
  • /etc/hosts conține în prezent:


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

Comentarii

  • Sunteți conectat efectiv la o rețea? Ce se află în /etc/hosts? –  > Por Michael Hampton.
  • Cum ar trebui să se comporte programul pe o mașină multihomed ? Ce se întâmplă dacă există un VPN sau un tunel 6rd ? Vă interesează ipv6?  > Por b0fh.
  • Programul este pentru un proiect școlar, așa că voi lua în considerare doar IPv4 în această versiune… Doresc să pot implementa programul pe laptopuri care schimbă rețelele în mod regulat, iar programul ar trebui să poată funcționa autonom fără nici o interacțiune cu utilizatorul. –  > Por Michelrandahl.
2 răspunsuri
kasperd

Cea mai sigură metodă de a găsi adresa IP pe care gazda dvs. o va folosi pentru a comunica este folosind getsockname pe un socket UDP conectat. În cazul UDP connect apel de sistem nu implică nicio comunicare în rețea.

Iată o funcție Python pe care am scris-o în trecut pentru un scop similar. Dacă nu știți dinainte cu ce adresă IP de la distanță veți comunica, ar trebui să căutați una care va folosi ruta implicită. Dacă știți deja cu ce adresă IP de la distanță veți comunica, atunci este mai bine să folosiți acea adresă IP în apelul de conectare.

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]

Cu câteva modificări minore, această funcție poate fi adaptată pentru a returna o adresă IPv6 în loc de 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]

b0fh

Ați luat în considerare posibilitatea de a amâna decizia către utilizatorul final la momentul execuției, printr-un parametru de configurare? Aceasta este o practică standard pentru această problemă.

Motivul este că nu există o modalitate sistematică și infailibilă de a determina „adresa IP locală” (o gazdă poate fi multihomed, poate rula un dual stack v4/v6, un VPN, etc.). Configurarea în timp de execuție va ușura munca administratorului de sistem !