GNU/Linux >> Belajar Linux >  >> Linux

Dapatkan alamat antarmuka jaringan lokal hanya menggunakan proc?

Solusi saya untuk mengambil konfigurasi jaringan IPv4, menggunakan /proc hanya:

Sayangnya, ini adalah bash (hanya bash dan tanpa garpu apa pun), bukan python. Tapi saya harap ini bisa dibaca:

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

Ada contoh keluaran:

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

Penjelasan:

Saya menggunakan nilai integer IPV4 untuk memeriksa IP & MASK == NETWORK .

Saya membaca dulu /proc/net/route untuk menemukan konfigurasi perutean, mencari rute yang dapat dijangkau tanpa gateway apa pun (gw==000000 ).

Untuk rute seperti itu, saya mencari di semua koneksi (TCP, daripada UDP jika tidak ditemukan di TCP) untuk koneksi menggunakan ini route, titik akhir pertama adalah alamat host saya.

Catatan:Ini tidak akan berfungsi dengan koneksi PPP

Nota2:Ini tidak akan berfungsi pada host yang benar-benar sepi tanpa koneksi jaringan terbuka. Anda dapat melakukan sesuatu seperti echo -ne '' | nc -q 0 -w 1 8.8.8.8 80 & sleep .2 && ./retrieveIp.sh untuk memastikan bahwa sesuatu ditemukan di /proc/net/tcp .

Nota3, 2016-09.23:Versi bash baru menggunakan >(command) sintaks untuk multiple inline pipe fitur . Ini menyiratkan bug pada baris 18:spasi harus hadir di antara > dan ( !!

Versi baru dengan gateway

Ada sedikit tambalan:Setelah Anda membuat file bernama getIPv4.sh dengan menyalin skrip sebelumnya, Anda dapat menempelkan yang berikut ke perintah: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

Akhiri dengan Ctrl d , ini mungkin menampilkan:

patching file getIPv4.sh

Dan mungkin

Hunk #1 succeeded at 35 with fuzz 2.

Kemudian jalankan kembali skrip Anda:

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

Anda mungkin menemukan output dari ip addr show lebih mudah diuraikan daripada keluaran dari alat lain:

$ 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

Pilihan lainnya adalah file /proc/net/tcp . Ini menunjukkan semua sesi TCP yang sedang dibuka, yang berbeda dari yang Anda minta, tetapi mungkin Cukup Baik.

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

IP saya adalah 192.168.0.121; perhatikan aritmatika lucu untuk membuatnya keluar dengan benar. :)


/proc/net/fib_trie memegang topografi jaringan

Untuk sekadar mencetak alamat semua adaptor:

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

Untuk menentukan adaptor dari alamat tersebut (a) lihat jaringan tujuan adaptor dari /proc/net/route , (b) mencocokkan jaringan tersebut dengan jaringan /proc/net/fib_trie dan (c) mencetak /32 alamat host yang sesuai yang tercantum di bawah jaringan tersebut.

Sekali lagi tidak ada python sayangnya, tapi bash cukup canggung pendekatan:

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

keluaran:

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

Batasan yang diketahui:

Pendekatan ini tidak dapat diandalkan untuk alamat host yang berbagi jaringan dengan alamat host lain. Hilangnya keunikan jaringan ini membuat tidak mungkin untuk menentukan alamat host yang benar dari fib_trie karena urutan alamat tersebut tidak harus sesuai dengan urutan jaringan rute.

Karena itu, saya tidak yakin mengapa Anda ingin beberapa alamat host milik jaringan yang sama di tempat pertama. Jadi dalam sebagian besar kasus penggunaan, pendekatan ini akan berfungsi dengan baik.


Tidak ada analog IPv4 dari /proc/net/if_inet6

ifconfig melakukan:

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

Anda akan mendapatkan sesuatu seperti ini:

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. Menggunakan alat SS untuk pemecahan masalah jaringan

  2. Temukan Hanya Tujuan Symlink?

  3. Tambahkan antarmuka Jaringan Cloud ke Server Cloud

  1. Dapatkan alamat IP dari sebuah antarmuka di Linux

  2. Python:dapatkan gateway default untuk antarmuka/alamat ip lokal di linux

  3. Mengizinkan akses ke host virtual Apache hanya dari jaringan lokal

  1. Cara memblokir alamat palsu lokal menggunakan firewall Linux

  2. Cara menuju ke layanan/server yang berada di jaringan yang tidak dapat diakses (menggunakan terowongan SSH)

  3. Linux - Pengikatan Antarmuka Jaringan Tampaknya Hanya Berfungsi Sebagai Root?