Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Oct 2008 10:03:45 -0700
From:      Jeremy Chadwick <koitsu@FreeBSD.org>
To:        Lowell Gilbert <freebsd-questions-local@be-well.ilk.org>
Cc:        Jack Barnett <jackbarnett@gmail.com>, Freebsd questions <freebsd-questions@freebsd.org>, mdh_lists@yahoo.com
Subject:   Re: Firewalls in FreeBSD?
Message-ID:  <20081031170345.GA36712@icarus.home.lan>
In-Reply-To: <444p2sd8od.fsf@be-well.ilk.org>
References:  <367168.61424.qm@web56806.mail.re3.yahoo.com> <490A4487.8020101@gmail.com> <20081030233933.GB16747@icarus.home.lan> <448ws4da2f.fsf@be-well.ilk.org> <20081031160949.GA36045@icarus.home.lan> <444p2sd8od.fsf@be-well.ilk.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Oct 31, 2008 at 12:35:30PM -0400, Lowell Gilbert wrote:
> Jeremy Chadwick <koitsu@FreeBSD.org> writes:
> 
> > On Fri, Oct 31, 2008 at 12:05:28PM -0400, Lowell Gilbert wrote:
> >> Jeremy Chadwick <koitsu@FreeBSD.org> writes:
> >> 
> >> > On Thu, Oct 30, 2008 at 06:34:31PM -0500, Jack Barnett wrote:
> >> >>
> >> >> Ok, I had some progress with this last night. Basically what I do is:
> >> >>
> >> >> in natd - redirect_port 1000 to 10000 to the internal windows box.
> >> >> set ipfw to "open" file wall.
> >> >>
> >> >> Obviously this isn't prefect - but gives some idea of what's going on.
> >> >>
> >> >> What I'd like to do, is a) keep the nat redirects since that works  
> >> >> pretty well.
> >> >> b) in ipfw, ONLY allow data back on these ports IF the windows box has  
> >> >> established the connection out first then deny everything else.
> >> >
> >> > This is called "port triggering" in the residential router world.  I
> >> > don't know how to do this on FreeBSD.
> >> 
> >> Stateful rules are the only way to do it.
> >> In fact, this is the main purpose of stateful rules.
> >
> > Read this part of the thread, where I outline protocol flow (based on
> > what the OP has stated about the protocol, which so far appears to be
> > accurate):
> >
> > http://lists.freebsd.org/pipermail/freebsd-questions/2008-October/thread.html
> >
> > Stateful rules will not solve this problem.
> >
> > The OP wants a feature that tells ipfw or pf "after the TCP handshake
> > has completed, dynamically add a port forward for port X on interface Y
> > to machine A on port Z; when the TCP session is FIN'd cleanly, or
> > extinguishes, dynamically remove that port forward".
> 
> Okay, I guess I'm a little confused by the line about "ONLY allow data
> back on these ports IF the windows box has established the connection
> out first then deny everything else."  I read that as saying that the
> Windows box had sent a packet on the same connection (4-tuple, at
> least) that should be later accepted heading *to* the Windows box.
> That's just a stateful rule, and it seems to be at odds with what you
> wrote in your first message in the thread.  The apparent disagreement
> was why I said anything in the first place; it sounds like there's
> more than one model of how the game works.

I understand the confusion.  Here's the actual protocol that the game
appears to be using (since the OP has stated forwarding a port range to
his LAN PC solves the problem -- meaning, his original description of
how the game protocol worked is accurate):

windows    = 192.168.x.x machine on the LAN
natgwlan   = private LAN-facing IP of FreeBSD box (e.g. gateway IP)
natgwwan   = public Internet-facing IP of FreeBSD box
gameserver = game server (public Internet IP)

*         = randomly-allocated port number
gameport  = some static port # for the game (OP hasn't disclosed this)
range     = some specific range of port numbers (OP says 1000-10000)

This is what would happen if the windows machine was on the Internet
directly (no NAT, no firewall):

Step 1)  windows:*     -->  gameserver:gameport
Step 2)  gameserver:*  -->  windows:range

Note that the randomly-allocated port number is *not* identical
between all of the above steps; literally each is a new port and
unrelated to the previous -- hence why state tracking won't work.

Now with NAT in the way, this is what happens for Step 1:

windows:*  <-->  natgwlan
                 natgwwan:*  <--> gameserver:gameport

Once the TCP handshake is completed for Step 1, the following happens
as a result of Step 2 -- again, note this is a *brand new connection*
being initiated from the gameserver:

gameserver:*  <-->  natgwwan:range

The problem is that these are all brand new connections being initiated,
and there's no way to cross-reference them, which is why state tracking
won't work to solve the OPs problem.

The "port triggering" method I described above, commonly available
on residential routers, is configured so that once the TCP handshake
is completed in Step 1, the router/natgw *immediately* adds a port
forward and firewall allow/pass rule (you have to configure it to
say what port range to forward, and what LAN IP to forward the packets
to).

Thus, the following would happen immediately after the TCP handshake was
completed in Step 1:

- natgw adds a firewall pass rule for natgwwan:range
- natgw adds a forwarding rule for natgwwan:1000 --> windows, where
  the port number matches (e.g. natgwwan:1000 --> windows:1000)

This pass/allow rule and the forward remains intact until the "port
triggered" connection is severed (FIN or expired).  It does not
expire/close based upon the connection made in Step 1.

This would allow Step to work, and would look like this with NAT
in the way:

gameserver:*  <-->  natgwwan:range
                    natgwlan       --> windows:range

This is as verbose as I can get, and based upon the forwarding and the
firewall rules the OP added, this does appear to be the protocol the
game uses.  And yes, this is a *horrible* protocol, completely NAT-
unfriendly.

The only part that confuses me is how the gameserver knows what port
number (e.g. "range") to connect to on natgwwan; I assume this port
number is somehow negotiated during Step 1, so that gameserver knows
to connect to windows:1000, windows:1578, windows:9739, etc.... you
get the point.

-- 
| Jeremy Chadwick                                jdc at parodius.com |
| Parodius Networking                       http://www.parodius.com/ |
| UNIX Systems Administrator                  Mountain View, CA, USA |
| Making life hard for others since 1977.              PGP: 4BD6C0CB |




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20081031170345.GA36712>