
In response to a Slashdot article about the problems of making TCP/IP connections between two hosts behind different NATs, I posted this scheme. Nobody replied to my post, though I got a couple of responses via e-mail telling me they thought it was a neat idea.
Anyway, this is a technique for using the simultaneous SYN exchange method of bringing up a TCP/IP connection to make connections between two hosts behind different NATs using a broker. I'm curious what you all think of its chances of working.
TCP allows a connection to be established if both sides simultaneously send eachother a SYN packet. This method requires a little NAT cooperation, but only a little. Here's how it could work:
This requires cooperation between the sources and their NATs. Specifically, it requires these three things from a NAT:
There is one non-problem I expect people to bring up. There seems to be an apparent race condition in step 11. This isn't really a race condition because of requirement 2 for NATs. Basically, the two sources can SYN eachother all day, and it won't matter until both NATs have performed the step required by requirement 3, at which point it will appear to both sources as if the SYNs were simultaneous.
It's a hack, but I think it'd work.
I think if you can get the level of cooperation between the two NATs and the broker, it would work, but I think there's a security hole in here:In steps 9 and 10 (and requirement 3), you require that the Source machine allow the 'far' end of the tcp connection to change based on the arrival of a syn packet from another machine, without any apparent means for authenticating the two. Using the 'broker' machine to pass data back and forth transparently would work, but I'm not sure that's what you want.
All in and all, it's a neat idea, but I think that given the level of access/cooperation you' d have to have with your NAT arrangement in the first place that you might be better served setting up a port-forward from the NAT device's live ip to your internal ip for a specific, prearranged port (on both sides).
No, steps 9 and 10 and requirement 3 cause the NATs destination IP to change on the basis of a SYN packet coming from inside the NAT. Basically, the call sequence of the non-broker program looks like this:
s = socket(PF_INET, SOCK_STREAM, PF_UNSPEC); bind(s, 0.0.0.0, port); ret = connect(s, broker_ip, size); assert(ret != 0); other_ip = getOtherIPFromBroker(brokerfd); ret = connect(s, other_ip, size); assert(ret == 0);The second connect causes a different SYN to be sent out to other_ip from the same IP and port as the SYN to broker_ip was originally sent from. The requirements require that the NAT hold open the same outgoing port for the same source IP and port, like they do now for UDP, and change the destination IP based on where the SYN packets are being sent to.
The intenet is to allow peer-to-peer services to connect even if they're behind NATs. A cooperating broker is not inconcievable in these cases.
Blech, it's morning and I somehow glossed over the contents of steps 7 and 8. Whoops. So, yes, you're fine authentication-wise there. :)The pseudo-code for the call sequence helps, and it makes sense for what you're trying to accomplish. I'm trying to think of a better way to go about it, but it looks like my initial thoughts are that this is a fairly sensible way to do it.
The amount of to and fro traffic is going to make connections between distant nodes very expensive. It's better if you can mark the initial packet as NAT-preferred, and the reply to optionally contain the necessary information. This way latency is not much impinged by your changes.Why is latency an issue? HTTP 1.0 connections from where I live (Australia) to the less well connected portions of Europe can cause grief. ping times of over 700 ms or more are typical. For future space- based IP sessions, any thought of 8 light minutes per AU for each one of these steps is not going to work. Think about how you can remove the steps to the barest minimum, whilst still achieving your goal.
The problem really needs sorting out in the IPv6 world with AH packet authentication.
There are security reasons for forcing the use of a single IP address or a pool of addresses to appear for any number of internal hosts. This doesn't change by going to IPv6, and in fact, due to AH, IPv6 is actually a retrograde step for sites relying on information hiding.
You also need to deal with load balancing devices that work by ever so slightly breaking IP to redistribute load. They are unfortunately with us now, for the largest sites in the world cannot cope without them.
> The problem really needs sorting out in the IPv6 world with AH packet > authentication.NAT is in fact violating the RFCs, even in the current IPv4 world.
> There are security reasons for forcing the use of a single IP address > or a pool of addresses to appear for any number of internal hosts. > This doesn't change by going to IPv6, and in fact, due to AH, IPv6 is > actually a retrograde step for sites relying on information hiding.
There are better ways for this than using NAT. Remember, in an IPv6 world, you will have more IP adresses for one local net than the complete Internet has today. One possible way to hide your internal information would be to add and delete IP aliases for each connection. This way you could still use authenticated P2P connection with AH and still don't provide any valuable information to the outside (the IP adress won't work after the connection has been shut down).
--jochen
FOAF updates: Trust rankings are now exported, making the data available to other users and websites. An external FOAF URI has been added, allowing users to link to an additional FOAF file.
Keep up with the latest Advogato features by reading the Advogato status blog.
If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!