A reverse proxy with IIS and URL Rewrite

I recently had to install and configure a reverse proxy using IIS and the URL rewrite extension. At first glance it seemed a pretty straight forward task to set up target location for the redirection, but it turned out not being as simple as that.

Step 1: understanding what URL rewrite do

URL rewrite is an IIS extension that can be downloaded here: http://www.iis.net/downloads/microsoft/url-rewrite Basically, it allows the rewriting of any URI on the fly (hence the name) in both directions (inbound and outbound). As such, it is a great tool for a reverse proxy, when all you want is to forward the request made to http://www.proxy.com/domain/soft1 to http://soft1/ for example. Each request follows the sequence diagram described in Figure 1.

URL Rewrite - Fig1

Figure 1 URL rewrite in action

So, in order to set up a proper redirection, you basically have two things to do:

  1. Set up the inbound rules, that will translate the public address of you service (here http://www.proxy.com/domain/soft1 ) to your internal address (here http://soft1)
  2. Set up the outbound rules that will correct relative and absolute links in the soft1 server answers so that they can be requested by the client

In both cases, a rule is nothing but a glorified way to do a String.Replace in the request/response.

Step 2: writing inbound rules

Inbound rules are here to translate the request coming from the client, using a publicly available address, to a request going to an internal and not exposed server, while preserving the part of the request that does not need translation.

URL Rewrite - Fig2

Figure 2 Inbound rule sample

  There are some key points:

  • In a great majority of cases, you want to set the HTTP_ACCEPT_ENCODING server variable to blank. This is because you’ll probably have to write outbound rules to rewrite the links in the responses. And you cannot do that if the response is compressed, so better remove the “gzip/deflate” flags from the accept_encoding part of the header, right? Note that, in order to be able to replace a server variable, you have to register it in the, guess what, View server variable screen.
  • While the default pattern (which is ^/(.*)) is sufficient in the vast majority of cases, you may have to deal with some mechanism that needs other pattern (such as the ASP.Net forms authentication mechanism and its returnurl parameter). In this case, you’ll have to write several rules: one for each of the particular cases, using a specific pattern (for ASP.Net it will be something like ^/(.*)\?returnurl=/(.*)\?(.*)) and finally the catch-all rule. Do not forget to set the Stop processing of subsequent rules flag on each one!
  • Do not forget that you are not limited to rewrite to a site root. You can, for example, redirect to http://soft1/Appli/{R:1} or even pass the input URI as a parameter such as http://soft1/query.aspx?uri={R:1}
  • If you specify explicitly the http:// prefix in the rewrite URL, you effectively add SSL offloading to your reverse proxy. If you want to keep the encryption, you have to add a condition on {CACHE_URL} with pattern ^(https?):// and start the rewrite URL by {C:1}://

Step 3: Writing outbound rules

Outbound rules are here to modify the response sent by the server so that the links within point to your reverse proxy instead of pointing to the real server. That concerns absolute links (change http://soft1/icon.png to http://www.proxy.com/domain/soft1/icon.png) or relative links (change /icon.png to /domain/soft1/icon.png) Why is that needed? Well, consider what will happen if you don’t do it:

  1. The client request http://www.proxy.com/domain/soft1
  2. Inbound rule triggers and rewrite it to http://soft1/
  3. The soft1 server answers with an http page containing a <img src= »/icon.png »/>
  4. The client request http://www.proxy.com/icon.png
  5. 404 – page not found !

So basically, unless you have a single page application, you’ll need to rewrite some links. And that’s why there are outbound rules!

 URL Rewrite - Fig3

Figure 3 Outbound rules samples

 As for inbound rules; some key points:

  • You’ll need at least one rule for relative paths (pattern ^/(.*)) and one for absolute paths (pattern ^http://soft1/(.*))
  • You can rewrite absolute path to relative ones. For example, translating ^http://soft1/(.*) to /domain/soft1/{R:1}
  • By default, a rule works only in the defined tags within the body of the response. If you do not specify a tag, it does a global search and replace, which is useful if you need to change the content of a javascript variable, for example.
  • If you want to be able to rewrite 30x responses (redirect/rewrite), for example to be able to chain reverse proxies, you’ll have to add a rule with replace the server variable RESPONSE_Location

Livre Blanc Cell'insight 1 DevOps

8 Commentaires Laisser un commentaire

Can the « url » in an action contain uppercase?

Note: MyApp is uppercase as the application server (i.e. Tomcat) is URL case sensitive.

Répondre

Hello! Could you explain more, what does modify content of web page in server? Is it ASP.NET application?

Répondre

And how fast does it work? If 500 clients request server per second?

Répondre

Hi, we have problem with the access to backend service in https://backend:8080

502 – Web server received an invalid response while acting as a gateway or proxy server

This is my web.config

Répondre
Mick Philippon
Mick Philippon
février 13, 2017 15:45

Unfortunately, your web.config content didn’t make it past the anti-spam filter…

Répondre

Thank you very much, it works fine. The redirect from external request to internal and from the internal response to external works very fine. But I would have the redirect only for authenticated user it is possible?

I think it could done with SSL certificates, is it right? But I have not created any certificates yet.
Can I create the certificates with the IIS?

A other solution would be adding basic authetification for the site, but where can I set the users and the passwords? I wouldn’t like to create for each user a windows account.

Perhaps someone here can give me an approach?

Répondre
Mick Philippon
Mick Philippon
février 13, 2017 15:49

You could use filter to redirect only URi accessible once authentication has been performed, but I would advise against it. The purpose of a reverse proxy is not to handle authentication request, but to allows you to expose internal services without exposigin your internal infrastructure.
Authentication is best handled through ‘standard’ processes, such as OAuth, AD Authentication or any other mean.

Regarding SSL, URL Rewrite can do either SSL offloading (meaning it decrypts the content which is then send unencrypted in your internal network), SSL rewriting (decrypting the content using your public certificate and encrypting it using a private one) or SSL throughput (doing nothing at all). You need to decrypt the content if you plan to rewrite part of it (which is almost mandatory), so as your internal network is already protected, you’ll probably better off doing SSL offloading.

Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *