tags:

views:

409

answers:

2

Looking for a way to issue an HTTPwebrequest, or use the browser control, or winhttp to make a request to a URL, but override the IP address it connects to from the DNS lookup to a specific one.

Trying to do something similar to the HOSTS file, but programatically without having to modify this file. It can be C# or C+

Why I need it, the host i am sending the request has multiple IPs, and their Domain servers are doing load balancing accross the different IPs. Trying to force the request to a particular IP, but I need the host in the http request to be still the original host. I need this programatically because changing the host file every time i need to run this test is too time consuming.

+1  A: 

If I understand correctly you have to make an http request to a web server using virtualhosts but the DNS isn't setup yet so you have to specify the ip address in the url but send something else in the Host: header.

If that's the case you may be able to do so..

In C# using WebProxy:

Here's the code I would use if I have my server running on 67.223.227.171:8888 but I need to have www.example.com in the Host: header.

System.Net.WebRequest r = System.Net.WebRequest.Create("http://www.example.com");
r.Proxy = new WebProxy("http://67.223.227.171:8888");

See this link

In C++ using WinHttp:

Using WinHttp you can simply set the Host: header with WinHttpAddRequestHeaders.

So once again if I have my server running on 67.223.227.171:8888 but I need to have www.example.com in the Host: header:

#include <windows.h>
#include <winhttp.h>
#include <assert.h>

int main() {
  HINTERNET hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0", 
                                    WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                                    WINHTTP_NO_PROXY_NAME, 
                                    WINHTTP_NO_PROXY_BYPASS, 0);

  assert(hSession != NULL);


  // Use WinHttpConnect to specify an HTTP server.
  HINTERNET hConnect = WinHttpConnect( hSession,
                             L"67.223.227.171",
                             8888,
                             0 );

  assert(hConnect != NULL);

  // Open and Send a Request Header.
  HINTERNET  hRequest = WinHttpOpenRequest( hConnect,
                                 L"GET", 
                                 L"/downloads/samples/internet/winhttp/retoptions/redirect.asp", 
                                 NULL,
                                 WINHTTP_NO_REFERER,
                                 WINHTTP_DEFAULT_ACCEPT_TYPES,
                                 0 );

    assert(hRequest != NULL);

   BOOL httpResult = WinHttpAddRequestHeaders(
                                  hRequest,
                                  L"Host: www.example.com",
                                  -1L,
                                  0);

   assert(httpResult);

  httpResult = WinHttpSendRequest( hRequest,
                                   WINHTTP_NO_ADDITIONAL_HEADERS, 
                                   0,
                                   WINHTTP_NO_REQUEST_DATA,
                                   0,
                                   0,
                                   0 );

  assert(httpResult);

  httpResult = WinHttpReceiveResponse( hRequest, NULL );

  assert(httpResult);
}

Edited: The class name is WebProxy. Added C# sample code. Added C++ sample code.

Alexandre Jasmin
@Alexandre - just tried this - it looked like a pretty novel approach (note in the article he corrects his use of "CustomWebProxy" and says it should just be "WebProxy"). However, it doesn't seem to work - the request still seems to have the original host header. I may be wrong - you can't easily use Fiddler to debug this as Fiddler works by setting a proxy (which this solution specifically overrides). However, having used a tcp packet sniffer it doesn't look like it works. Shame really.
Rob Levine
I've edited my post. Is that of any help? I seem to get the correct header here.
Alexandre Jasmin
+1 - I've had a second go - and I think you're right - this does seem to work. Also - good spot on making it "Fiddler debuggable" by setting the proxy to be the Fiddler proxy. Obvious but I just missed it :) Very neat trick this.
Rob Levine
thanks, i will give this a try
httpresearcher
is there something similar for WINHTTP?
httpresearcher
@httpresearcher looks like it. I've added another sample.
Alexandre Jasmin
A: 

I think you are saying that you want to be able to override the ip address for a given host, without changing the host header.

For example, news.bbc.co.uk maps to IP address 212.58.226.139, but you want to be able to map this to another ip address, while still presenting the same news.bbc.co.uk "Host" http header to the overriden address. This is what you'd acheive by overriding the HOSTS file as you say, which is slightly different to Jason's answer as his won't present the original "Host" http header.

I don't believe you can do this easily (although I'm about to experiment to find out!). Certainly you can't do the following:

var request = (HttpWebRequest) WebRequest.Create("http://192.168.1.1");
request.Headers["Host"] = "news.bbc.co.uk";

as this will fail with an error saying you can't modify the "Host" header.

You probably can do it if your are willing to go down a level below the HttpWebRequest and deal at a more TCP level, but I'm not sure how you'd approach it without going down to that level.

[Edit]: Having played around with various approaches of overriding HttpWebRequest and WebHeaderCollection, I'm pretty sure it can't be done this way. However, Alexandre Jasmin's answer seems to be the solution.

Rob Levine