Obtener la dirección IP 'externa' en Java

83

No estoy muy seguro de cómo obtener la dirección IP externa de la máquina como la vería una computadora fuera de una red.

Mi siguiente clase IPAddress solo obtiene la dirección IP local de la máquina.

public class IPAddress {

    private InetAddress thisIp;

    private String thisIpAddress;

    private void setIpAdd() {
        try {
            InetAddress thisIp = InetAddress.getLocalHost();
            thisIpAddress = thisIp.getHostAddress().toString();
        } catch (Exception e) {
        }
    }

    protected String getIpAddress() {
        setIpAdd();
        return thisIpAddress;
    }
}
Julio
fuente
13
¿Sabe que una máquina puede tener varias direcciones públicas a la vez? Realmente están asociados con una interfaz de red, no con una máquina.
Donal Fellows

Respuestas:

168

No estoy seguro de si puede obtener esa IP del código que se ejecuta en la máquina local.

Sin embargo, puede crear código que se ejecute en un sitio web, digamos en JSP, y luego usar algo que devuelva la IP de donde vino la solicitud:

request.getRemoteAddr()

O simplemente use los servicios ya existentes que hacen esto, luego analice la respuesta del servicio para averiguar la IP.

Utilice un servicio web como AWS y otros

import java.net.*;
import java.io.*;

URL whatismyip = new URL("http://checkip.amazonaws.com");
BufferedReader in = new BufferedReader(new InputStreamReader(
                whatismyip.openStream()));

String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
bakkal
fuente
4
Advertencia: han ajustado la URL de automatización
thegrinner
8
Sugeriría implementar al menos dos servidores que sirvan a su ip, en caso de que uno de ellos esté inactivo en este momento (con un manejo correcto de errores, por supuesto). Mi elección sería externalip.net (haga clic en el enlace "¿Necesita una API?"). He estado usando ese sitio durante más de un año, no he tenido ningún problema hasta ahora y es un servicio rápido que siempre devuelve una respuesta rápida.
Enlace impresionante; ¡Usaré esto como parte de una prueba de concepto en una asignación de redes universitarias!
Araisbec
Otra alternativa sería si tiene acceso a un servidor web o cuenta de host que ejecuta PHP, simplemente use el código @bakkal proporcionado anteriormente y apúntelo a su propio archivo PHP que simplemente contiene echo $_SERVER['REMOTE_ADDR'];. Si esta es la única o la primera línea de salida del script, ya está todo listo.
Kingsolmn
7
Whatsmyip.com parece que ya no admite este tipo de automatización.
Kingsolmn
79

Uno de los comentarios de @stivlo merece ser una respuesta:

Puede utilizar el servicio de Amazon http://checkip.amazonaws.com

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

public class IpChecker {

    public static String getIp() throws Exception {
        URL whatismyip = new URL("http://checkip.amazonaws.com");
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
                    whatismyip.openStream()));
            String ip = in.readLine();
            return ip;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Será
fuente
19

La verdad es: 'no puedes' en el sentido en que hiciste la pregunta. NAT ocurre fuera del protocolo. No hay forma de que el kernel de su máquina sepa cómo su caja NAT está mapeando desde direcciones IP externas a internas. Otras respuestas aquí ofrecen trucos que involucran métodos para hablar con sitios web externos.

bmargulies
fuente
3
O no, ya que no responde a la pregunta original, y parece un ejercicio académico
Bruno Bossola
Para ser justos, esta respuesta responde a la pregunta y la otra docena de respuestas básicamente dicen lo mismo pero muestran el código o las URL específicas de cualquier opción de verificador de IP externo.
Thomas Carlisle
14

¡Todo esto sigue funcionando sin problemas! (a 23 de septiembre de 2019)

Un consejo: no dependa directamente de uno solo de ellos; ¡Intente usar uno pero tenga un plan de contingencia considerando otros! ¡Cuanto más uses, mejor!

¡Buena suerte!

FranciscoBouza
fuente
12

Como escribió @Donal Fellows, debe consultar la interfaz de red en lugar de la máquina. Este código de los javadocs funcionó para mí:

El siguiente programa de ejemplo enumera todas las interfaces de red y sus direcciones en una máquina:

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNets {

    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
        out.printf("\n");
     }
} 

Lo siguiente es un resultado de muestra del programa de ejemplo:

Display name: TCP Loopback interface
Name: lo
InetAddress: /127.0.0.1

Display name: Wireless Network Connection
Name: eth0
InetAddress: /192.0.2.0

De docs.oracle.com

domih
fuente
1
¡Gracias! Si bien esta solución no funcionará cuando el software esté detrás de un NAT, sigue siendo muy útil para el software de servidor que sabe que no estará detrás de un NAT, o como alternativa si el software no puede conectarse a otro servidor para obtener el suyo. IP. En particular, para el software destinado a ejecutarse en LAN desconectadas de Internet, es el camino a seguir.
Pabellón
6

Haga una HttpURLConnection a algún sitio como www.whatismyip.com y analice eso :-)

nc3b
fuente
5

¿Qué tal esto? Es simple y funcionó mejor para mí :)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;


public class IP {
    public static void main(String args[]) {
        new IP();
    }

    public IP() {
        URL ipAdress;

        try {
            ipAdress = new URL("http://myexternalip.com/raw");

            BufferedReader in = new BufferedReader(new InputStreamReader(ipAdress.openStream()));

            String ip = in.readLine();
            System.out.println(ip);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Sparkoenig
fuente
¡Esto es excelente! Lo intentaré cuando llegue a casa. Este es exactamente el tipo de resolución de problemas que estaba buscando. No sé por qué no se ha votado más alto.
Adam893
4

http://jstun.javawi.de/ lo hará, siempre que su dispositivo de puerta de enlace aturda)

user461467
fuente
1
Muy interesante, funciona como se esperaba sin el uso de servicios externos sino simplemente hablando con la puerta de enlace. Sin embargo, la licencia GPL probablemente limitará su adopción.
Bruno Bossola
El sitio me está dando una pantalla de inicio de sesión. Probablemente no sea el original.
Jus12
1

No es tan fácil ya que una máquina dentro de una LAN generalmente no se preocupa por la IP externa de su enrutador a Internet ... ¡simplemente no la necesita!

Le sugiero que aproveche esto abriendo un sitio como http://www.whatismyip.com/ y obteniendo el número de IP analizando los resultados html ... ¡no debería ser tan difícil!

Jack
fuente
2
No es necesario analizar html. La primera línea de la fuente de la página web de whatismyip.com es su IP externa.
Martijn Courteaux
0

Si está utilizando una aplicación web basada en JAVA y desea obtener la IP externa del cliente (Uno que realiza la solicitud a través de un navegador), intente implementar la aplicación en un dominio público y use request.getRemoteAddr () para leer la dirección IP externa.

Arrendajo
fuente
0
System.out.println(pageCrawling.getHtmlFromURL("http://ipecho.net/plain"));
Mohsen Abasi
fuente
0

Una solución alternativa es ejecutar un comando externo, obviamente, esta solución limita la portabilidad de la aplicación.

Por ejemplo, para una aplicación que se ejecuta en Windows, se puede ejecutar un comando de PowerShell a través de jPowershell, como se muestra en el siguiente código:

public String getMyPublicIp() {
    // PowerShell command
    String command = "(Invoke-WebRequest ifconfig.me/ip).Content.Trim()";
    String powerShellOut = PowerShell.executeSingleCommand(command).getCommandOutput();

    // Connection failed
    if (powerShellOut.contains("InvalidOperation")) {
        powerShellOut = null;
    }
    return powerShellOut;
}
Carlos Alma
fuente