获取用于连接某些目标IP的客户端IP?

时间:2017-12-15 06:51:20

标签: c# .net networking network-programming system.net

首先,我必须提到在这种情况下我没有任何专用服务器。但我知道服务器的IP。所以问题是如果客户端连接到该IP,我怎么知道它使用哪个客户端IP?由于客户端可以拥有多个网络适配器,因此每个网络适配器都连接到不同的网络。此外,服务器不需要与客户端在同一LAN中,在客户端的数据包到达服务器之前可能需要几次跳跃。我们知道服务器的IP,在这种情况下我们如何知道客户端的IP?

因为我们没有专用服务器所以我们无法通过某些服务器应用程序(某种客户端管理器)检测客户端的IP。在这种情况下,Ping类似乎也没有帮助,通常服务器也不必启用ping。目前,服务器只是客户端直接执行某些查询的SQL Server。我知道我们可以在执行查询到我的SQL Server时使用客户端的IP(使用sys.dm_exec_connections),但这对我来说只是最后的选择。我想直接从客户端找到另一种方法(并且不涉及SQL Server)。

这是我可以遵循的最接近的方法,但我不知道为什么选择最后一个地址?

var hn = System.Net.Dns.GetHostName();
var ipEntry = System.Net.Dns.GetHostEntry(hn);
IPAddress[] addr = ipEntry.AddressList;
var ip = addr[addr.Length - 1].ToString();//why the last?

任何方式都有许多IP地址(不在同一个局域网中),AddressList中没有包含这些地址。

我的问题是找到客户端(从客户端上的某个可用网络适配器开始)和服务器(预先知道IP)之间的所有可能的网络路径。在几乎情况下,应该只有一条路径可用(所以我们应该只找到1个客户端的IP)。尝试从客户端发送一些请求可能需要找到路径,但我目前还没有任何关于如何完成的线索。

2 个答案:

答案 0 :(得分:0)

您可以使用服务器端的任何可用侦听端口(HTTP端口,SSH端口或SQL Server端口)从客户端轻松执行此操作。这是一个小型的python程序:

import sys
import socket
if len(sys.argv) != 3:
    print("Usage: {} ip-or-hostname port-number".format(sys.argv[0]))
    sys.exit(1)
hostname = sys.argv[1]
port = int(sys.argv[2])
s = socket.socket()
s.connect((hostname, port))
print(s.getsockname()[0])

它的作用是创建与目标系统的连接,然后使用getsockname系统调用提供连接中使用的本地地址。此本地地址始终对应于您的一个客户端接口。

例如,如果我使用参数www.google.com 80运行它,我得到:

python /tmp/disc.py www.google.com 80
192.168.0.110

如果我在不同的本地子网上给它一台机器的地址和端口,我得到:

python /tmp/disc.py 192.168.40.128 22
192.168.40.131

返回的两个地址对应于我本地系统上的两个不同接口:

ip -4 addr
[snipped]
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.0.110/24 brd 192.168.0.255 scope global dynamic ens33
       valid_lft 166968sec preferred_lft 166968sec
3: ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.40.131/24 brd 192.168.40.255 scope global ens34
       valid_lft forever preferred_lft forever

我确信您可以轻松地在C#中实现相同的程序 - 而不是我非常熟悉的语言。

答案 1 :(得分:0)

看起来我错过了一个重要的已经内置的类来充当客户端(我们有HttpClient,WebClient ......但在这种情况下我需要一个TcpClient)。这可以尝试连接到某些IP(提供了一些端口),如果成功,我可以获得已解析的LocalEndPoint底层webSocket。它只能转换为字符串,但我可以解析它使用的客户端IP(字符串格式类似于IP:port)。这里只是几行代码来实现我想要的东西:

public string GetIPConnectingTo(string targetIP, int port = 80){
    try {
        using(var tc = new TcpClient(targetIP, port)){
           return tc.Client.LocalEndPoint.ToString().Split(':')[0];
        }
    }
    catch {
        return null;
    }
}