it-swarm-es.tech

Obtenga una dirección IP externa a través de la comunicación remota en C #

Necesito averiguar el externo IP de la computadora en la que se ejecuta una aplicación C #.

En la aplicación tengo una conexión (a través de .NET remoting) a un servidor. ¿Hay una buena manera de obtener la dirección del cliente en el lado del servidor?

(He editado la pregunta, para ser un poco más claro. Pido disculpas a todas las personas amables que hicieron todo lo posible para responder a la pregunta, cuando tal vez era un poco vago)

Solución:
Encontré una manera que funcionó muy bien para mí. Al implementar un IServerChannelSinkProvider personalizado e IServerChannelSink donde tengo acceso a CommonTransportKeys.IPAddress, es fácil agregar la IP del cliente en CallContext.

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, 
    iMessage requestmessage, ITransportHeaders requestHeaders, 
    System.IO.Stream requestStream, out iMessage responseMessage, 
    out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
    try
    {
        // Get the IP address and add it to the call context.
        IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
        CallContext.SetData("ClientIP", ipAddr);
    }
    catch (Exception)
    {
    }

    sinkStack.Push(this, null);
    ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
        requestStream, out responseMessage, out responseHeaders, out responseStream);

    return srvProc;
}

Y luego (cuando recibo una solicitud de un cliente) simplemente obtengo la IP del CallContext de esta manera.

public string GetClientIP()
{
    // Get the client IP from the call context.
    object data = CallContext.GetData("ClientIP");

    // If the data is null or not a string, then return an empty string.
    if (data == null || !(data is IPAddress))
        return string.Empty;

    // Return the data as a string.
    return ((IPAddress)data).ToString();
}

Ahora puedo enviar la IP al cliente.

20
Patrik Svensson

Encontré una manera que funcionó muy bien para mí. Al implementar un IServerChannelSinkProvider personalizado e IServerChannelSink donde tengo acceso a CommonTransportKeys.IPAddress, es fácil agregar la IP del cliente en CallContext.

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, 
    iMessage requestmessage, ITransportHeaders requestHeaders, 
    System.IO.Stream requestStream, out iMessage responseMessage, 
    out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
    try
    {
        // Get the IP address and add it to the call context.
        IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
        CallContext.SetData("ClientIP", ipAddr);
    }
    catch (Exception)
    {
    }

    sinkStack.Push(this, null);
    ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
        requestStream, out responseMessage, out responseHeaders, out responseStream);

    return srvProc;
}

Y luego (cuando recibo una solicitud de un cliente) simplemente obtengo la IP del CallContext de esta manera.

public string GetClientIP()
{
    // Get the client IP from the call context.
    object data = CallContext.GetData("ClientIP");

    // If the data is null or not a string, then return an empty string.
    if (data == null || !(data is IPAddress))
        return string.Empty;

    // Return the data as a string.
    return ((IPAddress)data).ToString();
}

Ahora puedo enviar la IP al cliente.

5
Patrik Svensson

Esta es una de esas preguntas en las que debe profundizar y quizás repensar el problema original; en este caso, "¿Por qué necesita una dirección IP externa?"

El problema es que la computadora puede no tener una dirección IP externa. Por ejemplo, mi computadora portátil tiene una dirección IP interna (192.168.x.y) asignada por el enrutador. El enrutador tiene una dirección IP interna, pero su dirección IP "externa" también es interna. Solo se usa para comunicarse con el módem DSL, que en realidad tiene una dirección IP externa con conexión a Internet.

Entonces, la verdadera pregunta es: "¿Cómo obtengo la dirección IP de un dispositivo a 2 saltos de Internet?" Y la respuesta es generalmente, no lo haces; al menos no sin usar un servicio como whatismyip.com que ya ha descartado, o haciendo un hack realmente masivo que implica codificar la contraseña del módem DSL en su aplicación y consultar el módem DSL y raspar la página de administración (y Dios lo ayude si alguna vez se reemplaza el módem).

EDITAR: Ahora para aplicar esto a la pregunta refactorizada, "¿Cómo obtengo la dirección IP de mi cliente desde un componente de servidor .NET?" Al igual que whatismyip.com, lo mejor que el servidor podrá hacer es proporcionarle la dirección IP de su dispositivo con conexión a Internet, que es poco probable que sea la dirección IP real de la computadora que ejecuta la aplicación. Volviendo a mi computadora portátil, si mi IP con conexión a Internet era 75.75.75.75 y la IP de LAN era 192.168.0.112, el servidor solo podría ver la dirección IP 75.75.75.75. Eso lo llevará hasta mi módem DSL. Si su servidor quisiera hacer una conexión por separado a mi computadora portátil, primero necesitaría configurar el módem DSL y cualquier enrutador entre este y mi computadora portátil para reconocer las conexiones entrantes de su servidor y enrutarlas adecuadamente. Hay algunas formas de hacer esto, pero está fuera del alcance de este tema.

Si de hecho está intentando hacer una conexión desde el servidor de regreso al cliente, reconsidere su diseño porque está profundizando en el territorio WTF (o al menos, haciendo que su aplicación sea mucho más difícil de implementar).

19
Nathan Strong

Dns.GetHostEntry (Dns.GetHostName ()); devolverá una matriz de direcciones IP. La primera debe ser la IP externa, el resto serán las que están detrás de NAT.

Entonces:

IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
string externalIP = IPHost.AddressList[0].ToString();

EDITAR:

Hay informes de que esto no funciona para algunas personas. Lo hace para mí, pero tal vez dependiendo de la configuración de su red, puede que no funcione.

6
FlySwat

Es mejor usar http://www.whatismyip.com/automation/n09230945.asp solo genera la IP solo para las búsquedas automáticas.

Si desea algo que no dependa de otra persona, coloque su propia página http://www.unkwndesign.com/ip.php es solo un script rápido:

<?php
echo 'Your Public IP is: ' . $_SERVER['REMOTE_ADDR'];
?>

El único inconveniente aquí es que solo recuperará la IP externa de la interfaz que se utilizó para crear la solicitud.

5
UnkwnTech

La respuesta de Jonathan Holland es fundamentalmente correcta, pero vale la pena agregar que las llamadas a la API detrás de Dns.GetHostByName consumen bastante tiempo y es una buena idea almacenar en caché los resultados para que el código solo se llame una vez.

4
Yes - that Jake.

El problema principal es que la dirección IP pública no está necesariamente correlacionada con la computadora local que ejecuta la aplicación. Se traduce desde la red interna a través del firewall. Para obtener realmente la IP pública sin interrogar a la red local es hacer una solicitud a una página de Internet y devolver el resultado. Si no desea utilizar un sitio de tipo WhatIsMyIP.com disponible al público, puede crear uno fácilmente y alojarlo usted mismo, preferiblemente como un servicio web para que pueda hacer una simple llamada que cumpla con los requisitos de jabón desde su aplicación. No necesariamente harías una captura de pantalla tanto como una publicación detrás de escena y leerías la respuesta.

3
SqueakerJG

¡La solución de Patrik funciona para mí!

Hice uno cambio importante En el mensaje de proceso configuré el CallContext usando este código:

// try to set the call context
LogicalCallContext lcc = (LogicalCallContext)requestMessage.Properties["__CallContext"];
if (lcc != null)
{
    lcc.SetData("ClientIP", ipAddr);
}

Esto coloca la dirección IP en el CallContext correcto, para que luego pueda recuperarse con GetClientIP().

2
Justin Tanner

Si solo desea la IP vinculada al adaptador, puede usar WMI y la clase Win32_NetworkAdapterConfiguration.

http://msdn.Microsoft.com/en-us/library/aa394217 (VS.85) .aspx

2
TimK

Bueno, suponiendo que tienes un System.Net.Sockets.TcpClient conectado a su cliente, puede (en el servidor) usar client.Client.RemoteEndPoint. Esto te dará un System.Net.EndPoint señalando al cliente; que debería contener una instancia de System.Net.IPEndPoint subclase, aunque no estoy seguro de las condiciones para eso. Después de convertir a eso, puede verificar su propiedad Address para obtener la dirección del cliente.

En resumen, tenemos

using (System.Net.Sockets.TcpClient client = whatever) {
    System.Net.EndPoint ep = client.Client.RemoteEndPoint;
    System.Net.IPEndPoint ip = (System.Net.IPEndPoint)ep;
    DoSomethingWith(ip.Address);
}

Buena suerte.

1
configurator

Creo que, en teoría, no puede hacer tal cosa mientras está detrás de un enrutador (por ejemplo, usando rangos de IP no válidos) sin usar una "ayuda" externa.

0
Eduardo