Vanilla List Maling List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [VANILLA-LIST:2246] Thread on UDP and firewalls from euroclue-l




I've modified the Bronco 2.9pl2 server to work with clients behind IPFILTER
based NAT firewalls.  This should work with Linux, FreeBSD, and NetBSD based
NAT firewalls as well as units like the Ascend Pipeline P50/P75s and Ciscos
with NAT enabled.  See the included patch for the code.

My test environment:

Client: Cow 3.00pl2 compiled with USE_PORTSWAP defined
Server: Bronco 2.9pl2 with modified socket.c (in the "ntserv" directory)

The details (hit your 'd' key now if you're not interested):

The idea is that the PORTSWAP mode of the netrek protocol has already done 90%
of the job here.  Since the server obviously isn't going to be able to
establish a server->client connection through a NAT firewall, we pass the
server UDP serverport number back to the client via the TCP channel.  The
client then opens a NAT connection to the server UDP port.  This was already
all in the Bronco code.

The problem is that the server immediately glues its UDP port to listen only
to the _internal_ UDP source port of the client, by using the connect() call.
The server knows about the client source port because this port is passed
through the TCP connection at UDP Comm mode request time.

My workaround is to use PORTSWAP to get the client to first contact the
server, causing a NAT table entry to be created.  The server, instead of
establishing connection parameters based on the source port that the client
tells it, waits for the first UDP packet to come in on the negotiated server
source UDP port, and then sets up the reply IP/port pair based on where the
client packet came from.  Once the server has figured out what the
NAT-translated port number is, it uses that as its UDP connection parameters
instead of using the (incorrect) port number that the client supplies.

Anyway this works for me.

IMPORTANT: This does NOT work with out-of-the-box COW binaries. PORTSWAP mode
seems to be a compile-time only option.  The easiest way to turn it on, is to
get the source, run configure, and then edit the config.h file to include the
line "#define USE_PORTSWAP".  Then proceed as usual with the build.

I think it would be cool if this could be integrated into the bronco source,
as I'm stuck behind a NAT based firewall and I'm sick of redirecting my netrek
client via SSH from an outside machine to an inside machine so that I can get
UDP connections.  :)

EJR



On Fri, 9 Apr 1999, Alec Habig wrote:

> Bob Campbell writes:
> > Honestly, UDP is good for use in LANs (primarily for NFS) but even
> > it's use within LANs is declining; it's no longer the default
> > connection under NFSv3 (TCP is).
> 
> Well, I don't know how much of this is a security issue and how much is
> just do to the rather fundamental design flaw of using a lossy protocol
> (UDP) for a process which is loss-intolerant (pretending to be a file
> system). 
> 
> I've seen some rather nasty corruptions from early NFS implementations
> which forgot about this.  This was later fixed, but by the time you code
> robustness into UDP, you might as well be using TCP in the first place.
> 
> On the other hand, UDP is perfect for online gaming - if one can accept
> or work around any security issues.
> 
> -- 
>        Alec Habig, Boston University Particle Astrophysics Group
> 			   habig@budoe.bu.edu
> 		       http://hep.bu.edu/~habig/
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: vanilla-list-unsubscribe@us.netrek.org
> For additional commands, e-mail: vanilla-list-help@us.netrek.org
> 

Openface Internet Inc.                                          Erik Rungi
Montreal, Canada                                        rungus@openface.ca
(514) 281-8585                                          Technical Director
Web Services, Software Development                            OpenFace INC

237a238,242
> static int portswapflags = 0;           /* some hackish flags;          */
>                                         /* 1 = portswap enabled         */
>                                         /* 2 = connect()ed yet (yes/no) */
>                                         /* 4 = are we proccessing UDP?  */
> 
366c371
<     if (connect(ns, &addr, sizeof(addr)) < 0) {
---
>     if (connect(ns, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
833a839
>             portswapflags |= 4;
856a863,865
>     struct sockaddr_in moo;
> 
>     int s;
861a871,889
>     /* read the source port of the first UDP packet that comes in, and
>        connect() to it -- PORTSWAP mode hack to work with NAT firewalls */
> 
>     if (portswapflags == 5) {
>         s = sizeof(moo);
>         UDPDIAG(("portswap hack entered\n"));
>         if (0 > recvfrom(asock, buf, BUFSIZ*2, MSG_PEEK,
>                          (struct sockaddr *)&moo, &s)) {
>             perror("recvfrom");
>         } else {
>             UDPDIAG(("client port is really %d\n", ntohs(moo.sin_port)));
>             portswapflags |= 2;
>             portswapflags &= ~4;
>             if (0 > connect(asock, (struct sockaddr *)&moo, sizeof(moo))) {
>                 perror("connect");
>             }
>         }
>     }
> 
884c912,913
< 		if (connect(udpSock, &addr, sizeof(addr)) < 0) {
---
> 		if (connect(udpSock, (struct sockaddr *)&addr, 
>                     sizeof(addr)) < 0) {
2068a2098,2101
> 
>             if (packet->connmode == CONNMODE_PORT) {
>                 portswapflags |= 1;
>             }
2137c2170
<     if (bind(udpSock, &addr, sizeof(addr)) < 0) {
---
>     if (bind(udpSock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
2158,2159c2191,2195
< 	    
<     if (connect(udpSock, &caddr, sizeof(caddr)) < 0)
---
>         
>     UDPDIAG(("UDP_FIX code enabled.  portswapflags = %d\n",portswapflags));
>     if (portswapflags & 1) { 
>         UDPDIAG(("portswap mode -- putting of connect() until later\n"));
>     } else if (connect(udpSock, (struct sockaddr *)&caddr, sizeof(caddr)) < 0)
2181c2217
<     if (getsockname(udpSock, &addr, &len) < 0) {
---
>     if (getsockname(udpSock, (struct sockaddr *)&addr, &len) < 0) {
2217c2253
<     if (getsockname(udpSock, &addr, &len) < 0) {
---
>     if (getsockname(udpSock, (struct sockaddr *)&addr, &len) < 0) {
2224c2260
<     if (getpeername(udpSock, &addr, &len) < 0) {
---
>     if (getpeername(udpSock, (struct sockaddr *)&addr, &len) < 0) {