Esta pergunta é quase igual à anterior Obtenha o endereço IP do computador local - pergunta. No entanto, preciso encontrar o (s) endereço (s) IP de uma máquina Linux .
Então: Como faço para - programaticamente em C ++ - detectar os endereços IP do servidor Linux em que meu aplicativo está sendo executado. Os servidores terão pelo menos dois endereços IP e eu preciso de um específico (o de uma determinada rede (a pública)).
Tenho certeza de que existe uma função simples para fazer isso - mas onde?
Para tornar as coisas um pouco mais claras:
- O servidor obviamente terá o "localhost": 127.0.0.1
- O servidor terá um endereço IP interno (gerenciamento): 172.16.xx
- O servidor terá um endereço IP externo (público): 80.190.xx
Preciso encontrar o endereço IP externo para vincular meu aplicativo a ele. Obviamente, também posso vincular a INADDR_ANY (e na verdade é o que faço no momento). Eu preferiria detectar o endereço público, no entanto.
fonte
ifconfig
,route
etc são preteridos para oip
comando. Agora você deve usar isso.Respostas:
Achei a solução ioctl problemática no os x (que é compatível com POSIX, então deve ser semelhante ao Linux). No entanto getifaddress () permitirá que você faça a mesma coisa facilmente, ele funciona bem para mim no OS x 10.5 e deve ser o mesmo abaixo.
Fiz um exemplo rápido abaixo que imprimirá todos os endereços IPv4 da máquina (você também deve verificar se getifaddrs foi bem-sucedido, ou seja, retorna 0).
Eu o atualizei para mostrar os endereços IPv6 também.
fonte
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
lo
ewlan0
interfaces no meu caso. O que eu exijowlan0
oueth0
tem conexão com a internet. Então, devo usarstrcmp
ou há uma maneira melhor?ioctl(<socketfd>, SIOCGIFCONF, (struct ifconf)&buffer);
Leia
/usr/include/linux/if.h
para obter informações sobre as estruturasifconf
eifreq
. Isso deve fornecer o endereço IP de cada interface no sistema. Leia também/usr/include/linux/sockios.h
para ioctls adicionais.fonte
Gosto da resposta de jjvainio . Como Zan Lnyx diz, ele usa a tabela de roteamento local para encontrar o endereço IP da interface ethernet que seria usada para uma conexão a um host externo específico. Usando um soquete UDP conectado, você pode obter as informações sem realmente enviar nenhum pacote. A abordagem requer que você escolha um host externo específico. Na maioria das vezes, qualquer IP público conhecido deve resolver o problema. Eu gosto do endereço de servidor DNS público 8.8.8.8 do Google para essa finalidade, mas pode haver momentos em que você queira escolher um IP de host externo diferente. Aqui está um código que ilustra a abordagem completa.
fonte
Como você descobriu, não existe um único "endereço IP local". Veja como descobrir o endereço local que pode ser enviado a um host específico.
fonte
Isso tem a vantagem de funcionar em muitos sabores de unix ... e você pode modificá-lo trivialmente para funcionar em qualquer o / s. Todas as soluções acima geram erros de compilador dependendo da fase da lua. No momento em que houver uma boa maneira POSIX de fazer isso ... não use isso (na época em que isso foi escrito, não era o caso).
fonte
ifconfig
. Você deve usarip
agora. A maneira adequada de gerar uma saída de linguagem neutra é definirLANG
a variável de ambienteC
como:LANG=C ls -l
Eu não acho que haja uma resposta certa definitiva para sua pergunta. Em vez disso, há uma grande variedade de maneiras de chegar perto do que você deseja. Portanto, irei fornecer algumas dicas de como fazer isso.
Se uma máquina tiver mais de 2 interfaces (
lo
conta como uma), você terá problemas para detectar automaticamente a interface certa com facilidade. Aqui estão algumas receitas de como fazer isso.O problema, por exemplo, é se os hosts estão em uma DMZ atrás de um firewall NAT que muda o IP público para algum IP privado e encaminha as solicitações. Sua máquina pode ter 10 interfaces, mas apenas uma corresponde à pública.
Mesmo a autodetecção não funciona no caso de você estar em duplo-NAT, onde seu firewall até mesmo traduz o IP de origem em algo completamente diferente. Portanto, você não pode ter certeza de que a rota padrão leva à sua interface com uma interface pública.
Detecte-o pela rota padrão
Algo como
ip r get 1.1.1.1
geralmente informa a interface que tem a rota padrão.Se você quiser recriar isso em sua linguagem de script / programação favorita, use
strace ip r get 1.1.1.1
e siga o caminho dos tijolos amarelos.Definir com
/etc/hosts
Você pode criar uma entrada
/etc/hosts
comoEntão você pode usar este alias
publicinterfaceip
para se referir à sua interface pública.Use o ambiente
O mesmo que
/etc/hosts
. mas use o ambiente para isso. Você pode tentar/etc/profile
ou~/.profile
por isso.Portanto, se seu programa precisa de uma variável
MYPUBLICIP
, você pode incluir código como (este é C, fique à vontade para criar C ++ a partir dele):Então você pode chamar seu script / programa
/path/to/your/script
assimMYPUBLICIP=80.190.1.3 /path/to/your/script
isso até funciona em
crontab
.Enumere todas as interfaces e elimine aquelas que você não deseja
Se você sabe o que não quer, pode enumerar todas as interfaces e ignorar todas as falsas.
Aqui já parece haver uma resposta https://stackoverflow.com/a/265978/490291 para essa abordagem.
Faça como DLNA
Você pode tentar enumerar todos os gateways UPnP em sua rede e, dessa forma, descobrir uma rota adequada para alguma coisa "externa". Isso pode até ser em uma rota para a qual sua rota padrão não aponta.
Para mais informações, talvez consulte https://en.wikipedia.org/wiki/Internet_Gateway_Device_Protocol
Isso dá a você uma boa impressão de qual é a sua interface pública real, mesmo se sua rota padrão apontar para outro lugar.
Tem ainda mais
Os roteadores IPv6 se anunciam para fornecer o prefixo IPv6 correto. Olhar para o prefixo dá uma dica sobre se ele tem algum IP interno ou global.
Você pode escutar os quadros IGMP ou IBGP para descobrir algum gateway adequado.
Existem menos de 2 ^ 32 endereços IP. Conseqüentemente, em uma LAN não demora muito para fazer ping em todos eles. Isso lhe dá uma dica estatística sobre onde a maior parte da Internet está localizada do seu ponto de vista. No entanto, você deve ser um pouco mais sensato do que o famoso https://de.wikipedia.org/wiki/SQL_Slammer
ICMP e até ARP são boas fontes de informações de banda lateral de rede. Também pode te ajudar.
Você pode usar o endereço de Broadcast Ethernet para entrar em contato com todos os seus dispositivos de infraestrutura de rede, o que geralmente ajudará, como DHCP (mesmo DHCPv6) e assim por diante.
Essa lista adicional é provavelmente interminável e sempre incompleta, porque todos os fabricantes de dispositivos de rede estão ocupados inventando novas brechas de segurança para detectar automaticamente seus próprios dispositivos. O que geralmente ajuda muito a detectar alguma interface pública onde não deveria haver uma.
'Nuff disse. Fora.
fonte
Além do que Steve Baker disse, você pode encontrar uma descrição do SIOCGIFCONF ioctl na página do manual netdevice (7) .
Depois de ter a lista de todos os endereços IP no host, você terá que usar a lógica específica do aplicativo para filtrar os endereços que não deseja e esperar que ainda tenha um endereço IP.
fonte
Não fixe o código: esse é o tipo de coisa que pode mudar. Muitos programas descobrem o que vincular lendo um arquivo de configuração e fazendo o que quer que ele diga. Dessa forma, se no futuro seu programa precisar se vincular a algo que não seja um IP público, ele poderá fazer isso.
fonte
Como a pergunta especifica o Linux, minha técnica favorita para descobrir os endereços IP de uma máquina é usar o netlink. Ao criar um soquete netlink do protocolo NETLINK_ROUTE e enviar um RTM_GETADDR, seu aplicativo receberá mensagem (ns) contendo todos os endereços IP disponíveis. Um exemplo é fornecido aqui .
Para simplificar partes do tratamento da mensagem, libmnl é conveniente. Se você está curioso em saber mais sobre as diferentes opções do NETLINK_ROUTE (e como são analisadas), a melhor fonte é o código-fonte do iproute2 (especialmente o aplicativo do monitor), bem como as funções de recepção no kernel. A página de manual do rtnetlink também contém informações úteis.
fonte
Você pode fazer alguma integração com curl tão fácil como:
curl www.whatismyip.org
do shell você obterá seu ip global. Você meio que depende de algum servidor externo, mas sempre dependerá se estiver atrás de um NAT.fonte
Uma solução elegante com script para Linux pode ser encontrada em: http://www.damnsmalllinux.org/f/topic-3-23-17031-0.html
fonte
// 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;
}
fonte