Skip to content

Commit

Permalink
Added reverse proxy support
Browse files Browse the repository at this point in the history
  • Loading branch information
maaroen committed Nov 11, 2023
1 parent 4cc1fa2 commit 5a134d8
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 5 deletions.
18 changes: 18 additions & 0 deletions Models/ReverseProxySettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Fenrus.Models;

public class ReverseProxySettings
{
public bool DebugPrintRequestHeaders { get; set; }
public bool UseForwardedHeaders { get; set; }
public string[] KnownProxies { get; set; } = Array.Empty<string>();
public KnownNetwork KnownIpv4Network { get; set; } = new();
public KnownNetwork KnownIpv6Network { get; set; } = new();

}

public class KnownNetwork
{
public bool Enabled { get; set; }
public string IpAddress { get; set; }
public int PrefixLength { get; set; }
}
45 changes: 41 additions & 4 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System.Net;
using Blazored.Toast;
using Fenrus;
using Fenrus.Models;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.HttpOverrides;
using NUglify.Helpers;

if (args?.Any() == true && args[0] == "--init-config")
Expand All @@ -23,8 +26,15 @@
StartUpHelper.Run();

var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddEnvironmentVariables();
builder.Services.AddControllersWithViews();
builder.Services.AddMvc();
ReverseProxySettings reverseProxySettings = builder.Configuration.GetSection(nameof(ReverseProxySettings)).Get<ReverseProxySettings>();

if(reverseProxySettings.UseForwardedHeaders)
{
ConfigureUsingForwardedHeaders(builder, reverseProxySettings);
}
builder.Services.AddWebOptimizer(pipeline =>
{
pipeline.MinifyJsFiles("js/**/*.js");
Expand Down Expand Up @@ -83,16 +93,16 @@
options.ClientId = system.OAuthStrategyClientId;
options.ClientSecret = system.OAuthStrategySecret;
options.Authority = system.OAuthStrategyIssuerBaseUrl;

options.Scope.Add("email");
options.Scope.Add("openid");
options.Scope.Add("profile");
options.GetClaimsFromUserInfoEndpoint = true;
options.DisableTelemetry = true;
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.Prompt = "login";
return Task.CompletedTask;
if(reverseProxySettings.DebugPrintRequestHeaders)
Logger.DLog($"Request headers: {string.Join(Environment.NewLine, context.Request.Headers)}");
return Task.FromResult(0);
};
});
}
Expand All @@ -109,6 +119,8 @@

var app = builder.Build();

if(reverseProxySettings.UseForwardedHeaders)
app.UseForwardedHeaders();
bool debug = Environment.GetEnvironmentVariable("DEBUG") == "1";
app.UseWhen(context =>
{
Expand Down Expand Up @@ -184,4 +196,29 @@
Logger.ILog($"Fenrus v{Fenrus.Globals.Version} started");
app.Run();
Logger.ILog($"Fenrus v{Fenrus.Globals.Version} stopped");
workers.ForEach(x => x.Stop());
workers.ForEach(x => x.Stop());

void ConfigureUsingForwardedHeaders(WebApplicationBuilder webApplicationBuilder,
ReverseProxySettings reverseProxySettings1)
{
webApplicationBuilder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
foreach (var knownProxy in reverseProxySettings1.KnownProxies)
options.KnownProxies.Add(IPAddress.Parse($"{knownProxy}"));
if (reverseProxySettings1.KnownIpv4Network.Enabled)
{
if (string.IsNullOrWhiteSpace(reverseProxySettings1.KnownIpv4Network.IpAddress) ||
reverseProxySettings1.KnownIpv4Network.PrefixLength == 0)
throw new InvalidOperationException("Invalid IPv4 network configuration");
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse(reverseProxySettings1.KnownIpv4Network.IpAddress),
reverseProxySettings1.KnownIpv4Network.PrefixLength));
}

if (!reverseProxySettings1.KnownIpv6Network.Enabled) return;
if(string.IsNullOrWhiteSpace(reverseProxySettings1.KnownIpv6Network.IpAddress) || reverseProxySettings1.KnownIpv6Network.PrefixLength == 0)
throw new InvalidOperationException("Invalid IPv6 network configuration");
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse(reverseProxySettings1.KnownIpv6Network.IpAddress), reverseProxySettings1.KnownIpv6Network.PrefixLength));
});
}
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,25 @@ All the configuration is saved into LiteDB file, Fenrus.db. There is an encryp

---

### Reverse Proxy configuration

If you want to host Fenrus behind a ReverseProxy in combination with oauth authentication, you need to make sure that you are passing X-Forwarded-Proto and X-Forwarded-For headers from your reverse proxy to Fenrus.
Fenrus will use these headers to generate the correct urls for oauth authentication.

The following environment variables can be set to change the reverse proxy settings:

| Variable | Description | Default | Example |
|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|------------|----------------------------------|
| ReverseProxySettings__UseForwardedHeaders | Enable reverse proxy support, all the below settings are negated, if this setting is false | false | true |
| ReverseProxySettings__DebugPrintRequestHeaders | Print request headers to console, to verify if X-Forwarded-X headers are present | false | true |
| ReverseProxySettings__KnownProxies | String array of trusted proxy IP addresses | [] | ["192.168.2.15", "192.168.2.16"] |
| ReverseProxySettings__KnownIPv4Network__Enabled | Enable adding a Known IPv4 Network | true | false |
| ReverseProxySettings__KnownIPv4Network__IpAddress | Network network to add, for example 192.168.2.0/24 (the prefixLength, will be added in the below variable | "10.0.0.0" | "192.168.2.0" |
| ReverseProxySettings__KnownIPv4Network__PrefixLength | The prefix length for the Known network to add. | 8 | 24 |
| ReverseProxySettings__KnownIPv6Network__Enabled | Enable adding a Known IPv6 Network | true | false |
| ReverseProxySettings__KnownIPv6Network__IpAddress | Network network to add, for example fe80::/24 (the prefixLength, will be added in the below variable | "fe80::" | "fe80::" |
| ReverseProxySettings__KnownIPv6Network__PrefixLength | The prefix length for the Known network to add. | 64 | 24 |

## Getting Started

First, you need to register a user, you can do this on the login page by entering a username and password and clicking "Register" if no user with that username exists, a new one will be created.
Expand Down
17 changes: 16 additions & 1 deletion appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,20 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ReverseProxySettings": {
"DebugPrintRequestHeaders": false,
"UseForwardedHeaders": false,
"KnownProxies": [],
"KnownIPv4Network": {
"Enabled": true,
"IpAddress": "10.0.0.0",
"PrefixLength": 8
},
"KnownIPv6Network": {
"Enabled": false,
"IpAddress": "fe80::",
"PrefixLength": 64
}
}
}

0 comments on commit 5a134d8

Please sign in to comment.