Azure LoadBalancerProbe Responses being ignored - azure

I have defined a custom LoadBalancerProbe for my webrole as follows
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="CloudService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-03.2.0">
<LoadBalancerProbes>
<LoadBalancerProbe name="MyProbe" protocol="http" intervalInSeconds="15" path="/api/ping" port="80" timeoutInSeconds="30" />
</LoadBalancerProbes>
<WebRole name="TestApp" vmsize="Small">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" localPort="80" loadBalancerProbe="MyProbe"/>
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
<Import moduleName="RemoteAccess" />
<Import moduleName="RemoteForwarder" />
</Imports>
</WebRole>
</ServiceDefinition>
When in Azure I have 2 instances. I have enabled trace.axd and can see the load balancer calling the ping method, so that is definitely happening.
I can also see my "503" responses (Server Unavailable) in my test app when I want my instance to appear down (I change a config setting on the instance). I can see custom HTTP Headers from the load balancer X-MS-LB-MonitorStatus Down.
When I use a Curl request to access the load-balanced url, it always returns the correct results (If I have set an instance to return 503 rather than 200, it does not appear in the response results).
When I use a browser however (in this case Chrome) I can still get results back from the instance that is supposed to be down (i.e. the instance was available, I disable it, then additional calls to the load balanced url still resolve to the "disabled" instance).
I can confirm the actual instances that resolved each request using trace.axd information
I'm struggling to believe that azure is doing load balancing properly here.
Why does the browser continue to be able to access an instance that is supposedly out of rotation?
Why does curl "always get it right"?

The Azure load balancer is a layer 3 load balancer and only load balances new incoming TCP connections. It does not know anything about HTTP traffic.
Typically a browser will establish a TCP connection with keep-alive set to true and will keep that TCP connection open for a period of time, and any subsequent requests to the website will just be HTTP traffic over the existing TCP connection. Application such as curl will typically close the TCP connection after every request.
So in your case the Azure load balancer is behaving correctly, but your browser already has a TCP connection established to the instance that is out of rotation, so future HTTP requests will still go to the same out of rotation instance.
To validate that this is what is happening you can use netmon/wireshark on the client side or the server side.
To resolve this you have a few options:
After 4 minutes of idle time the connection will be terminated
and your browser should establish a new TCP connection and get
routed to an instance that is in rotation.
Closing all browser windows and reopening the browser should establish new TCP
connections.
On the server side you can set keep-alive to false and this will terminate the TCP connection on the Azure instance.
See the 3rd Q&A at http://blogs.msdn.com/b/kwill/archive/2013/02/28/heartbeats-recovery-and-the-load-balancer.aspx for a little more information.

According to this blog post (2014) Azure uses a Layer 4 load balancer:
http://azure.microsoft.com/blog/2014/04/08/microsoft-azure-load-balancing-services/
As such it can respond and monitor HTTP 200 and 503.

Related

How do I restrict domains for Silverlight NetTcp connections?

I'm hosting a clientaccesspolicy.xml for a locally hosted Silverlight component that communicates using TCP connections. It works but I'm trying to tighten the permitted domains and I can't find documentation to indicate how to specify these restrictions for TCP connections.
Is this possible, and if it is how should I be specifying these restrictions?
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<socket-resource port="4502-4534" protocol="tcp" />
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Basics of the Security Policy System
One additional restriction on using the sockets classes is that the
destination port range that a network application is allowed to
connect to must be within the range of 4502-4534. These are the only
destination ports allowed by a connection from a Silverlight
application using sockets. If the target port is not within this port
range, the attempt to connect will fail. It is possible for a target
server to receive connections on a port from this restricted range and
redirect it to a different port (a well-known port, for example) if
this is needed to support a specific existing application protocol.
I would think that narrowing the range of ports would would limit the available tcp sockets. They show an Example Policy File for Sockets here
<?xml version="1.0" encoding ="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from>
<domain uri="file:///" />
</allow-from>
<grant-to>
<socket-resource port="4502-4506" protocol="tcp" />
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Citing the following documentation from MS
To use a clientaccesspolicy.xml file to allow cross-domain access
To enable the service for access over TCP sockets, add
<socket-resource port="4502" protocol="tcp" /> to the <grant-to>
element, where the 4502 is the port value where the service is hosted.
Domain example
This policy file accepts connections only from the domains and scheme specified. This policy file specifies specific request headers and specifies resources that can be accessed.
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="MyHeader, X-API-*">
<domain uri="http://electronics.fabrikam.com"/>
<domain uri="http://books.fabrikam.com"/>
<domain uri="http://contoso.com:8080"/>
</allow-from>
<grant-to>
<socket-resource port="4502-4506" protocol="tcp" />
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
For the above policy, the Silverlight HTTP applications listed below are allowed to have access to the listed ports:
http://electronics.fabrikam.com/sample/app.xap
http://books.fabrikam.com/web/sample/app.html
http://contoso.com:8080/sample/app.xap
For the above policy, the Silverlight applications listed below are not allowed to have access to the listed ports:
http://electronics.fabrikam.com:8080/sample/app.xap
http://electronics.fabrikam.com:8080/sample/app.xap
http://bar.com/sample/app.xaml
https://bar.com/sample/app.html
The following HTTP request headers can be sent (in addition to the Content-Type header that is always allowed):
MyHeader
all headers starting with X-API-
Resource Network Security Access Restrictions in Silverlight

WebSockets in ASP.NET 5 (DNX) hosted on IIS not working

My website uses ASP.NET 5 with RC1-Update1 and some communication with the client goes through web sockets (SignalR is used).
During testing I found out that while running on IIS (or IIS Express), communication doesn't work through sockets. SignalR fallbacks to long polling.
SignalR log:
SignalR: Client subscribed to hub 'chathub'.
SignalR: Negotiating with '/signalr/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D'.
SignalR: serverSentEvents transport starting.
SignalR: Attempting to connect to SSE endpoint 'http://localhost:31650/signalr/signalr/connect?transport=serverSentEvents&c…wVlnXCY8bI7R8E&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=2'.
SignalR: serverSentEvents transport timed out when trying to connect.
SignalR: EventSource calling close().
SignalR: serverSentEvents transport failed to connect. Attempting to fall back.
SignalR: foreverFrame transport starting.
SignalR: Forever Frame is not supported by SignalR on browsers with SSE support.
SignalR: foreverFrame transport failed to connect. Attempting to fall back.
SignalR: longPolling transport starting.
SignalR: Opening long polling request to 'http://localhost:31650/signalr/signalr/connect?transport=longPolling&client…8WRrhWwVlnXCY8bI7R8E&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D'.
SignalR: Long poll complete
After long hours of debugging, I started my website directly through dnx (no IIS or anything else) via command line using:
dnx web
And web sockets worked out of the box without any problems.
During my research towards the solution I found out that in nodejs with socket.io web apps, web sockets in IIS must be disabled so that they are correctly forwarded to nodejs (link to resource here on iis.net), so I tried the same thing and got the error (occurs as soon as webSocket element is present in web.config):
An error occurred attempting to determine the process id of the DNX process hosting your application.
My web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
</handlers>
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" forwardWindowsAuthToken="false" stdoutLogEnabled="true" startupTimeLimit="3600" />
<staticContent>
<!-- A bunch of mime types (no difference if removed) -->
</staticContent>
<webSocket enabled="false" />
</system.webServer>
</configuration>
At this point I ran out of ideas. I made sure I have WebSockets installed in windows features and tried deploying my website on Azure (with web sockets turned on) where it will be hosted when finished.
I'd say that the problem is web sockets not being forwarded to DNX, but cannot find the solution for it. Any help would be greatly appreciated.
Update
Solution where the problem is recreated.
The problem was in missing package Microsoft.AspNet.WebSockets.Server and call in startup.cs app.UseWebSockets().
The issues was resolved on GitHub, big thanks to #davidfowl.

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.

How to trace overhead added by Application Request Routing?

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

Can't connect to IIS Express using IP Address

From what I understand, VS2012 comes with the IIS Express version by default. And it allows you to connect to the development site using IP address. Currently I can connect using http://localhost:22222. But this would not connect using this http://xxx.xxx.xxx.xxx:22222 where xxx just a local IP of the development machine . I have verified that the IIS Express is running and being used. The IE error was http 400 bad request.
I know you have asked question since a long time. I have an answer to this question at this link.
Go to your IISExpress>Config folder, locate applicationhost.config. Change <bindings> as below:
<bindings>
<binding protocol="http" bindingInformation="*:1407:YOUR_IP_ADDRESS" />
</bindings>
Before you do this , you will have to register this IP address using netsh command as below:
If you’re running Windows 7, pretty much all incoming connections are locked down, so you need to specifically allow incoming connections to your application. First, start an administrative command prompt. Second, run these commands, replacing 192.168.1.11:1234 with whatever IP and port you are using:
> netsh http add urlacl url=http://192.168.1.11:1234/ user=everyone
This just tells http.sys that it’s ok to talk to this url.
> netsh advfirewall firewall add rule name="IISExpressWeb" dir=in protocol=tcp localport=1234 profile=private remoteip=localsubnet action=allow
This adds a rule in the Windows Firewall, allowing incoming connections to port 58938 for computers on your local subnet.More information at this link.
Note: Be sure to change the bindings of your project only by locationg its name. You can even keep the localhost binding and add a new one , this way you can access same webpage using the given IP address.
The solution that worked for me was this one:
The one thing that fixed this for me was using the following line in the <bindings> section for my site in the applicationhost.config file:
<bindings>
<binding protocol="http" bindingInformation="*:8099:" />
</bindings>
The key was to simply remove localhost. Don't replace it with an asterisk, don't replace it with an IP or a computer name. Just leave it blank after the colon.
After doing this, I don't need to run Visual Studio as administrator, and I can freely change the Project Url in the project properties to the local IP or computer name. I then set up port forwarding and it was accessible to the Internet.
EDIT:
I've discovered one more quirk that is important to getting IIS Express to properly serve external requests.
If you are running Visual Studio/IIS Express as an administrator, you must not add a reservation to HTTP.SYS using the "netsh http add urlacl ..." command. Doing so will cause an HTTP 503 Service Unavailable error. Delete any reservations you've made in the URLACL to fix this.
If you are not running Visual Studio/IIS Express as an administrator, you must add a reservation to the URLACL.
Where is it located? applicationhost.config :)
Here
%userprofile%\Documents\IISExpress\config folder
or
%userprofile%\My Documents\IISExpress\config folder

Resources