mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
Apply review suggestions
This commit is contained in:
parent
414eb45899
commit
1cc7572445
@ -263,6 +263,7 @@ namespace Jellyfin.Networking.Manager
|
||||
_logger.LogError(ex, "Error obtaining interfaces.");
|
||||
}
|
||||
|
||||
// If no interfaces are found, fallback to loopback interfaces.
|
||||
if (_interfaces.Count == 0)
|
||||
{
|
||||
_logger.LogWarning("No interface information available. Using loopback interface(s).");
|
||||
@ -278,8 +279,8 @@ namespace Jellyfin.Networking.Manager
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogDebug("Discovered {0} interfaces.", _interfaces.Count);
|
||||
_logger.LogDebug("Interfaces addresses: {0}", _interfaces.OrderByDescending(s => s.AddressFamily == AddressFamily.InterNetwork).Select(s => s.Address.ToString()));
|
||||
_logger.LogDebug("Discovered {NumberOfInterfaces} interfaces.", _interfaces.Count);
|
||||
_logger.LogDebug("Interfaces addresses: {Addresses}", _interfaces.OrderByDescending(s => s.AddressFamily == AddressFamily.InterNetwork).Select(s => s.Address.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,14 +294,21 @@ namespace Jellyfin.Networking.Manager
|
||||
_logger.LogDebug("Refreshing LAN information.");
|
||||
|
||||
// Get configuration options
|
||||
string[] subnets = config.LocalNetworkSubnets;
|
||||
var subnets = config.LocalNetworkSubnets;
|
||||
|
||||
_ = NetworkExtensions.TryParseToSubnets(subnets, out _lanSubnets, false);
|
||||
_ = NetworkExtensions.TryParseToSubnets(subnets, out _excludedSubnets, true);
|
||||
if (!NetworkExtensions.TryParseToSubnets(subnets, out _lanSubnets, false))
|
||||
{
|
||||
_lanSubnets.Clear();
|
||||
}
|
||||
|
||||
if (!NetworkExtensions.TryParseToSubnets(subnets, out _excludedSubnets, true))
|
||||
{
|
||||
_excludedSubnets.Clear();
|
||||
}
|
||||
|
||||
// If no LAN addresses are specified, all private subnets and Loopback are deemed to be the LAN
|
||||
if (_lanSubnets.Count == 0)
|
||||
{
|
||||
// If no LAN addresses are specified, all private subnets and Loopback are deemed to be the LAN
|
||||
_logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
|
||||
|
||||
if (IsIpv6Enabled)
|
||||
@ -334,15 +342,15 @@ namespace Jellyfin.Networking.Manager
|
||||
{
|
||||
// Respect explicit bind addresses
|
||||
var localNetworkAddresses = config.LocalNetworkAddresses;
|
||||
if (localNetworkAddresses.Length > 0 && !string.IsNullOrWhiteSpace(localNetworkAddresses.First()))
|
||||
if (localNetworkAddresses.Length > 0 && !string.IsNullOrWhiteSpace(localNetworkAddresses[0]))
|
||||
{
|
||||
var bindAddresses = localNetworkAddresses.Select(p => NetworkExtensions.TryParseToSubnet(p, out var network)
|
||||
? network.Prefix
|
||||
: (_interfaces.Where(x => x.Name.Equals(p, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(x => x.Address)
|
||||
.FirstOrDefault() ?? IPAddress.None))
|
||||
.ToList();
|
||||
bindAddresses.RemoveAll(x => x == IPAddress.None);
|
||||
.Where(x => x != IPAddress.None)
|
||||
.ToHashSet();
|
||||
_interfaces = _interfaces.Where(x => bindAddresses.Contains(x.Address)).ToList();
|
||||
|
||||
if (bindAddresses.Contains(IPAddress.Loopback))
|
||||
@ -401,11 +409,15 @@ namespace Jellyfin.Networking.Manager
|
||||
if (remoteIPFilter.Any() && !string.IsNullOrWhiteSpace(remoteIPFilter.First()))
|
||||
{
|
||||
// Parse all IPs with netmask to a subnet
|
||||
_ = NetworkExtensions.TryParseToSubnets(remoteIPFilter.Where(x => x.Contains('/', StringComparison.OrdinalIgnoreCase)).ToArray(), out _remoteAddressFilter, false);
|
||||
var remoteFilteredSubnets = remoteIPFilter.Where(x => x.Contains('/', StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (!NetworkExtensions.TryParseToSubnets(remoteFilteredSubnets, out _remoteAddressFilter, false))
|
||||
{
|
||||
_remoteAddressFilter.Clear();
|
||||
}
|
||||
|
||||
// Parse everything else as an IP and construct subnet with a single IP
|
||||
var ips = remoteIPFilter.Where(x => !x.Contains('/', StringComparison.OrdinalIgnoreCase));
|
||||
foreach (var ip in ips)
|
||||
var remoteFilteredIPs = remoteIPFilter.Where(x => !x.Contains('/', StringComparison.OrdinalIgnoreCase));
|
||||
foreach (var ip in remoteFilteredIPs)
|
||||
{
|
||||
if (IPAddress.TryParse(ip, out var ipp))
|
||||
{
|
||||
@ -436,44 +448,43 @@ namespace Jellyfin.Networking.Manager
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
_logger.LogError("Unable to parse bind override: {Entry}", entry);
|
||||
return;
|
||||
}
|
||||
|
||||
var replacement = parts[1].Trim();
|
||||
var identifier = parts[0];
|
||||
if (string.Equals(identifier, "all", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_publishedServerUrls[new IPData(IPAddress.Broadcast, null)] = replacement;
|
||||
}
|
||||
else if (string.Equals(identifier, "external", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_publishedServerUrls[new IPData(IPAddress.Any, new IPNetwork(IPAddress.Any, 0))] = replacement;
|
||||
_publishedServerUrls[new IPData(IPAddress.IPv6Any, new IPNetwork(IPAddress.IPv6Any, 0))] = replacement;
|
||||
}
|
||||
else if (string.Equals(identifier, "internal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (var lan in _lanSubnets)
|
||||
{
|
||||
var lanPrefix = lan.Prefix;
|
||||
_publishedServerUrls[new IPData(lanPrefix, new IPNetwork(lanPrefix, lan.PrefixLength))] = replacement;
|
||||
}
|
||||
}
|
||||
else if (NetworkExtensions.TryParseToSubnet(identifier, out var result) && result != null)
|
||||
{
|
||||
var data = new IPData(result.Prefix, result);
|
||||
_publishedServerUrls[data] = replacement;
|
||||
}
|
||||
else if (TryParseInterface(identifier, out var ifaces))
|
||||
{
|
||||
foreach (var iface in ifaces)
|
||||
{
|
||||
_publishedServerUrls[iface] = replacement;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var replacement = parts[1].Trim();
|
||||
var identifier = parts[0];
|
||||
if (string.Equals(identifier, "all", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_publishedServerUrls[new IPData(IPAddress.Broadcast, null)] = replacement;
|
||||
}
|
||||
else if (string.Equals(identifier, "external", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_publishedServerUrls[new IPData(IPAddress.Any, new IPNetwork(IPAddress.Any, 0))] = replacement;
|
||||
_publishedServerUrls[new IPData(IPAddress.IPv6Any, new IPNetwork(IPAddress.IPv6Any, 0))] = replacement;
|
||||
}
|
||||
else if (string.Equals(identifier, "internal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (var lan in _lanSubnets)
|
||||
{
|
||||
var lanPrefix = lan.Prefix;
|
||||
_publishedServerUrls[new IPData(lanPrefix, new IPNetwork(lanPrefix, lan.PrefixLength))] = replacement;
|
||||
}
|
||||
}
|
||||
else if (NetworkExtensions.TryParseToSubnet(identifier, out var result) && result != null)
|
||||
{
|
||||
var data = new IPData(result.Prefix, result);
|
||||
_publishedServerUrls[data] = replacement;
|
||||
}
|
||||
else if (TryParseInterface(identifier, out var ifaces))
|
||||
{
|
||||
foreach (var iface in ifaces)
|
||||
{
|
||||
_publishedServerUrls[iface] = replacement;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Unable to parse bind override: {Entry}", entry);
|
||||
}
|
||||
_logger.LogError("Unable to parse bind override: {Entry}", entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -556,31 +567,28 @@ namespace Jellyfin.Networking.Manager
|
||||
public bool TryParseInterface(string intf, out List<IPData> result)
|
||||
{
|
||||
result = new List<IPData>();
|
||||
if (string.IsNullOrEmpty(intf))
|
||||
if (string.IsNullOrEmpty(intf) || _interfaces is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_interfaces != null)
|
||||
// Match all interfaces starting with names starting with token
|
||||
var matchedInterfaces = _interfaces.Where(s => s.Name.Equals(intf, StringComparison.OrdinalIgnoreCase)).OrderBy(x => x.Index).ToList();
|
||||
if (matchedInterfaces.Count > 0)
|
||||
{
|
||||
// Match all interfaces starting with names starting with token
|
||||
var matchedInterfaces = _interfaces.Where(s => s.Name.Equals(intf, StringComparison.OrdinalIgnoreCase)).OrderBy(x => x.Index).ToList();
|
||||
if (matchedInterfaces.Any())
|
||||
_logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", intf);
|
||||
|
||||
// Use interface IP instead of name
|
||||
foreach (var iface in matchedInterfaces)
|
||||
{
|
||||
_logger.LogInformation("Interface {Token} used in settings. Using its interface addresses.", intf);
|
||||
|
||||
// Use interface IP instead of name
|
||||
foreach (var iface in matchedInterfaces)
|
||||
if ((IsIpv4Enabled && iface.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
|| (IsIpv6Enabled && iface.Address.AddressFamily == AddressFamily.InterNetworkV6))
|
||||
{
|
||||
if ((IsIpv4Enabled && iface.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
|| (IsIpv6Enabled && iface.Address.AddressFamily == AddressFamily.InterNetworkV6))
|
||||
{
|
||||
result.Add(iface);
|
||||
}
|
||||
result.Add(iface);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -626,6 +634,11 @@ namespace Jellyfin.Networking.Manager
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<IPData> GetLoopbacks()
|
||||
{
|
||||
if (!(IsIpv4Enabled && IsIpv4Enabled))
|
||||
{
|
||||
return Array.Empty<IPData>();
|
||||
}
|
||||
|
||||
var loopbackNetworks = new List<IPData>();
|
||||
if (IsIpv4Enabled)
|
||||
{
|
||||
@ -643,62 +656,64 @@ namespace Jellyfin.Networking.Manager
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<IPData> GetAllBindInterfaces(bool individualInterfaces = false)
|
||||
{
|
||||
if (_interfaces.Count == 0)
|
||||
if (_interfaces.Count != 0)
|
||||
{
|
||||
// No bind address and no exclusions, so listen on all interfaces.
|
||||
var result = new List<IPData>();
|
||||
return _interfaces;
|
||||
}
|
||||
|
||||
if (individualInterfaces)
|
||||
{
|
||||
foreach (var iface in _interfaces)
|
||||
{
|
||||
result.Add(iface);
|
||||
}
|
||||
// No bind address and no exclusions, so listen on all interfaces.
|
||||
var result = new List<IPData>();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (IsIpv4Enabled && IsIpv6Enabled)
|
||||
if (individualInterfaces)
|
||||
{
|
||||
foreach (var iface in _interfaces)
|
||||
{
|
||||
// Kestrel source code shows it uses Sockets.DualMode - so this also covers IPAddress.Any by default
|
||||
result.Add(new IPData(IPAddress.IPv6Any, new IPNetwork(IPAddress.IPv6Any, 0)));
|
||||
}
|
||||
else if (IsIpv4Enabled)
|
||||
{
|
||||
result.Add(new IPData(IPAddress.Any, new IPNetwork(IPAddress.Any, 0)));
|
||||
}
|
||||
else if (IsIpv6Enabled)
|
||||
{
|
||||
// Cannot use IPv6Any as Kestrel will bind to IPv4 addresses too.
|
||||
foreach (var iface in _interfaces)
|
||||
{
|
||||
if (iface.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
result.Add(iface);
|
||||
}
|
||||
}
|
||||
result.Add(iface);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return _interfaces;
|
||||
if (IsIpv4Enabled && IsIpv6Enabled)
|
||||
{
|
||||
// Kestrel source code shows it uses Sockets.DualMode - so this also covers IPAddress.Any by default
|
||||
result.Add(new IPData(IPAddress.IPv6Any, new IPNetwork(IPAddress.IPv6Any, 0)));
|
||||
}
|
||||
else if (IsIpv4Enabled)
|
||||
{
|
||||
result.Add(new IPData(IPAddress.Any, new IPNetwork(IPAddress.Any, 0)));
|
||||
}
|
||||
else if (IsIpv6Enabled)
|
||||
{
|
||||
// Cannot use IPv6Any as Kestrel will bind to IPv4 addresses too.
|
||||
foreach (var iface in _interfaces)
|
||||
{
|
||||
if (iface.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
result.Add(iface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetBindInterface(string source, out int? port)
|
||||
{
|
||||
_ = NetworkExtensions.TryParseHost(source, out var address, IsIpv4Enabled, IsIpv6Enabled);
|
||||
var result = GetBindAddress(address.FirstOrDefault(), out port);
|
||||
if (!NetworkExtensions.TryParseHost(source, out var addresses, IsIpv4Enabled, IsIpv6Enabled))
|
||||
{
|
||||
addresses = Array.Empty<IPAddress>();
|
||||
}
|
||||
|
||||
var result = GetBindAddress(addresses.FirstOrDefault(), out port);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetBindInterface(HttpRequest source, out int? port)
|
||||
{
|
||||
string result;
|
||||
_ = NetworkExtensions.TryParseHost(source.Host.Host, out var addresses, IsIpv4Enabled, IsIpv6Enabled);
|
||||
result = GetBindAddress(addresses.FirstOrDefault(), out port);
|
||||
var result = GetBindInterface(source.Host.Host, out port);
|
||||
port ??= source.Host.Port;
|
||||
|
||||
return result;
|
||||
@ -749,36 +764,36 @@ namespace Jellyfin.Networking.Manager
|
||||
.ThenBy(x => x.Index)
|
||||
.ToList();
|
||||
|
||||
if (availableInterfaces.Any())
|
||||
if (availableInterfaces.Count > 0)
|
||||
{
|
||||
if (source != null)
|
||||
if (source is null)
|
||||
{
|
||||
foreach (var intf in availableInterfaces)
|
||||
{
|
||||
if (intf.Address.Equals(source))
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(intf.Address);
|
||||
_logger.LogDebug("{Source}: Found matching interface to use as bind address: {Result}", source, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = NetworkExtensions.FormatIpString(availableInterfaces.First().Address);
|
||||
_logger.LogDebug("{Source}: Using first internal interface as bind address: {Result}", source, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Does the request originate in one of the interface subnets?
|
||||
// (For systems with multiple internal network cards, and multiple subnets)
|
||||
foreach (var intf in availableInterfaces)
|
||||
foreach (var intf in availableInterfaces)
|
||||
{
|
||||
if (intf.Address.Equals(source))
|
||||
{
|
||||
if (intf.Subnet.Contains(source))
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(intf.Address);
|
||||
_logger.LogDebug("{Source}: Found internal interface with matching subnet, using it as bind address: {Result}", source, result);
|
||||
return result;
|
||||
}
|
||||
result = NetworkExtensions.FormatIpString(intf.Address);
|
||||
_logger.LogDebug("{Source}: Found matching interface to use as bind address: {Result}", source, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = NetworkExtensions.FormatIpString(availableInterfaces.First().Address);
|
||||
_logger.LogDebug("{Source}: Using first internal interface as bind address: {Result}", source, result);
|
||||
return result;
|
||||
// Does the request originate in one of the interface subnets?
|
||||
// (For systems with multiple internal network cards, and multiple subnets)
|
||||
foreach (var intf in availableInterfaces)
|
||||
{
|
||||
if (intf.Subnet.Contains(source))
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(intf.Address);
|
||||
_logger.LogDebug("{Source}: Found internal interface with matching subnet, using it as bind address: {Result}", source, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There isn't any others, so we'll use the loopback.
|
||||
@ -810,6 +825,11 @@ namespace Jellyfin.Networking.Manager
|
||||
foreach (var ept in addresses)
|
||||
{
|
||||
match |= IPAddress.IsLoopback(ept) || (_lanSubnets.Any(x => x.Contains(ept)) && !_excludedSubnets.Any(x => x.Contains(ept)));
|
||||
|
||||
if (match)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
@ -824,15 +844,15 @@ namespace Jellyfin.Networking.Manager
|
||||
ArgumentNullException.ThrowIfNull(address);
|
||||
|
||||
// See conversation at https://github.com/jellyfin/jellyfin/pull/3515.
|
||||
if (TrustAllIpv6Interfaces && address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
if ((TrustAllIpv6Interfaces && address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
|| address.Equals(IPAddress.Loopback)
|
||||
|| address.Equals(IPAddress.IPv6Loopback))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// As private addresses can be redefined by Configuration.LocalNetworkAddresses
|
||||
var match = CheckIfLanAndNotExcluded(address);
|
||||
|
||||
return address.Equals(IPAddress.Loopback) || address.Equals(IPAddress.IPv6Loopback) || match;
|
||||
return CheckIfLanAndNotExcluded(address);
|
||||
}
|
||||
|
||||
private bool CheckIfLanAndNotExcluded(IPAddress address)
|
||||
@ -865,20 +885,16 @@ namespace Jellyfin.Networking.Manager
|
||||
int? port = null;
|
||||
|
||||
var validPublishedServerUrls = _publishedServerUrls.Where(x => x.Key.Address.Equals(IPAddress.Any)
|
||||
|| x.Key.Address.Equals(IPAddress.IPv6Any)
|
||||
|| x.Key.Subnet.Contains(source))
|
||||
.GroupBy(x => x.Key)
|
||||
.Select(x => x.First())
|
||||
.OrderBy(x => x.Key.Address.Equals(IPAddress.Any)
|
||||
|| x.Key.Address.Equals(IPAddress.IPv6Any))
|
||||
.ToList();
|
||||
|| x.Key.Address.Equals(IPAddress.IPv6Any)
|
||||
|| x.Key.Subnet.Contains(source))
|
||||
.DistinctBy(x => x.Key)
|
||||
.OrderBy(x => x.Key.Address.Equals(IPAddress.Any)
|
||||
|| x.Key.Address.Equals(IPAddress.IPv6Any))
|
||||
.ToList();
|
||||
|
||||
// Check for user override.
|
||||
foreach (var data in validPublishedServerUrls)
|
||||
{
|
||||
// Get address interface.
|
||||
var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(x => data.Key.Subnet.Contains(x.Address));
|
||||
|
||||
if (isInExternalSubnet && (data.Key.Address.Equals(IPAddress.Any) || data.Key.Address.Equals(IPAddress.IPv6Any)))
|
||||
{
|
||||
// External.
|
||||
@ -886,6 +902,9 @@ namespace Jellyfin.Networking.Manager
|
||||
break;
|
||||
}
|
||||
|
||||
// Get address interface.
|
||||
var intf = _interfaces.OrderBy(x => x.Index).FirstOrDefault(x => data.Key.Subnet.Contains(x.Address));
|
||||
|
||||
if (intf?.Address != null)
|
||||
{
|
||||
// Match IP address.
|
||||
@ -896,7 +915,7 @@ namespace Jellyfin.Networking.Manager
|
||||
|
||||
if (string.IsNullOrEmpty(bindPreference))
|
||||
{
|
||||
_logger.LogDebug("{Source}: No matching bind address override found.", source);
|
||||
_logger.LogDebug("{Source}: No matching bind address override found", source);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -941,40 +960,22 @@ namespace Jellyfin.Networking.Manager
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
if (count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IPAddress? bindAddress = null;
|
||||
if (isInExternalSubnet)
|
||||
{
|
||||
IPAddress? bindAddress = null;
|
||||
var externalInterfaces = _interfaces.Where(x => !IsInLocalNetwork(x.Address))
|
||||
.OrderBy(x => x.Index)
|
||||
.ToList();
|
||||
|
||||
if (isInExternalSubnet)
|
||||
if (externalInterfaces.Count > 0)
|
||||
{
|
||||
if (externalInterfaces.Any())
|
||||
{
|
||||
// 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.
|
||||
bindAddress = externalInterfaces
|
||||
.OrderByDescending(x => x.Subnet.Contains(source))
|
||||
.ThenBy(x => x.Index)
|
||||
.Select(x => x.Address)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (bindAddress != null)
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(bindAddress);
|
||||
_logger.LogDebug("{Source}: External request received, matching external bind address found: {Result}", source, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogWarning("{Source}: External request received, no matching external bind address found, trying internal addresses.", source);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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.
|
||||
bindAddress = _interfaces.Where(x => IsInLocalNetwork(x.Address))
|
||||
// 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.
|
||||
bindAddress = externalInterfaces
|
||||
.OrderByDescending(x => x.Subnet.Contains(source))
|
||||
.ThenBy(x => x.Index)
|
||||
.Select(x => x.Address)
|
||||
@ -983,10 +984,29 @@ namespace Jellyfin.Networking.Manager
|
||||
if (bindAddress != null)
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(bindAddress);
|
||||
_logger.LogDebug("{Source}: Internal request received, matching internal bind address found: {Result}", source, result);
|
||||
_logger.LogDebug("{Source}: External request received, matching external bind address found: {Result}", source, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogWarning("{Source}: External request received, no matching external bind address found, trying internal addresses.", source);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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.
|
||||
bindAddress = _interfaces.Where(x => IsInLocalNetwork(x.Address))
|
||||
.OrderByDescending(x => x.Subnet.Contains(source))
|
||||
.ThenBy(x => x.Index)
|
||||
.Select(x => x.Address)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (bindAddress != null)
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(bindAddress);
|
||||
_logger.LogDebug("{Source}: Internal request received, matching internal bind address found: {Result}", source, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -1000,16 +1020,21 @@ namespace Jellyfin.Networking.Manager
|
||||
/// <returns><c>true</c> if a match is found, <c>false</c> otherwise.</returns>
|
||||
private bool MatchesExternalInterface(IPAddress source, out string result)
|
||||
{
|
||||
result = string.Empty;
|
||||
// Get the first WAN interface address that isn't a loopback.
|
||||
var extResult = _interfaces.Where(p => !IsInLocalNetwork(p.Address)).OrderBy(x => x.Index);
|
||||
// Get the first external interface address that isn't a loopback.
|
||||
var extResult = _interfaces.Where(p => !IsInLocalNetwork(p.Address)).OrderBy(x => x.Index).ToArray();
|
||||
|
||||
// No external interface found
|
||||
if (extResult.Length == 0)
|
||||
{
|
||||
result = string.Empty;
|
||||
_logger.LogWarning("{Source}: External request received, but no external interface found. Need to route through internal network.", source);
|
||||
return false;
|
||||
}
|
||||
|
||||
IPAddress? hasResult = null;
|
||||
// Does the request originate in one of the interface subnets?
|
||||
// (For systems with multiple internal network cards, and multiple subnets)
|
||||
// (For systems with multiple network cards and/or multiple subnets)
|
||||
foreach (var intf in extResult)
|
||||
{
|
||||
hasResult ??= intf.Address;
|
||||
if (!IsInLocalNetwork(intf.Address) && intf.Subnet.Contains(source))
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(intf.Address);
|
||||
@ -1018,15 +1043,10 @@ namespace Jellyfin.Networking.Manager
|
||||
}
|
||||
}
|
||||
|
||||
if (hasResult != null)
|
||||
{
|
||||
result = NetworkExtensions.FormatIpString(hasResult);
|
||||
_logger.LogDebug("{Source}: Using first external interface as bind address: {Result}", source, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.LogWarning("{Source}: External request received, but no external interface found. Need to route through internal network.", source);
|
||||
return false;
|
||||
// Fallback to first external interface.
|
||||
result = NetworkExtensions.FormatIpString(extResult.First().Address);
|
||||
_logger.LogDebug("{Source}: Using first external interface as bind address: {Result}", source, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,10 +59,16 @@ namespace MediaBrowser.Common.Net
|
||||
{
|
||||
get
|
||||
{
|
||||
return Address.Equals(IPAddress.None)
|
||||
? (Subnet.Prefix.AddressFamily.Equals(IPAddress.None)
|
||||
? AddressFamily.Unspecified : Subnet.Prefix.AddressFamily)
|
||||
: Address.AddressFamily;
|
||||
if (Address.Equals(IPAddress.None))
|
||||
{
|
||||
return Subnet.Prefix.AddressFamily.Equals(IPAddress.None)
|
||||
? AddressFamily.Unspecified
|
||||
: Subnet.Prefix.AddressFamily;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Address.AddressFamily;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user