在控制台应用程序中创建的 Kestrel 拒绝连接
Kestrel created in Console app refuses connections
这是这个问题的延续。
我能够使用动态端口从控制台应用程序启动 2 个 kestrel 服务器,并且在某些计算机上它工作正常,但有时这种方法会失败。
TLDR
- Kestrel 应该创建 HTTP 和 HTTPS 连接,但只创建 HTTP
- 即使提示已创建 HTTP 连接,也无法访问
出于测试目的,我创建了防火墙规则,为所有协议和所有应用程序打开所有端口,然后完全禁用防火墙本身。为清楚起见,我没有使用 IIS,而是从 C# 控制台应用程序手动启动 Kestrel 作为本地服务器。
问题
- 上面 link 中的代码应该为每个服务器创建 HTTPS 连接,但是在 Windows Server 2012 和一些 Windows 10 Pro 计算机上它只创建 HTTP 连接,尽管有 HTTPS如果我知道如何解决下面的另一个问题,在这种情况下并不重要。我认为,这是因为 Windows 中的某些更新可能要求所有 HTTPS 连接都具有 SSL 证书,而据我不提供,服务器甚至不会尝试创建 HTTPS 连接。 Kestrel 中是否有忽略本地主机 SSL 证书验证的设置?
public static IWebHost Run<T>(ServerOptions options = null) where T : class
{
var configuration = new ConfigurationBuilder().Build();
var urls = new[]
{
"http://0.0.0.0:0",
"https://0.0.0.0:0"
};
var environment = WebHost
.CreateDefaultBuilder(new string[0])
.ConfigureServices(o => o.AddSingleton(options))
.UseConfiguration(configuration)
.UseUrls(urls)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
//.UseIISIntegration()
.UseStartup<T>()
.Build();
environment.RunAsync();
return environment;
}
// Issue #1
// On some computers
// webAddresses = ["http://0.0.0.0:50210", "https://0.0.0.0:50220"]
// On other computers and even for 2 users on the same Windows server it doesn't create HTTPS
// webAddresses = ["http://0.0.0.0:50210"]
var webEnvironment = Server.Run<Startup>();
var webAddresses = webEnvironment.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
- 第二个问题是,在某些计算机上,代码的执行没有任何错误或异常,并且 returns 服务器的动态地址,例如http://0.0.0.0:50210 but when I try address http://127.0.0.1:50210 in a browser, it says that website cannot be reached and connection to this server was actively refused. I would blame some incompatibility issues with Windows Server 2012 and Windows 8 and Kestrel, but I have Windows 10 VPS where this app works fine for one system user and cannot create HTTPS for another one and the only difference between those users is that I modified NETSH rules 其中之一。我可能会创建 BAT 脚本,尝试为所有用户打开所有端口,这将允许我的具有动态端口的应用程序按预期运行,但也许有一些 Kestrel 设置可以使应用程序在动态端口上可用而无需强奸防火墙和网络设置?
Hacky 解决方案
Windows Server 2012 和 Kestrel 之间确实存在不兼容性。为了使它们兼容,我不得不强制 Kestrel 使用 HTTP/1 协议而不是默认设置的 HTTP/2。
ASP Core 3.1 和 Windows Server 2012 的最终版本
public static IWebHost Run<T>(ServerOptions options = null) where T : class
{
//var urls = new[]
//{
// "http://127.0.0.1:0",
// "https://127.0.0.1:0"
//};
var configuration = new ConfigurationBuilder().Build();
var environment = WebHost
.CreateDefaultBuilder(new string[0])
.ConfigureServices(o => o.AddSingleton(options))
.UseConfiguration(configuration)
//.UseUrls(urls)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel(o =>
{
o.Listen(IPAddress.Loopback, 0, v => v.Protocols = HttpProtocols.Http1); // FIX!!!
//o.Listen(IPAddress.Loopback, 0, v =>
//{
// v.UseHttps();
// v.Protocols = HttpProtocols.Http1;
//});
})
.UseStartup<T>()
.Build();
environment.RunAsync();
return environment;
}
无法建立 HTTPS 连接的问题仍然存在,因为当我使用上面的 hacky 解决方案并尝试创建 HTTPS 而不是 HTTP 时,我得到了一个异常
Cannot access a disposed object. Object name: 'IServiceProvider'
在这一行
var serviceEnvironment = Server.Run<ServiceStartup>();
var webEnvironment = Server.Run<WebStartup>(); // Exception happens here
可能是因为 Kestrel 正在尝试重用第一个服务器的现有连接...
更新
就我只能创建一个连接而言,决定始终使用 HTTPS 和自动生成的本地主机证书,并在 CefSharp 中禁用 SSL 验证。
public static IWebHost Run<T>(ServerOptions options = null) where T : class
{
var configuration = new ConfigurationBuilder().Build();
var environment = WebHost
.CreateDefaultBuilder(new string[0])
.ConfigureServices(o => o.AddSingleton(options))
.UseConfiguration(configuration)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback, 0, o =>
{
o.UseHttps("Certificate.pfx", "SomePassword");
o.Protocols = HttpProtocols.Http1;
});
})
.UseStartup<T>()
.Build();
environment.StartAsync();
return environment;
}
// Disable errors about invalid local certificate in CefSharp
var browserOptions = new BrowserSettings
{
WebSecurity = CefState.Disabled,
FileAccessFromFileUrls = CefState.Enabled,
UniversalAccessFromFileUrls = CefState.Enabled
};
Browser.BrowserSettings = browserOptions;
这是这个问题的延续。
我能够使用动态端口从控制台应用程序启动 2 个 kestrel 服务器,并且在某些计算机上它工作正常,但有时这种方法会失败。
TLDR
- Kestrel 应该创建 HTTP 和 HTTPS 连接,但只创建 HTTP
- 即使提示已创建 HTTP 连接,也无法访问
出于测试目的,我创建了防火墙规则,为所有协议和所有应用程序打开所有端口,然后完全禁用防火墙本身。为清楚起见,我没有使用 IIS,而是从 C# 控制台应用程序手动启动 Kestrel 作为本地服务器。
问题
- 上面 link 中的代码应该为每个服务器创建 HTTPS 连接,但是在 Windows Server 2012 和一些 Windows 10 Pro 计算机上它只创建 HTTP 连接,尽管有 HTTPS如果我知道如何解决下面的另一个问题,在这种情况下并不重要。我认为,这是因为 Windows 中的某些更新可能要求所有 HTTPS 连接都具有 SSL 证书,而据我不提供,服务器甚至不会尝试创建 HTTPS 连接。 Kestrel 中是否有忽略本地主机 SSL 证书验证的设置?
public static IWebHost Run<T>(ServerOptions options = null) where T : class
{
var configuration = new ConfigurationBuilder().Build();
var urls = new[]
{
"http://0.0.0.0:0",
"https://0.0.0.0:0"
};
var environment = WebHost
.CreateDefaultBuilder(new string[0])
.ConfigureServices(o => o.AddSingleton(options))
.UseConfiguration(configuration)
.UseUrls(urls)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
//.UseIISIntegration()
.UseStartup<T>()
.Build();
environment.RunAsync();
return environment;
}
// Issue #1
// On some computers
// webAddresses = ["http://0.0.0.0:50210", "https://0.0.0.0:50220"]
// On other computers and even for 2 users on the same Windows server it doesn't create HTTPS
// webAddresses = ["http://0.0.0.0:50210"]
var webEnvironment = Server.Run<Startup>();
var webAddresses = webEnvironment.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
- 第二个问题是,在某些计算机上,代码的执行没有任何错误或异常,并且 returns 服务器的动态地址,例如http://0.0.0.0:50210 but when I try address http://127.0.0.1:50210 in a browser, it says that website cannot be reached and connection to this server was actively refused. I would blame some incompatibility issues with Windows Server 2012 and Windows 8 and Kestrel, but I have Windows 10 VPS where this app works fine for one system user and cannot create HTTPS for another one and the only difference between those users is that I modified NETSH rules 其中之一。我可能会创建 BAT 脚本,尝试为所有用户打开所有端口,这将允许我的具有动态端口的应用程序按预期运行,但也许有一些 Kestrel 设置可以使应用程序在动态端口上可用而无需强奸防火墙和网络设置?
Hacky 解决方案
Windows Server 2012 和 Kestrel 之间确实存在不兼容性。为了使它们兼容,我不得不强制 Kestrel 使用 HTTP/1 协议而不是默认设置的 HTTP/2。
ASP Core 3.1 和 Windows Server 2012 的最终版本
public static IWebHost Run<T>(ServerOptions options = null) where T : class
{
//var urls = new[]
//{
// "http://127.0.0.1:0",
// "https://127.0.0.1:0"
//};
var configuration = new ConfigurationBuilder().Build();
var environment = WebHost
.CreateDefaultBuilder(new string[0])
.ConfigureServices(o => o.AddSingleton(options))
.UseConfiguration(configuration)
//.UseUrls(urls)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel(o =>
{
o.Listen(IPAddress.Loopback, 0, v => v.Protocols = HttpProtocols.Http1); // FIX!!!
//o.Listen(IPAddress.Loopback, 0, v =>
//{
// v.UseHttps();
// v.Protocols = HttpProtocols.Http1;
//});
})
.UseStartup<T>()
.Build();
environment.RunAsync();
return environment;
}
无法建立 HTTPS 连接的问题仍然存在,因为当我使用上面的 hacky 解决方案并尝试创建 HTTPS 而不是 HTTP 时,我得到了一个异常
Cannot access a disposed object. Object name: 'IServiceProvider'
在这一行
var serviceEnvironment = Server.Run<ServiceStartup>();
var webEnvironment = Server.Run<WebStartup>(); // Exception happens here
可能是因为 Kestrel 正在尝试重用第一个服务器的现有连接...
更新
就我只能创建一个连接而言,决定始终使用 HTTPS 和自动生成的本地主机证书,并在 CefSharp 中禁用 SSL 验证。
public static IWebHost Run<T>(ServerOptions options = null) where T : class
{
var configuration = new ConfigurationBuilder().Build();
var environment = WebHost
.CreateDefaultBuilder(new string[0])
.ConfigureServices(o => o.AddSingleton(options))
.UseConfiguration(configuration)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback, 0, o =>
{
o.UseHttps("Certificate.pfx", "SomePassword");
o.Protocols = HttpProtocols.Http1;
});
})
.UseStartup<T>()
.Build();
environment.StartAsync();
return environment;
}
// Disable errors about invalid local certificate in CefSharp
var browserOptions = new BrowserSettings
{
WebSecurity = CefState.Disabled,
FileAccessFromFileUrls = CefState.Enabled,
UniversalAccessFromFileUrls = CefState.Enabled
};
Browser.BrowserSettings = browserOptions;