I am currently tearing my hair out at work trying to resolve an issue with a web application that uses SignalR over WebSockets where traffic is directed through a Barracuda Web Application Firewall (WAF). Every attempt to connect to the signalr/connect
endpoint using websockets would fail with a 400 Bad Request. The connection is then reverted back to WebServer polling which works, but isn't what we want.
Requests made are sent to our Barracuda Web Application Firewall and are then sent on to our Load Balanced IIS Web Servers. We are using IIS 8.5 on Windows Server 2012R2 and the application is a .Net 4.6.2 Web Application.
The same setup (Not using a Barracuda WAF), works without an issue.
So Far I have
Enabled Websockets in the WAF as per this article https://campus.barracuda.com/product/webapplicationfirewall/doc/49054741/how-to-enable-websocket. I still get the same 400 error.
Checked to make sure that my IIS Servers have the WebSocket
Feature enabled.
Turned on SignalR debugging/tracing in the Web.Config as per https://docs.microsoft.com/en-us/aspnet/signalr/overview/testing-and-debugging/enabling-signalr-tracing. This results in log files, but no indicates errors.
I am not sure what else to check?
Best Answer
So I have found out my problem. I have found out that we are actually sending our traffic to our WAF through an Azure Load Balancer first. When I log out the Headers in the WAF Access Logs I can see that the
Connection
header has no value, which I know my client is sending asUpgrade
.It would appear to be an issue using an Azure Load Balancer. So I ma investigating using an Azure Application Gateway instead.
For the moment, however I can get this to work by having the WAF add the
Connection
Header for me, by configuring a rewrite header rule to send this header onto my IIS Servers.Required Headers for WebSockets
Connection: Upgrade Upgrade: websockets
Under HTTP Request Rewrite, Add a new Rewrite Ruleā¦
Header Upgrade eq websocket
as the Rewrite condition. This will now only apply the rule when theUpgrade
header contains the valuewebsocket
.Now when I try and load the application again and boom, connection successful to /signalr/connect with webSockets transport!
More information is available at my blog post