IPFW NAT Reflect for local net

I have settings like:
Code:
${fwcmd} nat 1 config if ${iiface} same_ports \
    redirect_port tcp 192.168.0.99:80 80 \
    redirect_port tcp 192.168.0.99:443 443

${fwcmd} add 50 nat 1 ip from any to ${myexternalip} in via ${iiface}
${fwcmd} add 51 nat 1 ip from "table(1)" to any out xmit ${iiface}

How i can allow access ${myexternalip} port 80 and 443 from localnet
 
I have settings like:
Code:
${fwcmd} nat 1 config if ${iiface} same_ports \
    redirect_port tcp 192.168.0.99:80 80 \
    redirect_port tcp 192.168.0.99:443 443

${fwcmd} add 50 nat 1 ip from any to ${myexternalip} in via ${iiface}
${fwcmd} add 51 nat 1 ip from "table(1)" to any out xmit ${iiface}

Is 192.168.0.99 a system on your internal network, or an address on this system?

How i can allow access ${myexternalip} port 80 and 443 from localnet

Your network topology isn't clear enough from the above.

On which iface is $myexternalip ?

Please show ifconfig for both inside and outside interfaces, and what kind of addresses are in table(1)? (obscured if need be)
 
Is 192.168.0.99 a system on your internal network, or an address on this system?
192.168.0.99 in my localnet 192.168.0.0/24

2rxte.png


Ho i can realize this "Proper Hairpin NAT" with ipfw?
 
As this is a web connection (ports 80 and 443), a reverse proxy is a good alternative. Has a few other benefits too (like being able to load-balance between two or more backend webservers).
 
My problem, in 443 80 port (it used in forum thread only for simplification), in my real situation use other ports/services.

Main question of thread is about network situation where need fix source ip of lan clients (reply from server need forward back to router, not direct to client by localnet)
 
Do not use this it's just an example and should not be used.

ipfw nat 1 config if ${external_if} log deny_in same_ports redirect_port tcp 192.168.3.11:80 80

ipfw add 50 nat 1 ip from 192.168.3.201 to any via ${iiface}
ipfw add 51 nat 1 ip from 192.168.3.11 to any via ${iiface}
 
For the uninitiated, it's instructive to know that:
  1. in any IP stack, all IP addresses on a host are accessible from any NIC on that host;
  2. hairpin NAT enables access to the external Internet IP address of a server by internal clients reaching that server by routing through the firewall; and
  3. internal connections reaching the Internet server via its external address and the firewall must be returned via the firewall -- and not via the direct internal network connection -- because the TCP connection is established and therefore exists via the firewall.
Hairpin NAT ensures that rule 3 is observed. The crude logic looks like this:
Code:
+--------+        +--------+
|Internal|<------>|Firewall|-----> Internet
| Client |        +--------+
+--------+             ^
Not |                  |
to  |                  |
be  |                  |
used|    +--------+    v
    +----|Internet|----+
         |Service |External Address of Service
         +--------+
The OP's diagram came from this StackExchange post, which I bookmarked about 10 years ago when I was figuring out how to support hairpin NAT on my own firewalls. It's worth a read, just for background.

Split DNS does mostly solve the theoretical problem (so internal clients use the internal address, and external clients use the external address), but not completely. With split DNS the external and internal port numbers must be identical. Wanting hairpin NAT is a therefore a valid thing, because it lets you re-arrange the port numbers.
 
Split DNS does mostly solve the theoretical problem (so internal clients use the internal address, and external clients use the external address), but not completely. With split DNS the external and internal port numbers must be identical. Wanting hairpin NAT is a therefore a valid thing, because it lets you re-arrange the port numbers.
Still not feeling it. If you need to do port redirection for some reason, do it on the server itself with pf(4) or ipfw(8) or whatever you like. That way you're not stupidly loading your gateway with extra traffic and NATting for machines that can simply communicate directly with each other.
 
I believe that there are situations where hairpin NAT makes sense (and why commercial firewalls support it).

If you run a split DNS, you probably already have the solution you want. But some people outsource their external DNS. One extra hairpin NAT forwarding rule is simpler to do and manage than setting up and getting the delegation for a complete new DNS service.
 
The fact idiot product managers at Ubiquity or Eero or whatever don't understand split-horizon DNS does not make hairpin NAT a good idea.
 
id run either split dns or a simple multiport forwarder on the internal interface and thats it
also portable between ipfw/pf/ipf/whatever (i even used inetd+netcat for this in some cases)
 
The fact idiot product managers at Ubiquity or Eero or whatever don't understand split-horizon DNS does not make hairpin NAT a good idea.
What if my services not use DNS it all, only IP Address ?
Manufactures of network routers not idiots, because exist situation where router forward external ports, and local users need access it from local net, without theorea about right DNS settings, just work, it simple.
And about split-horizon DNS, this is not good idea to modify DNS records, in some situation this modification can be detected via record-sign checksum and etc, this is not workaround of problem.
 
Point me to article or wiki how to config ipfw for Hairpin NAT
Sadly, my firewall experience is not on FreeBSD, and I have no specific knowledge of ipfw. Hopefully, others will help.

I don't know of any specific article or wiki for this, and I must assume that StreamThreader is quite familiar with ipfw(8).

I've been thinking about how to implement "proper hairpin NAT" in ipfw according to that diagram, and have a couple of ideas.

However I won't be back here for 6 hours or so, timezone mismatch, so if anyone else has any clues?
 
Do not use this it's just an example and should not be used.

The example you posted was in an unlabeled box that failed to quote here (how did you do that?) so I've copy/pasted it here as code:

Code:
ipfw nat 1 config if ${external_if} log deny_in same_ports redirect_port tcp 192.168.3.11:80 80

ipfw add 50 nat 1 ip from 192.168.3.201 to any via ${iiface}

ipfw add 51 nat 1 ip from 192.168.3.11 to any via ${iiface}

I'm struggling to see how this works according to that diagram, especially for the return packet #2?

Could you expand a bit on the two packet flows, given that 'ordinary' NAT needs to occur as well for ordinary traffic from ${inet} through gateway to outside, and back on return?

Couldn't rule 50 equally apply to other inside clients, and so be

(Edit, not enough sleep:
'from any in recv ${iiface}' (rather than via, which can refer to xmit iface also))

'from any to $external_IP via ${iiface}'

Which still needs separate nat config and rule/s for ordinary LAN access to net?

Thanks, Ian
 
Main question of thread is about network situation where need fix source ip of lan clients (reply from server need forward back to router, not direct to client by localnet)
Try to use some kind of TCP/UDP proxy instead of NAT.
In some cases I use simpleproxy() for portforwarding.
It works for me for the case when a local client connects to proxied port on the external interface.
Example: simpleproxy -L <externalIP>:extport -R 192.168.x.x:localport

Also you can try to use "nginx streams" as a TCP proxy. It is a more reliable solution.
Code:
load_module /usr/local/libexec/nginx/ngx_stream_module.so;

stream {
        log_format basic '$remote_addr [$time_local] '
                 '$protocol $status $bytes_sent $bytes_received '
                 '$session_time';
        access_log  /var/log/nginx/stream_access.log basic;
        upstream rdp {
                server <LOCALorDEST_IP>:<DESTINATION_PORT>;
                        }
        server {
                listen          <EXTERNALIP>:<EXTPORT>;
                proxy_pass      rdp;
                }
        }
 
Point me to article or wiki how to config ipfw for Hairpin NAT

Have you tried what VladiBG suggested yet? If it doesn't work, please show details of what happens.

Note that your nat config specified 'if ${iiface}' instead of VladiBG's ${external_if}.

Still wondering what table(1) might contain?
 
You don't need separate nat rule. You can easy merge both of them into one

ipfw add 50 nat 1 ip from any to any via ${iiface}
 
I vote for VladiBG's solution but I prefer separate NAT rule as I want to limit NAT on the outside interface as much as possible. I may have other VM's bridged on the outside inferface that I don't want to nat for example. Also I once saw a router setup (I didn't do it lol) to NAT everything (internal connections as well) and this played havoc with a splynx server trying to talk to a mikrotik router on a separate subnet (all ssh connections between subnets showed up as from the router) until I changed the nat rule to nat only external traffic. There are two ways to do redirects with ipfw that I know of 1) If the redirected IP is different 2) The redirected IP is the same or different and the setup is more complicate. Apache Proxy and Proxy Reverse will work but I did notice a big enough performance difference, ipfw kernel nat was faster.

1) Is simple and this example forwards outside interface ip xxx.xxx.xxx.xxx port 8080 to the localhost ip port 80
# this will not work if the fwd ip and external ip are the same
# do not add accept rule before fwd or it won't work
${fwcmd} add fwd 127.0.0.1,80 tcp from any to ${ip} 8080 in via ${oif}

2) Forwarded IP is the same or different like a VM that needs to answer requests from the hosts external IP see ...


This page has full instructions for settings in /boot/loader.conf /etc/sysctl.conf and rc.conf as well as ipfw.rules shown here...

Edit /etc/ipfw.rules
—————
#!/bin/sh
fwcmd=”ipfw -q”
oif=”em0″
net=”10.200.10.0/24″
vmip=”10.88.88.88″
natnet=”10.88.88.0/24″
#trusted1=”123.456.789.0/24″
trusted1=”123.456.789.111″
# avoid net.inet.ip.fw.one_pass=0
# try to avoid statefull

ipfw -q -f flush

${fwcmd} add allow ip from any to any via lo0
${fwcmd} add deny ip from any to 127.0.0.0/8
${fwcmd} add deny ip from 127.0.0.0/8 to any
${fwcmd} add deny ip from any to ::1
${fwcmd} add deny ip from ::1 to any
${fwcmd} add allow ipv6-icmp from :: to ff02::/16
${fwcmd} add allow ipv6-icmp from fe80::/10 to fe80::/10
${fwcmd} add allow ipv6-icmp from fe80::/10 to ff02::/16
${fwcmd} add allow ipv6-icmp from any to any icmp6types 1
${fwcmd} add allow ipv6-icmp from any to any icmp6types 2,135,136

# reassemble inbound packets
# ${fwcmd} add reass all from any to any in

ipfw -q nat 1 config if ${oif} same_ports unreg_only reset \
redirect_port tcp ${vmip}:22 22222 \
redirect_port tcp ${vmip}:81 81 \
redirect_port tcp ${vmip}:444 444 \
redirect_port tcp ${vmip}:8080 8080 \
redirect_port tcp ${vmip}:8443 8443 \
redirect_port tcp ${vmip}:25 25 \
redirect_port tcp ${vmip}:119 119 \
redirect_port tcp ${vmip}:143 143 \
redirect_port tcp ${vmip}:389 389 \
redirect_port tcp ${vmip}:465 465 \
redirect_port tcp ${vmip}:587 587 \
redirect_port tcp ${vmip}:993 993 \
redirect_port tcp ${vmip}:995 995 \
redirect_port tcp ${vmip}:7071 7071 \
redirect_port tcp ${vmip}:7073 7073 \
redirect_port tcp ${vmip}:7025 7025

# NOTE YOU CAN’T DO ACCEPT IN ON ABOVE PORTS eg 22222
# Use Apache to redirect to https on 444 / eg no http allowed
# Using Apache Proxy/Reverse to 10.88.88.88:81 works also

# NAT
${fwcmd} add nat 1 ip from ${natnet} to any out via ${oif}
${fwcmd} add nat 1 ip from any to me in via ${oif}

# Allow limited broadcast traffic from my own net.
${fwcmd} add pass all from ${net} to 255.255.255.255

# Allow any traffic to or from my own net.
${fwcmd} add pass all from me to ${net}
${fwcmd} add pass all from ${net} to me

# Allow setup of incoming https request
${fwcmd} add pass tcp from any to me 80,443 in via ${oif}

# SSH WIDE OPEN TEMP
# ${fwcmd} add pass tcp from any to me 22 in via ${oif}

# Deny ssh from NATNET / don’t trust ssh from the VM
${fwcmd} add deny tcp from ${natnet} to me 22

# TEMP allow ssh traffic to my test net
# ${fwcmd} add pass tcp from 10.200.0.0/16 to me 22 in via ${oif}
# ${fwcmd} add pass tcp from me to 10.200.0.0/16 22 in via ${oif}

# TRUSTED NET OR HOST
${fwcmd} add pass tcp from ${trusted1} to me 22 in via ${oif}
${fwcmd} add pass icmp from ${trusted1} to me
${fwcmd} add pass udp from ${trusted1} to me

# deny all other SSH requests
${fwcmd} add deny tcp from any to me 22 in via ${oif}

# Allow TCP through if setup succeeded
${fwcmd} add pass tcp from any to any established

# Allow IP fragments to pass through
${fwcmd} add pass all from any to any frag

# Allow setup of incoming email
# disable external mail, this host forwards mail to VM
# ${fwcmd} add pass tcp from any to me 25 setup

# another service to host I want to allow for example
${fwcmd} add pass tcp from any to me 23232 in via ${oif}

# NATNET
${fwcmd} add allow ip from ${natnet} to any
${fwcmd} add allow ip from any to ${natnet}

# OUT SIMPLE
${fwcmd} add allow tcp from me to any setup keep-state
${fwcmd} add allow udp from me to any keep-state
${fwcmd} add allow icmp from me to any keep-state

# Global Deny
${fwcmd} add deny ip from any to any

Something like this should work.
 
Back
Top