Scott Forsyth's Blog

Postings on IIS, ASP.NET, SQL Server, Webfarms and general system admin.

Cloud Resources

IIS Resources

Creating a Reverse Proxy with URL Rewrite for IIS

There are times when you need to reverse proxy through a server. The most common example is when you have an internal web server that isn’t exposed to the internet, and you have a public web server accessible to the internet. If you want to serve up traffic from the internal web server, you can do this through the public web server by creating a tunnel (aka reverse proxy).

Essentially, you can front the internal web server with a friendly URL, even hiding custom ports.

For example, consider an internal web server with a URL of http://10.10.0.50:8111. You can make that available through a public URL like http://tools.mysite.com/ as seen in the following image. The URL can be made public or it can be used for your internal staff and have it password protected and/or locked down by IP address.

image

This is easy to do with URL Rewrite and IIS. You will also need Application Request Routing (ARR) installed even though for a simple reverse proxy you won’t use most of ARR’s functionality. If you don’t already have URL Rewrite and ARR installed you can do so easily with the Web Platform Installer.

A lot can be said about reverse proxies and many different situations and ways to route the traffic and handle different URL patterns. However, my goal here is to get you up and going in the easiest way possible. Then you can dig in deeper after you get the base configuration in place.

URL Rewrite makes a reverse proxy very easy to set up. Note that the URL Rewrite Add Rules template doesn’t include Reverse Proxy at the server level. That’s not to say that you can’t create a server-level reverse proxy, but the URL Rewrite rules template doesn’t help you with that.

Getting Started

First you must create a website on your public web server that has the public bindings that you need. Alternately, you can use an existing site and route using conditions for certain traffic.

After you’ve created your site then open up URL Rewrite at the site level.

image

Using the “Add Rule(s)…” template that is opened from the right-hand actions pane, create a new Reverse Proxy rule.

image

If you receive a prompt (the first time) that the proxy functionality needs to be enabled, select OK. This is telling you that a proxy can route traffic outside of your web server, which happens to be our goal in this case. Be aware that reverse proxy rules can be dangerous if you open sites from inside you network to the world, so just be aware of what you’re doing and why.

image

The next and final step of the template asks a few questions.

image

The first textbox asks the name of the internal web server. In our example, it’s 10.10.0.50:8111. This can be any URL, including a subfolder like internal.mysite.com/blog. Don’t include the http or https here. The template assumes that it’s not entered.

You can choose whether to perform SSL Offloading or not. If you leave this checked then all requests to the internal server will be over HTTP regardless of the original web request. This can help with performance and SSL bindings if all requests are within a trusted network. If the network path between the two web servers is not completely trusted and safe then uncheck this.

Next, the template enables you to create an outbound rule. This is used to rewrite links in the page to look like your public domain name rather than the internal domain name. Outbound rules have a lot of CPU overhead because the entire web content needs to be parsed and updated. However, if you need it, then it’s well worth the extra CPU hit on the web server.

If you check the “Rewrite the domain names of the links in HTTP responses” checkbox then the From textbox will be filled in with what you entered for the inbound rule. You can enter your friendly public URL for the outbound rule. This will essentially replace any reference to 10.10.0.50:8111 (or whatever you enter) with tools.mysite.com in all <a>, <form>, and <img> tags on your site.

image

That’s it! Well, there is a lot more that you can do, this but will give you the base configuration. You can now visit www.mysite.com on your public web server and it will serve up the site from your internal web server.

You should see two rules show up; one inbound and one outbound. You can edit these, add conditions, and tweak them further as needed.

SNAGHTML325382fc

One common issue that can occur without outbound rules has to do with compression. If you run into errors with the new proxied site, try turning off compression to confirm if that’s the issue. Here’s a link with details on how to deal with compression and outbound rules.

I hope this was helpful to get started and to see how easy it is to create a simple reverse proxy using URL Rewrite for IIS.

Posted: Oct 24 2013, 01:18 PM by OWScott | with 14 comment(s)
Filed under: , , , ,

Comments

Raymond Yu said:

Hi Scott,

Great article about reverse proxy and url rewrite.

I am stuck at an issue with url rewrite across different app pools so I posted it in IIS forum below:

forums.iis.net/.../1203163.aspx

any suggestions and comments? thanks!

# October 28, 2013 5:02 PM

OWScott said:

Hi Raymond,

It looks like there's a good reply to that forums post already. Thanks for asking, and glad to see that you're good.

# November 1, 2013 5:17 PM

Vasily said:

Hi Scott. I have troubles with configuring proxy to WebDav.

My scenario:

Server1 - IIS, ARR.

Server2 - IIS, WebDav

Client - standart Windows WebDav client.

I need to conect to Webdav on Server2 through Server1 using https.

Traffic between Server1 and Server2 must be non-secure (http only).

Client has a normal connection to the first folder

https://server1/firstfolder

but when I try to navigate to other folder (https://server1/firstfolder/otherfolder)ARR is rewriting url to Server2 as server2/.../otherfolder

How can I fix it?

# November 7, 2013 7:42 AM

OWScott said:

Hi Vasily,

Good question. It sounds like WebDAV wants its real URL and is causing a redirect. You can probably change that with an outbound rule that updates the RESPONSE_LOCATION tag. Here's an example outbound rule that may do the trick:

<rule name="Updating location redirect">

   <match serverVariable="RESPONSE_LOCATION" pattern="(.*)server2(.*)" />

   <action type="Rewrite" value="{R:1}server1{R:2}" />

</rule>

Also, consider installing ARR Helper to help with WebDAV through ARR: weblogs.asp.net/.../using-webdav-with-arr.aspx

# November 8, 2013 10:21 AM

patiawn said:

Hey Scott,

thanks for great tutorial on creating reverse proxy. Was looking for something similar a while ago. =)

# November 11, 2013 11:41 AM

Nilesh Panchal said:

Hi,

I have a requirement to do URL rewriting from IIS 7.5 to Apache server

on IIS I have a website

www.mydomain.com

On the same machine I have apache web server installed which serves thru port 8080 and URL for that is

www.mydomain.com:8080

My requirement is if any request comes to port 80, it should be redirected to 8080 with appended query string..

For Example,

www.mydomain.com/portal/somename.ext?id=1002

should be redirected to

www.mydomain.com:8080/portal/somename.ext?id=1002

Can some one guide me on this?

# January 10, 2014 11:19 PM

Markus said:

Hi,

I've tried to follow this tuorial to setup the following: domain.tld/blog should be proxied to blog.domain.tld, as I have to integrate a WordPress blog running on a remote Apache.

Problem: whatever I'm entering in the input fields I get a validation error (see http://imgur.com/OlEopjb).

System:

Windows Server 2012 R2

IIS 8.5

URL Rewrite 2

ARR 3

Please help me to figure that out (it should be possible after all, right?) :)

# January 11, 2014 10:51 AM

OWScott said:

Hi Nilesh,

The querystring should pass through with the default rules, and the rules created with the wizard. Have you had a chance to try it out yet? And if so and it doesn't pass through the querystring, what do you see? One possibility is that there is another redirect on the server that causes the querystring to get lost.

# January 13, 2014 10:21 PM

OWScott said:

Hi Markus,

That wizard wants just a domain name without the trailing dot. A port is ok, but that's about it.

While your domain name is actually more accurate from a DNS perspective than one without the trailing dot, it doesn't work for that wizard. URL Rewrite's HTTP_HOST doesn't use a trailing dot either.

You can edit the rules after they are created to add more filtering for different paths and such, but to get the base rule, it's best to make it a simple domain name and port.

# January 13, 2014 10:27 PM

Pleo said:

Is it possible to use IIS to reverse proxy SSL.

Ideally I would like IIS to sit in a DMZ. I would like it to only listen on 443 with SSL.  

I have another java application server, on an internal net that also is encrypted using ssl.

I want to expose that application server using the IIS reverse proxy in the DMZ.

What I'm concerned about is how to avoid browsers complaining about a man-in-middle

Is is possible to have both servers encrypted with ssl, and reverse proxy the internal server?

Would the ssl certs need to be the same?

I think you can see my confusion

# January 29, 2014 12:17 PM

OWScott said:

Hi Pleo,

Yes, the way to do this is to add a valid cert on the IIS box that matches the public domain name. That's the handshake that the client will have so it won't notice the man in the middle.

The the IIS box will use a fresh SSL handshake between it and the Java application server.

So the IIS box needs a friendly domain name, a cert to match, and an IIS binding to match those. Then you should be set.

# January 29, 2014 8:56 PM

Rick Rajewski said:

Can this approach work with a public IIS server that is responding to root domain requests using subfolders, instead of subdomains?  For example, we want to have www.mydomain.com point to a public IIS server and have www.mydomain.com/blog to point to an Apache web server.

# January 30, 2014 6:16 PM

OWScott said:

Hi Rick,

Yes, this is supported well. That's called Layer 7 routing when it routes by parts of the URL like that. URL Rewrite rules can handle a whole combination of patterns, and you can then direct the request to different back end servers or server farms.

To do this, simply create a rule but make it more specific. For example, to route /blog to the Apache web server, enter "^blog(.*)" for the Match URL Pattern and use {R:1} in the Action path. That will only direct traffic that starts with /blog to the Apache server.

# February 1, 2014 12:32 PM

Nicola said:

Great article, without outboundRules, my application links redirect to internal web app!!!!!

# February 19, 2014 11:11 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)