I am trying to find the ip address (not the hostname) that responded to my WebRequest in C#. I do not want to do a DNS resolution, because their are cases where the DNS records returned are not the servers responding to the request. For ex:
Client -> Load Balancer -> Web Server
The DNS server would respond with the Load Balancer's IP. Assuming the responding Web server is not going back through the Load Balancer, the IP address would then be the actual Web server which is what I am trying to find.
Do you have access to the server side code? Or to the web server configuration? You could always place the machines IP, or whatever identifier you'd like, in a custom header and look for that on the client.
As for your original question, I do not believe that information is exposed anywhere by the HttpWebRequest/HttpWebResponse classes.
I think you'll have to go OSI-dipping, and create and harness your own socket;
then you'll have access to the RemoteEndPoint property (at least after your socket has connected, or been connected to) like so :
Socket sprocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sprocket.Connect("www.google.com", 80);
string IPAddressOfRespondingServer = ((IPEndPoint)sprocket.RemoteEndPoint).Address.ToString();
Related
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.
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.
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;
}
}
Writing a chat program (as so many do) and i have found that i would like to be able to get the clients to connect to the server automatically.
However, the IP address of the server would not be permanent, so i cannot just hard-core it into the program
In TCP, I'm looking for some sort of broadcast feature, that allows the client to know where the server is
Any ideas?
EDIT: should have said, this will be a LAN program only - no outside connections
If you are talking about a chat in a LAN and you can't or don't want to use DNS for some reason, you could implement, or find an implementation of, the discovery protocol used by UPnP. The SSDP is based on a UDP broadcast. It is, afaik, not possible to multicast via TCP, because TCP needs a session.
If you want to use the chat server over the internet you have no choice but to use DNS. Look for a dynamic dns provider (I use selfhost.bz). In C# you can then resolve the hostname to an IP address as described in the other answers. If you have a hostname to connect to it will probably be enough to pass that to the socket, though:
socket.Connect("myhostname.selfhost.bz", ...
Edit: Since you say you're in a LAN, a few more details on SSDP. The protocol does way more, than you actually need. If you're thinking of implementing it yourself, don't stick to it exactly. Just make your clients send a broadcast on a specified port. The server permanently listens on that port, answering with a predefined message, once it receives a message. When the client receives that answer, it will know that the sender is a valid server.
Use DNS. Resolve the hostname in your app and connect to the IP it resolves to. You'll need dynamic DNS since you say the IP isn't permanent.
Use the below process to find server IP address
public string GetIPAddress()
{
string strHostName = System.Net.Dns.GetHostName();
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
return ipAddress.ToString();
}
You can also use
Request.ServerVariables["LOCAL_ADDR"];
I had an idea: just get the server to write the IP address/port/whatever to a textfile somewhere on the (public) network, and the clients can read the text file
Obviously, if the text file is not there or empty, no server is running...
Is this such a bad idea?
I'm looking to get the local IP address of the socket I just created. I need to be able to support a server with more than one NIC and communicate back to the requesting client what the direct IP address is to connect later on. I'm using for following code:
Socket rsock = null;
rsock= new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
rsock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
rsock.Bind(new IPEndPoint(IPAddress.IPv6Any, port));
rsock.Listen((int)SocketOptionName.MaxConnections);
After this point, .LocalEndPoint kicks out: [::]:PORT.
Background:
The reason I need the IP address is that a secondary connection by another client will need to return to this specific server. These servers will likely be behind a load balancer for the initial server selection so the client cannot resolve the IP address based on the host name.
Since you're binding to IPAddress.IPv6Any, the endpoint information will not be available before the first I/O operation occurs. The documentation says:
If you allow the system to assign your socket's local IP address and
port number, the LocalEndPoint property will be set after the first
I/O operation. For connection-oriented protocols, the first I/O
operation would be a call to the Connect or Accept method.
So, in your case, you will have to call Accept() before accessing LocalEndPoint in order to obtain meaningful information.
I have a web service on a server in my company that we have restricted access to from all but one other server on our network.
I do however need to make calls to this from another machine. Is there a way I can spoof the other servers IP address in order to send an http request to the web service? I only need to send it info I don't need any returned data. It's for logging hits from another server on our main server.
I am using this
IPEndPoint endpointAddress = new IPEndPoint(IPAddress.Parse(ipAddress), 80);
using (Socket socket = new Socket(endpointAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
socket.SendTimeout = 500;
socket.Connect(endpointAddress);
socket.Send(byteGetString, byteGetString.Length, 0);
}
but get an exception
A connection attempt failed because
the connected party did not properly
respond after a period of time, or
established connection failed because
connected host has failed to respond
23.202.147.163:80
In general, it is not possible to establish a TCP connection with a server without being able to receive and process some reply packets from that server. HTTP is built upon TCP, and TCP starts communications with a "3-way handshake" that lets the client and server communicate.
The start of an HTTP request is not a single packet.
You could use a proxy to bounce your requests from an IP address that has access.
I am using TcpClient to listen on a port for requests. When the requests come in from the client I want to know the client ip making the request.
I've tried:
Console.WriteLine(tcpClient.Client.RemoteEndPoint.ToString());
Console.WriteLine(tcpClient.Client.LocalEndPoint.ToString());
var networkStream = tcpClient.GetStream();
var pi = networkStream.GetType().GetProperty("Socket", BindingFlags.NonPublic | BindingFlags.Instance);
var socketIp = ((Socket)pi.GetValue(networkStream, null)).RemoteEndPoint.ToString();
Console.WriteLine(socketIp);
All of these addresses output 10.x.x.x addresses which are private addresses and are clearly not the address of the clients off my network making the requests. What can I do to get the public ip of the clients making the requests?
Edit:
We are using an Amazon EC2 Load Balancer with tcp forwarding. Is there a way to get the true client ip in this set up?
Does this work:
((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address.ToString()
If the client is connecting to you via an internal network I am not sure you can get their public IP since the connection to get back to the client would not need that information.
It sounds like perhaps your server is behind a load balancer or router using NAT. In this case, the IP packet won't have the originating client's address, but the address of the NAT router. Only the NAT router knows the sender's address (on an IP level).
Depending on whatever higher-level protocol you might be using on top of TCP, you may be able to get client identification from that, although it's much easier to spoof such information at higher levels, if that may be a concern.
If you need this data only for research purposes, your NAT device may keep a log.
If it's a requirement that you get the true originating IP packet in real time, you may have to have to reconfigure your router or have your server moved to the DMZ, but that's a whole nother ball of wax. Talk to your network guys, as they would certainly know more about this than I (I'm not a network expert).
Simply use the connection socket object of Socket class which you have used to accept the client.
connectionSocket.RemoteEndPoint.toString();
AdresseIP = DirectCast(SocketClient.Client.RemoteEndPoint, IPEndPoint).Address.ToString