【问题标题】:Get the client IP used to connect to some target IP?获取用于连接到某个目标 IP 的客户端 IP?
【发布时间】:2018-05-29 08:40:09
【问题描述】:

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

因为我们没有专用服务器,所以我们无法通过某些服务器应用(某种客户端管理器)检测客户端的 IP。在这种情况下,Ping 类似乎也没有帮助,通常服务器也不必启用 ping。目前,服务器只是一个 SQL Server,客户端直接执行一些查询。我知道当客户端对我的 SQL Server 执行查询(使用sys.dm_exec_connections)时,我们可以获得客户端的 IP,但这对我来说只是最后的手段。我想直接从客户端找到另一种方式(不涉及 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?

无论如何,AddressList 中不包含许多 IP 地址(不直接在同一个 LAN 中)。

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

【问题讨论】:

  • 你当然可以让客户端到tracert,然后将该信息发送到服务器?或者如果是SQL,写入数据库?
  • 仍然不明白您是否有服务器以及为什么需要这一切。无论如何,看看 NetworkInterface.GetAllNetworkInterfaces
  • @Evk 我的意思是我没有在服务器上运行任何我自己的应用程序(以便我可以管理连接的客户端),我所拥有的只是客户端直接查询的 SQL Server网络接口具有客户端可以选择路由到某个目标的所有可能 IP,在这种情况下,我想知道它必须使用的确切 IP(正如我在几乎所有情况下所说,应该只有 1 个 IP 和一个路径从客户端到目标)。
  • @john 是的,tracert 可能是我需要的,但看起来它需要服务器启用 ping(允许 ping)?

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


【解决方案1】:

您可以使用服务器端的任何可用侦听端口(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# 实现相同的程序 -- 只是不是我非常熟悉的语言。

【讨论】:

  • 我的服务器没有任何 HTTP 网络服务器,只有 SQL Server,这个可以应用吗?如果您提供的代码是 C#,我可以自己尝试一下。
  • 请看我对 C# 版本的回答,你的回答实际上是提出一个想法来帮助我解决这个问题的来源。所以我接受了这个答案,但是对于任何找到解决方案的人(使用 C#),请查看我的答案。
【解决方案2】:

看起来我错过了一个重要的已内置类来充当客户端(我们有 HttpClient、WebClient ......但在这种情况下我需要一个 TcpClient)。这可以尝试连接到某个 IP(提供了某个端口),如果成功,我可以获得底层 webSocket 的解析 LocalEndPoint。它可以只转换为字符串,但我可以解析它使用的客户端 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;
    }
}

【讨论】:

    猜你喜欢
    • 2021-06-01
    • 2011-06-12
    • 1970-01-01
    • 2018-12-30
    • 2013-03-31
    • 2019-06-20
    • 2021-01-27
    • 1970-01-01
    • 2011-02-24
    相关资源
    最近更新 更多