C# Do really need external ip for max mind services - c#

We are using maxmind geo ip location service in our web application. Utilizing this maxmind we need ipaddress to give as input.
We are following below snippet to get Ip address.
var ip = Request.UserHostAddress;
if (Request.Headers["X-Forwarded-For"] != null)
{
ip = Request.Headers["X-Forwarded-For"];
Console.WriteLine(ip + "|X-Forwarded-For");
}
else if (Request.Headers["REMOTE_ADDR"] != null)
{
ip = Request.Headers["REMOTE_ADDR"];
Console.WriteLine(ip + "|REMOTE_ADDR");
}
We are under corprate network, So in local environment as well as development environment we are used to get private ip address like this 10.X.X.X.
Using this address we always fails to locate the client location.
So real problem is when you passing external/public ip(190.X.X.X) to maxmind then only its working.
Do we really need to get external/public ips to give input to maxmind services.

You are using Maxmind for IP services that has everything to do with your clients' IP, not yours.
who are you trying to Geolocate?
For fraud services, who are you trying to evaluate?
Private IPs are used extensively by internal networks (home and corporations/enterprises..like yours), so they are not unique (aside from being non-routable on the public internet, etc.)

All geolocation providers work only on the public IP addresses. Private IP addresses are being used in LAN and can be re-issued again as long as it is not within the same LAN. There is no uniqueness to determine the geolocation information.

You are correctly using 10.xx.xx.xx range which is is reserved for private (internal) use.
All you need do is alter your code so that prior to your Maxmind look-up you replace the "10" IP to be looked-up with a "public" one for the same locale. If your company has multiple locations then you can create an array/table of internal IPs to public "locale identifying" IPs.
e.g. if the department in LA, USA uses 10.222.xx.xx; and NY,USA uses 10.123.xx.xx addresses then for these IPs simply Maxmind Lookup with an "equivalent" public IP. so for 10.123.xx.xx (NY, USA) look up 154.16.85.37 instead.
You may not even need to use Maxmind at all for your "10 IPs". E.g. if you simply need country code; then include it in your own "IP 10" look-up table/array and for IPs prefixed 10 instead of Maxmind look-up look-up from your own table.

Related

Get currently working ip address

I am seeking for a solution which allows me to get the currently working/(in use) ip address of my pc/laptop.
What I mean is I might be in LAN and then switch to WLAN. The ip addy will change and I need to stay up to date.
That is why I am not happy with approaches I found on the internet like IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
What is the best approach for this?
You can look up the active interfaces of the machine like this:
var interfaces = NetworkInterface.GetAllNetworkInterfaces().Where(a => a.OperationalStatus == OperationalStatus.Up);
var addresses = interfaces.First().GetIPProperties().UnicastAddresses.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
The Address property of any item in addresses holds the ip. From there you could monitor the adapters and decide when you need to switch over and what address to bind to.

how check if port is currently used with IIS7 (webSite) in code behind?

I developed a program "installer" that will add and configure a new website on IIS.
My problem is that I want to check if the port given by the user is already used by another site before installing.
My project is in C # WinForm style.
Someone you have an idea?
string[] lPorts = System.IO.Ports.SerialPort.GetPortNames(); ?
Check this:
BindingInformation Property: Gets or sets the binding information for the current binding.
The value of this property is a colon-delimited string that includes the IP address, port, and host name of the binding. You can leave the host name blank. You can set the IP address to "*" to indicate that the binding works for all variables.
For example, a binding that is set for all IP addresses on port 80 and has no specified host name returns ":80:" from this property. A binding that is set for IP address 192.168.1.150 on port 8080 returns "192.168.1.150:8080:". A binding that is set for all IP addresses on port 80 for a host named "microsoft.com" returns ":80:microsoft.com".
The BindingInformation property values are maintained in the ApplicationHost.config file.
Also, you can check this: Get IIS bindings at runtime
foreach (Microsoft.Web.Administration.ConfigurationElement binding in mySite.GetCollection("bindings"))
{
string protocol = (string)binding["protocol"];
string bindingInfo = (string)binding["bindingInformation"];
if (protocol.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
string[] parts = bindingInfo.Split(':');
if (parts.Length == 3)
{
//Get the port in use HERE !!!
string port = parts[1];
yield return new KeyValuePair<string, string>(protocol, port);
}
}
}
You should look in the
Microsoft.Web.Administration namespace
You should use ServerManager.Sites to get a listing of sites. Take a look at the collection Bindings on each site. Each site may have one or more bindings, i.e. it may be accessed via one or more addresses / ports.
Your code above looks for the physical serial ports which where used before usb to connect modems and printers.
Hope this helps!
Not sure if you are looking for C#, but if you need powershell here you go..
Open PowerShell and enter the following:
import-module webadministration
get-webbinding

Difference between GetHostEntry and GetHostByName?

On MSDN it mentions GetHostByName is obsolete. The replacement is GetHostEntry. What are their difference?
It looks like GetHostEntry does a little more error checking and also supports Network Tracing
GetHostByName Decompiled:
public static IPHostEntry GetHostByName(string hostName)
{
if (hostName == null)
throw new ArgumentNullException("hostName");
Dns.s_DnsPermission.Demand();
IPAddress address;
if (IPAddress.TryParse(hostName, out address))
return Dns.GetUnresolveAnswer(address);
else
return Dns.InternalGetHostByName(hostName, false);
}
GetHostEntry Decompiled:
public static IPHostEntry GetHostEntry(string hostNameOrAddress)
{
if (Logging.On)
Logging.Enter(Logging.Sockets, "DNS", "GetHostEntry", hostNameOrAddress);
Dns.s_DnsPermission.Demand();
if (hostNameOrAddress == null)
throw new ArgumentNullException("hostNameOrAddress");
IPAddress address;
IPHostEntry ipHostEntry;
if (IPAddress.TryParse(hostNameOrAddress, out address))
{
if (((object) address).Equals((object) IPAddress.Any) || ((object) address).Equals((object) IPAddress.IPv6Any))
throw new ArgumentException(SR.GetString("net_invalid_ip_addr"), "hostNameOrAddress");
ipHostEntry = Dns.InternalGetHostByAddress(address, true);
}
else
ipHostEntry = Dns.InternalGetHostByName(hostNameOrAddress, true);
if (Logging.On)
Logging.Exit(Logging.Sockets, "DNS", "GetHostEntry", (object) ipHostEntry);
return ipHostEntry;
}
Firstly, it is important to recognize that these are wrappers of the UNIX socket library, which exposes functions inet_aton (equivalent to IPAddress.Parse), gethostbyname (wrapped by Dns.GetHostByName) and gethostbyaddr (wrapped by Dns.GetHostByAddress). Microsoft subsequently added the Dns.GetHostEntry utility function based on these.
After pondering the philosophical difference between Dns.GetHostByName and Dns.GetHostEntry, I've come to the conclusion that Microsoft decided that the primary API they expose for DNS lookups should be trying to return only actual DNS entries.
At the UNIX sockets level, gethostbyname can take either an IP address or a host name. It is explicitly documented as parsing the IP address if that's what you supply. But it is also explicitly documented as only supporting IPv4 addresses. As such, developers are encouraged to use the function getaddrinfo instead, which does a more complex look-up involving the service you want to connect to as well, and which supports address families other than IPv4.
Microsoft took a different approach in their wrapper. They still consider GetHostByName to be deprecated, but instead of tying the look-up to a services database, they decided to create a function that returns the actual physical DNS host entry you ask for. It's not enough that you perhaps supply a string with a valid address in it, if there's no DNS entry then GetHostEntry will fail, because that is its entire purpose. Thus, if you pass a host name into GetHostEntry, it performs a forward DNS lookup, and if you pass an IP address into GetHostEntry, it performs a reverse DNS lookup. Either way, the returned structure will tell you both the DNS entry name and the associated address -- but if there is no associated entry, the only thing you get back is an error.
If you're looking to handle user input that supplies a target for connection, GetHostEntry is not really suitable, because if the user types in an ad hoc IP address, it may fail to resolve it even though, since it's an IP address, you have everything you need to make a connection. GetHostByName is exactly the function you need in this case, but Microsoft have chosen to deprecate it. Given the deprecation, the idiom is going to be to replicate the "try to parse first" approach that #Faisai Mansoor showed in the decompiled GetHostByName function:
// Microsoft's internal code for GetHostByName:
if (IPAddress.TryParse(hostName, out address))
return Dns.GetUnresolveAnswer(address);
else
return Dns.InternalGetHostByName(hostName, false);
This uses internal implementation details of the Dns class, but the spirit of it is easy to replicate in your own code, e.g.:
if (!IPAddress.TryParse(userInput, out var addressToWhichToConnect))
addressToWhichToConnect = Dns.GetHostEntry(userInput).AddressList.First();

Get IPAddress from a hostname

I want to get IP address of a host on my aspx page using C#, I'm using DNS class methods to get these.
It worked fine locally, but when I deployed the solution on IIS7 it returned only the IP address assigned by ISP but I want local IP address of that machine.
Any suggestion?
Here is Example for this.
In this example we can get IP address of our given host name.
string strHostName = "www.microsoft.com";
// Get DNS entry of specified host name
IPAddress[] addresses = Dns.GetHostEntry(strHostName).AddressList;
// The DNS entry may contains more than one IP addresses.
// Iterate them and display each along with the type of address (AddressFamily).
foreach (IPAddress address in addresses)
{
Response.Write(string.Format("{0} = {1} ({2})", strHostName, address, address.AddressFamily));
Response.Write("<br/><br/>");
}
I'm fairly confident that you can not get the local 192.168.C.D address of the local machine like this.
This is because of security and visibility (NAT's etc).
If you are looking to uniquely identify a user. I would look to sessions or cookies.
When looking up the ip address in a public DNS, you will get the officiall IP address communicated outwards. If NAT is used and you want the internal address you have to connect to a DNS server which holds the internal IP addresses.
you can use this method...
public static String GetIP()
{
String ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if(string.IsNullOrEmpty(ip))
{
ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}

Get external IP address over remoting in C#

I need to find out the external IP of the computer a C# application is running on.
In the application I have a connection (via .NET remoting) to a server. Is there a good way to get the address of the client on the server side?
(I have edited the question, to be a little more clear. I'm apologize to all kind people who did their best to respond to the question, when I perhaps was a little too vague)
Solution:
I found a way that worked great for me. By implementing a custom IServerChannelSinkProvider and IServerChannelSink where I have access to CommonTransportKeys.IPAddress, it's easy to add the client ip on the 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;
}
And then later (when I get a request from a client) just get the IP from the CallContext like this.
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();
}
I can now send the IP back to the client.
This is one of those questions where you have to look deeper and maybe rethink the original problem; in this case, "Why do you need an external IP address?"
The issue is that the computer may not have an external IP address. For example, my laptop has an internal IP address (192.168.x.y) assigned by the router. The router itself has an internal IP address, but its "external" IP address is also internal. It's only used to communicate with the DSL modem, which actually has the external, internet-facing IP address.
So the real question becomes, "How do I get the Internet-facing IP address of a device 2 hops away?" And the answer is generally, you don't; at least not without using a service such as whatismyip.com that you have already dismissed, or doing a really massive hack involving hardcoding the DSL modem password into your application and querying the DSL modem and screen-scraping the admin page (and God help you if the modem is ever replaced).
EDIT: Now to apply this towards the refactored question, "How do I get the IP address of my client from a server .NET component?" Like whatismyip.com, the best the server will be able to do is give you the IP address of your internet-facing device, which is unlikely to be the actual IP address of the computer running the application. Going back to my laptop, if my Internet-facing IP was 75.75.75.75 and the LAN IP was 192.168.0.112, the server would only be able to see the 75.75.75.75 IP address. That will get it as far as my DSL modem. If your server wanted to make a separate connection back to my laptop, I would first need to configure the DSL modem and any routers inbetween it and my laptop to recognize incoming connections from your server and route them appropriately. There's a few ways to do this, but it's outside the scope of this topic.
If you are in fact trying to make a connection out from the server back to the client, rethink your design because you are delving into WTF territory (or at least, making your application that much harder to deploy).
Dns.GetHostEntry(Dns.GetHostName()); will return an array of IP addresses. The first one should be the external IP, the rest will be the ones behind NAT.
So:
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
string externalIP = IPHost.AddressList[0].ToString();
EDIT:
There are reports that this does not work for some people. It does for me, but perhaps depending on your network configuration, it may not work.
I found a way that worked great for me. By implementing a custom IServerChannelSinkProvider and IServerChannelSink where I have access to CommonTransportKeys.IPAddress, it's easy to add the client ip on the 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;
}
And then later (when I get a request from a client) just get the IP from the CallContext like this.
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();
}
I can now send the IP back to the client.
Better to just use http://www.whatismyip.com/automation/n09230945.asp it only outputs the IP just for the automated lookups.If you want something that does not rely on someone else put up your own page http://www.unkwndesign.com/ip.php is just a quick script:
<?php
echo 'Your Public IP is: ' . $_SERVER['REMOTE_ADDR'];
?>
The only downside here is that it will only retrieve the external IP of the interface that was used to create the request.
Jonathan Holland's answer is fundamentally correct, but it's worth adding that the API calls behind Dns.GetHostByName are fairly time consuming and it's a good idea to cache the results so that the code only has to be called once.
The main issue is the public IP address is not necessarily correlated to the local computer running the application. It is translated from the internal network through the firewall. To truly obtain the public IP without interrogating the local network is to make a request to an internet page and return the result. If you do not want to use a publicly available WhatIsMyIP.com type site you can easily create one and host it yourself - preferably as a webservice so you can make a simple soap compliant call to it from within your application. You wouldn't necessarily do a screen capture as much as a behind the scenes post and read the response.
If you just want the IP that's bound to the adapter, you can use WMI and the Win32_NetworkAdapterConfiguration class.
http://msdn.microsoft.com/en-us/library/aa394217(VS.85).aspx
Patrik's solution works for me!
I made one important change. In process message I set the CallContext using this code:
// try to set the call context
LogicalCallContext lcc = (LogicalCallContext)requestMessage.Properties["__CallContext"];
if (lcc != null)
{
lcc.SetData("ClientIP", ipAddr);
}
This places the ip address in the correct CallContext, so it can later be retrieved with
GetClientIP().
Well, assuming you have a System.Net.Sockets.TcpClient connected to your client, you can (on the server) use client.Client.RemoteEndPoint. This will give you a System.Net.EndPoint pointing to the client; that should contain an instance of the System.Net.IPEndPoint subclass, though I'm not sure about the conditions for that. After casting to that, you can check it's Address property to get the client's address.
In short, we have
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);
}
Good luck.
I believe theoretically you are unable to do such a thing while being behind a router (e.g. using invalid ip ranges) without using an external "help".
You can basically parse the page returned by doing a WebRequest of http://whatismyipaddress.com
http://www.dreamincode.net/forums/showtopic24692.htm
The most reliable manner of doing this is checking a site like http://checkip.dyndns.org/ or similar, because until you actually go external to your network, you cannot find your external IP. However, hardcoding such a URL is asking for eventual failure. You may wish to only perform this check if the current IP looks like an RFC1918 private address (192.168.x.x being the most familiar of these.
Failing that, you can implement your own, similar, service sitting external to the firewall, so you will at least know if it's broken.

Categories