diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 703f8d20da..7b4592fbc0 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -1203,12 +1203,8 @@ namespace Emby.Server.Implementations
///
public string GetLoopbackHttpApiUrl()
{
- if (NetManager.IsIP6Enabled)
- {
- return GetLocalApiUrl("::1", Uri.UriSchemeHttp, HttpPort);
- }
-
- return GetLocalApiUrl("127.0.0.1", Uri.UriSchemeHttp, HttpPort);
+ // Passing an external address cause GetBindInterface to return an externally accessible interface (if possible).
+ return GetLocalApiUrl(NetManager.GetBindInterface("8.8.8.8", out var _), Uri.UriSchemeHttp, HttpPort);
}
///
diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs
index 73e8b2cd72..fd8455dc85 100644
--- a/Jellyfin.Networking/Manager/NetworkManager.cs
+++ b/Jellyfin.Networking/Manager/NetworkManager.cs
@@ -990,6 +990,7 @@ namespace Jellyfin.Networking.Manager
// Read and parse bind addresses and exclusions, removing ones that don't exist.
_bindAddresses = CreateIPCollection(lanAddresses).ThatAreContainedInNetworks(_interfaceAddresses);
_bindExclusions = CreateIPCollection(lanAddresses, true).ThatAreContainedInNetworks(_interfaceAddresses);
+
_logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString());
_logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString());
}
diff --git a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
index 1cad625b73..61f9132528 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs
@@ -34,7 +34,7 @@ namespace Jellyfin.Networking.Tests
}
///
- /// Checks that thge given IP address is not in the network provided.
+ /// Checks that the given IP address is not in the network provided.
///
/// Network address(es).
/// The IP to check.
diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
index 9b0da2b3c4..ea14772910 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.ObjectModel;
+using System.Linq;
using System.Net;
using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager;
@@ -530,5 +531,52 @@ namespace Jellyfin.Networking.Tests
Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied);
}
+
+ [Theory]
+ [InlineData("192.168.1.209/24,-16,eth16", "192.168.1.0/24", "", "192.168.1.209")] // Only 1 address so use it.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.208")] // LAN address is specified by default.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "10.0.0.1")] // return bind address
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209")] // return internal bind address (Internal takes priority)
+
+ public void Get_Appropriate_Interface_NoSource(string interfaces, string lan, string bind, string result)
+ {
+ var conf = new NetworkConfiguration()
+ {
+ EnableIPV4 = true,
+ LocalNetworkSubnets = lan.Split(','),
+ LocalNetworkAddresses = bind.Split(',')
+ };
+
+ NetworkManager.MockNetworkSettings = interfaces;
+ using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger());
+
+ var interfaceToUse = nm.GetBindInterface(string.Empty, out var port);
+
+ Assert.Equal(interfaceToUse, result);
+ }
+
+ [Theory]
+ [InlineData("192.168.1.209/24,-16,eth16", "192.168.1.0/24", "", "192.168.1.210", "192.168.1.209")] // Source on LAN
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.209", "192.168.1.208")] // Source on LAN
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "8.8.8.8", "10.0.0.1")] // Source external.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209", "10.0.0.1")] // LAN not bound, so return external.
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "8.8.8.8", "10.0.0.1")] // return external bind address
+ [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "192.168.1.210", "192.168.1.208")] // return LAN bind address
+ public void Get_Appropriate_Interface_ForSource(string interfaces, string lan, string bind, string source, string result)
+ {
+ var conf = new NetworkConfiguration()
+ {
+ EnableIPV4 = true,
+ LocalNetworkSubnets = lan.Split(','),
+ LocalNetworkAddresses = bind.Split(',')
+ };
+
+ NetworkManager.MockNetworkSettings = interfaces;
+ using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger());
+
+ var interfaceToUse = nm.GetBindInterface(source, out var port);
+
+ Assert.Equal(interfaceToUse, result);
+ }
}
}