Skip to content

Commit

Permalink
More robust redirect detection and routing
Browse files Browse the repository at this point in the history
  • Loading branch information
Cellivar committed Mar 14, 2021
1 parent e6ff9fd commit 01b1405
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
27 changes: 22 additions & 5 deletions NetGoLynx/Redirects/RedirectWebUIRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;

namespace NetGoLynx.Redirects
Expand All @@ -13,8 +14,10 @@ namespace NetGoLynx.Redirects
public class RedirectWebUIRule : IRule
{
private readonly Uri _hostToRedirectTo;
private readonly ILogger _logger;
private readonly string _redirectScheme;
private readonly string _redirectHost;
private readonly bool _skipPortCheck;

private readonly PathString _apiPrefix = new PathString("/_");
private readonly PathString _healthcheckPrefix = new PathString("/_/health");
Expand All @@ -23,11 +26,19 @@ public class RedirectWebUIRule : IRule
/// Instantiates a new instance of the <see cref="RedirectWebUIRule"/> class.
/// </summary>
/// <param name="hostToRedirectTo">The URI to redirect to if not already on that host.</param>
public RedirectWebUIRule(Uri hostToRedirectTo)
/// <param name="logger">The logger to use for logging</param>
public RedirectWebUIRule(Uri hostToRedirectTo, ILogger logger)
{
_hostToRedirectTo = hostToRedirectTo;
_logger = logger;

// Precalculate some details to save time on actual redirect analysis.
_redirectScheme = _hostToRedirectTo.Scheme.ToLowerInvariant();
_redirectHost = _hostToRedirectTo.Host.ToLowerInvariant();

// The port on the request will be omitted if it matches the scheme's default port.
_skipPortCheck = (_redirectScheme == "http" && _hostToRedirectTo.Port == 80)
|| (_redirectScheme == "https" && _hostToRedirectTo.Port == 443);
}

/// <inheritdoc/>
Expand All @@ -42,15 +53,14 @@ public void ApplyRule(RewriteContext context)
return;
}

// If the request matches the expected host it shouldn't be redirected.
if ((request.Host.Host.ToLowerInvariant() == _redirectHost)
&& request.Host.Port == _hostToRedirectTo.Port
&& (request.Scheme == _redirectScheme))
if (RequestMatchesExpectedHost(request))
{
context.Result = RuleResult.ContinueRules;
return;
}

_logger.LogDebug($"{nameof(RedirectWebUIRule)}: Redirect from {request.Scheme}://{request.Host.Host}:{request.Host.Port} to {_redirectScheme}://{_redirectHost}:{_hostToRedirectTo.Port}");

var destination = new UriBuilder(request.GetDisplayUrl())
{
Host = _hostToRedirectTo.Host,
Expand All @@ -63,5 +73,12 @@ public void ApplyRule(RewriteContext context)
response.Headers[HeaderNames.Location] = destination.ToString();
context.Result = RuleResult.EndResponse;
}

private bool RequestMatchesExpectedHost(HttpRequest request)
{
return (request.Host.Host.ToLowerInvariant() == _redirectHost)
&& (request.Scheme.ToLowerInvariant() == _redirectScheme)
&& (_skipPortCheck || (request.Host.Port == _hostToRedirectTo.Port));
}
}
}
11 changes: 10 additions & 1 deletion NetGoLynx/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NetGoLynx.Data;
using NetGoLynx.Models.Configuration;
using NetGoLynx.Models.Configuration.Authentication;
Expand Down Expand Up @@ -164,12 +165,20 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseAuthentication();
app.UseAuthorization();

// Create a simple logger for debugging purposes.
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConfiguration(Configuration);
builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<Startup>();

// If there are proxy settings there should probably be a host to redirect the web UI to.
var proxySettings = Configuration.GetSection("ProxyNetworks").Get<ProxyNetworks>();
if (proxySettings != null && proxySettings.WebInterfaceHost != null)
{
app.UseRewriter(new RewriteOptions()
.Add(new RedirectWebUIRule(proxySettings.WebInterfaceHost)));
.Add(new RedirectWebUIRule(proxySettings.WebInterfaceHost, logger)));
}

app.UseEndpoints(endpoints =>
Expand Down

0 comments on commit 01b1405

Please sign in to comment.