IPFW nat ipv6 to ipv4 and other comprehension questions to IPFW rules

Hello,

I have some comprehension questions to IPFW rules, but I guess it is best if I first describe my environment and my current IPFW rules:
I'm running a server with FreeBSD 11.4 with several services (web server, chat server and a database), each isolated in an own jail (using iocage).
I've configured an internal virtual network device (192.168.0.0/24), so that each jail can has its own internal 192.168.0.X IPv4 address.
I use IPFW and in-kernel NAT to redirect external requests to the right jail (e.g. port 80 and 443 to the "web server"-jail).
I want to have the jails very isolated, means for example that the web server-jail can reach the necessary port on the database jail (web application requires a database), but the database-jail itself cannot reach the web server-jail at all. The web server-jail and the chat server-jail should also not be able to reach each other, but the chat server-jail also requires to access the database...
Currently I'm only focusing on IPv4.

My rules are already in use and seems to work fine,
but I would really appreciate if the IPFW experts could comment on these rules, e.g. if I have committed a fallacy, doing bad practice etc...
I don't want to accidentally punch a hole in my server. ;-)
I have composed my rules by the examples in the FreeBSD manual and other sources in the web and of course to my own understanding of IPFW. But I think I still have to learn a lot.

I've pasted my rules below, so that you can have a look at it, and I have especially the following comprehension questions:
  • Rules to deny all inbound traffic from non-routable reserved address spaces (starting at no. 10001) and other unwanted things: In the examples I found these are located AFTER the nat and check-state rules. Wouldn't it be better to place them before these rules? So that these packages are already denied before they go though nat or the dynamic table from check-state?
    Or is this bad from a performance perspective since there are likely not that much packages that are matched by these rules, so that its better to place them in a very high position?
  • I've seen examples that use a rule allow tcp from any to any established. What exactly is the difference to check-state? I do not have that rule but my configuration still works. As far as I remember I've had it during my experiments with IPFW located AFTER nat and check-state, and it never got a match ( ipfw -a list). I guess placing it BEFORE the nat rule doesn't make sense, because the established packages need to get nat'ed? Does it make sense after nat and before check-state? Will this give a performance boost because these packages will not run through the dynamic table?
  • I plan to additionally use IPv6 now (I know, I'm late...), but if possible I would like to leave my internal jail network (IPv4) untouched. Is it possible to nat (redirect) from IPv6 to IPv4?
    So that I can externally listen for example to port 80 using my (external) IPv6 address but redirect that to port 80 on my jail using its 192.168.0.X IPv4 address? I'v seen that ipfw has nat64lsn, but I didn't find a good example or so, that explains the details to me. Any help here would be appreciated!

My current IPFW rules are as followed:
Bash:
#!/bin/sh

#################################################
# configuration
################################################
fwcmd="/sbin/ipfw -q add"        # ipfw command
wan="em0"                # the external interface (public internet)
loop="lo0"                # loopback interface (local network for host only)
lan="lo1"                # internal interface (local network for jails)
jumpNAT="skipto 65100"            # jump to NAT rule
jail_host="192.168.0.1"            # jail aliases
database_jail="192.168.0.2"
chat_jail="192.168.0.3"
apache_jail="192.168.0.4"



################################################
# INIT
################################################

# flush out the list before we add any rules
/sbin/ipfw -q -f flush

# use in-kernel NAT and define port redirection
/sbin/ipfw disable one_pass
/sbin/ipfw -q nat 1 config if ${wan} same_ports unreg_only reset \
    redirect_port tcp ${apache_jail}:80 80 \
    redirect_port tcp ${apache_jail}:443 443 \
    redirect_port tcp ${chat_jail}:5222 5222



################################################
# LOCAL traffic (rules 0-499)
################################################

# ALLOW anything within the loopback interface
${fwcmd} 00001 allow all from any to any via ${loop}

# ALLOW each jail to reach itself without restriction
${fwcmd} 00010 allow all from ${jail_host} to ${jail_host} via ${lan}
${fwcmd} 00011 allow all from ${database_jail} to ${database_jail} via ${lan}
${fwcmd} 00012 allow all from ${chat_jail} to ${chat_jail} via ${lan}
${fwcmd} 00013 allow all from ${apache_jail} to ${apache_jail} via ${lan}



################################################
# NAT and existing entries in dynamic rules table
# (rules 500-999)
################################################

# reassemble inbound packets
${fwcmd} 00500 reass all from any to any in
# NAT any inbound packets
${fwcmd} 00501 nat 1 ip from any to any in via ${wan}
# allow packets having an existing entry in the dynamic rules table
${fwcmd} 00502 check-state



################################################
# OUTBOUND traffic (rules 1000-9999)
################################################

# ALLOW access to public DNS (see /etc/resolve.conf)
${fwcmd} 01000 ${jumpNAT} tcp from any to XXX 53 out via ${wan} setup keep-state
${fwcmd} 01001 ${jumpNAT} udp from any to XXX 53 out via ${wan} keep-state

# ALLOW traffic to services between jails (note: no NAT required)
# to database jail
${fwcmd} 01100 allow tcp from ${jail_host} to ${database_jail} 389 out via ${lan} setup keep-state
${fwcmd} 01101 allow tcp from ${chat_jail} to ${database_jail} 389 out via ${lan} setup keep-state
${fwcmd} 01102 allow tcp from ${apache_jail} to ${database_jail} 389 out via ${lan} setup keep-state
# to chat jail
${fwcmd} 01110 allow tcp from ${jail_host} to ${chat_jail} 5222 out via ${lan} setup keep-state
# to apache jail
${fwcmd} 01120 allow tcp from ${jail_host} to ${apache_jail} 80,443 out via ${lan} setup keep-state

# ALLOW each jail to reach the host's syslogd and exim (note: no NAT required)
${fwcmd} 01200 allow udp from 192.168.0.0/24 to ${jail_host} 514 out via ${lan} keep-state
${fwcmd} 01201 allow tcp from 192.168.0.0/24 to ${jail_host} 25 out via ${lan} setup keep-state

# ALLOW root user to reach anything
# (important for updates etc.)
${fwcmd} 01300 ${jumpNAT} tcp from me to any out via ${wan} setup keep-state uid root
${fwcmd} 01301 ${jumpNAT} udp  from me to any out via ${wan} keep-state uid root
${fwcmd} 01302 ${jumpNAT} icmp from me to any out via ${wan} keep-state

# DENY and log all other outbound connections
${fwcmd} 09999 deny log all from any to any out via ${wan}



################################################
# INBOUND traffic (rules 10000-19999)
################################################

# DENY all inbound traffic from non-routable reserved address spaces
${fwcmd} 10001 deny all from 192.168.0.0/16 to any in via ${wan}     #RFC 1918 private IP
${fwcmd} 10002 deny all from 172.16.0.0/12 to any in via ${wan}      #RFC 1918 private IP
${fwcmd} 10003 deny all from 10.0.0.0/8 to any in via ${wan}         #RFC 1918 private IP
${fwcmd} 10004 deny all from 127.0.0.0/8 to any in via ${wan}        #loopback
${fwcmd} 10005 deny all from 0.0.0.0/8 to any in via ${wan}          #loopback
${fwcmd} 10006 deny all from 169.254.0.0/16 to any in via ${wan}     #DHCP auto-config
${fwcmd} 10007 deny all from 192.0.2.0/24 to any in via ${wan}       #reserved for docs
${fwcmd} 10008 deny all from 204.152.64.0/23 to any in via ${wan}    #Sun cluster interconnect
${fwcmd} 10009 deny all from 224.0.0.0/3 to any in via ${wan}        #Class D & E multicast

# DENY public pings (only allow icmptype 0 if we ping stuff ourself)
${fwcmd} 10010 deny log icmp from any to any in via ${wan} not icmptypes 0

# DENY ident/ noise from routers
${fwcmd} 10020 deny tcp from any to any 113 in via ${wan}
${fwcmd} 10021 deny udp from any to any 520 in via ${wan}

# DENY all Netbios services
${fwcmd} 10030 deny tcp from any to any 137 in via ${wan}
${fwcmd} 10031 deny tcp from any to any 138 in via ${wan}
${fwcmd} 10032 deny tcp from any to any 139 in via ${wan}
${fwcmd} 10033 deny tcp from any to any 81 in via ${wan}

# DENY fragments
${fwcmd} 10040 deny all from any to any frag in via ${wan}

# DENY ACK packets that didn't match the dynamic rule table
${fwcmd} 10041 deny tcp from any to any established in via ${wan}

# DENY broadcasts and multicasts
${fwcmd} 10050 deny ip from any to 255.255.255.255
${fwcmd} 10051 deny ip from any to 224.0.0.0/24 in  

# DENY spoofing from outside
${fwcmd} 10060 deny ip from any to any not antispoof in via ${wan}
${fwcmd} 10061 deny all from any to 127.0.0.0/8 in via ${wan}

# ALLOW inbound SSH connections
${fwcmd} 11000 allow log tcp from any to me 22 in via ${wan} setup limit src-addr 3

# ALLOW inbound connections to services on jails
# web server
${fwcmd} 12000 ${jumpNAT} tcp from any to ${apache_jail} 80,443 in via ${wan} setup keep-state
# chat server
${fwcmd} 12100 ${jumpNAT} tcp from any to ${chat_jail} 5222 in via ${wan} setup keep-state

# DENY and log all other incoming connections
${fwcmd} 19999 deny log all from any to any in via ${wan}



################################################
## FINAL rules (>=65000)
################################################

# DENY and LOG all uncaptured messages on ANY interface
${fwcmd} 65000 deny log all from any to any

# ALLOW skipto location for outbound statefule rules
${fwcmd} 65100 nat 1 ip from 192.168.0.0/24 to any out via ${wan}
${fwcmd} 65101 allow ip from any to any

Thanks for reading and thanks for your help,
Fool
 
Hello,
is NAT from IPv6 to IPv4 even possible with in-kernel-NAT?
I'm really unsure about nat64lsn and how to really use it...any ideas/information for me?

For those who are familiar with IPFW: Do my existing firewall rules makes sense / look good? Or do I have some flaws?
Starting with IPv6 (ignoring my NAT problem to the IPv4 internal jails for now):
I understand that all IP-related rules are currently IPv4 only, and I have to create similar rules for IPv6.
What about all TCP-related rules? I guess these are automatically working for IPv4 and IPv6?
(For example my rule #11000 for inbound SSH connections: Does this rule automatically also work for SSH connections via IPv6?
Or do I need to replace the 'me' with 'me6'? Does me6 also include IPv4? Or do I need two rules, one with 'me' and one with 'me6'?)

Any help is appreciated. Thank you! :)

Kind regards,
Fool
 
Back
Top