I have a chat application that ran fine while debugging locally with IIS express under visual studio 2017. After I depolyed it into production (Windows server 2012R2 IIS 8.5.9600), the javascript console is giving me message:

"WebSocket connection to 'wss://[myServer]/[myHubName]?id=[weirdString]' failed: Error during WebSocket handshake: Unexpected response code: 200"

Altough The client uses https to access the website, the ssl decryption is performed at the firewall, so incoming https requests reach the server as http on port 8088.

Also tried to put my website url on teh "hostname" option on the site bindings on IIS, but then the site started to return error 400.

I have already installed WebSockets support on IIS as described on microsoft documentation and made sure my site had it enabled.

I also browsed the website locally on the server (http), and the error did not appear, so It looks like it`s some issue with IIS reverse proxy configuration.

Here are some IIS logs, with some private information ommited, from the same request both from a client on the WAN and the other with a local client, on the same machine as IIS is running.

IIS log when access was performed from wan:

[lan server ip address] POST /[myHubName]/negotiate - 8088 - https://[public website url]/ 200 0 0 0
[lan server ip address] GET /[myHubName] id=zHiunn5_ynV2jO5812KpDg 8088 -  https://[public website url]/ - 200 0 0 15
[lan server ip address] POST /[myHubName]/negotiate - 8088 -  https://[public website url]/ 200 0 0 78
[lan server ip address] POST /[myHubName] id=T7M5A-o-qqTyd13dSMB64A 8088 - https://[public website url]/ 200 0 0 0

IIS log when access was performed locally on the IIS machine:
::1 POST /[myHubName]/negotiate - 8088 - ::1  http://localhost:8088/ 200 0 0 14
::1 GET /[myHubName] id=QY4do7yqF3EKRbS1Y3usuw 8088 - ::1  - 101 0 64 6356

Fields reference for both scenarios are:

#Fields: s-ip cs-method cs-uri-stem cs-uri-query s-port c-ip  sc-status sc-substatus sc-win32-status time-taken

Any Ideas on how to fix that?

The snippets from my startup code are:

Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        //ommited configuration: authorization, database connection, etc.

        services.AddMvc(options =>
            {
                //some options;

            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        //adds signalR
        services.AddSignalR();

    }


    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }


        app.UseHttpsRedirection();
        app.UseCookiePolicy();
        app.UseSession();
        app.UseAuthentication();

        app.UseSignalR(routes =>
        {
            routes.MapHub<MyHubName>("/MyHubName");
        });

        app.UseStaticFiles();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });


    }
}

Program.cs :

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseKestrel()
            .UseIISIntegration();

}

1 Answers

1
Community On

Now that I understand your question more, make sure your IIS bindings are set to the listen on all ipaddresses, Type = http, hostname = the url you used from WAN, ipaddress = *, Port = 8088

Note: you said in your comment that 8088 is coming from the firewall to your server to access the application. So, you're not using https on the server, but http, and the incoming traffic is already encrypted by the firewall. You don't want to encrypt the traffic twice in route.

You also said that it works locally on the server, so one of two things are happening:

  1. Your server is only listening on the 127.0.0.1 IP address. Changing the * in the IIS bindings and using the correct port as above should fix that.

  2. The traffic is never making it your server properly from the network, or isn’t properly going back to the client.

Since 2 is happening, in part, based on your update, you need a URL rewrite somewhere, perhaps this will help:

Websockets reverse proxy in IIS 8

Maybe not exactly like that, but rewrite the traffic you are sending back to the client to remove the port to match the url the user used to connect from the client. The client doesn’t know about the 8088 port from the WAN.