mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Enforce interface bindings on SSDP, add Loopback to LAN if no LAN defined
This commit is contained in:
parent
05458a4a42
commit
f6e41269d9
@ -284,6 +284,7 @@ namespace Emby.Dlna.Main
|
|||||||
var udn = CreateUuid(_appHost.SystemId);
|
var udn = CreateUuid(_appHost.SystemId);
|
||||||
var descriptorUri = "/dlna/" + udn + "/description.xml";
|
var descriptorUri = "/dlna/" + udn + "/description.xml";
|
||||||
|
|
||||||
|
// Only get bind addresses in LAN
|
||||||
var bindAddresses = _networkManager
|
var bindAddresses = _networkManager
|
||||||
.GetInternalBindAddresses()
|
.GetInternalBindAddresses()
|
||||||
.Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork
|
.Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork
|
||||||
@ -304,12 +305,6 @@ namespace Emby.Dlna.Main
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limit to LAN addresses only
|
|
||||||
if (!_networkManager.IsInLocalNetwork(address.Address))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
|
var fullService = "urn:schemas-upnp-org:device:MediaServer:1";
|
||||||
|
|
||||||
_logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
|
_logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address);
|
||||||
|
@ -61,13 +61,18 @@ namespace Emby.Server.Implementations.Net
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ISocket CreateUdpMulticastSocket(IPAddress ipAddress, int multicastTimeToLive, int localPort)
|
public ISocket CreateUdpMulticastSocket(IPAddress ipAddress, IPAddress bindIpAddress, int multicastTimeToLive, int localPort)
|
||||||
{
|
{
|
||||||
if (ipAddress == null)
|
if (ipAddress == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(ipAddress));
|
throw new ArgumentNullException(nameof(ipAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bindIpAddress == null)
|
||||||
|
{
|
||||||
|
bindIpAddress = IPAddress.Any;
|
||||||
|
}
|
||||||
|
|
||||||
if (multicastTimeToLive <= 0)
|
if (multicastTimeToLive <= 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("multicastTimeToLive cannot be zero or less.", nameof(multicastTimeToLive));
|
throw new ArgumentException("multicastTimeToLive cannot be zero or less.", nameof(multicastTimeToLive));
|
||||||
@ -98,12 +103,10 @@ namespace Emby.Server.Implementations.Net
|
|||||||
// retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
// retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
||||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
|
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
|
||||||
|
|
||||||
var localIp = IPAddress.Any;
|
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ipAddress, bindIpAddress));
|
||||||
|
|
||||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ipAddress, localIp));
|
|
||||||
retVal.MulticastLoopback = true;
|
retVal.MulticastLoopback = true;
|
||||||
|
|
||||||
return new UdpSocket(retVal, localPort, localIp);
|
return new UdpSocket(retVal, localPort, bindIpAddress);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -298,20 +298,22 @@ namespace Jellyfin.Networking.Manager
|
|||||||
|
|
||||||
if (_lanSubnets.Count == 0)
|
if (_lanSubnets.Count == 0)
|
||||||
{
|
{
|
||||||
// If no LAN addresses are specified, all private subnets are deemed to be the LAN
|
// 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.");
|
_logger.LogDebug("Using LAN interface addresses as user provided no LAN details.");
|
||||||
|
|
||||||
if (IsIpv6Enabled)
|
if (IsIpv6Enabled)
|
||||||
{
|
{
|
||||||
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("fc00::"), 7)); // ULA
|
_lanSubnets.Add(new IPNetwork(IPAddress.IPv6Loopback, 128)); // RFC 4291 (Loopback)
|
||||||
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("fe80::"), 10)); // Site local
|
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("fe80::"), 10)); // RFC 4291 (Site local)
|
||||||
|
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("fc00::"), 7)); // RFC 4193 (Unique local)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsIpv4Enabled)
|
if (IsIpv4Enabled)
|
||||||
{
|
{
|
||||||
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
|
_lanSubnets.Add(new IPNetwork(IPAddress.Loopback, 8)); // RFC 5735 (Loopback)
|
||||||
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));
|
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8)); // RFC 1918 (private)
|
||||||
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16));
|
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12)); // RFC 1918 (private)
|
||||||
|
_lanSubnets.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16)); // RFC 1918 (private)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,11 +373,13 @@ namespace Jellyfin.Networking.Manager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all IPv4 interfaces if IPv4 is disabled
|
||||||
if (!IsIpv4Enabled)
|
if (!IsIpv4Enabled)
|
||||||
{
|
{
|
||||||
_interfaces.RemoveAll(x => x.AddressFamily == AddressFamily.InterNetwork);
|
_interfaces.RemoveAll(x => x.AddressFamily == AddressFamily.InterNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all IPv6 interfaces if IPv6 is disabled
|
||||||
if (!IsIpv6Enabled)
|
if (!IsIpv6Enabled)
|
||||||
{
|
{
|
||||||
_interfaces.RemoveAll(x => x.AddressFamily == AddressFamily.InterNetworkV6);
|
_interfaces.RemoveAll(x => x.AddressFamily == AddressFamily.InterNetworkV6);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net
|
namespace MediaBrowser.Model.Net
|
||||||
@ -23,9 +24,10 @@ namespace MediaBrowser.Model.Net
|
|||||||
/// Creates a new multicast socket using the specified multicast IP address, multicast time to live and local port.
|
/// Creates a new multicast socket using the specified multicast IP address, multicast time to live and local port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ipAddress">The multicast IP address to bind to.</param>
|
/// <param name="ipAddress">The multicast IP address to bind to.</param>
|
||||||
|
/// <param name="bindIpAddress">The bind IP address.</param>
|
||||||
/// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param>
|
/// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param>
|
||||||
/// <param name="localPort">The local port to bind to.</param>
|
/// <param name="localPort">The local port to bind to.</param>
|
||||||
/// <returns>A <see cref="ISocket"/> implementation.</returns>
|
/// <returns>A <see cref="ISocket"/> implementation.</returns>
|
||||||
ISocket CreateUdpMulticastSocket(IPAddress ipAddress, int multicastTimeToLive, int localPort);
|
ISocket CreateUdpMulticastSocket(IPAddress ipAddress, IPAddress bindIpAddress, int multicastTimeToLive, int localPort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace Rssdp.Infrastructure
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private object _BroadcastListenSocketSynchroniser = new object();
|
private object _BroadcastListenSocketSynchroniser = new object();
|
||||||
private ISocket _BroadcastListenSocket;
|
private List<ISocket> _BroadcastListenSockets;
|
||||||
|
|
||||||
private object _SendSocketSynchroniser = new object();
|
private object _SendSocketSynchroniser = new object();
|
||||||
private List<ISocket> _sendSockets;
|
private List<ISocket> _sendSockets;
|
||||||
@ -111,24 +111,21 @@ namespace Rssdp.Infrastructure
|
|||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
if (_BroadcastListenSocket == null)
|
lock (_BroadcastListenSocketSynchroniser)
|
||||||
{
|
{
|
||||||
lock (_BroadcastListenSocketSynchroniser)
|
if (_BroadcastListenSockets == null)
|
||||||
{
|
{
|
||||||
if (_BroadcastListenSocket == null)
|
try
|
||||||
{
|
{
|
||||||
try
|
_BroadcastListenSockets = ListenForBroadcastsAsync();
|
||||||
{
|
}
|
||||||
_BroadcastListenSocket = ListenForBroadcastsAsync();
|
catch (SocketException ex)
|
||||||
}
|
{
|
||||||
catch (SocketException ex)
|
_logger.LogError("Failed to bind to port 1900: {Message}. DLNA will be unavailable", ex.Message);
|
||||||
{
|
}
|
||||||
_logger.LogError("Failed to bind to port 1900: {Message}. DLNA will be unavailable", ex.Message);
|
catch (Exception ex)
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
_logger.LogError(ex, "Error in BeginListeningForBroadcasts");
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Error in BeginListeningForBroadcasts");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,11 +139,15 @@ namespace Rssdp.Infrastructure
|
|||||||
{
|
{
|
||||||
lock (_BroadcastListenSocketSynchroniser)
|
lock (_BroadcastListenSocketSynchroniser)
|
||||||
{
|
{
|
||||||
if (_BroadcastListenSocket != null)
|
if (_BroadcastListenSockets != null)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("{0} disposing _BroadcastListenSocket", GetType().Name);
|
_logger.LogInformation("{0} disposing _BroadcastListenSocket", GetType().Name);
|
||||||
_BroadcastListenSocket.Dispose();
|
foreach (var socket in _BroadcastListenSockets)
|
||||||
_BroadcastListenSocket = null;
|
{
|
||||||
|
socket.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_BroadcastListenSockets = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,12 +337,40 @@ namespace Rssdp.Infrastructure
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISocket ListenForBroadcastsAsync()
|
private List<ISocket> ListenForBroadcastsAsync()
|
||||||
{
|
{
|
||||||
var socket = _SocketFactory.CreateUdpMulticastSocket(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), _MulticastTtl, SsdpConstants.MulticastPort);
|
var sockets = new List<ISocket>();
|
||||||
_ = ListenToSocketInternal(socket);
|
if (_enableMultiSocketBinding)
|
||||||
|
{
|
||||||
|
foreach (var address in _networkManager.GetInternalBindAddresses())
|
||||||
|
{
|
||||||
|
if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
// Not support IPv6 right now
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return socket;
|
try
|
||||||
|
{
|
||||||
|
sockets.Add(_SocketFactory.CreateUdpMulticastSocket(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), address.Address, _MulticastTtl, SsdpConstants.MulticastPort));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error in ListenForBroadcastsAsync. IPAddress: {0}", address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sockets.Add(_SocketFactory.CreateUdpMulticastSocket(IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress), IPAddress.Any, _MulticastTtl, SsdpConstants.MulticastPort));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var socket in sockets)
|
||||||
|
{
|
||||||
|
_ = ListenToSocketInternal(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sockets;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ISocket> CreateSocketAndListenForResponsesAsync()
|
private List<ISocket> CreateSocketAndListenForResponsesAsync()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user