Pertanyaan ini hampir sama dengan pertanyaan sebelumnya, Dapatkan Alamat IP komputer lokal -Question. Namun saya perlu menemukan alamat IP dari Mesin Linux .
Jadi: Bagaimana cara saya - secara terprogram dalam C ++ - mendeteksi alamat IP server linux tempat aplikasi saya berjalan. Server akan memiliki setidaknya dua alamat IP dan saya memerlukan yang spesifik (yang ada di jaringan tertentu (yang publik)).
Saya yakin ada fungsi sederhana untuk melakukan itu - tetapi di mana?
Untuk membuatnya sedikit lebih jelas:
- Server jelas akan memiliki "localhost": 127.0.0.1
- Server akan memiliki alamat IP internal (manajemen): 172.16.xx
- Server akan memiliki alamat IP eksternal (publik): 80.190.xx
Saya perlu mencari alamat IP eksternal untuk mengikat aplikasi saya ke sana. Jelas saya juga bisa mengikat ke INADDR_ANY (dan sebenarnya itulah yang saya lakukan saat ini). Saya lebih suka mendeteksi alamat publik.
c++
linux
networking
ip-address
BlaM
sumber
sumber
ifconfig
,route
dll usang untukip
perintah. Sekarang Anda harus menggunakannya sebagai gantinya.Jawaban:
Saya menemukan solusi ioctl bermasalah pada os x (yang sesuai dengan POSIX sehingga harus serupa dengan linux). Namun getifaddress () akan membiarkan Anda melakukan hal yang sama dengan mudah, itu berfungsi dengan baik untuk saya di os x 10.5 dan harus sama di bawah ini.
Saya telah melakukan contoh cepat di bawah ini yang akan mencetak semua alamat IPv4 mesin, (Anda juga harus memeriksa apakah getifaddrs berhasil yaitu mengembalikan 0).
Saya telah memperbaruinya menunjukkan alamat IPv6 juga.
sumber
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
lo
danwlan0
antarmuka dalam kasus saya. Apa yang saya butuhkan adalahwlan0
ataueth0
yang memiliki koneksi internet. Jadi, haruskah saya menggunakanstrcmp
atau ada cara yang lebih baik?ioctl(<socketfd>, SIOCGIFCONF, (struct ifconf)&buffer);
Baca
/usr/include/linux/if.h
untuk informasi tentangifconf
danifreq
struktur. Ini akan memberi Anda alamat IP dari setiap antarmuka pada sistem. Baca juga/usr/include/linux/sockios.h
untuk ioctl tambahan.sumber
Saya suka jawaban jjvainio . Seperti yang dikatakan Zan Lnyx, ia menggunakan tabel perutean lokal untuk menemukan alamat IP antarmuka ethernet yang akan digunakan untuk koneksi ke host eksternal tertentu. Dengan menggunakan soket UDP yang terhubung, Anda bisa mendapatkan informasi tanpa benar-benar mengirim paket apa pun. Pendekatan ini mengharuskan Anda memilih host eksternal tertentu. Seringkali, IP publik terkenal harus melakukan triknya. Saya suka alamat server DNS publik Google 8.8.8.8 untuk tujuan ini, tetapi mungkin ada kalanya Anda ingin memilih IP host eksternal yang berbeda. Berikut adalah beberapa kode yang menggambarkan pendekatan lengkap.
sumber
Seperti yang Anda ketahui, tidak ada yang namanya "alamat IP lokal". Berikut cara mengetahui alamat lokal yang dapat dikirim ke host tertentu.
sumber
Ini memiliki keuntungan karena bekerja pada banyak jenis unix ... dan Anda dapat memodifikasinya dengan mudah untuk bekerja pada o / s apa pun. Semua solusi di atas memberi saya kesalahan kompiler tergantung pada fase bulan. Saat ada cara POSIX yang baik untuk melakukannya ... jangan gunakan ini (pada saat ini ditulis, bukan itu masalahnya).
sumber
ifconfig
. Anda harus menggunakanip
sekarang. Cara yang tepat untuk menghasilkan keluaran netral bahasa adalah dengan menyetelLANG
variabel lingkungan keC
, seperti:LANG=C ls -l
Saya rasa tidak ada jawaban pasti yang benar untuk pertanyaan Anda. Sebaliknya, ada banyak cara untuk mendekati apa yang Anda inginkan. Karenanya saya akan memberikan beberapa petunjuk bagaimana menyelesaikannya.
Jika mesin memiliki lebih dari 2 antarmuka (
lo
dihitung sebagai satu) Anda akan mengalami masalah untuk mendeteksi otomatis antarmuka yang benar dengan mudah. Berikut beberapa resep tentang cara melakukannya.Masalahnya, misalnya, adalah jika host berada dalam DMZ di belakang firewall NAT yang mengubah IP publik menjadi beberapa IP pribadi dan meneruskan permintaan. Mesin Anda mungkin memiliki 10 antarmuka, tetapi hanya satu yang sesuai dengan antarmuka publik.
Bahkan deteksi otomatis tidak berfungsi jika Anda menggunakan NAT ganda, di mana firewall Anda bahkan menerjemahkan IP sumber menjadi sesuatu yang sama sekali berbeda. Jadi Anda bahkan tidak dapat memastikan, bahwa rute default mengarah ke antarmuka Anda dengan antarmuka publik.
Mendeteksi melalui rute default
Sesuatu seperti
ip r get 1.1.1.1
biasanya memberi tahu Anda antarmuka yang memiliki rute default.Jika Anda ingin membuat ulang ini dalam bahasa skrip / pemrograman favorit Anda, gunakan
strace ip r get 1.1.1.1
dan ikuti jalan bata kuning.Setel dengan
/etc/hosts
Anda dapat membuat entri di
/etc/hosts
likeKemudian Anda dapat menggunakan alias ini
publicinterfaceip
untuk merujuk ke antarmuka publik Anda.Gunakan lingkungan
Sama seperti
/etc/hosts
. tetapi gunakan lingkungan untuk ini. Anda dapat mencoba/etc/profile
atau~/.profile
untuk ini.Karenanya, jika program Anda membutuhkan variabel
MYPUBLICIP
maka Anda dapat memasukkan kode seperti (ini adalah C, silakan buat C ++ darinya):Jadi Anda bisa memanggil script / program Anda
/path/to/your/script
seperti iniMYPUBLICIP=80.190.1.3 /path/to/your/script
ini bahkan berhasil
crontab
.Hitung semua antarmuka dan hilangkan yang tidak Anda inginkan
Jika Anda tahu apa yang tidak Anda inginkan, Anda dapat menghitung semua antarmuka dan mengabaikan semua yang salah.
Di sini sepertinya sudah menjadi jawaban https://stackoverflow.com/a/265978/490291 untuk pendekatan ini.
Lakukan seperti DLNA
Anda dapat mencoba menghitung semua gerbang UPnP di jaringan Anda dan dengan cara ini menemukan rute yang tepat untuk beberapa hal "eksternal". Ini bahkan mungkin pada rute di mana rute default Anda tidak menunjuk.
Untuk lebih lanjut tentang ini mungkin lihat https://en.wikipedia.org/wiki/Internet_Gateway_Device_Protocol
Ini memberi Anda kesan yang baik mana yang merupakan antarmuka publik Anda yang sebenarnya, meskipun rute default Anda mengarah ke tempat lain.
Ada lebih banyak lagi
Router IPv6 mengiklankan dirinya sendiri untuk memberi Anda awalan IPv6 yang benar. Melihat awalan memberi Anda petunjuk tentang apakah itu memiliki beberapa IP internal atau global.
Anda dapat mendengarkan frame IGMP atau IBGP untuk mengetahui beberapa gateway yang sesuai.
Ada kurang dari 2 ^ 32 alamat IP. Oleh karena itu, tidak butuh waktu lama di LAN untuk melakukan ping ke semuanya. Ini memberi Anda petunjuk statistik tentang di mana sebagian besar Internet berada dari sudut pandang Anda. Namun Anda harus sedikit lebih bijaksana daripada https://de.wikipedia.org/wiki/SQL_Slammer yang terkenal
ICMP dan bahkan ARP adalah sumber yang baik untuk informasi sideband jaringan. Ini mungkin membantu Anda juga.
Anda dapat menggunakan alamat Ethernet Broadcast untuk menghubungi semua perangkat infrastruktur jaringan Anda yang sering kali akan membantu, seperti DHCP (bahkan DHCPv6) dan sebagainya.
Daftar tambahan ini mungkin tidak ada habisnya dan selalu tidak lengkap, karena setiap produsen perangkat jaringan sibuk menciptakan lubang keamanan baru tentang cara mendeteksi perangkat mereka sendiri secara otomatis. Yang sering membantu banyak tentang cara mendeteksi beberapa antarmuka publik di mana tidak boleh ada satu pun.
'Kata Nuff. Di luar.
sumber
Lebih jauh dari apa yang dikatakan Steve Baker, Anda dapat menemukan deskripsi ioctl SIOCGIFCONF di halaman manual netdevice (7) .
Setelah Anda memiliki daftar semua alamat IP pada host, Anda harus menggunakan logika khusus aplikasi untuk menyaring alamat yang tidak Anda inginkan dan berharap Anda memiliki satu alamat IP yang tersisa.
sumber
Jangan sulit membuat kode: ini adalah hal yang bisa berubah. Banyak program mencari tahu apa yang harus diikat dengan membaca di file konfigurasi, dan melakukan apa pun yang tertulis. Dengan cara ini, jika program Anda suatu saat nanti perlu terikat ke sesuatu yang bukan IP publik, program tersebut dapat melakukannya.
sumber
Karena pertanyaan tersebut menentukan Linux, teknik favorit saya untuk menemukan alamat IP mesin adalah menggunakan netlink. Dengan membuat soket netlink dari protokol NETLINK_ROUTE, dan mengirimkan RTM_GETADDR, aplikasi Anda akan menerima pesan yang berisi semua alamat IP yang tersedia. Contoh disediakan di sini .
Untuk bagian sederhana dari penanganan pesan, libmnl nyaman. Jika Anda penasaran dalam mencari tahu lebih banyak tentang berbagai opsi NETLINK_ROUTE (dan bagaimana mereka diurai), sumber terbaik adalah kode sumber iproute2 (terutama aplikasi monitor) serta fungsi terima di kernel. Halaman manual rtnetlink juga berisi informasi yang berguna.
sumber
Anda dapat melakukan beberapa integrasi dengan curl semudah:
curl www.whatismyip.org
dari shell akan memberi Anda ip global Anda. Anda agak bergantung pada beberapa server eksternal, tetapi Anda akan selalu berada di belakang NAT.sumber
Solusi skrip elegan untuk Linux dapat ditemukan di: http://www.damnsmalllinux.org/f/topic-3-23-17031-0.html
sumber
// Use a HTTP request to a well known server that echo's back the public IP address void GetPublicIP(CString & csIP) { // Initialize COM bool bInit = false; if (SUCCEEDED(CoInitialize(NULL))) { // COM was initialized bInit = true;
}
sumber