Merge pull request #5495 from BaronGreenback/RemoteAccessFix

This commit is contained in:
Bond-009 2021-03-27 17:24:47 +01:00 committed by GitHub
commit a890a85092
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 41 deletions

View File

@ -576,6 +576,29 @@ namespace Jellyfin.Networking.Manager
return false;
}
/// <inheritdoc/>
public bool HasRemoteAccess(IPAddress remoteIp)
{
var config = _configurationManager.GetNetworkConfiguration();
if (config.EnableRemoteAccess)
{
// Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
// If left blank, all remote addresses will be allowed.
if (RemoteAddressFilter.Count > 0 && !IsInLocalNetwork(remoteIp))
{
// remoteAddressFilter is a whitelist or blacklist.
return RemoteAddressFilter.ContainsAddress(remoteIp) == !config.IsRemoteIPFilterBlacklist;
}
}
else if (!IsInLocalNetwork(remoteIp))
{
// Remote not enabled. So everyone should be LAN.
return false;
}
return true;
}
/// <summary>
/// Reloads all settings and re-initialises the instance.
/// </summary>

View File

@ -29,9 +29,8 @@ namespace Jellyfin.Server.Middleware
/// </summary>
/// <param name="httpContext">The current HTTP context.</param>
/// <param name="networkManager">The network manager.</param>
/// <param name="serverConfigurationManager">The server configuration manager.</param>
/// <returns>The async task.</returns>
public async Task Invoke(HttpContext httpContext, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager)
public async Task Invoke(HttpContext httpContext, INetworkManager networkManager)
{
if (httpContext.IsLocal())
{
@ -42,32 +41,8 @@ namespace Jellyfin.Server.Middleware
var remoteIp = httpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback;
if (serverConfigurationManager.GetNetworkConfiguration().EnableRemoteAccess)
if (!networkManager.HasRemoteAccess(remoteIp))
{
// Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
// If left blank, all remote addresses will be allowed.
var remoteAddressFilter = networkManager.RemoteAddressFilter;
if (remoteAddressFilter.Count > 0 && !networkManager.IsInLocalNetwork(remoteIp))
{
// remoteAddressFilter is a whitelist or blacklist.
bool isListed = remoteAddressFilter.ContainsAddress(remoteIp);
if (!serverConfigurationManager.GetNetworkConfiguration().IsRemoteIPFilterBlacklist)
{
// Black list, so flip over.
isListed = !isListed;
}
if (!isListed)
{
// If your name isn't on the list, you arn't coming in.
return;
}
}
}
else if (!networkManager.IsInLocalNetwork(remoteIp))
{
// Remote not enabled. So everyone should be LAN.
return;
}

View File

@ -1,4 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30503.244
MinimumVisualStudioVersion = 10.0.40219.1
@ -70,11 +71,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Networking", "Jell
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Dlna.Tests", "tests\Jellyfin.Dlna.Tests\Jellyfin.Dlna.Tests.csproj", "{B8AE4B9D-E8D3-4B03-A95E-7FD8CECECC50}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.XbmcMetadata.Tests", "tests\Jellyfin.XbmcMetadata.Tests\Jellyfin.XbmcMetadata.Tests.csproj", "{30922383-D513-4F4D-B890-A940B57FA353}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.XbmcMetadata.Tests", "tests\Jellyfin.XbmcMetadata.Tests\Jellyfin.XbmcMetadata.Tests.csproj", "{30922383-D513-4F4D-B890-A940B57FA353}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Model.Tests", "tests\Jellyfin.Model.Tests\Jellyfin.Model.Tests.csproj", "{FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Model.Tests", "tests\Jellyfin.Model.Tests\Jellyfin.Model.Tests.csproj", "{FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Networking.Tests", "tests\Jellyfin.Networking.Tests\Jellyfin.Networking.Tests.csproj", "{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server.Tests", "tests\Jellyfin.Server.Tests\Jellyfin.Server.Tests.csproj", "{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}"
EndProject
@ -210,6 +211,10 @@ Global
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU
{25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Release|Any CPU.Build.0 = Release|Any CPU
{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -229,5 +229,12 @@ namespace MediaBrowser.Common.Net
/// <param name="filter">Optional filter for the list.</param>
/// <returns>Returns a filtered list of LAN addresses.</returns>
Collection<IPObject> GetFilteredLANSubnets(Collection<IPObject>? filter = null);
/// <summary>
/// Checks to see if <paramref name="remoteIp"/> has access.
/// </summary>
/// <param name="remoteIp">IP Address of client.</param>
/// <returns><b>True</b> if has access, otherwise <b>false</b>.</returns>
bool HasRemoteAccess(IPAddress remoteIp);
}
}

View File

@ -201,29 +201,29 @@ namespace Jellyfin.Networking.Tests
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
// Test included.
Collection<IPObject> nc = nm.CreateIPCollection(settings.Split(","), false);
Collection<IPObject> nc = nm.CreateIPCollection(settings.Split(','), false);
Assert.Equal(nc.AsString(), result1);
// Test excluded.
nc = nm.CreateIPCollection(settings.Split(","), true);
nc = nm.CreateIPCollection(settings.Split(','), true);
Assert.Equal(nc.AsString(), result3);
conf.EnableIPV6 = false;
nm.UpdateSettings(conf);
// Test IP4 included.
nc = nm.CreateIPCollection(settings.Split(","), false);
nc = nm.CreateIPCollection(settings.Split(','), false);
Assert.Equal(nc.AsString(), result2);
// Test IP4 excluded.
nc = nm.CreateIPCollection(settings.Split(","), true);
nc = nm.CreateIPCollection(settings.Split(','), true);
Assert.Equal(nc.AsString(), result4);
conf.EnableIPV6 = true;
nm.UpdateSettings(conf);
// Test network addresses of collection.
nc = nm.CreateIPCollection(settings.Split(","), false);
nc = nm.CreateIPCollection(settings.Split(','), false);
nc = nc.AsNetworks();
Assert.Equal(nc.AsString(), result5);
}
@ -262,8 +262,8 @@ namespace Jellyfin.Networking.Tests
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
Collection<IPObject> nc1 = nm.CreateIPCollection(settings.Split(","), false);
Collection<IPObject> nc2 = nm.CreateIPCollection(compare.Split(","), false);
Collection<IPObject> nc1 = nm.CreateIPCollection(settings.Split(','), false);
Collection<IPObject> nc2 = nm.CreateIPCollection(compare.Split(','), false);
Assert.Equal(nc1.Union(nc2).AsString(), result);
}
@ -372,10 +372,10 @@ namespace Jellyfin.Networking.Tests
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
// Test included, IP6.
Collection<IPObject> ncSource = nm.CreateIPCollection(source.Split(","));
Collection<IPObject> ncDest = nm.CreateIPCollection(dest.Split(","));
Collection<IPObject> ncSource = nm.CreateIPCollection(source.Split(','));
Collection<IPObject> ncDest = nm.CreateIPCollection(dest.Split(','));
Collection<IPObject> ncResult = ncSource.Union(ncDest);
Collection<IPObject> resultCollection = nm.CreateIPCollection(result.Split(","));
Collection<IPObject> resultCollection = nm.CreateIPCollection(result.Split(','));
Assert.True(ncResult.Compare(resultCollection));
}
@ -514,5 +514,45 @@ namespace Jellyfin.Networking.Tests
Assert.Equal(intf, result);
}
[Theory]
[InlineData("185.10.10.10,200.200.200.200", "79.2.3.4", true)]
[InlineData("185.10.10.10", "185.10.10.10", false)]
[InlineData("", "100.100.100.100", false)]
public void HasRemoteAccess_GivenWhitelist_AllowsOnlyIpsInWhitelist(string addresses, string remoteIp, bool denied)
{
// Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
// If left blank, all remote addresses will be allowed.
var conf = new NetworkConfiguration()
{
EnableIPV4 = true,
RemoteIPFilter = addresses.Split(','),
IsRemoteIPFilterBlacklist = false
};
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied);
}
[Theory]
[InlineData("185.10.10.10", "79.2.3.4", false)]
[InlineData("185.10.10.10", "185.10.10.10", true)]
[InlineData("", "100.100.100.100", false)]
public void HasRemoteAccess_GivenBlacklist_BlacklistTheIps(string addresses, string remoteIp, bool denied)
{
// Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
// If left blank, all remote addresses will be allowed.
var conf = new NetworkConfiguration()
{
EnableIPV4 = true,
RemoteIPFilter = addresses.Split(','),
IsRemoteIPFilterBlacklist = true
};
using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger<NetworkManager>());
Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied);
}
}
}