Skip to content

Commit d9fb6b6

Browse files
committed
Fixes issues caused by Microsoft being more strict than the world really is
Now uses our own brand of managed websockets that works properly.
1 parent 943d1fa commit d9fb6b6

File tree

7 files changed

+51
-20
lines changed

7 files changed

+51
-20
lines changed

CitadelCore/CitadelCore.csproj

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
<PackageIconUrl />
1313
<RepositoryUrl>https://github.com/TechnikEmpire/CitadelCore</RepositoryUrl>
1414
<PackageTags>proxy filtering content-filtering transparent-proxy</PackageTags>
15-
<PackageReleaseNotes>Re-externalizes managed websockets.</PackageReleaseNotes>
15+
<PackageReleaseNotes>Now uses own websocket fork.
16+
Bypasses restrictions on GET requests to enable technically-illegal headers that everyone uses anyway, including Microsoft.</PackageReleaseNotes>
1617
<Title>CitadelCore</Title>
1718
<Summary>Transparent filtering HTTP/S and Websocket/WebsocketSecure proxy.</Summary>
1819
<Description>Transparent filtering HTTP/S and Websocket/WebsocketSecure proxy.</Description>
19-
<Version>3.7.2</Version>
20-
<AssemblyVersion>3.7.2.0</AssemblyVersion>
21-
<FileVersion>3.7.2.0</FileVersion>
20+
<Version>3.7.4</Version>
21+
<AssemblyVersion>3.7.4.0</AssemblyVersion>
22+
<FileVersion>3.7.4.0</FileVersion>
2223
</PropertyGroup>
2324

2425
<ItemGroup Label="dotnet pack instructions">
@@ -60,14 +61,14 @@
6061
</ItemGroup>
6162

6263
<ItemGroup>
64+
<PackageReference Include="CitadelCore.Websockets.Client.Managed" Version="1.1.1" />
6365
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="2.1.1" />
6466
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.1.1" />
6567
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.1.3" />
6668
<PackageReference Include="Microsoft.AspNetCore.WebSockets.Server" Version="0.1.0" />
6769
<PackageReference Include="Portable.BouncyCastle" Version="1.8.4" />
6870
<PackageReference Include="StreamExtended" Version="[1.0.81]" />
6971
<PackageReference Include="System.Memory" Version="4.5.1" />
70-
<PackageReference Include="System.Net.WebSockets.Client.Managed" Version="1.0.22" />
7172
</ItemGroup>
7273

7374
<!-- If you want to bundle the websocket lib internally!

CitadelCore/Extensions/HttpRequestMessageExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System;
1313
using System.Collections.Generic;
1414
using System.Collections.Specialized;
15+
using System.Linq;
1516
using System.Net.Http;
1617
using System.Threading;
1718

@@ -59,7 +60,7 @@ public static NameValueCollection PopulateHeaders(this HttpRequestMessage messag
5960
if (message.Content != null)
6061
{
6162
if (message.Content.Headers.TryAddWithoutValidation(key, headers.GetValues(key)))
62-
{
63+
{
6364
clonedCollection.Remove(key);
6465
}
6566
}

CitadelCore/Extensions/HttpResponseMessageExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System;
1313
using System.Collections.Generic;
1414
using System.Collections.Specialized;
15+
using System.Linq;
1516
using System.Net.Http;
1617
using System.Threading;
1718

CitadelCore/Net/Handlers/FilterHttpResponseHandler.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using CitadelCore.Net.Proxy;
1414
using Microsoft.AspNetCore.Http;
1515
using System;
16+
using System.Collections.Generic;
1617
using System.IO;
1718
using System.Net;
1819
using System.Net.Http;
@@ -57,6 +58,23 @@ internal class FilterHttpResponseHandler : AbstractFilterResponseHandler
5758
/// </summary>
5859
private static readonly System.Collections.Generic.HashSet<string> s_emptyExemptedHeaders = new System.Collections.Generic.HashSet<string>();
5960

61+
static FilterHttpResponseHandler()
62+
{
63+
// Use reflection to enable us to send a content-type with GET messages and such,
64+
// because Microsoft is ultra-strict with .NET, but breaks all the rules
65+
// with everything else.
66+
var invalidHeadersField = typeof(System.Net.Http.Headers.HttpRequestHeaders).GetField(
67+
"invalidHeaders",
68+
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) ??
69+
typeof(System.Net.Http.Headers.HttpRequestHeaders).GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
70+
71+
if (invalidHeadersField != null)
72+
{
73+
var invalidHeadersCollection = (HashSet<string>)invalidHeadersField.GetValue(null);
74+
invalidHeadersCollection.Remove("Content-Type");
75+
}
76+
}
77+
6078
/// <summary>
6179
/// Constructs a FilterHttpResponseHandler instance.
6280
/// </summary>

CitadelCore/Net/Handlers/FilterWebsocketHandler.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
using CitadelCore.Logging;
1111
using CitadelCore.Net.Http;
1212
using CitadelCore.Net.Proxy;
13+
using CitadelCore.Websockets.Managed;
1314
using Microsoft.AspNetCore.Http;
1415
using System;
1516
using System.Net.Http;
16-
using System.Net.WebSockets.Managed;
1717
using System.Text;
1818
using System.Text.RegularExpressions;
1919
using System.Threading;
@@ -63,7 +63,7 @@ public override async Task Handle(HttpContext context)
6363
{
6464
// First we need the URL for this connection, since it's been requested to be
6565
// upgraded to a websocket.
66-
var fullUrl = Microsoft.AspNetCore.Http.Extensions.UriHelper.GetDisplayUrl(context.Request);
66+
var fullUrl = Microsoft.AspNetCore.Http.Extensions.UriHelper.GetEncodedUrl(context.Request);
6767

6868
// Need to replate the scheme with appropriate websocket scheme.
6969
if (fullUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
@@ -130,6 +130,24 @@ public override async Task Handle(HttpContext context)
130130
// Connect the server websocket to the upstream, remote webserver.
131131
await wsServer.ConnectAsync(wsUri, context.RequestAborted);
132132

133+
foreach (string key in wsServer.ResponseHeaders)
134+
{
135+
if (!ForbiddenWsHeaders.IsForbidden(key))
136+
{
137+
try
138+
{
139+
var value = wsServer.ResponseHeaders[key];
140+
context.Response.Headers[key] = wsServer.ResponseHeaders[key];
141+
}
142+
catch (Exception hdrException)
143+
{
144+
LoggerProxy.Default.Error(hdrException);
145+
}
146+
}
147+
}
148+
149+
Console.WriteLine();
150+
133151
// Create, via acceptor, the client websocket. This is the local machine's websocket.
134152
wsClient = await context.WebSockets.AcceptWebSocketAsync(wsServer.SubProtocol ?? null);
135153

CitadelCore/Net/Http/ForbiddenWsHeaders.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ internal static class ForbiddenWsHeaders
3737
// Don't set the version for our client socket. Microsoft sets this all by themselves.
3838
"Sec-WebSocket-Version",
3939

40+
"Sec-WebSocket-Accept",
41+
4042
// We manually add cookies so we don't want them this way.
4143
"Cookie",
4244

CitadelCore/Net/Proxy/ProxyServer.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,7 @@ public void Configure(IApplicationBuilder app)
447447
app.UseResponseCompression();
448448

449449
// We proxy websockets, so enable this.
450-
var wsOpts = new WebSocketOptions
451-
{
452-
ReceiveBufferSize = (int)(ushort.MaxValue * 5)
453-
};
454-
455-
app.UseWebSockets(wsOpts);
450+
app.UseWebSockets();
456451

457452
// Exception handler. Not yet sure what to do here.
458453
app.UseExceptionHandler(
@@ -521,12 +516,7 @@ public void Configure(IApplicationBuilder app)
521516
app.UseResponseCompression();
522517

523518
// We proxy websockets, so enable this.
524-
var wsOpts = new WebSocketOptions
525-
{
526-
ReceiveBufferSize = (int)(ushort.MaxValue * 5)
527-
};
528-
529-
app.UseWebSockets(wsOpts);
519+
app.UseWebSockets();
530520

531521
// Exception handler. Not yet sure what to do here.
532522
app.UseExceptionHandler(

0 commit comments

Comments
 (0)