GNU/Linux >> Znalost Linux >  >> Linux

Získat adresy místního síťového rozhraní pouze pomocí proc?

Moje řešení pro načtení konfigurace sítě IPv4 pomocí /proc pouze:

Bohužel se jedná o bash (pouze bash a bez jakákoli vidlice), ne python. Ale doufám, že to bude čitelné:

#!/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

Existuje ukázka výstupu:

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

Vysvětlení:

Ke kontrole IP & MASK == NETWORK používám celočíselnou hodnotu IPV4 .

Nejprve jsem přečetl /proc/net/route k nalezení konfigurací směrování, hledání cest dosažitelných bez brány (gw==000000 ).

Pro takovou trasu hledám ve všech spojeních (TCP, než UDP, pokud se nenachází v TCP) spojení pomocí toto trasa, první koncový bod je moje adresa hostitele.

Poznámka:Toto nebude fungovat s připojením PPP

Poznámka2:Toto nebude fungovat na zcela tichém hostiteli bez otevřeného síťového připojení. Můžete udělat něco jako echo -ne '' | nc -q 0 -w 1 8.8.8.8 80 & sleep .2 && ./retrieveIp.sh pro zajištění toho, že se něco nachází v /proc/net/tcp .

Nota3, 2016-09.23:Nová verze bash používá >(command) syntaxe pro multiple inline pipe funkce . To znamená chybu na řádku 18:mezera musí být přítomen mezi > a ( !!

Nová verze s bránou

Existuje malá oprava:Jakmile vytvoříte soubor s názvem getIPv4.sh zkopírováním předchozího skriptu můžete do příkazu vložit následující: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

Ukončete klávesou Ctrl d , může to mít výstup:

patching file getIPv4.sh

A možná

Hunk #1 succeeded at 35 with fuzz 2.

Poté znovu spusťte skript:

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ůžete najít výstup ip addr show snazší analyzovat než výstup z jiných nástrojů:

$ 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

Další možností je soubor /proc/net/tcp . Zobrazuje všechny aktuálně otevřené TCP relace, což se liší od toho, co jste požadovali, ale může být dost dobré.

$ 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]

Moje IP je 192.168.0.121; všimněte si legrační aritmetiky, aby to vyšlo správně. :)


/proc/net/fib_trie obsahuje topografii sítě

Chcete-li jednoduše vytisknout adresy všech adaptérů:

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

Chcete-li určit adaptér těchto adres (a), podívejte se na cílové sítě adaptérů z /proc/net/route , (b) spárovat tyto sítě se sítěmi /proc/net/fib_trie a (c) vytisknout odpovídající /32 hostitelské adresy uvedené pod těmito sítěmi.

Opět žádné python bohužel, ale docela trapné bash přístup:

#!/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

výstup:

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

Známé omezení:

Tento přístup nefunguje spolehlivě pro adresy hostitelů, které sdílejí síť s jinými adresami hostitelů. Tato ztráta jedinečnosti sítě znemožňuje určit správnou adresu hostitele z fib_trie, protože pořadí těchto adres nemusí nutně odpovídat pořadí sítí na trase.

Přesto si nejsem jistý, proč byste na prvním místě chtěli více adres hostitelů patřících do stejné sítě. Takže ve většině případů použití by tento přístup měl fungovat dobře.


Neexistuje žádný analog IPv4 /proc/net/if_inet6

ifconfig dělá:

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

Dostanete něco takového:

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. Použití nástroje SS pro řešení problémů se sítí

  2. Jak se dostat ke službě/serveru, který je v nepřístupné síti (pomocí SSH tunelů)

  3. Ssh – Vyžadovat Google-authenticator pouze mimo místní síť?

  1. Přidejte cloudové síťové rozhraní ke cloudovému serveru

  2. Ifconfig:7 příkladů konfigurace síťového rozhraní

  3. Získejte IP adresu rozhraní v systému Linux

  1. Jak blokovat místní podvržené adresy pomocí firewallu Linux

  2. Linux – Zdá se, že vazba síťového rozhraní funguje pouze jako root?

  3. Povolení přístupu k virtuálnímu hostiteli Apache pouze z místní sítě