Page MenuHomeFreeBSD

Document IPFW's in-kernel NAT
Changes PlannedPublic

Authored by driesm.michiels_gmail.com on Aug 17 2019, 3:56 PM.

Details

Reviewers
ae
eugen_grosbein.net
lev
Group Reviewers
Doc Committers
Summary

Basically did a rewrite of the NAT chapter with a focus on in-kernel NAT, at the end there is still a small section documenting natd.

Test Plan

I ran igor against chapter.xml, but I can't seem to figure out how to fix the leftover alignment errors it is spitting out.
Would love if someone checks and "teaches" me what was wrong (and how I can fix it in the future).

Diff Detail

Repository
rD FreeBSD doc repository
Lint
Lint Skipped
Unit
Unit Tests Skipped

Event Timeline

en_US.ISO8859-1/books/handbook/firewalls/chapter.xml
2441

Extra capitalizing seems to be unintended.

Thank you very much for starting this work. We really need updates to the Handbook.

There are some not-so-serious issues that can, however, complicate migration from natd to ipfw nat in practice and Handbook chapter should make it easier instead of adding more complexity:

  1. Standard scripts using standard settings in /etc/rc.conf generate ipfw ruleset using rule 50 instead of 500 and "nat 123" instead of "nat 1". To simplify learning curve we should make the Handbook more consistent with system it describes.
  1. Modern IPFW has "ipfw disable one_pass" command equivalent for sysctl net.inet.ip.fw.one_pass="0", and had it for long time. Users should be able to touch fewer files to configure IPFW and the Handbook should use "ipfw disable one_pass". This is also less cryptic to read and remember.
  1. There is more serious issue with in-kernel LIBALIAS replacement for user-land copy of libalias used with natd binary.

GENERIC kernel has no "options LIBALIAS". This option provides complete in-kernel replacement for userland libalias.

For GENERIC-based system, kernel module libalias.ko is automatically loaded by ipfw instead. However, libalias.ko does NOT provide complete replacement for userland libalias by itself. One needs to specify additional protocol helpers manually by means of /boot/loader.conf or rc.conf's kld_list variable:

alias_cuseeme.ko
alias_ftp.ko
alias_nbt.ko
alias_skinny.ko
alias_irc.ko
alias_pptp.ko
alias_smedia.ko

You won't get working FTP or PPtP etc. transit traffic aliasing otherwise if you migrate from natd to ipfw nat. Or if you setup ipfw nat initially.

The Handbook should mention this somehow.

There is also one subtle difference between "ipfw divert" command used with natd and "ipfw nat" command.

Correct NAT operations require IP fragments reassembly to be performed before passing traffic to NAT engine. ipfw(8) manual page informs: "Incoming packet fragments diverted by divert are reassembled before delivery to the socket" (see BUGS section). So, default ipfw rules generated by system guarantee fragment reassembly.

This is not a case after move to ipfw nat and one may need additional "ipfw reass" rule manually added before "ipfw nat" rule. It is mostly unneeded as TCP and some UDP-based protocols have means to prevent IP fragmentation from happening in first place. But sometimes it is needed if system routinely processes other types of IP packets like IPSEC/ESP/GRE tunneling other IP packets. Sometimes encapsulation leads to oversized and therefore fragmented traffic.

Thanks for the feedback Eugen, that will take a bit more time to restructure / add some of your comments.

I have one remark regarding 1), rc.firewall creates the NAT rule at number 50, although I think the example in the handbook and the ruleset rc.firewall creates are different. rc.firewall only has one NAT rule and does not have all stateful rules. So I don't feel too strong about renumbering the existing ruleset in the handbook just to match the NAT rule at number 50. Renaming the nat instance from 1 -> 123 is quickly done. Thoughts?

eugen_grosbein.net added a comment.EditedWed, Aug 21, 7:10 AM

Thanks for the feedback Eugen, that will take a bit more time to restructure / add some of your comments.
I have one remark regarding 1), rc.firewall creates the NAT rule at number 50, although I think the example in the handbook and the ruleset rc.firewall creates are different. rc.firewall only has one NAT rule and does not have all stateful rules. So I don't feel too strong about renumbering the existing ruleset in the handbook just to match the NAT rule at number 50.

There is nothing wrong with extended examples in Handbook. But we should avoid unneeded confusion for users and state is explicitly that default rule number is different. Also, please make sure your example creates no conflicts with default ruleset, e.g. it does not produce ruleset with both default rule 50 and additional ipfw nat rule. Also, rule number 500 is already in use by default ruleset, look at /etc/rc.firewall:

setup_loopback() {
        ############
        # Only in rare cases do you want to change these rules
        #
        ${fwcmd} add 100 pass all from any to any via lo0
        ${fwcmd} add 200 deny all from any to 127.0.0.0/8
        ${fwcmd} add 300 deny ip from 127.0.0.0/8 to any
        if [ $ipv6_available -eq 0 ]; then
                ${fwcmd} add 400 deny all from any to ::1
                ${fwcmd} add 500 deny all from ::1 to any
        fi
}
driesm.michiels_gmail.com planned changes to this revision.Wed, Aug 21, 8:11 AM

Thanks, I see what you mean now! :-) Let me see what I can cook up.