|
--- Gateway configuration --- | ![]() |
||
|---|---|---|---|---|
| 22.9.2003 | 1.7 | Alexander Kühn | ||
This documentation is not intended to give you an introduction to FreeBSD, there is more than
sufficient documentation on this subject available in various places in
the Internet (check http://www.de.freebsd.org/docproj/doc-set.html
for a start). I will just cover the points that were relevant for the
setup of our gateway as it is today but I'll try to make many links to
available documentation where appropriate.
I have replaced or removed all confidential values such as password and
hostnames so that the document does not need to be kept secret from any
of our employees or even the world. The domain was renamed to
mydomain.org in this documentation.
The install didn't went as smooth as expected as the 4.7 install disks (which was the current stable version at that time) stuck at the harddrive recognition for some unknown reason (all self compiled versions didn't have any problems though) so I was forced to install FreeBSD 3.5.1 which I then upgraded to FreeBSD 4.0 following the instructions in /usr/src/UPDATING (see section 21.3 of the FreeBSD Handbook on how to sync your sources and section A7 for which tags to use when checking out) and from 4.0 I upgraded to FreeBSD-Stable (RELENG_4).
The system, a Intel Pentium II 300MHz, came with 2 harddrives, I utilized both completely (see section 2.5.3) making the 4.3 GB SCSI drive my root fs and mount the 14,3GB IDE to /usr/local. Later I moved /usr/home, /usr/src and /usr/ports to this drive, leaving enough space for the years to come on the root fs (32% used currently) but keeping the system working even without /usr/local (except for the ports of cause). After the system was brought up-to-day which required already the install of some ports (namely cvsup(1)) I started with the configuration.
One of the first things to do was the kernel configuration, as I had to upgrade the system right after the install what can't be done without rebuilding a kernel. I started with GENERIC and created a new /usr/src/sys/i386/conf/gateway for the kernel configuration and added a KERNCONF=gateway to /etc/make.conf(5) to spare me some typing with each kernel rebuild. But what did I change? I dropped support for older architectures (i386,i486,i586) and the software fpu (MATH_EMULATE), added power management options (CPU_SUSP_HLT), lowered the SCSI delay from 15 to the minimum of 5 second (SCSI_DELAY) added netgraph support (NETGRAPH_*) in case we want to use the kernel pppd, added ipfirewall and ipfilter support (IPFIREWALL, IPDIVERT for nat, IPFILTER, IPFILTER_LOG) along with some security options (ICMP_BANDLIM, RANDOM_IP_ID) and the dummynet driver (DUMMYNET) which can help avoid some troubles when using dial-up links as we do. I dropped support for a plethora of devices that are not installed in our machine and increased the number of Berkeley packet filter devices from 1 to 4 to be able to use ntop.
This file contains only the changes to the defaults from
/etc/defaults/rc.conf. A bit initial setup (keymap, mouse,
screensaver) was already done during the install by sysinstall(8)
but as the first network card was later to be used as the pppoe card all
networking setup had to be redone too. Before configuring the pppoe
dialin some decision have to be taken as FreeBSD offers different ways
to do things. The first decision was to use either the user
pppd(8) or the kernel
pppd(8).
Although performance
considerations would suggest to use the kernel pppd I chose to use the
user pppd as the documentation available appears
to be more extensive on this one (at least in regards to the use as
pppoe driver). The performance is not really a critical point in our
situation with a relatively thin link (768kBit/s) and a relatively fast
processor (typical CPU usage is about 1-2%). We may consider to switch
if the load becomes higher because of a different link or whatsoever,
now that the configuration is done this should be pretty easy as I'm
also not using any of the user
pppd(8) specials like the -nat switch. Comments suggest the use of
mpd(8)
but I didn't investigate in this any further. There is also a port of
the NetBSD1.6 kernel
PPPoE (if_pppoe.c)
in the works, unfortunately pppoectl(8)
has not yet been ported. (Damien
Bergamini) The next decision to take was using ipfilter (
ipf(8)/
ipnat(1))
or ipfirewall (ipfw(8)/
natd(8))
for the firewall
and nat,
pppd's -nat switch would be another alternative but I prefer the one
tool for one problem approach, additionally this is unsupported by the
kernel pppd in case we ever switch. At first I chose to go with ipfw as
it seems to be easier to configure because there are predefined firewall
types in /etc/rc.firewall.
However it turned out that the predefined firewall types did not
suffice our needs and the usual way to make your own ipfw firewall is to
modify this script which is something I don't feel really comfortable
with. Additionally the logging features of ipf are more advanced and
ipf offers stateful packet filtering. As ipf is not FreeBSD specific documentation
on ipf usually applies to all plattforms ipf is used (OpenBSD, NetBSD,
Solaris,...)
I'll now explain a few (less obvious) options from rc.conf in more
detail.
/etc/natd.conf contained our portforwarding configuration, we use only the redirect_port command.
Our configuration is basically a replication of what's written in section 18.4, worth mentioning is the the selected dialmode ddial which has to be set in /etc/rc.conf. Along with the ppp.conf there is also the ppp.linkup which executes certain things each time the link has been established:
More examples on several configuration files in this directory are available here /usr/src/share/examples/ppp/.MYADDR: # we got an IP! add 0 0 HISADDR # set new default route !bg /usr/local/sbin/ddclient # update dyndns address !bg /etc/ppp/pppip-tx # run ftp script for ip update
/etc/ppp/pppip-tx hasn't changed except for the grep(1) that extract the IP of the tun0 interface:
#!/usr/local/bin/bash
LOCALIP=""
while [ -z $LOCALIP ]
do
sleep 5
LOCALIP=`/sbin/ifconfig tun0|/usr/bin/grep "inet"|/usr/bin/cut -d " " -f 2`
done
echo $LOCALIP > /tmp/pppip
/usr/bin/ftp -n -i our-server.de >/dev/null <<-EOF
user username password
cd redirection/
put /tmp/pppip pppip
chmod a+r pppip
bye
EOF
rm /tmp/pppip
This is our current crontab(1):
# make sure dyndns and out pppip get updated */30 * * * * /usr/local/sbin/ddclient && /etc/ppp/pppip-tx # update /usr/src and /usr/ports + report cvs inconsistencies + check package_db 45 20 * * 6 /usr/local/bin/cvsup /usr/local/etc/cvsup/supfile && \ /root/bin/cvsupchk -d /usr -c /usr/local/etc/cvsup/sup/src-all/checkouts.cvs:RELENG_4 && \ /root/bin/cvsupchk -d /usr -c /usr/local/etc/cvsup/sup/ports-all/checkouts.cvs:. && \ /usr/local/sbin/pkgdb --autofix * * * * * /root/bin/ifmonitor.pl
Here the links to the appropriate documentations: ddclient, cvsup(1), cvsupchk,pkgdb, ifmonitor. If any unresolved dependencies are reported you can use pkgdb -F to fix them.
This is what adduser(8) is for, take care when choosing the group, adduser may suggest a new group for each user, we use a group called 'users' (gid 1000) (edit /etc/adduser.conf to change this). adduser will not create the homedirectory, you can do this manually either by mkdir /home/username or cp -pr /etc/skel /home/username. As of the time of writing /etc/skel and /usr/local/share/skel are both empty so it would not really make a difference. After the directory has been created the ownership should be transferred to user, which can be done with chown -R username:users (or username.users for older versions) /home/username .
This can be separated into two points:
- DNS setup
The named(8) has it's configuration files in /etc/namedb namely named.conf(8) and the zone files. To add a new workstation to the subnet you'll have to modify the zonefile mydomain.zone and the 192.168.1.zone (depending on which zone you wish to modify obviously).
mydomain.zone: You can basically copy an existing entry and simply alter the IP and hostname, I've kept the hosts ordered by IP to ease finding of an unused one. The last thing to do is to update the serial which simply the date followed by the version number (which restarts every day). For example 2002120901 for the first version at the 9th December 2002.
After modifying the 192.168.1.zone file in a similar manner (don't forget the trailing dot!) we have to make the named to load the new configuration:kill -s HUP `cat /var/run/named.pid`Now we should do a quick test using nslookup(8) and look up the new host by name and by address.
- DHCP setup
The installed dhcpd(3) is the isc-dhcp3 from /usr/ports/net/isc-dhcp3 which keeps it's configuration file dhcpd.conf(5) in /usr/local/etc/ . At the top of the configuration file we have some genric settings which apply to our subnet and are explained in dhcpd-options(5):
ddns-update-style none; # this zone is static, no updates authoritative; # yes we are the ruler default-lease-time 1800; max-lease-time 3600; get-lease-hostnames true; use-host-decl-names true; option subnet-mask 255.255.255.0; option broadcast-address 192.168.1.255; option routers 192.168.1.1; option domain-name-servers 192.168.1.1; option domain-name "mydomain.org"; option netbios-name-servers files; option time-offset -3600; # CET is GMT-3600sec option time-servers time; option ntp-servers time; option smtp-server mail; option pop-server pop; option www-server gateway; option finger-server gateway; option irc-server irc.uni-stuttgart.de, irc.fu-berlin.de;This section is followed by the host definitions. All entries look very similar to another, they all look like this:
host foobar { hardware ethernet 01:23:45:67:89:ab; fixed-address 192.168.1.123; }We simply duplicate an entry and modify it to suit our needs. After adding the new host we do the usual (again I kept it ordered by IP for better usability):
kill -s HUP `cat /var/run/dhcpd.pid`After that we should be able to monitor the dhcp requests and responses using the syslogd(8).
At the end of the configuration file you can find the definition for our dynamic range:subnet 192.168.1.0 netmask 255.255.255.0 { range 192.168.1.200 192.168.1.239; }
The dialup configuration is done by creating a section in the /etc/ppp/ppp.conf and selecting this section/profile in /etc/rc.conf (ppp_profile), see 00.0100 for further details.
Besides the usual syslogd(8) which is configured in /etc/syslogd.conf(5), FreeBSD runs a number of regular cron jobs to do accounting and other security related things. Whether the output is mailed to the admin or not is specified in /etc/periodic.conf(5) (defaults in /etc/defaults/periodic.conf), for further details see periodic(8).
This subject is well covered in chapter 11 of the FreeBSD Handbook.
After the hardware has been installed (physically) you will probably have to modify the kernel configuration file and recompile the kernel (the "new" way).
First you have to differentiate between "build-in" services, which come with FreeBSD itself and third-party services installed via the ports or manually. Build-in services include sshd(8),inetd(8),ftpd(8),telnetd(8) and such (/etc/inetd.conf is good place to look) and usually only need to be enable the service in /etc/inetd.conf or rc.conf (see section 6.5). However you should always consult the corresponding manual pages for further configuring the new service (e.g. logging features).
For installing additional services the preferred install method is using the ports tree. A complete description is given in chapter 4, but a usual install session may look like this:# whereis unrarIf you can't find what you are looking for the following might help too:
unrar: /usr/ports/archivers/unrar
# cd /usr/ports/archivers/unrar
# make install clean
<build and clean output># cd /usr/ports # make search key=CMF Port: zope-cmf-1.1 Path: /usr/ports/www/zope-cmf Info: The Zope Content Management Framework (CMF) Maint: nbm@FreeBSD.org Index: www zope B-deps: python-2.2.2_2 R-deps: python-2.1.3_2 python-2.2.2_2 zope-2.5.1_2A listing of the installed applications can be obtained by looking into /var/db/pkg/, to check if they are up-to-date you can use pkg_version -v (assuming the ports tree was recently updated). The easiest way to update all out-of-date packages is probably using portupgrade -a but take care you may break things by updating dependencies but not the main app but thereby breaking the main application, portupgrade -f mainapp\* will rebuild the mainapp and should solve these kind problems (Apache is probably the most obvious candidate for such).
All ports are by default installed to /usr/local so the natural place for the configuration files would be /usr/local/etc plus eventually a subdirectory if the application has several configuration files such as apache: /usr/local/etc/apache . The start scripts are consequently placed below /usr/local/etc/rc.d/ (see section 6.5). They must be called with their complete path (e.g. /usr/local/etc/rc.d/mysql-server.sh) and the desired behaviour as parameter (start|stop). Final word, pay a visit to http://www.freshports.org/ it can do things like notifying you when a certain port was updated or give you a heads up if a dependency of a watched port has changed.. There are plenty of useful things that can be done using the ports system this article explains some of them in greater detail.
Firewall functionality is part of the base system and therefore requires no installation. The firewall start options are set in /etc/rc.conf, we use ipfilter so we leave firewall_enable disabled but set ipfilter_enable="YES". The default option file for ipfilter is set in the /etc/defaults/rc.conf to /etc/ipf.rules, no need to change that just had to create ipf.rules. Our current ruleset consists basically of the following rules:
- allow all sorts of traffic coming from our intranet to the internet
- deny all traffic from the internet to the gateway on ports below 1024 except for ssh, http, https and ident.
- allow all traffic from the internet to the gateway on higher ports than 1023 except for the ports squid is using.
- block spoofing (traffic from IP's which are not part of the Internet)
The nat options are set in /etc/rc.conf as well, we use ipnat so we leave natd_enable (actually it won't be enabled unless firewall_enable="YES") so we just set ipnat_enable="YES". The default option file is set to /etc/ipnat.rules so I used this. I do 3 different mappings and the port redirection here:
- enable the ftp proxy mode, this does basically the same as the masq_ftp module under linux.
- map outgoing tcp and udp connections to source ports in the range of 30000-65000, it is necessary to do this remapping because the different clients in our network are not aware which port another client may has already used as source port which could lead to a port collision. By remapping all connections to a certain port range the gateway's tcp stack takes care of the port usage and avoids these collisions. The port range itself is rather unconcerned, as long as we don't interfere with any already occupied ports, however it may could become interesting in case the ISP tries to track down all the people using a NAT because most NAT implementations use a specific port range for this mapping. So in theory the ISP could analyse the traffic and if 90% if the traffic is coming from this high port range this could be taken as proof that the machine on the other end of the line is doing NAT.
- map outgoing icmp to allow ping, traceroute, et al.
Then follow the redirection options, the whole thing look like this (I included only 3 examples, see ipnat(5) for details):
map tun0 192.168.1.0/24 -> 0/32 proxy port 21 ftp/tcp # allow active ftp from clients map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 30000:65000 # remap port to avoid collisions from multiple hosts map tun0 192.168.1.0/24 -> 0.0.0.0/32 proxy port 500 ipsec/udp # IPSec 4 all map tun0 192.168.1.0/24 -> 0/32 # handle ICMP, etc. rdr tun0 0/0 port 7080 -> 192.168.1.192 port 80 # map to a different port rdr tun0 0/0 port 2000-2010 -> 192.168.1.123 port 2000 # map a small range #rdr tun0 0/0 port 500 -> 192.168.1.255 port 500 udp # even broadcasting is possible, # we don't use this anymore thoughFinally just a few usage examples for ipf and ipnat:
ipf -Fa -f /etc/ipf.rules # reload all ipf rules ipfstat -i # check if everything has been loaded as expected ipnat -C -f /etc/ipnat.rules # reload the redirection and mapping rulesBoth commands support the -n parameter which can be used to test the command, this prevents the commands from actually making any ioctl calls or doing anything which would alter the currently running kernel. Also advised is to use -v (verbose switch). ipf also supports a shadowed filter list, that is a filter list that can be modified and tweaked but is not really used until you swap the active filter list against the shadowed by using ipf -s . This is useful for testing new filter lists because if you are not satisfied with the new list you can easily switch back by calling ipf -s again.
ipfstat -t # display a top(1) like traffic statisticIf you want to do some bandwidth trottling you can use dummynet(4). Dummynet provides an easy way to do some really flexible traffic shaping, these two commands limit outgoing traffic to 100kbit/s:
ipfw add pipe 1 ip from any to any via tun0 out ipfw pipe 1 config bw 100Kbit/s queue 5To remove the pipe you simply do:
ipfw delete pipe 1Pipes can become really useful in conjunction with Alternate Queueing ALTQ because when having an asymmetric link the normal behaviour of a TCP/IP stack is to equally balance up and downstream which results in a huge bandwidth waste for the downstream channel. There is an excellent article describing the problem and a possible solution using ALTQ available. Unfortunately ALTQ is still not part of the default FreeBSD, you have to fetch and apply the patch to the sources all by yourself.
This is naturally also one of the subjects that has been addressed in the FreeBSD Handbook, Chapter 20 is the place to look at. The default behaviour is to accept mail only from localhost and to relay it using the standard delivery route. I modified only the delivery method to use our 'smart' relay server mail.mydomain.org by modifying /etc/mail/sendmail.cf, changing the line DS to DSmail . Take care of keeping this modification when using mergemaster after an update!
As we have our own dedicated mailserver in the subnet we should make use of it by forwarding all mail to it using .forward(5). We can still read our mail locally by using pine and setting the following option in the .pinerc: inbox-path={mail.mydomain.org/imap/user=username}INBOX whereby username should be replaced with your loginname at the mailserver.
FreeBSD uses the standard syslogd(8) so /etc/syslog.conf(5) is good place to start looking for logfiles. Everything should reside below /var/log/, I've modified the config so that there is an all.log containing everything syslog receives. It is possible to filter for certain applications when creating logfiles an example is /var/log/ppp.log which contains solely messages from the pppd. So in case the Internet connections is having problems you can either look into /var/log/ppp.log or /var/log/all.log. Speaking of it, here is an example what it looks like when the provider is having problems:
Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: ** Too many ECHO LQR packets lost ** Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: open -> lcp Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: bundle: Terminate Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: Disconnected! Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: lcp -> logout Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: Disconnected! Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: logout -> hangup Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: Connect time: 15094 secs: 9360373 octets in, 3401578 octets out Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: 1878741 packets in, 2297267 packets out Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: total 845 bytes/sec, peak 96606 bytes/sec on Sun Jan 5 02:33:59 2003 Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: hangup -> opening Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: bundle: Establish Jan 5 06:34:01 gateway ppp[66]: tun0: Phase: deflink: Enter pause (3) for redialing. Jan 5 06:34:01 gateway ppp[66]: tun0: Chat: deflink: Reconnect try 4 of 0after that you will probably see lots of these:
Jan 5 06:50:16 gateway ppp[66]: tun0: Chat: deflink: Redial timer expired. Jan 5 06:50:16 gateway ppp[66]: tun0: Phase: deflink: Connected! Jan 5 06:50:16 gateway ppp[66]: tun0: Phase: deflink: opening -> dial Jan 5 06:50:16 gateway ppp[66]: tun0: Phase: deflink: dial -> carrier Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: deflink: Disconnected! Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: deflink: carrier -> hangup Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: deflink: Connect time: 5 secs: 0 octets in, 0 octets out Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: deflink: 1878741 packets in, 2297267 packets out Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: total 0 bytes/sec, peak 0 bytes/sec on Sun Jan 5 06:50:16 2003 Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: deflink: hangup -> opening Jan 5 06:50:21 gateway ppp[66]: tun0: Phase: deflink: Enter pause (30) for redialing.and when it's finally working again it will look something like this:
Jan 5 02:22:27 gateway ppp[66]: tun0: Chat: deflink: Redial timer expired. Jan 5 02:22:27 gateway ppp[66]: tun0: Phase: deflink: Connected! Jan 5 02:22:27 gateway ppp[66]: tun0: Phase: deflink: opening -> dial Jan 5 02:22:27 gateway ppp[66]: tun0: Phase: deflink: dial -> carrier Jan 5 02:22:28 gateway ppp[66]: tun0: Phase: Received NGM_PPPOE_ACNAME (hook "STGX12-erx") Jan 5 02:22:28 gateway ppp[66]: tun0: Phase: Received NGM_PPPOE_SESSIONID Jan 5 02:22:28 gateway ppp[66]: tun0: Phase: Received NGM_PPPOE_SUCCESS Jan 5 02:22:28 gateway ppp[66]: tun0: Phase: deflink: carrier -> login Jan 5 02:22:28 gateway ppp[66]: tun0: Phase: deflink: login -> lcp Jan 5 02:22:29 gateway ppp[66]: tun0: Warning: deflink: Reducing configured MRU from 1500 to 1492 Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: bundle: Authenticate Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: deflink: his = PAP, mine = none Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: Pap Output: username ******** Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: Pap Input: SUCCESS () Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: deflink: lcp -> open Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: bundle: Network Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: deflink: IPV6CP protocol reject closes IPV6CP ! Jan 5 02:22:29 gateway ppp[66]: tun0: Phase: deflink: IPV6CP protocol reject closes IPV6CP ! Jan 5 02:22:29 gateway ppp[66]: tun0: Command: MYADDR: add 0 0 HISADDR Jan 5 02:22:29 gateway ppp[66]: tun0: Warning: Add route failed: 0.0.0.0/0 already exists Jan 5 02:22:29 gateway ppp[66]: tun0: Command: MYADDR: !bg /etc/ppp/nat_update.sh Jan 5 02:22:29 gateway ppp[66]: tun0: Command: MYADDR: !bg /usr/local/sbin/ddclient Jan 5 02:22:29 gateway ppp[66]: tun0: Command: MYADDR: !bg /etc/ppp/pppip-tx Jan 5 02:22:32 gateway ppp[66]: tun0: Phase: deflink: IPV6CP protocol reject closes IPV6CP !The next question that arises is how do we keep the logfiles from growing ad infinitum? Well this is what newsyslog(8) and /etc/newsyslog.conf are for. It rolls over logfile at the specified interval or logfile size.
We are using afbackup for the backup. We have 10 tapes used in circle and once a month we do a full backup to tapes which will be stored at another location. So our backup plan looks like this:
Mo-Do: incremental backup to the tapeset
Fr: full backup to the tapeset
once a month: full backup to different tapes not in the tapesetThe tool itself is installed in /usr/local/afbackup and divided into a server and a client. As our backup strategy is not directly supported there are some small things you have to take care of. afbackup will try to prevent you from overwriting so called precious tapes, these are all tapes listed in /usr/local/afbackup/server/var/precious_tapes, so you have edit this file from time to time to enable the reuse of the tapes from the tapeset (labeled 1-10). When doing the monthly backup you should label the tapes before starting the backup (use server/bin/label_tape), if you do it during backup you have to use the -f flag to force the labelling although the drive is in use.
To manually start a full or incremental backup I recommend using the backup login, this will give you a simple menu from which you chose what you want to do.
To restore a file from a backup use client/bin/afrestore the usage is explained in detail in the manpage here is just a simple example:
/usr/local/afbackup/client/bin/afrestore -C /home/restore home/projects/projects/public_htmlwhich would restore home/projects/projects/public_html to /home/restore.Related links:
- The FreeBSD project
- The FreeBSD Handbook
- FreeBSD Hypertext Man Pages
- The CVS Repository
- various links to FreeBSD related resources
- PPPoE performance under Linux and BSDs
- pf - The OpenBSD Packet Filter
- ALTQ: Alternate Queueing for BSD UNIX
- Prioritizing empty TCP ACKs with pf and ALTQ
- afbackup - a client-server backup system
- FreeBSD Ports Tricks
- portupgrade - a feature-rich port designed to help you get the most out of the ports collection.
- A Newbie's Guide to Setting up PF on OpenBSD 3.x
- Installing a secure BSD System
- Setting Up Squid on FreeBSD