0

First of all I have to mention that I don't have any dedicated server in this case. But I know about the server's IP. So the problem is if the client connects to that IP, how could I know which client IP it uses? Because a client can have more than 1 network adapter, each one is connected to a different network. Also the server does not need to be in the same LAN with the client, it may require several hops before the client's packets reaching the server. We know the server's IP, how could we know the client's IP in this case?

Because we don't have dedicated server so we cannot detect the client's IP via some server app (some kind of clients manager). Also the Ping class seems not helpful in this case, also in general the server does not have to have pinging enabled. Currently the server is just a SQL Server to which the client executes some query directly. I know we can obtain the client's IP when it executes a query to my SQL Server (using sys.dm_exec_connections) but it's just the last resort for me. I would like to find another way directly from the client (and without involving the SQL Server).

Here is the closest approach I can follow but I don't really know why it chooses the last address?

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?

Any way there are many IP addresses (not in the same LAN directly) which are not contained in the AddressList.

My problem is some kind of finding all possible network paths between the client (starting at some available network adapter on the client) and the server (with IP known beforehand). In almost cases there should be just 1 path available (so we should just find 1 client's IP). Trying sending some request from the client may be required to find the path but I currently don't have any clue on how it can be done.

halfer
  • 18,701
  • 13
  • 79
  • 158
Hopeless
  • 3,626
  • 3
  • 29
  • 50
  • Surely you can just get the client to [tracert](https://stackoverflow.com/questions/142614/traceroute-and-ping-in-c-sharp) and then send that information to the server? Or if it's SQL, write it to the database? – Llama Dec 15 '17 at 07:25
  • 1
    Still didn't understand if you have server or not and why you need all this. Anyway, look at NetworkInterface.GetAllNetworkInterfaces – Evk Dec 15 '17 at 07:48
  • @Evk I mean I don't have any my own app running on the server (so that I can manage connected clients), what I have is just the SQL Server to which the clients query directly The Network Interfaces has all possible IPs that the client can choose to route to some target, in this case I would like to know the exact IP it must use (as I said in almost cases, there should be just 1 IP as well as one path to the target from the client). – Hopeless Dec 16 '17 at 01:15
  • @john yes tracert may be what I need but looks like it requires the server to have pinging enabled (allows to ping)? – Hopeless Dec 16 '17 at 01:21

2 Answers2

0

You can easily do this from the client side using any available listening port on the server side (HTTP port, SSH port, or SQL Server port). Here's a small python program:

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])

What it does is to create a connection to the destination system, then uses the getsockname system call to provide the local address used in the connection. This local address will always correspond to one of your client side interfaces.

So for example, if I run it with arguments www.google.com 80, I get:

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

If I instead give it an address and port of a machine on a different local subnet, I get:

python /tmp/disc.py 192.168.40.128 22
192.168.40.131

The two addresses returned correspond to two different interfaces on my local system:

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

I'm sure you could easily implement the same program in C# -- just not a language I'm intimately familiar with.

Gil Hamilton
  • 10,965
  • 22
  • 45
  • my server does not host any HTTP webserver, just SQL Server, can this be applied on? I can try this myself if the code you provided was in C#. – Hopeless Dec 16 '17 at 01:18
  • please see my answer for the C# version, your answer is actually the source raising an idea to help me solve this. So I accepted this answer, but for any one finding a solution for this (using C#), please see my answer instead. – Hopeless Dec 16 '17 at 01:56
0

Looks like I missed one important already built-in class to act as a client (we have HttpClient, WebClient ... but in this case I need a TcpClient). This can try connecting to some IP (with some port provided) and if it succeeds I can obtain the resolved LocalEndPoint of the underlying webSocket. It can just be converted to string but I can parse for the client IP it used (the string format is like IP:port). Here is just a few lines of code to achieve what I want:

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;
    }
}
Hopeless
  • 3,626
  • 3
  • 29
  • 50