Question that has dogged me for a while.

Julian Elischer julian at freebsd.org
Sat May 6 03:59:57 UTC 2017


On 6/5/17 7:53 am, Karl Denninger wrote:
> On 5/5/2017 14:33, Julian Elischer wrote:
>> On 5/5/17 1:48 am, Dr. Rolf Jansen wrote:
>>> Resolving this with ipfw/NAT may easily become quite complicated, if
>>> not impossible if you want to run a stateful nat'ting firewall, which
>>> is usually the better choice.
>>>
>>> IMHO a DNS based solution is much more effective.
>>>
>>> On my gateway I have running the caching DNS resolver Unbound. Now
>>> let's assume, the second level domain name in question is
>>> example.com, and your web server would be accessed by
>>> www.example.com, while other services, e.g. mail are served from
>>> other sites on the internet.
>> I believe this is a much cleaner solution thanusing double NAT.
>> (see also my solution for if the server is also freebsd)
>> even though we have a nice set of new IPFW capabilities that can do
>> this, I still think double nat is an over complication of the system.
>>
> Well, the DNS answer is one that works IF you control the zone in
> question every time.  I'm loathe to stick "illegal" (e.g. bad IP number)
> packets on a network in any event, so while yeah, that'll work I'd
> rather not.

Interestingly the "bad" IP packets are no different than the packets 
you are  seeing on the network anyhow (with nat).
You just deliver them to a different place.
Effectively you are turning on the transparent proxy support in the 
kernel and making the gateway a transparent proxy for your clients. 
(but only for your own server)

for example  if your client is 192.168.0.2
and your server is 192.168.0.3 and your external address is 8.8.8.9,

Then what you are asking for is a way that your client can make a 
session where the remote address is 8.8.8.9 and the local address is 
192.168.0.2.
You are going to generate these packets no matter what you do because 
they are what you asked to do even if you are NATing.

The packets when bounced to the server STILL look like 
src=192.169.0.2, dest=8.8.8.9 and the server(FreeBSD or Linux with TP 
support only) will consume them as such.
The server will produce a packet that looks like src=8.8.8.9, 
dest=192.168.0.2.    These packets look exactly like the packets that 
would be returning from the NAT to the client had you used nat.

so, overall, you are not introducing any packets onto your network 
that wouldn't have been there anyhow.
They look exactly like the traffic would look between the NAT and the 
client.
The difference is that it is way more efficient, because the return 
packets take no processing at all.

The advantage of setting up a DNS (mostly) forwarding proxy is that 
what is happening is absolutely visible on the wire.
Nothing is pretending to be anything it is not.

The nat option on the other hand.
  (don't get me wrong, I am sure it would work given enough work) is 
that it just has more moving parts and will make it more complicated 
to get your firewall correct in other cases.
I like ipfw and it's nat, it's just more complicated in some cases.

> The "set up a fake forward" zone thing works too, but it shouldn't have to.
>
> This /should /work on a generalized basis but doesn't (ue1 is on the
> public address 70.169.168.7, ue0 on private address 192.168.10.200, the
> host being "twisted to/hole punched" is on 192.168.10.100:
>
> # Set up the NAT configuration
> #
>          ${fwcmd} nat 100 config if ue1 log same_ports reset
> redirect_port tcp 192.168.10.100:2552 2552
>          ${fwcmd} nat 200 config ip 192.168.10.200 log same_ports reset


shouldn't one of these be declared to be a reverse nat?

>
> ....
> 06000    0       0 nat 200 ip4 from 192.168.0.0/16 2552 to 192.168.10.200
> 06010 1521  726601 nat 100 ip4 from any to me recv ue1
> 07000    0       0 check-state :default
>
> 08000    6     312 nat 200 ip4 from 192.168.0.0/16 to 70.169.168.7
> 08001    0       0 count log ip4 from 192.168.10.200 to any dst-port 2552
> 08002 2125 2408339 nat 100 ip4 from 192.168.0.0/16 to any xmit ue1
> 08009    0       0 deny log ip4 from 192.168.0.0/16 to any xmit ue1
>
> A "telnet 70.169.168.7 2552" from outside works perfectly well.  But the
> second NAT should cause a "telnet 70.169.168.7 2552" from an
> internet-network host to work also.  It doesn't.
>
> 8000 gets the packet (a telnet attempt from inside to port 2552) and
> allegedly is supposed to NAT it.  It does not.  The following rule,
> which is where execution should continue after it NATs it, should match
> but no packet ever comes back into the stack -- nor does it show up on
> the wire (tcpdump fails to show it.)  I have verbose logging on in
> sysctl and none of the deny lines in the remainder of the ipfw config
> file trap it either.
>
> The *other* NAT instance on the same box (to translate other things on
> the same network out to the Internet at large and perform the hole
> punch) works perfectly well.
>
> This looks like a bug in the code -- unless there's a requirement that a
> packet in the kernel is marked to be enqueued for emission on an actual
> physical interface before it will translate (e.g. a "forward" NAT has to
> be associated with an "xmit ...." clause in order to work) in which case
> it's impossible to make in-kernel NAT work for the "double twist" case
> since the packet never leaves the box until it goes through the
> hole-punch in the first NAT statement (which it *should* do in 8002,
> right?)
>
> Is that a bug (ought to PR it), a "feature" (e.g. design choice and thus
> "working as intended") or do I (still) have it configured incorrectly?
>



More information about the freebsd-ipfw mailing list