pupnp / pupnp

libupnp: Build UPnP-compliant control points, devices, and bridges on several operating systems.
https://pupnp.github.io/pupnp
BSD 3-Clause "New" or "Revised" License
352 stars 117 forks source link

Allow listening on multiple addresses and on multiple interfaces chosen by user. #156

Open crass opened 4 years ago

crass commented 4 years ago

We live in a multihomed, multi-interface world now, and it would be nice if pupnp also lived there with us. What if I want to listen on a wired and a wireless interface, or two wired interfaces or one wired interface with two IP addresses but have replies come from the second associated address on the interface (I actually do for a gerbera server on a multi-homed interface!). This isn't possible today with pupnp. My two options right now are UpnpInit(const char *HostIP, unsigned short DestPort) and UpnpInit2(const char *IfName, unsigned short DestPort). So I get to choose to listen either on one IP with the interface inferred or one interface where the IP selected can not be controlled by the user, and UpnpInit is supposedly deprecated.

Perhaps there could be a UpnpAddIPAddress(const char *HostIP) and a UpnpAddIPAddress(const char *IfName, const char *HostIP) where HostIP==NULL in the later call would mean that the first address on that interface is replied from.

Alternatively or in addition to the above (ideally both), a UpnpInit3(const char **IfNameHostIPList, unsigned short DestPort) could be added. IfNameHostIPList is a null-pointer terminated array of pointers to a null-pointer terminated array of size 1 or 2 where if the array is length 1 it contains a pointer to an interface name and if length 2 it contains a pointer to an interface name and a pointer to an IP address string. If just an interface name, then the first ip address associated with the interface is listened on (like is done now in UpnpInit2). And if an {interface, IP address} pair is given, then just the specified IP on that interface is replied from.

A cursory look at the code appears to suggest this is a non-trivial undertaking, but I think it would be great to have this feature.

makay68g commented 3 years ago

I had the same problem, but I could solve it by some simple modification of the code.

  1. I have IP aliases on the interfaces, but iptables does not really like that: I changed the executed iptables commands not to use the aliases, but rather the main interface's names. Actually, it is a bit more complicated in our case: we have bonded interfaces with tagged VLAN's and aliases on those, but it works.

  2. Also, we have a quite strict firewall, which does not forward anything from the internal networks to the external without me saying so (positive port filtering). So I had to add another forward rule allowing the internal IP address to answer the requests coming from the internet.

  3. Although starting the UPNP daemon says that it listens on 0.0.0.0:1900, it is actually bound to the interface (or ip address) of your choice given as a parameter for UpnpInit2 (or UpnpInit). Therefore you can start many instances of the UPNP daemon on the interfaces you would like to. It might be confusing to see many listening processes on 0.0.0.0:1900, but it works well. For this to work, I also needed different configuration files, but the configuration file can also be included as an option for the UPNP daemon.

I hope this helps.

limburgher commented 10 months ago

Any updates on this? I'm hitting issues with this with keepalived and gerbera, when I have multiple IPs on one interface.

Anonym271 commented 4 months ago

I am having the same issue here. I have multiple IPs on one interface and would like to advertise on both at the same time

mrjimenez commented 4 months ago

We need someone interested in implementing this feature. Patches are always welcome, but unfortunately I do not currently have the resources to develop it.

We also need more tests in github actions to be sure we don't break stuff when implementing new features.

Best regards.