mafintosh / dns-discovery

Discovery peers in a distributed system using regular dns and multicast dns.
MIT License
193 stars 18 forks source link

Use all local network interfaces instead of network-address #16

Open RangerMauve opened 6 years ago

RangerMauve commented 6 years ago

I've got a virtualbox network installed on my machine, and network-address resolves to this IP address instead of my WiFi or Ethernet.

This means that my laptop will never make connections on local networks and must rely on the DNS discovery servers to connect over the internet.

I think this will be a problem for supporting local networks on other machines as well.

I think a good alternative would be to enumerate all the local IP addresses and publish all of them on MDNS, this will also support bridging multiple local networks together.

The change will need to happen here, and could probably take some of the logic right out of network-interface.

RangerMauve commented 6 years ago

Ping @pfrazee

Also, would you mind pointing me to the part of dns-discovery that gets it's public IP from the discovery server? (The replacement to STUN)

RangerMauve commented 6 years ago

Here are are comments from IRC based on someone having issues getting discovery to work with their VPN.

``` Samuel Loury @Konubinix Jul 25 02:40 Hi. I just found out about dat and decided to give it a try. I have two computer connected via the tinc vpn and I cannot find a way to say to dat to make then connect through the tinc ip Somehow, dat find out my public and my local network addresses and tries to use those. It there anything like 'dat clone dat:some_key --address the_address_on_tinc' ? Anyway, I use a lot IPFS to share content between my computers, using ugly ad-hoc bash scripts to try to synchronise them. Dat appears to be much more suited to my use case than IPFS. So great job guys! konobi_ Konubinix: iirc it listens on 0.0.0.0, so it'll use the appropriate IP based on netmask, etc. Samuel Loury @Konubinix Jul 25 02:54 @dat-bot: I could see that both listen to 0.0.0.0. But when I run "dat doctor" on one and "dat doctor the_key_given_by_the_previous_dat_doctor", I can observe that the later tries to connect to the former through the local network or the public ip, not the tinc ip. dat-bot @dat-bot Jul 25 02:54 konobi_ Konubinix: it's probably something that could be added... but if you're looking for an immediate fix, there are a variety of LD_PRELOAD style libraries available that allow you to force the process to bind to a specific IP... bindhack and netjail are examples Samuel Loury @Konubinix Jul 25 02:57 @dat-bot: Not really looking for an immediate fix. May be with some hint about where dat finds out in which ip addresses the peers are located, I could try to pull request the feature dat-bot @dat-bot Jul 25 02:58 konobi_ dat-swarm is the underpinings to how peers are discovered, etc. Samuel Loury @Konubinix Jul 25 02:58 @dat-bot: Also, I don't think this is a problem of bind, since both are listening on 0.0.0.0. It is most likely a problem of host discovery. @dat-bot: On the master branch of dat, there is no mention of dat-swarm. May be the peer discovery is now done in hyperdiscovery ? Just guessing, based on the name dat-bot @dat-bot Jul 25 03:11 konubinix Thanks, I will take a look at those RangerMauve @RangerMauve Jul 25 09:27 @Konubinix Might be related to this issue in dns-discovery: mafintosh/dns-discovery#16 Basically, it uses a library called network-interface to find your local IP address. It ends up taking the first valid IP from the list and discarding the rest. This means that if you have a VPN, unless network-interface picks up that interface first, it'll never bother advertising on it. dat-bot @dat-bot Jul 25 09:56 konubinix RangerMauve: Thank you :-) konubinix Actually, it is called network-address RangerMauve @RangerMauve Jul 25 10:02 konubinix: My bad! That's probably what you can hack around with if you go into node_modules directly, though. :o dat-bot @dat-bot Jul 25 10:04 konubinix I tried to hardcode my vpn ip address in this package to validate your hypothesis. Unfortunately, dat-doctor still shows my local network ip address konubinix Thanks for the tip though RangerMauve @RangerMauve Jul 25 12:40 konubinix: Dang it. :( konubinix konobi_: mafintosh : The issue was that two computers only connected via a vpn won't find each other konubinix I looked at the code and found out that the discovery-channel owns a dns-discovery that owns a multicast-dns konubinix The multicast-dns is setup to acknowledge all the interfaces (via the addMembership method), but only communicate through the default interface (computed with defaultInterface) konubinix In the case the default interface is not the vpn's, both computers won't see each other konubinix I tested to hardcode the output of defaultInterface to the ip address of my vpn, and the connection happened this time konubinix I need to understand how mdns works more thoroughly before jumping to conclusions. I'm still ensure what addMembership means. dat-bot @dat-bot Jul 26 02:10 konubinix On first glance, I guess that the multicast should communicate through all the interfaces. That way, when the discovery-channel calls the announce of dns-discovery that itself sends a multicast-dns message about itself, the multicast-dns would send the message on all the interfaces. dat-bot @dat-bot Jul 26 02:45 konobi_ konubinix: ah... multicast is link-local, so it would need an addMembership per interface konobi_ konubinix: do you have a link to the lines of code where this multicast membership setup is? dat-bot @dat-bot Jul 26 02:56 konubinix konobi_: The membership is setup in https://github.com/mafintosh/multicast-dns/blob/master/index.js#L134 konubinix I am currently reading https://www.tldp.org/HOWTO/text/Multicast-HOWTO konubinix And found an interesting piece of information on https://stackoverflow.com/questions/10692956/what-does-it-mean-to-bind-a-multicast-udp-socket konubinix konobi_: IIUC, when using multicast, the bound address is the one receiving the messages. The membership is the list of interfaces to which the messages will be sent. konubinix 2.4.1. Joining a Multicast Group., https://www.tldp.org/HOWTO/text/Multicast-HOWTO konubinix So, when in https://github.com/mafintosh/multicast-dns/blob/master/index.js, the socket is bound to, say 192.168.1.2, it says that it will listen to packets from this interface konubinix Then, when adding the membership to 192.168.1.2 and 192.168.2.2, it says it will send packets to both konubinix But it will never receive packets from 192.168.2.2 konubinix Hmmm, I forgot to mention that my local network is 192.168.1.0 and my vpn network is 192.168.2.0 dat-bot @dat-bot Jul 26 03:01 konobi_ iirc, you use setMulticastInterface to set the interface to bind as a multicast socket... addMembership is how you add a multicast group address to the socket konubinix konobi_: I did not see this konobi_ (which looks like an address like https://en.wikipedia.org/wiki/Multicast_address#IPv4 ) konubinix So there are 3 things to consider. The multicast binds a socket on the defaultInterface, then setMulticastInterface to the defaultInterface and finally addMembership to all the interfaces konobi_ multicast is full of little quirks, especially across OS and even node versions =0/ konubinix Using the zeroconf multicast group 224.0.0.251 konubinix konobi_: Actually, now that I start to understand multicast and the multicast-dns code better, I think that my situation makes sense konubinix I think that the multicast-dns code should bind on all the interfaces so that it can receive the packets that were sent to the multicast group from any interface dat-bot @dat-bot Jul 26 03:07 konobi_ yeah, though I know a network engineer or two that'd slap my wrists konubinix This explains why when I hardcode the defaultInterface to 192.168.2.2, the connection starts to work. By doing so, I just told it to listen to the multicast paquets going through the vpn and sent by the other side konubinix konobi_: Why ? konubinix Ohh BTW, the part that I was referring to in https://www.tldp.org/HOWTO/text/Multicast-HOWTO was: "Finally, consider that for a process to receive multicast datagrams it has to ask the kernel to join the group and bind the port those datagrams were being sent to." konobi_ i also wonder if in multicast-dns there may be an ordering issue in whether addMembership or setMulticastInterface is needed to be first konobi_ nodejs api docs don't give an indication on that konubinix konobi_: I can see the igmp packets with tcpdump, so I think that the joining of the multicast group was a success konobi_ nice! dat-bot @dat-bot Jul 26 03:14 konobi_ RangerMauve: ^^ this may be of interest to you dat-bot @dat-bot Jul 26 03:26 konubinix konobi_: I'm starting to see what you mean by "multicast is full of little quirks, especially across OS" konubinix I tried binding to 0.0.0.0 and setMulticastInterface to 0.0.0.0, without success konobi_ konubinix: which nodejs version are you using, for reference? konubinix v9.8.0 on one side, v9.6.1 on the other konobi_ tbh, I wouldn't expect 0.0.0.0 to work in that scenario, since it's not describing a specific interface dat-bot @dat-bot Jul 26 03:32 konobi_ ugh... multicast makes my head hurt... spent many days/weeks dealing with it for dhcp fun several years back konubinix konobi_: I guessed that binding on 0.0.0.0 would indicate we want to listen to multicast packet, whatever interface they come through konubinix I don't get the point of choosing ONE interface to bind, when you already indicate the interfaces you want to use in addMembership konubinix For what I could understand, the bind indicated the RECEIVE interfaces, the addMembership indicated the SEND interfaces. konobi_ bind and setMulticastInterface are related to configuring the socket, the addMembership is about linking the multicast group(s) from the kernel to the socket konobi_ iirc konubinix Now, there is also the setMulticastInterface, that is about another interface... konubinix konobi_: Yes, but in addMembership, you also precise the interfaces konubinix As second argument dat-bot @dat-bot Jul 26 03:37 konobi_ yup... since you can have multicast traffic on the same address across a variety of interfaces konubinix I wonder what would mean bind(A), setMulticastInterface(B) and addMembership(..., C) -> listen on A, but actually listen on B and finally communicate on C? konobi_ setMulticastInterface seems to be specific to how multicast messages are sent (you're forcing the interface that it sends on, rather than letting the kernel do that on your behalf) konobi_ the nodejs docs indicate that using setMulticastInterface with 0.0.0.0 tells it to revert control to the kernel (assuming you had limited it previously) dat-bot @dat-bot Jul 26 03:46 konobi_ konubinix: the multicast group address can exist on multiple or all your interfaces... so you need to explicitly state which interfaces you want to receive that multicast traffic for (on the socket that is being configured) konubinix konobi_: I still don't understand, could you explain it with the example "bind(A), setMulticastInterface(B) and addMembership(..., C)"? konubinix To make it more concrete dat-bot @dat-bot Jul 26 03:52 konobi_ bind is to a port number... to get it to listen on a specific address and therefor a specific interface you'd follow up with a listen(). So initially a bind will configure against a port. setMulticastInterface uses the address of an interface to configure which interface you want to restrict multicast domain to (for the configured socket in question) konobi_ addmembership is using 2 addresses, the first is the multicast group address, which is the common thing your clients will agree to communicate on/via. The second address is just to pick an interface upon which you want multicast traffic to be received and then routed to your configured socket konobi_ you can addmembership a bunch of times for each interface you want to be listening for multicast traffic on, but multicast is explicitly opt-in (iirc, historical reasons, security, etc) dat-bot @dat-bot Jul 26 03:57 konobi_ konubinix: tbh, I have a feeling that setMulticastInterface usage here is over-eager and may not need to be used konobi_ (though there may be a quirk specific to mafintosh's needs that I'm unable to take into account) dat-bot @dat-bot Jul 26 04:06 konobi_ konubinix: that make any sense at all? konobi_ (it's a topic that I always have to refresh myself on, so it may be a little fragmented) konubinix konobi_: Thank you for the explanation. I'm reading it konubinix In node, bind and listen appear to be mixed together in socket.bind(port, address) konubinix As in the code of multicast-dns -> socket.bind(port, opts.interface) konubinix Therefore we still precise the listening address twice: once in socket.bind(port, address1), another time with setMulticastInterface(address2) dat-bot @dat-bot Jul 26 05:17 konubinix Yet, the doc says that "For IPv4 sockets, this should be the IP configured for the desired physical interface." konubinix I guess this means address2 == address1 konubinix IIUC, by with the code socket.bind(5353, some_not_vpn_local_address) ; socket.addMembership("224.0.0.251", vpn_local_address), the trafic sent to the socket should go through the vpn interface. Right ? konubinix I can see the igmp packets resulting from addMembership on the vpn interface, but that's all dat-bot @dat-bot Jul 26 05:22 konubinix On both sides dat-bot @dat-bot Jul 26 05:29 konobi_ konubinix: with a unicast address, it can only ever interact via a single interface (modulo some very esoteric cases)... with multicast, the same "address" or specifically multicast group address, it can interact with any or all interfaces all at the same time. konobi_ so the "listening" address I think you're thinking of with bind is the unicast one... but in the multicast case, it's superfluous konobi_ the kernel is doing the listening on your behalf, but you're instructing it which socket struct to forward that traffic to and which interfaces you want that traffic from dat-bot @dat-bot Jul 26 05:37 konobi_ setMulticastInterface isn't about listening from what I'm reading... it's more akin to setting a default route/interface for sending multicast packets konobi_ "traffic sent to the socket" is ambiguous? we'd need to define the direction in which it's being sent konobi_ from host to (MC) domain or (MC) domain to host dat-bot @dat-bot Jul 26 05:49 konobi_ lets go with two MC domains... Internal and DMZ... bind (with just a port... ignore the addr part for now) sets up a socket... addMembership defines the ties between the setup socket, the MC group address and which MC domains that are attached to the socket konobi_ there's circumstances where you want to receive multicast traffic from both domains, but when responding you want to limit the sends to go only to your Internal domain rather than both... that's where setMulticastInterface comes in konobi_ i think by default, it'll send to all domains that the socket is currently in membership with dat-bot @dat-bot Jul 26 08:06 konubinix konobi_: Thank you for the detail konubinix I think I was disturbed by the superfluous thing konubinix Therefore, there is something wrong with my network, I guess konubinix I will investigate further, thank you again for the clarification dat-bot @dat-bot Jul 26 08:12 konobi_ konubinix: there's lots of places where it uses an address in the API... it's using this not as a way to bind/listen on that address itself, but since it's a unicast address, it's used to choose/identify programatically, the appropriate network interface. This is due to it being the most portable/stateless way to pick interfaces, since 'eth0' doesn't mean anything on OSX and eth0/eth1/eth2 can vary in use between machines konobi_ um... substitute the first "it" with "nodejs" konubinix konobi_: What about not providing anything to let the system guess ? konubinix Or about using IFNET_ANY ? konubinix I think it would be easier to understand konobi_ IFNET_ANY is only applicable to unicast, iirc konubinix Would it work? ... theoretically dat-bot @dat-bot Jul 26 08:54 konobi_ konubinix: the "address/interface" argument to dgram bind() is optional konobi_ (it defaults to all interfaces in that case) dat-bot @dat-bot Jul 26 09:34 konubinix konobi_: Actually, I think I did not configure my vpn network correctly to handle multicast konubinix Thanks for the clarifications that helped me understand the problem :-) konubinix I will try to play with the bootstrap to make the peer discover each other konobi_ blink oh yeah... that makes sense... keep forgetting the L2/L3 splits for vpn ```

I'll try to summarize what happened with them later. Just wanted to make sure it doesn't get lost in the history. :D