FreeBSD Gateway (PPPoE pppNat IPFW) Howto

Original document

by Y. Kowara. Sydney - Australia


I wrote this HowTo because I don't find a clear step by step HowTo when I was trying to setup ADSL with FreeBSD using PPPoE, pppNat and IPFW. I found pieces of information here and there and after a few search, trial-and-error, mailing list, and a few hair-pulling later I finally get my FreeBSD box up and running.

The ISP I am connected to does not even provide a support for FreeBSD. So, I hope this article would be of some assistance to a FreeBSD newbie who wants to get a broadband connection using ADSL.

The IPFW part probably is not good enough, I am not a security/firewall expert. However, it at least let me do what I need. I managed to find a better one and I will post it in my second article - PPPoE, NatD and IPFW.

This article assume that you have installed FreeBSD. I am using FreeBSD 4.9. I am connected with a static IP. I don't think it is a problem if you have a dynamic IP, because with PPPoE you don't have to assign an IP address to your external interface. In fact, you initialise your external NIC at boot without assigning an IP address.

Initialise NICs at boot

##initialise NIC
             network_interfaces="ed0 fxp0 rl0 lo0 tun0"
             ifconfig tun0
             ifconfig_ed0="media 10baseT/UTP up"   #ed0 does not need IP address
             ifconfig_fxp0="inet netmask"
             ifconfig_rl0="inet netmask"

My ISP sold me D-Link DSL300+ when I sign up. It is easy to configure using Windows. I had to use Windows at first because I could not find any help online except for Paul Hoadley's FreeBSD on Telstra's Bigpond ADSL Network. The article helped me to configure my FreeBSD box to use PPPoE for ADSL.

If this howto is confusing or does not work, please take a look at Paul Hoadley's article. Even though the Paul suggested that it may not be applicable to ISP other than Telstra, it worked on mine without a glitch. So I'd say that his configuration is generic enough to be applied in normal circumstances, at least with FreeBSD 4.X.

The box will be the gateway for your LAN, so You need at least two NICs. My external interface is ed0.

To Do List

  1. recompile kernel to include ipfw
  2. configure userland PPP
  3. modify rc.conf to enable ppp at boot
  4. test ppp_nat
  5. build IPFW script
  6. test your ipfw script
  7. security check
  8. final thoughts

1. Recompile kernel to include ipfw

Make a backup of your current (generic) kernel. Please read the full explanation in the FreeBSD handbook: Building and Installing a Custom Kernel.
# cd /usr/ssrc/sys/i386/conf
# mkdir /root/kernels
# cp GENERIC /root/kernels/MYKERNEL
# ln -s /root/kernels/MYKERNEL

Edit MYKERNEL with your text editor, and add firewall/NAT support:

options IPDIVERT

Rebuild MYKERNEL - the traditional way.

# /usr/sbin/config MYKERNEL
# cd ../../compile/MYKERNEL
# make depend
# make
# make install

Modify /etc/rc.conf to run IPFW at start up

firewall_type="OPEN"              #NOT secure, but makes it easy to test your firewall

2. Userland PPP - /etc/ppp/ppp.conf

You have the option of enabling PPP in the kernel (kernel ppp) or configure a userland ppp(no need to enable ppp in the kernel). I chose userland ppp because it is easier to deploy. However, Complete FreeBSD suggested that ....

When you are writing your ppp.conf, make sure to indent the codes.The FeeBSD handbook does not seem to instruct users to indent the scripts in the ppp.conf. However, without indenting, PPP complained about missing colons and failed to execute.

Indentation in any coding practice makes it easier to read the code.

Here is my ppp.conf

        set device PPPoE:ed0:my_isp's_name
        set speed sync
        set mru 1492
        set mtu 1492
        set ctsrts off
        enable lqr
        add default HISADDR
        set timeout 0
        set redial 0 0

        nat enable yes
        nat log yes
        nat same_ports yes
        nat unregistered_only yes
        enable dns

        set authname username
        set authkey password

3. Modify rc.conf to start ppp at boot

##User ppp configuration.
 ppp_enable="YES"        # Start user-ppp (or NO).
 ppp_profile="iinet"     # Which profile to use from /etc/ppp/ppp.conf.
 ppp_mode="ddial"        # Choice of "auto", "ddial", "direct" or "dedicated".
                         # For details see man page for ppp(8). Default is auto.
 ppp_nat="YES"           # Use PPP's internal network address translation or NO
                         # nat config is already set in ppp.conf
 ppp_user="root"         # Which user to run ppp as

4. Test ppp_nat

5. Create simple IPFW script


 ## Global variable

 #Reset all rules
   ${fwcmd} -f flush

 # Check state
   ${fwcmd} add 00180 check-state

 # Allow all via loopback to loopback
   ${fwcmd} add 00200 allow all from any to any via lo0

 # Deny connection attempt to loopback devices NOT coming from loopback device
   ${fwcmd} add 00300 deny all from any to

 # Deny connection attempt from loopback device NOT to loopback device
   ${fwcmd} add 00400 deny all from to any

 # Allow firewall to do everything
   ${fwcmd} add 00510 pass tcp from ${myip} to any setup keep-state
   ${fwcmd} add 00520 pass udp from ${myip} to any keep-state
   ${fwcmd} add 00530 pass icmp from ${myip} to any icmptype 0,8

 # Allow local LAN to connect to us
   ${fwcmd} add 00550 allow all from ${mynetwork} to ${mynetwork}

 # Explicitly open ssh to this box from mynetwork, otherwise the authentication
 # session becomes slow
   ${fwcmd} add 00560 allow tcp from ${mynetwork} to ${mynetwork} 22

 # Allow SSH in
   ${fwcmd} add 00610 allow tcp from any to ${myip} 22 in keep-state setup

 # Allow DNS requests to my ISP DNS server
   ${fwcmd} add 00700 allow udp from ${dns_server} 53 to any
   ${fwcmd} add 00710 allow udp from any to ${dns_server} 53

 # Allow pop3 and smtp services to my mail server
   ${fwcmd} add 00820 allow tcp from any to ${mail_server} pop3
   ${fwcmd} add 00830 allow tcp from ${mail_server} pop3 to any established
   ${fwcmd} add 00840 allow tcp from any to ${mail_server} smtp
   ${fwcmd} add 00850 allow tcp from ${mail_server} smtp to any established

 # Allow access to http, https
   ${fwcmd} add 00900 allow tcp from any to any http
   ${fwcmd} add 00910 allow tcp from any http to any
   ${fwcmd} add 00920 allow tcp from any to any https
   ${fwcmd} add 00930 allow tcp from any https to any

6. Test your ipfw

7. Security Check

Your box is now visible from the Internet. You have setup a firewall to protect it. Guess what? That is not the end of the story. Security is not the end of your project. It is a journey. Always check your security measures using available tools.

For a quick and easy firewall test, go to

8. Final thoughts

I am yet to conclude whether there is a particular sequence as to where to put your scripts in rc.conf, i.e. whether to put PPPoE first then NICs then IPFW or it does not matter at all.

My rc.conf is structured as following:

This is experimental, I haven't a chance to revisit my configuration. So, make sure to drop into the relevant mailing lists when you are doing this.

If you have a better suggestion or if there are any corrections I should make (which I am sure there are), please email me at