FreeBSD IP/Nat Firewall

Building a FreeBSD NAT/DHCP Gateway
-Objective:

The objective of this Howto: is to provide a user with beginning UNIX skills a 
pattern to create a FreeBSD Gateway through a Roadrunner cable connection 
(this setup has also been tested with the cable service provided by Comcast) 
that provides a DHCP and NAT interface to an internal network.  Also included 
in this Howto: are instructions to add a firewall framework with ipfw to the 
kernel and some simple firewall rules.  A full treatment of firewalls is 
reserved for a future Howto: or can be left as a exercise for the user as well.

-Requirements:

FreeBSD 4.x
ISC DHCP 3.0
Two NICs
A machine you can install and run FreeBSD 4.5 on, just about anything will do. 
Take notice that FreeBSD hasn't supported non-ATAPI CDROM drives since prior
to version 4.0 so your old 4x drive probably won't work.

-Expected Time Required:

This set of instructions should take the user about 90 minutes to complete, depending on your experience and comfort with FreeBSD.


-Installing FreeBSD 4.5: OK, you've got all your stuff put together time to slap in that FreeBSD install disc and we're off. When the CDROM starts booting you'll see an information screen containing some feedback on the process of booting the generic kernel from the CDROM. At the bottom of your screen you should see: Hit [Enter] to boot immediately, or any other key for command prompt. Booting [kernel] in 9 seconds... Go ahead and press the Enter key or wait the nine seconds. The next screen you see is the 'Kernel Configuration Menu'. Unless you have ISA NICs you can just highlight 'Skip kernel configuration and continue with installation' and press enter. If you do have ISA NICs I'll leave it as an exercise to the user to configure, you'll not need to worry about it unless the NICs are using conflicting IRQs or memory spaces. I would also take this time to ask the user to reconsider - I've seen boxes of 3COM 3C905's down at Surplus Exchange for $10 a piece. After you press Enter you'll see several screens of information as the kernel probes your system this should only take 15-30 seconds (unless you've SCSI devices in which case add another 15 seconds). After the system probe is finished you will be presented with the '/stand/sysinstall Main Menu'. Arrow down to 'Standard' and press enter. At this point you will be asked to select and configure your hard drive(s). Highlight you hard drive and press enter. Now you will be presented with the 'FDISK Partition Editor' - delete any existing partitions by highlighting them and pressing 'D'. After you've deleted all existing partitions press the 'A' key to tell FreeBSD to use the entire disk. When you have done that press the 'Q' key to indicate you are finished. Now you will be presented with a screen asking you to install a boot manager replace the MBR with a standard MBR entry. Highlight 'Standard' and press the Enter key. Now you will be presented with the 'FreeBSD Disklabel Editor'. If you have multiple disks you will see them listed at the top of the screen. Highlight the disk you wish to edit and use the command index at the bottom of the screen to issue the necessary commands. Here's where you are going to have to make some decisions on you own - a battle continues to wage over how to size your disk partitions and I choose not to enter the fray. At the bare minimum you will need a '/' slice and a 'swap' slice. For our purposes here I will suggest a separate '/var' slice around 1GB in size because as you play with your ipfw rules later you stand a very good chance of generating a huge amount of logs and we don't want that spilling over into your '/' slice. For each slice you create you will be prompted to indicate a size - in cylinders or megabytes - for each slice (a input box will popup). A default number of cylinders remaining on the disk will be in the popup, if you are comfortable with megabytes just backspace over the number and enter the desired slice size and append 'mb' the number. You will now be prompted to choose the slice type - either 'filesystem' or 'swap' - you only need to choose 'swap' when you are creating your swap partition. When you are finished press 'Q' to finish. Next you will encounter the 'Choose Distributions' screen. If adequate disk space exists select 'All'. Because we are going to be compiling a new kernel at the minimum, arrow down to '[] 6 Kern-Developer' and press the spacebar to select. You will next be prompted to install the ports system. If you've never used the FreeBSD ports system you will fall in love with it shortly after you've used it the first time. Highlight 'Yes' and press the Enter key. After you select 'Yes' for the ports system you will be returned to the 'Choose Distributions' screen. Tab down to '[OK]' and press enter. You will now be prompted to select your install media, highlight 'CD/DVD' and press Enter. The next screen is your last chance to back out, take a deep breath, highlight 'Yes' and press the Enter key. You will see several screens indicating the progress of you install, this should only take a few minutes. Finally you will see a message congratulating your choice of operating system. The next screen will be a prompt to choose to configure Ethernet or SLIP/PPP devices. Highligh 'Yes' and press EnterHighlightight the interface you will used internally, highlight 'OK' and press Enter. You will be prompted to try IPv6 and DHCP on the interface, choose 'No' for both (we'll change the dhcp part later). Now you are presented with a network configuration screen for the device. Fill in appropriate values for your internal interface, highlight 'OK' and press enter. Next you will be prompted to bring the interface up - I usually choose 'Yes' just to make sure the dang thing works. The next screen will ask you if this machine will function as a network gateway - funny they should ask - choose either value here we will address this later in the Howto. Next you will be prompted to configure the inetd super server, choose 'Yes'. The next screen prompts you to enable the inetd, again choose 'Yes', following this install asks you if you want to edit your inetd.conf file, choose 'No'. The next few screens prompt you, in this order, to setup anonymous FTP, an NFS server, an NFS Client and a default security profile (other than moderate), select 'No' for each. Following these is a confirmation screen listing your choices on the last few screens. Next you will be prompted to customize console settings, choose 'Yes' and on the following screen highlight 'Saver' press Enter. Finally, highlight 'Daemon' (because an ASCII screensaver is so cool) and highlight 'OK' then press the Enter key. The next few screens prompt you to set your time zone. Choose the appropriate values and continue. The next screen asks if you like to enable linux compatability mode, for our purposes here it isn't necessary but enabling it won't hurt anything either. Next you are asked to configure your mouse. Again it's not going to hurt anything to enable it but we're not using it in this Howto. If you chose to install the 'X' package you will next be presented with an opportunity to configure you X server. The next few screens will allow you to choose different pre-built packages to include in your install. Feel free to explore but understand you can spend a lot of time in there. The only suggestion I'll make is to install shells-> bash-2.05a After choosing the packages you want installed you will be prompted to add user accounts to the system. Add an account for yourself and be sure to enter '0' in the group field. Users in group 0 also known as the 'wheel' group are the only users allowed to execute 'su' to root on a FreeBSD system. Finally you will be prompted to enter and verify the root password, given an additional chance to set a few things the you are done. Pat yourself on the back you did a good job. Now pull that install disk out of the cdrom and choose 'Exit Install' on the last screen. ------------------------------------------------------------------------------- -Building a custom kernel: Building a custom kernel in FreeBSD is fairly straight forward and by following these instructions you stand a good chance of success. the kernel configuration file is located at /usr/src/sys/i386/conf. After install you most likely running a kernel as described by /usr/src/sys/i386/conf/GENERIC Let's go to the configuration file directory: # cd /usr/src/sys/i386/conf Just in case we break something we'll copy GENERIC to another file, the naming this new configuration file is left to the user but the standard seems to be to call it after the name of the machine in question. This machine is called ripper. # cp GENERIC MYKERNEL If you want to discover all the possible configuration options supported by FreeBSD kernel you should have noticed there is a file called LINT. It's all there (including the stuff we're about to do), my LINT has 2,619 lines of configuration options and comments compared to the 252 lines in my GENERIC file. DO NOT ATTEMPT TO BUILD A KERNEL WITH THE LINT CONFIGURATION FILE. You will most likely end up with a seriously malfunctioning system if you do. We'll need to open our new file in our favorite editor: # vi MYKERNEL Find the line that says ident GENERIC and replace GENERIC with your new kernel name, like so: ident MYKERNEL Now open a new line below the 'maxusers' line. This is where we will put our additional configuration directives. I'll be including comments from the LINT file with our options (you don't have to). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE sends # logged packets to the system logger. IPFIREWALL_VERBOSE_LIMIT # limits the number of times a matching entry can be logged. # options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #enable logging to syslogd(8) # # IPDIVERT enables the divert IP sockets, used by ``ipfw divert'' # options IPDIVERT #divert sockets now save and exit the file. We're ready to make our new kernel. Call config(8) to prepare your new kernel. Remember to replace 'MYKERNEL' with whatever you've named your kernel config file. # /usr/sbin/config MYKERNEL then # cd ../../compile/MYKERNEL compile the new kernel and any dependencies cd # make depend # make and finally to copy your new kernel to the root directory as /kernel (the old kernel will be moved to /kernel.old). # make install There you have it a brand spanking new kernel with ipfw and divert extensions. Now let's go ahead and setup some other stuff. Note: Your new kernel is ready and if you are anxious to see if it works you can go ahead and reboot your system then return to this Howto: afterwards. ------------------------------------------------------------------------------- -Configuration: Before we continue let's clean up a few things that will be necessary in our /etc/rc.conf file. rc.conf is the master startup file for FreeBSD, if you want to see more possible options check out the rc.conf file located at /etc/defaults/. Open /etc/rc.conf in your favorite editor: # vi /etc/rc.conf now let's add the following lines (some of these may already exist, if so it's OK edit them as necessary): gateway_enable="YES" natd_enable="YES" natd_interface="xl0" natd_flags="-s -u -m" firewall_enable="YES" firewall_logging_enable="YES" firewall_quiet="NO" firewall_type="open" hostname="[your hostname here]" ifconfig_xl1="inet 192.168.254.1 netmask 255.255.255.0" Where you see the ifconfig_[xl0|xl1] be sure to replace xl0 and xl1 with the correct interface names on your machine and make sure that the interface named in 'natd_enable' is your external interface (the one plugged into your modem. ------------------------------------------------------------------------------- -Installing dhcpd and dhclient: Time to set up your dhcp server on the inside interface (the NIC that is plugged into your hub or switch) and a dhcp client on the external interface (the side where your cable modem is attached). Go to /usr/ports/net/isc-dhcp3 Then type make install and away this should go. Now you've got ISC's latest dhcpd and dhcp client installed. Now let's make them useful. If you have a dynamic external IP address, the you will need to configure the dhclient piece. This is very simply. Simply open /etc/rc.conf in your favorite editor. # vi /etc/rc.conf We need to add a line like so: ifconfig_xl0="DHCP" and there you have it, next time we boot our gateway will be connected to the internet. If you have a static IP, then your line in rc.conf should look something more like this: ifconfig_xl0="inet 66.1.2.241 netmask 255.255.255.248" You'll need to make some decisions about your network before we can setup dhcpd like what subnet you are going to use and what range of IPs in that subnet you will allow the dhcpd to lease to your other boxes. I have historically used the 192.168.254.0/24 subnet so my examples here will use it. Previously I had assigned 192.168.254.1 as the IP to the internal interface, this is our gateway address. It is the IP that our internal machines will send packets to if they are destined to IPs outside of our network. There are two things to do to prepare dhcpd. First let's make sure it will start up when we start the box. # vi /usr/local/etc/rc.d/dhcpd.sh insert the following into the file #!/bin/sh /usr/sbin/dhcpd xl1 -q Make sure where I have xl1 you put the interface name of you internal interface the save the file. This tells the dhcpd to listen on xl1 and the -q tells it to be quiet about it (i.e. don't display the copyright message). Now we need to edit the configuration file. The ISC install made the dhcpd configuration for you at /etc/dhcpd.conf and it's full of things we won't address in this Howto: so let's move it to another location so we can start with a clean file (I would suggest looking at the file to see all the neat stuff you can do). # cp /usr/src/dhcp-3.0/server/dhcpd.conf /etc/dhcpd.conf Now open /etc/dhcpd.conf in your favorite text editor: # vi /etc/dhcpd.conf and insert the following lines: option domain-name "[your internal network domain name here]"; option domain-name-servers [your DNS server IP here]; ddns-updates off; ddns-update-style none; default-lease-time 600; max-lease-time 7200; authoritative; subnet 192.168.254.0 netmask 255.255.255.0 { range 192.168.254.2 192.168.254.254; option domain-name "[your internal network's domain name here]"; option domain-name-servers [your DNS server IP here]; default-lease-time 600; max-lease-time 7200; option routers 192.168.70.230; option broadcast-address 192.168.254.255; default-lease-time 600; max-lease-time 7200; } Be sure replace the place holders for at domain-name and domain-name-servers with the appropriate values for your site. If you are expecting Roadrunner or Comcast to provide dns IP values for you, we can put a dummy IP in there for now and replace it with values in /etc/resolv.conf after we make a connection to the service provider. Also be sure to replace the subnet, range, router (this will be the IP of your internal interface) and broadcast values with appropriate values for your site the save the file. Just one final thing to do and where ready to start up the dhcp server for our internal network. # touch /var/db/dhcpd.leases # chmod 644 /var/db/dhcpd.leases This is the file that the dhcp server uses to keep track of leases it has given out. Now start the server: # /usr/local/etc/rc.d/dhcpd.conf Now you need to configure /etc/rc.firewall to actually allow all of your traffic to pass through it. That's done by typing the following: /sbin/ipfw -f flush /sbin/ipfw add divert natd all from any to any via ed0 /sbin/ipfw add pass all from any to any Now you just need to reboot your machine to make all of the changes active. # shutdown -r now Congratulations, you've got a FreeBSD gateway the does NAT and DHCP service for your internal network connected to your Roadrunner or Comcast cable service. ------------------------------------------------------------------------------- -Remarks: You'll notice that we didn't create any firewall rules in this Howto. While it wasn't in our objectives I think at least a simple explaination is in order. If you remember wexplanationne to /etc/rc.conf like so: firewall_type="open" this line indicates that the kernel should load the /etc/rc.firewall script and configure the firewall as an open firewall on startup. An open firewall installs ip_divert for NAT then allows all ip conections from inside as well as outside your network. Now you are probably saying, "Thanks blather, for making me bend over for connections" and I would indicate that you've got a good feeling for the internet. If you are especially worried you can change 'open' to 'simple' like so: firewall_type="simple" and this will afford you a fair amount of protection from the wolves and you will discover is doesn't allow you to do much of anything. -Resources: http://www.freebsd.org http://www.freebsd.org/handbook/index.html http://www.freebsddiary.org