Proxying a VPN

Topics: Developer Forum, User Forum
Nov 10, 2011 at 9:52 AM
Edited Nov 10, 2011 at 9:52 AM

Hello all,

I'm a relative newbie to IIS 6.0 and an absolute newbie to IIRF. I have the following problem and I'm a bit stumped, I would be grateful for some help.  It is a one-time problem, really, so I can't really afford to spend days or weeks on getting to know all the ins and outs of IIRF however great the product may be...

We have a IIS 6.0 server running on Windows 2003 32-bit.  This server is exposed to the internet and can be accessed through and we have several virtual directories (as in

We also have, on a remote location, a small https server that can only be reached through a VPN tunnel (hamachi, IP address range Our web server is a member of this vpn so it can actually see the remote server.

What I'd like to achieve, is that our public server acts as a proxy so that users from the internet can access our remote vpn server though a virtual directory. So that all requests directed to "" are transparently modified (RewriteRule ???) and sent through the remote server down the vpn tunnel. BTW, the remote server also uses a virtual directory, it looks like https://ip-address/myapp.

Is this possible using IIRF?  And can somebody PLEASE show me a small example?

Thanks in advance,


Nov 10, 2011 at 3:47 PM
Edited Nov 10, 2011 at 3:50 PM

Yes Arthur, it's possible.

You need to use the ProxyPass directive. It's described in the IIRF documentation, and there are lots of examples.



Nov 14, 2011 at 8:23 AM

Well, it's certainly not working for me. Whenever I call our virtual directory, all I get is a html error message "12175 (0x00002f8f)" instead of the login screen of our remote webservice. This remote webservice was written using Atozed Intraweb, by the way.


This is the iirf.ini that I wrote, following the example (the IP address is fake):

RewriteLog c:\logs\iirf
RewriteLogLevel 1
IterationLimit 10
MaxMatchCount 10
RewriteEngine ON
StatusInquiry ON
ProxyPass          ^/(.*)$
ProxyPassReverse   /


This is what the logfile says:

Mon Nov 14 09:20:34 -  4012 - -------------------------------------------------------Mon Nov 14 09:20:34 -  4012 - Ionic ISAPI Rewriting Filter (IIRF) x86 RELEASEMon Nov 14 09:20:34 -  4012 - IIRF was built on: Oct 26 2011 20:40:58Mon Nov 14 09:20:34 -  4012 - Cached: DLL_PROCESS_ATTACHMon Nov 14 09:20:34 -  4012 - Cached: Process ID: 2556Mon Nov 14 09:20:34 -  4012 - Cached: DLL_PROCESS_ATTACH - completeMon Nov 14 09:20:34 -  4012 - Cached: GetFilterVersionMon Nov 14 09:20:34 -  4012 - GetLogFile: app:'/LM/W3SVC/1/Root/test'  new log:'c:\logs\iirf.2556.log'Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: actual log file 'c:\logs\iirf.2556.log'Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: ini file: 'C:\GEO-data\test\Iirf.ini'Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: ini file timestamp: 2011/11/14 08:51:59 Romance Standard TimeMon Nov 14 09:20:34 -  4012 - ReadVdirConfig: cfg(0x012746F8)Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: LogLevel = 1Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(8): IterationLimit 10Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(9): MaxMatchCount 10Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(10): RewriteEngine will be enabled.Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(11): StatusInquiry ON (--) (--)Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(11): IIRF Status Inquiry is enabled at path '/iirfStatus' for local requests only.Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(17): ProxyPass (rule 1)  '^/(.*)$'  ''   (null)Mon Nov 14 09:20:34 -  4012 - ReadVdirConfig: C:\GEO-data\test\Iirf.ini(18): ProxyPassReverse   / Nov 14 09:20:34 -  4012 - ReadVdirConfig: Done reading INI for vdir(/test), found 1 rules (0 errors, 0 warnings) on 21 lines, in 1 modulesMon Nov 14 09:20:34 -  4012 - Iirfproxy: SslStatusCallback: stat(0x0104F280) len(4) e[0]=00000008 e[1]=01DD0000 e[2]=00000000 e[3]=00000010Mon Nov 14 09:20:34 -  4012 - IirfProxy_TryRelayEmptyBodyRequest: Error in WinHttpSendRequest(): 12175

Nov 15, 2011 at 5:07 PM

The number 12175 is ERROR_WINHTTP_SECURE_FAILURE, which indicates an error in the SSL layer.

WinHttpSendRequest will fail with that error when there is a problem with the SSL configuration. The way SSL works - when a client sends out a request over SSL, the server replies with a certificate that is signed by a certifying authority (CA).  The 12175 error indicates a revoked certificate, an untrusted CA, a mismatch between the certificate and the hostname, or some other similar SSL misconfiguration problem.  In Windows, you can manage the trusted CA list via the certmgr.msc control panel applet. In windows7 I believe there is a certutil tool you can use from the command line.

Often people install the certificate for the target server into the trusted CA list for a user account on the server, and then test it by running IE on the server to verify SSL connectivity with the target. Based on that successful outcome, they conclude that everything in the HTTPS flow from the IIS server to the desired target of the proxy is "working fine." But when executing a ProxyPass, IIS/IIRF does not use a user account to send out the HTTPS request.; it uses the IIS account. The IIS account is the one that needs the CA of the target host on its trusted CA list.  To check this, start mmc.exe, load the certmgr.msc and select "machine account"; then install the required CA.

See this discussion for a previous incident of this situation.

I will include this information in the IIRF documentation. Not sure anyone reads it, but at least I can document it.


Nov 15, 2011 at 5:08 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Nov 17, 2011 at 8:46 AM
Edited Nov 17, 2011 at 8:55 AM

HTTPS (self-signed certificate) appears to be only a minor part of the problem so I continue inside this thread.

I've re-configured one of the Intraweb websites that I want to proxy to use http instead of https just to see if it works now without the certificate problem. But it doesn't.

This time it's the user authentication that fails (or rather, it keeps asking for the password).  I set RewriteLogLevel to 5 in the iirf.ini and I see that the website uses cookies, could that be the problem? The "path" in the cookie appears to be that of the website behind the proxy rather than that of the proxy. Shouldn't it be replaced by IIRF also?

The line in the logfile looks like this:

Set-Cookie: IntraWeb_logviewer=0ymnjkz1mv7wkc1gbe76s1bsalpc_0; path=/logviewer/logviewer.dll/0ymnjkz1mv7wkc1gbe76s1bsalpc/; expires=Sat, 19 Nov 2011 08:33:27 GMT


The virtual directory on the proxy server is "/test", so shouldn't the string "/logviewer/logviewer.dll"  in the cookie be replaced by "/test" and vice versa? And if yes, how do I set that up (I'm a total newbie!) ?


I tried out a different product (octagate) and it does work with my Intraweb websites. No idea how they do it. Only - Octagate is a standalone application which does not integrate inside IIS so it's no solution for me.

Nov 17, 2011 at 6:58 PM
Edited Nov 17, 2011 at 7:03 PM

1. First Up

Well no, just to be clear: HTTPS is not (or was not) a "minor" part of the problem.  HTTPS was THE problem exhibited in the logfile you sent earlier.  It may be true now that you have reconsidered your use of HTTPS and decided you do not need it in this case. Regardless, incorrect configuration of HTTPS was in fact the reason for the failure of your original attempt to proxy a request with IIRF.

Now, having removed HTTPS from the system, you see another, different failure, which , like the original problem, prevents the proxy from succeeding. But that does not mean that HTTPS was not the problem, originally.


2. About proxies

Regarding your current problem, Proxying can be tricky.

2.1 Simple cases

In the simplest case, a browser makes a request, the proxy (IIRF) relays the request to a different target server, then relays the response to the original requestor.  This is easy.

2.2 Hostnames in the response headers

In some cases, there are ways for the hostname of the proxied site to leak into the response.  This happens if the response sets one or more of the following http response headers: Location, Content-Location, or URI.  This usually breaks the proxy transaction, because the target of the proxied request is inaccessible to the original requestor.  To handle this slightly more tricky case, you need to use a ProxyPassReverse directive; this tells IIRF to do the appropriate substitution of hostnames. Then, when the original requestor trues to access those URLs, it goes through the IIRF proxy, as necessary.  This takes care of 80% of the issues in proxied requests.

2.3 Hostnames Embedded in URL references

There are other ways the hostname of the proxy target can leak into the response. For example, an anchor tag generated by the proxied server may hard-code a hostname. (<a href='http://foo/bar'>).  This may also happen with links to stylesheets, scripts, and other assets.  Once again, this will break proxied transactions, because the hostname is not accessible to the original requestor. The way to correct this is to remove hard-coded hostnames from the generated response.

2.4 Absolute and relative URL paths

Your problem is an example of a different category of issue in proxy operations - that relating to URL paths.  In many cases a URL is specified without a hostname - this is normally how a generated page would refer to required CSS stylesheets, related pages, scripts, images, and so on.  URL's for any of those assets can use absolute or relative paths. an absolute path begins with a / and includes the complete URL path. To resolve such a path, user agents prepend the hostname and scheme used for the page.

For example, imagine a script tag in the HTML like so:

     <script src="/js/Impression.js"></script>

This is an absolute path - it begins with a slash.  Suppose this page was requested as

The resulting URL for the Javascript asset is:

Now, suppose the page containing that script tag was requested from

Notice the URL path in the original request includes an extra segment.  In that case the resulting URL for the Javascript asset is THE SAME.

In contrast, a relative URL path does not start with a / .  To resolve such a path, user agents prepend the scheme, hostname, and current relative path.

In the above example, supposing the script tag is constructed like this:

     <script src="js/Impression.js"></script>

(no leading slash)

Then the resulting URL for the javascript will be  ==>  ==>

In other words, the URL path used to request the page, affects the resolved URLs for assets with relative URLs.


3. Proxied requests and Relative URL paths

When using IIRF (or any transparent HTTP proxy) to proxy requests, it is possible to modify the scheme, host, and/or URL path. For example, suppose there is a resource available at HTTPS, at host  The normal full URL would be:

You could configure IIRF to expose that restricted resource through a transparent (Reverse) proxy, so that requests to

...get proxied to the restricted Resource.aspx on the internal network.

In this case the proxy transaction modifies the scheme (https --becomes--> http), the hostname ( ---becomes--->, and and the resource name (Resource.aspx ---becomes--> Something.aspx).  But the URL path to the resource remains unchanged (/Restricted).

When the path is unchanged, it means that relative URL references in the response that flows through the proxy all still "work" without modification or intervention. (See section 2.4 above)

On the other hand it is also possible for administrators to specify a ProxyPass directive that modifies the URL path, as well as the scheme and hostname. For example you could specify a rule to proxy


In this case, any relative paths that are included in the response that flows back through the proxy, will not work properly. I hope it's clear why. If not, read section 2.4 of this message again.

Your rule

ProxyPass ^/(.*)$

..does this.  It changes the URL path of the request.

There are ways to get around the problem of broken relative URL references when the URL path changes.  A simple way is to *also* proxy the secondary requests that are generated from relative URL references.  These are requests for scripts, images, and so on, that use a relative URL. This is often pretty straightforward to do with another ProxyPass rule, or a more general ProxyPass rule.

If you have a good understanding of when and where relative URL references appear in the HTTP response, it's easy to craft the proxypass rule to handle them. IF you don't have a good understanding, then you can hook up Fiddler and you can see the requests flowing through to IIRF, and you will easily see which secondary requests need to be proxied.

4. Proxies and Cookies

Your problem is a slightly different wrinkle of that situation. In your case the relative URL path appears in the Cookie, not in a URL reference.

The actual page thinks it is running at a URL path of /logviewer, but you've proxied it so that the path that is apparent to the browser is /test. On a successful login, the actual page injects a cookie with the path it knows about: /logviewer, and the browser stores and retains that cookie.

When the browser sends its next request, it *believes* it is sending the request to /test/Something , which means it also sends along Cookies designated for the URL path /test .  Meanwhile, the actual cookie the browser received is rooted at the /logviewer path. Because the /logviewer label on the cookie doesn't match the /test path in the request, the browser does not send out that Cookie with the followup request.  The result is the server on the other side of the proxy sees no cookie, and thus concludes there is no prior state held by the browser, and so asks the browser to login again.  This is the symptom you're reporting.

Because the path is attached to a cookie, the mitigation I described above - just making sure that IIRF also proxies the script and image requests and so on - will not apply.  A cookie with a wrong path won't result in a request through to IIRF, so there's nothing you can configure in IIRF to make things right, when the Cookie path is wrong.

There are some ways I can think of to avoid this problem:

 1. Don't use cookies with relative paths when proxying requests

 2. The server can be smart about setting cookies, examining the Via header, which indicates how the incoming request was proxied.  This requires modification of the target server, in your case the /logviewer app.

 3. Don't modify the URL path of requests across proxies

Avoidance #3 is probably easiest in your case. Instead of using /test, use /logviewer in the public, exposed URL.

ProxyPass ^/test/(.*)$1

ProxyPass ^/logviewer/(.*)$1

5. Getting IIRF to do the work

It may be possible to modify IIRF to do this work intelligently - in other words to examine the response that flows back for the presence of a Set-Cookie header. If one is found, IIRF could modify the path of the cookie (if present) to the path used for the public, external request.

Upon quick consideration, this seems like a relatively benign change, and it should be simple to implement. I'll need to think about it further, though, before I am ready to conclusively say it will be easy and benign.

For now you have a way to get things to work without that change.

Nov 17, 2011 at 7:04 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.