How to trace overhead added by Application Request Routing? - iis

We have a Delphi SOAP service which needs to be SSL-enabled. I opted to use an IIS ARR reverse proxy to do SSL offloading for ease of configuration (compared to OpenSSL and manual certificate + passphrase management). ARR works, but it adds an insane amount of overhead... Response time went from under 2 seconds to 19 seconds for 18 service requests (about 60Kb compressed total).
I added timestamp logging to client & server for when messages are both sent and received. It shows about 1 second added to each request routing through ARR between sending from the client and receipt by the service. The response is routed back very quickly, only the request routing via ARR is slow (see image below).
How can I trace the source of overhead? Is ARR not suited to this use case? I tried tweaking and disabling most settings, including caching. I tried different hosts with clean IIS setups, including a production Windows Server 2012. SSL itself is not the overhead, just having an ARR HTTP reverse proxy causes the delay.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:8987/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Request & response samples from Fiddler:
Raw HTTP Request
Raw HTTP Response

We have the same problem. I found the root, it's in System.Net.Sockets.Socket.DoConnect
The problem is related to IPv6:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/203b6230-e4c0-477c-9a0a-0c21a7ad1615/strange-onesecond-delay-with-tcpconnections-to-localhost?forum=clr
http://msdn.microsoft.com/en-us/library/115ytk56.aspx
"If IPv6 is enabled and the TcpClient(String, Int32) method is called to connect to a host that resolves to both IPv6 and IPv4 addresses, the connection to the IPv6 address will be attempted first before the IPv4 address. This may have the effect of delaying the time to establish the connection if the host is not listening on the IPv6 address."
To resolve it for loopback requests you need to disable IPv6 on a machine, see p.4-5-6:
https://stackoverflow.com/a/12403731

My advice: use IIS for the apps, use Apache HTTP Daemon for the proxying.
In the past I've used various pieces of software and hardware for SSL offloading (starting somewhere in 2003 I think). Each with their own pricing level and features. The last years I've switched to solely using Apache HTTP Daemon for that purpose. Even in combination with IIS and on Windows. Apache is easy to configure once you have a running sample and more easily grows to more complex scenarios with forwarding and renaming.
Some instructions how to use Apache HTTP Daemon on Windows as SSL offloading engine can be found on http://www.invantive.com/about-invantive/news/entryid/897/ssl-offloading-for-apache-tomcat.

Turning off IPv6, as Dmitry suggested, solved this for me.
You could also use 127.0.0.1 in your rewrite, instead of localhost, to force IPv4.

I would say you have something screwy in your setup. We currently run ARR for SSL offloading and conducted throughput testing at significant volume and ARR showed little to no affect on throughput.
I would agree with Brock and say check your App Pool settings first. Basically an ARR App Pool should be set to never recycle.
I would recommend watching episodes 32-38 starting at:
http://dotnetslackers.com/articles/iis/Bindings-and-Rules-for-Application-Request-Routing-ARR-Week-32.aspx

Related

Route Client App To Different Port Backend IIS 10

I have a HTTP Listener that listens for incoming traffic on port 11000 in my Azure VM. I want a client app sending data to that port but without having to type the port in the client app and also using https instead of http.
For instance, when typing the URL in the client app, it would be: https://myurl/data. But in the back end, IIS would re-route to http://myurl:11000/data.
I also have an app that is on 443, so I would want it to route from 443 to 11000.
I followed this article's example but still doesn't route the data stream to my HTTP listener to the port provide in the config file. Would I use redirect or rewrite for the web.config file?
If I understand correctly, what you want is that
https://myurl/data re-route to http://myurl:11000/data
HTTPS requests can be redirected to HTTP via rewrite rules. But redirecting HTTPS to HTTP is not recommended for many factors.
If you want to send data to port 11000 in the client application, but don't have to type the port in the client application, you need to create the URL rewrite rule on port 80, not on port 11000.
Refer to the following rules and modify it according to your actual requirements:
<rewrite>
<rules>
<rule name="Rule1" enabled="true" stopProcessing="true">
<match url="^data(.*)" />
<action type="Rewrite" url="http://myurl:11000/{R:0}" />
</rule>
</rules>
</rewrite>
Also, you need to double-click Application Request Routing Cache at the server level and select Server Proxy Settings on the right, then enable proxy and apply.
If you haven't installed the ARR module on IIS, you can refer to this link.

How to setup forward proxy on Windows server for outgoing HTTP and HTTPS requests?

I have a windows server 2012 VPS running a web app behind Cloudflare. The app needs to initiate outbound connections based on user actions (eg upload image from URL). The problem is that this 'leaks' my server's IP address and increases risk of DDOS attacks.
So I would like to prevent my server's IP from being discovered by setting up a forward proxy. So far my research has shown that this is no simple task, and would involve setting up another VPS to act as a proxy.
Does this extra forward proxy VPS have to be running windows ? Are their any paid services that could act as a forward proxy for my server (like cloudflare's reverse proxy system)?
Also, it seems that the suggested IIS forward proxy plugin, Application Request Routing, does not work for HTTPS.
Is there a solution for both types of outgoing (HTTPS + HTTP) requests?
I'm really lost here, so any help or suggestions would be appreciated.
You are correct in needing a "Forward Proxy". A good analogy for this is the proxy settings your browser has for outbound requests. In your case, the web application behaves like a desktop browser and can be configured to make the resource request through a proxy.
Often you can control this for individual requests at the application layer. An example of doing so with C#: C# Connecting Through Proxy
As far as the actual proxy server: No, it does not need to run Windows or IIS. Yes, you can use a proxy service. The vast majority of proxy services are targeted towards consumers and are used for personal privacy or to get around network restrictions. As such, I have no direct recommendations.
Cloudflare actually has recommendations regarding this: https://blog.cloudflare.com/ddos-prevention-protecting-the-origin/.
Features like "upload from URL" that allow the user to upload a photo from a given URL should be configured so that the server doing the download is not the website origin server.
This may be a more comfortable risk mitigator, as it wouldn't depend on a third party proxy service. A request for upload could be handled as a web service call to a dedicated "file downloader" server. Keep in mind that if you have a queued process for another server to do the work, and that server is hosted in the same infrastructure, both might be impacted by a DDoS, depending on the type of DDoS.
Your question implies that you may be comfortable using a non-windows server. Many softwares exist that can operate as a proxy(most web servers), but suffer from the same problem as ARR - lack of support for the HTTP "CONNECT" verb, which is used by modern browsers to start an HTTPS connection before issuing a "GET". SQUID is very popular, open source, and supports everything to connect to.. anything. It's not trivial to set up. Apache also has support for this in "mod_proxy_connect", but I have no experience in that and the online documentation isn't very robust. It's Apache, though, so it may be worth the extra investigation.

BonCode Connector, IIS 7.5 & Tomcat 8, Intermittent Generic Connector Error

I have a JSP web-app hosted on IIS 7.5 & Tomcat 8.0.30 via BonCode AJP13 v1.0.26 on Win 2008 R2 64 bit.
On the production environment, some users are getting an intermittent BonCode error:
Generic Connector Error: Please check...
Has anyone got a known working configuration for BonCode 1.0.26, IIS 7.5 & Tomcat 8?
Details
The users affected seem to be roaming laptops and home-workers that connect via a VPN
ie desktops seem unaffected.
There is no authentication on Tomcat / JSP web-app.
A single instance of Tomcat is on the same server as IIS 7.5.
ie no load-balancing etc.
Only plain HTTP is being used
ie not HTTPS and no associated certificates.
Client Diagnosis
IE 11 Developer Tools > Network
shows the generation of a HTTP 502.
Fiddler
shows the generation of a HTTP 502.
Server Diagnosis
BonCode logs
Occasionally, this is seen:
2016-02-29 15:59:01 1.0.26 ERROR
TCP Client level -- Server/Port:localhost/8009
Value cannot be null.
Parameter name: buffer
2016-02-29 15:59:01 One Connection raised an error
but usually, no related errors / warnings are being shown
IIS Failed Trace Requests
shows the generation of a HTTP 502 in module ‘ManagedPipelineHandler’.
Tomcat logs
no errors, as expected as servlet/JSP requests are not being forwarded.
Configuration Files
BonCode - BonCodeAJP13.settings
<Settings>
<Port>8009</Port>
<Server>localhost</Server>
<MaxConnections>0</MaxConnections>
<LogLevel>4</LogLevel>
<LogDir>E:\inetpub\logs\BonCode</LogDir>
<FlushThresholdTicks>0</FlushThresholdTicks>
<EnableRemoteAdmin>False</EnableRemoteAdmin>
<PacketSize>65536</PacketSize>
</Settings>
Tomcat - server.xml
...
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"
packetSize="65536" />
...
Notes
I am aware that, as well as BonCode, there are these other connector options:
Tomcat ISAPI
IIS ARR
If we get no joy with BonCode, we will probably try IIS ARR next.
Thanks for reading.
After much trial and error, it seems that the authorization HTTP header must be filtered out.
Some client machines, roaming laptops etc, seem to generate very large authorization packets - I have seen sizes of about 12K.
For whatever reason, despite setting the packet size to 64K on both BonCode & Tomcat 8, this header seems to be too large.
This is now our BonCode configuration - note the updated HeaderBlacklist value
<Settings>
<Port>8009</Port>
<Server>localhost</Server>
<MaxConnections>0</MaxConnections>
<LogLevel>2</LogLevel>
<LogDir>E:\inetpub\logs\BonCode</LogDir>
<FlushThreshold>0</FlushThreshold>
<EnableRemoteAdmin>False</EnableRemoteAdmin>
<HeaderBlacklist>AUTHORIZATION,URL,SERVER_SOFTWARE,SERVER_NAME,SERVER_PROTOCOL</HeaderBlacklist>
<PacketSize>65536</PacketSize>
</Settings>

Cloudflare 524 w/ nodejs + express

I'm running a nodejs webserver on azure using the express library for http handling. We've been attempting to enable cloudflare protection on the domains pointing to this box, but when we turn cloudflare proxying on, we see cycling periods of requests succeeding, and requests failing with a 524 error. I understand this error is returned when the server fails to respond to the connection with an HTTP response in time, but I'm having a hard time figuring out why it is
A. Only failing sometimes as opposed to all the time
B. Immediately fixed when we turn cloudflare proxying off.
I've been attempting to confirm the TCP connection using
tcpdump -i eth0 port 443 | grep cloudflare (the request come over https) and have seen curl requests fail seemingly without any traffic hitting the box, while others do arrive. For further reference, these requests should be and are quite quick when they succeed, so I'm having a hard time believe the issue is due to a long running process stalling the response.
I do not believe we have any sort of IP based throttling or firewall (at least not intentionally?)
Any ideas greatly appreciated, thanks
It seems that the issue was caused by DNS resolution.
On Azure, you can configure a custom domain name for your created webapp. And according to the CloudFlare usage, you need to switch the DNS resolution to CloudFlare DNS server, please see more infomation for configuring domain name https://azure.microsoft.com/en-us/documentation/articles/web-sites-custom-domain-name/.
You can try to refer to the faq doc of CloudFlare How do I enter Windows Azure DNS records in CloudFlare? to make sure the DNS settings is correct.
Try clearing your cookies.
Had a similar issue when I changed cloudflare settings to a new host but cloudflare cookies for the domain was doing something funky to the request (I am guessing it might be trying to contact the old host?)

Binding IISExpress to IP Address Failing

I've had this working on the same Windows box in Win8 Win8.1 and Win10. Yesterday I performed the Threshold 2 upgrade to Windows 10 and now I can't launch my API in IISExpress.
The bindings are setup like this:
<binding protocol="http" bindingInformation="*:51258:jamhq" />
<binding protocol="http" bindingInformation="*:51258:192.168.0.8" />
I've triple checked all my netsh settings and at the moment Windows Firewall is completely disabled whilst I troubleshoot.
Every time I try to launch this I'm now presented with an error like this:
Failed to register URL "http://192.168.0.8:51258/" for site "<name>" application "/"
Error Description: The Network location cannot be reached.
For more information ... (0x800704d0)
I can ping this IP (obviously since I'm pinging myself), I can ping this location from my other machines / devices.
It seems like some extremely low level network setting has been changed.
Has anyone seen this problem or have a solution?
So, this is something that might help others in the future, I've been going round and round on this problem today and have just fixed the issue.
It appears that the update removes IP addresses that the http.sys is listening on. So when executing:
netsh http show iplisten
The only entry I had after the update was:
::
So executing:
netsh http add iplisten 192.168.0.8
Bingo, everything is now working again.

Resources