web-dev-qa-db-fra.com

Comment obtenir l'adresse IP de l'interface physique à partir d'une interface

Ce que j'ai fait jusqu'à présent, en utilisant les classes PyQt:

all_Addresses = QNetworkInterface.allAddresses()    #list-of-QHostAddress

for addr in all_Addresses:
    print(addr.toString())

Production:

172.16.0.186 - Virtual Interface IP address
192.168.10.2 - Physical interface IP address. I want this one.
127.0.0.1

Utilisation de socket:

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

Production:

172.16.0.186 - When openVPN is on
192.168.10.2 - When its off
  1. Existe-t-il un moyen de les distinguer?
  2. Cela peut-il être fait avec Python ordinaire, au lieu d'utiliser des classes PyQt?
  3. Comment puis-je également obtenir l'adresse IPv6?
19
Johny_M

Vous devez utiliser netifaces . Il est conçu pour être multiplateforme et contient du code spécialisé pour Windows ainsi qu'une variété de versions génériques qui fonctionnent sur différentes plates-formes de type UNIX/UNIX.

Depuis netifaces version 0.10.0, Python3 est pris en charge.

Résumé d'utilisation

>>> from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
>>> import netifaces as ni
>>> ni.interfaces()
['lo', 'eth0', 'eth1', 'vboxnet0', 'dummy1']
>>>
>>> ni.ifaddresses('eth0')[AF_LINK]   # NOTE: AF_LINK is an alias for AF_PACKET
[{'broadcast': 'ff:ff:ff:ff:ff:ff', 'addr': '00:02:55:7b:b2:f6'}]
>>> ni.ifaddresses('eth0')[AF_INET]
[{'broadcast': '172.16.161.7', 'netmask': '255.255.255.248', 'addr': '172.16.161.6'}]
>>>
>>> # eth0 ipv4 interface address
>>> ni.ifaddresses('eth0')[AF_INET][0]['addr']
'172.16.161.6'
>>>>

Détails

Prise en charge de Windows:

Aucun compilateur requis pour la plupart des installations MS Windows. Si vous recevez des avertissements concernant l'installation de MS Visual C++ pour Windows, soyez très prudent car vous devez faire correspondre la version du compilateur utilisée pour votre python avec celle utilisée pour le module .

Exemple détaillé de netifaces structures de données:

>>> import netifaces as ni
>>> ni.interfaces()
['lo', 'eth0', 'eth1', 'vboxnet0', 'dummy1']
>>> ni.ifaddresses('eth0')
{
    17: [
        {
            'broadcast': 'ff:ff:ff:ff:ff:ff',
            'addr': '00:02:55:7b:b2:f6'
        }
    ],
    2: [
        {
            'broadcast': '172.16.161.7',
            'netmask': '255.255.255.248',
            'addr': '172.16.161.6'
        }
    ],
    10: [
        {
            'netmask': 'ffff:ffff:ffff:ffff::',
            'addr': 'fe80::202:55ff:fe7b:b2f6%eth0'
        }
    ]
}
>>> 
>>> print(ni.ifaddresses.__doc__)
Obtain information about the specified network interface.

Returns a dict whose keys are equal to the address family constants,
e.g. netifaces.AF_INET, and whose values are a list of addresses in
that family that are attached to the network interface.
>>>
>>> # for the IPv4 address of eth0
>>> ni.ifaddresses('eth0')[2][0]['addr']
'172.16.161.6'

Les nombres utilisés pour indexer les protocoles proviennent de /usr/include/linux/socket.h (sous Linux) ... [~ # ~] éditez [~ # ~] : mon noyau 3.2 les a ici: /usr/src/linux-headers-3.2.0-4-common/include/linux/socket.h

#define AF_INET         2       /* Internet IP Protocol         */
#define AF_INET6        10      /* IP version 6                 */
#define AF_PACKET       17      /* Packet family                */

La bonne nouvelle est que vous n'avez pas à vous souvenir de toutes ces constantes d'en-tête, elles sont incluses avec netifaces :

>>> from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
>>> import netifaces as ni
43
Mike Pennington

Utilise l'ioctl SIOCGIFADDR Linux pour trouver l'adresse IP associée à une interface réseau, étant donné le nom de cette interface, par ex. "eth0 ". L'adresse est renvoyée sous la forme d'une chaîne contenant un quadrillé en pointillés.

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

>>> get_ip_address('lo')
'127.0.0.1'

>>> get_ip_address('eth0')
'38.113.228.130'

Pour plus

16
Tanveer Alam

J'utilise cette solution. C'est un peu délicat en fait, et cela ne fonctionne que sur la famille Linux.

import commands
intf = 'eth0'
intf_ip = commands.getoutput("ip address show dev " + intf).split()
intf_ip = intf_ip[intf_ip.index('inet') + 1].split('/')[0]
print intf_ip

Ces codes utilisent la commande ip sur le système d'exploitation de la famille linux. Il divise la sortie de la commande ip et ne prend que l'adresse IPv4 de cette interface. Vous pouvez remplacer la valeur intf par eth1 ou p2p1.

9
dataq