Encontrando endereços IP locais usando o stdlib do Python sob o Debian jessie

2

Estou escrevendo um programa de sistemas distribuídos em python, e neste programa eu preciso saber o endereço IP local ... por exemplo. 168.192 .... 10.13 ..... etc, não 127.0.0.1 ou hostname.

Eu encontrei a seguinte solução em stackoverflow

link

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

Quando eu executo isso no meu laptop Debian jessie, eu consigo 127.0.0.1, no entanto , meu amigo que está usando o Fedora em sua máquina recebe o endereço IP desejado quando ele executa o mesmo script 168.192 ..)

Eu prefiro usar a solução acima, se possível, para obter o endereço IP local, porque a maioria das outras soluções propostas são hacks ou incríveis por muito tempo ...

Existe algo que eu possa configurar no meu laptop Debian jessie, de modo que o python retorne o endereço IP local correto?

  • usando o debian jessie
  • python 3
  • está conectado à rede (.. e o computador está ligado) ...;)
  • / etc / hosts contém atualmente:

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

    
por Michelrandahl 07.05.2015 / 18:27

2 respostas

3

A maneira mais confiável de encontrar o endereço IP que seu host usará para se comunicar é usando getsockname em um soquete UDP conectado. No caso do UDP, a chamada do sistema connect não envolve nenhuma comunicação de rede.

Aqui está uma função do Python que escrevi no passado para um propósito semelhante. Se você não sabe de antemão com qual endereço IP remoto irá se comunicar, você deve procurar por um que esteja usando a rota padrão. Se você já sabe com qual endereço IP remoto irá se comunicar, então é melhor usar esse endereço IP na chamada de conexão.

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]

Com algumas pequenas alterações, essa função pode ser adaptada para retornar um endereço IPv6 em vez 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]
    
por 24.07.2016 / 11:32
2

Já considerou adiar a decisão para o usuário final em tempo de execução, por meio de um parâmetro de configuração? Esta é uma prática padrão para este problema.

A razão é que não existe uma maneira sistemática de descobrir "o" endereço IP local (um host pode ser multihomed, pode estar executando uma pilha dual v4 / v6, uma VPN, etc.). A configuração em tempo de execução tornará o trabalho do administrador de sistemas mais fácil!

    
por 08.05.2015 / 09:00