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

Why so complicated? #9

Open
piegamesde opened this issue Sep 10, 2021 · 5 comments
Open

Why so complicated? #9

piegamesde opened this issue Sep 10, 2021 · 5 comments

Comments

@piegamesde
Copy link

I tried implementing this and only got a lot of really frustrating errors (the accept call tends to hang up indefinitely). But I tried a simpler method which does seem to work:

  1. Bind a port (with SO_REUSEADDR)
  2. Find out the IP addresses and exchange them over an external channel
  3. Connect to the peer with the bound socket. If there is more than one IP address to contact, bind a new socket on the same port and connect from there.

You can easily reproduce this with two nc commands. There are no listen and accept calls, making thins a lot easier. The first connect may fail on a firewall, but it will try again and once the peer has sent their first message the packets will go through. It doesn't matter that there is no accept call, if both sides connect to each other it works nevertheless. The usual caveats apply: both sides need to synchronize temporally with the precision of one timeout. If any firewall sends RST packets, it's game over (this holds especially true on loopback connections on the same machine).

My question is: did you try this approach, what do you think of it and how does it compare to the one implemented here? Is there something big that I'm missing (I didn't test with NATs yet for example, but there's no reason it shouldn't work).

@Periodic1911
Copy link

Could you add the nc commands you are using? That way we can try your proposal.

@piegamesde
Copy link
Author

I think it was as simple as a well-timed nc -p 12345 $PEER_IP 12345 on both sides. We then looked at the strace to see that only bind and connect were called.

@piegamesde
Copy link
Author

Well, I found an issue with my approach: it doesn't work on devices without firewalls: The packets will be let through to the kernel, which will notice that no one is listening on that port and then send an RST packet. This is nothing that can't be worked around, but it certainly is annoying.

@piegamesde
Copy link
Author

I've now combined the approach with a naive listen/accept on a different port. It now requires twice as many connection attempts, but at least it works at all settings. It would be great to have the listener socket on the same port as the connect sockets, but I did not manage to get this to work at all.

@ValdikSS
Copy link

Well, I found an issue with my approach: it doesn't work on devices without firewalls: The packets will be let through to the kernel, which will notice that no one is listening on that port and then send an RST packet. This is nothing that can't be worked around, but it certainly is annoying.

setsockopt(SOL_IP, IP_TTL, ttlvalue) works on Linux for the regular user and could be changed mid-connection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants