Skip to content

Commit 6cb799e

Browse files
authored
feat: measure host-header-mismatch for HTTP endpoint (no TLS) (#2093)
* try without TLS * http scheme for server * httpsys httponly * fix NRE * dont rely on a separate flag * settings to init
1 parent 302fb36 commit 6cb799e

File tree

5 files changed

+98
-26
lines changed

5 files changed

+98
-26
lines changed

scenarios/rejection.benchmarks.yml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020
project: src/BenchmarksApps/TLS/HttpSys/HttpSys.csproj
2121
readyStateText: Application started.
2222
variables:
23+
serverScheme: https
2324
# behavioral settings
2425
mTLS: false # enables settings on http.sys to negotiate client cert on connections
2526
tlsRenegotiation: false # enables client cert validation
@@ -30,7 +31,7 @@ jobs:
3031
httpSysLogs: false
3132
statsEnabled: false
3233
logRequestDetails: false
33-
arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --httpSysLogs {{httpSysLogs}} --logRequestDetails {{logRequestDetails}} --httpSysUrlPrefix {{httpSysUrlPrefix}}"
34+
arguments: "--urls {{serverScheme}}://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --httpSysLogs {{httpSysLogs}} --logRequestDetails {{logRequestDetails}} --httpSysUrlPrefix {{httpSysUrlPrefix}}"
3435

3536
kestrelServer:
3637
source:
@@ -39,6 +40,7 @@ jobs:
3940
project: src/BenchmarksApps/TLS/Kestrel/Kestrel.csproj
4041
readyStateText: Application started.
4142
variables:
43+
serverScheme: https
4244
# behavioral settings
4345
mTLS: false
4446
tlsRenegotiation: false
@@ -49,7 +51,7 @@ jobs:
4951
certValidationConsoleEnabled: false
5052
statsEnabled: false
5153
logRequestDetails: false
52-
arguments: "--urls https://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --tlsProtocols {{tlsProtocols}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --logRequestDetails {{logRequestDetails}} --enableHostHeaderValidation {{enableHostHeaderValidation}}"
54+
arguments: "--urls {{serverScheme}}://{{serverAddress}}:{{serverPort}} --mTLS {{mTLS}} --certValidationConsoleEnabled {{certValidationConsoleEnabled}} --tlsProtocols {{tlsProtocols}} --statsEnabled {{statsEnabled}} --tlsRenegotiation {{tlsRenegotiation}} --logRequestDetails {{logRequestDetails}} --enableHostHeaderValidation {{enableHostHeaderValidation}}"
5355

5456
scenarios:
5557

@@ -92,6 +94,21 @@ scenarios:
9294
customHeaders:
9395
- "Host: google.com"
9496

97+
httpsys-hostheader-mismatch-notls:
98+
application:
99+
job: httpSysServer
100+
variables:
101+
httpSysUrlPrefix: "http://testserver:{{serverPort}}"
102+
serverScheme: http
103+
load:
104+
job: wrk
105+
variables:
106+
path: /hello-world
107+
connections: 32
108+
serverScheme: http
109+
customHeaders:
110+
- "Host: google.com"
111+
95112
# Kestrel
96113

97114
kestrel-encoded-url:
@@ -131,3 +148,18 @@ scenarios:
131148
serverScheme: https
132149
customHeaders:
133150
- "Host: google.com"
151+
152+
kestrel-hostheader-mismatch-notls:
153+
application:
154+
job: kestrelServer
155+
variables:
156+
enableHostHeaderValidation: true
157+
serverScheme: http
158+
load:
159+
job: wrk
160+
variables:
161+
path: /hello-world
162+
connections: 32
163+
serverScheme: http
164+
customHeaders:
165+
- "Host: google.com"

src/BenchmarksApps/TLS/HttpSys/Program.cs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,30 @@
1616

1717
// endpoints
1818
var listeningEndpoints = builder.Configuration["urls"] ?? "https://localhost:5000/";
19-
var httpsIpPort = listeningEndpoints.Split(";").First(x => x.Contains("https")).Replace("https://", "");
19+
var httpsIpPort = listeningEndpoints.Split(";").FirstOrDefault(x => x.Contains("https"))?.Replace("https://", "");
20+
var httpOnly = httpsIpPort is null; // in case TLS is disabled. Only for debug purposes - this app is designed to measure TLS scenario
21+
if (httpOnly)
22+
{
23+
Console.WriteLine("[Note] Server scheme is HTTP, not HTTPS.");
24+
}
2025

2126
// debug
2227
var writeCertValidationEventsToConsole = bool.TryParse(builder.Configuration["certValidationConsoleEnabled"], out var certValidationConsoleEnabled) && certValidationConsoleEnabled;
2328
var statsEnabled = bool.TryParse(builder.Configuration["statsEnabled"], out var connectionStatsEnabledConfig) && connectionStatsEnabledConfig;
2429
var logRequestDetails = bool.TryParse(builder.Configuration["logRequestDetails"], out var logRequestDetailsConfig) && logRequestDetailsConfig;
2530

26-
var sslCertConfiguration = NetshConfigurator.PreConfigureNetsh(
27-
httpsIpPort,
31+
if (!httpOnly)
32+
{
33+
var sslCertConfiguration = NetshConfigurator.PreConfigureNetsh(
34+
httpsIpPort!,
2835
certPublicKeyLength: certPublicKeyLength,
2936
clientCertNegotiation: mTlsEnabled ? NetShFlag.Enable : NetShFlag.Disabled,
3037
disablesessionid: NetShFlag.Enable,
3138
enableSessionTicket: NetShFlag.Disabled);
3239

33-
// because app shutdown is on a timeout, we need to prepare the reset (pre-generate certificate)
34-
NetshConfigurator.PrepareResetNetsh(httpsIpPort, certPublicKeyLength: 4096);
40+
// because app shutdown is on a timeout, we need to prepare the reset (pre-generate certificate)
41+
NetshConfigurator.PrepareResetNetsh(httpsIpPort, certPublicKeyLength: 4096);
42+
}
3543

3644
#pragma warning disable CA1416 // Can be launched only on Windows (HttpSys)
3745
builder.WebHost.UseHttpSys(options =>
@@ -126,7 +134,10 @@
126134

127135
await app.StartAsync();
128136

129-
NetshConfigurator.LogCurrentSslCertBinding(httpsIpPort);
137+
if (!httpOnly)
138+
{
139+
NetshConfigurator.LogCurrentSslCertBinding(httpsIpPort!);
140+
}
130141

131142
Console.WriteLine("Application Info:");
132143
if (mTlsEnabled)
@@ -148,6 +159,9 @@
148159
await app.WaitForShutdownAsync();
149160
Console.WriteLine("Application stopped.");
150161

151-
Console.WriteLine("Starting netsh rollback configuration...");
152-
NetshConfigurator.ResetNetshConfiguration(httpsIpPort);
153-
Console.WriteLine($"Reset netsh (ipport={httpsIpPort}) completed.");
162+
if (!httpOnly)
163+
{
164+
Console.WriteLine("Starting netsh rollback configuration...");
165+
NetshConfigurator.ResetNetshConfiguration(httpsIpPort);
166+
Console.WriteLine($"Reset netsh (ipport={httpsIpPort}) completed.");
167+
}

src/BenchmarksApps/TLS/HttpSys/appsettings.Development.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
"httpSysLogs": "true",
1010
"tlsRenegotiation": "false",
1111
"certValidationConsoleEnabled": "false",
12-
"httpSysUrlPrefix": "https://testserver:5000"
12+
// "httpSysUrlPrefix": "https://testserver:5000",
13+
"httpOnly": "false"
1314
}

src/BenchmarksApps/TLS/Kestrel/Program.cs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,25 @@
2121
var certPublicKeySpecified = int.TryParse(builder.Configuration["certPublicKeyLength"], out var certPublicKeyConfig);
2222
var certPublicKeyLength = certPublicKeySpecified ? certPublicKeyConfig : 2048;
2323
var enableHostHeaderValidation = bool.TryParse(builder.Configuration["enableHostHeaderValidation"], out var enableHostHeaderValidationConfig) && enableHostHeaderValidationConfig;
24+
var supportedTlsVersions = ParseSslProtocols(builder.Configuration["tlsProtocols"]);
2425

2526
// endpoints
2627
var listeningEndpoints = builder.Configuration["urls"] ?? "https://localhost:5000/";
27-
var supportedTlsVersions = ParseSslProtocols(builder.Configuration["tlsProtocols"]);
28+
29+
// determine if listening is expected only on HTTP scheme
30+
var httpOnly = true;
31+
foreach (var endpoint in listeningEndpoints.Split([';'], StringSplitOptions.RemoveEmptyEntries))
32+
{
33+
var urlPrefix = UrlPrefix.Create(endpoint);
34+
if (urlPrefix.Scheme == "https")
35+
{
36+
httpOnly = false;
37+
}
38+
}
39+
if (httpOnly)
40+
{
41+
Console.WriteLine("[Note] Server scheme is HTTP, not HTTPS.");
42+
}
2843

2944
// debug
3045
var writeCertValidationEventsToConsole = bool.TryParse(builder.Configuration["certValidationConsoleEnabled"], out var certValidationConsoleEnabled) && certValidationConsoleEnabled;
@@ -71,6 +86,22 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
7186

7287
serverOptions.Listen(endpoint, listenOptions =>
7388
{
89+
var protocol = config["protocol"] ?? "";
90+
if (protocol.Equals("h2", StringComparison.OrdinalIgnoreCase))
91+
{
92+
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
93+
}
94+
else if (protocol.Equals("h2c", StringComparison.OrdinalIgnoreCase))
95+
{
96+
listenOptions.Protocols = HttpProtocols.Http2;
97+
}
98+
99+
if (httpOnly)
100+
{
101+
// all TLS related settings should be below
102+
return;
103+
}
104+
74105
var certificatePath = Path.Combine("certificates", $"testCert-{certPublicKeyLength}.pfx");
75106
Console.WriteLine($"Using certificate: {certificatePath}");
76107

@@ -107,16 +138,6 @@ void ConfigureListen(KestrelServerOptions serverOptions, IConfigurationRoot conf
107138
options.ClientCertificateValidation = AllowAnyCertificateValidationWithLogging;
108139
}
109140
});
110-
111-
var protocol = config["protocol"] ?? "";
112-
if (protocol.Equals("h2", StringComparison.OrdinalIgnoreCase))
113-
{
114-
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
115-
}
116-
else if (protocol.Equals("h2c", StringComparison.OrdinalIgnoreCase))
117-
{
118-
listenOptions.Protocols = HttpProtocols.Http2;
119-
}
120141
});
121142
}
122143
});
@@ -204,7 +225,11 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
204225
await app.StartAsync();
205226

206227
Console.WriteLine("Application Info:");
207-
LogOpenSSLVersion();
228+
if (!httpOnly)
229+
{
230+
LogOpenSSLVersion();
231+
Console.WriteLine($"\tsupported TLS versions: {supportedTlsVersions}");
232+
}
208233
if (mTlsEnabled)
209234
{
210235
Console.WriteLine($"\tmTLS is enabled (client cert is required)");
@@ -221,7 +246,6 @@ bool AllowAnyCertificateValidationWithLogging(X509Certificate2 certificate, X509
221246
{
222247
Console.WriteLine($"\tenabled logging stats to console");
223248
}
224-
Console.WriteLine($"\tsupported TLS versions: {supportedTlsVersions}");
225249
Console.WriteLine($"\tlistening endpoints: {listeningEndpoints}");
226250
Console.WriteLine("--------------------------------");
227251

src/BenchmarksApps/TLS/Kestrel/appsettings.Development.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
"mTLS": "false",
99
"tlsRenegotiation": "false",
1010
"certValidationConsoleEnabled": "false",
11-
"enableHostHeaderValidation": "false"
11+
"enableHostHeaderValidation": "false",
12+
"httpOnly": "false"
1213
}

0 commit comments

Comments
 (0)