Yes. Yes it is possible. The network has to be able to handle all the packets (without exceptions - packet loss means death), the machines have to be able to send out packets fast enough, the other end must not have "flooding protection" and the address has to not change every time you open a new connection. This method managed to connect my laptop behind my University's WiFi with my friends laptop behind his WiFi and it sent a packet from my home WiFi through my University's symmetric NAT. If you're using a phone, you should probably send packets as fast as possible because phones are slow but with laptops you can synchronize the barrage of UDP packets with Thread.sleep()
/**
* Shoots empty UDP packets at every port between "start" and "end".
*/
public static void sendBarrage(int start, int end, InetAddress target) {
final ByteBuffer to_send = ByteBuffer.allocate(0);
// Start at a random value to avoid re-traversing failed paths on repeated attempts.
final int starting_point = start + generator.nextInt(end - start);
// Go from starting_point down to 1024.
for (int port = starting_point; port >= start; --port) {
try {
if (made_connection == false) {
myChannel.send(to_send, new InetSocketAddress(target, port));
} else {
break;
}
} catch (java.nio.channels.ClosedChannelException cce) {
Application.printerr("Channel closed while on port: " + port);
break;
} catch (IOException e) {
Application.printerr("Error sending in port: " + port);
continue;
}
}
// Go from 65535 down to say starting_point, not including starting_point.
for (int port = end - 1; port > starting_point; --port) {
try {
if (made_connection == false) {
myChannel.send(to_send, new InetSocketAddress(target, port));
} else {
break;
}
} catch (java.nio.channels.ClosedChannelException cce) {
Application.printerr("Channel closed while on port: " + port);
break;
} catch (IOException e) {
Application.printerr("Error sending in port: " + port);
continue;
}
}
}
^ Make sure you call this method in a loop, it might take a few attempts. Keep in mind that this method does NOT work with cell phone tower networks (unless you get insanely lucky and the public ip address does not change). It might work better if one side holds the port open while the other guesses rather than having them both brute force both sides.
Also, if only one side holds the ports open, this method might be good: https://www.goto.info.waseda.ac.jp/~wei/file/wei-apan-v10.pdf
One of my buddies is saying that TCP will be a problem for this gateway because it is going to establish a new connection for every message it sends (not kafka but the underlying transportation protocol itself is the issue), requiring a new port each time. At the rate we'll be sending these clients messages (gigabytes), kafka will run out of ports to read from??
Your friend is badly confused. TCP is a stream-oriented protocol. It has no notion of messages. Of course, it does use packets at the IP layer, but to the application this is an implementation detail. TCP inserts packet boundaries where it makes sense to do so, and not necessarily once per write()
or send()
. Similarly, it combines successive packets together if you receive more than one between calls to read()
or recv()
.
Needless to say, this stream-oriented design would be completely unworkable if every send established a new connection. So, the only way to establish a new connection is to close and reopen the connection manually.
(In practice, most protocols built on top of TCP have something which resembles messages, such as HTTP requests and responses. But TCP does not know or care about the structures of such things.)
It is possible that your friend was thinking of UDP, which does have messages, but is also connectionless. Most socket implementations allow you to "connect" a UDP socket to a remote host, but this is just a convenient way to avoid having to repeatedly specify the IP address and port. It does not actually do anything at the networking level. Nevertheless, you can manually keep track of which peers you are talking to under UDP. But if you do that, then deciding what counts as a "connection" is your problem, not the OS's. If you want to re-establish a "connection" on every message, you could do that. It probably isn't a very good idea, however.
Best Answer
There are basically two options this could be handled by NAT.
First, the NAT implementation can use an Application Level Gateway for
RTP
. In this case it will create a new entry in the NAPT mappings. In that mapping the client-facing port should be the one signaled, the server-facing port can be random. After the new mapping has been created, the ALG overwrites the port and ip in the RTP message with the server-facing data of that new mapping. This is transparent for clients, but NAT implementations need to keep up with the protocols.Secondly, if supported by the NAT gateway, a client could use a protocol to learn it's server-facing ip and to allocate a port before signaling
RTP
. Most common protocols to do this arePCP
andUPnP
. This needs work/added complexity on the client side but is more generic as only the client needs to update it's protocol implementation and can use this for other protocols as well.