@ -689,10 +689,10 @@ public class NetworkManager : INetworkManager, IDisposable
{
{
// Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
// 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 left blank, all remote addresses will be allowed.
if ( _remoteAddressFilter . Any ( ) & & ! _lanSubnets. Any ( x = > x . Contains ( remoteIP ) ) )
if ( _remoteAddressFilter . Any ( ) & & ! IsInLocalNetwork( remoteIP ) )
{
{
// remoteAddressFilter is a whitelist or blacklist.
// remoteAddressFilter is a whitelist or blacklist.
var matches = _remoteAddressFilter . Count ( remoteNetwork = > remoteNetwork. Contains ( remoteIP ) ) ;
var matches = _remoteAddressFilter . Count ( remoteNetwork = > SubNetContainsAddress( remoteNetwork , remoteIP ) ) ;
if ( ( ! config . IsRemoteIPFilterBlacklist & & matches > 0 )
if ( ( ! config . IsRemoteIPFilterBlacklist & & matches > 0 )
| | ( config . IsRemoteIPFilterBlacklist & & matches = = 0 ) )
| | ( config . IsRemoteIPFilterBlacklist & & matches = = 0 ) )
{
{
@ -816,7 +816,7 @@ public class NetworkManager : INetworkManager, IDisposable
_logger . LogWarning ( "IPv4 is disabled in Jellyfin, but enabled in the OS. This may affect how the interface is selected." ) ;
_logger . LogWarning ( "IPv4 is disabled in Jellyfin, but enabled in the OS. This may affect how the interface is selected." ) ;
}
}
bool isExternal = ! _lanSubnets. Any ( network = > network . Contains ( source ) ) ;
bool isExternal = ! IsInLocalNetwork( source ) ;
_logger . LogDebug ( "Trying to get bind address for source {Source} - External: {IsExternal}" , source , isExternal ) ;
_logger . LogDebug ( "Trying to get bind address for source {Source} - External: {IsExternal}" , source , isExternal ) ;
if ( ! skipOverrides & & MatchesPublishedServerUrl ( source , isExternal , out result ) )
if ( ! skipOverrides & & MatchesPublishedServerUrl ( source , isExternal , out result ) )
@ -863,7 +863,7 @@ public class NetworkManager : INetworkManager, IDisposable
// (For systems with multiple internal network cards, and multiple subnets)
// (For systems with multiple internal network cards, and multiple subnets)
foreach ( var intf in availableInterfaces )
foreach ( var intf in availableInterfaces )
{
{
if ( intf. Subnet . Contains ( source ) )
if ( SubNetContainsAddress( intf . Subnet , source ) )
{
{
result = NetworkUtils . FormatIPString ( intf . Address ) ;
result = NetworkUtils . FormatIPString ( intf . Address ) ;
_logger . LogDebug ( "{Source}: Found interface with matching subnet, using it as bind address: {Result}" , source , result ) ;
_logger . LogDebug ( "{Source}: Found interface with matching subnet, using it as bind address: {Result}" , source , result ) ;
@ -891,21 +891,11 @@ public class NetworkManager : INetworkManager, IDisposable
{
{
if ( NetworkUtils . TryParseToSubnet ( address , out var subnet ) )
if ( NetworkUtils . TryParseToSubnet ( address , out var subnet ) )
{
{
return I PAddress. IsLoopback ( subnet . Prefix ) | | ( _lanSubnets . Any ( x = > x . Contains ( subnet . Prefix ) ) & & ! _excludedSubnets . Any ( x = > x . Contains ( subnet . Prefix ) ) ) ;
return I sInLocalNetwork( subnet . Prefix ) ;
}
}
if ( NetworkUtils . TryParseHost ( address , out var addresses , IsIPv4Enabled , IsIPv6Enabled ) )
return NetworkUtils . TryParseHost ( address , out var addresses , IsIPv4Enabled , IsIPv6Enabled )
{
& & addresses . Any ( IsInLocalNetwork ) ;
foreach ( var ept in addresses )
{
if ( IPAddress . IsLoopback ( ept ) | | ( _lanSubnets . Any ( x = > x . Contains ( ept ) ) & & ! _excludedSubnets . Any ( x = > x . Contains ( ept ) ) ) )
{
return true ;
}
}
}
return false ;
}
}
/// <summary>
/// <summary>
@ -919,6 +909,19 @@ public class NetworkManager : INetworkManager, IDisposable
return NetworkConstants . IPv4RFC3927LinkLocal . Contains ( address ) | | address . IsIPv6LinkLocal ;
return NetworkConstants . IPv4RFC3927LinkLocal . Contains ( address ) | | address . IsIPv6LinkLocal ;
}
}
private static bool SubNetContainsAddress ( IPNetwork network , IPAddress address )
{
ArgumentNullException . ThrowIfNull ( address ) ;
ArgumentNullException . ThrowIfNull ( network ) ;
if ( address . IsIPv4MappedToIPv6 )
{
address = address . MapToIPv4 ( ) ;
}
return network . Contains ( address ) ;
}
/// <inheritdoc/>
/// <inheritdoc/>
public bool IsInLocalNetwork ( IPAddress address )
public bool IsInLocalNetwork ( IPAddress address )
{
{
@ -940,6 +943,11 @@ public class NetworkManager : INetworkManager, IDisposable
return CheckIfLanAndNotExcluded ( address ) ;
return CheckIfLanAndNotExcluded ( address ) ;
}
}
/// <summary>
/// Check if the address is in the LAN and not excluded.
/// </summary>
/// <param name="address">The IP address to check. The caller should make sure this is not an IPv4MappedToIPv6 address.</param>
/// <returns>Boolean indicates whether the address is in LAN.</returns>
private bool CheckIfLanAndNotExcluded ( IPAddress address )
private bool CheckIfLanAndNotExcluded ( IPAddress address )
{
{
foreach ( var lanSubnet in _lanSubnets )
foreach ( var lanSubnet in _lanSubnets )
@ -979,7 +987,7 @@ public class NetworkManager : INetworkManager, IDisposable
{
{
// Only use matching internal subnets
// Only use matching internal subnets
// Prefer more specific (bigger subnet prefix) overrides
// Prefer more specific (bigger subnet prefix) overrides
validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . IsInternalOverride & & x. Data . Subnet .Contains ( source ) )
validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . IsInternalOverride & & SubNetContainsAddress( x. Data . Subnet , source ) )
. OrderByDescending ( x = > x . Data . Subnet . PrefixLength )
. OrderByDescending ( x = > x . Data . Subnet . PrefixLength )
. ToList ( ) ;
. ToList ( ) ;
}
}
@ -987,7 +995,7 @@ public class NetworkManager : INetworkManager, IDisposable
{
{
// Only use matching external subnets
// Only use matching external subnets
// Prefer more specific (bigger subnet prefix) overrides
// Prefer more specific (bigger subnet prefix) overrides
validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . IsExternalOverride & & x. Data . Subnet .Contains ( source ) )
validPublishedServerUrls = _publishedServerUrls . Where ( x = > x . IsExternalOverride & & SubNetContainsAddress( x. Data . Subnet , source ) )
. OrderByDescending ( x = > x . Data . Subnet . PrefixLength )
. OrderByDescending ( x = > x . Data . Subnet . PrefixLength )
. ToList ( ) ;
. ToList ( ) ;
}
}
@ -995,7 +1003,7 @@ public class NetworkManager : INetworkManager, IDisposable
foreach ( var data in validPublishedServerUrls )
foreach ( var data in validPublishedServerUrls )
{
{
// Get interface matching override subnet
// Get interface matching override subnet
var intf = _interfaces . OrderBy ( x = > x . Index ) . FirstOrDefault ( x = > data. Data . Subnet .Contains ( x . Address ) ) ;
var intf = _interfaces . OrderBy ( x = > x . Index ) . FirstOrDefault ( x = > SubNetContainsAddress( data. Data . Subnet , x . Address ) ) ;
if ( intf ? . Address is not null
if ( intf ? . Address is not null
| | ( data . Data . AddressFamily = = AddressFamily . InterNetwork & & data . Data . Address . Equals ( IPAddress . Any ) )
| | ( data . Data . AddressFamily = = AddressFamily . InterNetwork & & data . Data . Address . Equals ( IPAddress . Any ) )
@ -1058,6 +1066,7 @@ public class NetworkManager : INetworkManager, IDisposable
if ( isInExternalSubnet )
if ( isInExternalSubnet )
{
{
var externalInterfaces = _interfaces . Where ( x = > ! IsInLocalNetwork ( x . Address ) )
var externalInterfaces = _interfaces . Where ( x = > ! IsInLocalNetwork ( x . Address ) )
. Where ( x = > ! IsLinkLocalAddress ( x . Address ) )
. OrderBy ( x = > x . Index )
. OrderBy ( x = > x . Index )
. ToList ( ) ;
. ToList ( ) ;
if ( externalInterfaces . Count > 0 )
if ( externalInterfaces . Count > 0 )
@ -1065,7 +1074,7 @@ public class NetworkManager : INetworkManager, IDisposable
// Check to see if any of the external bind interfaces are in the same subnet as the source.
// Check to see if any of the external bind interfaces are in the same subnet as the source.
// If none exists, this will select the first external interface if there is one.
// If none exists, this will select the first external interface if there is one.
bindAddress = externalInterfaces
bindAddress = externalInterfaces
. OrderByDescending ( x = > x. Subnet . Contains ( source ) )
. OrderByDescending ( x = > SubNetContainsAddress( x . Subnet , source ) )
. ThenByDescending ( x = > x . Subnet . PrefixLength )
. ThenByDescending ( x = > x . Subnet . PrefixLength )
. ThenBy ( x = > x . Index )
. ThenBy ( x = > x . Index )
. Select ( x = > x . Address )
. Select ( x = > x . Address )
@ -1083,7 +1092,7 @@ public class NetworkManager : INetworkManager, IDisposable
// Check to see if any of the internal bind interfaces are in the same subnet as the source.
// Check to see if any of the internal bind interfaces are in the same subnet as the source.
// If none exists, this will select the first internal interface if there is one.
// If none exists, this will select the first internal interface if there is one.
bindAddress = _interfaces . Where ( x = > IsInLocalNetwork ( x . Address ) )
bindAddress = _interfaces . Where ( x = > IsInLocalNetwork ( x . Address ) )
. OrderByDescending ( x = > x. Subnet . Contains ( source ) )
. OrderByDescending ( x = > SubNetContainsAddress( x . Subnet , source ) )
. ThenByDescending ( x = > x . Subnet . PrefixLength )
. ThenByDescending ( x = > x . Subnet . PrefixLength )
. ThenBy ( x = > x . Index )
. ThenBy ( x = > x . Index )
. Select ( x = > x . Address )
. Select ( x = > x . Address )
@ -1127,7 +1136,7 @@ public class NetworkManager : INetworkManager, IDisposable
// (For systems with multiple network cards and/or multiple subnets)
// (For systems with multiple network cards and/or multiple subnets)
foreach ( var intf in extResult )
foreach ( var intf in extResult )
{
{
if ( intf. Subnet . Contains ( source ) )
if ( SubNetContainsAddress( intf . Subnet , source ) )
{
{
result = NetworkUtils . FormatIPString ( intf . Address ) ;
result = NetworkUtils . FormatIPString ( intf . Address ) ;
_logger . LogDebug ( "{Source}: Found external interface with matching subnet, using it as bind address: {Result}" , source , result ) ;
_logger . LogDebug ( "{Source}: Found external interface with matching subnet, using it as bind address: {Result}" , source , result ) ;