-
Notifications
You must be signed in to change notification settings - Fork 6
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
TCP support #1
Comments
Is your application a custom STUN server that only uses TCP? Or do you need to forward STUN requests over some TCP-only channel? |
Dealing with TCP = dealing with short reads and properly accumulating incoming chunks until full STUN message gets buffered. So this change would definitely be more complicated than just swapping the socket type. |
I need it because the underlying protocol that I want to speak once the connection is set up is TCP-only.
No, I just need to get some public IP for a socket. We have some kind-of self-made TURN server for TCP connections but I don't think that is relevant to this issue.
As you said, that code can probably all go away :) |
If TCP connection would be established to STUN server then it cannot be redirected elsewhere. And if just create new TCP connection from the same source port, would typical a NAT preserve it's external source port or consider it a new, unrelated allocation? If closing the socket, then opening another with the same local port works, then API should be designed to aid it (either doing close&reopen itself or exposing just the port number). Also, if this is TCP hole punching, I'm not sure how one would both connect from a local TCP port and simultaneously accept incoming connections to the same TCP port using portable APIs. |
If you're interested in the gory details of my endeavor, I recommend reading https://bford.info/pub/net/p2pnat/. At the moment, I am prototyping an implementation of the algorithm presented in that paper (albeit with a few small variations). |
I gave it a try and the basic code is ridiculously simple: let bytes = get_binding_request()?;
let server_addr = "stun.stunprotocol.org:3478".to_socket_addrs().unwrap().find(|x|x.is_ipv6()).unwrap();
let mut socket = std::net::TcpStream::connect(server_addr)?;
socket.write_all(&bytes[..])?;
let mut buf = [0u8; 256];
let len = socket.read(&mut buf[..])?;
let buf = &buf[0..len];
let external_addr = decode_address(buf); Of course this doesn't account for async and socket reuse and all that stuff. Also note that the default google server does not appear to host a STUN/TCP service. |
What if for some reason the first |
I also asked this myself and I honestly don't know. STUN probably has some framing mechanism that I don't know of. I just read https://datatracker.ietf.org/doc/html/rfc5389#section-7.2.2 and it says that unless the STUN is mixed into some other protocol, no additional framing is needed [compared to UDP]. |
Even if STUN server itself won't (deliberately) fragment packet, networking equipment may. I expect this simple scheme to work in wast majority of cases, but there will always be lurking some chance that in some ugly network it would break down. It's like undefined behaviour that "always just works in practice". |
Isn't IPv6 supposed to be a Better World where addresses don't need to be mapped, and one can just query socket address and assume it's the external, globally routable address? |
Yeah, I was just doing some experiments and forgot to change it back. We definitely won't NAT66, but in the case some people do this regardless STUN/IPv6 got us covered. [Off-topic] Speaking of which, you shouldn't bind to I found the appropriate section: https://datatracker.ietf.org/doc/html/rfc5389#section-6. Maybe |
How would that apply to UDP? The only thing that comes to mind is validating that UDP packet does not contain extra trailing bytes. |
Wouldn't it break support of system where |
As far as I can tell from the RFC (disclaimer: I maybe read at most 20% by now), it doesn't specify a mapping from messages to UDP packets. Thus, they could be fragmented as well. In that case, the safest way to read would be to always check the header and then wait for additional packets if necessary until the required length has been reached.
Yeah, probably. Do I care about people deliberately not supporting IPv6 on machines they control? Nope |
UDP packets may be reordered and selectively dropped, so it is generally impossible to recover UDP message from headerless chunks. |
This crate is great, but my application requires to use TCP instead :(
If I understand the RFC correctly, one should be able to swap out the UDP socket (and respective connection logic) with a TCP socket and the rest of the could could still be the same.
The text was updated successfully, but these errors were encountered: