4 votes

Comment obtenir l'adresse IP locale associée à la passerelle par défaut

Il peut y avoir plusieurs interfaces réseau sur un serveur, par exemple, lo, eth0, eth1

À partir de la table de routage, je sais que eth0 est connecté à la passerelle par défaut. L'adresse de la passerelle par défaut, par exemple, est 192.168.1.1. Et l'adresse de eth0 est, par exemple, 192.168.1.100.

Comment puis-je obtenir l'adresse "192.168.1.100"? Toute approche est ok : Python, Shell, UNIX C API...

Actuellement, je ne peux penser qu'à une seule façon:

  1. Exécuter la commande "route" et obtenir la dernière ligne (par défaut 192.168.1.1 0.0.0.0 ...)
  2. Exécuter la commande "ifconfig" et obtenir la liste des adresses (127.0.0.1, 192.168.1.100, ...)
  3. Trouver l'adresse qui est dans le même sous-réseau que la passerelle par défaut (192.168.1.1)
  4. Ensuite, nous obtenons l'adresse 192.168.1.100

Y a-t-il de meilleures solutions?

PS: Il a été suggéré que nous pouvons appeler connect() sur un socket udp, puis appeler getsockname() pour obtenir l'adresse locale. Cependant, cela fonctionne uniquement sur une partie des serveurs.

@EEAA

Voici mon script :

route -n | awk '$1 == "0.0.0.0" { print $2 }' > gateway.tmp
ip -4 addr show | grep inet | awk '{ print $2 }' > addrs.tmp

La première ligne imprime la passerelle par défaut :

10.1.40.1

La deuxième ligne imprime une liste d'adresses d'interface (en notation cidr) :

127.0.0.1/8
10.1.46.122/21

Ensuite, je dois décider à quel réseau appartient 10.1.40.1. J'écris donc un script Python :

import sys

def ip_to_binary(ip):
    bytes = ip.split(".")
    a = int(bytes[0])
    b = int(bytes[1])
    c = int(bytes[2])
    d = int(bytes[3])
    return "{0:08b}{1:08b}{2:08b}{3:08b}".format(a, b, c, d)

def mask_to_binary(bits):
    return "1" * bits + "0" * (32 - bits)

def binary_and(a, b):
    if len(a) == len(b):
        result = ""
        for i in range(0, len(a)):
            if a[i] == "1" and b[i] == "1":
                result += "1"
            else:
                result += "0"
        return result
    return None

def ip_in_net(ip, net_cidr_notation):
    net_addr, bits = net_cidr_notation.split("/")
    bin_mask = mask_to_binary(int(bits))
    bin_net = ip_to_binary(net_addr)
    bin_ip = ip_to_binary(ip)

    if binary_and(bin_ip, bin_mask) == binary_and(bin_net, bin_mask):
        return True
    return False

# usage: python autoaddr.py gateway_file addrs_file
gateway = open(sys.argv[1]).readline().strip()
addrs = open(sys.argv[2]).readlines()

for addr in addrs:
    if ip_in_net(gateway, addr):
        print addr.split("/")[0]

Pour éviter des dépendances supplémentaires, je n'ai pas utilisé de bibliothèques comme netaddr et ipaddress. Enfin, je dois ajouter le script Python au script Shell :

python autoaddr.py gateway.tmp addrs.tmp > auto.tmp
rm -f gateway.tmp
rm -f addrs.tmp

Maintenant, j'ai un fichier auto.tmp contenant l'adresse générée automatiquement :

10.1.46.122

2voto

SvenniBenni Points 116

Un bash one-liner pour obtenir l'adresse IP par "défaut" de votre machine :

ip -o route get 1.1.1.1 | cut -d " " -f 7

Et si vous en avez besoin en Python 3 :

def get_default_ip():
    output = subprocess.check_output(["ip", "-o", "route", "get", "1.1.1.1"],
                                     universal_newlines=True)
    return output.split(" ")[6]

0voto

Samat Jain Points 165

Pourquoi ne pas essayer quelque chose comme ceci :

$ ip -4 addr show eth0 | grep inet | awk '{ print $2 }'
192.168.1.100/24

Pour votre information, ifconfig est obsolète. Vous devriez commencer à utiliser les différentes commandes ip à la place de ce que vous utilisiez précédemment avec ifconfig.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X