Esta pregunta es casi la misma que la pregunta anterior Obtener la dirección IP de la computadora local . Sin embargo, necesito encontrar la (s) dirección (es) IP de una máquina Linux .
Entonces: ¿Cómo puedo, programáticamente en C ++ , detectar las direcciones IP del servidor Linux en el que se está ejecutando mi aplicación? Los servidores tendrán al menos dos direcciones IP y necesito una específica (la de una red determinada (la pública)).
Estoy seguro de que hay una función simple para hacer eso, pero ¿dónde?
Para aclarar un poco las cosas:
- El servidor obviamente tendrá el "localhost": 127.0.0.1
- El servidor tendrá una dirección IP interna (de gestión): 172.16.xx
- El servidor tendrá una dirección IP externa (pública): 80.190.xx
Necesito encontrar la dirección IP externa para vincular mi aplicación a ella. Obviamente, también puedo vincularme a INADDR_ANY (y en realidad eso es lo que hago en este momento). Sin embargo, preferiría detectar la dirección pública.
fuente
ifconfig
,route
etc están en desuso para elip
comando. Ahora deberías usar eso en su lugar.Respuestas:
Encontré la solución ioctl problemática en os x (que es compatible con POSIX, por lo que debería ser similar a linux). Sin embargo, getifaddress () le permitirá hacer lo mismo fácilmente, funciona bien para mí en os x 10.5 y debería ser el mismo a continuación.
He hecho un ejemplo rápido a continuación que imprimirá todas las direcciones IPv4 de la máquina (también debe verificar que getifaddrs fue exitoso, es decir, devuelve 0).
Lo actualicé para mostrar direcciones IPv6 también.
fuente
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
lo
ewlan0
interfaces en mi caso. Lo que necesito eswlan0
oeth0
que tenga conexión a Internet. Entonces, ¿debo usarstrcmp
o hay una mejor manera?ioctl(<socketfd>, SIOCGIFCONF, (struct ifconf)&buffer);
Lea
/usr/include/linux/if.h
para obtener información sobre las estructurasifconf
yifreq
. Esto debería darle la dirección IP de cada interfaz en el sistema. Lea también/usr/include/linux/sockios.h
para ioctls adicionales.fuente
Me gusta la respuesta de jjvainio . Como dice Zan Lnyx, usa la tabla de enrutamiento local para encontrar la dirección IP de la interfaz Ethernet que se usaría para una conexión a un host externo específico. Al utilizar un conector UDP conectado, puede obtener la información sin enviar ningún paquete. El enfoque requiere que elija un host externo específico. La mayoría de las veces, cualquier IP pública conocida debería ser suficiente. Me gusta la dirección 8.8.8.8 del servidor DNS público de Google para este propósito, pero puede haber ocasiones en las que desee elegir una IP de host externa diferente. Aquí hay un código que ilustra el enfoque completo.
fuente
Como ha descubierto, no existe una única "dirección IP local". A continuación, le indicamos cómo averiguar la dirección local que se puede enviar a un host específico.
fuente
Esto tiene la ventaja de trabajar en muchas versiones de Unix ... y puedes modificarlo trivialmente para que funcione en cualquier sistema operativo. Todas las soluciones anteriores me dan errores de compilación según la fase de la luna. En el momento en que haya una buena forma POSIX de hacerlo ... no use esto (en el momento en que se escribió esto, ese no era el caso).
fuente
ifconfig
. Deberías usarip
ahora. La forma correcta de generar una salida de lenguaje neutral es establecerLANG
la variable de entorno enC
, como:LANG=C ls -l
No creo que haya una respuesta correcta definitiva a su pregunta. En cambio, hay un gran conjunto de formas de acercarse a lo que desea. Por lo tanto, proporcionaré algunos consejos sobre cómo hacerlo.
Si una máquina tiene más de 2 interfaces (
lo
cuenta como una), tendrá problemas para detectar automáticamente la interfaz correcta fácilmente. Aquí hay algunas recetas sobre cómo hacerlo.El problema, por ejemplo, es si los hosts están en una DMZ detrás de un firewall NAT que cambia la IP pública a alguna IP privada y reenvía las solicitudes. Su máquina puede tener 10 interfaces, pero solo una corresponde a la pública.
Incluso la autodetección no funciona en caso de que esté en doble NAT, donde su firewall incluso traduce la IP de origen en algo completamente diferente. Por lo tanto, ni siquiera puede estar seguro de que la ruta predeterminada conduce a su interfaz con una interfaz pública.
Detectarlo por la ruta predeterminada
Algo como
ip r get 1.1.1.1
normalmente te dice la interfaz que tiene la ruta predeterminada.Si desea recrear esto en su lenguaje de programación / scripts favorito, use
strace ip r get 1.1.1.1
y siga el camino de ladrillos amarillos.Configurarlo con
/etc/hosts
Puedes crear una entrada
/etc/hosts
comoEntonces puede usar este alias
publicinterfaceip
para referirse a su interfaz pública.Usa el medio ambiente
Igual que
/etc/hosts
. pero usa el entorno para esto. Puedes probar/etc/profile
o~/.profile
para esto.Por lo tanto, si su programa necesita una variable
MYPUBLICIP
, puede incluir código como (esto es C, no dude en crear C ++ a partir de él):Entonces puedes llamar a tu script / programa
/path/to/your/script
asíMYPUBLICIP=80.190.1.3 /path/to/your/script
esto incluso funciona en
crontab
.Enumere todas las interfaces y elimine las que no desee
Si sabe lo que no desea, puede enumerar todas las interfaces e ignorar todas las falsas.
Aquí ya parece haber una respuesta https://stackoverflow.com/a/265978/490291 para este enfoque.
Hazlo como DLNA
Puede intentar enumerar todas las puertas de enlace UPnP en su red y de esta manera encontrar una ruta adecuada para alguna cosa "externa". Esto incluso podría estar en una ruta donde su ruta predeterminada no apunta.
Para obtener más información sobre esto, quizás consulte https://en.wikipedia.org/wiki/Internet_Gateway_Device_Protocol
Esto le da una buena impresión de cuál es su interfaz pública real, incluso si su ruta predeterminada apunta a otro lugar.
Hay aun mas
Los enrutadores IPv6 se anuncian a sí mismos para ofrecerle el prefijo IPv6 correcto. Mirar el prefijo le da una pista sobre si tiene alguna IP interna o global.
Puede escuchar tramas IGMP o IBGP para encontrar una puerta de enlace adecuada.
Hay menos de 2 ^ 32 direcciones IP. Por lo tanto, no se necesita mucho tiempo en una LAN para hacer ping a todos. Esto le da una pista estadística sobre dónde se encuentra la mayoría de Internet desde su punto de vista. Sin embargo, debería ser un poco más sensato que el famoso https://de.wikipedia.org/wiki/SQL_Slammer
ICMP e incluso ARP son buenas fuentes de información de banda lateral de la red. También podría ayudarte.
Puede usar la dirección de transmisión Ethernet para comunicarse con todos los dispositivos de su infraestructura de red, lo que a menudo le ayudará, como DHCP (incluso DHCPv6), etc.
Esta lista adicional probablemente sea interminable y siempre incompleta, porque todos los fabricantes de dispositivos de red están inventando afanosamente nuevos agujeros de seguridad sobre cómo detectar automáticamente sus propios dispositivos. Lo que a menudo ayuda mucho sobre cómo detectar alguna interfaz pública donde no debería haber una.
'Nuff dijo. Fuera.
fuente
Además de lo que ha dicho Steve Baker, puede encontrar una descripción del ioctl SIOCGIFCONF en la página de manual de netdevice (7) .
Una vez que tenga la lista de todas las direcciones IP en el host, tendrá que usar la lógica específica de la aplicación para filtrar las direcciones que no desea y esperar que le quede una dirección IP.
fuente
No lo codifique: este es el tipo de cosas que pueden cambiar. Muchos programas descubren a qué vincularse leyendo un archivo de configuración y haciendo lo que sea que indique. De esta forma, si su programa en el futuro necesita vincularse a algo que no es una IP pública, puede hacerlo.
fuente
Como la pregunta especifica Linux, mi técnica favorita para descubrir las direcciones IP de una máquina es usar netlink. Al crear un conector de enlace de red del protocolo NETLINK_ROUTE y enviar un RTM_GETADDR, su aplicación recibirá un mensaje que contiene todas las direcciones IP disponibles. Aquí se proporciona un ejemplo .
Para simplemente partes del manejo de mensajes, libmnl es conveniente. Si tiene curiosidad por averiguar más sobre las diferentes opciones de NETLINK_ROUTE (y cómo se analizan), la mejor fuente es el código fuente de iproute2 (especialmente la aplicación de monitorización), así como las funciones de recepción en el kernel. La página de manual de rtnetlink también contiene información útil.
fuente
Puede hacer algo de integración con curl como algo tan fácil como:
curl www.whatismyip.org
desde el shell obtendrá su ip global. Depende de algún servidor externo, pero siempre lo será si está detrás de un NAT.fuente
Se puede encontrar una elegante solución con script para Linux en: http://www.damnsmalllinux.org/f/topic-3-23-17031-0.html
fuente
// 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;
}
fuente