begin quoting Andrew Lentvorski as of Tue, Mar 28, 2006 at 04:40:30PM -0800: [snip] > I think part of the issue is that no one is explaining the issue > correctly. SIP isn't the problem. > > SIP is just one of many protocols that really want to be able to connect > to "peers" in a client(ephemeral port)-client(ephemeral port) > arrangement rather than a client(ephemeral port)-server(static port) > arrangement.
Yes. The ephermeral-ephermeral connection is what's a violation of good policy, and a default-deny firewall will break those protocols just as hard as a NAT device. > Normally, I don't like to be quite this definitive, but, as someone who > has been playing quite a bit lately with punching through NAT devices, > you are just *wrong* about there being a reliable solution to this problem. I think we're looking at different problems. I don't _want_ a program to spin up a server socket on an ephermeral port for anything other than local-network access; if I want that service to be accessible from the 'Net, I want to grant that permission explicitly. > There is no reliable way from an application programming perspective to > reliably get two machines behind NAT devices to talk TCP to one another > on ephemeral ports. Even if both people *want* to. Even UDP is often > questionable. > > If there is, *please* let me know how. I've got 2K lines of nasty code > that I would *love* to throw away. It's a matter of broken software. If you have an application that wants to open a server socket, that application _ought_ to be able to have the port to use settable by the user. Once the user can say "Run your server socket on port XYZ", most of the problems go away. All the NAT devices I've seen let you configure 'em to poke an incoming port through to an internal machine, which is all you really need by that time. > Even the big boys haven't solved this problem and they have a *huge* > incentive with things like Xbox Live, Evercrack, World of Warcrack, etc. Even clever people can miss the obvious solutions. > Fortunately, most of the modern NAT devices are starting to do cone-type > translations. That still doesn't help TCP much (since you have to work > really hard to get to the SO_REUSEPORT flag), but at least UDP works > okay then. Bleah. > >What's wrong with passing port and IP numbers? > > There is no way to autodiscover which ports are actually being used. > Multiple hosts behind the same NAT often want to use the same ports. And those programmers want to hard-code those ports, too. :( > There is a reason why practically every TCP service uses ephemeral ports > on *outbound* connections. Are you saying that ephermeral ports should > be abandoned? If so, you disagree with the wisdom of decades of TCP > network programmers. Outgoing connections are fine. A TCP/UDP connection is defined by a five-tuple; I can give fifteen connections from machine A to the same port on machine B, with no confusion about which packets go where. > >>point the two end points have to know how to get ahold of each other. I > > > >Yes. And that's a matter of policy. It should be UNDER THE CONTROL OF > >THE USER. > > Why? You, yourself, often point out that almost everything that winds > up under the control of the end user becomes a security hole. Heh. I should say instead, the OWNER. Even so, it's the user who bears the risk, so it's the user who should have the control. Users may be a security hole, but a worse one is the separation of risk and power. When the one taking the risk isn't the one making the decisions, you tend to get really crappy security. The user is the biggest security hole... but it's also /their/ hardware. Their network. Their data. Their ass. Taking power *away* from the user is just wrong; they're the ones who'll suffer, therefore, they're the ones who need to make the decisions. IT departments that are handed the responsibility for security, but aren't allowed to set the security policy ... well, they soon devolve into a corporate hell. (Likewise, IT departments that get to set policy but aren't responsible for problems tend to become arrogant and oppressive.) (Have I really opined that everything under the control of the user is a security hole, as opposed to the user's actions being the biggest security hole?) > Many users find NAT to be so annoying that they just give complete > control of the NAT to anyone via UPnP. Are you suggesting that is a > good solution? That is what your position tends to lead to. Oh, hell no, that's not a good solution. However, that's not the only solution my position tends to... it's a metastable state, after all. The solution that I _want_ it to go to is that applications let the user _set_ the port, and NAT devices make it easy for the owner to tunnel connections through to the appropriate machine. The solution I _don't_ want is applications demanding default-allow firewall policies in order to work, or hardcoded connections, or tunnelling everything over a single port. Default-allow is bad; hardcoding is stupid; and tunnelling will require intelligent proxies, which are going to be complicated and error-prone. > If, however, there was a useful traversal protocol where I could at > least *request* a consistent routing and either be permitted or denied, > this mess would go away and security would improve. Upon denial, I > would quit trying to "penetrate" the NAT and flag to the user that he > was specifically *denied* by the NAT/firewall instead of wondering > whether it was just a crap firewall. Let the user specify the port to listen on (with a reasonable default). If they want to let people through, they'll do the same thing they'd do with a default-deny firewall -- poke a hole for that port. The only difference would be that the users would have to choose distinct ports, for each machine. > In fact, if I could request my external mapping, I could even cope with > "symmetric" NATs rather than just cone NATs. This would actually > improve security. I'd like to have the OS let me constrain the ports used for epheremal ports on a per-machine/per-program/per-process level, too, which would be useful in conjunction with NATs, and help avoid port-translation too. [snip] > Given that a whole lot of very smart people have taken a crack at this > problem and failed to solve it, your dismissal is a bit flippant. I'd Heh. I'm working on a different set of assumptions. I don't like ephermeral server ports. I think the software is broke when it doesn't use a port-aware protocol, and when it doesn't let the user set the (server) ports to use. [snip] > >It is. The VOIP protocols that are broken by NAT are _broken_. > > Sorry. You are wrong. I challenge you to create a VoIP protocol that > can directly connect two people behind symmetric NAT boxes (new external > port:IP for every external IP:external port: internal IP: internal port > quad). I'll even let you use a single colocated server as a rendezvous > host, but not to proxy all the traffic. > > I await your solution. TCP/UDP connections are specified by a 5-tuple: source address source port protocol destination address destination port If we fix the destination port, we can then configure the NAT box to forward connections to <external address> to the <internal address> at the specified port. We can have the user specify the external hostname, or we can sniff it from the registration connection. The protocol sends the port it is running on to the remote server (rendezvous host, if you like). Outgoing connections use an ephermeral port, 'cuz we don't care what it is, so long as it's sufficient to distinguish the connection. You can have two users using NAT, and they can both connect to each other. Let's say we have user1 and user2 on network 192.168.x.x, with a NAT box with an external address of 12.34.56.78, and we have userA and userB on network 10.10.10.x, using a NAT box with an external address of 9.87.65.43. user1 runs his app, and configures it to use port 4000. user1 contacts his admin and requests a NAT tunnel through to port 4000. (Admin does this.) user2 runs his app, and configures it to use port 4000. user2 contacts his admin and requests a NAT tunnel through to port 4000. (Admin responds with a 'denied, use 4001 instead') user2 reconfigures his app to use port 4001. userA runs his app, configures it to use port 5000. userA logs in to the NAT box and connects incoming port 5000 to his machine. userB runs his app, and configures it to use port 3500. userB logs in to the NAT box and adds a separate connection etc. etc. If you don't want the users to have to know their "external" domain names or IPs, you can use the rendezvous server idea. When user1 contacts userA, and user2 contacts userB, they're connecting to different destination ports. No conflict. When user2 hangs up and talks to userA, the protocol, destination address, destination port, and source address are all the same, but the ephermeral port is different (and if not, the NAT box should either translate it or abort the connection, and a new ephermeral outgoing port would be used). Still, no confict. Everyone can talk to everyone else, at the cost of maybe some retry logic if an outgoing connection is rejected. The outgoing ephermeral port is sufficient to distinguish the session; the fixed incoming port is sufficient to direct the session to the right machine (and to allow limited access through the firewall, rather than having to engage in a default-allow policy). Only two downsides: (a) no ephermeral server ports on the 'Net, and (b) user-selectable server ports. But I see those as an application issue, and a _good_ thing. -- _ |\_ \| -- [email protected] http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-list
