From 35a30c9d098e7ac5fcaf7d86a4cc616deb8a2cfa Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Fri, 8 Jan 2021 00:05:15 +0000 Subject: [PATCH 01/20] Impliments KnownNetworks and KnownProxies --- .../Configuration/NetworkConfiguration.cs | 2 +- Jellyfin.Networking/Manager/NetworkManager.cs | 95 +++++++++----- .../ApiServiceCollectionExtensions.cs | 120 ++++++++++++++++-- Jellyfin.Server/Startup.cs | 8 +- MediaBrowser.Common/Net/INetworkManager.cs | 16 +++ tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 95 ++++++++++++++ 6 files changed, 285 insertions(+), 51 deletions(-) create mode 100644 tests/Jellyfin.Api.Tests/ParseNetworkTests.cs diff --git a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs index 792e57f6ab..91bf0015fd 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs @@ -224,7 +224,7 @@ namespace Jellyfin.Networking.Configuration public string[] LocalNetworkAddresses { get; set; } = Array.Empty(); /// - /// Gets or sets the known proxies. + /// Gets or sets the known proxies. If the proxy is a network, it's added to the KnownNetworks. /// public string[] KnownProxies { get; set; } = Array.Empty(); } diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 60b899519e..e2fe440608 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -139,6 +139,16 @@ namespace Jellyfin.Networking.Manager /// public bool IsIP4Enabled { get; set; } + /// + /// Gets or sets a value indicating whether the system has IP4 is enabled. + /// + public bool SystemIP4Enabled { get; set; } + + /// + /// Gets or sets a value indicating whether the system has IP6 is enabled. + /// + public bool SystemIP6Enabled { get; set; } + /// public Collection RemoteAddressFilter { get; private set; } @@ -185,6 +195,15 @@ namespace Jellyfin.Networking.Manager return _macAddresses; } + /// + /// REMOVE after debugging. + /// + /// Message. + public void Log(string msg) + { + _logger.LogInformation(msg); + } + /// public bool IsGatewayInterface(IPObject? addressObj) { @@ -1047,47 +1066,55 @@ namespace Jellyfin.Networking.Manager // populate interface address list foreach (UnicastIPAddressInformation info in ipProperties.UnicastAddresses) { - if (IsIP4Enabled && info.Address.AddressFamily == AddressFamily.InterNetwork) + if (info.Address.AddressFamily == AddressFamily.InterNetwork) { - IPNetAddress nw = new IPNetAddress(info.Address, IPObject.MaskToCidr(info.IPv4Mask)) - { - // Keep the number of gateways on this interface, along with its index. - Tag = ipProperties.GetIPv4Properties().Index - }; - - int tag = nw.Tag; - if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) + SystemIP4Enabled = true; + if (IsIP4Enabled) { - // -ve Tags signify the interface has a gateway. - nw.Tag *= -1; + IPNetAddress nw = new IPNetAddress(info.Address, IPObject.MaskToCidr(info.IPv4Mask)) + { + // Keep the number of gateways on this interface, along with its index. + Tag = ipProperties.GetIPv4Properties().Index + }; + + int tag = nw.Tag; + if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) + { + // -ve Tags signify the interface has a gateway. + nw.Tag *= -1; + } + + _interfaceAddresses.AddItem(nw); + + // Store interface name so we can use the name in Collections. + _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; + _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; } - - _interfaceAddresses.AddItem(nw); - - // Store interface name so we can use the name in Collections. - _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; - _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; } - else if (IsIP6Enabled && info.Address.AddressFamily == AddressFamily.InterNetworkV6) + else if (info.Address.AddressFamily == AddressFamily.InterNetworkV6) { - IPNetAddress nw = new IPNetAddress(info.Address, (byte)info.PrefixLength) + SystemIP6Enabled = true; + if (IsIP6Enabled) { - // Keep the number of gateways on this interface, along with its index. - Tag = ipProperties.GetIPv6Properties().Index - }; - - int tag = nw.Tag; - if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) - { - // -ve Tags signify the interface has a gateway. - nw.Tag *= -1; + IPNetAddress nw = new IPNetAddress(info.Address, (byte)info.PrefixLength) + { + // Keep the number of gateways on this interface, along with its index. + Tag = ipProperties.GetIPv6Properties().Index + }; + + int tag = nw.Tag; + if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) + { + // -ve Tags signify the interface has a gateway. + nw.Tag *= -1; + } + + _interfaceAddresses.AddItem(nw); + + // Store interface name so we can use the name in Collections. + _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; + _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; } - - _interfaceAddresses.AddItem(nw); - - // Store interface name so we can use the name in Collections. - _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; - _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; } } } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index bbfc4fbd4c..4f6329f824 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net; +using System.Net.Sockets; using System.Reflection; +using System.Text; using Emby.Server.Implementations; using Jellyfin.Api.Auth; using Jellyfin.Api.Auth.DefaultAuthorizationPolicy; @@ -20,6 +23,7 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Controllers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; +using Jellyfin.Networking.Configuration; using Jellyfin.Server.Configuration; using Jellyfin.Server.Filters; using Jellyfin.Server.Formatters; @@ -169,36 +173,124 @@ namespace Jellyfin.Server.Extensions .AddScheme(AuthenticationSchemes.CustomAuthentication, null); } + /// + /// Sets up the proxy configuration based on the addresses in . + /// + /// The instance. + /// The containing the config settings. + /// The string array to parse. + /// The instance. + public static void ParseList(INetworkManager networkManager, NetworkConfiguration config, string[] userList, ForwardedHeadersOptions options) + { + for (var i = 0; i < userList.Length; i++) + { + if (IPNetAddress.TryParse(userList[i], out var addr)) + { + if ((!config.EnableIPV4 && addr.AddressFamily == AddressFamily.InterNetwork) + || (!config.EnableIPV6 && addr.AddressFamily == AddressFamily.InterNetworkV6)) + { + continue; + } + + if (networkManager.SystemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork) + { + // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. + // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . + addr.Address = addr.Address.MapToIPv6(); + } + + if (addr.PrefixLength == 32) + { + options.KnownProxies.Add(addr.Address); + } + else + { + options.KnownNetworks.Add(new IPNetwork(addr.Address, addr.PrefixLength)); + } + } + else if (IPHost.TryParse(userList[i], out var host)) + { + foreach (var address in host.GetAddresses()) + { + if ((!config.EnableIPV4 && host.AddressFamily == AddressFamily.InterNetwork) + || (!config.EnableIPV6 && host.AddressFamily == AddressFamily.InterNetworkV6)) + { + continue; + } + + var hostAddr = address; + if (networkManager.SystemIP6Enabled && address.AddressFamily == AddressFamily.InterNetwork) + { + // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. + // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . + hostAddr = address.MapToIPv6(); + } + + options.KnownProxies.Add(hostAddr); + } + } + } + } + + private static string EnumToString(IEnumerable x) + { + var sb = new StringBuilder(); + foreach (var item in x) + { + if (item is IPAddress ipItem) + { + sb.Append(ipItem.ToString()); + } + else if (item is IPNetwork ipNetwork) + { + sb.Append(ipNetwork.Prefix.ToString()); + sb.Append('/'); + sb.Append(ipNetwork.PrefixLength.ToString(CultureInfo.InvariantCulture)); + sb.Append(','); + } + } + + return sb.ToString(); + } + /// /// Extension method for adding the jellyfin API to the service collection. /// /// The service collection. /// An IEnumerable containing all plugin assemblies with API controllers. - /// A list of all known proxies to trust for X-Forwarded-For. + /// The . + /// The instance. /// The MVC builder. - public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable pluginAssemblies, IReadOnlyList knownProxies) + public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable pluginAssemblies, NetworkConfiguration config, INetworkManager networkManager) { IMvcBuilder mvcBuilder = serviceCollection - .AddCors() - .AddTransient() - .Configure(options => + .AddCors() + .AddTransient() + .Configure(options => { + // https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/HttpOverrides/src/ForwardedHeadersMiddleware.cs + // Enable debug logging on Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware to help investigate issues. + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; - if (knownProxies.Count == 0) + if (config.KnownProxies.Length == 0) { - options.KnownNetworks.Clear(); options.KnownProxies.Clear(); + options.KnownNetworks.Clear(); } else { - for (var i = 0; i < knownProxies.Count; i++) - { - if (IPHost.TryParse(knownProxies[i], out var host)) - { - options.KnownProxies.Add(host.Address); - } - } + ParseList(networkManager, config, config.KnownProxies, options); + networkManager.Log("KnownProxies: " + EnumToString(options.KnownProxies)); + networkManager.Log("KnownNetworks: " + EnumToString(options.KnownNetworks)); + } + + // Only set forward limit if we have some known proxies or some known networks. + if (options.KnownProxies.Count != 0 || options.KnownNetworks.Count != 0) + { + options.ForwardLimit = null; } + + networkManager.Log("Forward Limit : " + options.ForwardLimit?.ToString(CultureInfo.CurrentCulture) ?? "None"); }) .AddMvc(opts => { diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 3395d2413f..05228ccaab 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -26,18 +26,22 @@ namespace Jellyfin.Server { private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerApplicationHost _serverApplicationHost; + private readonly INetworkManager _networkManager; /// /// Initializes a new instance of the class. /// /// The server configuration manager. /// The server application host. + /// The network manager. public Startup( IServerConfigurationManager serverConfigurationManager, - IServerApplicationHost serverApplicationHost) + IServerApplicationHost serverApplicationHost, + INetworkManager networkManager) { _serverConfigurationManager = serverConfigurationManager; _serverApplicationHost = serverApplicationHost; + _networkManager = networkManager; } /// @@ -52,7 +56,7 @@ namespace Jellyfin.Server { options.HttpsPort = _serverApplicationHost.HttpsPort; }); - services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration().KnownProxies); + services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration(), _networkManager); services.AddJellyfinApiSwagger(); diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index b6c390d239..455fbe27a6 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -44,6 +44,16 @@ namespace MediaBrowser.Common.Net /// bool IsIP4Enabled { get; set; } + /// + /// Gets or sets a value indicating whether the system has IP4 is enabled. + /// + public bool SystemIP4Enabled { get; set; } + + /// + /// Gets or sets a value indicating whether the system has IP6 is enabled. + /// + public bool SystemIP6Enabled { get; set; } + /// /// Calculates the list of interfaces to use for Kestrel. /// @@ -229,5 +239,11 @@ namespace MediaBrowser.Common.Net /// Optional filter for the list. /// Returns a filtered list of LAN addresses. Collection GetFilteredLANSubnets(Collection? filter = null); + + /// + /// REMOVE after debugging. + /// + /// Message. + void Log(string msg); } } diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs new file mode 100644 index 0000000000..3a9f0a0790 --- /dev/null +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Jellyfin.Networking.Configuration; +using Jellyfin.Networking.Manager; +using Jellyfin.Server.Extensions; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.Api.Tests +{ + public class ParseNetworkTests + { + private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) + { + var configManager = new Mock + { + CallBase = true + }; + configManager.Setup(x => x.GetConfiguration(It.IsAny())).Returns(conf); + return (IConfigurationManager)configManager.Object; + } + + private static NetworkManager CreateNetworkManager() + { + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + }; + + return new NetworkManager(GetMockConfig(conf), new NullLogger()); + } + + /// + /// Order of the result has always got to be hosts, then networks. + /// + /// IP4 enabled. + /// IP6 enabled. + /// List to parse. + /// What it should match. + [Theory] + [InlineData(true, true, "192.168.0.0/16,www.yahoo.co.uk", "::ffff:212.82.100.150,::ffff:192.168.0.0/16")] + [InlineData(true, false, "192.168.0.0/16,www.yahoo.co.uk", "212.82.100.150,192.168.0.0/16")] + [InlineData(true, true, "192.168.t,127.0.0.1,1234.1232.12.1234", "::ffff:127.0.0.1")] + [InlineData(true, false, "192.168.x,127.0.0.1,1234.1232.12.1234", "127.0.0.1")] + [InlineData(true, true, "::1", "::1/128")] + public void TestNetworks(bool ip4, bool ip6, string hostList, string match) + { + using var nm = CreateNetworkManager(); + nm.SystemIP6Enabled = ip6; + + var settings = new NetworkConfiguration(); + settings.EnableIPV4 = ip4; + settings.EnableIPV6 = ip6; + + var result = match + ','; + ForwardedHeadersOptions options = new ForwardedHeadersOptions(); + + // Need this here as ::1 and 127.0.0.1 are in them by default. + options.KnownProxies.Clear(); + options.KnownNetworks.Clear(); + + ApiServiceCollectionExtensions.ParseList(nm, settings, hostList.Split(","), options); + + var sb = new StringBuilder(); + foreach (var item in options.KnownProxies) + { + sb.Append(item.ToString()); + sb.Append(','); + } + + foreach (var item in options.KnownNetworks) + { + sb.Append(item.Prefix.ToString()); + sb.Append('/'); + sb.Append(item.PrefixLength.ToString(CultureInfo.InvariantCulture)); + sb.Append(','); + } + + if (!string.Equals(sb.ToString(), result, StringComparison.OrdinalIgnoreCase)) + { + throw new Exception("Not matched: " + sb.ToString() + " does not match " + result); + } + } + } +} From 2979c8dd377bf0948be00082b97416b38c21de56 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 12 Jan 2021 13:23:10 +0000 Subject: [PATCH 02/20] Fixed test on Mac --- Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 2 +- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 4f6329f824..2d03c129e2 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -274,8 +274,8 @@ namespace Jellyfin.Server.Extensions options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; if (config.KnownProxies.Length == 0) { - options.KnownProxies.Clear(); options.KnownNetworks.Clear(); + options.KnownProxies.Clear(); } else { diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index 3a9f0a0790..f4ea45cc2b 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -48,8 +48,8 @@ namespace Jellyfin.Api.Tests /// List to parse. /// What it should match. [Theory] - [InlineData(true, true, "192.168.0.0/16,www.yahoo.co.uk", "::ffff:212.82.100.150,::ffff:192.168.0.0/16")] - [InlineData(true, false, "192.168.0.0/16,www.yahoo.co.uk", "212.82.100.150,192.168.0.0/16")] + // [InlineData(true, true, "192.168.0.0/16,www.yahoo.co.uk", "::ffff:212.82.100.150,::ffff:192.168.0.0/16")] <- fails on Max. www.yahoo.co.uk resolves to a different ip address. + // [InlineData(true, false, "192.168.0.0/16,www.yahoo.co.uk", "212.82.100.150,192.168.0.0/16")] [InlineData(true, true, "192.168.t,127.0.0.1,1234.1232.12.1234", "::ffff:127.0.0.1")] [InlineData(true, false, "192.168.x,127.0.0.1,1234.1232.12.1234", "127.0.0.1")] [InlineData(true, true, "::1", "::1/128")] From 08e83cfa54a9c5ca9b33ad71731825dcb1f79442 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 12 Jan 2021 18:52:48 +0000 Subject: [PATCH 03/20] Remove additional debug logging. --- Jellyfin.Networking/Manager/NetworkManager.cs | 9 ------- .../ApiServiceCollectionExtensions.cs | 25 ------------------- MediaBrowser.Common/Net/INetworkManager.cs | 6 ----- 3 files changed, 40 deletions(-) diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index e2fe440608..c9f900660b 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -195,15 +195,6 @@ namespace Jellyfin.Networking.Manager return _macAddresses; } - /// - /// REMOVE after debugging. - /// - /// Message. - public void Log(string msg) - { - _logger.LogInformation(msg); - } - /// public bool IsGatewayInterface(IPObject? addressObj) { diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 2d03c129e2..dae57b2273 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -232,27 +232,6 @@ namespace Jellyfin.Server.Extensions } } - private static string EnumToString(IEnumerable x) - { - var sb = new StringBuilder(); - foreach (var item in x) - { - if (item is IPAddress ipItem) - { - sb.Append(ipItem.ToString()); - } - else if (item is IPNetwork ipNetwork) - { - sb.Append(ipNetwork.Prefix.ToString()); - sb.Append('/'); - sb.Append(ipNetwork.PrefixLength.ToString(CultureInfo.InvariantCulture)); - sb.Append(','); - } - } - - return sb.ToString(); - } - /// /// Extension method for adding the jellyfin API to the service collection. /// @@ -280,8 +259,6 @@ namespace Jellyfin.Server.Extensions else { ParseList(networkManager, config, config.KnownProxies, options); - networkManager.Log("KnownProxies: " + EnumToString(options.KnownProxies)); - networkManager.Log("KnownNetworks: " + EnumToString(options.KnownNetworks)); } // Only set forward limit if we have some known proxies or some known networks. @@ -289,8 +266,6 @@ namespace Jellyfin.Server.Extensions { options.ForwardLimit = null; } - - networkManager.Log("Forward Limit : " + options.ForwardLimit?.ToString(CultureInfo.CurrentCulture) ?? "None"); }) .AddMvc(opts => { diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 455fbe27a6..eb7e9ee615 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -239,11 +239,5 @@ namespace MediaBrowser.Common.Net /// Optional filter for the list. /// Returns a filtered list of LAN addresses. Collection GetFilteredLANSubnets(Collection? filter = null); - - /// - /// REMOVE after debugging. - /// - /// Message. - void Log(string msg); } } From 94cc5b9d8b885a32adedfad67da4f36fbaf69914 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 12 Jan 2021 20:41:40 +0000 Subject: [PATCH 04/20] Update MediaBrowser.Common/Net/INetworkManager.cs Co-authored-by: Cody Robibero --- MediaBrowser.Common/Net/INetworkManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index eb7e9ee615..5862328b42 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -52,7 +52,7 @@ namespace MediaBrowser.Common.Net /// /// Gets or sets a value indicating whether the system has IP6 is enabled. /// - public bool SystemIP6Enabled { get; set; } + bool SystemIP6Enabled { get; set; } /// /// Calculates the list of interfaces to use for Kestrel. From dfd7ff573200509def414a030152054f4d67c835 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 12 Jan 2021 20:41:48 +0000 Subject: [PATCH 05/20] Update MediaBrowser.Common/Net/INetworkManager.cs Co-authored-by: Cody Robibero --- MediaBrowser.Common/Net/INetworkManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 5862328b42..7ee76107bc 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Common.Net /// /// Gets or sets a value indicating whether the system has IP4 is enabled. /// - public bool SystemIP4Enabled { get; set; } + bool SystemIP4Enabled { get; set; } /// /// Gets or sets a value indicating whether the system has IP6 is enabled. From d66bc3fb3e3256353c2643e372905b74a55774d4 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 12 Jan 2021 20:43:25 +0000 Subject: [PATCH 06/20] Fixed indentation --- .../Extensions/ApiServiceCollectionExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index dae57b2273..86b98db0a7 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -243,9 +243,9 @@ namespace Jellyfin.Server.Extensions public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable pluginAssemblies, NetworkConfiguration config, INetworkManager networkManager) { IMvcBuilder mvcBuilder = serviceCollection - .AddCors() - .AddTransient() - .Configure(options => + .AddCors() + .AddTransient() + .Configure(options => { // https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/HttpOverrides/src/ForwardedHeadersMiddleware.cs // Enable debug logging on Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware to help investigate issues. From 9a730241b1f2bee8601d4d2e4883908868c2b4a8 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Wed, 13 Jan 2021 15:14:04 +0000 Subject: [PATCH 07/20] Changed to address. --- Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 86b98db0a7..6690ad1c9f 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -212,8 +212,8 @@ namespace Jellyfin.Server.Extensions { foreach (var address in host.GetAddresses()) { - if ((!config.EnableIPV4 && host.AddressFamily == AddressFamily.InterNetwork) - || (!config.EnableIPV6 && host.AddressFamily == AddressFamily.InterNetworkV6)) + if ((!config.EnableIPV4 && address.AddressFamily == AddressFamily.InterNetwork) + || (!config.EnableIPV6 && address.AddressFamily == AddressFamily.InterNetworkV6)) { continue; } From 4bc8a1e77beacb607ac221cc8d37f30e16dd4984 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Wed, 13 Jan 2021 15:29:57 +0000 Subject: [PATCH 08/20] updated --- Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 6690ad1c9f..bd72b1e27d 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; using Emby.Server.Implementations; using Jellyfin.Api.Auth; @@ -42,6 +43,8 @@ using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes; +[assembly: InternalsVisibleTo("Jellyfin.Api.Tests")] + namespace Jellyfin.Server.Extensions { /// @@ -180,7 +183,7 @@ namespace Jellyfin.Server.Extensions /// The containing the config settings. /// The string array to parse. /// The instance. - public static void ParseList(INetworkManager networkManager, NetworkConfiguration config, string[] userList, ForwardedHeadersOptions options) + internal static void ParseList(INetworkManager networkManager, NetworkConfiguration config, string[] userList, ForwardedHeadersOptions options) { for (var i = 0; i < userList.Length; i++) { From bced1eab54180c1dd60d884dd03adb5207a4a20b Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Wed, 13 Jan 2021 21:16:04 +0000 Subject: [PATCH 09/20] Assert.True --- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index f4ea45cc2b..ca7b8a965b 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -1,15 +1,10 @@ using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Net; using System.Text; -using System.Threading.Tasks; using Jellyfin.Networking.Configuration; using Jellyfin.Networking.Manager; using Jellyfin.Server.Extensions; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Logging.Abstractions; using Moq; @@ -86,10 +81,7 @@ namespace Jellyfin.Api.Tests sb.Append(','); } - if (!string.Equals(sb.ToString(), result, StringComparison.OrdinalIgnoreCase)) - { - throw new Exception("Not matched: " + sb.ToString() + " does not match " + result); - } + Assert.True(string.Equals(sb.ToString(), result, StringComparison.OrdinalIgnoreCase), "Not matched: " + sb.ToString() + " does not match " + result); } } } From 688e7c6a2d7748cdcad64c557d3e5a01b0a1590f Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sun, 17 Jan 2021 12:45:11 +0000 Subject: [PATCH 10/20] Moved internalVisibleToAttribute to .csj --- .../Extensions/ApiServiceCollectionExtensions.cs | 2 -- Jellyfin.Server/Jellyfin.Server.csproj | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index bd72b1e27d..73a2265dec 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -43,8 +43,6 @@ using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes; -[assembly: InternalsVisibleTo("Jellyfin.Api.Tests")] - namespace Jellyfin.Server.Extensions { /// diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 5940cf9389..cfec2d82fe 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -36,6 +36,12 @@ ../jellyfin.ruleset + + + <_Parameter1>Jellyfin.Api.Tests + + + From b9f0f4f53bdacc6abb7f449cdf7149525cd6119c Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sun, 17 Jan 2021 13:35:30 +0000 Subject: [PATCH 11/20] reverted --- .../ApiServiceCollectionExtensions.cs | 2 + Jellyfin.Server/Jellyfin.Server.csproj | 12 ++--- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 50 ++++++++++--------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 73a2265dec..bd72b1e27d 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -43,6 +43,8 @@ using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes; +[assembly: InternalsVisibleTo("Jellyfin.Api.Tests")] + namespace Jellyfin.Server.Extensions { /// diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index cfec2d82fe..f91f2db02b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -36,12 +36,6 @@ ../jellyfin.ruleset - - - <_Parameter1>Jellyfin.Api.Tests - - - @@ -79,4 +73,10 @@ + + + <_Parameter1>Jellyfin.Api.Tests + + + diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index ca7b8a965b..6ee66d2a8f 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -14,27 +14,6 @@ namespace Jellyfin.Api.Tests { public class ParseNetworkTests { - private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) - { - var configManager = new Mock - { - CallBase = true - }; - configManager.Setup(x => x.GetConfiguration(It.IsAny())).Returns(conf); - return (IConfigurationManager)configManager.Object; - } - - private static NetworkManager CreateNetworkManager() - { - var conf = new NetworkConfiguration() - { - EnableIPV6 = true, - EnableIPV4 = true, - }; - - return new NetworkManager(GetMockConfig(conf), new NullLogger()); - } - /// /// Order of the result has always got to be hosts, then networks. /// @@ -53,9 +32,11 @@ namespace Jellyfin.Api.Tests using var nm = CreateNetworkManager(); nm.SystemIP6Enabled = ip6; - var settings = new NetworkConfiguration(); - settings.EnableIPV4 = ip4; - settings.EnableIPV6 = ip6; + var settings = new NetworkConfiguration + { + EnableIPV4 = ip4, + EnableIPV6 = ip6 + }; var result = match + ','; ForwardedHeadersOptions options = new ForwardedHeadersOptions(); @@ -83,5 +64,26 @@ namespace Jellyfin.Api.Tests Assert.True(string.Equals(sb.ToString(), result, StringComparison.OrdinalIgnoreCase), "Not matched: " + sb.ToString() + " does not match " + result); } + + private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) + { + var configManager = new Mock + { + CallBase = true + }; + configManager.Setup(x => x.GetConfiguration(It.IsAny())).Returns(conf); + return (IConfigurationManager)configManager.Object; + } + + private static NetworkManager CreateNetworkManager() + { + var conf = new NetworkConfiguration() + { + EnableIPV6 = true, + EnableIPV4 = true, + }; + + return new NetworkManager(GetMockConfig(conf), new NullLogger()); + } } } From 49e3b70722abe8982da015f3a57d9a23b984ea59 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Mon, 18 Jan 2021 13:03:37 +0000 Subject: [PATCH 12/20] Moved InternalsVisibleTo --- .../Extensions/ApiServiceCollectionExtensions.cs | 2 -- Jellyfin.Server/Jellyfin.Server.csproj | 6 ------ Jellyfin.Server/Properties/AssemblyInfo.cs | 3 +++ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index bd72b1e27d..73a2265dec 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -43,8 +43,6 @@ using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes; -[assembly: InternalsVisibleTo("Jellyfin.Api.Tests")] - namespace Jellyfin.Server.Extensions { /// diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index f91f2db02b..5940cf9389 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -73,10 +73,4 @@ - - - <_Parameter1>Jellyfin.Api.Tests - - - diff --git a/Jellyfin.Server/Properties/AssemblyInfo.cs b/Jellyfin.Server/Properties/AssemblyInfo.cs index 5de1e653d9..7abf298b12 100644 --- a/Jellyfin.Server/Properties/AssemblyInfo.cs +++ b/Jellyfin.Server/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Resources; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -19,3 +20,5 @@ using System.Runtime.InteropServices; // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] + +[assembly: InternalsVisibleTo("Jellyfin.Api.Tests")] From 8b2b3b77a548bf5e46e1cb6931ecaaf81a8ca751 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 10:29:17 +0000 Subject: [PATCH 13/20] Removed duplication --- .../ApiServiceCollectionExtensions.cs | 62 ++++++++----------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 73a2265dec..9b4e53fc09 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -174,6 +174,30 @@ namespace Jellyfin.Server.Extensions .AddScheme(AuthenticationSchemes.CustomAuthentication, null); } + private static void AddIpAddress(NetworkConfiguration config, ForwardedHeadersOptions options, IPAddress addr, int prefixLength, bool systemIP6Enabled) + { + if ((!config.EnableIPV4 && addr.AddressFamily == AddressFamily.InterNetwork) || (!config.EnableIPV6 && addr.AddressFamily == AddressFamily.InterNetworkV6)) + { + return; + } + + if (systemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork) + { + // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. + // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . + addr = addr.MapToIPv6(); + } + + if (prefixLength == 32) + { + options.KnownProxies.Add(addr); + } + else + { + options.KnownNetworks.Add(new IPNetwork(addr, prefixLength)); + } + } + /// /// Sets up the proxy configuration based on the addresses in . /// @@ -187,47 +211,13 @@ namespace Jellyfin.Server.Extensions { if (IPNetAddress.TryParse(userList[i], out var addr)) { - if ((!config.EnableIPV4 && addr.AddressFamily == AddressFamily.InterNetwork) - || (!config.EnableIPV6 && addr.AddressFamily == AddressFamily.InterNetworkV6)) - { - continue; - } - - if (networkManager.SystemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork) - { - // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. - // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . - addr.Address = addr.Address.MapToIPv6(); - } - - if (addr.PrefixLength == 32) - { - options.KnownProxies.Add(addr.Address); - } - else - { - options.KnownNetworks.Add(new IPNetwork(addr.Address, addr.PrefixLength)); - } + AddIpAddress(config, options, addr.Address, addr.PrefixLength, networkManager.SystemIP6Enabled); } else if (IPHost.TryParse(userList[i], out var host)) { foreach (var address in host.GetAddresses()) { - if ((!config.EnableIPV4 && address.AddressFamily == AddressFamily.InterNetwork) - || (!config.EnableIPV6 && address.AddressFamily == AddressFamily.InterNetworkV6)) - { - continue; - } - - var hostAddr = address; - if (networkManager.SystemIP6Enabled && address.AddressFamily == AddressFamily.InterNetwork) - { - // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. - // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . - hostAddr = address.MapToIPv6(); - } - - options.KnownProxies.Add(hostAddr); + AddIpAddress(config, options, addr.Address, addr.PrefixLength, networkManager.SystemIP6Enabled); } } } From 6a7623da02045bb8600bc2aad3047a4debda03f1 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 10:36:37 +0000 Subject: [PATCH 14/20] Simplified Code --- Jellyfin.Networking/Manager/NetworkManager.cs | 16 +-- .../ApiServiceCollectionExtensions.cs | 103 +++++++++--------- Jellyfin.Server/Startup.cs | 8 +- MediaBrowser.Common/Net/INetworkManager.cs | 10 -- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 4 +- 5 files changed, 63 insertions(+), 78 deletions(-) diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index c9f900660b..34b1f0daaf 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -130,24 +130,24 @@ namespace Jellyfin.Networking.Manager public static string MockNetworkSettings { get; set; } = string.Empty; /// - /// Gets or sets a value indicating whether IP6 is enabled. + /// Gets or sets a value indicating whether the system has IP4 is enabled. /// - public bool IsIP6Enabled { get; set; } + public static bool SystemIP4Enabled { get; set; } /// - /// Gets or sets a value indicating whether IP4 is enabled. + /// Gets or sets a value indicating whether the system has IP6 is enabled. /// - public bool IsIP4Enabled { get; set; } + public static bool SystemIP6Enabled { get; set; } /// - /// Gets or sets a value indicating whether the system has IP4 is enabled. + /// Gets or sets a value indicating whether IP6 is enabled. /// - public bool SystemIP4Enabled { get; set; } + public bool IsIP6Enabled { get; set; } /// - /// Gets or sets a value indicating whether the system has IP6 is enabled. + /// Gets or sets a value indicating whether IP4 is enabled. /// - public bool SystemIP6Enabled { get; set; } + public bool IsIP4Enabled { get; set; } /// public Collection RemoteAddressFilter { get; private set; } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 9b4e53fc09..0a7ae9a410 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -25,6 +25,7 @@ using Jellyfin.Api.Controllers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; using Jellyfin.Networking.Configuration; +using Jellyfin.Networking.Manager; using Jellyfin.Server.Configuration; using Jellyfin.Server.Filters; using Jellyfin.Server.Formatters; @@ -174,64 +175,14 @@ namespace Jellyfin.Server.Extensions .AddScheme(AuthenticationSchemes.CustomAuthentication, null); } - private static void AddIpAddress(NetworkConfiguration config, ForwardedHeadersOptions options, IPAddress addr, int prefixLength, bool systemIP6Enabled) - { - if ((!config.EnableIPV4 && addr.AddressFamily == AddressFamily.InterNetwork) || (!config.EnableIPV6 && addr.AddressFamily == AddressFamily.InterNetworkV6)) - { - return; - } - - if (systemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork) - { - // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. - // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . - addr = addr.MapToIPv6(); - } - - if (prefixLength == 32) - { - options.KnownProxies.Add(addr); - } - else - { - options.KnownNetworks.Add(new IPNetwork(addr, prefixLength)); - } - } - - /// - /// Sets up the proxy configuration based on the addresses in . - /// - /// The instance. - /// The containing the config settings. - /// The string array to parse. - /// The instance. - internal static void ParseList(INetworkManager networkManager, NetworkConfiguration config, string[] userList, ForwardedHeadersOptions options) - { - for (var i = 0; i < userList.Length; i++) - { - if (IPNetAddress.TryParse(userList[i], out var addr)) - { - AddIpAddress(config, options, addr.Address, addr.PrefixLength, networkManager.SystemIP6Enabled); - } - else if (IPHost.TryParse(userList[i], out var host)) - { - foreach (var address in host.GetAddresses()) - { - AddIpAddress(config, options, addr.Address, addr.PrefixLength, networkManager.SystemIP6Enabled); - } - } - } - } - /// /// Extension method for adding the jellyfin API to the service collection. /// /// The service collection. /// An IEnumerable containing all plugin assemblies with API controllers. /// The . - /// The instance. /// The MVC builder. - public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable pluginAssemblies, NetworkConfiguration config, INetworkManager networkManager) + public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable pluginAssemblies, NetworkConfiguration config) { IMvcBuilder mvcBuilder = serviceCollection .AddCors() @@ -249,7 +200,7 @@ namespace Jellyfin.Server.Extensions } else { - ParseList(networkManager, config, config.KnownProxies, options); + ParseList(config, config.KnownProxies, options); } // Only set forward limit if we have some known proxies or some known networks. @@ -370,6 +321,54 @@ namespace Jellyfin.Server.Extensions }); } + /// + /// Sets up the proxy configuration based on the addresses in . + /// + /// The containing the config settings. + /// The string array to parse. + /// The instance. + internal static void ParseList(NetworkConfiguration config, string[] userList, ForwardedHeadersOptions options) + { + for (var i = 0; i < userList.Length; i++) + { + if (IPNetAddress.TryParse(userList[i], out var addr)) + { + AddIpAddress(config, options, addr.Address, addr.PrefixLength); + } + else if (IPHost.TryParse(userList[i], out var host)) + { + foreach (var address in host.GetAddresses()) + { + AddIpAddress(config, options, addr.Address, addr.PrefixLength); + } + } + } + } + + private static void AddIpAddress(NetworkConfiguration config, ForwardedHeadersOptions options, IPAddress addr, int prefixLength) + { + if ((!config.EnableIPV4 && addr.AddressFamily == AddressFamily.InterNetwork) || (!config.EnableIPV6 && addr.AddressFamily == AddressFamily.InterNetworkV6)) + { + return; + } + + if (NetworkManager.SystemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork) + { + // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. + // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . + addr = addr.MapToIPv6(); + } + + if (prefixLength == 32) + { + options.KnownProxies.Add(addr); + } + else + { + options.KnownNetworks.Add(new IPNetwork(addr, prefixLength)); + } + } + private static void AddSwaggerTypeMappings(this SwaggerGenOptions options) { /* diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 05228ccaab..e56e61092b 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -26,22 +26,18 @@ namespace Jellyfin.Server { private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerApplicationHost _serverApplicationHost; - private readonly INetworkManager _networkManager; /// /// Initializes a new instance of the class. /// /// The server configuration manager. /// The server application host. - /// The network manager. public Startup( IServerConfigurationManager serverConfigurationManager, - IServerApplicationHost serverApplicationHost, - INetworkManager networkManager) + IServerApplicationHost serverApplicationHost) { _serverConfigurationManager = serverConfigurationManager; _serverApplicationHost = serverApplicationHost; - _networkManager = networkManager; } /// @@ -56,7 +52,7 @@ namespace Jellyfin.Server { options.HttpsPort = _serverApplicationHost.HttpsPort; }); - services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration(), _networkManager); + services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration()); services.AddJellyfinApiSwagger(); diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index 7ee76107bc..b6c390d239 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -44,16 +44,6 @@ namespace MediaBrowser.Common.Net /// bool IsIP4Enabled { get; set; } - /// - /// Gets or sets a value indicating whether the system has IP4 is enabled. - /// - bool SystemIP4Enabled { get; set; } - - /// - /// Gets or sets a value indicating whether the system has IP6 is enabled. - /// - bool SystemIP6Enabled { get; set; } - /// /// Calculates the list of interfaces to use for Kestrel. /// diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index 6ee66d2a8f..a76b8b2439 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -30,7 +30,7 @@ namespace Jellyfin.Api.Tests public void TestNetworks(bool ip4, bool ip6, string hostList, string match) { using var nm = CreateNetworkManager(); - nm.SystemIP6Enabled = ip6; + NetworkManager.SystemIP6Enabled = ip6; var settings = new NetworkConfiguration { @@ -45,7 +45,7 @@ namespace Jellyfin.Api.Tests options.KnownProxies.Clear(); options.KnownNetworks.Clear(); - ApiServiceCollectionExtensions.ParseList(nm, settings, hostList.Split(","), options); + ApiServiceCollectionExtensions.ParseList(settings, hostList.Split(","), options); var sb = new StringBuilder(); foreach (var item in options.KnownProxies) From dd089fd27ab20755b7cac1e71fa328dddbfe2c68 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 10:50:17 +0000 Subject: [PATCH 15/20] Changed test --- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index a76b8b2439..6717137d9d 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -50,19 +50,19 @@ namespace Jellyfin.Api.Tests var sb = new StringBuilder(); foreach (var item in options.KnownProxies) { - sb.Append(item.ToString()); + sb.Append(item); sb.Append(','); } foreach (var item in options.KnownNetworks) { - sb.Append(item.Prefix.ToString()); + sb.Append(item.Prefix); sb.Append('/'); sb.Append(item.PrefixLength.ToString(CultureInfo.InvariantCulture)); sb.Append(','); } - Assert.True(string.Equals(sb.ToString(), result, StringComparison.OrdinalIgnoreCase), "Not matched: " + sb.ToString() + " does not match " + result); + Assert.Equal(sb.ToString(), result); } private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) @@ -72,7 +72,7 @@ namespace Jellyfin.Api.Tests CallBase = true }; configManager.Setup(x => x.GetConfiguration(It.IsAny())).Returns(conf); - return (IConfigurationManager)configManager.Object; + return configManager.Object; } private static NetworkManager CreateNetworkManager() From 821473557c7747e4029cddc4f562ae3f207508d7 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 11:31:40 +0000 Subject: [PATCH 16/20] Changed mapping logic --- Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 0a7ae9a410..0e68c523fc 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -352,7 +352,8 @@ namespace Jellyfin.Server.Extensions return; } - if (NetworkManager.SystemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork) + // In order for dual-mode sockets to be used, IP6 has to be enabled in JF and an interface has to have an IP6 address. + if (NetworkManager.SystemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork && config.EnableIPV6) { // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . From 82d365045a0c7bf9acfa8c62433b5ec68d7b34a5 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 12:50:11 +0000 Subject: [PATCH 17/20] Removed systemIp6 functionality. --- Jellyfin.Networking/Manager/NetworkManager.cs | 12 ------------ .../Extensions/ApiServiceCollectionExtensions.cs | 2 +- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 1 - 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 34b1f0daaf..349a30ed3e 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -129,16 +129,6 @@ namespace Jellyfin.Networking.Manager /// public static string MockNetworkSettings { get; set; } = string.Empty; - /// - /// Gets or sets a value indicating whether the system has IP4 is enabled. - /// - public static bool SystemIP4Enabled { get; set; } - - /// - /// Gets or sets a value indicating whether the system has IP6 is enabled. - /// - public static bool SystemIP6Enabled { get; set; } - /// /// Gets or sets a value indicating whether IP6 is enabled. /// @@ -1059,7 +1049,6 @@ namespace Jellyfin.Networking.Manager { if (info.Address.AddressFamily == AddressFamily.InterNetwork) { - SystemIP4Enabled = true; if (IsIP4Enabled) { IPNetAddress nw = new IPNetAddress(info.Address, IPObject.MaskToCidr(info.IPv4Mask)) @@ -1084,7 +1073,6 @@ namespace Jellyfin.Networking.Manager } else if (info.Address.AddressFamily == AddressFamily.InterNetworkV6) { - SystemIP6Enabled = true; if (IsIP6Enabled) { IPNetAddress nw = new IPNetAddress(info.Address, (byte)info.PrefixLength) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 0e68c523fc..f8626b6e0e 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -353,7 +353,7 @@ namespace Jellyfin.Server.Extensions } // In order for dual-mode sockets to be used, IP6 has to be enabled in JF and an interface has to have an IP6 address. - if (NetworkManager.SystemIP6Enabled && addr.AddressFamily == AddressFamily.InterNetwork && config.EnableIPV6) + if (addr.AddressFamily == AddressFamily.InterNetwork && config.EnableIPV6) { // If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format. // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0 . diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index 6717137d9d..039c393770 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -30,7 +30,6 @@ namespace Jellyfin.Api.Tests public void TestNetworks(bool ip4, bool ip6, string hostList, string match) { using var nm = CreateNetworkManager(); - NetworkManager.SystemIP6Enabled = ip6; var settings = new NetworkConfiguration { From 9db8a4d88dd276c907cb44eddd3633f8ec83989a Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 13:56:16 +0000 Subject: [PATCH 18/20] reverted --- Jellyfin.Networking/Manager/NetworkManager.cs | 74 +++++++++---------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 349a30ed3e..60b899519e 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -1047,53 +1047,47 @@ namespace Jellyfin.Networking.Manager // populate interface address list foreach (UnicastIPAddressInformation info in ipProperties.UnicastAddresses) { - if (info.Address.AddressFamily == AddressFamily.InterNetwork) + if (IsIP4Enabled && info.Address.AddressFamily == AddressFamily.InterNetwork) { - if (IsIP4Enabled) + IPNetAddress nw = new IPNetAddress(info.Address, IPObject.MaskToCidr(info.IPv4Mask)) { - IPNetAddress nw = new IPNetAddress(info.Address, IPObject.MaskToCidr(info.IPv4Mask)) - { - // Keep the number of gateways on this interface, along with its index. - Tag = ipProperties.GetIPv4Properties().Index - }; - - int tag = nw.Tag; - if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) - { - // -ve Tags signify the interface has a gateway. - nw.Tag *= -1; - } - - _interfaceAddresses.AddItem(nw); - - // Store interface name so we can use the name in Collections. - _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; - _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; + // Keep the number of gateways on this interface, along with its index. + Tag = ipProperties.GetIPv4Properties().Index + }; + + int tag = nw.Tag; + if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) + { + // -ve Tags signify the interface has a gateway. + nw.Tag *= -1; } + + _interfaceAddresses.AddItem(nw); + + // Store interface name so we can use the name in Collections. + _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; + _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; } - else if (info.Address.AddressFamily == AddressFamily.InterNetworkV6) + else if (IsIP6Enabled && info.Address.AddressFamily == AddressFamily.InterNetworkV6) { - if (IsIP6Enabled) + IPNetAddress nw = new IPNetAddress(info.Address, (byte)info.PrefixLength) { - IPNetAddress nw = new IPNetAddress(info.Address, (byte)info.PrefixLength) - { - // Keep the number of gateways on this interface, along with its index. - Tag = ipProperties.GetIPv6Properties().Index - }; - - int tag = nw.Tag; - if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) - { - // -ve Tags signify the interface has a gateway. - nw.Tag *= -1; - } - - _interfaceAddresses.AddItem(nw); - - // Store interface name so we can use the name in Collections. - _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; - _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; + // Keep the number of gateways on this interface, along with its index. + Tag = ipProperties.GetIPv6Properties().Index + }; + + int tag = nw.Tag; + if (ipProperties.GatewayAddresses.Count > 0 && !nw.IsLoopback()) + { + // -ve Tags signify the interface has a gateway. + nw.Tag *= -1; } + + _interfaceAddresses.AddItem(nw); + + // Store interface name so we can use the name in Collections. + _interfaceNames[adapter.Description.ToLower(CultureInfo.InvariantCulture)] = tag; + _interfaceNames["eth" + tag.ToString(CultureInfo.InvariantCulture)] = tag; } } } From ab632b96fe64e9803bde8387b80aca2deeb478bf Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 19:29:51 +0000 Subject: [PATCH 19/20] renamed. --- .../Extensions/ApiServiceCollectionExtensions.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index f8626b6e0e..4f65a31e07 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -200,7 +200,7 @@ namespace Jellyfin.Server.Extensions } else { - ParseList(config, config.KnownProxies, options); + AddProxyAddresses(config, config.KnownProxies, options); } // Only set forward limit if we have some known proxies or some known networks. @@ -322,20 +322,20 @@ namespace Jellyfin.Server.Extensions } /// - /// Sets up the proxy configuration based on the addresses in . + /// Sets up the proxy configuration based on the addresses in . /// /// The containing the config settings. - /// The string array to parse. + /// The string array to parse. /// The instance. - internal static void ParseList(NetworkConfiguration config, string[] userList, ForwardedHeadersOptions options) + internal static void AddProxyAddresses(NetworkConfiguration config, string[] allowedProxies, ForwardedHeadersOptions options) { - for (var i = 0; i < userList.Length; i++) + for (var i = 0; i < allowedProxies.Length; i++) { - if (IPNetAddress.TryParse(userList[i], out var addr)) + if (IPNetAddress.TryParse(allowedProxies[i], out var addr)) { AddIpAddress(config, options, addr.Address, addr.PrefixLength); } - else if (IPHost.TryParse(userList[i], out var host)) + else if (IPHost.TryParse(allowedProxies[i], out var host)) { foreach (var address in host.GetAddresses()) { From 25eaf21a8f79ca49bfc0b29f521c5429093e7e50 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 19 Jan 2021 19:32:46 +0000 Subject: [PATCH 20/20] renamed func in test --- tests/Jellyfin.Api.Tests/ParseNetworkTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs index 039c393770..6c3fd0ee10 100644 --- a/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Api.Tests/ParseNetworkTests.cs @@ -44,7 +44,7 @@ namespace Jellyfin.Api.Tests options.KnownProxies.Clear(); options.KnownNetworks.Clear(); - ApiServiceCollectionExtensions.ParseList(settings, hostList.Split(","), options); + ApiServiceCollectionExtensions.AddProxyAddresses(settings, hostList.Split(","), options); var sb = new StringBuilder(); foreach (var item in options.KnownProxies)