I am trying to convert a VBScript COM component based Reverse/Forward IP checking system to C#.
This system was created to prevent the banning of SERPs like Googlebot using what was back then (becoming) the standard way of checking an IP was who it said it belonged to e.g a reverse/forward DNS check.
Although we have lists of SERP IP Ranges so we don't ban them if they come in - even with hack vectors - we cannot keep up with new ranges being added all the time.
The process is based around this short example.
It is explained simply here > http://ipadmin.junkemailfilter.com/rdns.php
This has been working fine for ages in VBScript but now I am converting to .NET I am having issues where people have set their IP to resolve to "localhost" like this one 113.168.154.182 as you just get back your own DNS server, Virgin media, or if I run it from my PC with c# I get my own computer name. The IP is from Vietnam > http://www.geoiptool.com/en/?ip=113.168.154.182
Now I am trying to use .NET and this code.
But as I am using this code to do get the hostname
IPHostEntry DNSHostIP = Dns.GetHostEntry("113.168.154.182");
hostname = DNSHostIP.HostName;
When I output the value of hostname I get my own computers name e.g std36w7.metal.mycompany.co.uk not localhost.
Then when I try and do a forward DNS check to get the list of IP addresses with this hostname I get my own IP addresses (one IPv6 one IPv4).
If I could get back "localhost" then I could have a check to skip it as a spoof along with anything starting with 10 or 192 etc.
However at the moment I cannot do this.
What is the best way of doing reverse/forward DNS checks which I thought was becoming the standard way of checking for spoofers nowadays in .NET?
And how can I handle people who have set (or some mistake might be causing it) their IP to be localhost.
Thanks
Simple. Your LOCAL DNS (guessing your router unless you have your own DNS server) is resolving it - upstream to it's INTERNET DNS server. Also if you really want it to return LOCALHOST, you'd have to literally edit your local HOSTS file and add an entry since no system ever returns the name LOCALHOST when you look up your ip even from a local DNS server. I believe the ONLY example is if you completely eliminate a DNS server to fallback on your local HOSTS file.
Related
I am trying to retrieve a file on a network location - actually a NAS with fixed IP address.
Using File.Exists(#"//myserver/myfile.txt") works just fine, unfortunately, File.Exists(#"//192.168.1.101/myfile.txt") doesn't (of course, I made sure ping myserver returns 192.168.1.101).
I couldn't find any reasonable explanation as to why using DNS names would work but not IP address. Is this a known issue or is it possibly an issue with my network? I'd really get it to work with IP address, but is it possible?
Final edit for clarity - In my environment, DNS will only store one record per client. If a client has multiple NICs, or changes subnets, the original IP is registered in DNS until the corresponding DHCP record expires (this is an AD environment where DHCP registers DNS addresses).
In this scenario DNS has one, incorrect, record for the client. I want to query DHCP by client name, to see all IPs that are leased to it.
The only possible solution I have found is to dump all subnet info from DHCP (supported by the below API) then query against that, but that is not feasible in my environment, since multiple people would use this application, and I don't want the additional strain on DHCP.
I cannot change any configuration for DNS or DHCP.
Thanks,
This is similar to this question, but with the referenced API (here), I can only query via IP. Is it possible with this API, or any other, to query DHCP by hostname? (The issue being, DNS gives me an old IP for MachineA, I want to retrieve any other IPs being leased by MachineA from the DHCP server).
Edit: To clarify, I want to write a program that I can type in a hostname, it will then query a DHCP server for all IPs for that hostname in any subnet administered by that DHCP server. This is to workaround the issue of a machine with multiple NICs registering an IP that is useless to me (wireless), so for instance the DNS result may be NICA (wireless) but I want NICB (wired).
From what I can tell, you've encountered the age-old problem of which IP address to use. Now-a-days many computers have multiple NICs, some virtual, some local-only, some with internet access, etc... For the application to choose is very difficult. Most of the time I simply make the IP by which the application hosts things like sockets a configuration item--simply because the application is incapable of really choosing which is the right ip address to use. e.g. two NICs both with the same network access, which do you choose? If you run the application twice, maybe one should use NIC 1 and the other should use NIC 2--how would the app make that determination? (i.e. it can't).
Having said that, depending your needs, you can go looking for the best NIC and get it's IP address. For example, if you want an IPv4 address on a non-wireless NIC, you can do something like:
var ips = from ni
in NetworkInterface.GetAllNetworkInterfaces()
where ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet
from ip in ni.GetIPProperties().UnicastAddresses
where ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && ip.IsDnsEligible
select ip;
IPAddress address = ips.First().Address;
...error checking omitted for readability--apply whatever error checking suitable for your requirements.
You can even go so far as to check whether the address is link local (i.e. can communicate out of the local network segment--which usually means an address automatically assigned by Windows instead of DNS/DHCP) by seeing if the first two bytes of an IPv4 address are 169 and 254.
But, you need to specifically define what your requirements are. simply to say "undesirable wireless IP" doesn't provide unambiguous and verifiable criteria to tell what solution will always work for your needs.
If you are trying to locate a machine on the network, then querying DNS is probably what you want to do first. i.e. Think of a machine that has a static ip address on the network. It would register its name with the name service only, it would not show up in DHCP att all if the machine's IP stack is configured with the static address only.
I'm not sure how long it should take for a new machine or a recently changed IP address to show up in DNS. But if you want to see if DHCP has something different(newer), then query DHCP after trying it from DNS first.
I have the following code:
string ip = Request.ServerVariables["REMOTE_ADDR"];
Which, in the test environment does return the user IP addrress, but when we deploy the website to production, this variable has the IP of the server where the application is hosted. Any help?
My guess is that there is a proxy in the middle. Use HTTP_X_FORWARDED_FOR first, and if that's null, then use REMOTE_ADDR
From the MSDN article:
Although retrieving just the REMOTE_ADDR server variable should be enough, I found resources online that suggested that code like this should also check the HTTP_X_FORWARDED_FOR variable; if the request comes through a proxy server that translates the address, it's this variable that contains the correct address. If you request a server variable that doesn't exist, the ServerVariables property returns an empty string. Therefore, even though this property doesn't appear in my tests, attempting to retrieve its value doesn't cause trouble.
UPDATE:
If it's a load balancer that you have have settings changed on, you should ask to see if they can have the origination IP passed through. I know this can be done with Microsoft's ISA server.
If that's not an option, there are these other server variables that you can try and see if they produce a result:
"HTTP_X_COMING_FROM"
"HTTP_X_FORWARDED_FOR"
"HTTP_X_FORWARDED"
"HTTP_X_REAL_IP"
"HTTP_VIA"
"HTTP_COMING_FROM"
"HTTP_FORWARDED_FOR"
"HTTP_FORWARDED"
"HTTP_FROM"
"HTTP_PROXY_CONNECTION"
"CLIENT_IP"
"FORWARDED"
Why do you use old, VB-style server variables instead of Request.UserHostAddress?
See MSDN Library.
As the others have stated, you will get the IP address of the reverse proxy/SSL terminator if it doesn't make the requests look like they come from the original client (As is possible at least in ISA server, and probably in most other reverse proxies).
If not, you will get the public address of the client (which is probably a router address at the client site, as most LANs are NAT-ed).
How does your setup in the production environment differ from your test environment?
Are you actually getting the IP address of the Web server, or of some other server in the same network?
I see this is an old question but I ran across it and I think I know the answer. The answer is simpler than those above... I just ran into the same issue today. I bet you are trying to get the IP from a page being called by XMLHTTP which will return the server IP since it is the one making the request and not the user.
I have a program in C# that I want to get a news feed from a server I setup in my basement. I also want to setup this program so it can work locally. To do this I THINK I need to compare the resolved ip of my dyndns.biz hostname to my router's public ip (I have dynamic ip and a client on my server updating the ip of the hostname) and thus determine if the hostname needs to be used or the local ip of the server (192.168.0.100) or the hostname. I already have code to connect to the ftp server assuming I can get the right usage of the hostname versus the localized IP.
Edit: Anyways, in summary because I realized this might not look like a question, how can I determine a) the resolved IP of the hostname and b) the public IP of my router in a C# app
You're overcomplicating this.
Just open your hosts file (found in C:\Windows\System32\drivers\etc) and add your dyndns hostname routing it to loopback. That way you don't have to add any workaround code to your final application to prevent it from even asking your DNS or router:
127.0.0.1 yourhostname.dyndns.biz
To obtain the IP address of a hostname, use the following code:
IPAddress[] addresses = System.Net.Dns.GetHostAddresses("www.cnn.com");
To obtain your public IP address of your router or local network, you need to talk to an outside system that can tell you that part, and unfortunately I don't know if there is any such system that is free to use as well as easy to use from a program.
If Request.ServerVariables["HTTP_X_FORWARDED_FOR"] returns multiple ip's, which one do I take and how would I do it in c#? It is my understanding that if it is blank or null, then the client computer is not going through a proxy and I can just get their ip from Request.ServerVariables["REMOTE_ADDR"]. Is this a correct statement?
By "which one do I take", I mean do I take the first IP in the list or the last IP and is all I have to do is just split it into an array and take the one I want. I am not really sure how HTTP_X_FORWARDED_FOR works.
According to this, the format of X-Forwarded-For HTTP header is:
X-Forwarded-For: client1, proxy1, proxy2, ...
So the IP address of the client that you want should be the first one in the list
A further note on the reliability subject:
Anyone can forge HTTP_X_FORWARDED_FOR by using a tool such as the Firefox plugin "Tamper Data" or their own local proxy (e.g. Privoxy). This means that the entire string might be fake, and REMOTE_ADDR is the actual original host. It might also mean that the first "client1" address is faked, and then the client connected through a proxy, resulting in proxy1 being the client's IP address and REMOTE_ADDR being the single proxy used.
If you are looking to deny access based on IP, I would suggest checking every IP address in the XFF header as well as REMOTE_ADDR.
If you're looking to grant access based on the region of an IP, I'd suggest allowing access only if XFF is blank and the IP is from the proper area.
As Mastermind already noted, however, there are proxies which will hide the chain of proxies. For instance, the Tor network will make a request appear as if it came from the final proxy machine, rather than the original IP. Anonymizing proxies will often claim they are forwarding for the same IP as reported in REMOTE_ADDR.
IP based filtering is generally a pretty crude, last-resort mechanism of access control.
I asked some time ago a very similar question.
Getting the client IP address: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, what else could be useful?
As correctly pointed out, you can take the first value considering it to be the client's IP address. But it may as well be company gateway IP.
And anonymous proxies will wipe out information in this header anyway, so it is useful but not reliable.
The actual client IP should be the left-most IP address in the header value. You can extract it into an environment variable using a regex:
SetEnvIf X-Forwarded-For "^(\d{1,3}+\.\d{1,3}+\.\d{1,3}+\.\d{1,3}+).*" XFFCLIENTIP=$1
Note the use of $1 to set the XFFCLIENTIP environment variable to hold the contents of the first group in the regex (in the parentheses).
As an example of using this, you can define a log format that uses the variable: this example is one we use internally at nearmap.com, so it logs extra information, but the bit you want is the %{XFFCLIENTIP}e at the beginning. Note the env=XFFCLIENTIP at the end of the line, which means this format is only used if the environment variable is set.
CustomLog /var/log/apache2/access.log "%{XFFCLIENTIP}e \"%{session}C\" \"%{nearmapuid}C\" %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" env=XFFCLIENTIP