SignalR on multiple Windows Azure instances (no backplane) - azure

I'm currently working on a Windows Azure application using WebAPI and SignalR for communication. Both services are hosted via OWIN on a Worker role with multiple instances.
Current solution
Currently we start one Owin host with WebAPI on port 443 on every machine and one SignalR Owin host on the instance input endpoint port (e.g. 10106-1010x) on every machine.
Everything works fine, but some of our customer are sitting behind a firewall where all ports except 80/443 are blocked -> so no websocket communication there (WebAPI works fine).
New solution
We are starting one Owin host with WebAPI and SignalR on every instance. So both HTTP and WebSocket traffic will be routed through the loadbalancer over port 443 -> no more instance input endpoints (and no more firewall problems).
The problem
The problem now is that sometimes the WebSocket connection can be established and sometimes not (browser independent). If the connection can't be established the following error appears in the console:
Error during WebSocket handshake: Unexpected response code: 400
No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.
I've already added the role instance id to the websocket response messages from the server, but couldn't find any (ir)regularities (e.g. a single instance doesn't respond, ...). All SignalR servers seem to be up and running, but sometimes the connection can't be established.
You can test it yourself by going to the following link. If you don't get an error dialog ("Connection to server lost") it is working, otherwise try to refresh the page several times.
-
I'm not looking for a scaleout feature for SignalR (as described here or here). The client just connects to one (random) server (worker role instance) and communicates with the server until a close message is sent. If he connects again he can be routed to any other server. Also there is no communication between the servers.
Update/Solution
halter73 was right, each instance generates its own anti-CSRF token. To avoid this I implemented my own IDataProtector/IDataProtectionProvider, similar to these to SO questions (see here and here).

If you can look at content of the 400 response (this may be difficult since it is an SSL encrypted response to a WebSocket request), you will probably see a message similar to "The ConnectionId is in the incorrect format."
SignalR uses the server's machine key to create an anti-CSRF token, but this requires that all the servers in your farm share a machine key for the token to be properly decrypted in when SignalR requests hop servers. The /negotiate is the request that retrieves the anti-CSRF token. When the SignalR client then uses the anti-CSRF token to make a /connect request, it sometimes fails when the /connect request is processed by a different server which didn't create the token and therefore is unable to decrypt it.
Here is an issue that filed on GitHub by someone who experienced a similar issue: https://github.com/SignalR/SignalR/issues/2292.

Related

How does an azure app service access a no azure web server

I have an Azure app service and in some cases I need to send a web request to a non-azure webserver. What do I need to do to make it possible.
Currently the web request fails with no clear error message.
In response to a HttpClient Put request I get a System.Net.WebException exception which says there were errors.
THe same request works from a desktop application.
If your webserver is reachable from the internet you should be able to access it through your App Service. Try to log a ping to your webserver and google (8.8.8.8).
If your App Service is in a VNET you should enable some outbound rules to your webservers IP adress.
The server I am connecting to is an other Azure service. After some more investigating, It appears that I can connect to it if I do not use SSL (i.e. http://) but the connection is immediately closed when using SSL (https://). I assume that the problem must be related to the use of SSL.

How to connect to an external service on a non-standard port from an Azure App Service?

I'm trying to access a third party service from Azure App Services (ideally Functions, but a Web App would do). However this service is hosted on a non-standard port, e.g. https://myservice.com:445
I'm using the System.Net.Http.HttpClient to make a POST request, but consistently get a SocketException:
An error occurred while sending the request. Unable to connect to the remote server An attempt was made to access a socket in a way forbidden by its access permissions 1.2.3.4:445
The code works on my local environment (Functions emulator or Kestrel), but fails on Azure. I tried using a service hosted on a regular https endpoint, e.g. https://myotherservice.com, and the call goes through normally.
I'm assuming there is some sort of outbound firewall rule that's preventing the fist call, but I haven't found any configuration option to disable this. Is it possible? I unfortunately cannot change the endpoint of the service I need to call.
After checking your application, I did indeed find that those outgoing requests were being blocked by the infrastructure.
I was also able to find public documentation covering those ports here:
https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#restricted-outgoing-ports

What can cause connection timeouts from Azure Cloud Service?

We have a WebApi in Azure that sends requests to a VM cluster that is load balanced via an Azure Cloud Service. We see occasional timeouts where requests are working, then one times out for no reason. Reissuing the request immediately succeeds.
In Fiddler I see:
[Fiddler] The connection to '[myApp].cloudapp.net' failed. Error: TimedOut (0x274c). System.Net.Sockets.SocketException A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 40.122.42.33:9200
I can't find any telemetry in the portal that shows any kind of error, and all is fine when the request is issued from my api. Also, I don't see anything in the Event Logs on my VMs.
I am thinking it might have something to do with TCP port closure, but I am unfamiliar with this. My requests are specifying 'Connection: keep-alive', so I assume that subsequent requests to the same protocol/domain would attempt to use the same connection. It usually works, however.
Is there any kind of throttling on the number of active connections that can come into my Cloud Service? It is possible that these timeouts happen during peak load (though we don't have enough consistent traffic to verify this).
thanks!

Does an HTTPS connection to Windows Azure web role stay connected?

It's my understanding that if I connect to a windows Azure web role with HTTPS that there is an initial handshake to exchange certificates and then another connection is made to get data.
Can someone explain to me is the connection persisted or if the user needs another page a few minutes later would there me another exchange of handshakes? How about if the WebRole was serving data from the Web API, would that be the same?
It depends on a client capabilities but in terms of modern web browsers I wouldn't be so worried about single connection(handshake) per request:
HTTP 1.1 - Persistent connection
Modern browsers use HTTP 1.1 by default which according to RFC 2616 makes connection persistent by default. Another important aspect of HTTP 1.1 is that it forces support of HTTP pipelining which means that multiple requests to the same endpoint will be send in a batch and response will be also received in a batch (on the same connection). Browsers generally have a limit of connections per server (Chrome - 2 connections by default) and reuse connections.
Azure: It looks like Azure will drop connection if idle for 4 minutes
Handshake
Every first connection requires full handshake but subsequent can reuse session ticket (ID), but this depends on a client. Microsoft introduced TLS session resumption some time ago - What's New in TLS/SSL (Schannel SSP) in Windows Server and Windows. As long as you have only one host serving HTTPS connection it should resume sessions, according to this blog post:
There’s also a warning about session resumption. This is due to the
Azure load balancer and non-sticky sessions. If you run a single
instance in your cloud service, session resumption will turn green
since all connections will hit the same instance.
It should not make any difference if it's a WebAPI or Website. You can always test it using SSLyze.

Connectivity between NodeJS applications behind load balancer

I'm currently working on nodejs application and I got small issue.
My NodeJS application consists of 2 parts:
Internal API from other applications. Let's call this part API.
User faced web server (Express + Socket.io). Let's call this Web.
We're receiving a lot of calls to API from our other internal applications. Some of this calls would generate notifications to web users (let's imaging it's online-chat).
So if we have message for client #1000 and he's online (connected to Web application through Socket.io) we would emit message throught Socket.io to this client. Everything works fine.
But there is an issue.
We're going to introduce load balancer between our NodeJS application (it's one application, so both parts - API and Web would be behind the load balancer). Now let's imagine that we have load balancer and 2 servers with this application: server1 and server2.
Thus some of API calls are sent to server1 and some of them are sent to server2. So let's imagine we got API call to server1 and this call should send a message to client #1000. But this client has open connection to server2.
The question is: is there any best practices or common solutions - how these two servers should communicate? One of possible solutions could be open socket connection between all servers with nodejs application and if we need to send a message to client - just broadcast it so every server could check if client is connected at this moment and send the message to correct client.

Resources