33

I've written my own managed IIS HTTP-module in C#. It's purpose is to simply set X-Forwarded-For and X-Forwarded-Proto request headers on some condition (which can not be handled with routing rules). The module must be deployed to our load balancer (which is none other than IIS with installed ARR and configured server farms). For some reasons the headers are set but are not transmitted to the web servers behind the load balancer. I know it because I checked the Failed Request Tracing output logs. Failed Request Tracing logs

And here is a screenshot of all the IIS Modules installed on our load balancer:

Ordered module list

As you can see my managed module called "QA.XForwardedHeadersModule" is loaded before the ApplicationRequestRouting (ARR) native module. But the headers aren't transmitted anyway. I even traced my requests with Wireshark. There aren't any X-Forwarded headers at all.

Does it mean that managed modules are not fully compatible with native modules and native modules (like ARR) can not see request headers set with managed modules (like my custom written module)? Is there any possible workaround to this problem?

Dobby007
  • 1,229
  • 1
  • 12
  • 22
  • Is there a priority order that you define or this is automatically done by IIS? possible that you are late in the game for changing/appending headers by any chance? – Tarun Lalwani Dec 29 '17 at 17:37
  • @TarunLalwani, no. As I noted in my question the order is ok. You can see it on the screenshot of the ordered module list I attached. My module is loaded before ARR. – Dobby007 Jan 01 '18 at 20:26
  • Don't know if this is flexible enough for you but supposedly you can just write URL rewrite module rules to set the headers for you: https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/url-rewrite-module-20-configuration-reference#Setting_Server_Variables – zaitsman Jan 02 '18 at 01:47
  • @zaitsman, no, rewrite module rules are not enough for me (I told about it in the question also). There is a quite large stuff of logic beyond this "setting of headers" which can grow in the future furthermore. So it will not be the best solution (it will look like a dirty workaround) to do it in the terms of routing rules. – Dobby007 Jan 02 '18 at 10:51
  • @Dobby007 this here is a bit of a long shot, but from quick googling it seems that you can try to 1) Declare some server variables in the url rewrite with dummy values 2) reset these in your module using reflection like so: https://forums.asp.net/t/1125149.aspx?Adding+servervariables According to the same article i referenced above, these should be forwarded to your backend. – zaitsman Jan 02 '18 at 11:21
  • @zaitsman, and how does it relate to my question? Server variable and HTTP header are different things. – Dobby007 Jan 02 '18 at 11:39
  • @Dobby007 According to the document i referenced above: https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/url-rewrite-module-20-configuration-reference#Setting_Server_Variables, `The request headers are set by using the same mechanism as for server variables, but with a special naming convention. If a server variable name in the collection starts with "HTTP_" then this results in an HTTP request header being set ` So yes, they are related – zaitsman Jan 02 '18 at 12:15
  • @zaitsman, yes, I knew it. It's just a rule for the rewrite module configuration to set headers and it works. But how can it help me? The problem is not that my headers are not set. They are set successfully (I can see it from the server log attached above) but they aren't transmitted with the request to the underlying web servers. – Dobby007 Jan 02 '18 at 12:27
  • @Dobby007 So what i was saying is: Try setting the variables (not headers) to some dummy values, and then inside your module code use reflection to replace those values with your own. Since you have shown clearly your code runs in the correct order, i *suspect* that IIS will load them into memory when request comes in and then carry out the whole worker; and since you would've hooked into that pipleine in your module, that gives you access to modify what you want. – zaitsman Jan 02 '18 at 12:30
  • I would say that you need to check your machine config and see if it is blowing away your configuration. Not sure which version of IIS you are using, but https://learn.microsoft.com/en-us/iis/configuration/system.webserver/httpprotocol/customheaders/ is a link to give you some direction with http response headers. –  Jan 03 '18 at 16:05
  • @Programmer, it's all about response headers. In my case I need to change request headers and then pass the modified request to the underlying web server. – Dobby007 Jan 03 '18 at 19:43
  • @zaitsman, I'll try to do it via variables although it looks like a workaround. – Dobby007 Jan 03 '18 at 19:57
  • Nobody out there got an answer? – Dobby007 Jan 04 '18 at 21:52
  • 1
    As such posts indicate, https://blogs.msdn.microsoft.com/benjaminperkins/2015/05/04/passing-client-ip-to-a-server-in-the-web-farm-using-application-request-router/ ARR itself would take control of headers such as `X-Forwarded-For`. So it is very likely in your case that ARR removes what you have set. You shouldn't attempt to hijack ARR (as that might lead to even more issues), so try the workaround mentioned above and leave ARR alone. – Lex Li Jan 08 '18 at 17:50
  • @LexLi, yes, I know that ARR can set X-Forwarded-For header itself if I tell it to do so, but my module also sets other headers such as X-Forwarded-Proto and X-Orig-Forwarded-For besides X-Forwarded-For. But I don't see any headers at all on my backend server with the exception of the header set by ARR itself. By the way I don't understand you entirely. You say to try the mentioned workaround but at the same time you recommend to leave ARR alone. The purpose of the mentioned workaround is to set headers but via server variables. – Dobby007 Jan 09 '18 at 08:03
  • @Dobby007, not sure if you found a solution to this! If you did please post as answer. However, since I didn’t see any answer here, I did some reverse search and found an article that might explain the cause to your problem: https://www.dionach.com/blog/easily-remove-unwanted-http-headers-in-iis-70-to-85 – dj079 Aug 31 '18 at 01:55

1 Answers1

1

This is an old "unanswered" post so I figured I would add my two cents. Adding request headers might not work in general, depending on how the ARR module/handler will process the request. It may be too late as Tarun mentioned, but for another reason. ARR module may be grabbing the raw data being received, in which case it definitely will be too late. Or ARR handler may be looking at particular Server Variables containing the original headers which were set before your notification (e.g. I don't think ALL_RAW is updated if you add additional request headers.) In the likely case ARR module is grabbing raw buffers, you would need to get ahead of that and update the raw data, which, if possible, is a whole new level of complexity.

Brian Clink
  • 297
  • 2
  • 17