Question that has dogged me for a while.

Julian Elischer julian at freebsd.org
Fri May 5 19:27:21 UTC 2017


On 5/5/17 2:06 am, Karl Denninger wrote:
> On 5/4/2017 12:12, Rodney W. Grimes wrote:
>>> Consider the following network configuration.
>>>
>>>
>>> Internet ------- Gateway/Firewall ---------- Inside network (including a
>>> web host)
>>>              70.16.10.1/28     192.168.0.0/24
>>>
>>> The address of the outside is FICTIONAL, by the way.
>>>
>>> For policy reasons I do NOT want the gateway machine to actually have
>>> the host on it.  There may be a number of things running on there but
>>> for the instant moment let's assume a standard pedestrian web host on
>>> port 80.
>>>
>>> I have DNS pointing at "webhost.domain" @ 70.16.10.1.
>>>
>>> I have NAT on the gateway (NAT internal to the kernel), and a "hole
>>> punch" in there with redirect_port tcp 192.168.1.1:80 70.16.10.1:80 as
>>> pat of the nat configuration statement.
>>>
>>> This works fine for anyone on the outside.  HOWEVER, anyone on the
>>> INTERNAL network cannot see the host.
>>>
>>> My NAT configuration looks like this:
>>>
>>> #
>>> # Now divert all inbound packets that should go through NAT. Since this
>>> is NAT
>>> # it can only match a packet that previously was NATted on the way out.
>>> #
>>>          ${fwcmd} add 6000 nat 100 ip4 from any to me recv ${oif}
>>> #
>>> # Check stateful rules; we want to go there directly if there is a match
>>> #
>>>          ${fwcmd} add 7000 check-state
>>> #
>>> # Now pick up all *outbound* packets that originated from an inside address
>>> # and put them through NAT.  We then have
>>> # a packet with a local source address and we can allow it to be sent.
>>> # Therefore, if the packet is outbound let it pass and be done with it.
>>> #
>>>          ${fwcmd} add 8000 nat 100 ip4 from 192.168.0.0/16 to any xmit ${oif}
>>>>>     ${fwcmd} add 8001 nat 100 ip4 from 192.168.0.0/16 to ${oip}
>>>          ${fwcmd} add 8009 deny log ip4 from 192.168.0.0/16 to any xmit
>>> ${oif}
>>>          ${fwcmd} add 8010 pass ip4 from ${onet} to any xmit ${oif}
>>>
>>> Without the ">>" line I get nothing; the packets get to the gateway and
>>> disappear.
>>>
>>> With the ">>" line I DO get the packets re-emitted on the internal
>>> interface HOWEVER there is no translation to the internal interface IP
>>> on the gateway box.  So what I see on the internal box is this:
>>>
>>> 11:19:16.369634 IP 192.168.10.40.60924 > 192.168.10.100.11443: Flags
>>> [S], seq 292171178, win 8192, options [mss 1460,nop,wscale
>>> 8,nop,nop,sackOK], length 0
>>> 11:19:16.369662 IP 192.168.10.100.11443 > 192.168.10.40.60924: Flags
>>> [S.], seq 3088872007, ack 292171179, win 65535, options [mss
>>> 1460,nop,wscale 6,sackOK,eol], length 0
>>>
>>> Which won't work because the internal box got and sent this:
>> What is the NAT command running at instance 100?
>> Does it have an -alias_address of inside IP of router?
>> Are you tryint to use the same Nat instance to do both
>> the global internet acess translation and this special
>> inside loop back translation?  If so that usually can
>> not be made to work.
> Aha.  That's probably the problem -- I need a second instance.
>
> Here's the entire salient section:
>
>
> # Set up the NAT configuration; there are multiple entries that have to
> be here
> # because we redirect a bunch of ports around so we can see things from the
> # outside -- specifically, webcams and the HomeDaemon server.
> #
>          ${fwcmd} nat 100 config ip ${oip} log same_ports reset
> redirect_port tcp.... (whole bunch of stuff)
>
> #
> # Stop spoofing
> #
>          ${fwcmd} add 2010 deny log all from ${inet} to any not ipsec in
> via ${oif}
>          ${fwcmd} add 2020 deny log all from ${onet} to any in via ${iif}
>          if [ -n "$inet6" ]; then
>                  ${fwcmd} add 2040 deny all from ${inet6} to any in via
> ${oif6}
>                  if [ -n "$onet6" ]; then
>                          ${fwcmd} add 2050 deny log all from ${onet6} to
> any in \
>                              via ${iif6}
>                  fi
>          fi
>
>          ${fwcmd} add 3000 deny log all from ${onet} to any recv ${iif}
>
> #
> # This table is a list of denied addresses that tried to attack us.  Updated
> # by sshguard.  Anything coming inbound from the outside is blocked.  We
> also
> # block anything on the "screw you" lists (two)
> #
>          ${fwcmd} add 4000 deny log all from table\(22\) to any recv ${oif}
>          ${fwcmd} add 4010 deny all from any to ${foscam}
>          ${fwcmd} add 4020 deny log all from ${china} to any via ${oif}
> #
> # Anything related to RFC1918 or the Manning range that comes in on
> # the external interface (shouldn't happen) gets tossed immediately, EXCEPT
> # for RFC1918 stuff coming in via IPSEC.  That we must pass or our IPSEC
> # gateway will not work.
> #
>          ${fwcmd} add 5000 deny log all from ${rfc1918} to any not ipsec
> recv ${oif}
>          ${fwcmd} add 5010 deny log all from ${manning} to any recv ${oif}
>
> #
> # Now divert all inbound packets that should go through NAT. Since this
> is NAT
> # it can only match a packet that previously was NATted on the way out.
> #
>          ${fwcmd} add 6000 nat 100 ip4 from any to me recv ${oif}
> #
> # Check stateful rules; we want to go there directly if there is a match
> #
>          ${fwcmd} add 7000 check-state
> #
> # Now pick up all *outbound* packets that originated from an inside address
> # (including IPSEC tunneled stuff) and put them through NAT.  We $then have
> # a packet with a local source address and we can allow it to be sent.
> # Therefore, if the packet is outbound let it pass and be done with it.
> #
>          ${fwcmd} add 8000 nat 100 ip4 from 192.168.0.0/16 to any xmit ${oif}
>          ${fwcmd} add 8001 nat 100 ip4 from 192.168.0.0/16 to ${oip}
>          ${fwcmd} add 8009 deny log ip4 from 192.168.0.0/16 to any xmit
> ${oif}
>          ${fwcmd} add 8010 pass ip4 from ${onet} to any xmit ${oif}
>
>  From the above I assume I need to direct 8001 through a nat 200, and
> define that as "twist anything that comes through there to be aliased
> from the INTERNAL IP address", yes?
>
> So I changed the above to be this:
>        
>         ${fwcmd} add 8000 nat 200 ip4 from 192.168.0.0/16 to ${oip}
>         ${fwcmd} add 8001 nat 100 ip4 from 192.168.0.0/16 to any xmit ${oif}
>
> So the first one would catch any inside packet that was headed to the
> outside IP before the other gets ahold of it.
>
> And added:
>
>      ipfw nat 200 config ip ${iip} same_ports reset
>
> Up above for the second NAT channel; "iip" is the gateway's internal IP
> address.
>
> But that winds up doing nothing; I get no packets back out on the inside
> interface at all (just as if the "200" nat stuff was not there at all)
>
>
>
>>> 11:19:16.369337 IP 192.168.10.40.60924 > 70.169.168.7.11443: Flags [S],
>>> seq 292171178, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK],
>>> length 0
>>> 11:19:16.369433 IP 192.168.10.40.60925 > 70.169.168.7.11443: Flags [S],
>>> seq 2666765817, win 8192, options [mss 1460,nop,wscale
>>> 8,nop,nop,sackOK], length 0
>>>>> 11:19:16.369502 IP 192.168.10.40.60924 > 192.168.10.100.11443: Flags
>>> [S], seq 292171178, win 8192, options [mss 1460,nop,wscale
>>> 8,nop,nop,sackOK], length 0
>>>>> 11:19:16.369511 IP 192.168.10.40.60925 > 192.168.10.100.11443: Flags
>>> [S], seq 2666765817, win 8192, options [mss 1460,nop,wscale
>>> 8,nop,nop,sackOK], length 0
>>>
>>> But since the gateway emitted the packet back on the wire *without*
>>> remapping the source address (to itself) it doesn't match on the client
>>> box 'cause there's no way back for it.
>> Yep.
>>
>>> There has to be a solution to this somewhere and I'm obviously missing
>>> it..... :)
>>>
>>> -- 
>>> Karl Denninger
>>> karl at denninger.net <mailto:karl at denninger.net>
>>> /The Market Ticker/
>>> /[S/MIME encrypted email preferred]/
>> This is the classical "Loopback Nat Problem" of accessing machines
>> behind a NAT device that does not do the proper NATTing and
>> routing of these packets.   Many small consumer routers got this
>> wrong for years, just like most ipfw code I have seen.
>>
>> Most of the consumber devices have been fixed.  The trickery is
>> you need to NAT packets coming from the inside destined for the
>> outside IP into the internal IP.  That internal box MUST route
>> back via the NAT device, so the NATTED addresses for these
>> packets must be the inside IP of the router.
>>
>> Your code looks to get this mostly right, but I think you have
>> missed something someplace.  I dont use kernel nat, and it looks
>> like you do so you well have to adjust these a little.
>>
>> inside_ip_router="192.168.10.40"
>> outside_ip_router="70.16.10.1"
>> inside_ip_webserver="192.168.10.100"
>>
>> #natd-vmxZ.conf should just be an empty file for this type of nat
>> /sbin/natd -f /etc/firewall/natd-vmxZ.conf  -port 8888 -alias_address ${192.168.10.40}
>>
>> Something like
>> # This takes inside traffic to outside port 80 address and
>> # remaps it to inside IP of router to send to web server
>> ${fwcmd} add X divert 8888 tcp from 192.168.0.0/24 to ${outside_ip_router} port 80
>> # This translates the returning packets
>> ${fwcmd} add X divert 8888 tcp from 192.168.0.0/24 port 80 to ${inside_ip_router}
>>
I'd use ipfw fwd on the internal interface of the firewall to forward 
the packet to the inside host, and assuming the host is a freebsd 
machine use another ipfw fwd to localhost to 'capture' it locally.

the packets from hte internal client to the internal server would go 
via the router but the return packets would go direct.


sort of:

on the firewall:

ipfw add xxx fwd $WEBSERVER tcp from any to $EXTERNAL_IP 80,443 in 
recv $INSIDE_INTERFACE


on hte web server, same rule..

ipfw add xxx fwd $WEBSERVER tcp from any to $EXTERNAL_IP 80,433 in 
recv $INSIDE_INTERFACE

internal packets will get redirected to the web server which will 
process them directly using the transparent proxy code.

You may need to make sure you have the right options set in your 
kernel to support this.

so:

packet to OUTSIDE:80 leaves client

packet hits firewall which sends it completely unmodified to server,

which openes an "illegal" socket using the firewall's address,

Return packets leave the server saying they have come from the 
firewall address, but addressed to the internal client address and go 
there directly.





More information about the freebsd-ipfw mailing list