Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Companion doesn't detect and rebind service to new IP if bound interface's address changes #3193

Open
2 tasks done
spoelstraethan opened this issue Dec 30, 2024 · 4 comments
Labels
area/launcher Skeleton Launcher Enhancement New feature or request

Comments

@spoelstraethan
Copy link

Is this a bug in companion itself or a module?

  • I believe this to be a bug in companion

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I have a Mac Mini running the latest Stable companion, I was reorganizing the desk where it sits so it was unplugged from the network for a little while, and since I test a LOT of devices I have a pretty short DHCP lease time on my firewall/router and apparently in the time it was unplugged another device came online and ended up grabbing the IP it was bound to. I'd imagine if I had used the 0.0.0.0 binding that Companion might have correctly started responding to the new IP, but I specifically want to be able to have Companion only accessible on the device's wired interface while having the wireless interface only used for inbound remote desktop/SSH type management connections.

Pretty soon I'll be putting the wired interface into a separate VLAN (and probably adding a static IP to sort of work around this issue) because many of the local network services/devices that Companion can interact with have pretty poor security (or require downgrading the security to talk to Companion) and shouldn't be exposed to potentially compromised Windows (or other OS) hosts and/or IoT devices that are commonly used in botnets and for network penetration because people DON'T properly isolate things.

Steps To Reproduce

  1. Launch Companion and select a specific interface/IP to bind to.
  2. Flush/clear the router's DHCP leases and refresh the host's network interface (or set a new different IP manually).
  3. Confirm Companion isn't accessible via the new IP from another host, and running "Launch GUI" from companion uses the old IP.
  4. Quit and relaunch Companion and notice it may still be using the old IP (it was in my case)
  5. Manually change the interface binding to the new interface/IP address and save
  6. Confirm Companion is now accessible via the new IP since it was explicitly bound again.

Expected Behavior

I would have expected that if the IP address of the host's bound interface changed that Companion could/should have noticed, and if the application process is bound to a specific IP that is no longer present (but the interface is still there) I would expect it to pick up the new IP (but not switch interfaces), possibly by restarting the service process.

Environment (please complete the following information)

- OS: macOS Ventura 13.6.9
- Browser: Google Chrome and Safari
- Companion Version: 3.4.3 stable

Additional context

No response

@spoelstraethan spoelstraethan added the BUG Something isn't working label Dec 30, 2024
@krocheck krocheck added Enhancement New feature or request Good first issue Good for newcomers area/launcher Skeleton Launcher and removed BUG Something isn't working Good first issue Good for newcomers labels Jan 1, 2025
@krocheck krocheck changed the title [BUG] Companion doesn't detect and rebind service to new IP if bound interface's address changes (ie network hiccup and DHCP hands current IP to something else) Companion doesn't detect and rebind service to new IP if bound interface's address changes Jan 1, 2025
@krocheck
Copy link
Member

krocheck commented Jan 1, 2025

I reclassified this as an enhancement, although I can easily see why this would be thought of as a bug. The noted behavior has been true of Companion since the original versions, and I believe we added the "All Interfaces: 0.0.0.0" option as the workaround for users that regularly encountered this as a problem or had special network setups (e.g. VLANs on interfaces in Win). It has always been the case that we're binding to the IP of the interface, not the interface itself. There are technical reasons for this.

As it stands systeminformation, which is the library that provides us the interfaces and IPs on launch, does not have a way to 'subscribe' to interface changes. This would instead require us to manually poll for changes on an interval. I'd have to find it, but we had an issue where a user reported we were polling the OS too aggressively for a different parameter and it was causing slowdowns and/or crashes on lightweight platforms like the RaspberryPi. Like there, we'd have to come to some agreement on the polling interval and I'd push for something as long as 10 minutes (maybe 5), but nothing lower than that. So in your scenario this would allow for recovery but would take as long as 5-10 minutes based on when the change happened in the interval's cycle (or we'd have to put a button to manually refresh in the UI, which defeats the purpose because you can just re-pick the interface w/ new IP at that point).

Plus we'd have to change how the storage of the selected option is handled, as we currently store the bound IP, not the interface. And this is why the dropdown does not highlight to the last selected interface on launch and instead shows "Change network interface".

I'll leave this open, but I'm opposed to adding polling for this, so unless there's a different library out there that we can use to subscribe to interface changes, I don't see this getting picked up by anyone.

@krocheck
Copy link
Member

krocheck commented Jan 1, 2025

@spoelstraethan I'm going to add some specific notes about your setup and wanting to restrict the Companion interface to just the wired segment.

  • All Interfaces should account for changes in realtime with no intervention ... that's the intent and if not that would be a bug
  • You could block the Companion port via the OS firewall on the non-wired segments as a work-around
  • Any Companion remote control services you have on (e.g. TCP control, OSC control) listen on all interfaces (ips) regardless of the UI selection. That dropdown, as noted, only handles the bind address for the GUI (and the HTTP API). All other Companion service ports are exposed on your non-wired segments unless you disable them via a firewall.

@spoelstraethan
Copy link
Author

So if I'm understanding correctly even though the web interface wasn't functional to change my buttons, I should be able to send state changes like volume via knobs and activate other functions via my Stream Deck devices even though the web interface was bound to the wrong IP because outbound requests are handled through a different thread and wouldn't try to use that bogus IP?

I may see if I can force this state by assigning a different IP via DHCP reservation and then confirm that re-plugging a Stream Deck device the system has previously seen picks up the config and lets me control things as that would at least give me confidence that this isn't a show stopper, but not having the application automatically resolve the fact that the IP isn't available on the network to use anymore even through a close and open cycle is a violation of the "turn it off and on again" "appliance" hiccup fix resolution I would hope for.

If I close and reopen the app while it is trying to bind to the old IP I at least got an error that it couldn't use that IP, but does that actually leave me in a worse state than leaving the instance open with the invalid IP, because not all the background processes/connections to other systems on the network will work unless the web UI thread starts?

I also am not a fan of polling IF event driven is available and works, but sometimes you need a simple watchdog that makes sure that unexpected but entirely common state changes like the IP changing are detected and handled, and I agree a 5 or 10 minute poll rate should be sufficient, honestly even 15 minutes would probably be fine, because going much lower than that on a DHCP lease could lead to a lot of churn (though with the MAC randomization for privacy these days there is already a lot of churn).

You could block the Companion port via the OS firewall on the non-wired segments as a work-around
Any Companion remote control services you have on (e.g. TCP control, OSC control) listen on all interfaces (ips) regardless of the UI selection. That dropdown, as noted, only handles the bind address for the GUI (and the HTTP API). All other Companion service ports are exposed on your non-wired segments unless you disable them via a firewall.

This is great information, I hadn't realized that everything was basically binding 0.0.0.0 and it requires a lot of extra effort to lock down the ports, that isn't nearly as secure out of the box as I'd hoped but the design decision makes sense because it would be a lot of friction for users doing silly things like being connected to wired and wireless networks and not being able to have Companion reach certain devices because of the routing and interface binding.

@krocheck
Copy link
Member

krocheck commented Jan 2, 2025

If I close and reopen the app while it is trying to bind to the old IP I at least got an error that it couldn't use that IP, but does that actually leave me in a worse state than leaving the instance open with the invalid IP, because not all the background processes/connections to other systems on the network will work unless the web UI thread starts?

Connections are not bound to the IP selection. They lean on the OS's routing table and (when allowed by the connection) DNS to find the appropriate interface/route to the device. So long as the route it up (recovered), those will be fine. Now, some devices may not like a connected client randomly changing IP and the developer may or may not have programmed a graceful recovery from that edge case. And to the earlier question about Stream Deck and other control surfaces working while this IP state is in error; those will continue to work normally as well.

The only functionalities that cease to function if the GUI IP binding is in error are:

  • Admin GUI (where you manage the configurations)
  • Web Buttons / Emulator
  • HTTP API

This is great information, I hadn't realized that everything was basically binding 0.0.0.0 and it requires a lot of extra effort to lock down the ports, that isn't nearly as secure out of the box as I'd hoped but the design decision makes sense because it would be a lot of friction for users doing silly things like being connected to wired and wireless networks and not being able to have Companion reach certain devices because of the routing and interface binding.

Short answer is: no, this was not designed with security in mind. It was designed for isolated and/or firewall protected networks with limited actors. The admin password feature is quite basic and easily cracked, really designed to keep the interns at bay. Now, in the name of security, we did turn off all the "Remote Control" protocols on a fresh installation. But there's still ports open for always on things like the Stream Deck App, Satellite devices, Socket.IO (for the GUI to talk to the core).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/launcher Skeleton Launcher Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants