Problems discovering DVR server if interface has multiple IPs

I recently moved my Channels DVR instance to a new server and am now running into a problem that I had not experienced before. My instance of the DVR server is running inside a systemd-nspawn container, using a bridge interface on the host. When run under these conditions, systemd-networkd defaults to soliciting a DHCP address on the container's host0 network interface, which works without a problem.

The problem, however, is that the default .network file used for containers (/usr/lib/systemd/network/80-container-host.network) also assigns a LinkLocal address (169.254/16) on the host0 network interface. When Channels is started on the container, it shows that it is running and advertising its services on both IP addresses: 10.0.0.x which is in line with the 10/8 LAN in my home, as well as the 169.254.x.x LinkLocal address that systemd-networkd adds by default.

When attempting to use a client on the home network (10/8) to connect to the server, it cannot find the server and must be manually specified by inputting the DVR server's IP address. It appears that Channels is only advertising the DVR server on the LinkLocal address, because when you visit the DVR settings tab in the client, even if the server was manually specified by a 10/8 IP address, the client claims it is connected to a DVR at 169.254.x.x.

This can be worked around by superseding the default 80-container-host.network configuration file by replacing it with one in /etc/systemd/network. However, on servers with multiple interfaces and/or IP addresses it would be nice if we could have a command line flag to pass to the DVR server to specify which interface(s) and/or IP address(es) to listen on. (Or perhaps to publish/broadcast its presence on all interfaces/IP addresses instead of only advertising on the first IP address.)

Any thoughts? Have others run into a similar situation?

The DVR advertises on every available interface using the IP on that interface. So your setup shouldn't be causing issues.

Can you post the output of /bonjour and /system/network

Default /usr/lib/systemd/network/80-container-host0.network:

[Match]
Virtualization=container
Name=host0

[Network]
DHCP=yes
LinkLocalAddressing=yes
LLDP=yes
EmitLLDP=customer-bridge

[DHCP]
UseTimezone=yes

Returns this:

  • /bonjour
{
  "addresses": ["10.0.0.81","169.254.105.102"],
  "enabled":true,
  "hostname":"dvr-channels.local.",
  "interfaces":["host0"]
}
  • /system/network
[
  {
    "mtu":65536,
    "name":"lo",
    "hardwareaddr":"",
    "flags":["up","loopback"],
    "addrs":[
      {"addr":"127.0.0.1/8"},
      {"addr":"::1/128"}
    ]
  },
  {
    "mtu":1500,
    "name":"host0",
    "hardwareaddr":"b2:1b:cc:4e:75:e4",
    "flags":["up","broadcast","multicast"],
    "addrs":[
      {"addr":"169.254.105.102/16"},
      {"addr":"10.0.0.81/24"},
      {"addr":"fe80::b01b:ccff:fe4e:75e4/64"}
    ]
  }
]

Modified/override 80-container-host0.network:

[Match]
Virtualization=container
Name=host0

[Network]
DHCP=ipv4
LinkLocalAddressing=no
LLDP=no
EmitLLDP=customer-bridge

[DHCP]
UseTimezone=yes

Returns this:

  • /bonjour
{
  "addresses":["10.0.0.81"],
  "enabled":true,
  "hostname":"dvr-channels.local.",
  "interfaces":["host0"]
}
  • /system/network
[
  {
    "mtu":65536,
    "name":"lo",
    "hardwareaddr":"",
    "flags":["up","loopback"],
    "addrs":[
      {"addr":"127.0.0.1/8"},
      {"addr":"::1/128"}
    ]
  },
  {
    "mtu":1500,
    "name":"host0",
    "hardwareaddr":"b2:1b:cc:4e:75:e4",
    "flags":["up","broadcast","multicast"],
    "addrs":[
      {"addr":"10.0.0.81/24"}
    ]
  }
]

I see, so there's only one interface and it has both IPs on it.

That's tricky. Probably the best we can do is try to ignore 169.x addresses on an interface when other IPs are also present.

The problem is that LL addresses are perfectly valid (and while I rarely have need of them, sometimes they are useful). As I mentioned, I worked around this by:

  • specifying a manual IP address for the server in the clients after local discovery timed out, or by
  • overriding systemd-nspawn's default host0 configuration to disable automatic creation of LinkLocal addresses.

I realize my use case is probably a bit outside the norm for most users of Channels. I just wondered whether I was imagining a problem where one didn't exist, if I can misconfigured my network is some way (quite a real possibility, especially with opaque situations such as containers and nested networking), whether I missed a setting or flag for the server, or if I had just run into a situation unforeseen by the developers.

If you are considering modifying Channels' behavior, may I suggest instead of ignoring LL 169.254/16 addresses that you offer command line flags to specify network settings such as interfaces or IP addresses to attach to instead of always trying to attach to all interfaces/addresses.

Also, just a note to say "Thanks!" to Aman and everyone with the Channels team for the prompt and awesome support.

2 Likes

I had hoped that with systemd 244 this would have been fixed.

  • systemd-networkd does not create a default route for IPv4 link local
    addressing anymore. The creation of the route was unexpected and was
    breaking routing in various cases, but people who rely on it being
    created implicitly will need to adjust. Such a route may be requested
    with DefaultRouteOnDevice=yes.
    Similarly, systemd-networkd will not assign a link-local IPv6 address
    when IPv6 link-local routing is not enabled.

Alas, that was not the case, and the override 80-container-host.network file is still required to get Channels DVR clients (at least, Android clients) to discover DVR servers on the network.