GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Lokale Netzwerkschnittstellenadressen nur mit proc abrufen?

Meine Lösung zum Abrufen der IPv4-Netzwerkkonfiguration mit /proc nur:

Leider ist dies Bash (nur Bash und ohne jede Gabel), nicht Python. Aber ich hoffe, das wird lesbar sein:

#!/bin/bash

# ip functions that set variables instead of returning to STDOUT

hexToInt() {
    printf -v $1 "%d\n" 0x${2:6:2}${2:4:2}${2:2:2}${2:0:2}
}
intToIp() {
    local var=$1 iIp
    shift
    for iIp ;do 
        printf -v $var "%s %s.%s.%s.%s" "${!var}" $(($iIp>>24)) \
            $(($iIp>>16&255)) $(($iIp>>8&255)) $(($iIp&255))
    done
}
maskLen() {
    local i
    for ((i=0; i<32 && ( 1 & $2 >> (31-i) ) ;i++));do :;done
    printf -v $1 "%d" $i
}

# The main loop.

while read -a rtLine ;do
    if [ ${rtLine[2]} == "00000000" ] && [ ${rtLine[7]} != "00000000" ] ;then
        hexToInt netInt  ${rtLine[1]}
        hexToInt maskInt ${rtLine[7]}
        if [ $((netInt&maskInt)) == $netInt ] ;then
            for procConnList in /proc/net/{tcp,udp} ;do
                while IFS=': \t\n' read -a conLine ;do
                    if [[ ${conLine[1]} =~ ^[0-9a-fA-F]*$ ]] ;then
                        hexToInt ipInt ${conLine[1]}
                        [ $((ipInt&maskInt)) == $netInt ] && break 3
                    fi
                done < $procConnList
            done
        fi
    fi
done < /proc/net/route 

# And finaly the printout of what's found

maskLen maskBits $maskInt
intToIp addrLine $ipInt $netInt $maskInt
printf -v outForm '%-12s: %%s\\n' Interface Address Network Netmask Masklen
printf "$outForm" $rtLine $addrLine $maskBits\ bits

Es gibt ein Ausgabebeispiel:

Interface   : eth0
Address     : 192.168.1.32
Network     : 192.168.1.0
Netmask     : 255.255.255.0
Masklen     : 24 bits

Erklärung:

Ich verwende den ganzzahligen Wert von IPV4, um IP & MASK == NETWORK zu überprüfen .

Ich habe zuerst /proc/net/route gelesen um Routing-Konfigurationen zu finden, Suche nach Routen, die ohne Gateway erreichbar sind (gw==000000 ).

Für eine solche Route suche ich in allen Verbindungen (TCP, dann UDP, wenn nicht in TCP gefunden) nach Verbindungen mit this route, der erste Endpunkt ist meine Hostadresse.

Hinweis:Dies funktioniert nicht mit PPP-Verbindungen

Nota2:Dies funktioniert nicht auf einem völlig ruhigen Host ohne geöffnete Netzwerkverbindung. Sie könnten so etwas wie echo -ne '' | nc -q 0 -w 1 8.8.8.8 80 & sleep .2 && ./retrieveIp.sh tun um sicherzustellen, dass etwas in /proc/net/tcp gefunden wurde .

Nota3, 2016-09.23:Neue Bash-Version verwendet >(command) Syntax für multiple inline pipe Funktion . Dies impliziert einen Fehler in Zeile 18:ein Leerzeichen muss zwischen > vorhanden sein und ( !!

Neue Version mit Gateway

Es gibt einen kleinen Patch:Sobald Sie eine Datei namens getIPv4.sh erstellen Wenn Sie das vorherige Skript kopieren, können Sie Folgendes in den Befehl einfügen:patch -p0

--- getIPv4.sh
+++ getIPv4.sh
@@ -35,13 +35,16 @@
                 done < $procConnList
             done
         fi
+    elif [ ${rtLine[1]} == "00000000" ] && [ ${rtLine[7]} == "00000000" ] ;then
+       hexToInt netGw ${rtLine[2]}
     fi
 done < /proc/net/route 

 # And finaly the printout of what's found

 maskLen maskBits $maskInt
-intToIp addrLine $ipInt $netInt $maskInt
-printf -v outForm '%-12s: %%s\\n' Interface Address Network Netmask Masklen
+intToIp addrLine $ipInt $netInt $netGw $maskInt
+printf -v outForm '%-12s: %%s\\n' \
+       Interface Address Network Gateway Netmask Masklen
 printf "$outForm" $rtLine $addrLine $maskBits\ bits

Beenden Sie mit Strg d , kann dies Folgendes ausgeben:

patching file getIPv4.sh

Und vielleicht

Hunk #1 succeeded at 35 with fuzz 2.

Führen Sie dann Ihr Skript erneut aus:

getIPv4.sh
Interface   : eth0
Address     : 192.168.1.32
Network     : 192.168.1.0
Gateway     : 192.168.1.1
Netmask     : 255.255.255.0
Masklen     : 24 bits

Möglicherweise finden Sie die Ausgabe von ip addr show einfacher zu parsen als die Ausgabe von anderen Tools:

$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:24:1d:ce:47:05 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.121/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::224:1dff:fece:4705/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
    link/ether 00:24:1d:ce:35:d5 brd ff:ff:ff:ff:ff:ff
4: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 92:e3:6c:08:1f:af brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
    inet6 fe80::90e3:6cff:fe08:1faf/64 scope link
       valid_lft forever preferred_lft forever

Eine weitere Möglichkeit ist die Datei /proc/net/tcp . Es zeigt alle derzeit geöffneten TCP-Sitzungen an, was anders ist als das, wonach Sie gefragt haben, aber möglicherweise ausreichend ist.

$ cat tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 13536 1 ffff88019f0a1380 300 0 0 2 -1
   1: 00000000:1355 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 19877854 1 ffff880016e69380 300 0 0 2 -1
   2: 017AA8C0:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 13633 1 ffff88019f0a1a00 300 0 0 2 -1
   3: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 8971 1 ffff88019f0a0000 300 0 0 2 -1
   4: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 12952880 1 ffff880030e30680 300 0 0 2 -1
   5: 00000000:0539 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14332 1 ffff88019f0a2080 300 0 0 2 -1
   6: 00000000:C000 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 14334 1 ffff88019f0a2700 300 0 0 2 -1
   7: 0100007F:0A44 00000000:0000 0A 00000000:00000000 00:00000000 00000000   119        0 51794804 1 ffff880016e6a700 300 0 0 2 -1
   8: 7900A8C0:B094 53D50E48:01BB 01 00000000:00000000 00:00000000 00000000  1000        0 64877487 1 ffff880100502080 23 4 16 4 -1
   9: 7900A8C0:9576 537F7D4A:01BB 06 00000000:00000000 03:00000E5D 00000000     0        0 0 3 ffff880100c84600
  10: 7900A8C0:CC84 0CC181AE:01BB 01 00000000:00000000 00:00000000 00000000  1000        0 61775908 1 ffff880198715480 35 4 11 4 -1
$ irb
irb(main):001:0> [0x79, 0x00, 0xa8, 0xc0]
=> [121, 0, 168, 192]

Meine IP ist 192.168.0.121; Beachten Sie die lustige Arithmetik, damit es richtig herauskommt. :)


/proc/net/fib_trie enthält die Netzwerktopographie

Um einfach die Adressen aller Adapter auszudrucken:

$ awk '/32 host/ { print f } {f=$2}' <<< "$(</proc/net/fib_trie)"
127.0.0.1
192.168.0.5
192.168.1.14

Um den Adapter dieser Adressen zu bestimmen, (a) konsultieren Sie die Zielnetzwerke der Adapter unter /proc/net/route , (b) diese Netzwerke mit denen von /proc/net/fib_trie abgleichen und (c) die entsprechenden /32-Hostadressen drucken, die unter diesen Netzwerken aufgelistet sind.

Wieder kein python leider, aber ein ziemlich umständlicher bash Ansatz:

#!/bin/bash

ft_local=$(awk '$1=="Local:" {flag=1} flag' <<< "$(</proc/net/fib_trie)")

for IF in $(ls /sys/class/net/); do
    networks=$(awk '$1=="'$IF'" && $3=="00000000" && $8!="FFFFFFFF" {printf $2 $8 "\n"}' <<< "$(</proc/net/route)" )
    for net_hex in $networks; do
            net_dec=$(awk '{gsub(/../, "0x& "); printf "%d.%d.%d.%d\n", $4, $3, $2, $1}' <<< $net_hex)
            mask_dec=$(awk '{gsub(/../, "0x& "); printf "%d.%d.%d.%d\n", $8, $7, $6, $5}' <<< $net_hex)
            awk '/'$net_dec'/{flag=1} /32 host/{flag=0} flag {a=$2} END {print "'$IF':\t" a "\n\t'$mask_dec'\n"}' <<< "$ft_local"
    done
done

exit 0

Ausgabe:

eth0:     192.168.0.5
          255.255.255.0

lo:       127.0.0.1
          255.0.0.0

wlan0:    192.168.1.14
          255.255.255.0

Bekannte Einschränkung:

Dieser Ansatz funktioniert nicht zuverlässig für Hostadressen, die das Netzwerk mit anderen Hostadressen teilen. Dieser Verlust der Eindeutigkeit des Netzwerks macht es unmöglich, die korrekte Hostadresse von fib_trie zu bestimmen, da die Reihenfolge dieser Adressen nicht unbedingt mit der Reihenfolge der Routennetzwerke übereinstimmt.

Allerdings bin ich mir nicht sicher, warum Sie überhaupt mehrere Hostadressen haben möchten, die zu demselben Netzwerk gehören. In den meisten Anwendungsfällen sollte dieser Ansatz also gut funktionieren.


Es gibt kein IPv4-Analogon von /proc/net/if_inet6

ifconfig macht:

fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)
ioctl(fd, SIOCGIFCONF, ...)

Sie erhalten etwa Folgendes:

ioctl(4, SIOCGIFCONF, {120, {{"lo", {AF_INET, inet_addr("127.0.0.1")}}, {"eth0", {AF_INET, inet_addr("10.6.23.69")}}, {"tun0", {AF_INET, inet_addr("10.253.10.151")}}}})

Linux
  1. Verwenden des SS-Tools für die Netzwerkfehlerbehebung

  2. So gelangen Sie zu einem Dienst/Server, der sich in einem unzugänglichen Netzwerk befindet (mithilfe von SSH-Tunneln)

  3. Ssh – Nur Google-Authentifikator von außerhalb des lokalen Netzwerks erforderlich?

  4. Fügen Sie einem Cloud-Server eine Cloud-Netzwerkschnittstelle hinzu

  5. Ifconfig:7 Beispiele zum Konfigurieren der Netzwerkschnittstelle

So blockieren Sie lokale gefälschte Adressen mit der Linux-Firewall

3 Möglichkeiten, eine Netzwerkschnittstelle in Linux zu konfigurieren

Verwenden von ifstat für Linux-Netzwerkstatistiken

Nur Ziel von Symlink finden?

CentOS / RHEL 6 :Hinzufügen/Entfernen zusätzlicher IP-Adressen zu einer Netzwerkschnittstelle

Rufen Sie die IP-Adresse einer Schnittstelle unter Linux ab