Legal:
This document is copyright © 2005 Jim Brooks.
Permission to copy, distribute, link, and reformat is given on condition that authorship is indicated.
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.