FreeBSD

Sharing an Internet connection using a FreeBSD router/firewall

These are my notes from configuring kernel PPP (pppd), a firewall, and Network Address Translation (NAT/masquerading) on FreeBSD 4.10. My goal was to have a shared Internet connection in which my FreeBSD box acts as the Internet router (gateway) and firewall via a dialup connection for other computers on my LAN.

  1. Recompile the FreeBSD kernel with these options (if necessary):
    options IPFIREWALL
    options IPDIVERT
    

    Build the FreeBSD kernel. Put the above options in MYKERNCONF.

  2. Add to /etc/rc.local:
    sysctl net.inet.ip.fw.verbose=1
    
  3. Add to /etc/rc.conf:
    gateway_enable="YES"
    natd_enable="YES"
    natd_interface="ppp0"
    natd_flags="-interface ${natd_interface}"
    firewall_enable="YES"
    firewall_script="/etc/firewall.custom"
    
  4. Create this as the file /etc/firewall.custom but first configure it for your network:
    #!/bin/sh
    # Based on:
    # /etc/rc.firewall
    # http://www.freebsd.org/doc/en_US.ISO8859-1/articles/dialup-firewall/rules.html
    
    #--------- CONFIGURATION BEGIN -----------
    
    fwcmd="/sbin/ipfw -q"
    
    # Your outside interface.
    oif="ppp0"
    
    # Your inside interface.
    iif="dc0"
    
    # Your private network address/mask.
    inet="192.168.1.0/16"
    
    # Your ISP DNS servers.
    odns1=""
    odns2=""
    odns3=""
    
    # Loopback interface and network address.
    loif="lo0"
    lonet="127.0.0.0/8"
    
    #--------- CONFIGURATION END -------------
    
    echo "Enabling firewall."
    
    # Clear firewall rules.
    $fwcmd -f flush
    
    # Short circuits.
    $fwcmd add pass all from any   to any   via $loif
    $fwcmd add pass all from $inet to $inet via $iif
    
    # Prevent spoofing.
    $fwcmd add deny all from     $lonet to any in via any
    $fwcmd add deny all from     $inet  to any in via $oif
    $fwcmd add deny all from not $inet  to any in via $iif
    
    # Reject packets from outside destined to an inside address.
    $fwcmd add deny all from any to $inet via $oif
    
    # Allow natd.
    $fwcmd add divert natd all from any to any 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 access to your ISP DNS servers.
    for odns in $odns1 $odns2 $odns3; do
        $fwcmd add pass tcp from any to $odns 53 setup
        $fwcmd add pass udp from any to $odns 53
        $fwcmd add pass udp from $odns 53 to any
    done
    
    # Reject setup of incoming connections from the outside.
    $fwcmd add deny log tcp from any to any in via $oif setup
    
    # Allow setup of any other TCP connection.
    $fwcmd add pass tcp from any to any setup
    
    # Allow DNS queries to your ISP DNS servers.
    for odns in $odns1 $odns2 $odns3; do
        $fwcmd add pass udp from $odns to any 53 keep-state
    done
    
    # Deny and log all the rest.
    $fwcmd add deny log ip from any to any
    
  5. This is a shell script to start pppd and natd. You may need to modify it for your modem.
    #!/bin/sh
    # Start pppd with NAT (masquerading).
    
    . /etc/rc.conf
    
    echo "Starting pppd."
    pppd connect \
    '/usr/bin/chat -v -f /root/bin/chatscript' \
    crtscts defaultroute modem \
    /dev/cuaa0 115200 &
    
    if [ "$natd_enable" = "YES" ] && [ "$natd_interface" = "ppp0" ]; then
        # Restart natd.
        killall -9 natd 2>/dev/null
        echo "Waiting for ppp0 to come up..."
        sleep 10
        while ! ( ifconfig | grep -q ppp0.*UP )
        do
            sleep 1
        done
        sleep 1
        echo "Starting natd."
        natd ${natd_flags} &
    fi
    
  6. This is an example of a chat script. You will need to modify it for your ISP. You can use a terminal program to discover your ISP's particular login prompt.
    TIMEOUT 5
    "" ATM0
    OK ATDT[YOUR_ISP_PHONE_NUMBER]
    ABORT "NO CARRIER"
    ABORT BUSY
    ABORT "NO DIALTONE"
    ABORT WAITING
    TIMEOUT 45
    CONNECT ""
    TIMEOUT 5
    "ogin:" [YOUR_ISP_USER_ID]
    "assword:" [YOUR_PASSWORD]
    

That should be it. Run the ppp script to connect to your ISP. It will take about 30 seconds to run, waiting for the ppp0 interface to come up, then it will start natd so that the FreeBSD box will route IP packets between your other computers on your network and your ISP for a shared Internet connection.

Check /var/log/security to ensure that the firewall is blocking malicious packets from the outside Internet, but that it isn't blocking packets inside your network:

Dec 11 23:44:18 lion /kernel: ipfw: 1800 Deny TCP 209.165.3.212:4488 209.165.11.101:445 in via ppp0
Dec 11 23:45:15 lion /kernel: ipfw: 1800 Deny TCP 141.156.234.216:3868 209.165.11.101:445 in via ppp0

If the firewall is interfering with your private network, temporarily disable it by running "ipfw -f flush", then permanently by editing /etc/rc.conf.


index   home