Working in multiple locations with different test IP's - c#

So I am curious about people's solution to solve my problem. I work in different locations on one project and have different IP address (testing phase). Once completed I won't need this as I can throw to an exposed HTTP client endpoint.
My frustration is when I get to a new location and have to go through getting new addresses. Is there a simple pattern, solution to get the IP automatically and apply to my RESTSharp calls. ie
var client = new RestClient("http://192.168.0.0/API/getresult");
I would say this is common, but frustrating when you are showing a client progress but it crashes and need to re-apply corrections.

Related

How can I resolve a "NameResolutionFailure" error when trying to gather data from every type of internet connection?

I am currently using Httpclient and I can successfully gather my data with a specific network/internet-connection at the place that has the data.
However when I try to gather the data at home with another internet-connection I receive an "NameResolutionFailure" error.
My goal is to be able to reach the data from any type of connection but I am not sure what I am quite missing here. (I am also new in this area).
This is the code that I use when I talk to the db:
string dataurl = "my-url-here";
var http = new HttpClientHandler()
{
Credentials = new NetworkCredential("user", "password", "domain"),
};
var httpClient = new HttpClient(http);
try
{
var result = await httpClient.GetStringAsync(dataurl);
System.Diagnostics.Debug.WriteLine(result);
}
catch (HttpRequestException ex)
{
if (ex.GetBaseException() != null)
{
System.Diagnostics.Debug.WriteLine(ex.GetBaseException().Message); //this is where i recieve the NameResolutionFailure error
}
else
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
How come I can only reach the data when I am on a certain network and not with every network? Am I missing code or is there something else in play here?
Appreciate every help, tips, code-examples i can get!
The problem is likely to be in the string dataurl = "my-url-here"; and where that's accessible from. There are likely to be two obstacles:
Name resolution
Network Access
While your error message only mentions Name resolution, I'm guessing you'll need to do something about network access as well.
Name resolution (or DNS) is about translating a host name into an I.P. address.
When you're on a work network, there'll be a name resolution service that resolves local computer names to I.P. addresses on the network. Normally these local computer names are not visible to public DNS servers. If you connect your device to a different network (e.g. a mobile network), it uses the public DNS servers, which know nothing about the local domain named computers.
For example MyServer might resolve on your local network because it's part of your local domain, and the local network infrastructure will sort that out. MyServer.MyCompany.com is usually similar, as by default machines names aren't exposed externally.
For a mobile application, you're going to need a public domain name. Something like MyServer.MyDomain.com (or www.google.com is the same thing, essential). A public DNS server translates this name to an I.P. address.
This is probably where the problem you're experiencing is occurring. You're probably using a local host name, that the public DNS servers don't know about.
If you're working for an organisation they may already have a domain, or you may need to purchase a domain for your application.
In the meantime you could look at one of the dynamic DNS solutions that may allow you to progress for development purposes.
For my Xamarin app, I use the name of the local machine when I'm developing, and the mobile device is on the same network.
If I'm not on the same network, I have a VPN that I can use. This connects into the work network as if I'm on the same network. If I'm developing at home and both devices are on my home network, I use the I.P. address of my development box, because I haven't made local DNS work on my home wifi.
When we go to release we use a public URL, like api.MyApp.com - which public DNS points to our prod server.
Network Access might be a thing that you need to deal with too.
A major part of a Network Engineer's job is to keep the hackers out. When your mobile device is on the same network as the server (i.e. when it's working for you), this isn't a problem because because mostly networks are configured so that two devices on the same network can see each other. It sounds like this is the sort of network you have, if your app can see your server on one connection.
But if you're needing to connect to your server from a mobile network, you need a way to tell your network router to forward specific traffic from the internet to your server.
This gets complicated, but for development purposes, strategies I've seen work are:
A VPN - we have a VPN that I fire up on the mobile device, enter my work network credentials, and then I can access my development box as if I'm on the same network
Virtual server / port forwarding - if you're at home, you can probably configure your modem to forward a particular port to your development box. Every modem is different, so you'd have to search up instructions for your particular one.
Network Engineer - if you're in a corporate, and want traffic from outside to get to a server that you're managing (and don't have a VPN), you probably need to talk to your networks department. Good luck.

ASP.NET Request.ServerVariables yields local IP address not remote IP

Got an asp.net web page in c#. One thing we would like to do is track hits to the site including their IP address. I implemented some code (thanks to SO) but the logged IP address always seem to be local, ie: 192.168.x.x. I have tried it from a variety of devices, even my phone and Version MiFi just to make sure its not something weird with the ISP but the log always list the same 2-3 different internal ip addresses (seems to change a little as the day goes on).
Here is my function that gets the IP (again thanks to postings here on SO):
protected IPAddress GetIp(HttpRequest request)
{
string ipString;
if (string.IsNullOrEmpty(request.ServerVariables["HTTP_X_FORWARDED_FOR"]))
ipString = request.ServerVariables["REMOTE_ADDR"];
else
ipString = request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
IPAddress result;
if (!IPAddress.TryParse(ipString, out result))
result = IPAddress.None;
return result;
}
public void logHit()
{
IPAddress ip = GetIp(Request);
string sIP = ip.ToString();
}
I tried this as well which yields the same result:
HttpContext.Current.Request.UserHostAddress;
When I do a call on the client side using something like the service on appspot, it works just fine:
<script type="application/javascript">
function getip(json) {
//txtIP is a input box on the form
document.getElementById("txtIP").value = json.ip;
}
</script>
<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"></script>
I suppose I could do a round-about way by hitting that appspot link and parse it out but that seems like a whole lot of trouble for something that should be simple.
Could it be the IIS on the server? Some kind of redirect going on? The ip addresses logged are NOT the servers. The problem is I dont have direct access to it so I have to talk to the guys that admin it and would like to give them some direction before they just start changing things.
Thanks
Ernie
If the HTTP_X_FORWARDED_FOR header is truly supported, then I think this would not be either forward or reverse proxy server causing this, but more likely Dynamic Network Address Translation or Dynamic Port Address Translation, which is happening below the application layer on the TCP/IP stack and thus would not affect an HTTP request header.
There are many ways to configure NAT, most of which would not cause these symptoms, but it is certainly possible to configure NAT in a way that would present this problem. Dynamic NAT or Dynamic PAT would be two such examples, and I would suggest this is what you ask your network administrators.
For more on Dynamic NAT/PAT, with good examples, you could review: http://www.cisco.com/en/US/docs/security/asa/asa82/configuration/guide/nat_dynamic.html
In a typical NAT scenario, the request packets reach the NAT device (firewall or router) as:
FROM - 5.5.5.5 (public address of the client)
TO - 6.6.6.6 (the public address of the server)
The "typical" NAT configuration would rewrite only the destination, as follows:
FROM - 5.5.5.5
TO - 192.168.6.6 (the private address of the server)
In this typical case, the server would still see REMOTE_ADDR as 5.5.5.5, as that is the source address on the incoming request. Then, the packets would be returned to 5.5.5.5, and the response would return to the client successfully.
Now, in the case of dynamic PAT, for example, the request would reach the NAT device as follows:
FROM - 5.5.5.5
TO - 6.6.6.6
Then, the NAT device would rewrite both source and destination packets, maintaining this "dynamic" mapping for only the lifetime of the request:
FROM - 192.168.1.1:12345 (the dynamic PAT address)
TO - 192.168.6.6 (the private address of the server)
Now, when the server sees this request, it appears to be from private address 192.168.1.1. In fact, with a strict PAT all requests will appear to be from this address. In your case, there are 2 or 3 of these addresses, probably because you may have enough traffic that you risk running out of ports if you use only a single dynamic PAT address.
So, your REMOTE_ADDR is 192.168.1.1, because that is actually the source address on the request packets. There is no HTTP_X_FORWARDED_FOR, because the Dynamic PAT is occurring at a lower TCP/IP layer (address and not application).
Finally, the response is sent back to 192.168.1.1:12345, which routs to the NAT device, which for the duration of the request/response (see the Cisco documentation above) maps it back to 5.5.5.5, and then drops the "dynamic" mapping.
Everything worked perfectly, the client gets the response back, except that you have no idea of the actual client address from the viewpoint of the server. And if it is dynamic NAT in play, I don't see how you could get this information from the server.
Fortunately, you did exactly the right thing to get the information in javascript on the client, so this likely solves your problem as well as it could be solved.
It depends on your network structure. Simply a firewall or load balancer can change the variables which you are checking.
if you are using a load balancer check this:
How to get visitor IP on load balancing machine using asp.net
if your sever is behind a firewall check this:
Find if request was forwarded from firewall to IIS

How to ensure my C#.net "webservice" is always up in shared hosting

I have a c#.net wpf application which sends data to a webservice on daily basis.
I am planning to host my webservice on shared hosting.
My question is How to ensure my webservice is always up and running ? i.e What should I need to take care if my webserver is down for few days? Do I need to maintain multiple servers if one goes down another will be available ?
To acheive this do I need to mention both the servers ip addresses in wpf windows application?
I have searched google but couldnt find the correct answer.
Any links from the community will be appreciated.
i have two suggestions:
1. call a method of web service method and handle it with exception.
2. get the dynamic URL from section <applicationSettings> and then do a httprequest to check if url is valid or not
solution 1 example:
[WebMethod]
public DateTime GetCurrentServerTime()
{
return System.DateTime.UtcNow.ToString("yyyyMMddZHHmmss");
}
and in you application :
catch (System.Net.WebException ex)
{
messgabebox.show( "Your Web Service not available");
}
it cause about 10 seconds for a response ....
solution 2 example:
HttpWebRequest objRequest = (System.Net.HttpWebRequest)HttpWebRequest.Create(strWebServiceUrl);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)objRequest.GetResponse();
if (myHttpWebResponse.StatusCode != HttpStatusCode.OK)
{
DisplayMessage("Your Web Service not available" + "\r" + "Please try after some time");
return;
}
I think this is the better way to check for webservice availability..
The reason you haven't found an answer on google is that there is no correct answer. Everyone approaches these problems differently based on the needs of their application. To answer some of your questions, I can really only provide general suggestions and even those are just approaches I would take to solving this problem:
My question is How to ensure my webservice is always up and running ?
Maximizing uptime is important and can require careful design. You need to gracefully handle error conditions and be able to handle any input thrown at you. One caveat with this is that, while uptime is important, accuracy of your data may be more important. If this is the case, it may be better for your webservice to be down, than to appear to be up, but have it corrupting data.
What should I need to take care if my webserver is down for few days?
You need to code your client application in such a way that it can properly queue data up and send it when the service is back up. Also, you need to be smart in your service (i.e. not assuming that upload data == data date). Don't forget that the client application can be down for days at a time too (natural disaster, power outage, downtime for maintenace, crashing on a weekend...)
Do I need to maintain multiple servers if one goes down another will be available ?
To acheive this do I need to mention both the servers ip addresses in wpf windows application?`
That is definitely an option. Redundancy can allow you to perform maintenance on servers or upgrade while minimizing downtime. There are a lot of ways to approach this. I would probably use multiple FQDNs. So I would have server1.example.com and server2.example.com each pointing to a different server (ideally in a different data center). I would also have these servers have a very low TTL on their DNS entries, so I can swap out the servers to a new IP if they start going down.
Then in your client app, you can either round robin between the two servers or you can have a main server and the other just serves as a backup.
With all of that being said, the point many people forget about when setting something like this up is testing. You need to test one server coming down, both servers coming down, switching DNS and any other permutations you can think of to ensure your redundancy solution works, is scalable, and doesn't cause other issues.

Two unique named pipes conflicting and InvalidCredentialException

There are two problems I ran into last night which I have resolved now, but I am not 100% sure as to why what I have done has resolved them and was hoping maybe someone could offer some insight as I've been turning over a lot of rocks and have had no luck!
First Problem
The first issue is that I had two uniquely named pipes that were in two separate programs:
net.pipe://localhost/superuniquepipe1
net.pipe://localhost/superuniquepipe2
However, the second program to launch would throw an exception (I believe it was AddressAlreadyInUseException) when opening the ServiceHost due to the address already being in use.
The way I was instantiating these ServiceHosts was as follows:
Uri[] baseAddresses = new Uri[] { new Uri("net.pipe://localhost") };
this.host = new ServiceHost(this, baseAddresses);
this.host.AddServiceEndpoint(typeof(IHostType), new NetNamedPipeBinding(), "superuniquepipe1");
this.host.Open();
So I'd specify the base address of localhost first, and then specify the rest of it when adding the endpoint, the way I resolved this was to change the code as follows:
this.host = new ServiceHost(this);
this.host.AddServiceEndpoint(typeof(IHostType), new NetNamedPipeBinding(), "net.pipe://localhost/superuniquepipe2");
this.host.Open();
Am I correct in saying the reason this worked is because it was checking only the base addresses and not the endpoint I was trying to add? And is using the second code sample a valid / safe way to have multiple programs listening on "localhost"?
Second Problem:
In an attempt to fix the above, I had changed the base address from localhost to a number of different unique strings e.g. "net.pipe://rawrwhyisntthisworkingsadface", but when doing this I'd be presented with an InvalidCredentialException from the client trying to establish a connection (see below code)
I was under the impression a named pipe can literally be named anything, can anyone shed some light on this one?
ChannelFactory<IHostType> factory = new ChannelFactory<IHostType>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://rawrwhyisntthisworkingsadface/superuniquepipe2"));
IHostType proxy = factory.CreateChannel();
proxy.CallSomeMethodAndGetAnException();
Any input would be greatly appreciated, as I said I have resolved the issue and just want to know why my solution worked, but if you see a flaw in how I've resolved it and can suggest a better way of doing it please do so :)
Re problem 1:
The WCF NetNamedPipeBinding uses a named shared memory section to publish to its clients the actual name of the pipe over which the service can be called. The pipe name itself is a GUID, generated afresh each time the service host is opened. It is the name of the shared memory section used to publish the service which is dependant on the service URL. If a base address is defined, the base address is used to derive this name.
This means you can only ever have one WCF service application at a time running which uses a particular base address for its NetNamedPipe endpoints. If you try to start a second one, it fails with AddressAlreadyInUseException because it finds that the name WCF wants to use for the publishing location (derived from the base address) has already been taken by another application.
If you specify no base address, and give each service an absolute, unique service URL, then the name of the publishing location is now derived from the full absolute URL, and there is no name clash between the applications. This is an entirely valid and safe way to have multiple WCF named pipe services listening.
Re problem 2:
On the service side you can use anything for the host name part of the service URL. This is due to the HostNameComparisonMode setting applied by default in the NetNamePipeBinding, since the algorithm in WCF which derives the name for the shared memory publishing location substitutes a wildcard character for the host name see here to enable the configured host name comparison mode to be implemented.
On the client side, however, the service URL is constrained: the host part must genuinely resolve to localhost (i.e. it is localhost, the correct IP address, or the correct machine name).

Ping always succeeds, cant easily check uptime using ping on a url

Im getting frustrated because of OpenDNS and other services (ie: roadrunner) that now always returns a ping even if you type any invalid url ie: lkjsdaflkjdsjf.com --- I had created software for my own use that would ping a url to verify if the site was up or not. This no longer works. Does anyone have any ideas about this?
Requirements:
It should work with any valid web site, even ones i dont control
It should be able to run from any network that has internet access
I would greatly appreciate to hear how others now handle this. I would like to add, im attempting to do this using System.Net in c#
Thank you greatly :-)
New addition: Looking for a solution that i can either buy and run on my windows machine, or program in c#. :-)
Update:
Thank you all very much for your answers. Ultimately i ended up creating a solution by doing this:
Creating a simple webclient that downloaed the specified page from the url (may change to just headers or use this to notify of page changes)
Read in xml file that simply lists the full url to the site/pages to check
Created a windows service to host the solution so it would recover server restarts.
On error an email and text message is sent to defined list of recipients
Most values (interval, smtp, to, from, etc) are defined in the .config for easy change
I will be taking some of your advice to add 'features' to this later, which includes:
AJAX page for real-time monitoring. I will use WCF to connect to the existing windows service from the asp.net page
Download Headers only (with option for page change comparison)
make more configurable (ie: retries on failure before notification)
Wget is a nice alternative. It will check not only whether the machine is active, but also whether the HTTP server is accepting connections.
You could create a simple web page with an address bar for the website and some javascript that uses AJAX to hit a site. If you get any HTTP response other than 200 on the async callback, the site isn't working.
<html>
<head>
<script language="javascript" type="text/javascript">
<!--
var ajax = new XMLHttpRequest();
function pingSite() {
ajax.onreadystatechange = stateChanged;
ajax.open('GET', document.getElementById('siteToCheck').value, true);
ajax.send(null);
}
function stateChanged() {
if (ajax.readyState == 4) {
if (ajax.status == 200) {
document.getElementById('statusLabel').innerHTML = "Success!";
}
else {
document.getElementById('statusLabel').innerHTML = "Failure!";
}
}
}
-->
</script>
</head>
<body>
Site To Check:<br />
<input type="text" id="siteToCheck" /><input type="button" onclick="javascript:pingSite()" />
<p>
<span id="statusLabel"></span>
</p>
</body>
This code depends on the browser not being IE and I haven't tested it, but it should give you a really good idea.
To see if a service is up, not only should you ping, but it's good to have scripts that will hit a service, such as a website, and get back a valid response. I've used What's Up Gold in the past, rather than write my own. I like all the features in products like that. such as sending me a page when a service is down.
For the record, lkjsdaflkjdsjf.com is a hostname (which at the moment is not registered to anyone). ping does not work with URLs, ping works with hostnames. hostnames are looked up using the Domain Name System. DNS is supposed to fail when hostnames are not registered.
The problem is that some services (apparently your ISP, and definitely OpenDNS) do NOT fail DNS requests for hostnames that aren't registered. Instead they return the IP address of a host on their network that presents a search page to any http request.
You appear to want to know two things: Is the name real (that is, is there a host with this name registered to some actual machine)? and Is that machine functioning?
If you already know that the name in question is real (for instance, you want to know if www.google.com is up), then you can use ping because you know that the name will resolve to a real address (the ISP can't return their IP for a registered name) and you'll only be measuring whether that machine is in operation.
If you don't know whether the name is real, then the problem is harder because your ISP is returning false data to your DNS request. The ONLY solution here is to find a DNS server that is not going to lie to you about unresolved names.
The only way I can think of to differentiate between your ISP's fake records and real ones is to do a reverse lookup on the IP you get back and see if that IP is in your ISP's network. The problem with this trick is that if the ISP doesn't have reverse DNS info for that IP, you won't know whether it's the ISP or just some knucklehead who didn't configure his DNS properly (I've made that mistake many times in the past).
I'm sure there are other techniques, but the fact that DNS lies underneath everything makes it hard to deal with this problem.
Don't directly know of any off the shelf options in c#, although I'd be very suprised if there aren't a few available.
I wrote something similar a few years ago, don't have the code anymore cos it belongs to someone else, but the basic idea was using a WebClient to hit the domain default page, and check for a http status code of 200.
You can then wire any notification logic around the success or fail of this operation.
If bandwidth is a concern you can trim it back to just use a HEAD request.
For more complex sites that you control, you can wire up a health monitoring page that does some more in depth testing before it sends the response, eg is DB connection up etc.
Often a machine that is dead on port 80 will still respond to a ping, so testing port 80 (or whatever other one you are interested in) will be a much more reliable way to go.
I've found ping to be very unreliable just because of all the hops you're having to jump through, and something in between can always interfere.
Trying to open up an http connection with a web server is probably the best way to go.
You could try running 'httping' if you have cygwin available or
http://freshmeat.net/projects/httping/
As far as I can see, the problem here that OpenDNS resolves invalid domains back to themselves to forward you on to something close to what you're after (so if you typo ggooggllee.com you end up at the right place via a bounce from the OpenDNS servers). (correct me if I'm wrong)
If that's the case, you should just be able to check whether the IP you've resolved == any of the IPs of OpenDNS? No more ping - no protocol (HTTP) level stuff - just checking for the exceptional case?
If you tend toward the sys-admin solution rather than the programming solution you could install a local name server and tell it not to accept anything but NS records for delegation only zones. This was the fix I (and I assumed everyone else on the internet) used when Network Solution/Verisign broke this last time. I installed BIND on a couple of local machine, told my DHCP servers to hand out those addrs as the local name servers, and set up something like the following for each of the delegation only zones that I cared about:
zone "com" { type delegation-only; };
zone "net" { type delegation-only; };
Come to think of this, I think this might be turned on by default in later BIND versions. As an added bonus you tend to get more stable DNS resolution than most ISPs provide, you control your own cache, a little patching and you don't have to rely on your ISP to fix the latest DNS attack, etc.
i like CALM for this sort of thing as it logs to a database and provides email notifications as well as a status dashboard
you can set up a test page on the site and periodically do a GET on it to receive either a 'true' result (all is well) or an error message result that gets emailed to you
caveat: i am the author of CALM

Categories

Resources