Ядро ASP.NET с signalR, размещенное на IIS: ошибка во время рукопожатия WebSocket: неожиданный код ответа: 200 - PullRequest
0 голосов
/ 06 марта 2019

У меня есть приложение чата, которое работало нормально при локальной отладке с IIS Express в Visual Studio 2017. После того, как я развернул его в рабочей среде (Windows Server 2012R2 IIS 8.5.9600), консоль javascript выдает мне сообщение:

"Ошибка подключения WebSocket к 'wss: // [myServer] / [myHubName]? Id = [weirdString]': ошибка при рукопожатии WebSocket: неожиданный код ответа: 200"

Хотя клиент использует https длядоступ к веб-сайту, ssl-расшифровка выполняется на брандмауэре, поэтому входящие https-запросы поступают на сервер как http на порт 8088.

Также попытался поставить URL моего веб-сайта на параметр «имя-хоста» в привязках сайта наIIS, но затем сайт начал возвращать ошибку 400.

Я уже установил поддержку WebSockets в IIS, как описано в документации Microsoft , и убедился, что на моем сайте она включена.

Я также просматривал веб-сайт локально на сервере (http), и ошибка не появилась, так что, похоже, это какая-то проблемаe с конфигурацией обратного прокси-сервера IIS.

Ниже приведены некоторые журналы IIS с опущенной частной информацией из одного и того же запроса как от клиента в глобальной сети, так и от другого с локальным клиентом, на том же компьютере, что и IIS.

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: s-ip cs-method cs-uri-stem cs-uri-query s-port c-ip  sc-status sc-substatus sc-win32-status time-taken

Есть идеи, как это исправить?

Фрагменты моего кода запуска:

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 Ответ

1 голос
/ 06 марта 2019

Теперь, когда я понимаю ваш вопрос больше, убедитесь, что ваши привязки IIS настроены на прослушивание на всех ipaddresses, Type = http, hostname = url, который вы использовали из WAN, ipaddress = *, Port = 8088

Примечание: вы сказали в своем комментарии, что 8088 идет от брандмауэра к вашему серверу для доступа к приложению. Таким образом, вы используете не https на сервере, а http, и входящий трафик уже зашифрован брандмауэром. Вы не хотите дважды шифровать трафик в маршруте.

Вы также сказали, что он работает локально на сервере, поэтому происходит одно из двух:

  1. Ваш сервер прослушивает только IP-адрес 127.0.0.1. Изменение * в привязках IIS и использование правильного порта, как указано выше, должно исправить это.

  2. Трафик никогда не делает его вашим сервером должным образом из сети или неправильно возвращается к клиенту.

Поскольку 2 происходит, частично на основе вашего обновления, вам нужно где-то переписать URL, возможно, это поможет:

Обратный прокси веб-сокетов в IIS 8

Может быть, не совсем так, но переписать трафик, который вы отправляете обратно клиенту, чтобы удалить порт, чтобы он соответствовал URL, который пользователь использовал для соединения с клиентом. Клиент не знает о порте 8088 из глобальной сети.

...