diff --git a/documentation/content/en/articles/freebsd-update-server/_index.adoc b/documentation/content/en/articles/freebsd-update-server/_index.adoc index fd7c066605..5c0cc4f7f2 100644 --- a/documentation/content/en/articles/freebsd-update-server/_index.adoc +++ b/documentation/content/en/articles/freebsd-update-server/_index.adoc @@ -1,641 +1,641 @@ --- title: Build Your Own FreeBSD Update Server authors: - author: Jason Helfman email: jgh@FreeBSD.org copyright: 2009-2011, 2013 Jason Helfman description: Building your own freebsd-update server allows a system administrator to perform fast updates for a number of machines from a local mirror trademarks: ["freebsd", "amd", "intel", "general"] tags: ["FreeBSD", "Update", "Server", "internal"] --- = Build Your Own FreeBSD Update Server :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/freebsd-update-server/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [WARNING] ==== The instructions in this article refer to an older version of FreeBSD and may not work properly on recent versions of the OS. With the availability of pkgbase, the freebsd-update utility is scheduled to be removed from FreeBSD in the future. When that happens, this article is either updated to reflect the new procedures or removed entirely. ==== [.abstract-title] Abstract This article describes building an internal FreeBSD Update Server. The https://github.com/freebsd/freebsd-update-build/[freebsd-update-server] is written by `{cperciva}`, Security Officer Emeritus of FreeBSD. For users that think it is convenient to update their systems against an official update server, building their own FreeBSD Update Server may help to extend its functionality by supporting manually-tweaked FreeBSD releases or by providing a local mirror that will allow faster updates for a number of machines. ''' toc::[] [[acknowledgments]] == Acknowledgments This article was subsequently printed at https://people.freebsd.org/~jgh/files/fus/BSD_03_2010_EN.pdf[BSD Magazine]. [[introduction]] == Introduction Experienced users or administrators are often responsible for several machines or environments. They understand the difficult demands and challenges of maintaining such an infrastructure. Running a FreeBSD Update Server makes it easier to deploy security and software patches to selected test machines before rolling them out to production. It also means a number of systems can be updated from the local network rather than a potentially slower Internet connection. This article outlines the steps involved in creating an internal FreeBSD Update Server. [[prerequisites]] == Prerequisites To build an internal FreeBSD Update Server some requirements should be met. * A running FreeBSD system. + [NOTE] ==== At a minimum, updates require building on a FreeBSD release greater than or equal to the target release version for distribution. ==== * A user account with at least 4 GB of available space. This will allow the creation of updates for 7.1 and 7.2, but the exact space requirements may change from version to version. * An man:ssh[1] account on a remote machine to upload distributed updates. * A web server, like extref:{handbook}network-servers[Apache, network-apache], with over half of the space required for the build. For instance, test builds for 7.1 and 7.2 consume a total amount of 4 GB, and the webserver space needed to distribute these updates is 2.6 GB. -* Basic knowledge of shell scripting with Bourne shell, man:sh[1]. +* Basic knowledge of shell scripting with POSIX(R) shell, man:sh[1]. [[Configuration]] == Configuration: Installation & Setup Download the https://github.com/freebsd/freebsd-update-build/[freebsd-update-server] software by installing package:devel/git[] and package:security/ca_root_nss[], and execute: [source,shell] .... % git clone https://github.com/freebsd/freebsd-update-build.git freebsd-update-server .... Update [.filename]#scripts/build.conf# appropriately. It is sourced during all build operations. Here is the default [.filename]#build.conf#, which should be modified to suit your environment. [.programlisting] .... # Main configuration file for FreeBSD Update builds. The # release-specific configuration data is lower down in # the scripts tree. # Location from which to fetch releases export FTP=ftp://ftp2.freebsd.org/pub/FreeBSD/releases <.> # Host platform export HOSTPLATFORM=`uname -m` # Host name to use inside jails export BUILDHOSTNAME=${HOSTPLATFORM}-builder.daemonology.net <.> # Location of SSH key export SSHKEY=/root/.ssh/id_dsa <.> # SSH account into which files are uploaded MASTERACCT=builder@wadham.daemonology.net <.> # Directory into which files are uploaded MASTERDIR=update-master.freebsd.org <.> .... Parameters for consideration would be: <.> This is the location where ISO images are downloaded from (by the `fetchiso()` subroutine of [.filename]#scripts/build.subr#). The location configured is not limited to FTP URIs. Any URI scheme supported by standard man:fetch[1] utility should work fine. Customizations to the `fetchiso()` code can be installed by copying the default [.filename]#build.subr# script to the release and architecture-specific area at [.filename]#scripts/RELEASE/ARCHITECTURE/build.subr# and applying local changes. <.> The name of the build host. This information will be displayed on updated systems when issuing: + [source,shell] .... % uname -v .... + <.> The SSH key for uploading files to the update server. A key pair can be created by typing `ssh-keygen -t dsa`. This parameter is optional; standard password authentication will be used as a fallback authentication method when `SSHKEY` is not defined. The man:ssh-keygen[1] manual page has more detailed information about SSH and the appropriate steps for creating and using one. <.> Account for uploading files to the update server. <.> Directory on the update server where files are uploaded to. The default [.filename]#build.conf# shipped with the freebsd-update-server sources is suitable for building i386 releases of FreeBSD. As an example of building an update server for other architectures, the following steps outline the configuration changes needed for amd64: [.procedure] ==== . Create a build environment for amd64: + [source,shell] .... % mkdir -p /usr/local/freebsd-update-server/scripts/7.2-RELEASE/amd64 .... . Install a [.filename]#build.conf# in the newly created build directory. The build configuration options for FreeBSD 7.2-RELEASE on amd64 should be similar to: + [.programlisting] .... # SHA256 hash of RELEASE disc1.iso image. export RELH=1ea1f6f652d7c5f5eab7ef9f8edbed50cb664b08ed761850f95f48e86cc71ef5 <.> # Components of the world, source, and kernels export WORLDPARTS="base catpages dict doc games info manpages proflibs lib32" export SOURCEPARTS="base bin contrib crypto etc games gnu include krb5 \ lib libexec release rescue sbin secure share sys tools \ ubin usbin cddl" export KERNELPARTS="generic" # EOL date export EOL=1275289200 <.> .... + <.> The man:sha256[1] hash key for the desired release, is published within the respective link:https://www.FreeBSD.org/releases/[release announcement]. <.> To generate the "End of Life" number for [.filename]#build.conf#, refer to the "Estimated EOL" posted on the link:https://www.FreeBSD.org/security/security/[FreeBSD Security Website]. The value of `EOL` can be derived from the date listed on the web site, using the man:date[1] utility, for example: + [source,shell] .... % date -j -f '%Y%m%d-%H%M%S' '20090401-000000' '+%s' .... ==== [[build]] == Building Update Code The first step is to run [.filename]#scripts/make.sh#. This will build some binaries, create directories, and generate an RSA signing key used for approving builds. In this step, a passphrase will have to be supplied for the final creation of the signing key. [source,shell] .... # sh scripts/make.sh cc -O2 -fno-strict-aliasing -pipe findstamps.c -o findstamps findstamps.c: In function 'usage': findstamps.c:45: warning: incompatible implicit declaration of built-in function 'exit' cc -O2 -fno-strict-aliasing -pipe unstamp.c -o unstamp install findstamps ../bin install unstamp ../bin rm -f findstamps unstamp Generating RSA private key, 4096 bit long modulus ................................................................................++ ...................++ e is 65537 (0x10001) Public key fingerprint: 27ef53e48dc869eea6c3136091cc6ab8589f967559824779e855d58a2294de9e Encrypting signing key for root enter aes-256-cbc encryption password: Verifying - enter aes-256-cbc encryption password: .... [NOTE] ==== Keep a note of the generated key fingerprint. This value is required in [.filename]#/etc/freebsd-update.conf# for binary updates. ==== At this point, we are ready to stage a build. [source,shell] .... # cd /usr/local/freebsd-update-server # sh scripts/init.sh amd64 7.2-RELEASE .... What follows is a sample of an _initial_ build run. [source,shell] .... # sh scripts/init.sh amd64 7.2-RELEASE Mon Aug 24 16:04:36 PDT 2009 Starting fetch for FreeBSD/amd64 7.2-RELEASE /usr/local/freebsd-update-server/work/7.2-RELE100 of 588 MB 359 kBps 00m00s Mon Aug 24 16:32:38 PDT 2009 Verifying disc1 hash for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 16:32:44 PDT 2009 Extracting components for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 16:34:05 PDT 2009 Constructing world+src image for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 16:35:57 PDT 2009 Extracting world+src for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 23:36:24 UTC 2009 Building world for FreeBSD/amd64 7.2-RELEASE Tue Aug 25 00:31:29 UTC 2009 Distributing world for FreeBSD/amd64 7.2-RELEASE Tue Aug 25 00:32:36 UTC 2009 Building and distributing kernels for FreeBSD/amd64 7.2-RELEASE Tue Aug 25 00:44:44 UTC 2009 Constructing world components for FreeBSD/amd64 7.2-RELEASE Tue Aug 25 00:44:56 UTC 2009 Distributing source for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 17:46:18 PDT 2009 Moving components into staging area for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 17:46:33 PDT 2009 Identifying extra documentation for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 17:47:13 PDT 2009 Extracting extra docs for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 17:47:18 PDT 2009 Indexing release for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 17:50:44 PDT 2009 Indexing world0 for FreeBSD/amd64 7.2-RELEASE Files built but not released: Files released but not built: Files which differ by more than contents: Files which differ between release and build: kernel|generic|/GENERIC/hptrr.ko kernel|generic|/GENERIC/kernel src|sys|/sys/conf/newvers.sh world|base|/boot/loader world|base|/boot/pxeboot world|base|/etc/mail/freebsd.cf world|base|/etc/mail/freebsd.submit.cf world|base|/etc/mail/sendmail.cf world|base|/etc/mail/submit.cf world|base|/lib/libcrypto.so.5 world|base|/usr/bin/ntpq world|base|/usr/lib/libalias.a world|base|/usr/lib/libalias_cuseeme.a world|base|/usr/lib/libalias_dummy.a world|base|/usr/lib/libalias_ftp.a ... .... Then the build of the world is performed again, with world patches. A more detailed explanation may be found in [.filename]#scripts/build.subr#. [WARNING] ==== During this second build cycle, the network time protocol daemon, man:ntpd[8], is turned off. Per `{cperciva}`, Security Officer Emeritus of FreeBSD, "the https://github.com/freebsd/freebsd-update-build/[freebsd-update-server] build code needs to identify timestamps which are stored in files so that they can be ignored when comparing builds to determine which files need to be updated. This timestamp-finding works by doing two builds 400 days apart and comparing the results." ==== [source,shell] .... Mon Aug 24 17:54:07 PDT 2009 Extracting world+src for FreeBSD/amd64 7.2-RELEASE Wed Sep 29 00:54:34 UTC 2010 Building world for FreeBSD/amd64 7.2-RELEASE Wed Sep 29 01:49:42 UTC 2010 Distributing world for FreeBSD/amd64 7.2-RELEASE Wed Sep 29 01:50:50 UTC 2010 Building and distributing kernels for FreeBSD/amd64 7.2-RELEASE Wed Sep 29 02:02:56 UTC 2010 Constructing world components for FreeBSD/amd64 7.2-RELEASE Wed Sep 29 02:03:08 UTC 2010 Distributing source for FreeBSD/amd64 7.2-RELEASE Tue Sep 28 19:04:31 PDT 2010 Moving components into staging area for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 19:04:46 PDT 2009 Extracting extra docs for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 19:04:51 PDT 2009 Indexing world1 for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 19:08:04 PDT 2009 Locating build stamps for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 19:10:19 PDT 2009 Cleaning staging area for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 19:10:19 PDT 2009 Preparing to copy files into staging area for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 19:10:20 PDT 2009 Copying data files into staging area for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 12:16:57 PDT 2009 Copying metadata files into staging area for FreeBSD/amd64 7.2-RELEASE Mon Aug 24 12:16:59 PDT 2009 Constructing metadata index and tag for FreeBSD/amd64 7.2-RELEASE Files found which include build stamps: kernel|generic|/GENERIC/hptrr.ko kernel|generic|/GENERIC/kernel world|base|/boot/loader world|base|/boot/pxeboot world|base|/etc/mail/freebsd.cf world|base|/etc/mail/freebsd.submit.cf world|base|/etc/mail/sendmail.cf world|base|/etc/mail/submit.cf world|base|/lib/libcrypto.so.5 world|base|/usr/bin/ntpq world|base|/usr/include/osreldate.h world|base|/usr/lib/libalias.a world|base|/usr/lib/libalias_cuseeme.a world|base|/usr/lib/libalias_dummy.a world|base|/usr/lib/libalias_ftp.a ... .... Finally, the build completes. [source,shell] .... Values of build stamps, excluding library archive headers: v1.2 (Aug 25 2009 00:40:36) v1.2 (Aug 25 2009 00:38:22) @()FreeBSD 7.2-RELEASE 0: Tue Aug 25 00:38:29 UTC 2009 FreeBSD 7.2-RELEASE 0: Tue Aug 25 00:38:29 UTC 2009 root@server.myhost.com:/usr/obj/usr/src/sys/GENERIC 7.2-RELEASE Mon Aug 24 23:55:25 UTC 2009 Mon Aug 24 23:55:25 UTC 2009 built by root@server.myhost.com on Tue Aug 25 00:16:15 UTC 2009 built by root@server.myhost.com on Tue Aug 25 00:16:15 UTC 2009 built by root@server.myhost.com on Tue Aug 25 00:16:15 UTC 2009 built by root@server.myhost.com on Tue Aug 25 00:16:15 UTC 2009 Mon Aug 24 23:46:47 UTC 2009 ntpq 4.2.4p5-a Mon Aug 24 23:55:53 UTC 2009 (1) * Copyright (c) 1992-2009 The FreeBSD Project. Mon Aug 24 23:46:47 UTC 2009 Mon Aug 24 23:55:40 UTC 2009 Aug 25 2009 ntpd 4.2.4p5-a Mon Aug 24 23:55:52 UTC 2009 (1) ntpdate 4.2.4p5-a Mon Aug 24 23:55:53 UTC 2009 (1) ntpdc 4.2.4p5-a Mon Aug 24 23:55:53 UTC 2009 (1) Tue Aug 25 00:21:21 UTC 2009 Tue Aug 25 00:21:21 UTC 2009 Tue Aug 25 00:21:21 UTC 2009 Mon Aug 24 23:46:47 UTC 2009 FreeBSD/amd64 7.2-RELEASE initialization build complete. Please review the list of build stamps printed above to confirm that they look sensible, then run sh -e approve.sh amd64 7.2-RELEASE to sign the release. .... Approve the build if everything is correct. More information on determining this can be found in the distributed source file named [.filename]#USAGE#. Execute [.filename]#scripts/approve.sh#, as directed. This will sign the release, and move components into a staging area suitable for uploading. [source,shell] .... # cd /usr/local/freebsd-update-server # sh scripts/mountkey.sh .... [source,shell] .... # sh -e scripts/approve.sh amd64 7.2-RELEASE Wed Aug 26 12:50:06 PDT 2009 Signing build for FreeBSD/amd64 7.2-RELEASE Wed Aug 26 12:50:06 PDT 2009 Copying files to patch source directories for FreeBSD/amd64 7.2-RELEASE Wed Aug 26 12:50:06 PDT 2009 Copying files to upload staging area for FreeBSD/amd64 7.2-RELEASE Wed Aug 26 12:50:07 PDT 2009 Updating databases for FreeBSD/amd64 7.2-RELEASE Wed Aug 26 12:50:07 PDT 2009 Cleaning staging area for FreeBSD/amd64 7.2-RELEASE .... After the approval process is complete, the upload procedure may be started. [source,shell] .... # cd /usr/local/freebsd-update-server # sh scripts/upload.sh amd64 7.2-RELEASE .... [NOTE] ==== In the event update code needs to be re-uploaded, this may be done by changing to the public distributions directory for the target release and updating attributes of the _uploaded_ file. [source,shell] .... # cd /usr/local/freebsd-update-server/pub/7.2-RELEASE/amd64 # touch -t 200801010101.01 uploaded .... ==== The uploaded files will need to be in the document root of the webserver in order for updates to be distributed. The exact configuration will vary depending on the web server used. For the Apache web server, please refer to the extref:{handbook}network-servers[Configuration of Apache servers, network-apache] section in the Handbook. Update client's `KeyPrint` and `ServerName` in [.filename]#/etc/freebsd-update.conf#, and perform updates as instructed in the extref:{handbook}cutting-edge[FreeBSD Update, updating-upgrading-freebsdupdate] section of the Handbook. [IMPORTANT] ==== In order for FreeBSD Update Server to work properly, updates for both the _current_ release and the release _one wants to upgrade to_ need to be built. This is necessary for determining the differences of files between releases. For example, when upgrading a FreeBSD system from 7.1-RELEASE to 7.2-RELEASE, updates will need to be built and uploaded to your distribution server for both versions. ==== For reference, the entire run of link:../../source/articles/freebsd-update-server/init.txt[init.sh] is attached. [[patch]] == Building a Patch Every time a link:https://www.FreeBSD.org/security/advisories/[security advisory] or link:https://www.FreeBSD.org/security/notices/[security notice] is announced, a patch update can be built. For this example, 7.1-RELEASE will be used. A couple of assumptions are made for a different release build: * Setup the correct directory structure for the initial build. * Perform an initial build for 7.1-RELEASE. Create the patch directory of the respective release under [.filename]#/usr/local/freebsd-update-server/patches/#. [source,shell] .... % mkdir -p /usr/local/freebsd-update-server/patches/7.1-RELEASE/ % cd /usr/local/freebsd-update-server/patches/7.1-RELEASE .... As an example, take the patch for man:named[8]. Read the advisory, and grab the necessary file from link:https://www.FreeBSD.org/security/advisories/[FreeBSD Security Advisories]. More information on interpreting the advisory, can be found in the extref:{handbook}security[FreeBSD Handbook, security-advisories]. In the https://security.freebsd.org/advisories/FreeBSD-SA-09:12.bind.asc[security brief], this advisory is called `SA-09:12.bind`. After downloading the file, it is required to rename the file to an appropriate patch level. It is suggested to keep this consistent with official FreeBSD patch levels, but its name may be freely chosen. For this build, let us follow the currently established practice of FreeBSD and call this `p7`. Rename the file: [source,shell] .... % cd /usr/local/freebsd-update-server/patches/7.1-RELEASE/; mv bind.patch 7-SA-09:12.bind .... [NOTE] ==== When running a patch level build, it is assumed that previous patches are in place. When a patch build is run, it will run all patches contained in the patch directory. There can be custom patches added to any build. Use the number zero, or any other number. ==== [WARNING] ==== It is up to the administrator of the FreeBSD Update Server to take appropriate measures to verify the authenticity of every patch. ==== At this point, a _diff_ is ready to be built. The software checks first to see if a [.filename]#scripts/init.sh# has been run on the respective release prior to running the diff build. [source,shell] .... # cd /usr/local/freebsd-update-server # sh scripts/diff.sh amd64 7.1-RELEASE 7 .... What follows is a sample of a _differential_ build run. [source,shell] .... # sh -e scripts/diff.sh amd64 7.1-RELEASE 7 Wed Aug 26 10:09:59 PDT 2009 Extracting world+src for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 17:10:25 UTC 2009 Building world for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 18:05:11 UTC 2009 Distributing world for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 18:06:16 UTC 2009 Building and distributing kernels for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 18:17:50 UTC 2009 Constructing world components for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 18:18:02 UTC 2009 Distributing source for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 11:19:23 PDT 2009 Moving components into staging area for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 11:19:37 PDT 2009 Extracting extra docs for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 11:19:42 PDT 2009 Indexing world0 for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 11:23:02 PDT 2009 Extracting world+src for FreeBSD/amd64 7.1-RELEASE-p7 Thu Sep 30 18:23:29 UTC 2010 Building world for FreeBSD/amd64 7.1-RELEASE-p7 Thu Sep 30 19:18:15 UTC 2010 Distributing world for FreeBSD/amd64 7.1-RELEASE-p7 Thu Sep 30 19:19:18 UTC 2010 Building and distributing kernels for FreeBSD/amd64 7.1-RELEASE-p7 Thu Sep 30 19:30:52 UTC 2010 Constructing world components for FreeBSD/amd64 7.1-RELEASE-p7 Thu Sep 30 19:31:03 UTC 2010 Distributing source for FreeBSD/amd64 7.1-RELEASE-p7 Thu Sep 30 12:32:25 PDT 2010 Moving components into staging area for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:32:39 PDT 2009 Extracting extra docs for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:32:43 PDT 2009 Indexing world1 for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:35:54 PDT 2009 Locating build stamps for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:36:58 PDT 2009 Reverting changes due to build stamps for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:37:14 PDT 2009 Cleaning staging area for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:37:14 PDT 2009 Preparing to copy files into staging area for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:37:15 PDT 2009 Copying data files into staging area for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:43:23 PDT 2009 Copying metadata files into staging area for FreeBSD/amd64 7.1-RELEASE-p7 Wed Aug 26 12:43:25 PDT 2009 Constructing metadata index and tag for FreeBSD/amd64 7.1-RELEASE-p7 ... Files found which include build stamps: kernel|generic|/GENERIC/hptrr.ko kernel|generic|/GENERIC/kernel world|base|/boot/loader world|base|/boot/pxeboot world|base|/etc/mail/freebsd.cf world|base|/etc/mail/freebsd.submit.cf world|base|/etc/mail/sendmail.cf world|base|/etc/mail/submit.cf world|base|/lib/libcrypto.so.5 world|base|/usr/bin/ntpq world|base|/usr/include/osreldate.h world|base|/usr/lib/libalias.a world|base|/usr/lib/libalias_cuseeme.a world|base|/usr/lib/libalias_dummy.a world|base|/usr/lib/libalias_ftp.a ... Values of build stamps, excluding library archive headers: v1.2 (Aug 26 2009 18:13:46) v1.2 (Aug 26 2009 18:11:44) @()FreeBSD 7.1-RELEASE-p7 0: Wed Aug 26 18:11:50 UTC 2009 FreeBSD 7.1-RELEASE-p7 0: Wed Aug 26 18:11:50 UTC 2009 root@server.myhost.com:/usr/obj/usr/src/sys/GENERIC 7.1-RELEASE-p7 Wed Aug 26 17:29:15 UTC 2009 Wed Aug 26 17:29:15 UTC 2009 built by root@server.myhost.com on Wed Aug 26 17:49:58 UTC 2009 built by root@server.myhost.com on Wed Aug 26 17:49:58 UTC 2009 built by root@server.myhost.com on Wed Aug 26 17:49:58 UTC 2009 built by root@server.myhost.com on Wed Aug 26 17:49:58 UTC 2009 Wed Aug 26 17:20:39 UTC 2009 ntpq 4.2.4p5-a Wed Aug 26 17:29:42 UTC 2009 (1) * Copyright (c) 1992-2009 The FreeBSD Project. Wed Aug 26 17:20:39 UTC 2009 Wed Aug 26 17:29:30 UTC 2009 Aug 26 2009 ntpd 4.2.4p5-a Wed Aug 26 17:29:41 UTC 2009 (1) ntpdate 4.2.4p5-a Wed Aug 26 17:29:42 UTC 2009 (1) ntpdc 4.2.4p5-a Wed Aug 26 17:29:42 UTC 2009 (1) Wed Aug 26 17:55:02 UTC 2009 Wed Aug 26 17:55:02 UTC 2009 Wed Aug 26 17:55:02 UTC 2009 Wed Aug 26 17:20:39 UTC 2009 ... .... Updates are printed, and approval is requested. [source,shell] .... New updates: kernel|generic|/GENERIC/kernel.symbols|f|0|0|0555|0|7c8dc176763f96ced0a57fc04e7c1b8d793f27e006dd13e0b499e1474ac47e10| kernel|generic|/GENERIC/kernel|f|0|0|0555|0|33197e8cf15bbbac263d17f39c153c9d489348c2c534f7ca1120a1183dec67b1| kernel|generic|/|d|0|0|0755|0|| src|base|/|d|0|0|0755|0|| src|bin|/|d|0|0|0755|0|| src|cddl|/|d|0|0|0755|0|| src|contrib|/contrib/bind9/bin/named/update.c|f|0|10000|0644|0|4d434abf0983df9bc47435670d307fa882ef4b348ed8ca90928d250f42ea0757| src|contrib|/contrib/bind9/lib/dns/openssldsa_link.c|f|0|10000|0644|0|c6805c39f3da2a06dd3f163f26c314a4692d4cd9a2d929c0acc88d736324f550| src|contrib|/contrib/bind9/lib/dns/opensslrsa_link.c|f|0|10000|0644|0|fa0f7417ee9da42cc8d0fd96ad24e7a34125e05b5ae075bd6e3238f1c022a712| ... FreeBSD/amd64 7.1-RELEASE update build complete. Please review the list of build stamps printed above and the list of updated files to confirm that they look sensible, then run sh -e approve.sh amd64 7.1-RELEASE to sign the build. .... Follow the same process as noted before for approving a build: [source,shell] .... # sh -e scripts/approve.sh amd64 7.1-RELEASE Wed Aug 26 12:50:06 PDT 2009 Signing build for FreeBSD/amd64 7.1-RELEASE Wed Aug 26 12:50:06 PDT 2009 Copying files to patch source directories for FreeBSD/amd64 7.1-RELEASE Wed Aug 26 12:50:06 PDT 2009 Copying files to upload staging area for FreeBSD/amd64 7.1-RELEASE Wed Aug 26 12:50:07 PDT 2009 Updating databases for FreeBSD/amd64 7.1-RELEASE Wed Aug 26 12:50:07 PDT 2009 Cleaning staging area for FreeBSD/amd64 7.1-RELEASE The FreeBSD/amd64 7.1-RELEASE update build has been signed and is ready to be uploaded. Remember to run sh -e umountkey.sh to unmount the decrypted key once you have finished signing all the new builds. .... After approving the build, upload the software: [source,shell] .... # cd /usr/local/freebsd-update-server # sh scripts/upload.sh amd64 7.1-RELEASE .... For reference, the entire run of link:../../source/articles/freebsd-update-server/diff.txt[diff.sh] is attached. [[tips]] == Tips * If a custom release is built using the native `make release` extref:{releng}[procedure, release-build], freebsd-update-server code will work from your release. As an example, a release without ports or documentation can be built by clearing functionality pertaining to documentation subroutines `findextradocs ()`, `addextradocs ()` and altering the download location in `fetchiso ()`, respectively, in [.filename]#scripts/build.subr#. As a last step, change the man:sha256[1] hash in [.filename]#build.conf# under your respective release and architecture and you are ready to build off your custom release. + [.programlisting] .... # Compare ${WORKDIR}/release and ${WORKDIR}/$1, identify which parts # of the world|doc subcomponent are missing from the latter, and # build a tarball out of them. findextradocs () { } # Add extra docs to ${WORKDIR}/$1 addextradocs () { } .... * Adding `-j _NUMBER_` flags to `buildworld` and `obj` targets in the [.filename]#scripts/build.subr# script may speed up processing depending on the hardware used, however it is not necessary. Using these flags in other targets is not recommended, as it may cause the build to become unreliable. + [.programlisting] .... # Build the world log "Building world" cd /usr/src && make -j 2 ${COMPATFLAGS} buildworld 2>&1 # Distribute the world log "Distributing world" cd /usr/src/release && make -j 2 obj && make ${COMPATFLAGS} release.1 release.2 2>&1 .... * Create an appropriate extref:{handbook}network-servers[DNS, network-dns] SRV record for the update server, and put others behind it with variable weights. Using this facility will provide update mirrors, however this tip is not necessary unless you wish to provide a redundant service. + [.programlisting] .... _http._tcp.update.myserver.com. IN SRV 0 2 80 host1.myserver.com. IN SRV 0 1 80 host2.myserver.com. IN SRV 0 0 80 host3.myserver.com. .... diff --git a/documentation/content/en/articles/linux-users/_index.adoc b/documentation/content/en/articles/linux-users/_index.adoc index 343b523c6b..dba46ac5fc 100644 --- a/documentation/content/en/articles/linux-users/_index.adoc +++ b/documentation/content/en/articles/linux-users/_index.adoc @@ -1,378 +1,378 @@ --- title: FreeBSD Quickstart Guide for Linux® Users authors: - author: John Ferrell copyright: 2008 The FreeBSD Documentation Project description: This document is intended to quickly familiarize intermediate to advanced Linux® users with the basics of FreeBSD. trademarks: ["freebsd", "intel", "redhat", "linux", "unix", "general"] tags: ["Quickstart", "guide", "Linux", "FreeBSD"] --- = FreeBSD Quickstart Guide for Linux(R) Users :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/linux-users/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Abstract This document is intended to quickly familiarize intermediate to advanced Linux(R) users with the basics of FreeBSD. ''' toc::[] [[intro]] == Introduction This document highlights some of the technical differences between FreeBSD and Linux(R) so that intermediate to advanced Linux(R) users can quickly familiarize themselves with the basics of FreeBSD. This document assumes that FreeBSD is already installed. Refer to the extref:{handbook}bsdinstall[Installing FreeBSD, bsdinstall] chapter of the FreeBSD Handbook for help with the installation process. [[shells]] == Default Shell Linux(R) users are often surprised to find that Bash is not the default shell in FreeBSD. In fact, Bash is not included in the default installation. -Instead, the Bourne shell-compatible man:sh[1] as the default user shell. +Instead, the POSIX(R)-compatible man:sh[1] is the default user shell. The root shell is man:tcsh[1] by default on FreeBSD 13 and earlier and man:sh[1] on FreeBSD 14 and later. man:sh[1] is very similar to Bash but with a much smaller feature-set. Generally shell scripts written for man:sh[1] will run in Bash, but the reverse is not always true. However, Bash and other shells are available for installation using the FreeBSD extref:{handbook}ports[Packages and Ports Collection, ports]. After installing another shell, use man:chsh[1] to change a user's default shell. It is recommended that the `root` user's default shell remain unchanged since shells which are not included in the base distribution are installed to [.filename]#/usr/local/bin#. In the event of a problem, the file system where [.filename]#/usr/local/bin# is located may not be mounted. In this case, `root` would not have access to its default shell, preventing `root` from logging in and fixing the problem. [[software]] == Packages and Ports: Adding Software in FreeBSD FreeBSD provides two methods for installing applications: binary packages and compiled ports. Each method has its own benefits: .Binary Packages * Faster installation as compared to compiling large applications. * Does not require an understanding of how to compile software. * No need to install a compiler. .Ports * Ability to customize installation options. * Custom patches can be applied. If an application installation does not require any customization, installing the package is sufficient. Compile the port instead whenever an application requires customization of the default options. If needed, a custom package can be compiled from ports using `make package`. A complete list of all available ports and packages can be found https://ports.freebsd.org[here]. [[packages]] === Packages Packages are pre-compiled applications, the FreeBSD equivalents of [.filename]#.deb# files on Debian/Ubuntu based systems and [.filename]#.rpm# files on Red Hat/Fedora based systems. Packages are installed using `pkg`. For example, the following command installs Apache 2.4: [source,shell] .... # pkg install apache24 .... For more information on packages refer to section 4.4 of the FreeBSD Handbook: extref:{handbook}ports[Using pkgng for Binary Package Management, pkgng-intro]. [[ports]] === Ports The FreeBSD Ports Collection is a framework of [.filename]#Makefiles# and patches specifically customized for installing applications from source on FreeBSD. When installing a port, the system will fetch the source code, apply any required patches, compile the code, and install the application and any required dependencies. The Ports Collection, sometimes referred to as the ports tree, can be installed to [.filename]#/usr/ports# using link:{handbook}mirrors/#git[Git]. Detailed instructions for installing the Ports Collection can be found in extref:{handbook}ports[section 4.5.1, ports-using-installation-methods] of the FreeBSD Handbook. To compile a port, change to the port's directory and start the build process. The following example installs Apache 2.4 from the Ports Collection: [source,shell] .... # cd /usr/ports/www/apache24 # make install clean .... A benefit of using ports to install software is the ability to customize the installation options. This example specifies that the mod_ldap module should also be installed: [source,shell] .... # cd /usr/ports/www/apache24 # make WITH_LDAP="YES" install clean .... Refer to extref:{handbook}ports[Using the Ports Collection, ports-using] for more information. [[startup]] == System Startup Many Linux(R) distributions use the SysV init system, whereas FreeBSD uses the traditional BSD-style man:init[8]. Under the BSD-style man:init[8], there are no run-levels and [.filename]#/etc/inittab# does not exist. Instead, startup is controlled by man:rc[8] scripts. At system boot, [.filename]#/etc/rc# reads [.filename]#/etc/rc.conf# and [.filename]#/etc/defaults/rc.conf# to determine which services are to be started. The specified services are then started by running the corresponding service initialization scripts located in [.filename]#/etc/rc.d/# and [.filename]#/usr/local/etc/rc.d/#. These scripts are similar to the scripts located in [.filename]#/etc/init.d/# on Linux(R) systems. The scripts found in [.filename]#/etc/rc.d/# are for applications that are part of the "base" system, such as man:cron[8], man:sshd[8], and man:syslog[3]. The scripts in [.filename]#/usr/local/etc/rc.d/# are for user-installed applications such as Apache and Squid. Since FreeBSD is developed as a complete operating system, user-installed applications are not considered to be part of the "base" system. User-installed applications are generally installed using extref:{handbook}ports[Packages or Ports, ports-using]. In order to keep them separate from the base system, user-installed applications are installed under [.filename]#/usr/local/#. Therefore, user-installed binaries reside in [.filename]#/usr/local/bin/#, configuration files are in [.filename]#/usr/local/etc/#, and so on. Services are enabled by adding an entry for the service in [.filename]#/etc/rc.conf#. The system defaults are found in [.filename]#/etc/defaults/rc.conf# and these default settings are overridden by settings in [.filename]#/etc/rc.conf#. Refer to man:rc.conf[5] for more information about the available entries. When installing additional applications, review the application's install message to determine how to enable any associated services. The following entries in [.filename]#/etc/rc.conf# enable man:sshd[8], enable Apache 2.4, and specify that Apache should be started with SSL. [.programlisting] .... # enable SSHD sshd_enable="YES" # enable Apache with SSL apache24_enable="YES" apache24_flags="-DSSL" .... Once a service has been enabled in [.filename]#/etc/rc.conf#, it can be started without rebooting the system: [source,shell] .... # service sshd start # service apache24 start .... If a service has not been enabled, it can be started from the command line using `onestart`: [source,shell] .... # service sshd onestart .... [[network]] == Network Configuration Instead of a generic _ethX_ identifier that Linux(R) uses to identify a network interface, FreeBSD uses the driver name followed by a number. The following output from man:ifconfig[8] shows two Intel(R) Pro 1000 network interfaces ([.filename]#em0# and [.filename]#em1#): [source,shell] .... % ifconfig em0: flags=8843 mtu 1500 options=b inet 10.10.10.100 netmask 0xffffff00 broadcast 10.10.10.255 ether 00:50:56:a7:70:b2 media: Ethernet autoselect (1000baseTX ) status: active em1: flags=8843 mtu 1500 options=b inet 192.168.10.222 netmask 0xffffff00 broadcast 192.168.10.255 ether 00:50:56:a7:03:2b media: Ethernet autoselect (1000baseTX ) status: active .... An IP address can be assigned to an interface using man:ifconfig[8]. To remain persistent across reboots, the IP configuration must be included in [.filename]#/etc/rc.conf#. The following [.filename]#/etc/rc.conf# entries specify the hostname, IP address, and default gateway: [.programlisting] .... hostname="server1.example.com" ifconfig_em0="inet 10.10.10.100 netmask 255.255.255.0" defaultrouter="10.10.10.1" .... Use the following entries to instead configure an interface for DHCP: [.programlisting] .... hostname="server1.example.com" ifconfig_em0="DHCP" .... [[firewall]] == Firewall FreeBSD does not use Linux(R) IPTABLES for its firewall. Instead, FreeBSD offers a choice of three kernel level firewalls: * extref:{handbook}firewalls[PF, firewalls-pf] * extref:{handbook}firewalls[IPFILTER, firewalls-ipf] * extref:{handbook}firewalls[IPFW, firewalls-ipfw] PF is developed by the OpenBSD project and ported to FreeBSD. PF was created as a replacement for IPFILTER and its syntax is similar to that of IPFILTER. PF can be paired with man:altq[4] to provide QoS features. This sample PF entry allows inbound SSH: [.programlisting] .... pass in on $ext_if inet proto tcp from any to ($ext_if) port 22 .... IPFILTER is the firewall application developed by Darren Reed. It is not specific to FreeBSD and has been ported to several operating systems including NetBSD, OpenBSD, SunOS, HP/UX, and Solaris. The IPFILTER syntax to allow inbound SSH is: [.programlisting] .... pass in on $ext_if proto tcp from any to any port = 22 .... IPFW is the firewall developed and maintained by FreeBSD. It can be paired with man:dummynet[4] to provide traffic shaping capabilities and simulate different types of network connections. The IPFW syntax to allow inbound SSH would be: [.programlisting] .... ipfw add allow tcp from any to me 22 in via $ext_if .... [[updates]] == Updating FreeBSD There are two methods for updating a FreeBSD system: from source or binary updates. Updating from source is the most involved update method, but offers the greatest amount of flexibility. The process involves synchronizing a local copy of the FreeBSD source code with the FreeBSD Git repository. Once the local source code is up-to-date, a new version of the kernel and userland can be compiled. Binary updates are similar to using `yum` or `apt-get` to update a Linux(R) system. In FreeBSD, man:freebsd-update[8] can be used fetch new binary updates and install them. These updates can be scheduled using man:cron[8]. [NOTE] ==== When using man:cron[8] to schedule updates, use `freebsd-update cron` in the man:crontab[1] to reduce the possibility of a large number of machines all pulling updates at the same time: [.programlisting] .... 0 3 * * * root /usr/sbin/freebsd-update cron .... ==== For more information on source and binary updates, refer to extref:{handbook}cutting-edge[the chapter on updating, updating-upgrading-freebsdupdate] in the FreeBSD Handbook. [[procfs]] == procfs: Gone But Not Forgotten In some Linux(R) distributions, one could look at [.filename]#/proc/sys/net/ipv4/ip_forward# to determine if IP forwarding is enabled. In FreeBSD, man:sysctl[8] is instead used to view this and other system settings. For example, use the following to determine if IP forwarding is enabled on a FreeBSD system: [source,shell] .... % sysctl net.inet.ip.forwarding net.inet.ip.forwarding: 0 .... Use `-a` to list all the system settings: [source,shell] .... % sysctl -a | more .... If an application requires procfs, add the following entry to [.filename]#/etc/fstab#: [source,shell] .... proc /proc procfs rw,noauto 0 0 .... Including `noauto` will prevent [.filename]#/proc# from being automatically mounted at boot. To mount the file system without rebooting: [source,shell] .... # mount /proc .... [[commands]] == Common Commands Some common command equivalents are as follows: [.informaltable] [cols="1,1,1", frame="none", options="header"] |=== | Linux(R) command (Red Hat/Debian) | FreeBSD equivalent | Purpose |`yum install _package_` / `apt-get install _package_` |`pkg install _package_` |Install package from remote repository |`rpm -ivh _package_` / `dpkg -i _package_` |`pkg add _package_` |Install local package |`rpm -qa` / `dpkg -l` |`pkg info` |List installed packages |`lspci` |`pciconf` |List PCI devices |`lsmod` |`kldstat` |List loaded kernel modules |`modprobe` |`kldload` / `kldunload` |Load/Unload kernel modules |`strace` |`truss` |Trace system calls |=== [[conclusion]] == Conclusion This document has provided an overview of FreeBSD. Refer to the extref:{handbook}[FreeBSD Handbook] for more in-depth coverage of these topics as well as the many topics not covered by this document. diff --git a/documentation/content/en/books/faq/_index.adoc b/documentation/content/en/books/faq/_index.adoc index a4019a0020..e421019dcb 100644 --- a/documentation/content/en/books/faq/_index.adoc +++ b/documentation/content/en/books/faq/_index.adoc @@ -1,538 +1,538 @@ --- title: Frequently Asked Questions for FreeBSD authors: - author: The FreeBSD Documentation Project copyright: 1995-2023 The FreeBSD Documentation Project description: Frequently Asked Questions for FreeBSD trademarks: ["freebsd", "ieee", "linux", "microsoft", "openbsd", "netbsd", "general"] bookOrder: 5 tags: ["FAQ", "FreeBSD FAQ"] layout: single --- = Frequently Asked Questions for FreeBSD :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :partnums: :source-highlighter: rouge :experimental: :images-path: books/faq/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Abstract This is the Frequently Asked Questions (FAQ) for FreeBSD. Every effort has been made to make this FAQ as informative as possible. ''' toc::[] [[introduction]] == Introduction Welcome to the world of FreeBSD! In this section, we provide a comprehensive overview of what FreeBSD is, its origins, goals, use cases, and the community behind it. Discover the reasons behind its name, learn how to contribute to this project, and explore the rich ecosystem of FreeBSD within the context of open-source operating systems. [[what-is-FreeBSD]] === What is FreeBSD? FreeBSD is a versatile and open-source UNIX(R)-like operating system known for its exceptional stability, security, and performance. Developed by a dedicated community of volunteers, it's based on the Berkeley Software Distribution (BSD) UNIX operating system. FreeBSD offers a powerful and customizable environment suitable for a wide range of applications, from servers and embedded systems to desktops and networking equipment. Its commitment to open source principles ensures a transparent and collaborative development process, making FreeBSD a trusted choice for those seeking a reliable and highly adaptable operating system. [[why-called-FreeBSD]] === Why is it called FreeBSD? The name "FreeBSD" stems from its roots in the Berkeley Software Distribution (BSD) UNIX operating system, renowned for its contributions to the world of open-source software. The "Free" in FreeBSD signifies its commitment to the principles of free and open-source software, which grant users the freedom to study, modify, and distribute the code. It is worth pointing out that the word "free" is being used in two ways here: one meaning "at no cost" and the other meaning "do whatever you like". [[FreeBSD-goals]] === What is the goal of the FreeBSD Project? The FreeBSD Project has a clear and unwavering goal: to provide a high-quality, open-source UNIX-like operating system that excels in terms of performance, security, and stability. It aims to offer a versatile platform suitable for a wide range of computing needs, from servers and workstations to embedded systems and beyond. FreeBSD is developed with a strong commitment to open source principles, fostering a collaborative environment where contributions from a global community of developers help shape and refine the operating system. This dedication to quality, freedom, and reliability is what sets FreeBSD apart and drives its ongoing success as an open-source project. [[FreeBSD-usecases]] === What use cases is FreeBSD good for? FreeBSD is a versatile operating system that excels in various use cases. It is particularly well-suited for server environments, where its stability and performance make it a popular choice for web hosting, databases, and networking applications. FreeBSD's robust security features also position it as a strong candidate for firewall and security appliance deployments. Beyond servers, FreeBSD can be tailored to function in specialized environments, including embedded systems and game console devices. Its adaptability, reliability, and open-source nature make FreeBSD a compelling choice for a wide range of computing needs. [[responsible]] === Who is responsible for FreeBSD? FreeBSD is a community-driven open-source project with a decentralized structure. Its development and maintenance are carried out by a global community of dedicated volunteers, developers, and organizations who collaborate to enhance and expand the operating system. The key decisions concerning the FreeBSD project, such as the overall direction of the project or who is allowed to add code to the source tree, are made by an elected Core Team of nine people. This collaborative and community-driven approach has been fundamental to FreeBSD's success and longevity as a reliable and robust UNIX-like operating system. [[how-to-contribute]] === How can I contribute to FreeBSD? What can I do to help? We accept all types of contributions: documentation, code, and even art. See the article on extref:{contributing}[Contributing to FreeBSD] for specific advice on how to do this. And thanks for the thought! [[bsd-license-restrictions]] === Does the FreeBSD license have any restrictions? FreeBSD is distributed under the https://www.FreeBSD.org/copyright/freebsd-license/[BSD License], which is known for its permissive nature. This license places very few restrictions on how you can use FreeBSD: * Do not claim that you wrote this. * Do not sue us if it breaks. * Do not remove or modify the license. The license means you are free to modify, distribute, and even sell FreeBSD without *being required to release your modifications as open source*. However, there are some minimal conditions, such as retaining the original copyright notice and disclaimers when distributing FreeBSD. Overall, the BSD License provides a high degree of freedom and flexibility, making FreeBSD an attractive choice for a wide range of applications and projects. Code in our source tree which falls under the https://www.FreeBSD.org/copyright/COPYING[GNU General Public License (GPL)] or https://www.FreeBSD.org/copyright/COPYING.LIB[GNU Library General Public License (LGPL)] comes with slightly more strings attached though, at least on the side of enforced access rather than the usual opposite. [[replace-current-OS]] === Can FreeBSD replace my current operating system? For many users and administrators, yes. But this question is not quite that cut-and-dried. FreeBSD is a powerful and versatile operating system that can replace or coexist with many other operating systems, depending on users and administrators specific needs. However, whether FreeBSD can replace your current operating system depends on factors such as your hardware, software requirements, and familiarity with FreeBSD. While it offers a robust and feature-rich alternative, it's essential to evaluate your specific use case and compatibility requirements before making the switch. If an application is only available on one operating system, that operating system cannot just be replaced. Users migrating to FreeBSD from another UNIX-like environment will find FreeBSD to be similar. Non-UNIX users, like Windows(R) users, should expect to invest some additional time learning the UNIX way of doing things. [[run-popular-software]] === Can FreeBSD run popular open source software? Yes, FreeBSD is well-suited for running popular open source software. Its compatibility with a wide range of applications and libraries makes it a favorable choice for those looking to deploy and use open source software packages. FreeBSD provides a robust and stable environment that supports various programming languages, databases, web servers, and other software commonly used in the open source community. Its ports and packages system simplifies the installation and management of such software, ensuring that users can easily access and run their favorite open source tools and applications on FreeBSD with minimal hassle. [[install-software]] === How can I install software in FreeBSD? FreeBSD offers multiple methods for software installation. One of the most common methods involves using the built-in man:pkg[8] package manager, which simplifies the process by fetching and installing pre-built binary packages. Another approach is to compile and install software from source code using the man:ports[7] collection, providing a flexible and customizable way to install software. FreeBSD's documentation offer detailed guidance on both methods, ensuring that users can easily expand their system's capabilities with the software they need. [[differences-to-other-bsds]] === What are the differences between FreeBSD, NetBSD, OpenBSD, and other open source BSD operating systems? FreeBSD, NetBSD, OpenBSD and DragonFly BSD are all part of the open source BSD family, sharing common UNIX-like foundations, but each has its own distinct focus and priorities. These differences reflect the unique goals of each project, and while they share similarities, their specific strengths and emphases cater to different use cases and preferences within the BSD ecosystem. [[freebsd-linux-distribution]] === Is FreeBSD a Linux(R) distribution? No, FreeBSD is *not* a Linux distribution. While both FreeBSD and Linux are UNIX-like operating systems and share many similarities, they have distinct kernels. Linux uses the Linux kernel, whereas FreeBSD uses the FreeBSD kernel, which is based on the Berkeley Software Distribution (BSD) UNIX operating system. FreeBSD and Linux each have their own unique development communities, release cycles, and system architectures, making them separate and independent operating systems. FreeBSD provides its own set of advantages, including a different licensing model, system design, and userland utilities compared to Linux distributions. [[run-linux-programs-freebsd]] === Is it possible to run Linux programs on FreeBSD? Yes, FreeBSD provides a compatibility layer known as _linuxulator_ (man:linux[4]), allowing many Linux programs to function on FreeBSD. This feature facilitates the execution of a broad spectrum of Linux binaries without the necessity of a dedicated Linux environment. Nevertheless, it's important to note that numerous widely used open-source software *have native FreeBSD versions available* through the ports and packages system. [[installing-freebsd]] == Installing FreeBSD The process of installing FreeBSD is the initial step toward harnessing the power of this robust open-source operating system. This section provides essential information on where to obtain FreeBSD, detailed installation instructions, and insights into concepts like FreeBSD-CURRENT and FreeBSD-STABLE. It also delves into the release and snapshot schedules, post-installation configuration tools, package search methods, and addresses common questions regarding package updates. [[where-get]] === Where can I get FreeBSD? FreeBSD is freely available for download from the link:https://www.FreeBSD.org/where/[official FreeBSD website]. Additionally, FreeBSD may also be available through various mirror sites, ensuring accessibility to users worldwide. The link:https://www.FreeBSD.org/where/[official website] is the primary and most reliable source for obtaining the latest FreeBSD releases and updates, making it the ideal starting point for a FreeBSD journey. [[install-instructions-location]] === Where are the instructions for installing FreeBSD? Installation instructions can be found at the extref:{handbook}bsdinstall/[Installing FreeBSD Chapter of the Handbook]. [[current]] === What is the FreeBSD-CURRENT concept? FreeBSD-CURRENT represents the development branch of the FreeBSD operating system. It is the most cutting-edge version of FreeBSD, where active development takes place. While it incorporates the latest features, improvements, and experimental changes, it may not always be as stable as the FreeBSD-STABLE or release versions. FreeBSD-CURRENT serves as a platform for developers and enthusiasts who want to contribute to the future of FreeBSD and stay on the leading edge of its development, even though it may occasionally undergo significant changes and *is not recommended for production systems*. [[stable]] === What is the FreeBSD-STABLE concept? The FreeBSD-STABLE branch is a more stable development branch compared to CURRENT. It contains code that is undergoing further testing and refinement before being merged into the RELEASE branch. STABLE is a good choice for those who want to track FreeBSD's development but prefer a more stable environment than CURRENT. [[release-freq]] === When are FreeBSD releases made of? The {re} releases a new major version of FreeBSD about every 18 months and a new minor version about every 8 months, on average. Release dates are announced well in advance, so that the people working on the system know when their projects need to be finished and tested. A testing period precedes each release, to ensure that the addition of new features does not compromise the stability of the release. [[snapshot-freq]] === When are FreeBSD snapshots made? FreeBSD snapshots are typically generated at regular intervals for all actively developed branches. These snapshots capture a moment in time of the FreeBSD source code and associated binary packages. The frequency of these snapshots may vary but is often done on a weekly or bi-weekly basis. These snapshots provide users with an opportunity to access the latest developments and changes in FreeBSD, helping them stay up-to-date with the project's progress. [[general-configuration-tool]] === Is there a tool to perform post-installation configuration tasks? Yes. man:bsdconfig[8] provides a nice interface to configure FreeBSD post-installation. [[search-software-freebsd]] === How can I search for software to install in FreeBSD? Searching for software to install in FreeBSD is made easy through the man:pkg[8] package manager and the `pkg search` command. Users can utilize this command to search for available packages using keywords, package names, or descriptions. This feature helps users quickly locate the software they need within the extensive FreeBSD ports and packages collection, simplifying the process of adding new applications and tools to their FreeBSD systems. [[latest-packages-freebsd]] === Why am I not getting the latest packages in my FreeBSD system? The availability of the latest packages in FreeBSD can be influenced by various factors, including the package repository's update frequency and the specific version of FreeBSD being used. It should also be added that there are two branches for the FreeBSD ports. The most updated is called `latest` and the most stable is called `quarterly`. To use the latest packages it will be necessary to configure the `latest` branch. Information on how to configure branches can be found in the link:{handbook}ports/[Ports chapter of the Handbook]. [[hardware]] == Hardware The Hardware section explores FreeBSD's compatibility with various hardware configurations. It covers a range of topics, including supported architectures, maximum RAM capacity, processor scalability, graphics card compatibility, Wi-Fi card support, and the inclusion of 10 Gigabit Ethernet network card support. Whether planning to deploy FreeBSD on servers, workstations, or specialized hardware, this section provides insights into FreeBSD's capabilities and limitations, offering information about hardware choices and configurations. [[architectures-support]] === What architectures does FreeBSD support? FreeBSD boasts a versatile range of supported architectures, making it a flexible choice for a variety of hardware environments. Its compatibility extends to architectures such as `amd64`, `arm64`, `riscv` and more. A complete list of supported architectures can be found on the link:https://www.FreeBSD.org/platforms/[platforms page]. [[ram-support]] === How much RAM does FreeBSD support? FreeBSD as an operating system generally supports as much physical memory (RAM) as the platform it is running on does. Keep in mind that different platforms have different limits for memory. For example, `amd64` platforms support up to 4TB of physical memory. [[cpu-support]] === How many processors does FreeBSD support? FreeBSD's processor support varies across different architectures. On amd64 and arm64 systems, FreeBSD can efficiently harness the power of up to 1024 processors. For powerpc-based systems, FreeBSD supports up to 256 processors, while on risc-v systems, it can effectively utilize up to 16 processors. [[graphics-cards-support]] === What graphics cards does FreeBSD support? Popular graphics vendors like Intel(R), AMD(R) or NVIDIA(R) are well-supported. A list of supported graphics cards from link:https://wiki.freebsd.org/Graphics/Intel-GPU-Matrix[Intel] and link:https://wiki.freebsd.org/Graphics/AMD-GPU-Matrix[AMD] can be found in the FreeBSD Wiki. [[wifi-support]] === What Wi-Fi cards does FreeBSD support? This is a rapidly changing area as of 2025, so it's worth checking the Hardware Compatibility List for your chosen link:https://www.freebsd.org/releases/[release]. The list of PCIe Wi-Fi devices that are known to work well on FreeBSD: * Intel chipset devices covered by man:iwlwifi[4] (high-speed as of FreeBSD 14.3) * Realtek RTL8188CE Mini PCIe The list of USB Wi-Fi devices that are known to work well on FreeBSD: * RT5370 USB dongles (supports hostap mode) * TP-Link TL-WDN3200 (RT5592, man:if_run[4]) * TP-Link TL-WN725N v2 (RTL8188EU, man:rtwn[4]) * TP-Link Archer T4U (RTL8812AU, man:rtwn[4]) * D-Link DWA-131 (RTL8192CU, man:rtwn[4]) * D-Link DWA-171 rev A1 (RTL8821AU, man:rtwn[4]) * ASUS USB-N10 NANO (RTL8188CUS, man:rtwn[4]) [[gigabit-ethernet-network-support]] === Does FreeBSD support 10 Gigabit Ethernet network cards? FreeBSD provides robust support for 10 Gigabit Ethernet network cards, making it a viable choice for high-speed networking environments. The FreeBSD kernel includes drivers for a wide range of 10 Gigabit Ethernet adapters from various manufacturers, ensuring seamless integration and optimal network performance. More information can be obtained at the link:https://wiki.freebsd.org/Networking/10GbE[FreeBSD Wiki]. [[documentation-support]] == Documentation and Support This section provides valuable resources for those seeking to deepen their knowledge of FreeBSD. It covers a range of topics, including recommended books for learning FreeBSD, avenues for commercial training and support, insights into understanding FreeBSD's internals, and where to find assistance within the FreeBSD community. [[books]] === What good books are there about FreeBSD? FreeBSD enthusiasts and learners can explore a variety of informative books dedicated to the operating system. These books cover topics ranging from FreeBSD basics to advanced system administration and development. Some notable titles include "Absolute FreeBSD: The Complete Guide To FreeBSD" by Michael W. Lucas, and the "FreeBSD Mastery series" also by Michael W. Lucas, among others. These resources offer valuable insights and knowledge to help users of all levels master FreeBSD and maximize its potential. Apart from the books, The FreeBSD Project produces a wide range of documentation, available online in the link:https://docs.FreeBSD.org/[Documentation Portal]. [[training]] === Where can I get commercial FreeBSD training and support? For those seeking professional training and support for FreeBSD, several commercial providers offer tailored services. The FreeBSD project maintains a link:https://www.freebsd.org/commercial/[list of companies] from which support can be requested. [[learn-advanced]] === How can I learn more about FreeBSD's internals? To delve deeper into the inner workings of FreeBSD, interested individuals can explore resources like "The Design And Implementation Of The FreeBSD Operating System". The extref:{arch-handbook}[FreeBSD Architecture Handbook]. is another valuable resource that provides detailed information about FreeBSD's architecture, system organization, and design principles Additionally, reviewing the FreeBSD source code, available through the FreeBSD source repository, provides valuable insights into the operating system's core components. [[help-freebsd-system]] === How can I get help in a FreeBSD system? Getting assistance within a FreeBSD system is straightforward. FreeBSD offers a wealth of built-in documentation, accessible through the man:man[1] command, which provides comprehensive information about various commands and system components. Additionally, the extref:{handbook}[FreeBSD Handbook], available both online and locally on the system, serves as a valuable resource for in-depth guidance. If specific issues arise, seeking help from the FreeBSD community via mailing lists, forums, or IRC can provide timely solutions and insights from experienced FreeBSD users and developers. [[community-questions]] == Community Questions Explore this section to discover ways to engage with the FreeBSD community. Learn about FreeBSD IRC channels for real-time discussions, web-based forums for sharing insights, and access to FreeBSD mailing lists and news groups for in-depth discussions and news updates. [[irc]] === Are there FreeBSD IRC (Internet Relay Chat) channels? Yes, most major IRC networks host a FreeBSD chat channel and the FreeBSD wiki holds an up to date link:https://wiki.freebsd.org/IRC/Channels[list of IRC channels]. Each of these channels are distinct and are not connected to each other. Since their chat styles differ, try each to find one suited to your chat style. [[forums]] === Are there any web based forums to discuss FreeBSD? The official FreeBSD forums are located at the link:https://forums.FreeBSD.org/[FreeBSD Forums homepage]. [[mailing]] === Where do I find info on the FreeBSD mailing lists? The public mailing lists can be found at the link:https://lists.freebsd.org/[FreeBSD mailing lists]. [[misc]] == Miscellaneous Questions Explore a variety of intriguing and practical queries about FreeBSD, covering topics from shell choices to system quirks and even the FreeBSD pet's name. [[minimal-sh]] === Why is /bin/sh so minimal? Why does FreeBSD not use bash or another shell? Many people need to write shell scripts which will be portable across many systems. That is why POSIX(R) specifies the shell and utility commands in great detail. -Most scripts are written in Bourne shell (man:sh[1]), and because several important programming interfaces are specified to use the Bourne shell to interpret commands. -As the Bourne shell is so often and widely used, it is important for it to be quick to start, be deterministic in its behavior, and have a small memory footprint. +Most scripts are written in POSIX shell (man:sh[1]), and several important programming interfaces are specified to use the POSIX shell to interpret commands. +As the POSIX shell is so often and widely used, it is important for it to be quick to start, be deterministic in its behavior, and have a small memory footprint. The existing implementation is our best effort at meeting as many of these requirements simultaneously as we can. To keep `/bin/sh` small, we have not provided many of the convenience features that other shells have. That is why other more featureful shells like `bash`, `scsh`, man:tcsh[1], and `zsh` are available. [[keyboard-delete-key]] === How do I use my delete key in sh and csh? -For the Bourne Shell, add the following lines to [.filename]#~/.shrc#: +For man:sh[1], add the following lines to [.filename]#~/.shrc#: [.programlisting] .... bind ^[[3~ ed-delete-next-char # for xterm .... -For the C Shell, add the following lines to [.filename]#~/.cshrc#: +For the man:csh[1], add the following lines to [.filename]#~/.cshrc#: [.programlisting] .... bindkey ^[[3~ delete-char # for xterm .... [[forgot-root-pw]] === I have forgotten the root password! What do I do? Do not panic! Restart the system, type `boot -s` at the `Boot:` prompt to enter single-user mode. At the question about the shell to use, hit kbd:[Enter] which will display a # prompt. Enter `mount -urw /` to remount the root file system read/write, then run `mount -a` to remount all the file systems. Run `passwd root` to change the `root` password then run man:exit[1] to continue booting. [TIP] ==== If you are still prompted to give the `root` password when entering the single-user mode, it means that the console has been marked as `insecure` in [.filename]#/etc/ttys#. In this case, it will be required to boot from a FreeBSD installation disk, choose the [.guimenuitem]#Live CD# or [.guimenuitem]#Shell# at the beginning of the install process and issue the commands mentioned above. Mount the specific partition in this case and then chroot to it. For example, replace `mount -urw /` with `mount /dev/ada0p1 /mnt; chroot /mnt` for a system on _ada0p1_. ==== [TIP] ==== If the root partition cannot be mounted from single-user mode, it is possible that the partitions are encrypted and it is impossible to mount them without the access keys. For more information see the section about encrypted disks in the FreeBSD extref:{handbook}disks/[Handbook, disks-encrypting]. ==== [[rcconf-readonly]] === I made a mistake in rc.conf, or another startup file, and now I cannot edit it because the file system is read-only. What should I do? Restart the system using `boot -s` at the loader prompt to enter single-user mode. When prompted for a shell pathname, press kbd:[Enter] and run `mount -urw /` to re-mount the root file system in read/write mode. You may also need to run `mount -a -t ufs` to mount the file system where your favorite editor is defined. If that editor is on a network file system, either configure the network manually before mounting the network file systems, or use an editor which resides on a local file system, such as man:ed[1]. In order to use a full screen editor such as man:vi[1] or man:emacs[1], run `export TERM=xterm` so that these editors can load the correct data from the man:termcap[5] database. After performing these steps, edit [.filename]#/etc/rc.conf# to fix the syntax error. The error message displayed immediately after the kernel boot messages should indicate the number of the line in the file which is at fault. [[free-memory-amount]] === How much free memory is available? There are a couple of kinds of "free memory". The most common is the amount of memory immediately available without reclaiming memory already in use. That is the size of the free pages queue plus some other reserved pages. This amount is exported by the `vm.stats.vm.v_free_count` man:sysctl[8], shown, for instance, by man:top[1]. Another kind of "free memory" is the total amount of virtual memory available to userland processes, which depends on the sum of swap space and usable memory. Other kinds of "free memory" descriptions are also possible, but it is relatively useless to define these, but rather it is important to make sure that the paging rate is kept low, and to avoid running out of swap space. [[timezone]] === My time is wrong, how can I change the timezone? Use man:tzsetup[8]. [[more-swap]] === FreeBSD uses a lot of swap space even when the computer has free memory left. Why? FreeBSD will proactively move entirely idle, unused pages of main memory into swap in order to make more main memory available for active use. This heavy use of swap is balanced by using the extra free memory for caching. Note that while FreeBSD is proactive in this regard, it does not arbitrarily decide to swap pages when the system is truly idle. Thus, the system will not be all paged out after leaving it idle overnight. [[top-freemem]] === Why does top show very little free memory even when I have very few programs running? The simple answer is that free memory is wasted memory. Any memory that programs do not actively allocate is used within the FreeBSD kernel as disk cache. The values shown by man:top[1] labeled as `Inact` and `Laundry` are cached data at different aging levels. This cached data means the system does not have to access a slow disk again for data it has accessed recently, thus increasing overall performance. In general, a low value shown for `Free` memory in man:top[1] is good, provided it is not _very_ low. [[daemon-name]] === What is the cute little red guy's name? He does not have one, and is just called "the BSD daemon". If you insist upon using a name, call him "beastie". Note that "beastie" is pronounced "BSD". More about the BSD daemon is available on his http://www.mckusick.com/beastie/index.html[home page]. [[use-beastie]] === Can I use the BSD daemon image? Perhaps. The BSD daemon is copyrighted by Marshall Kirk McKusick. Check his http://www.mckusick.com/beastie/mainpage/copyright.html[Statement on the Use of the BSD Daemon Figure] for detailed usage terms. In summary, the image can be used in a tasteful manner, for personal use, so long as appropriate credit is given. Before using the logo commercially, contact {mckusick} for permission. More details are available on the http://www.mckusick.com/beastie/index.html[BSD Daemon's home page]. [[bikeshed-painting]] === Why should I care what color the bikeshed is? The really, really short answer is that you should not. The somewhat longer answer is that just because you are capable of building a bikeshed does not mean you should stop others from building one just because you do not like the color they plan to paint it. This is a metaphor indicating that you need not argue about every little feature just because you know enough to do so. Some people have commented that the amount of noise generated by a change is inversely proportional to the complexity of the change. The longer and complete answer is that after a very long argument about whether man:sleep[1] should take fractional second arguments, {phk} posted a long message entitled link:http://www.bikeshed.com[A bike shed (any color will do) on greener grass...]. [[acknowledgments]] == Acknowledgments This FAQ has undergone countless revisions and improvements by a diverse group of contributors over the past decades. diff --git a/documentation/content/en/books/handbook/basics/_index.adoc b/documentation/content/en/books/handbook/basics/_index.adoc index ad0cdb7a9c..4c88eca131 100644 --- a/documentation/content/en/books/handbook/basics/_index.adoc +++ b/documentation/content/en/books/handbook/basics/_index.adoc @@ -1,1963 +1,1963 @@ --- title: Chapter 3. FreeBSD Basics part: Part I. Getting Started prev: books/handbook/bsdinstall next: books/handbook/ports description: Basic commands and functionality of the FreeBSD operating system tags: ["basics", "virtual consoles", "users", "management", "permissions", "directory structure", "disk organization", "mounting", "processes", "daemons", "shell", "editor", "manual pages", "devices"] showBookMenu: true weight: 5 params: path: "/books/handbook/basics/" --- [[basics]] = FreeBSD Basics :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 3 :partnums: :source-highlighter: rouge :experimental: :images-path: books/handbook/basics/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[basics-synopsis]] == Synopsis This chapter covers the basic commands and functionality of the FreeBSD operating system. Much of this material is relevant for any UNIX(R)-like operating system. New FreeBSD users are encouraged to read through this chapter carefully. Read this chapter to learn: * How to use and configure virtual consoles. * How to create and manage users and groups on FreeBSD. * How UNIX(R) file permissions and FreeBSD file flags work. * The default FreeBSD file system layout. * The FreeBSD disk organization. * How to mount and unmount file systems. * What processes, daemons, and signals are. * What a shell is, and how to change the default login environment. * How to use basic text editors. * What devices and device nodes are. * How to read manual pages for more information. [[consoles]] == Virtual Consoles and Terminals Unless FreeBSD has been configured to automatically start a graphical environment during startup, the system will boot into a command line login prompt, as seen in this example: [.programlisting] .... FreeBSD/amd64 (pc3.example.org) (ttyv0) login: .... The first line contains some information about the system. The `amd64` indicates that FreeBSD is running on a 64-bit x86 system. The hostname is `pc3.example.org`, and `ttyv0` indicates that this is the "system console". The second line is the login prompt. Since FreeBSD is a multiuser system, it needs some way to distinguish between different users. This is accomplished by requiring every user to log into the system before gaining access to the programs on the system. Every user has a unique "username" and a personal "password". To log into the system console, type the username that was configured during system installation, as described in crossref:bsdinstall[bsdinstall-addusers,Add Users], and press kbd:[Enter]. Then enter the password associated with the username and press kbd:[Enter]. The password is _not echoed_ for security reasons. Once the correct password is input, the message of the day (MOTD) will be displayed followed by a command prompt. Depending upon the shell that was selected when the user was created, this prompt will be a `+#+`, `$`, or `%` character. The prompt indicates that the user is now logged into the FreeBSD system console and ready to try the available commands. [[consoles-virtual]] === Virtual Consoles While the system console can be used to interact with the system, a user working from the command line at the keyboard of a FreeBSD system will typically instead log into a virtual console. This is because system messages are configured by default to display on the system console. These messages will appear over the command or file that the user is working on, making it difficult to concentrate on the work at hand. By default, FreeBSD is configured to provide several virtual consoles for inputting commands. Each virtual console has its own login prompt and shell and it is easy to switch between virtual consoles. This essentially provides the command line equivalent of having several windows open at the same time in a graphical environment. The key combinations kbd:[Alt+F1] through kbd:[Alt+F8] have been reserved by FreeBSD for switching between virtual consoles. Use kbd:[Alt+F1] to switch to the system console (`ttyv0`), kbd:[Alt+F2] to access the first virtual console (`ttyv1`), kbd:[Alt+F3] to access the second virtual console (`ttyv2`), and so on. When using Xorg as a graphical console, the combination becomes kbd:[Ctrl+Alt+F1] to return to a text-based virtual console. When switching from one console to the next, FreeBSD manages the screen output. The result is an illusion of having multiple virtual screens and keyboards that can be used to type commands for FreeBSD to run. The programs that are launched in one virtual console do not stop running when the user switches to a different virtual console. Refer to man:kbdcontrol[1], man:vidcontrol[1], man:atkbd[4], man:syscons[4], and man:vt[4] for a more technical description of the FreeBSD console and its keyboard drivers. In FreeBSD, the number of available virtual consoles is configured in this section of `/etc/ttys`: [.programlisting] .... # name getty type status comments # ttyv0 "/usr/libexec/getty Pc" xterm on secure # Virtual terminals ttyv1 "/usr/libexec/getty Pc" xterm on secure ttyv2 "/usr/libexec/getty Pc" xterm on secure ttyv3 "/usr/libexec/getty Pc" xterm on secure ttyv4 "/usr/libexec/getty Pc" xterm on secure ttyv5 "/usr/libexec/getty Pc" xterm on secure ttyv6 "/usr/libexec/getty Pc" xterm on secure ttyv7 "/usr/libexec/getty Pc" xterm on secure ttyv8 "/usr/X11R6/bin/xdm -nodaemon" xterm off secure .... To disable a virtual console, put a comment symbol (`+#+`) at the beginning of the line representing that virtual console. For example, to reduce the number of available virtual consoles from eight to four, put a `+#+` in front of the last four lines representing virtual consoles `ttyv5` through `ttyv8`. _Do not_ comment out the line for the system console `ttyv0`. Note that the last virtual console (`ttyv8`) is used to access the graphical environment if Xorg has been installed and configured as described in crossref:x11[x11,The X Window System]. For a detailed description of every column in this file and the available options for the virtual consoles, refer to man:ttys[5]. [[consoles-singleuser]] === Single User Mode The FreeBSD boot menu provides an option labelled as "Boot Single User". If this option is selected, the system will boot into a special mode known as "single user mode". This mode is typically used to repair a system that will not boot or to reset the `root` password when it is not known. While in single user mode, networking and other virtual consoles are not available. However, full `root` access to the system is available, and by default, the `root` password is not needed. For these reasons, physical access to the keyboard is needed to boot into this mode and determining who has physical access to the keyboard is something to consider when securing a FreeBSD system. The settings which control single user mode are found in this section of `/etc/ttys`: [.programlisting] .... # name getty type status comments # # If console is marked "insecure", then init will ask for the root password # when going to single-user mode. console none unknown off secure .... By default, the status is set to `secure`. This assumes that who has physical access to the keyboard is either not important or it is controlled by a physical security policy. If this setting is changed to `insecure`, the assumption is that the environment itself is insecure because anyone can access the keyboard. When this line is changed to `insecure`, FreeBSD will prompt for the `root` password when a user selects to boot into single user mode. [NOTE] ==== _Be careful when changing this setting to `insecure`!_ If the `root` password is forgotten, booting into single user mode is still possible, but may be difficult for someone who is not familiar with the FreeBSD booting process. ==== [[consoles-vidcontrol]] === Changing Console Video Modes The FreeBSD console default video mode may be adjusted to 1024x768, 1280x1024, or any other size supported by the graphics chip and monitor. To use a different video mode load the `VESA` module: [source,shell] .... # kldload vesa .... To determine which video modes are supported by the hardware, use man:vidcontrol[1]. To get a list of supported video modes issue the following: [source,shell] .... # vidcontrol -i mode .... The output of this command lists the video modes that are supported by the hardware. To select a new video mode, specify the mode using man:vidcontrol[1] as the `root` user: [source,shell] .... # vidcontrol MODE_279 .... If the new video mode is acceptable, it can be permanently set on boot by adding it to `/etc/rc.conf`: [.programlisting] .... allscreens_flags="MODE_279" .... [[users-synopsis]] == Users and Basic Account Management FreeBSD allows multiple users to use the computer at the same time. While only one user can sit in front of the screen and use the keyboard at any one time, any number of users can log in to the system through the network. To use the system, each user should have their own user account. This chapter describes: * The different types of user accounts on a FreeBSD system. * How to add, remove, and modify user accounts. * How to set limits to control the resources that users and groups are allowed to access. * How to create groups and add users as members of a group. [[users-introduction]] === Account Types Since all access to the FreeBSD system is achieved using accounts and all processes are run by users, user and account management is important. There are three main types of accounts: system accounts, user accounts, and the superuser account. [[users-system]] ==== System Accounts System accounts are used to run services such as DNS, mail, and web servers. The reason for this is security; if all services ran as the superuser, they could act without restriction. Examples of system accounts are `daemon`, `operator`, `bind`, `news`, and `www`. `nobody` is the generic unprivileged system account. However, the more services that use `nobody`, the more files and processes that user will become associated with, and hence the more privileged that user becomes. [[users-user]] ==== User Accounts User accounts are assigned to real people and are used to log in and use the system. Every person accessing the system should have a unique user account. This allows the administrator to find out who is doing what and prevents users from clobbering the settings of other users. Each user can set up their own environment to accommodate their use of the system, by configuring their default shell, editor, key bindings, and language settings. Every user account on a FreeBSD system has certain information associated with it: User name:: The user name is typed at the `login:` prompt. Each user must have a unique user name. There are a number of rules for creating valid user names which are documented in man:passwd[5]. It is recommended to use user names that consist of eight or fewer, all lower case characters in order to maintain backwards compatibility with applications. Password:: Each account has an associated password. User ID (UID):: The User ID (UID) is a number used to uniquely identify the user to the FreeBSD system. Commands that allow a user name to be specified will first convert it to the UID. It is recommended to use a UID less than 65535, since higher values may cause compatibility issues with some software. Group ID (GID):: The Group ID (GID) is a number used to uniquely identify the primary group that the user belongs to. Groups are a mechanism for controlling access to resources based on a user's GID rather than their UID. This can significantly reduce the size of some configuration files and allows users to be members of more than one group. It is recommended to use a GID of 65535 or lower as higher GIDs may break some software. Login class:: Login classes are an extension to the group mechanism that provide additional flexibility when tailoring the system to different users. Login classes are discussed further in crossref:security[users-limiting,Configuring Login Classes]. Password change time:: By default, passwords do not expire. However, password expiration can be enabled on a per-user basis, forcing some or all users to change their passwords after a certain amount of time has elapsed. Account expiration time:: By default, FreeBSD does not expire accounts. When creating accounts that need a limited lifespan, such as student accounts in a school, specify the account expiry date using man:pw[8]. After the expiry time has elapsed, the account cannot be used to log in to the system, although the account's directories and files will remain. User's full name:: The user name uniquely identifies the account to FreeBSD, but does not necessarily reflect the user's real name. Similar to a comment, this information can contain spaces, uppercase characters, and be more than 8 characters long. Home directory:: The home directory is the full path to a directory on the system. This is the user's starting directory when the user logs in. A common convention is to put all user home directories under `/home/username` or `/usr/home/username`. Each user stores their personal files and subdirectories in their own home directory. User shell:: The shell provides the user's default environment for interacting with the system. There are many different kinds of shells and experienced users will have their own preferences, which can be reflected in their account settings. [[users-superuser]] ==== The Superuser Account The superuser account, usually called `root`, is used to manage the system with no limitations on privileges. For this reason, it should not be used for day-to-day tasks like sending and receiving mail, general exploration of the system, or programming. The superuser, unlike other user accounts, can operate without limits, and misuse of the superuser account may result in spectacular disasters. User accounts are unable to destroy the operating system by mistake, so it is recommended to login as a user account and to only become the superuser when a command requires extra privilege. Always double and triple-check any commands issued as the superuser, since an extra space or missing character can mean irreparable data loss. There are several ways to gain superuser privilege. While one can log in as `root`, this is highly discouraged. Instead, use man:su[1] to become the superuser. If `-` is specified when running this command, the user will also inherit the root user's environment. The user running this command must be in the `wheel` group or else the command will fail. The user must also know the password for the `root` user account. In this example, the user only becomes superuser in order to run `make install` as this step requires superuser privilege. Once the command completes, the user types `exit` to leave the superuser account and return to the privilege of their user account. .Install a Program As the Superuser [example] ==== [source,shell] .... % configure % make % su - Password: # make install # exit % .... ==== The built-in man:su[1] framework works well for single systems or small networks with just one system administrator. An alternative is to install the package:security/sudo[] package or port. This software provides activity logging and allows the administrator to configure which users can run which commands as the superuser. [[users-modifying]] === Managing Accounts FreeBSD provides a variety of different commands to manage user accounts. The most common commands are summarized in crossref:basics[users-modifying-utilities,Utilities for Managing User Accounts], followed by some examples of their usage. See the manual page for each utility for more details and usage examples. [[users-modifying-utilities]] .Utilities for Managing User Accounts [cols="25h,~"] |=== | Command | Summary |man:adduser[8] |The recommended command-line application for adding new users. |man:rmuser[8] |The recommended command-line application for removing users. |man:chpass[1] |A flexible tool for changing user database information. |man:passwd[1] |The command-line tool to change user passwords. |man:pw[8] |A powerful and flexible tool for modifying all aspects of user accounts. |man:bsdconfig[8] |A system configuration utility with account management support. |=== [[users-adduser]] ==== Adding a user The recommended program for adding new users is man:adduser[8]. When a new user is added, this program automatically updates `/etc/passwd` and `/etc/group`. It also creates a home directory for the new user, copies in the default configuration files from `/usr/share/skel`, and can optionally mail the new user a welcome message. This utility must be run as the superuser. The man:adduser[8] utility is interactive and walks through the steps for creating a new user account. As seen in crossref:basics[users-modifying-adduser, Adding a User on FreeBSD], either input the required information or press kbd:[Return] to accept the default value shown in square brackets. In this example, the user has been invited into the `wheel` group, allowing them to become the superuser with man:su[1]. When finished, the utility will prompt to either create another user or to exit. [[users-modifying-adduser]] .Adding a User on FreeBSD [example] ==== [source,shell] .... # adduser .... The output should be similar to the following: [.programlisting] .... Username: jru Full name: J. Random User Uid (Leave empty for default): Login group [jru]: Login group is jru. Invite jru into other groups? []: wheel Login class [default]: Shell (sh csh tcsh zsh nologin) [sh]: zsh Home directory [/home/jru]: Home directory permissions (Leave empty for default): Use password-based authentication? [yes]: Use an empty password? (yes/no) [no]: Use a random password? (yes/no) [no]: Enter password: Enter password again: Lock out the account after creation? [no]: Username : jru Password : **** Full Name : J. Random User Uid : 1001 Class : Groups : jru wheel Home : /home/jru Shell : /usr/local/bin/zsh Locked : no OK? (yes/no): yes adduser: INFO: Successfully added (jru) to the user database. Add another user? (yes/no): no Goodbye! .... ==== [NOTE] ==== Since the password is not echoed when typed, be careful to not mistype the password when creating the user account. ==== [[users-rmuser]] ==== Removing a user To completely remove a user from the system, run man:rmuser[8] as the superuser. This command performs the following steps: [.procedure] ==== . Removes the user's man:crontab[1] entry, if one exists. . Removes any man:at[1] jobs belonging to the user. . Sends a SIGKILL signal to all processes owned by the user. . Removes the user from the system's local password file. . Removes the user's home directory (if it is owned by the user), including handling of symbolic links in the path to the actual home directory. . Removes the incoming mail files belonging to the user from `/var/mail`. . Removes all files owned by the user from `/tmp`, `/var/tmp`, and `/var/tmp/vi.recover`. . Removes the username from all groups to which it belongs in `/etc/group`. (If a group becomes empty and the group name is the same as the username, the group is removed; this complements man:adduser[8]'s per-user unique groups.) . Removes all message queues, shared memory segments and semaphores owned by the user. ==== man:rmuser[8] cannot be used to remove superuser accounts since that is almost always an indication of massive destruction. By default, an interactive mode is used, as shown in the following example. .`rmuser` Interactive Account Removal [example] ==== [source,shell] .... # rmuser jru .... The output should be similar to the following: [.programlisting] .... Matching password entry: jru:*:1001:1001::0:0:J. Random User:/home/jru:/usr/local/bin/zsh Is this the entry you wish to remove? y Remove user's home directory (/home/jru)? y Removing user (jru): mailspool home passwd. .... ==== [[users-chpass]] ==== Change user information Any user can use man:chpass[1] to change their default shell and personal information associated with their user account. The superuser can use this utility to change additional account information for any user. When passed no options, aside from an optional username, man:chpass[1] displays an editor containing user information. When the user exits from the editor, the user database is updated with the new information. [NOTE] ==== This utility will prompt for the user's password when exiting the editor, unless the utility is run as the superuser. ==== In crossref:basics[users-modifying-chpass-su,Using `chpass` as Superuser], the superuser has typed `chpass jru` and is now viewing the fields that can be changed for this user. If `jru` runs this command instead, only the last six fields will be displayed and available for editing. This is shown in crossref:basics[users-modifying-chpass-ru,Using `chpass` as Regular User]. [[users-modifying-chpass-su]] .Using `chpass` as Superuser [example] ==== [source,shell] .... # chpass jru .... The output should be similar to the following: [.programlisting] .... # Changing user database information for jru. Login: jru Password: * Uid [#]: 1001 Gid [# or name]: 1001 Change [month day year]: Expire [month day year]: Class: Home directory: /home/jru Shell: /usr/local/bin/zsh Full Name: J. Random User Office Location: Office Phone: Home Phone: Other information: .... ==== [[users-modifying-chpass-ru]] .Using `chpass` as Regular User [example] ==== [source,shell] .... #Changing user database information for jru. Shell: /usr/local/bin/zsh Full Name: J. Random User Office Location: Office Phone: Home Phone: Other information: .... ==== [NOTE] ==== The commands man:chfn[1] and man:chsh[1] are links to man:chpass[1], as are man:ypchpass[1], man:ypchfn[1], and man:ypchsh[1]. Since NIS support is automatic, specifying the `yp` before the command is not necessary. How to configure NIS is covered in crossref:network-servers[network-servers,Network Servers]. ==== [[users-passwd]] ==== Change user password Any user can easily change their password using man:passwd[1]. To prevent accidental or unauthorized changes, this command will prompt for the user's original password before a new password can be set: .Changing The Password [example] ==== [source,shell] .... % passwd .... The output should be similar to the following: [.programlisting] .... Changing local password for jru. Old password: New password: Retype new password: passwd: updating the database... passwd: done .... ==== The superuser can change any user's password by specifying the username when running man:passwd[1]. When this utility is run as the superuser, it will not prompt for the user's current password. This allows the password to be changed when a user cannot remember the original password. .Changing Another User's Password as the Superuser [example] ==== [source,shell] .... # passwd jru .... The output should be similar to the following: [.programlisting] .... Changing local password for jru. New password: Retype new password: passwd: updating the database... passwd: done .... ==== [NOTE] ==== As with man:chpass[1], man:yppasswd[1] is a link to man:passwd[1], so NIS works with either command. ==== [[users-pw]] ==== Create, remove, modify and display system users and groups The man:pw[8] utility can create, remove, modify, and display users and groups. It functions as a front end to the system user and group files. man:pw[8] has a very powerful set of command line options that make it suitable for use in shell scripts, but new users may find it more complicated than the other commands presented in this section. [[users-groups]] === Managing Groups A group is a list of users. A group is identified by its group name and GID. In FreeBSD, the kernel uses the UID of a process, and the list of groups it belongs to, to determine what the process is allowed to do. Most of the time, the GID of a user or process usually means the first group in the list. The group name to GID mapping is listed in `/etc/group`. This is a plain text file with four colon-delimited fields. The first field is the group name, the second is the encrypted password, the third the GID, and the fourth the comma-delimited list of members. For a complete description of the syntax, refer to man:group[5]. The superuser can modify `/etc/group` using a text editor, although editing the group file using man:vigr[8] is preferred because it can catch some common mistakes. Alternatively, man:pw[8] can be used to add and edit groups. For example, to add a group called `teamtwo` and then confirm that it exists: [WARNING] ==== Care must be taken when using the operator group, as unintended superuser-like access privileges may be granted, including but not limited to shutdown, reboot, and access to all items in `/dev` in the group. ==== .Adding a Group Using man:pw[8] [example] ==== [source,shell] .... # pw groupadd teamtwo # pw groupshow teamtwo .... The output should be similar to the following: [.programlisting] .... teamtwo:*:1100: .... ==== In this example, `1100` is the GID of `teamtwo`. Right now, `teamtwo` has no members. This command will add `jru` as a member of `teamtwo`. .Adding User Accounts to a New Group Using man:pw[8] [example] ==== [source,shell] .... # pw groupmod teamtwo -M jru # pw groupshow teamtwo .... The output should be similar to the following: [.programlisting] .... teamtwo:*:1100:jru .... ==== The argument to `-M` is a comma-delimited list of users to be added to a new (empty) group or to replace the members of an existing group. To the user, this group membership is different from (and in addition to) the user's primary group listed in the password file. This means that the user will not show up as a member when using `groupshow` with man:pw[8], but will show up when the information is queried via man:id[1] or a similar tool. When man:pw[8] is used to add a user to a group, it only manipulates `/etc/group` and does not attempt to read additional data from `/etc/passwd`. .Adding a New Member to a Group Using man:pw[8] [example] ==== [source,shell] .... # pw groupmod teamtwo -m db # pw groupshow teamtwo .... The output should be similar to the following: [.programlisting] .... teamtwo:*:1100:jru,db .... ==== In this example, the argument to `-m` is a comma-delimited list of users who are to be added to the group. Unlike the previous example, these users are appended to the group and do not replace existing users in the group. .Using man:id[1] to Determine Group Membership [example] ==== [source,shell] .... % id jru .... The output should be similar to the following: [.programlisting] .... uid=1001(jru) gid=1001(jru) groups=1001(jru), 1100(teamtwo) .... ==== In this example, `jru` is a member of the groups `jru` and `teamtwo`. For more information about this command and the format of `/etc/group`, refer to man:pw[8] and man:group[5]. [[permissions]] == Permissions In FreeBSD, every file and directory has an associated set of permissions and several utilities are available for viewing and modifying these permissions. Understanding how permissions work is necessary to make sure that users are able to access the files that they need and are unable to improperly access the files used by the operating system or owned by other users. This section discusses the traditional UNIX(R) permissions used in FreeBSD. For finer-grained file system access control, refer to crossref:security[fs-acl,Access Control Lists]. In UNIX(R), basic permissions are assigned using three types of access: read, write, and execute. These access types are used to determine file access to the file's owner, group, and others (everyone else). The read, write, and execute permissions can be represented as the letters `r`, `w`, and `x`. They can also be represented as binary numbers as each permission is either on or off (`0`). When represented as a number, the order is always read as `rwx`, where `r` has an on value of `4`, `w` has an on value of `2` and `x` has an on value of `1`. Table 4.1 summarizes the possible numeric and alphabetic possibilities. When reading the "Directory Listing" column, a `-` is used to represent a permission that is set to off. .UNIX(R) Permissions [cols="1,1,1", frame="none", options="header"] |=== | Value | Permission | Directory Listing |0 |No read, no write, no execute |`---` |1 |No read, no write, execute |`--x` |2 |No read, write, no execute |`-w-` |3 |No read, write, execute |`-wx` |4 |Read, no write, no execute |`r--` |5 |Read, no write, execute |`r-x` |6 |Read, write, no execute |`rw-` |7 |Read, write, execute |`rwx` |=== Use the `-l` argument with man:ls[1] to view a long directory listing that includes a column of information about a file's permissions for the owner, group, and everyone else. For example, `ls -l` in an arbitrary directory may show: [source,shell] .... % ls -l .... The output should be similar to the following: [.programlisting] .... total 530 -rw-r--r-- 1 root wheel 512 Sep 5 12:31 myfile -rw-r--r-- 1 root wheel 512 Sep 5 12:31 otherfile -rw-r--r-- 1 root wheel 7680 Sep 5 12:31 email.txt .... Focusing on the line for `myfile`, the first `(leftmost)` character indicates whether this file is a regular file, a directory, a special character device, a socket, or any other special pseudo-file device. In this example, the `-` indicates a regular file. The next three characters, `rw-` in this example, give the permissions for the owner of the file. The next three characters, `r--`, give the permissions for the group that the file belongs to. The final three characters, `r--`, give the permissions for the rest of the world. A dash means that the permission is turned off. In this example, the permissions are set so the owner can read and write to the file, the group can read the file, and the rest of the world can only read the file. According to the table above, the permissions for this file would be `644`, where each digit represents the three parts of the file's permission. How does the system control permissions on devices? FreeBSD treats most hardware devices as a file that programs can open, read, and write data to. These special device files are stored in `/dev/`. Directories are also treated as files. They have read, write, and execute permissions. The executable bit for a directory has a slightly different meaning than that of files. When a directory is marked executable, it means it is possible to change into that directory using man:cd[1]. This also means that it is possible to access the files within that directory, subject to the permissions on the files themselves. In order to perform a directory listing, the read permission must be set on the directory. In order to delete a file that one knows the name of, it is necessary to have write _and_ execute permissions to the directory containing the file. There are more permission bits, but they are primarily used in special circumstances such as setuid binaries and sticky directories. For more information on file permissions and how to set them, refer to man:chmod[1]. === Symbolic Permissions Symbolic permissions use characters instead of octal values to assign permissions to files or directories. Symbolic permissions use the syntax of (who) (action) (permissions), where the following values are available: [.informaltable] [cols="1,1,1", frame="none", options="header"] |=== | Option | Letter | Represents |(who) |u |User |(who) |g |Group owner |(who) |o |Other |(who) |a |All ("world") |(action) |+ |Adding permissions |(action) |- |Removing permissions |(action) |= |Explicitly set permissions |(permissions) |r |Read |(permissions) |w |Write |(permissions) |x |Execute |(permissions) |t |Sticky bit |(permissions) |s |Set UID or GID |=== These values are used with man:chmod[1], but with letters instead of numbers. For example, the following command would block both members of the group associated with _FILE_ and all other users from accessing _FILE_: [source,shell] .... % chmod go= FILE .... A comma separated list can be provided when more than one set of changes to a file must be made. For example, the following command removes the group and "world" write permission on _FILE_, and adds the execute permissions for everyone: [source,shell] .... % chmod go-w,a+x FILE .... === FreeBSD File Flags In addition to file permissions, FreeBSD supports the use of "file flags". These flags add an additional level of security and control over files, but not directories. With file flags, even `root` can be prevented from removing or altering files. File flags are modified using man:chflags[1]. For example, to enable the system undeletable flag on the file `file1`, issue the following command: [source,shell] .... # chflags sunlink file1 .... To disable the system undeletable flag, put a "no" in front of the `sunlink`: [source,shell] .... # chflags nosunlink file1 .... To view the flags of a file, use `-lo` with man:ls[1]: [source,shell] .... # ls -lo file1 .... [.programlisting] .... -rw-r--r-- 1 trhodes trhodes sunlnk 0 Mar 1 05:54 file1 .... Several file flags may only be added or removed by the `root` user. In other cases, the file owner may set its file flags. Refer to man:chflags[1] and man:chflags[2] for more information. === The setuid, setgid, and sticky Permissions Other than the permissions already discussed, there are three other specific settings that all administrators should know about. They are the `setuid`, `setgid`, and `sticky` permissions. These settings are important for some UNIX(R) operations as they provide functionality not normally granted to normal users. To understand them, the difference between the real user ID and effective user ID must be noted. The real user ID is the UID who owns or starts the process. The effective UID is the user ID the process runs as. As an example, man:passwd[1] runs with the real user ID when a user changes their password. However, in order to update the password database, the command runs as the effective ID of the `root` user. This allows users to change their passwords without seeing a `Permission Denied` error. The setuid permission may be added symbolically by adding the `s` permission for the user as in the following example: [source,shell] .... # chmod u+s suidexample.sh .... The setuid permission may also be set by prefixing a permission set with the number four (4) as shown in the following example: [source,shell] .... # chmod 4755 suidexample.sh .... The permissions on `suidexample.sh` now look like the following: [.programlisting] .... -rwsr-xr-x 1 trhodes trhodes 63 Aug 29 06:36 suidexample.sh .... Note that a `s` is now part of the permission set designated for the file owner, replacing the executable bit. This allows utilities which need elevated permissions, such as man:passwd[1]. [NOTE] ==== The `nosuid` man:mount[8] option will cause such binaries to silently fail without alerting the user. That option is not completely reliable as a `nosuid` wrapper may be able to circumvent it. ==== To view this in real time, open two terminals. On one, type `passwd` as a normal user. While it waits for a new password, check the process table and look at the user information for man:passwd[1]: In terminal A: [source,shell] .... Changing local password for trhodes Old Password: .... In terminal B: [source,shell] .... # ps aux | grep passwd .... [source,shell] .... trhodes 5232 0.0 0.2 3420 1608 0 R+ 2:10AM 0:00.00 grep passwd root 5211 0.0 0.2 3620 1724 2 I+ 2:09AM 0:00.01 passwd .... Although man:passwd[1] is run as a normal user, it is using the effective UID of `root`. The `setgid` permission performs the same function as the `setuid` permission; except that it alters the group settings. When an application or utility executes with this setting, it will be granted the permissions based on the group that owns the file, not the user who started the process. To set the `setgid` permission on a file symbolically, add the `s` permission for the group with man:chmod[1]: [source,shell] .... # chmod g+s sgidexample.sh .... Alternatively, provide man:chmod[1] with a leading two (2): [source,shell] .... # chmod 2755 sgidexample.sh .... In the following listing, notice that the `s` is now in the field designated for the group permission settings: [source,shell] .... -rwxr-sr-x 1 trhodes trhodes 44 Aug 31 01:49 sgidexample.sh .... [NOTE] ==== In these examples, even though the shell script in question is an executable file, it will not run with a different EUID or effective user ID. This is because shell scripts may not access the man:setuid[2] system calls. ==== The `setuid` and `setgid` permission bits may lower system security, by allowing for elevated permissions. The third special permission, the `sticky bit`, can strengthen the security of a system. When the `sticky bit` is set on a directory, it allows file deletion only by the file owner. This is useful to prevent file deletion in public directories, such as `/tmp`, by users who do not own the file. To utilize this permission, add the `t` mode to the file: [source,shell] .... # chmod +t /tmp .... Alternatively, prefix the permission set with a one (1): [source,shell] .... # chmod 1777 /tmp .... The `sticky bit` permission will display as a `t` at the very end of the permission set: [source,shell] .... # ls -al / | grep tmp .... [source,shell] .... drwxrwxrwt 10 root wheel 512 Aug 31 01:49 tmp .... [[dirstructure]] == Directory Structure The FreeBSD directory hierarchy is fundamental to obtaining an overall understanding of the system. The most important directory is root or, "/". This directory is the first one mounted at boot time and it contains the base system necessary to prepare the operating system for multi-user operation. The root directory also contains mount points for other file systems that are mounted during the transition to multi-user operation. A mount point is a directory where additional file systems can be grafted onto a parent file system (usually the root file system). This is further described in crossref:basics[disk-organization, Disk Organization]. Standard mount points include `/usr/`, `/var/`, `/tmp/`, `/mnt/`, and `/media/`. These directories are usually referenced to entries in `/etc/fstab`. This file is a table of various file systems and mount points and is read by the system. Most of the file systems in `/etc/fstab` are mounted automatically at boot time from the script man:rc[8] unless their entry includes `noauto`. Details can be found in crossref:basics[disks-fstab, The fstab File]. A complete description of the file system hierarchy is available in man:hier[7]. The following table provides a brief overview of the most common directories. [cols="25h,~"] |=== | Directory | Description |`/` |Root directory of the file system. |`/bin/` |User utilities fundamental to both single-user and multi-user environments. |`/boot/` |Programs and configuration files used during operating system bootstrap. |`/boot/defaults/` |Default boot configuration files. Refer to man:loader.conf[5] for details. |`/dev/` |Device special files managed by man:devfs[5] |`/etc/` |System configuration files and scripts. |`/etc/defaults/` |Default system configuration files. Refer to man:rc[8] for details. |`/etc/periodic/` |Scripts that run daily, weekly, and monthly, via man:cron[8]. Refer to man:periodic[8] for details. |`/lib/` |Critical system libraries needed for binaries in `/bin` and `/sbin` |`/libexec/` |Critical system files |`/media/` |Contains subdirectories to be used as mount points for removable media such as CDs, USB drives, and floppy disks |`/mnt/` |Empty directory commonly used by system administrators as a temporary mount point. |`/net/` |Automounted NFS shares; see man:auto_master[5] |`/proc/` |Process file system. Refer to man:procfs[5] for details. |`/rescue/` |Statically linked programs for emergency recovery as described in man:rescue[8]. |`/root/` |Home directory for the `root` account. |`/sbin/` |System programs and administration utilities fundamental to both single-user and multi-user environments. |`/tmp/` |Temporary files which are usually _not_ preserved across a system reboot. A memory-based file system is often mounted at `/tmp`. This can be automated using the tmpmfs-related variables of man:rc.conf[5] or with an entry in `/etc/fstab`; refer to man:mdmfs[8] for details. |`/usr/` |The majority of user utilities and applications. |`/usr/bin/` |Common utilities, programming tools, and applications. |`/usr/include/` |Standard C include files. |`/usr/lib/` |Archive libraries. |`/usr/libdata/` |Miscellaneous utility data files. |`/usr/libexec/` |System daemons and system utilities executed by other programs. |`/usr/local/` |Local executables and libraries. Also used as the default destination for the FreeBSD ports framework. Within `/usr/local`, the general layout sketched out by man:hier[7] for `/usr` should be used. Exceptions are the man directory, which is directly under `/usr/local` rather than under `/usr/local/share`, and the ports documentation is in `share/doc/port`. |`/usr/ports/` |The FreeBSD Ports Collection (optional). |`/usr/sbin/` |System daemons and system utilities executed by users. |`/usr/share/` |Architecture-independent files. |`/usr/src/` |BSD and/or local source files. |`/var/` |Multi-purpose log, temporary, transient, and spool files. |`/var/log/` |Miscellaneous system log files. |`/var/tmp/` |Temporary files which are usually preserved across a system reboot. |=== [[disk-organization]] == Disk Organization The smallest unit of organization that FreeBSD uses to find files is the filename. Filenames are case-sensitive, which means that `readme.txt` and `README.TXT` are two separate files. FreeBSD does not use the extension of a file to determine whether the file is a program, document, or some other form of data. Files are stored in directories. A directory may contain no files, or it may contain many hundreds of files. A directory can also contain other directories, allowing a hierarchy of directories within one another in order to organize data. Files and directories are referenced by giving the file or directory name, followed by a forward slash, `/`, followed by any other directory names that are necessary. For example, if the directory `foo` contains a directory `bar` which contains the file `readme.txt`, the full name, or _path_, to the file is `foo/bar/readme.txt`. Note that this is different from Windows(R) which uses `\` to separate file and directory names. FreeBSD does not use drive letters, or other drive names in the path. For example, one would not type `c:\foo\bar\readme.txt` on FreeBSD. [[disks-file-systems]] === File systems Directories and files are stored in a file system. Each file system contains exactly one directory at the very top level, called the _root directory_ for that file system. This root directory can contain other directories. One file system is designated the _root file system_ or `/`. Every other file system is _mounted_ under the root file system. No matter how many disks are on the FreeBSD system, every directory appears to be part of the same disk. Consider three file systems, called `A`, `B`, and `C`. Each file system has one root directory, which contains two other directories, called `A1`, `A2` (and likewise `B1`, `B2` and `C1`, `C2`). Call `A` the root file system. If man:ls[1] is used to view the contents of this directory, it will show two subdirectories, `A1` and `A2`. The directory tree looks like this: image::example-dir1.png[Directory tree with the root directory and two subdirectories, A1 and A2] A file system must be mounted on to a directory in another file system. When mounting file system `B` on to the directory `A1`, the root directory of `B` replaces `A1`, and the directories in `B` appear accordingly: image::example-dir2.png[Directory tree with the root directory and two subdirectories, A1 and A2. And more subdirectories, B1 and B2 hanging from A1] Any files that are in the `B1` or `B2` directories can be reached with the path `/A1/B1` or `/A1/B2` as necessary. Any files that were in `/A1` have been temporarily hidden. They will reappear if `B` is _unmounted_ from `A`. If `B` had been mounted on `A2` then the diagram would look like this: image::example-dir3.png[Directory tree with the root directory and two subdirectories, A1 and A2. And more subdirectories, B1 and B2 hanging from A2] and the paths would be `/A2/B1` and `/A2/B2` respectively. File systems can be mounted on top of one another. Continuing the last example, the `C` file system could be mounted on top of the `B1` directory in the `B` file system, leading to this arrangement: image::example-dir4.png[A complex directory tree. With different subdirectories hanging from root.] Or `C` could be mounted directly on to the `A` file system, under the `A1` directory: image::example-dir5.png[A complex directory tree. With different subdirectories hanging from root.] It is entirely possible to have one large root file system, and not need to create any others. There are some drawbacks to this approach, and one advantage. .Benefits of Multiple File Systems * Different file systems can have different _mount options_. For example, the root file system can be mounted read-only, making it impossible for users to inadvertently delete or edit a critical file. Separating user-writable file systems, such as `/home`, from other file systems allows them to be mounted _nosuid_. This option prevents the _suid_/_guid_ bits on executables stored on the file system from taking effect, possibly improving security. * FreeBSD automatically optimizes the layout of files on a file system, depending on how the file system is being used. So a file system that contains many small files that are written frequently will have a different optimization to one that contains fewer, larger files. By having one big file system this optimization breaks down. * FreeBSD's file systems are robust if power is lost. However, a power loss at a critical point could still damage the structure of the file system. By splitting data over multiple file systems it is more likely that the system will still come up, making it easier to restore from backup as necessary. .Benefit of a Single File System * File systems are a fixed size. When creating a file system during the FreeBSD installation and giving it a specific size, it may be that one wants to make the partition bigger. This is not easily accomplished without backing up, recreating the file system with the new size, and then restoring the backed up data. + [IMPORTANT] ==== FreeBSD features the man:growfs[8] command, which makes it possible to increase the size of file system on the fly, removing this limitation. A file system can only be expanded into free space in the partition in which it resides. If there is space after the partition, the partition can be expanded with man:gpart[8]. If the partition is the last one on a virtual disk, and the disk is expanded, the partition can then be expanded. ==== [[disks-partitions]] === Disk partitions File systems are contained in _partitions_. Disks are divided into partitions using one of several partitioning schemes; see crossref:bsdinstall[bsdinstall-part-manual, Manual Partitioning]. The newer scheme is GPT; older BIOS-based computers use MBR. GPT supports division of a disk into partitions with a size, offset, and type. It supports a large number of partitions and partition types, and is recommended whenever its use is possible. GPT partitions use the disk name with a suffix, where the suffix is `p1` for the first partition, `p2` for the second, and so on. MBR, however, supports only a small number of partitions. The MBR partitions are known in FreeBSD as `slices`. Slices may be used for different operating systems. FreeBSD slices are subdivided into partitions using BSD labels (see man:bsdlabel[8]). Slice numbers follow the device name, prefixed with an `s`, starting at 1. So "da0__s1__" is the first slice on the first SCSI drive. There can only be four physical slices on a disk, but there can be logical slices inside physical slices of the appropriate type. These extended slices are numbered starting at 5, so "ada0__s5__" is the first extended slice on the first SATA disk. These devices are used by file systems that expect to occupy a slice. Each GPT or BSD partition can contain only one file system, which means that file systems are often described by either their typical mount point in the file system hierarchy, or the name of the partition they are contained in. FreeBSD also uses disk space for _swap space_ to provide _virtual memory_. This allows the computer to behave as though it has much more memory than it actually does. When FreeBSD runs out of memory, it moves some of the data that is not currently being used to the swap space, and moves it back in (moving something else out) when it needs it. This is called _paging_. Some BSD partitions have certain conventions associated with them. [cols="25h,~"] |=== | Partition | Convention |`a` |Normally contains the root file system. |`b` |Normally contains swap space. |`c` |Normally the same size as the enclosing slice. This allows utilities that need to work on the entire slice, such as a bad block scanner, to work on the `c` partition. A file system would not normally be created on this partition. |`d` |Partition `d` used to have a special meaning associated with it, although that is now gone and `d` may work as any normal partition. |=== Slices and "dangerously dedicated" physical drives contain BSD partitions, which are represented as letters from `a` to `h`. This letter is appended to the device name, so "da0__a__" is the `a` partition on the first `da` drive, which is "dangerously dedicated". "ada1s3__e__" is the fifth partition in the third slice of the second SATA disk drive. Finally, each disk on the system is identified. A disk name starts with a code that indicates the type of disk, and then a number, indicating which disk it is. Unlike partitions and slices, disk numbering starts at 0. Common codes are listed in crossref:basics[disks-naming,Disk Device Names]. When referring to a partition in a slice, include the disk name, `s`, the slice number, and then the partition letter. Examples are shown in crossref:basics[basics-disk-slice-part,Sample Disk, Slice, and Partition Names]. GPT partitions include the disk name, `p`, and then the partition number. crossref:basics[basics-concept-disk-model,Conceptual Model of a Disk] shows a conceptual model of a disk layout using MBR slices. When installing FreeBSD, configure the disk slices if using MBR, and create partitions within the slice to be used for FreeBSD. If using GPT, configure partitions for each file system. In either case, create a file system or swap space in each partition, and decide where each file system will be mounted. See man:gpart[8] for information on manipulating partitions. [[disks-naming]] .Disk Device Names [cols="1,1", frame="none", options="header"] |=== | Drive Type | Drive Device Name |SATA and IDE hard drives |`ada` |SCSI hard drives and USB storage devices |`da` |NVMe storage |`nvd` or `nda` |SATA and IDE CD-ROM drives |`cd` |SCSI CD-ROM drives |`cd` |Floppy drives |`fd` |SCSI tape drives |`sa` |RAID drives |Examples include `aacd` for Adaptec(R) AdvancedRAID, `mlxd` and `mlyd` for Mylex(R), `amrd` for AMI MegaRAID(R), `idad` for Compaq Smart RAID, `twed` for 3ware(R) RAID. |=== [example] ==== [[basics-disk-slice-part]] .Sample Disk, Slice, and Partition Names [.informaltable] [cols="1,1", frame="none", options="header"] |=== | Name | Meaning |`ada0s1a` |The first partition (`a`) on the first slice (`s1`) on the first SATA disk (`ada0`). |`da1s2e` |The fifth partition (`e`) on the second slice (`s2`) on the second SCSI disk (`da1`). |=== ==== [[basics-concept-disk-model]] .Conceptual Model of a Disk [example] ==== This diagram shows FreeBSD's view of the first SATA disk attached to the system. Assume that the disk is 250 GB in size, and contains an 80 GB slice and a 170 GB slice (MS-DOS(R) partitions). The first slice contains a Windows(R) NTFS file system, `C:`, and the second slice contains a FreeBSD installation. This example FreeBSD installation has four data partitions and a swap partition. The four partitions each hold a file system. Partition `a` is used for the root file system, `d` for `/var/`, `e` for `/tmp/`, and `f` for `/usr/`. Partition letter `c` refers to the entire slice, and so is not used for ordinary partitions. image::disk-layout.png[Layout of a shared drive between Windows and FreeBSD] ==== [[mount-unmount]] == Mounting and Unmounting File Systems The file system is best visualized as a tree, rooted, as it were, at `/`. `/dev`, `/usr`, and the other directories in the root directory are branches, which may have their own branches, such as `/usr/local`, and so on. There are various reasons to house some of these directories on separate file systems. `/var` contains the directories `log/`, `spool/`, and various types of temporary files, and as such, may get filled up. Filling up the root file system is not a good idea, so splitting `/var` from `/` is often favorable. Another common reason to contain certain directory trees on other file systems is if they are to be housed on separate physical disks, or are separate virtual disks, such as Network File System mounts, described in crossref:network-servers[network-nfs,“Network File System (NFS)”], or CDROM drives. [[disks-fstab]] === The fstab File During the boot process (crossref:boot[boot,The FreeBSD Booting Process]), file systems listed in `/etc/fstab` are automatically mounted except for the entries containing `noauto`. This file contains entries in the following format: [.programlisting] .... device /mount-point fstype options dumpfreq passno .... `device`:: An existing device name as explained in crossref:basics[disks-naming,Disk Device Names]. `mount-point`:: An existing directory on which to mount the file system. `fstype`:: The file system type to pass to man:mount[8]. The default FreeBSD file system is `ufs`. `options`:: Either `rw` for read-write file systems, or `ro` for read-only file systems, followed by any other options that may be needed. A common option is `noauto` for file systems not normally mounted during the boot sequence. Other options are listed in man:mount[8]. `dumpfreq`:: Used by man:dump[8] to determine which file systems require dumping. If the field is missing, a value of zero is assumed. `passno`:: Determines the order in which UFS file systems should be checked by man:fsck[8] after a reboot. File systems that should be skipped should have their `passno` set to zero. The root file system needs to be checked before everything else and should have its `passno` set to one. The other file systems should be set to values greater than one. If more than one file system has the same `passno`, man:fsck[8] will attempt to check file systems in parallel if possible. Refer to man:fstab[5] for more information on the format of `/etc/fstab` and its options. [[disks-mount]] === Using man:mount[8] File systems are mounted using man:mount[8]. The most basic syntax is as follows: [example] ==== [source,shell] .... # mount device mountpoint .... ==== A file system listed in `/etc/fstab` can also be mounted by providing just the mountpoint. This command provides many options which are described in man:mount[8]. The most commonly used options include: .Mount Options `-a`:: Mount all the file systems listed in `/etc/fstab`, except those marked as "noauto", excluded by the `-t` flag, or those that are already mounted. `-d`:: Do everything except for the actual mount system call. This option is useful in conjunction with the `-v` flag to determine what man:mount[8] is actually trying to do. `-f`:: Force the mount of an unclean file system (dangerous), or the revocation of write access when downgrading a file system's mount status from read-write to read-only. `-r`:: Mount the file system read-only. This is identical to using `-o ro`. ``-t _fstype_``:: Mount the specified file system type or mount only file systems of the given type, if `-a` is included. "ufs" is the default file system type. `-u`:: Update mount options on the file system. `-v`:: Be verbose. `-w`:: Mount the file system read-write. The following options can be passed to `-o` as a comma-separated list: nosuid:: Do not interpret setuid or setgid flags on the file system. This is also a useful security option. [[disks-umount]] === Using man:umount[8] To unmount a file system use man:umount[8]. This command takes one parameter which can be a mountpoint, device name, `-a` or `-A`. All forms take `-f` to force unmounting, and `-v` for verbosity. Be warned that `-f` is not generally a good idea as it might crash the computer or damage data on the file system. To unmount all mounted file systems, or just the file system types listed after `-t`, use `-a` or `-A`. Note that `-A` does not attempt to unmount the root file system. [[basics-processes]] == Processes and Daemons FreeBSD is a multi-tasking operating system. Each program running at any one time is called a _process_. Every running command starts at least one new process and there are a number of system processes that are run by FreeBSD. Each process is uniquely identified by a number called a _process ID_ (PID). Similar to files, each process has one owner and group, and the owner and group permissions are used to determine which files and devices the process can open. Most processes also have a parent process that started them. For example, the shell is a process, and any command started in the shell is a process which has the shell as its parent process. The exception is a special process called man:init[8] which is always the first process to start at boot time and which always has a PID of `1`. Some programs are not designed to be run with continuous user input and disconnect from the terminal at the first opportunity. For example, a web server responds to web requests, rather than user input. Mail servers are another example of this type of application. These types of programs are known as _daemons_. The term daemon comes from Greek mythology and represents an entity that is neither good nor evil, and which invisibly performs useful tasks. This is why the BSD mascot is the cheerful-looking daemon with sneakers and a pitchfork. There is a convention to name programs that normally run as daemons with a trailing "d". For example, BIND is the Berkeley Internet Name Domain, but the actual program that executes is `named`. The Apache web server program is `httpd` and the line printer spooling daemon is `lpd`. This is only a naming convention. For example, the main mail daemon for the Sendmail application is `sendmail`, and not `maild`. === Viewing Processes To see the processes running on the system, use man:ps[1] or man:top[1]. To display a static list of the currently running processes, their PIDs, how much memory they are using, and the command they were started with, use man:ps[1]. To display all the running processes and update the display every few seconds in order to interactively see what the computer is doing, use man:top[1]. By default, man:ps[1] only shows the commands that are running and owned by the user. For example: [source,shell] .... % ps .... The output should be similar to the following: [.programlisting] .... PID TT STAT TIME COMMAND 8203 0 Ss 0:00.59 /bin/csh 8895 0 R+ 0:00.00 ps .... The output from man:ps[1] is organized into a number of columns. The `PID` column displays the process ID. PIDs are assigned starting at 1, go up to 99999, then wrap around back to the beginning. However, a PID is not reassigned if it is already in use. The `TT` column shows the tty the program is running on and `STAT` shows the program's state. `TIME` is the amount of time the program has been running on the CPU. This is usually not the elapsed time since the program was started, as most programs spend a lot of time waiting for things to happen before they need to spend time on the CPU. Finally, `COMMAND` is the command that was used to start the program. A number of different options are available to change the information that is displayed. One of the most useful sets is `auxww`, where `a` displays information about all the running processes of all users, `u` displays the username and memory usage of the process' owner, `x` displays information about daemon processes, and `ww` causes man:ps[1] to display the full command line for each process, rather than truncating it once it gets too long to fit on the screen. The output from man:top[1] is similar: [source,shell] .... % top .... The output should be similar to the following: [.programlisting] .... last pid: 9609; load averages: 0.56, 0.45, 0.36 up 0+00:20:03 10:21:46 107 processes: 2 running, 104 sleeping, 1 zombie CPU: 6.2% user, 0.1% nice, 8.2% system, 0.4% interrupt, 85.1% idle Mem: 541M Active, 450M Inact, 1333M Wired, 4064K Cache, 1498M Free ARC: 992M Total, 377M MFU, 589M MRU, 250K Anon, 5280K Header, 21M Other Swap: 2048M Total, 2048M Free PID USERNAME THR PRI NICE SIZE RES STATE C TIME WCPU COMMAND 557 root 1 -21 r31 136M 42296K select 0 2:20 9.96% Xorg 8198 dru 2 52 0 449M 82736K select 3 0:08 5.96% kdeinit4 8311 dru 27 30 0 1150M 187M uwait 1 1:37 0.98% firefox 431 root 1 20 0 14268K 1728K select 0 0:06 0.98% moused 9551 dru 1 21 0 16600K 2660K CPU3 3 0:01 0.98% top 2357 dru 4 37 0 718M 141M select 0 0:21 0.00% kdeinit4 8705 dru 4 35 0 480M 98M select 2 0:20 0.00% kdeinit4 8076 dru 6 20 0 552M 113M uwait 0 0:12 0.00% soffice.bin 2623 root 1 30 10 12088K 1636K select 3 0:09 0.00% powerd 2338 dru 1 20 0 440M 84532K select 1 0:06 0.00% kwin 1427 dru 5 22 0 605M 86412K select 1 0:05 0.00% kdeinit4 .... The output is split into two sections. The header (the first five or six lines) shows the PID of the last process to run, the system load averages (which are a measure of how busy the system is), the system uptime (time since the last reboot) and the current time. The other figures in the header relate to how many processes are running, how much memory and swap space has been used, and how much time the system is spending in different CPU states. If the ZFS file system module has been loaded, an `ARC` line indicates how much data was read from the memory cache instead of from disk. Below the header is a series of columns containing similar information to the output from man:ps[1], such as the PID, username, amount of CPU time, and the command that started the process. By default, man:top[1] also displays the amount of memory space taken by the process. This is split into two columns: one for total size and one for resident size. Total size is how much memory the application has needed and the resident size is how much it is actually using now. man:top[1] automatically updates the display every two seconds. A different interval can be specified with `-s`. [[basics-daemons]] === Killing Processes One way to communicate with any running process or daemon is to send a _signal_ using man:kill[1]. There are a number of different signals; some have a specific meaning while others are described in the application's documentation. A user can only send a signal to a process they own and sending a signal to someone else's process will result in a permission denied error. The exception is the `root` user, who can send signals to anyone's processes. The operating system can also send a signal to a process. If an application is badly written and tries to access memory that it is not supposed to, FreeBSD will send the process the "Segmentation Violation" signal (`SIGSEGV`). If an application has been written to use the man:alarm[3] system call to be alerted after a period of time has elapsed, it will be sent the "Alarm" signal (`SIGALRM`). Two signals can be used to stop a process: `SIGTERM` and `SIGKILL`. `SIGTERM` is the polite way to kill a process as the process can read the signal, close any log files it may have open, and attempt to finish what it is doing before shutting down. In some cases, a process may ignore `SIGTERM` if it is in the middle of some task that cannot be interrupted. `SIGKILL` cannot be ignored by a process. Sending a `SIGKILL` to a process will usually stop that process there and then. footnote:[There are a few tasks that cannot be interrupted. For example, if the process is trying to read from a file that is on another computer on the network, and the other computer is unavailable, the process is said to be uninterruptible. Eventually the process will time out, typically after two minutes. As soon as this time out occurs the process will be killed.]. Other commonly used signals are `SIGHUP`, `SIGUSR1`, and `SIGUSR2`. Since these are general purpose signals, different applications will respond differently. For example, after changing a web server's configuration file, the web server needs to be told to re-read its configuration. Restarting `httpd` would result in a brief outage period on the web server. Instead, send the daemon the `SIGHUP` signal. Be aware that different daemons will have different behavior, so refer to the documentation for the daemon to determine if `SIGHUP` will achieve the desired results. [IMPORTANT] ==== Killing a random process on the system is a bad idea. In particular, man:init[8], PID 1, is special. Running `/bin/kill -s KILL 1` is a quick, and unrecommended, way to shutdown the system. _Always_ double check the arguments to man:kill[1] _before_ pressing kbd:[Return]. ==== [[shells]] == Shells A _shell_ provides a command line interface for interacting with the operating system. A shell receives commands from the input channel and executes them. Many shells provide built in functions to help with everyday tasks such as file management, file globbing, command line editing, command macros, and environment variables. -FreeBSD comes with several shells, including the Bourne shell (man:sh[1]) and the extended C shell (man:tcsh[1]). +FreeBSD comes with several shells, including an extended POSIX(R) shell (man:sh[1]) and the extended C shell (man:tcsh[1]). Other shells are available from the FreeBSD Ports Collection, such as `zsh` and `bash`. The shell that is used is really a matter of taste. A C programmer might feel more comfortable with a C-like shell such as man:tcsh[1]. A Linux(R) user might prefer `bash`. Each shell has unique properties that may or may not work with a user's preferred working environment, which is why there is a choice of which shell to use. One common shell feature is filename completion. After a user types the first few letters of a command or filename and presses kbd:[Tab], the shell completes the rest of the command or filename. Consider two files called `foobar` and `football`. To delete `foobar`, the user might type `rm foo` and press kbd:[Tab] to complete the filename. But the shell only shows `rm foo`. It was unable to complete the filename because both `foobar` and `football` start with `foo`. Some shells sound a beep or show all the choices if more than one name matches. The user must then type more characters to identify the desired filename. Typing a `t` and pressing kbd:[Tab] again is enough to let the shell determine which filename is desired and fill in the rest. Another feature of the shell is the use of environment variables. Environment variables are a variable/key pair stored in the shell's environment. This environment can be read by any program invoked by the shell, and thus contains a lot of program configuration. crossref:basics[shell-env-vars,Common Environment Variables] provides a list of common environment variables and their meanings. Note that the names of environment variables are always in uppercase. [[shell-env-vars]] .Common Environment Variables [cols="25h,~"] |=== | Variable | Description |`USER` |Current logged in user's name. |`PATH` |Colon-separated list of directories to search for binaries. |`DISPLAY` |Network name of the Xorg display to connect to, if available. |`SHELL` |The current shell. |`TERM` |The name of the user's type of terminal. Used to determine the capabilities of the terminal. |`TERMCAP` |Database entry of the terminal escape codes to perform various terminal functions. |`OSTYPE` |Type of operating system. |`MACHTYPE` |The system's CPU architecture. |`EDITOR` |The user's preferred text editor. |`PAGER` |The user's preferred utility for viewing text one page at a time. |`MANPATH` |Colon-separated list of directories to search for manual pages. |=== How to set an environment variable differs between shells. In man:tcsh[1] and man:csh[1], use `setenv` to set environment variables. In man:sh[1] and `bash`, use `export` to set the current environment variables. This example sets the default `EDITOR` to `/usr/local/bin/emacs` for the man:tcsh[1] shell: [source,shell] .... % setenv EDITOR /usr/local/bin/emacs .... The equivalent command for `bash` would be: [source,shell] .... % export EDITOR="/usr/local/bin/emacs" .... To expand an environment variable in order to see its current setting, type a `$` character in front of its name on the command line. For example, `echo $TERM` displays the current `$TERM` setting. Shells treat special characters, known as meta-characters, as special representations of data. The most common meta-character is `\*`, which represents any number of characters in a filename. Meta-characters can be used to perform filename globbing. For example, `echo *` is equivalent to `ls` because the shell takes all the files that match `*` and `echo` lists them on the command line. To prevent the shell from interpreting a special character, escape it from the shell by starting it with a backslash (`\`). For example, `echo $TERM` prints the terminal setting whereas `echo \$TERM` literally prints the string `$TERM`. [[changing-shells]] === Changing the Shell The easiest way to permanently change the default shell is to use `chsh`. Running this command will open the editor that is configured in the `EDITOR` environment variable, which by default is set to man:vi[1]. Change the `Shell:` line to the full path of the new shell. Alternately, use `chsh -s` which will set the specified shell without opening an editor. For example, to change the shell to `bash`: [source,shell] .... % chsh -s /usr/local/bin/bash .... Enter the password at the prompt and press kbd:[Return] to change the shell. Log off and log in again to start using the new shell. [NOTE] ==== The new shell _must_ be present in `/etc/shells`. If the shell was installed from the FreeBSD Ports Collection as described in crossref:ports[ports,Installing Applications: Packages and Ports], it should be automatically added to this file. If it is missing, add it using this command, replacing the path with the path of the shell: [source,shell] .... # echo /usr/local/bin/bash >> /etc/shells .... Then, rerun man:chsh[1]. ==== === Advanced Shell Techniques The UNIX(R) shell is not just a command interpreter, it acts as a powerful tool which allows users to execute commands, redirect their output, redirect their input and chain commands together to improve the final command output. When this functionality is mixed with built in commands, the user is provided with an environment that can maximize efficiency. Shell redirection is the action of sending the output or the input of a command into another command or into a file. To capture the output of the man:ls[1] command, for example, into a file, redirect the output: [source,shell] .... % ls > directory_listing.txt .... The directory contents will now be listed in `directory_listing.txt`. Some commands can be used to read input, such as man:sort[1]. To sort this listing, redirect the input: [source,shell] .... % sort < directory_listing.txt .... The input will be sorted and placed on the screen. To redirect that input into another file, one could redirect the output of man:sort[1] by mixing the direction: [source,shell] .... % sort < directory_listing.txt > sorted.txt .... In all of the previous examples, the commands are performing redirection using file descriptors. Every UNIX(R) system has file descriptors, which include standard input (stdin), standard output (stdout), and standard error (stderr). Each one has a purpose, where input could be a keyboard or a mouse, something that provides input. Output could be a screen or paper in a printer. And error would be anything that is used for diagnostic or error messages. All three are considered I/O based file descriptors and sometimes considered streams. Through the use of these descriptors, the shell allows output and input to be passed around through various commands and redirected to or from a file. Another method of redirection is the pipe operator. The UNIX(R) pipe operator, "|" allows the output of one command to be directly passed or directed to another program. Basically, a pipe allows the standard output of a command to be passed as standard input to another command, for example: [source,shell] .... % cat directory_listing.txt | sort | less .... In that example, the contents of `directory_listing.txt` will be sorted and the output passed to man:less[1]. This allows the user to scroll through the output at their own pace and prevent it from scrolling off the screen. [[editors]] == Text Editors Most FreeBSD configuration is done by editing text files, so it is a good idea to become familiar with a text editor. FreeBSD comes with a few as part of the base system, and many more are available in the Ports Collection. A simple editor to learn is man:ee[1], which stands for easy editor. To start this editor, type `ee _filename_` where _filename_ is the name of the file to be edited. Once inside the editor, all of the commands for manipulating the editor's functions are listed at the top of the display. The caret (`^`) represents kbd:[Ctrl], so `^e` expands to kbd:[Ctrl+e]. To leave man:ee[1], press kbd:[Esc], then choose the "leave editor" option from the main menu. The editor will prompt to save any changes if the file has been modified. FreeBSD also comes with more powerful text editors, such as man:vi[1], as part of the base system. Other editors, like package:editors/emacs[] and package:editors/vim[], are part of the FreeBSD Ports Collection. These editors offer more functionality at the expense of being more complicated to learn. Learning a more powerful editor such as vim or Emacs can save more time in the long run. Many applications which modify files or require typed input will automatically open a text editor. To change the default editor, set the `EDITOR` environment variable as described in crossref:basics[shells, Shells]. [[basics-devices]] == Devices and Device Nodes A device is a term used mostly for hardware-related activities in a system, including disks, printers, graphics cards, and keyboards. When FreeBSD boots, the majority of the boot messages refer to devices being detected. A copy of the boot messages is saved to `/var/run/dmesg.boot`. Each device has a device name and number. For example, `ada0` is the first SATA hard drive, while `kbd0` represents the keyboard. Most devices in FreeBSD must be accessed through special files called device nodes, which are located in `/dev`. [[basics-more-information]] == Manual Pages The most comprehensive documentation on FreeBSD is in the form of manual pages. Nearly every program on the system comes with a short reference manual explaining the basic operation and available arguments. These manuals can be viewed using `man`: [source,shell] .... % man command .... where _command_ is the name of the command to learn about. For example, to learn more about man:ls[1], type: [source,shell] .... % man ls .... Manual pages are divided into sections which represent the type of topic. In FreeBSD, the following sections are available: . User commands. . System calls and error numbers. . Functions in the C libraries. . Device drivers. . File formats. . Games and other diversions. . Miscellaneous information. . System maintenance and operation commands. . System kernel interfaces. In some cases, the same topic may appear in more than one section of the online manual. For example, there is a `chmod` user command and a `chmod()` system call. To tell man:man[1] which section to display, specify the section number: [source,shell] .... % man 1 chmod .... This will display the manual page for the user command man:chmod[1]. References to a particular section of the online manual are traditionally placed in parenthesis in written documentation, so man:chmod[1] refers to the user command and man:chmod[2] refers to the system call. If the name of the manual page is unknown, use `man -k` to search for keywords in the manual page descriptions: [source,shell] .... % man -k mail .... This command displays a list of commands that have the keyword "mail" in their descriptions. This is equivalent to using man:apropos[1]. To read the descriptions for all of the commands in `/usr/sbin`, type: [source,shell] .... % cd /usr/sbin % man -f * | more .... or [source,shell] .... % cd /usr/sbin % whatis * |more .... [[basics-info]] === GNU Info Files FreeBSD includes several applications and utilities produced by the Free Software Foundation (FSF). In addition to manual pages, these programs may include hypertext documents called `info` files. These can be viewed using man:info[1] or, if package:editors/emacs[] is installed, the info mode of emacs. To use man:info[1], type: [source,shell] .... % info .... For a brief introduction, type `h`. For a quick command reference, type `?`. diff --git a/documentation/content/en/books/handbook/boot/_index.adoc b/documentation/content/en/books/handbook/boot/_index.adoc index b8fe0c7e7c..3adda24db7 100644 --- a/documentation/content/en/books/handbook/boot/_index.adoc +++ b/documentation/content/en/books/handbook/boot/_index.adoc @@ -1,454 +1,454 @@ --- title: Chapter 15. The FreeBSD Booting Process part: Part III. System Administration prev: books/handbook/config next: books/handbook/security description: An introduction to the FreeBSD Booting Process, demonstrates how to customize the FreeBSD boot process, including everything that happens until the FreeBSD kernel has started, probed for devices, and started init tags: ["boot", "boot process", "device hints", "x86", "amd64", "MBR", "GPT", "UEFI", "bsdlabel", "boot0", "Single-User Mode", "Multi-User Mode"] showBookMenu: true weight: 19 params: path: "/books/handbook/boot/" --- [[boot]] = The FreeBSD Booting Process :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 15 :partnums: :source-highlighter: rouge :experimental: :images-path: books/handbook/boot/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[boot-synopsis]] == Synopsis The process of starting a computer and loading the operating system is referred to as "the bootstrap process", or "booting". FreeBSD's boot process provides a great deal of flexibility in customizing what happens when the system starts, including the ability to select from different operating systems installed on the same computer, different versions of the same operating system, or a different installed kernel. This chapter details the configuration options that can be set. It demonstrates how to customize the FreeBSD boot process, including everything that happens until the FreeBSD kernel has started, probed for devices, and started man:init[8]. This occurs when the text color of the boot messages changes from bright white to grey. Read this chapter to learn: * The components of the FreeBSD bootstrap system and how they interact. * The options that can be passed to the components in the FreeBSD bootstrap in order to control the boot process. * The basics of setting device hints. * How to boot into single- and multi-user mode and how to properly shut down a FreeBSD system. [NOTE] ==== This chapter only describes the boot process for FreeBSD running on x86 and amd64 systems. ==== [[boot-introduction]] == FreeBSD Boot Process Turning on a computer and starting the operating system poses an interesting dilemma. By definition, the computer does not know how to do anything until the operating system is started. This includes running programs from the disk. If the computer can not run a program from the disk without the operating system, and the operating system programs are on the disk, how is the operating system started? This problem parallels one in the book The Adventures of Baron Munchausen. A character had fallen part way down a manhole, and pulled himself out by grabbing his bootstraps and lifting. In the early days of computing, the term _bootstrap_ was applied to the mechanism used to load the operating system. It has since become shortened to "booting". On x86 hardware, the Basic Input/Output System (BIOS) is responsible for loading the operating system. The BIOS looks on the hard disk for the Master Boot Record (MBR), which must be located in a specific place on the disk. The BIOS has enough knowledge to load and run the MBR, and assumes that the MBR can then carry out the rest of the tasks involved in loading the operating system, possibly with the help of the BIOS. [NOTE] ==== FreeBSD provides for booting from both the older MBR standard, and the newer GUID Partition Table (GPT). GPT partitioning is often found on computers with the Unified Extensible Firmware Interface (UEFI). However, FreeBSD can boot from GPT partitions even on machines with only a legacy BIOS with man:gptboot[8]. Work is under way to provide direct UEFI booting. ==== The code within the MBR is typically referred to as a _boot manager_, especially when it interacts with the user. The boot manager usually has more code in the first track of the disk or within the file system. Examples of boot managers include the standard FreeBSD boot manager boot0, also called Boot Easy, and GNU GRUB, which is used by many Linux(R) distributions. [NOTE] ==== // There is extref:{faq}[a frequently asked question] about GRUB. Beyond the answer there, // Users of GRUB should refer to https://www.gnu.org/software/grub/grub-documentation.html[GNU-provided documentation]. ==== If only one operating system is installed, the MBR searches for the first bootable (active) slice on the disk, and then runs the code on that slice to load the remainder of the operating system. When multiple operating systems are present, a different boot manager can be installed to display a list of operating systems so the user can select one to boot. The remainder of the FreeBSD bootstrap system is divided into three stages. The first stage knows just enough to get the computer into a specific state and run the second stage. The second stage can do a little bit more, before running the third stage. The third stage finishes the task of loading the operating system. The work is split into three stages because the MBR puts limits on the size of the programs that can be run at stages one and two. Chaining the tasks together allows FreeBSD to provide a more flexible loader. The kernel is then started and begins to probe for devices and initialize them for use. Once the kernel boot process is finished, the kernel passes control to the user process man:init[8], which makes sure the disks are in a usable state, starts the user-level resource configuration which mounts file systems, sets up network cards to communicate on the network, and starts the processes which have been configured to run at startup. This section describes these stages in more detail and demonstrates how to interact with the FreeBSD boot process. [[boot-boot0]] === The Boot Manager The boot manager code in the MBR is sometimes referred to as _stage zero_ of the boot process. By default, FreeBSD uses the boot0 boot manager. The MBR installed by the FreeBSD installer is based on [.filename]#/boot/boot0#. The size and capability of boot0 is restricted to 446 bytes due to the slice table and `0x55AA` identifier at the end of the MBR. If boot0 and multiple operating systems are installed, a message similar to this example will be displayed at boot time: [[boot-boot0-example]] .[.filename]#boot0# Screenshot [example] ==== [source,shell] .... F1 Win F2 FreeBSD Default: F2 .... ==== Other operating systems will overwrite an existing MBR if they are installed after FreeBSD. If this happens, or to replace the existing MBR with the FreeBSD MBR, use the following command: [source,shell] .... # fdisk -B -b /boot/boot0 device .... where _device_ is the boot disk, such as [.filename]#ad0# for the first IDE disk, [.filename]#ad2# for the first IDE disk on a second IDE controller, or [.filename]#da0# for the first SCSI disk. To create a custom configuration of the MBR, refer to man:boot0cfg[8]. [[boot-boot1]] === Stage One and Stage Two Conceptually, the first and second stages are part of the same program on the same area of the disk. Due to space constraints, they have been split into two, but are always installed together. They are copied from the combined [.filename]#/boot/boot# by the FreeBSD installer or `bsdlabel`. These two stages are located outside file systems, in the first track of the boot slice, starting with the first sector. This is where boot0, or any other boot manager, expects to find a program to run which will continue the boot process. The first stage, [.filename]#boot1#, is very simple, since it can only be 512 bytes in size. It knows just enough about the FreeBSD _bsdlabel_, which stores information about the slice, to find and execute [.filename]#boot2#. Stage two, [.filename]#boot2#, is slightly more sophisticated, and understands the FreeBSD file system enough to find files. It can provide a simple interface to choose the kernel or loader to run. It runs loader, which is much more sophisticated and provides a boot configuration file. If the boot process is interrupted at stage two, the following interactive screen is displayed: [[boot-boot2-example]] .[.filename]#boot2# Screenshot [example] ==== [source,shell] .... >> FreeBSD/i386 BOOT Default: 0:ad(0,a)/boot/loader boot: .... ==== To replace the installed [.filename]#boot1# and [.filename]#boot2#, use `bsdlabel`, where _diskslice_ is the disk and slice to boot from, such as [.filename]#ad0s1# for the first slice on the first IDE disk: [source,shell] .... # bsdlabel -B diskslice .... [WARNING] ==== If just the disk name is used, such as [.filename]#ad0#, `bsdlabel` will create the disk in "dangerously dedicated mode", without slices. This is probably not the desired action, so double check the _diskslice_ before pressing kbd:[Return]. ==== [[boot-loader]] === Stage Three The loader is the final stage of the three-stage bootstrap process. It is located on the file system, usually as [.filename]#/boot/loader#. The loader is intended as an interactive method for configuration, using a built-in command set, backed up by a more powerful interpreter which has a more complex command set. During initialization, loader will probe for a console and for disks, and figure out which disk it is booting from. It will set variables accordingly, and an interpreter is started where user commands can be passed from a script or interactively. The loader will then read [.filename]#/boot/loader.rc#, which by default reads in [.filename]#/boot/defaults/loader.conf# which sets reasonable defaults for variables and reads [.filename]#/boot/loader.conf# for local changes to those variables. [.filename]#loader.rc# then acts on these variables, loading whichever modules and kernel are selected. Finally, by default, loader issues a 10 second wait for key presses, and boots the kernel if it is not interrupted. If interrupted, the user is presented with a prompt which understands the command set, where the user may adjust variables, unload all modules, load modules, and then finally boot or reboot. crossref:boot[boot-loader-commands,Loader Built-In Commands] lists the most commonly used loader commands. For a complete discussion of all available commands, refer to man:loader[8]. [[boot-loader-commands]] .Loader Built-In Commands [cols="20%,80%", frame="none", options="header"] |=== | Variable | Description |autoboot _seconds_ |Proceeds to boot the kernel if not interrupted within the time span given, in seconds. It displays a countdown, and the default time span is 10 seconds. |boot [`-options`] [`kernelname`] |Immediately proceeds to boot the kernel, with any specified options or kernel name. Providing a kernel name on the command-line is only applicable after an `unload` has been issued. Otherwise, the previously-loaded kernel will be used. If _kernelname_ is not qualified, it will be searched under _/boot/kernel_ and _/boot/modules_. |boot-conf |Goes through the same automatic configuration of modules based on specified variables, most commonly `kernel`. This only makes sense if `unload` is used first, before changing some variables. |help [`_topic_`] |Shows help messages read from [.filename]#/boot/loader.help#. If the topic given is `index`, the list of available topics is displayed. |include `_filename_` ... |Reads the specified file and interprets it line by line. An error immediately stops the `include`. |load [-t ``_type_``] `_filename_` |Loads the kernel, kernel module, or file of the type given, with the specified filename. Any arguments after _filename_ are passed to the file. If _filename_ is not qualified, it will be searched under _/boot/kernel_ and _/boot/modules_. |ls [-l] [``_path_``] |Displays a listing of files in the given path, or the root directory, if the path is not specified. If `-l` is specified, file sizes will also be shown. |lsdev [`-v`] |Lists all of the devices from which it may be possible to load modules. If `-v` is specified, more details are printed. |lsmod [`-v`] |Displays loaded modules. If `-v` is specified, more details are shown. |more `_filename_` |Displays the files specified, with a pause at each `LINES` displayed. |reboot |Immediately reboots the system. |set `_variable_`, set `_variable=value_` |Sets the specified environment variables. |unload |Removes all loaded modules. |=== Here are some practical examples of loader usage. To boot the usual kernel in single-user mode: [source,shell] .... boot -s .... To unload the usual kernel and modules and then load the previous or another, specified kernel: [source,shell] .... unload load /path/to/kernelfile .... Use the qualified [.filename]#/boot/GENERIC/kernel# to refer to the default kernel that comes with an installation, or [.filename]#/boot/kernel.old/kernel#, to refer to the previously installed kernel before a system upgrade or before configuring a custom kernel. Use the following to load the usual modules with another kernel. Note that in this case it is not necessary the qualified name: [source,shell] .... unload set kernel="mykernel" boot-conf .... To load an automated kernel configuration script: [source,shell] .... load -t userconfig_script /boot/kernel.conf .... [[boot-init]] === Last Stage Once the kernel is loaded by either loader or by boot2, which bypasses loader, it examines any boot flags and adjusts its behavior as necessary. crossref:boot[boot-kernel,Kernel Interaction During Boot] lists the commonly used boot flags. Refer to man:boot[8] for more information on the other boot flags. [[boot-kernel]] .Kernel Interaction During Boot [cols="1,1", frame="none", options="header"] |=== | Option | Description |`-a` |During kernel initialization, ask for the device to mount as the root file system. |`-C` |Boot the root file system from a CDROM. |`-s` |Boot into single-user mode. |`-v` |Be more verbose during kernel startup. |=== Once the kernel has finished booting, it passes control to the user process man:init[8], which is located at [.filename]#/sbin/init#, or the program path specified in the `init_path` variable in `loader`. This is the last stage of the boot process. The boot sequence makes sure that the file systems available on the system are consistent. If a UFS file system is not, and `fsck` cannot fix the inconsistencies, init drops the system into single-user mode so that the system administrator can resolve the problem directly. Otherwise, the system boots into multi-user mode. [[boot-singleuser]] ==== Single-User Mode A user can specify this mode by booting with `-s` or by setting the `boot_single` variable in loader. It can also be reached by running `shutdown now` from multi-user mode. Single-user mode begins with this message: [.programlisting] .... Enter full pathname of shell or RETURN for /bin/sh: .... -If the user presses kbd:[Enter], the system will enter the default Bourne shell. +If the user presses kbd:[Enter], the system will enter the default POSIX(R) shell. To specify a different shell, input the full path to the shell. Single-user mode is usually used to repair a system that will not boot due to an inconsistent file system or an error in a boot configuration file. It can also be used to reset the `root` password when it is unknown. These actions are possible as the single-user mode prompt gives full, local access to the system and its configuration files. There is no networking in this mode. While single-user mode is useful for repairing a system, it poses a security risk unless the system is in a physically secure location. By default, any user who can gain physical access to a system will have full control of that system after booting into single-user mode. If the system `console` is changed to `insecure` in [.filename]#/etc/ttys#, the system will first prompt for the `root` password before initiating single-user mode. This adds a measure of security while removing the ability to reset the `root` password when it is unknown. [[boot-insecure-console]] .Configuring an Insecure Console in [.filename]#/etc/ttys# [example] ==== [.programlisting] .... # name getty type status comments # # If console is marked "insecure", then init will ask for the root password # when going to single-user mode. console none unknown off insecure .... ==== An `insecure` console means that physical security to the console is considered to be insecure, so only someone who knows the `root` password may use single-user mode. [[boot-multiuser]] ==== Multi-User Mode If init finds the file systems to be in order, or once the user has finished their commands in single-user mode and has typed `exit` to leave single-user mode, the system enters multi-user mode, in which it starts the resource configuration of the system. The resource configuration system reads in configuration defaults from [.filename]#/etc/defaults/rc.conf# and system-specific details from [.filename]#/etc/rc.conf#. It then proceeds to mount the system file systems listed in [.filename]#/etc/fstab#. It starts up networking services, miscellaneous system daemons, then the startup scripts of locally installed packages. To learn more about the resource configuration system, refer to man:rc[8] and examine the scripts located in [.filename]#/etc/rc.d#. [[device-hints]] == Device Hints During initial system startup, the boot man:loader[8] reads man:device.hints[5]. This file stores kernel boot information known as variables, sometimes referred to as "device hints". These "device hints" are used by device drivers for device configuration. Device hints may also be specified at the Stage 3 boot loader prompt, as demonstrated in crossref:boot[boot-loader, Stage Three]. Variables can be added using `set`, removed with `unset`, and viewed `show`. Variables set in [.filename]#/boot/device.hints# can also be overridden. Device hints entered at the boot loader are not permanent and will not be applied on the next reboot. Once the system is booted, man:kenv[1] can be used to dump all of the variables. The syntax for [.filename]#/boot/device.hints# is one variable per line, using the hash "#" as comment markers. Lines are constructed as follows: [source,shell] .... hint.driver.unit.keyword="value" .... The syntax for the Stage 3 boot loader is: [source,shell] .... set hint.driver.unit.keyword=value .... where `driver` is the device driver name, `unit` is the device driver unit number, and `keyword` is the hint keyword. The keyword may consist of the following options: * `at`: specifies the bus which the device is attached to. * `port`: specifies the start address of the I/O to be used. * `irq`: specifies the interrupt request number to be used. * `drq`: specifies the DMA channel number. * `maddr`: specifies the physical memory address occupied by the device. * `flags`: sets various flag bits for the device. * `disabled`: if set to `1` the device is disabled. Since device drivers may accept or require more hints not listed here, viewing a driver's manual page is recommended. For more information, refer to man:device.hints[5], man:kenv[1], man:loader.conf[5], and man:loader[8]. [[boot-shutdown]] == Shutdown Sequence Upon controlled shutdown using man:shutdown[8], man:init[8] will attempt to run the script [.filename]#/etc/rc.shutdown#, and then proceed to send all processes the `TERM` signal, and subsequently the `KILL` signal to any that do not terminate in a timely manner. To power down a FreeBSD machine on architectures and systems that support power management, use `shutdown -p now` to turn the power off immediately. To reboot a FreeBSD system, use `shutdown -r now`. One must be `root` or a member of `operator` in order to run man:shutdown[8]. One can also use man:halt[8] and man:reboot[8]. Refer to their manual pages and to man:shutdown[8] for more information. Modify group membership by referring to crossref:basics[users-synopsis,“Users and Basic Account Management”]. [NOTE] ==== Power management requires man:acpi[4] to be loaded as a module or statically compiled into a custom kernel. ==== diff --git a/documentation/content/en/books/handbook/config/_index.adoc b/documentation/content/en/books/handbook/config/_index.adoc index 640c1e0f0e..ba77b932d9 100644 --- a/documentation/content/en/books/handbook/config/_index.adoc +++ b/documentation/content/en/books/handbook/config/_index.adoc @@ -1,1593 +1,1593 @@ --- title: Chapter 14. Configuration, Services, Logging and Power Management part: Part III. System Administration prev: books/handbook/partiii next: books/handbook/boot description: This chapter explains much of the FreeBSD configuration files, how to enable or disable a service, how to configure the logging system and the power management area. tags: ["configuration", "services", "cron", "periodic", "logging", "configuration files", "sysctl", "swap", "power management"] showBookMenu: true weight: 18 params: path: "/books/handbook/config/" --- [[config-tuning]] = Configuration, Services, Logging and Power Management :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 14 :partnums: :source-highlighter: rouge :experimental: :images-path: books/handbook/config/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[config-synopsis]] == Synopsis One of the important aspects of FreeBSD is proper system configuration. This chapter explains much of the FreeBSD configuration process, including some of the parameters which can be set to tune a FreeBSD system. Before reading this chapter: * Understand UNIX(R) and FreeBSD basics (crossref:basics[basics,FreeBSD Basics]). Read this chapter to learn: * How to use the various configuration files in [.filename]#/etc#. * The basics of [.filename]#rc.conf# configuration and [.filename]#/usr/local/etc/rc.d# startup scripts. * How to tune FreeBSD using man:sysctl[8] variables. * How to configure the power management in FreeBSD. [[configtuning-configfiles]] == Configuration Files FreeBSD maintains a clear separation between the base system and third party applications and therefore this affects where the configuration files of these applications are located. FreeBSD base system configuration is located at the [.filename]#/etc# directory, and the [.filename]#/usr/local/etc# directory contains all the configuration files of the applications installed on the system through the ports collection and packages. The kernel state configuration is located in [.filename]#/etc/sysctl.conf#. In the section crossref:config[configtuning-sysctl, The sysctl utility], the operation of man:sysctl[8] will be explained in more detail. For more information about the FreeBSD file system structure refer to man:hier[7]. As a general rule, configuration files do not use a standard on what syntax they must follow. Although it is true that the `#` character is normally used to comment a line and that each line has a configuration variable. [NOTE] ==== Some applications like man:pkg[8] are starting to use the link:https://github.com/vstakhov/libucl[Universal Configuration Language (UCL)]. ==== === The [.filename]#/etc# directory The [.filename]#/etc# directory contains all of the FreeBSD base system configuration files that are responsible for configuring FreeBSD. [CAUTION] ==== *Extreme* caution must be taken when modifying files in the [.filename]#/etc# directory; misconfiguration could make FreeBSD unbootable or malfunction. ==== [.informaltable] [cols="1,1", frame="none"] |=== |[.filename]#/etc# |System configuration files and scripts. |[.filename]#/etc/defaults# |Default system configuration files, see man:rc[8] for more information. |[.filename]#/etc/fstab# |man:fstab[5] contains descriptive information about the various file systems. |[.filename]#/etc/mail# |Extra man:sendmail[8] configuration and other MTA configuration files. |[.filename]#/etc/mtree# |mtree configuration files, see man:mtree[8] for more information. |[.filename]#/etc/pam.d# |Configuration files for the Pluggable Authentication Modules (PAM) library. |[.filename]#/etc/periodic# |Scripts that are run daily, weekly, and monthly, via man:cron[8], see man:periodic[8] for more information. |[.filename]#/etc/rc.d# |System and daemon startup/control scripts, see man:rc[8] for more information. |[.filename]#/etc/rc.conf# |Contains descriptive information about the local host name, configuration details for any potential network interfaces and which services should be started up at system initial boot time. More information in crossref:bsdinstall[configtuning-core-configuration, Managing System-Specific Configuration] |[.filename]#/etc/security# |OpenBSM audit configuration files, see man:audit[8] for more information. |[.filename]#/etc/ppp# |ppp configuration files, see man:ppp[8] for more information. |[.filename]#/etc/ssh# |OpenSSH configuration files, see man:ssh[1] for more information. |[.filename]#/etc/ssl# |OpenSSL configuration files. |[.filename]#/etc/sysctl.conf# |Contains settings for the kernel. More information in crossref:bsdinstall[configtuning-sysctl, The sysctl utility] |=== [[configtuning-sysctl]] === The sysctl utility The man:sysctl[8] utility is used to make changes to a running FreeBSD system. The man:sysctl[8] utility retrieves kernel state and allows processes with appropriate privilege to set kernel state. The state to be retrieved or set is described using a "Management Information Base" ("MIB") style name, described as a dotted set of components. .Management Information Base [.informaltable] [cols="1,1", frame="none"] |=== |sysctl |"Magic" numbers |kern |Kernel functions and features |vm |Virtual memory |vfs |Filesystem |net |Network |debug |Debugging parameters |hw |Hardware |machdep |Machine dependent |user |Userland |p1003_1b |POSIX 1003.1B |=== At its core, man:sysctl[8] serves two functions: to read and to modify system settings. To view all readable variables: [source,shell] .... % sysctl -a .... The output should be similar to the following: [.programlisting] .... kern.ostype: FreeBSD ... vm.swap_enabled: 1 vm.overcommit: 0 vm.domain.0.pidctrl.kdd: 8 vm.domain.0.pidctrl.kid: 4 vm.domain.0.pidctrl.kpd: 3 ... vfs.zfs.sync_pass_rewrite: 2 vfs.zfs.sync_pass_dont_compress: 8 vfs.zfs.sync_pass_deferred_free: 2 .... To read a particular variable, specify its name: [source,shell] .... % sysctl kern.maxproc .... The output should be similar to the following: [.programlisting] .... kern.maxproc: 1044 .... The Management Information Base (MIB) is hierarchical and hence, specifying a prefix prints all the nodes hanging from it: [source,shell] .... % sysctl net .... The output should be similar to the following: [.programlisting] .... net.local.stream.recvspace: 8192 net.local.stream.sendspace: 8192 net.local.dgram.recvspace: 16384 net.local.dgram.maxdgram: 2048 net.local.seqpacket.recvspace: 8192 net.local.seqpacket.maxseqpacket: 8192 net.local.sockcount: 60 net.local.taskcount: 25 net.local.recycled: 0 net.local.deferred: 0 net.local.inflight: 0 net.inet.ip.portrange.randomtime: 1 net.inet.ip.portrange.randomcps: 9999 [...] .... To set a particular variable, use the _variable_=_value_ syntax: [source,shell] .... # sysctl kern.maxfiles=5000 .... The output should be similar to the following: [.programlisting] .... kern.maxfiles: 2088 -> 5000 .... [NOTE] ==== To keep the configuration after a reboot it is necessary to add these variables to the [.filename]#/etc/sysctl.conf# file as explained below. ==== [[configtuning-sysctlconf]] === The [.filename]#/etc/sysctl.conf# file The configuration file for man:sysctl[8], [.filename]#/etc/sysctl.conf#, looks much like [.filename]#/etc/rc.conf#. Values are set using a `variable=value` syntax. [NOTE] ==== The specified values are set after the system goes into multi-user mode. Not all variables are settable in this mode. ==== For example, to turn off logging of fatal signal exits and prevent users from seeing processes started by other users, the following tunables can be set in [.filename]#/etc/sysctl.conf#: [.programlisting] .... # Do not log fatal signal exits (e.g., sig 11) kern.logsigexit=0 # Prevent users from seeing information about processes that # are being run under another UID. security.bsd.see_other_uids=0 .... To obtain more information about what function a particular sysctl has, the following command can be executed: [source,shell] .... % sysctl -d kern.dfldsiz .... The output should be similar to the following: [.programlisting] .... kern.dfldsiz: Initial data size limit .... [[configtuning-core-configuration]] === Managing System-Specific Configuration The principal location for system configuration information is [.filename]#/etc/rc.conf#. This file contains a wide range of configuration information and it is read at system startup to configure the system. It provides the configuration information for the [.filename]#rc*# files. The entries in [.filename]#/etc/rc.conf# override the default settings in [.filename]#/etc/defaults/rc.conf#. [TIP] ==== The file [.filename]#/etc/defaults/rc.conf# containing the default settings should not be edited. Instead, all system-specific changes should be made to [.filename]#/etc/rc.conf#. ==== A number of strategies may be applied in clustered applications to separate site-wide configuration from system-specific configuration in order to reduce administration overhead. The recommended approach is to place system-specific configuration into [.filename]#/etc/rc.conf.local#. For example, these entries in [.filename]#/etc/rc.conf# apply to all systems: [.programlisting] .... sshd_enable="YES" keyrate="fast" defaultrouter="10.1.1.254" .... Whereas these entries in [.filename]#/etc/rc.conf.local# apply to this system only: [.programlisting] .... hostname="node1.example.org" ifconfig_fxp0="inet 10.1.1.1/8" .... Distribute [.filename]#/etc/rc.conf# to every system using an application such as rsync or puppet, while [.filename]#/etc/rc.conf.local# remains unique. Upgrading the system will not overwrite [.filename]#/etc/rc.conf#, so system configuration information will not be lost. [TIP] ==== Both [.filename]#/etc/rc.conf# and [.filename]#/etc/rc.conf.local# are parsed by man:sh[1]. This allows system operators to create complex configuration scenarios. Refer to man:rc.conf[5] for further information on this topic. ==== [[configtuning-rcd]] == Managing Services in FreeBSD FreeBSD uses the man:rc[8] system of startup scripts during system initialization and for managing services. The scripts listed in [.filename]#/etc/rc.d# provide basic services which can be controlled with the `start`, `stop`, and `restart` options to man:service[8]. A basic script may look similar to the following: [.programlisting] .... #!/bin/sh # # PROVIDE: utility # REQUIRE: DAEMON # KEYWORD: shutdown . /etc/rc.subr name=utility rcvar=utility_enable command="/usr/local/sbin/utility" load_rc_config $name # # DO NOT CHANGE THESE DEFAULT VALUES HERE # SET THEM IN THE /etc/rc.conf FILE # utility_enable=${utility_enable-"NO"} pidfile=${utility_pidfile-"/var/run/utility.pid"} run_rc_command "$1" .... Refer to extref:{rc-scripting}[this article] for instructions on how to create custom man:rc[8] scripts. [[configtuning-starting-services]] === Starting Services Many users install third party software on FreeBSD from the Ports Collection and require the installed services to be started upon system initialization. Services, such as package:security/openssh-portable[] or package:www/nginx[] are just two of the many software packages which may be started during system initialization. This section explains the procedures available for starting services. Since the man:rc[8] system is primarily intended to start and stop services at system startup and shutdown time, the `start`, `stop` and `restart` options will only perform their action if the appropriate [.filename]#/etc/rc.conf# variable is set. So the first step to start a service, like for example package:www/nginx[] is to add it to [.filename]#/etc/rc.conf# by executing the following command: [source,shell] .... # sysrc nginx_enable="YES" .... Then nginx can be started executing the following command: [source,shell] .... # service nginx start .... [TIP] ==== To `start`, `stop` or `restart` a service regardless of the settings in [.filename]#/etc/rc.conf#, these commands should be prefixed with "one". For instance, to start package:www/nginx[] regardless of the current [.filename]#/etc/rc.conf# setting, execute the following command: [source,shell] .... # service nginx onestart .... ==== It is also possible to put a service automatically into a jail, see the corresponding crossref:jails[service-jails,Service Jails] explanation. [[configtuning-status-services]] === Status of a Service To determine if a service is running, use the `status` subcommand. For example, to verify that package:www/nginx[] is running: [source,shell] .... # service nginx status .... The output should be similar to the following: [.programlisting] .... nginx is running as pid 27871. .... [[configtuning-reload-services]] === Reload a Service In some cases, it is also possible to `reload` a service. This attempts to send a signal to an individual service, forcing the service to reload its configuration files. In most cases, this means sending the service a `SIGHUP` signal. *Not all services support this feature.* The man:rc[8] system is used for network services and it also contributes to most of the system initialization. For instance, when the [.filename]#/etc/rc.d/bgfsck# script is executed, it prints out the following message: [source,shell] .... Starting background file system checks in 60 seconds. .... This script is used for background file system checks, which occur only during system initialization. Many system services depend on other services to function properly. For example, man:yp[8] and other RPC-based services may fail to start until after the man:rpcbind[8] service has started. Additional information can be found in man:rc[8] and man:rc.subr[8]. === Using Services to Start Services Other services can be started using man:inetd[8]. Working with man:inetd[8] and its configuration is described in depth in crossref:network-servers[network-inetd,“The inetd Super-Server”]. In some cases, it may make more sense to use man:cron[8] to start system services. This approach has a number of advantages as man:cron[8] runs these processes as the owner of the man:crontab[5]. This allows regular users to start and maintain their own applications. The `@reboot` feature of man:cron[8], may be used in place of the time specification. This causes the job to run when man:cron[8] is started, normally during system initialization. [[cron-periodic]] == Cron and Periodic Scheduling tasks to run at a certain day or time is a very common task on FreeBSD. The tool in charge of performing this task is man:cron[8]. In addition to tasks that can be scheduled by the user via man:cron[8], FreeBSD performs routine background tasks managed by man:periodic[8]. [[configtuning-cron]] === Cron The man:cron[8] utility runs in the background and regularly checks [.filename]#/etc/crontab# for tasks to execute and searches [.filename]#/var/cron/tabs# for custom crontab files. These files are used to schedule tasks which cron runs at the specified times. Each entry in a crontab defines a task to run and is known as a _cron job_. Two different types of configuration files are used: the system crontab, which should not be modified, and user crontabs, which can be created and edited as needed. The format used by these files is documented in man:crontab[5]. The format of the system crontab, [.filename]#/etc/crontab# includes a `who` column which does not exist in user crontabs. In the system crontab, cron runs the command as the user specified in this column. In a user crontab, all commands run as the user who created the crontab. User crontabs allow individual users to schedule their own tasks. The `root` user can also have a user [.filename]#crontab# which can be used to schedule tasks that do not exist in the system [.filename]#crontab#. Here is a sample entry from the system crontab, [.filename]#/etc/crontab#: [.programlisting] .... # /etc/crontab - root's crontab for FreeBSD # # <.> # SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin <.> # #minute hour mday month wday who command <.> # # Save some entropy so that /dev/random can re-seed on boot. */11 * * * * operator /usr/libexec/save-entropy <.> # # Rotate log files every hour, if necessary. 0 * * * * root newsyslog # # Perform daily/weekly/monthly maintenance. 1 3 * * * root periodic daily 15 4 * * 6 root periodic weekly 30 5 1 * * root periodic monthly # # Adjust the time zone if the CMOS clock keeps local time, as opposed to # UTC time. See adjkerntz(8) for details. 1,31 0-5 * * * root adjkerntz -a .... <.> Lines that begin with the `+#+` character are comments. A comment can be placed in the file as a reminder of what and why a desired action is performed. Comments cannot be on the same line as a command or else they will be interpreted as part of the command; they must be on a new line. Blank lines are ignored. -<.> The equals (`=`) character is used to define any environment settings. In this example, it is used to define the `SHELL` and `PATH`. If the `SHELL` is omitted, cron will use the default Bourne shell. If the `PATH` is omitted, the full path must be given to the command or script to run. +<.> The equals (`=`) character is used to define any environment settings. In this example, it is used to define the `SHELL` and `PATH`. If the `SHELL` is omitted, cron will use the default POSIX(R) shell. If the `PATH` is omitted, the full path must be given to the command or script to run. <.> This line defines the seven fields used in a system crontab: `minute`, `hour`, `mday`, `month`, `wday`, `who`, and `command`. The `minute` field is the time in minutes when the specified command will be run, the `hour` is the hour when the specified command will be run, the `mday` is the day of the month, `month` is the month, and `wday` is the day of the week. These fields must be numeric values, representing the twenty-four hour clock, or a `*`, representing all values for that field. The `who` field only exists in the system crontab and specifies which user the command should be run as. The last field is the command to be executed. <.> This entry defines the values for this cron job. The `\*/11`, followed by several more `*` characters, specifies that `/usr/libexec/save-entropy` is invoked by `operator` every eleven minutes of every hour, of every day and day of the week, of every month. Commands can include any number of switches. However, commands which extend to multiple lines need to be broken with the backslash "\" continuation character. [[configtuning-installcrontab]] === Creating a User Crontab To create a user crontab, invoke `crontab` in editor mode: [source,shell] .... % crontab -e .... This will open the user's crontab using the default text editor. The first time a user runs this command, it will open an empty file. Once a user creates a crontab, this command will open that file for editing. It is useful to add these lines to the top of the crontab file in order to set the environment variables and to remember the meanings of the fields in the crontab: [.programlisting] .... SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin # Order of crontab fields # minute hour mday month wday command .... Then add a line for each command or script to run, specifying the time to run the command. -This example runs the specified custom Bourne shell script every day at two in the afternoon. +This example runs the specified custom shell script every day at two in the afternoon. Since the path to the script is not specified in `PATH`, the full path to the script is given: [.programlisting] .... 0 14 * * * /home/user/bin/mycustomscript.sh .... [TIP] ==== Before using a custom script, make sure it is executable and test it with the limited set of environment variables set by cron. To replicate the environment that would be used to run the above cron entry, use: [.programlisting] .... env -i SHELL=/bin/sh PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin HOME=/home/user LOGNAME=user /home/user/bin/mycustomscript.sh .... The environment set by cron is discussed in man:crontab[5]. Checking that scripts operate correctly in a cron environment is especially important if they include any commands that delete files using wildcards. ==== When finished editing the crontab, save the file. It will automatically be installed, and cron will read the crontab and run its cron jobs at their specified times. To list the cron jobs in a crontab, use this command: [source,shell] .... % crontab -l .... The output should be similar to the following: [.programlisting] .... 0 14 * * * /home/user/bin/mycustomscript.sh .... To remove all of the cron jobs in a user crontab: [source,shell] .... % crontab -r .... The output should be similar to the following: [.programlisting] .... remove crontab for user? y .... [[configtuning-periodic]] === Periodic FreeBSD provides a set of system management scripts to check status of various subsystems, perform security-related checks, rotate log files, etc. These scripts are run on a periodic basis: daily. weekly, or monthly. The management of these tasks is performed by man:periodic[8] and its configuration resides in man:periodic.conf[5]. The periodic tasks are initiated by entries in the system crontab, shown above. Scripts executed by man:periodic[8] are located in [.filename]#/etc/periodic/# for base utilities and in [.filename]#/usr/local/etc/periodic/# for third-party software. They are organized in 4 subdirectories, daily, weekly, monthly and security. [[enable-disable-periodic]] === Enable or Disable Periodic Tasks FreeBSD has some scripts enabled by default to run periodically. To enable or disable a task, the first step is to edit [.filename]#/etc/periodic.conf# executing the following command: [source,shell] .... # ee /etc/periodic.conf .... And then to enable, for example, `daily_status_zfs_enable` put the following content in the file: [.programlisting] .... daily_status_zfs_enable="YES" .... To disable a task that is active by default, all that needs to be done is to change `YES` to `NO`. [[configuring-output-periodic-tasks]] === Configuring the Output of Periodic Tasks In [.filename]#/etc/periodic.conf# the variables `daily_output`, `weekly_output` and `monthly_output` specifies where to send the results of the script execution. By default the output of the periodic scripts are emailed to root, and therefore it is best to read root's mail or alias root to a mailbox that is monitored. To send the results to another email or to other emails, add the email addresses separated by spaces to [.filename]#/etc/periodic.conf#: [.programlisting] .... daily_output="email1@example.com email2@example.com" weekly_output="email1@example.com email2@example.com" monthly_output="email1@example.com email2@example.com" .... To log periodic output instead of receiving it as email, add the following lines to [.filename]#/etc/periodic.conf#. man:newsyslog[8] will rotate these files at the appropriate times: [.programlisting] .... daily_output=/var/log/daily.log weekly_output=/var/log/weekly.log monthly_output=/var/log/monthly.log .... [[configtuning-syslog]] == Configuring System Logging Generating and reading system logs is an important aspect of system administration. The information in system logs can be used to detect hardware and software issues as well as application and system configuration errors. This information also plays an important role in security auditing and incident response. Most system daemons and applications will generate log entries. FreeBSD provides a system logger, man:syslogd[8], to manage logging. By default, syslogd is enabled and started when the system boots. This section describes how to configure the FreeBSD system logger for both local and remote logging and how to perform log rotation and log management. === Configuring Local Logging The configuration file, [.filename]#/etc/syslog.conf#, controls what syslogd does with log entries as they are received. There are several parameters to control the handling of incoming events. The _facility_ describes which subsystem generated the message, such as the kernel or a daemon, and the _level_ describes the severity of the event that occurred. This makes it possible to configure if and where a log message is logged, depending on the facility and level. It is also possible to take action depending on the application that sent the message, and in the case of remote logging, the hostname of the machine generating the logging event. This configuration file contains one line per action, where the syntax for each line is a selector field followed by an action field. The syntax of the selector field is _facility.level_ which will match log messages from _facility_ at level _level_ or higher. It is also possible to add an optional comparison flag before the level to specify more precisely what is logged. Multiple selector fields can be used for the same action, and are separated with a semicolon (`;`). Using `*` will match everything. The action field denotes where to send the log message, such as to a file or remote log host. As an example, here is the default [.filename]#/etc/syslog.conf# from FreeBSD: [.programlisting] .... # Spaces ARE valid field separators in this file. However, # other *nix-like systems still insist on using tabs as field # separators. If you are sharing this file between systems, you # may want to use only tabs as field separators here. # Consult the syslog.conf(5) manpage. *.err;kern.warning;auth.notice;mail.crit /dev/console <.> *.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err /var/log/messages security.* /var/log/security auth.info;authpriv.info /var/log/auth.log mail.info /var/log/maillog <.> cron.* /var/log/cron !-devd *.=debug /var/log/debug.log <.> *.emerg * daemon.info /var/log/daemon.log # uncomment this to log all writes to /dev/console to /var/log/console.log # touch /var/log/console.log and chmod it to mode 600 before it will work #console.info /var/log/console.log # uncomment this to enable logging of all log messages to /var/log/all.log # touch /var/log/all.log and chmod it to mode 600 before it will work #*.* /var/log/all.log # uncomment this to enable logging to a remote loghost named loghost #*.* @loghost # uncomment these if you're running inn # news.crit /var/log/news/news.crit # news.err /var/log/news/news.err # news.notice /var/log/news/news.notice # Uncomment this if you wish to see messages produced by devd # !devd # *.>=notice /var/log/devd.log <.> !* include /etc/syslog.d include /usr/local/etc/syslog.d .... <.> Matches all messages with a level of `err` or higher, as well as `kern.warning`, `auth.notice` and `mail.crit`, and sends these log messages to the console ([.filename]#/dev/console#). <.> Matches all messages from the `mail` facility at level `info` or above and logs the messages to [.filename]#/var/log/maillog#. <.> Uses a comparison flag (`=`) to only match messages at level `debug` and logs them to [.filename]#/var/log/debug.log#. <.> Is an example usage of a program specification. This makes the rules following it only valid for the specified program. In this case, only the messages generated by man:devd[8] are logged to [.filename]#/var/log/devd.log#. For more information about [.filename]#/etc/syslog.conf#, its syntax, and more advanced usage examples, see man:syslog.conf[5]. [[logging-facilities]] === Logging Facilities A facility describes the part of the system generating the message. Facilities are a way of separating the different messages so that it is easier for the user to consult the logs. .syslog facilities [options="header", cols="1,1"] |=== | Name | Description | auth | The authorization system: man:login[1], man:su[1], man:getty[8], etc. | authpriv | The same as auth, but logged to a file readable only by root. | console | Messages written to [.filename]#/dev/console# by the kernel console output driver. | cron | Messages written by the man:cron[8] daemon. | daemon | System daemons, such as man:routed[8], that are not provided for explicitly by other facilities. | ftp | The file transfer protocol daemons: man:ftpd[8], man:tftpd[8]. | kern | Messages generated by the kernel. These cannot be generated by any user processes. | lpr | The line printer spooling system: man:lpr[1], man:lpc[8], man:lpd[8], etc. | mail | The mail system. | mark | This facility adds a record every 20 minutes. | news | The network news system. | ntp | The network time protocol system. | security | Security subsystems, such as man:ipfw[4]. | syslog | Messages generated internally by syslogd(8). | user | Messages generated by random user processes. *This is the default facility identifier if none is specified*. | uucp | The Unix-to-Unix Copy system. An ancient protocol. Really weird to see messages from this facility. | local0 through local7 | Reserved for local use. |=== [[logging-levels]] === Logging Levels The level describes the severity of the message, and is a keyword from the following ordered list (higher to lower): .syslog levels [options="header", cols="1,1"] |=== | Name | Description | emerg | A panic condition. This is normally broadcast to all users. | alert | A condition that should be corrected immediately, such as a corrupted system database. | crit | Critical conditions, e.g., hard device errors. | err | Errors. | warning | Warning messages. | notice | Conditions that are not error conditions, but should possibly be handled specially. | info | Informational messages. | debug | Messages that contain information normally of use only when debugging a program. | none | This special level disables a particular facility. |=== [[read-log-messages]] === Read Log Messages By default FreeBSD log files use the format link:https://datatracker.ietf.org/doc/html/rfc3164[rfc3164], also known as The BSD syslog Protocol. Learn more about other formats and how to use them at man:syslog[8]. Typically the logs have the following syntax: [.programlisting] .... date time hostname program[pid]: the message .... The output of the [.filename]#/var/log/cron# file will be used as an example: [.programlisting] .... [...] Jul 16 12:40:00 FreeBSD /usr/sbin/cron[81519]: (root) CMD (/usr/libexec/atrun) Jul 16 12:44:00 FreeBSD /usr/sbin/cron[83072]: (operator) CMD (/usr/libexec/save-entropy) [...] .... Verbose logging, so the facility and the level on each message will be added, can be enabled in man:syslog[8] by running the following command: [source,shell] .... # sysrc syslogd_flags="-vv" .... Once the function is activated, the facility and the level will be displayed in the log as shown in the following example: [.programlisting] .... [...] Jul 16 17:40:00 FreeBSD /usr/sbin/cron[1016]: (root) CMD (/usr/libexec/atrun) Jul 16 17:44:00 FreeBSD /usr/sbin/cron[1030]: (operator) CMD (/usr/libexec/save-entropy) [...] .... === Log Management and Rotation Log files can grow quickly, taking up disk space and making it more difficult to locate useful information. In FreeBSD, man:newsyslog[8] is used to manage log files and attempt to mitigate this. This built-in program periodically rotates and compresses log files, and optionally creates missing log files and signals programs when log files are moved. [NOTE] ==== Since newsyslog is run from man:cron[8], it cannot rotate files more often than it is scheduled to run from man:cron[8]. In the default configuration, it runs every hour. ==== Here is the default configuration in FreeBSD, more information in man:newsyslog.conf[5]: [.programlisting] .... # configuration file for newsyslog # # Entries which do not specify the '/pid_file' field will cause the # syslogd process to be signalled when that log file is rotated. This # action is only appropriate for log files which are written to by the # syslogd process (ie, files listed in /etc/syslog.conf). If there # is no process which needs to be signalled when a given log file is # rotated, then the entry for that file should include the 'N' flag. # # Note: some sites will want to select more restrictive protections than the # defaults. In particular, it may be desirable to switch many of the 644 # entries to 640 or 600. For example, some sites will consider the # contents of maillog, messages, and lpd-errs to be confidential. In the # future, these defaults may change to more conservative ones. # # logfilename [owner:group] mode count size when flags [/pid_file] [sig_num] /var/log/all.log 600 7 * @T00 J /var/log/auth.log 600 7 1000 @0101T JC /var/log/console.log 600 5 1000 * J /var/log/cron 600 3 1000 * JC /var/log/daily.log 640 7 * @T00 JN /var/log/debug.log 600 7 1000 * JC /var/log/init.log 644 3 1000 * J /var/log/kerberos.log 600 7 1000 * J /var/log/maillog 640 7 * @T00 JC /var/log/messages 644 5 1000 @0101T JC /var/log/monthly.log 640 12 * $M1D0 JN /var/log/devd.log 644 3 1000 * JC /var/log/security 600 10 1000 * JC /var/log/utx.log 644 3 * @01T05 B /var/log/weekly.log 640 5 * $W6D0 JN /var/log/daemon.log 644 5 1000 @0101T JC /etc/newsyslog.conf.d/[!.]*.conf /usr/local/etc/newsyslog.conf.d/[!.]*.conf .... . `logfilename` - Name of the system log file to be archived. . `[owner:group]` - This optional field specifies the owner and group for the archive file. . `mode` - Specify the file mode of the log file and archives. Valid mode bits are 0666. (That is, read and write permissions for the rotated log may be specified for the owner, group, and others.) . `count` - Specify the maximum number of archive files which may exist. . `size` - When the size of the log file reaches size in kilobytes, the log file will be trimmed as described above. If this field contains an asterisk ('*'), the log file will not be trimmed based on size. . `when` - Consist of an interval, a specific time, or both. Supported options in man:newsyslog.conf[5]. . `flags` - Indicates the flags that newsyslog accepts, supported options in man:newsyslog.conf[5]. . `[/pid_file]` - This optional field specifies the file name containing a daemon's process ID or to find a group process ID. . `[sig_num]` - This optional field specifies the signal that will be sent to the daemon process. [NOTE] ==== The last two fields are optional and specify the name of the Process ID (PID) file of a process and a signal number to send to that process when the file is rotated. ==== [[network-syslogd]] === Configuring Remote Logging Monitoring the log files of multiple hosts can become unwieldy as the number of systems increases. Configuring centralized logging can reduce some of the administrative burden of log file administration. In FreeBSD, centralized log file aggregation, merging, and rotation can be configured using syslogd and newsyslog. This section demonstrates an example configuration, where host `A`, named `logserv.example.com`, will collect logging information for the local network. Host `B`, named `logclient.example.com`, will be configured to pass logging information to the logging server. ==== Log Server Configuration A log server is a system that has been configured to accept logging information from other hosts. Before configuring a log server, check the following: * If there is a firewall between the logging server and any logging clients, ensure that the firewall ruleset allows UDP port 514 for both the clients and the server. * The logging server and all client machines must have forward and reverse entries in the local DNS. If the network does not have a DNS server, create entries in each system's [.filename]#/etc/hosts#. Proper name resolution is required so that log entries are not rejected by the logging server. On the log server, edit [.filename]#/etc/syslog.conf# to specify the name of the client to receive log entries from, the logging facility to be used, and the name of the log to store the host's log entries. This example adds the hostname of `B`, logs all facilities, and stores the log entries in [.filename]#/var/log/logclient.log#. .Sample Log Server Configuration [example] ==== [.programlisting] .... +logclient.example.com *.* /var/log/logclient.log .... ==== When adding multiple log clients, add a similar two-line entry for each client. More information about the available facilities may be found in man:syslog.conf[5]. Next, execute the following commands: [source,shell] .... # sysrc syslogd_enable="YES" # sysrc syslogd_flags="-a logclient.example.com -v -v" .... The first entry starts syslogd at system boot. The second entry allows log entries from the specified client. The `-v -v` increases the verbosity of logged messages. This is useful for tweaking facilities as administrators are able to see what type of messages are being logged under each facility. Multiple `-a` options may be specified to allow logging from multiple clients. IP addresses and whole netblocks may also be specified. Refer to man:syslogd[8] for a full list of possible options. Finally, create the log file: [source,shell] .... # touch /var/log/logclient.log .... At this point, syslogd should be restarted and verified: [source,shell] .... # service syslogd restart # pgrep syslog .... If a PID is returned, the server restarted successfully, and client configuration can begin. If the server did not restart, consult [.filename]#/var/log/messages# for the error. ==== Log Client Configuration A logging client sends log entries to a logging server on the network. The client also keeps a local copy of its own logs. Once a logging server has been configured, execute the following commands on the logging client: [source,shell] .... # sysrc syslogd_enable="YES" # sysrc syslogd_flags="-s -v -v" .... The first entry enables syslogd on boot up. The second entry prevents logs from being accepted by this client from other hosts (`-s`) and increases the verbosity of logged messages. Next, define the logging server in the client's [.filename]#/etc/syslog.conf#. In this example, all logged facilities are sent to a remote system, denoted by the `@` symbol, with the specified hostname: [.programlisting] .... *.* @logserv.example.com .... After saving the edit, restart syslogd for the changes to take effect: [source,shell] .... # service syslogd restart .... To test that log messages are being sent across the network, use man:logger[1] on the client to send a message to syslogd: [source,shell] .... # logger "Test message from logclient" .... This message should now exist both in [.filename]#/var/log/messages# on the client and [.filename]#/var/log/logclient.log# on the log server. ==== Debugging Log Servers If no messages are being received on the log server, the cause is most likely a network connectivity issue, a hostname resolution issue, or a typo in a configuration file. To isolate the cause, ensure that both the logging server and the logging client are able to `ping` each other using the hostname specified in their [.filename]#/etc/rc.conf#. If this fails, check the network cabling, the firewall ruleset, and the hostname entries in the DNS server or [.filename]#/etc/hosts# on both the logging server and clients. Repeat until the `ping` is successful from both hosts. If the `ping` succeeds on both hosts but log messages are still not being received, temporarily increase logging verbosity to narrow down the configuration issue. In the following example, [.filename]#/var/log/logclient.log# on the logging server is empty and [.filename]#/var/log/messages# on the logging client does not indicate a reason for the failure. To increase debugging output, edit the `syslogd_flags` entry on the logging server and issue a restart: [source,shell] .... sysrc syslogd_flags="-d -a logclient.example.com -v -v" .... [source,shell] .... # service syslogd restart .... Debugging data similar to the following will flash on the console immediately after the restart: [.programlisting] .... logmsg: pri 56, flags 4, from logserv.example.com, msg syslogd: restart syslogd: restarted logmsg: pri 6, flags 4, from logserv.example.com, msg syslogd: kernel boot file is /boot/kernel/kernel Logging to FILE /var/log/messages syslogd: kernel boot file is /boot/kernel/kernel cvthname(192.168.1.10) validate: dgram from IP 192.168.1.10, port 514, name logclient.example.com; rejected in rule 0 due to name mismatch. .... In this example, the log messages are being rejected due to a typo which results in a hostname mismatch. The client's hostname should be `logclient`, not `logclien`. Fix the typo, issue a restart, and verify the results: [source,shell] .... # service syslogd restart .... The output should be similar to the following: [.programlisting] .... logmsg: pri 56, flags 4, from logserv.example.com, msg syslogd: restart syslogd: restarted logmsg: pri 6, flags 4, from logserv.example.com, msg syslogd: kernel boot file is /boot/kernel/kernel syslogd: kernel boot file is /boot/kernel/kernel logmsg: pri 166, flags 17, from logserv.example.com, msg Dec 10 20:55:02 logserv.example.com syslogd: exiting on signal 2 cvthname(192.168.1.10) validate: dgram from IP 192.168.1.10, port 514, name logclient.example.com; accepted in rule 0. logmsg: pri 15, flags 0, from logclient.example.com, msg Dec 11 02:01:28 trhodes: Test message 2 Logging to FILE /var/log/logclient.log Logging to FILE /var/log/messages .... At this point, the messages are being properly received and placed in the correct file. ==== Security Considerations As with any network service, security requirements should be considered before implementing a logging server. Log files may contain sensitive data about services enabled on the local host, user accounts, and configuration data. Network data sent from the client to the server will not be encrypted or password protected. If a need for encryption exists, consider using package:security/stunnel[], which will transmit the logging data over an encrypted tunnel. Local security is also an issue. Log files are not encrypted during use or after log rotation. Local users may access log files to gain additional insight into system configuration. Setting proper permissions on log files is critical. The built-in log rotator, newsyslog, supports setting permissions on newly created and rotated log files. Setting log files to mode `600` should prevent unwanted access by local users. Refer to man:newsyslog.conf[5] for additional information. [[acpi-overview]] == Power and Resource Management It is important to utilize hardware resources in an efficient manner. Power and resource management allows the operating system to monitor system limits and to possibly run some actions triggered by events related to those limits. [[acpi-config]] === ACPI configuration On FreeBSD the management of these resources is managed by the man:acpi[4] kernel device. [NOTE] ==== In FreeBSD the man:acpi[4] driver is loaded by default at system boot. This driver *cannot be unloaded after boot* because the system bus uses it for various hardware interactions. ==== In addition to man:acpi[4], FreeBSD has several dedicated kernel modules for various ACPI vendor subsystems. These modules will add some extra functionality like fan speed, keyboard backlit or screen brightness. The list can be obtained by running the following command: [source,shell] .... % ls /boot/kernel | grep acpi .... The output should be similar to the following: [.programlisting] .... acpi_asus.ko acpi_asus_wmi.ko acpi_dock.ko acpi_fujitsu.ko acpi_hp.ko acpi_ibm.ko acpi_panasonic.ko acpi_sony.ko acpi_toshiba.ko acpi_video.ko acpi_wmi.ko sdhci_acpi.ko uacpi.ko .... In the event that, for example, an IBM/Lenovo laptop is used, it will be necessary to load the module man:acpi_ibm[4] by executing the following command: [source,shell] .... # kldload acpi_ibm .... And add this line to [.filename]#/boot/loader.conf# to load it at boot: [.programlisting] .... acpi_ibm_load="YES" .... An alternative to the man:acpi_video[4] module is the man:backlight[9] driver. It provides a generic way for handling a panel backlight. The default GENERIC kernel includes this driver. The man:backlight[8] utility can be used to query and adjust the brightness of the panel backlight. In this example the brightness is decreased by 10%: [source,shell] .... % backlight decr 10 .... [[cpu-power-management]] === CPU Power Management CPU is the most consuming part of the system. Knowing how to improve CPU efficiency is a fundamental part of our system in order to save energy. In order to make proper use of the machine's resources in a correct way, FreeBSD supports technologies such as Intel Turbo Boost, AMD Turbo Core, Intel Speed Shift among others through the use of man:powerd[8] and man:cpufreq[4]. The first step will be to obtain the CPU information by executing the following command: [source,shell] .... % sysctl dev.cpu.0 <.> .... <.> In this case the `0` digit represents the first core of the CPU. The output should be similar to the following: [.programlisting] .... dev.cpu.0.cx_method: C1/mwait/hwc C2/mwait/hwc C3/mwait/hwc/bma dev.cpu.0.cx_usage_counters: 3507294 0 0 dev.cpu.0.cx_usage: 100.00% 0.00% 0.00% last 3804us dev.cpu.0.cx_lowest: C3 <1> dev.cpu.0.cx_supported: C1/1/1 C2/2/1 C3/3/57 <2> dev.cpu.0.freq_levels: 2267/35000 2266/35000 1600/15000 800/12000 <3> dev.cpu.0.freq: 1600 <4> dev.cpu.0.temperature: 40.0C <5> dev.cpu.0.coretemp.throttle_log: 0 dev.cpu.0.coretemp.tjmax: 105.0C dev.cpu.0.coretemp.resolution: 1 dev.cpu.0.coretemp.delta: 65 dev.cpu.0.%parent: acpi0 dev.cpu.0.%pnpinfo: _HID=none _UID=0 _CID=none dev.cpu.0.%location: handle=\_PR_.CPU0 dev.cpu.0.%driver: cpu dev.cpu.0.%desc: ACPI CPU .... <1> Lowest Cx state to use for idling the CPU. <2> CPU supported Cx states. <3> Currently available levels for the CPU (frequency/power usage). <4> Current active CPU frequency in MHz. <5> Current temperature of the CPU. [NOTE] ==== If the temperature information is not displayed, load the man:coretemp[4] module. In case of using an AMD CPU, load the man:amdtemp[4] module. ==== Once the CPU information is available the easiest way to configure power saving is to let man:powerd[8] take over. Enable man:powerd[8] service in [.filename]#/etc/rc.conf# to start at system boot: [source,shell] .... # sysrc powerd_enable=YES .... It will also be necessary to indicate certain parameters to man:powerd[8] to tell it how to manage the state of the CPU executing the following command: [source,shell] .... # sysrc powerd_flags="-a hiadaptive -i 25 -r 85 -N" .... . `-a`: Selects the mode to use while on AC power. . `hiadaptive`: Operation mode. More info at man:powerd[8]. . `-i`: Specifies the CPU load percent level when adaptive mode should begin to degrade performance to save power. . `-r`: Specifies the CPU load percent level where adaptive mode should consider the CPU running and increase performance. . `-N`: Treat "nice" time as idle for the purpose of load calculation; i.e., do not increase the CPU frequency if the CPU is only busy with "nice" processes. And then enable the service executing the following command: [source,shell] .... # service powerd start .... [[cpufreq]] === CPU Frequency Control FreeBSD includes a generic man:cpufreq[4] driver to allow the administrator, or software such as man:powerd[8] and package:sysutils/powerdxx[], to manage the frequency of the CPU to achieve the desired balance between performance and economy. A lower setting will save power while reducing the heat generated by the CPU. A higher setting will increase performance at the cost of using additional power and generating more heat. [[est]] === Intel(R) Enhanced Speed Step(TM) The Intel(R) Enhanced Speed Step(TM) driver, man:est[4], replaces the generic man:cpufreq[4] driver for CPUs that provide this feature. The CPU frequency can be statically adjusted using man:sysctl[8], or with the `/etc/rc.d/power_profile` startup script. Additional software, such as man:powerd[8] or package:sysutils/powerdxx[], can be used to automatically adjust the CPU frequency based on processor utilization. Each supported frequency, along with its expected power consumption, can be listed by examining the man:sysctl[3] tree: [source,shell] .... # sysctl dev.cpufreq.0.freq_driver dev.cpu.0.freq_levels dev.cpu.0.freq .... The output should be similar to the following: [.programlisting] .... dev.cpufreq.0.freq_driver: est0 dev.cpu.0.freq_levels: 3001/53000 3000/53000 2900/50301 2700/46082 2600/43525 2400/39557 2300/37137 2100/33398 2000/31112 1800/27610 1700/25455 1500/22171 1400/20144 1200/17084 1100/15181 900/12329 800/10550 dev.cpu.0.freq: 800 .... A frequency 1 MHz higher than the maximum frequency of the CPU indicates the Intel(R) Turbo Boost(TM) feature. [[hwpstate_intel]] === Intel Speed Shift(TM) Users running newer Intel(R) CPUs may find some differences in dynamic frequency control when upgrading to FreeBSD 13. A new driver for the Intel(R) Speed Shift(TM) feature set, available on certain SKUs, exposes the ability for the hardware to dynamically vary the core frequencies, including on a per core basis. FreeBSD 13 comes with the man:hwpstate_intel[4] driver to automatically enable Speed Shift(TM) control on equipped CPUs, replacing the older Enhanced Speed Step(TM) man:est[4] driver. The man:sysctl[8] `dev.cpufreq.%d.freq_driver` will indicate if the system is using Speed Shift. To determine which frequency control driver is being used, examining the `dev.cpufreq.0.freq_driver` oid. [source,shell] .... # sysctl dev.cpufreq.0.freq_driver .... The output should be similar to the following: [.programlisting] .... dev.cpufreq.0.freq_driver: hwpstate_intel0 .... This indicates that the new man:hwpstate_intel[4] driver is in use. On such systems, the oid `dev.cpu.%d.freq_levels` will show only the maximum CPU frequency, and will indicate a power consumption level of `-1`. The current CPU frequency can be determined by examining the `dev.cpu.%d.freq` oid. [source,shell] .... # sysctl dev.cpu.0.freq_levels dev.cpu.0.freq .... The output should be similar to the following: [.programlisting] .... dev.cpu.0.freq_levels: 3696/-1 dev.cpu.0.freq: 898 .... For more information, including on how to balance performance and energy use, and on how to disable this driver, refer to the man page man:hwpstate_intel[4]. [NOTE] ==== Users accustomed to using man:powerd[8] or package:sysutils/powerdxx[] will find these utilities have been superseded by the man:hwpstate_intel[4] driver and no longer work as expected. ==== [[graphics-card-power-management]] === Graphics Card Power Management Graphics cards have become a fundamental part of computing in recent years. Some graphics cards may have excessive power consumption. FreeBSD allows certain configurations to improve power consumption. In case of using a Intel(R) graphics card with the package:graphics/drm-kmod[] driver these options can be added to [.filename]#/boot/loader.conf#: [.programlisting] .... compat.linuxkpi.fastboot=1 <.> compat.linuxkpi.enable_dc=2 <.> compat.linuxkpi.enable_fbc=1 <.> .... <.> Try to skip unnecessary mode sets at boot time. <.> Enable power-saving display C-states. <.> Enable frame buffer compression for power savings === Suspend/Resume The suspend/resume function allows the machine to be kept in a state in which there is no a big energy consumption and allows the system to be resumed without having to lose the state of the running programs. [NOTE] ==== In order for the suspend/resume functionality to work correctly the graphics drivers must be loaded on the system. In non-KMS-supported graphics cards man:sc[4] must be used not to break the suspend/resume functionality. More information about which driver to use and how to configure it can be found at the crossref:x11[x11, The X Window System chapter]. ==== man:acpi[4] supports the next list of sleep states: .Supported Sleep States [options="header", cols="1,1"] |=== |S1 |Quick suspend to RAM. The CPU enters a lower power state, but most peripherals are left running. |S2 |Lower power state than S1, but with the same basic characteristics. Not supported by many systems. |S3 (Sleep mode) |Suspend to RAM. Most devices are powered off, and the system stops running except for memory refresh. |S4 (Hibernation) |Suspend to disk. All devices are powered off, and the system stops running. When resuming, the system starts as if from a cold power on. *Not yet supported by FreeBSD*. |S5 |System shuts down cleanly and powers off. |=== [[configure-suspend-resume]] ==== Configuring Suspend/Resume The first step will be to know which type of sleep states supports the hardware we are using executing the following command: [source,shell] .... % sysctl hw.acpi.supported_sleep_state .... The output should be similar to the following: [.programlisting] .... hw.acpi.supported_sleep_state: S3 S4 S5 .... [WARNING] ==== As stated above FreeBSD does *not* yet support the `S4` state. ==== man:acpiconf[8] can be used to check if the `S3` state works correctly by running the following command, if it succeeds, the screen should go black and the machine will turn off: [source,shell] .... # acpiconf -s 3 .... In the vast majority of cases the Suspend/Resume functionality wants to be used on a laptop. FreeBSD can be configured to enter the `S3` state when closing the lid by adding the following line to the [.filename]#/etc/sysctl.conf# file. [.programlisting] .... hw.acpi.lid_switch_state=S3 .... [[troubleshooting-suspend-resume]] ==== Troubleshooting in Suspend/Resume A lot of effort has been made to make the Suspend and Resume functions work properly and in the best way on FreeBSD. But currently the Suspend and Resume functions only work properly on some specific laptops. Some checks can be done in case it doesn't work properly. In some cases it is enough to turn off the bluetooth. In others it is enough loading the correct driver for the graphics card, etc. In case it doesn't work correctly, some tips can be found on the FreeBSD Wiki in the section link:https://wiki.freebsd.org/SuspendResume[Suspend/Resume]. [[adding-swap-space]] == Adding Swap Space Sometimes a FreeBSD system requires more swap space. This section describes two methods to increase swap space: adding swap to an existing partition or new hard drive, and creating a swap file on an existing file system. For information on how to encrypt swap space, which options exist, and why it should be done, refer to crossref:disks[swap-encrypting,“Encrypting Swap”]. [[new-drive-swap]] === Swap on a New Hard Drive or Existing Partition Adding a new drive for swap gives better performance than using a partition on an existing drive. Setting up partitions and drives is explained in crossref:disks[disks-adding,"Adding Disks"] while crossref:bsdinstall[configtuning-initial,"Designing the Partition Layout"] discusses partition layouts and swap partition size considerations. [WARNING] ==== It is possible to use any partition not currently mounted, even if it already contains data. Using `swapon` on a partition that contains data will overwrite and destroy that data. Make sure that the partition to be added as swap is really the intended partition before running `swapon`. ==== man:swapon[8] can be used to add a swap partition to the system executing the following command: [source,shell] .... # swapon /dev/ada1p2 .... To automatically add this swap partition on boot, add an entry to [.filename]#/etc/fstab#: [.programlisting] .... /dev/ada1p2 none swap sw 0 0 .... See man:fstab[5] for an explanation of the entries in [.filename]#/etc/fstab#. [[create-swapfile]] === Creating a Swap File [[swapfile-10-and-later]] These examples create a 512M swap file called [.filename]#/usr/swap0#. [WARNING] ==== Swap files on ZFS file systems are strongly discouraged, as swapping can lead to system hangs. ==== The first step is to create the swap file: [source,shell] .... # dd if=/dev/zero of=/usr/swap0 bs=1m count=512 .... The second step is to put the proper permissions on the new file: [source,shell] .... # chmod 0600 /usr/swap0 .... The third step is to inform the system about the swap file by adding a line to [.filename]#/etc/fstab#: [.programlisting] .... md none swap sw,file=/usr/swap0,late 0 0 .... Swap space will be added on system startup. To add swap space immediately, use man:swapon[8]: [source,shell] .... # swapon -aL .... diff --git a/documentation/content/en/books/handbook/firewalls/_index.adoc b/documentation/content/en/books/handbook/firewalls/_index.adoc index 0b8f580471..44d7155172 100644 --- a/documentation/content/en/books/handbook/firewalls/_index.adoc +++ b/documentation/content/en/books/handbook/firewalls/_index.adoc @@ -1,2692 +1,2692 @@ --- title: Chapter 33. Firewalls part: IV. Network Communication prev: books/handbook/network-servers next: books/handbook/advanced-networking description: "FreeBSD has three firewalls built into the base system: PF, IPFW, and IPFILTER. This chapter covers how to define packet filtering rules, the differences between the firewalls built into FreeBSD and how to use them" tags: ["firewall", "pf", "ipfw", "ipfilter", "blocklistd", "filtering"] showBookMenu: true weight: 38 params: path: "/books/handbook/firewalls/" --- [[firewalls]] = Firewalls :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 33 :partnums: :source-highlighter: rouge :experimental: :images-path: books/handbook/firewalls/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[firewalls-intro]] == Synopsis Firewalls make it possible to filter the incoming and outgoing traffic that flows through a system. A firewall can use one or more sets of "rules" to inspect network packets as they come in or go out of network connections and either allows the traffic through or blocks it. The rules of a firewall can inspect one or more characteristics of the packets such as the protocol type, source or destination host address, and source or destination port. Firewalls can enhance the security of a host or a network. They can be used to do one or more of the following: * Protect and insulate the applications, services, and machines of an internal network from unwanted traffic from the public Internet. * Limit or disable access from hosts of the internal network to services of the public Internet. * Support network address translation (NAT), which allows an internal network to use private IP addresses and share a single connection to the public Internet using either a single IP address or a shared pool of automatically assigned public addresses. FreeBSD has three firewalls built into the base system: PF, IPFW, and IPFILTER, also known as IPF. FreeBSD also provides two traffic shapers for controlling bandwidth usage: man:altq[4] and man:dummynet[4]. ALTQ has traditionally been closely tied with PF and dummynet with IPFW. Each firewall uses rules to control the access of packets to and from a FreeBSD system, although they go about it in different ways and each has a different rule syntax. FreeBSD provides multiple firewalls in order to meet the different requirements and preferences for a wide variety of users. Each user should evaluate which firewall best meets their needs. Read this chapter to learn: * How to define packet filtering rules. * The differences between the firewalls built into FreeBSD. * How to use and configure the PF firewall. * How to use and configure the IPFW firewall. * How to use and configure the IPFILTER firewall. Before reading this chapter: * Understand basic FreeBSD and Internet concepts. [NOTE] ==== Since all firewalls are based on inspecting the values of selected packet control fields, the creator of the firewall ruleset must have an understanding of how TCP/IP works, what the different values in the packet control fields are, and how these values are used in a normal session conversation. For a good introduction, refer to http://www.ipprimer.com[Daryl's TCP/IP Primer]. ==== [[firewalls-concepts]] == Firewall Concepts A ruleset contains a group of rules which pass or block packets based on the values contained in the packet. The bi-directional exchange of packets between hosts comprises a session conversation. The firewall ruleset processes both the packets arriving from the public Internet, as well as the packets produced by the system as a response to them. Each TCP/IP service is predefined by its protocol and listening port. Packets destined for a specific service originate from the source address using an unprivileged port and target the specific service port on the destination address. All the above parameters can be used as selection criteria to create rules which will pass or block services. To lookup unknown port numbers, refer to [.filename]#/etc/services#. Alternatively, visit https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers[https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers] and do a port number lookup to find the purpose of a particular port number. Check out this link for http://web.archive.org/web/20150803024617/http://www.sans.org/security-resources/idfaq/oddports.php[port numbers used by Trojans]. FTP has two modes: active mode and passive mode. The difference is in how the data channel is acquired. Passive mode is more secure as the data channel is acquired by the ordinal ftp session requester. For a good explanation of FTP and the different modes, see http://www.slacksite.com/other/ftp.html[http://www.slacksite.com/other/ftp.html]. A firewall ruleset can be either "exclusive" or "inclusive". An exclusive firewall allows all traffic through except for the traffic matching the ruleset. An inclusive firewall does the reverse as it only allows traffic matching the rules through and blocks everything else. An inclusive firewall offers better control of the outgoing traffic, making it a better choice for systems that offer services to the public Internet. It also controls the type of traffic originating from the public Internet that can gain access to a private network. All traffic that does not match the rules is blocked and logged. Inclusive firewalls are generally safer than exclusive firewalls because they significantly reduce the risk of allowing unwanted traffic. [NOTE] ==== Unless noted otherwise, all configuration and example rulesets in this chapter create inclusive firewall rulesets. ==== Security can be tightened further using a "stateful firewall". This type of firewall keeps track of open connections and only allows traffic which either matches an existing connection or opens a new, allowed connection. Stateful filtering treats traffic as a bi-directional exchange of packets comprising a session. When state is specified on a matching rule the firewall dynamically generates internal rules for each anticipated packet being exchanged during the session. It has sufficient matching capabilities to determine if a packet is valid for a session. Any packets that do not properly fit the session template are automatically rejected. When the session completes, it is removed from the dynamic state table. Stateful filtering allows one to focus on blocking/passing new sessions. If the new session is passed, all its subsequent packets are allowed automatically and any impostor packets are automatically rejected. If a new session is blocked, none of its subsequent packets are allowed. Stateful filtering provides advanced matching abilities capable of defending against the flood of different attack methods employed by attackers. NAT stands for _Network Address Translation_. NAT function enables the private LAN behind the firewall to share a single ISP-assigned IP address, even if that address is dynamically assigned. NAT allows each computer in the LAN to have Internet access, without having to pay the ISP for multiple Internet accounts or IP addresses. NAT will automatically translate the private LAN IP address for each system on the LAN to the single public IP address as packets exit the firewall bound for the public Internet. It also performs the reverse translation for returning packets. According to RFC 1918, the following IP address ranges are reserved for private networks which will never be routed directly to the public Internet, and therefore are available for use with NAT: * `10.0.0.0/8`. * `172.16.0.0/12`. * `192.168.0.0/16`. [WARNING] ==== When working with the firewall rules, be _very careful_. Some configurations _can lock the administrator out_ of the server. To be on the safe side, consider performing the initial firewall configuration from the local console rather than doing it remotely over ssh. ==== [[firewalls-pf]] == PF Since FreeBSD 5.3, a ported version of OpenBSD's PF firewall has been included as an integrated part of the base system. PF is a complete, full-featured firewall that has optional support for ALTQ (Alternate Queuing), which provides Quality of Service (QoS). The OpenBSD Project maintains the definitive reference for PF in the http://www.openbsd.org/faq/pf/[PF FAQ]. Peter Hansteen maintains a thorough PF tutorial at http://home.nuug.no/\~peter/pf/[http://home.nuug.no/~peter/pf/]. [WARNING] ==== When reading the http://www.openbsd.org/faq/pf/[PF FAQ], keep in mind that FreeBSD's version of PF has diverged substantially from the upstream OpenBSD version over the years. Not all features work the same way on FreeBSD as they do in OpenBSD and vice versa. ==== The {freebsd-pf} is a good place to ask questions about configuring and running the PF firewall. Check the mailing list archives before asking a question as it may have already been answered. This section of the Handbook focuses on PF as it pertains to FreeBSD. It demonstrates how to enable PF and ALTQ. It also provides several examples for creating rulesets on a FreeBSD system. === Enabling PF To use PF, its kernel module must be first loaded. This section describes the entries that can be added to [.filename]#/etc/rc.conf# to enable PF. Start by adding `pf_enable=yes` to [.filename]#/etc/rc.conf#: [source,shell] .... # sysrc pf_enable=yes .... Additional options, described in man:pfctl[8], can be passed to PF when it is started. Add or change this entry in [.filename]#/etc/rc.conf# and specify any required flags between the two quotes (`""`): [.programlisting] .... pf_flags="" # additional flags for pfctl startup .... PF will not start if it cannot find its ruleset configuration file. By default, FreeBSD does not ship with a ruleset and there is no [.filename]#/etc/pf.conf#. Example rulesets can be found in [.filename]#/usr/share/examples/pf/#. If a custom ruleset has been saved somewhere else, add a line to [.filename]#/etc/rc.conf# which specifies the full path to the file: [.programlisting] .... pf_rules="/path/to/pf.conf" .... Logging support for PF is provided by man:pflog[4]. To enable logging support, add `pflog_enable=yes` to [.filename]#/etc/rc.conf#: [source,shell] .... # sysrc pflog_enable=yes .... The following lines can also be added to change the default location of the log file or to specify any additional flags to pass to man:pflog[4] when it is started: [.programlisting] .... pflog_logfile="/var/log/pflog" # where pflogd should store the logfile pflog_flags="" # additional flags for pflogd startup .... Finally, if there is a LAN behind the firewall and packets need to be forwarded for the computers on the LAN, or NAT is required, enable the following option: [.programlisting] .... gateway_enable="YES" # Enable as LAN gateway .... After saving the needed edits, PF can be started with logging support by typing: [source,shell] .... # service pf start # service pflog start .... By default, PF reads its configuration rules from [.filename]#/etc/pf.conf# and modifies, drops, or passes packets according to the rules or definitions specified in this file. The FreeBSD installation includes several sample files located in [.filename]#/usr/share/examples/pf/#. Refer to the http://www.openbsd.org/faq/pf/[PF FAQ] for complete coverage of PF rulesets. To control PF, use `pfctl`. crossref:firewalls[pfctl,Useful `pfctl` Options] summarizes some useful options to this command. Refer to man:pfctl[8] for a description of all available options: [[pfctl]] .Useful `pfctl` Options [cols="1,1", frame="none", options="header"] |=== | Command | Purpose |`pfctl -e` |Enable PF. |`pfctl -d` |Disable PF. |`pfctl -F all -f /etc/pf.conf` |Flush all NAT, filter, state, and table rules and reload [.filename]#/etc/pf.conf#. |`pfctl -s [ rules \| nat \| states ]` |Report on the filter rules, NAT rules, or state table. |`pfctl -vnf /etc/pf.conf` |Check [.filename]#/etc/pf.conf# for errors, but do not load ruleset. |=== [TIP] ==== package:security/sudo[] is useful for running commands like `pfctl` that require elevated privileges. It can be installed from the Ports Collection. ==== To keep an eye on the traffic that passes through the PF firewall, consider installing the package:sysutils/pftop[] package or port. Once installed, pftop can be run to view a running snapshot of traffic in a format which is similar to man:top[1]. [[pf-tutorial]] === PF Rulesets This section demonstrates how to create a customized ruleset. It starts with the simplest of rulesets and builds upon its concepts using several examples to demonstrate real-world usage of PF's many features. The simplest possible ruleset is for a single machine that does not run any services and which needs access to one network, which may be the Internet. To create this minimal ruleset, edit [.filename]#/etc/pf.conf# so it looks like this: [.programlisting] .... block in all pass out all keep state .... The first rule denies all incoming traffic by default. The second rule allows connections created by this system to pass out, while retaining state information on those connections. This state information allows return traffic for those connections to pass back and should only be used on machines that can be trusted. The ruleset can be loaded with: [source,shell] .... # pfctl -e ; pfctl -f /etc/pf.conf .... In addition to keeping state, PF provides _lists_ and _macros_ which can be defined for use when creating rules. Macros can include lists and need to be defined before use. As an example, insert these lines at the very top of the ruleset: [.programlisting] .... tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }" udp_services = "{ domain }" .... PF understands port names as well as port numbers, as long as the names are listed in [.filename]#/etc/services#. This example creates two macros. The first is a list of seven TCP port names and the second is one UDP port name. Once defined, macros can be used in rules. In this example, all traffic is blocked except for the connections initiated by this system for the seven specified TCP services and the one specified UDP service: [.programlisting] .... tcp_services = "{ ssh, smtp, domain, www, pop3, auth, pop3s }" udp_services = "{ domain }" block all pass out proto tcp to any port $tcp_services keep state pass proto udp to any port $udp_services keep state .... Even though UDP is considered to be a stateless protocol, PF is able to track some state information. For example, when a UDP request is passed which asks a name server about a domain name, PF will watch for the response to pass it back. Whenever an edit is made to a ruleset, the new rules must be loaded so they can be used: [source,shell] .... # pfctl -f /etc/pf.conf .... If there are no syntax errors, `pfctl` will not output any messages during the rule load. Rules can also be tested before attempting to load them: [source,shell] .... # pfctl -nf /etc/pf.conf .... Including `-n` causes the rules to be interpreted only, but not loaded. This provides an opportunity to correct any errors. At all times, the last valid ruleset loaded will be enforced until either PF is disabled or a new ruleset is loaded. [TIP] ==== Adding `-v` to a `pfctl` ruleset verify or load will display the fully parsed rules exactly the way they will be loaded. This is extremely useful when debugging rules. ==== [[pftut-gateway]] ==== A Simple Gateway with NAT This section demonstrates how to configure a FreeBSD system running PF to act as a gateway for at least one other machine. The gateway needs at least two network interfaces, each connected to a separate network. In this example, [.filename]#xl0# is connected to the Internet and [.filename]#xl1# is connected to the internal network. First, enable the gateway to let the machine forward the network traffic it receives on one interface to another interface. This sysctl setting will forward IPv4 packets: [source,shell] .... # sysctl net.inet.ip.forwarding=1 .... To forward IPv6 traffic, use: [source,shell] .... # sysctl net.inet6.ip6.forwarding=1 .... To enable these settings at system boot, use man:sysrc[8] to add them to [.filename]#/etc/rc.conf#: [source,shell] .... # sysrc gateway_enable=yes # sysrc ipv6_gateway_enable=yes .... Verify with `ifconfig` that both of the interfaces are up and running. Next, create the PF rules to allow the gateway to pass traffic. While the following rule allows stateful traffic from hosts of the internal network to pass to the gateway, the `to` keyword does not guarantee passage all the way from source to destination: [.programlisting] .... pass in on xl1 from xl1:network to xl0:network port $ports keep state .... That rule only lets the traffic pass in to the gateway on the internal interface. To let the packets go further, a matching rule is needed: [.programlisting] .... pass out on xl0 from xl1:network to xl0:network port $ports keep state .... While these two rules will work, rules this specific are rarely needed. For a busy network admin, a readable ruleset is a safer ruleset. The remainder of this section demonstrates how to keep the rules as simple as possible for readability. For example, those two rules could be replaced with one rule: [.programlisting] .... pass from xl1:network to any port $ports keep state .... The `interface:network` notation can be replaced with a macro to make the ruleset even more readable. For example, a `$localnet` macro could be defined as the network directly attached to the internal interface (`$xl1:network`). Alternatively, the definition of `$localnet` could be changed to an _IP address/netmask_ notation to denote a network, such as `192.168.100.1/24` for a subnet of private addresses. If required, `$localnet` could even be defined as a list of networks. Whatever the specific needs, a sensible `$localnet` definition could be used in a typical pass rule as follows: [.programlisting] .... pass from $localnet to any port $ports keep state .... The following sample ruleset allows all traffic initiated by machines on the internal network. It first defines two macros to represent the external and internal 3COM interfaces of the gateway. [NOTE] ==== For dialup users, the external interface will use [.filename]#tun0#. For an ADSL connection, specifically those using PPP over Ethernet (PPPoE), the correct external interface is [.filename]#tun0#, not the physical Ethernet interface. ==== [.programlisting] .... ext_if = "xl0" # macro for external interface - use tun0 for PPPoE int_if = "xl1" # macro for internal interface localnet = $int_if:network # ext_if IP address could be dynamic, hence ($ext_if) nat on $ext_if from $localnet to any -> ($ext_if) block all pass from { lo0, $localnet } to any keep state .... This ruleset introduces the `nat` rule which is used to handle the network address translation from the non-routable addresses inside the internal network to the IP address assigned to the external interface. The parentheses surrounding the last part of the nat rule `($ext_if)` is included when the IP address of the external interface is dynamically assigned. It ensures that network traffic runs without serious interruptions even if the external IP address changes. Note that this ruleset probably allows more traffic to pass out of the network than is needed. One reasonable setup could create this macro: [.programlisting] .... client_out = "{ ftp-data, ftp, ssh, domain, pop3, auth, nntp, http, \ https, cvspserver, 2628, 5999, 8000, 8080 }" .... to use in the main pass rule: [.programlisting] .... pass inet proto tcp from $localnet to any port $client_out \ flags S/SA keep state .... A few other pass rules may be needed. This one enables SSH on the external interface: [.programlisting] .... pass in inet proto tcp to $ext_if port ssh .... This macro definition and rule allows DNS and NTP for internal clients: [.programlisting] .... udp_services = "{ domain, ntp }" pass quick inet proto { tcp, udp } to any port $udp_services keep state .... Note the `quick` keyword in this rule. Since the ruleset consists of several rules, it is important to understand the relationships between the rules in a ruleset. Rules are evaluated from top to bottom, in the sequence they are written. For each packet or connection evaluated by PF, _the last matching rule_ in the ruleset is the one which is applied. However, when a packet matches a rule which contains the `quick` keyword, the rule processing stops and the packet is treated according to that rule. This is very useful when an exception to the general rules is needed. [[pftut-ftp]] ==== Creating an FTP Proxy Configuring working FTP rules can be problematic due to the nature of the FTP protocol. FTP pre-dates firewalls by several decades and is insecure in its design. The most common points against using FTP include: * Passwords are transferred in the clear. * The protocol demands the use of at least two TCP connections (control and data) on separate ports. * When a session is established, data is communicated using randomly selected ports. All of these points present security challenges, even before considering any potential security weaknesses in client or server software. More secure alternatives for file transfer exist, such as man:sftp[1] or man:scp[1], which both feature authentication and data transfer over encrypted connections. For those situations when FTP is required, PF provides redirection of FTP traffic to a small proxy program called man:ftp-proxy[8], which is included in the base system of FreeBSD. The role of the proxy is to dynamically insert and delete rules in the ruleset, using a set of anchors, to correctly handle FTP traffic. To enable the FTP proxy, add this line to [.filename]#/etc/rc.conf#: [.programlisting] .... ftpproxy_enable="YES" .... Then start the proxy by running: [source,bash] .... # service ftp-proxy start .... For a basic configuration, three elements need to be added to [.filename]#/etc/pf.conf#. First, the anchors which the proxy will use to insert the rules it generates for the FTP sessions: [.programlisting] .... nat-anchor "ftp-proxy/*" rdr-anchor "ftp-proxy/*" .... Second, a pass rule is needed to allow FTP traffic in to the proxy. Third, redirection and NAT rules need to be defined before the filtering rules. Insert this `rdr` rule immediately after the `nat` rule: [.programlisting] .... rdr pass on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021 .... Finally, allow the redirected traffic to pass: [.programlisting] .... pass out proto tcp from $proxy to any port ftp .... where `$proxy` expands to the address the proxy daemon is bound to. Save [.filename]#/etc/pf.conf#, load the new rules, and verify from a client that FTP connections are working: [source,shell] .... # pfctl -f /etc/pf.conf .... This example covers a basic setup where the clients in the local network need to contact FTP servers elsewhere. This basic configuration should work well with most combinations of FTP clients and servers. As shown in man:ftp-proxy[8], the proxy's behavior can be changed in various ways by adding options to the `ftpproxy_flags=` line. Some clients or servers may have specific quirks that must be compensated for in the configuration, or there may be a need to integrate the proxy in specific ways such as assigning FTP traffic to a specific queue. For ways to run an FTP server protected by PF and man:ftp-proxy[8], configure a separate `ftp-proxy` in reverse mode, using `-R`, on a separate port with its own redirecting pass rule. [[pftut-icmp]] ==== Managing ICMP Many of the tools used for debugging or troubleshooting a TCP/IP network rely on the Internet Control Message Protocol (ICMP), which was designed specifically with debugging in mind. The ICMP protocol sends and receives _control messages_ between hosts and gateways, mainly to provide feedback to a sender about any unusual or difficult conditions enroute to the target host. Routers use ICMP to negotiate packet sizes and other transmission parameters in a process often referred to as _path MTU discovery_. From a firewall perspective, some ICMP control messages are vulnerable to known attack vectors. Also, letting all diagnostic traffic pass unconditionally makes debugging easier, but it also makes it easier for others to extract information about the network. For these reasons, the following rule may not be optimal: [.programlisting] .... pass inet proto icmp from any to any .... One solution is to let all ICMP traffic from the local network through while stopping all probes from outside the network: [.programlisting] .... pass inet proto icmp from $localnet to any keep state pass inet proto icmp from any to $ext_if keep state .... Additional options are available which demonstrate some of PF's flexibility. For example, rather than allowing all ICMP messages, one can specify the messages used by man:ping[8] and man:traceroute[8]. Start by defining a macro for that type of message: [.programlisting] .... icmp_types = "echoreq" .... and a rule which uses the macro: [.programlisting] .... pass inet proto icmp all icmp-type $icmp_types keep state .... If other types of ICMP packets are needed, expand `icmp_types` to a list of those packet types. Type `more /usr/src/sbin/pfctl/pfctl_parser.c` to see the list of ICMP message types supported by PF. Refer to http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml[http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml] for an explanation of each message type. Since Unix `traceroute` uses UDP by default, another rule is needed to allow Unix `traceroute`: [.programlisting] .... # allow out the default range for traceroute(8): pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state .... Since `TRACERT.EXE` on Microsoft Windows systems uses ICMP echo request messages, only the first rule is needed to allow network traces from those systems. Unix `traceroute` can be instructed to use other protocols as well, and will use ICMP echo request messages if `-I` is used. Check the man:traceroute[8] man page for details. [[pftut-pathmtudisc]] ===== Path MTU Discovery Internet protocols are designed to be device independent, and one consequence of device independence is that the optimal packet size for a given connection cannot always be predicted reliably. The main constraint on packet size is the _Maximum Transmission Unit_ (MTU) which sets the upper limit on the packet size for an interface. Type `ifconfig` to view the MTUs for a system's network interfaces. TCP/IP uses a process known as path MTU discovery to determine the right packet size for a connection. This process sends packets of varying sizes with the "Do not fragment" flag set, expecting an ICMP return packet of "type 3, code 4" when the upper limit has been reached. Type 3 means "destination unreachable", and code 4 is short for "fragmentation needed, but the do-not-fragment flag is set". To allow path MTU discovery in order to support connections to other MTUs, add the `destination unreachable` type to the `icmp_types` macro: [.programlisting] .... icmp_types = "{ echoreq, unreach }" .... Since the pass rule already uses that macro, it does not need to be modified to support the new ICMP type: [.programlisting] .... pass inet proto icmp all icmp-type $icmp_types keep state .... PF allows filtering on all variations of ICMP types and codes. The list of possible types and codes are documented in man:icmp[4] and man:icmp6[4]. [[pftut-tables]] ==== Using Tables Some types of data are relevant to filtering and redirection at a given time, but their definition is too long to be included in the ruleset file. PF supports the use of tables, which are defined lists that can be manipulated without needing to reload the entire ruleset, and which can provide fast lookups. Table names are always enclosed within `< >`, like this: [.programlisting] .... table { 192.168.2.0/24, !192.168.2.5 } .... In this example, the `192.168.2.0/24` network is part of the table, except for the address `192.168.2.5`, which is excluded using the `!` operator. It is also possible to load tables from files where each item is on a separate line, as seen in this example [.filename]#/etc/clients#: [.programlisting] .... 192.168.2.0/24 !192.168.2.5 .... To refer to the file, define the table like this: [.programlisting] .... table persist file "/etc/clients" .... Once the table is defined, it can be referenced by a rule: [.programlisting] .... pass inet proto tcp from to any port $client_out flags S/SA keep state .... A table's contents can be manipulated live, using `pfctl`. This example adds another network to the table: [source,shell] .... # pfctl -t clients -T add 192.168.1.0/16 .... Note that any changes made this way will take affect now, making them ideal for testing, but will not survive a power failure or reboot. To make the changes permanent, modify the definition of the table in the ruleset or edit the file that the table refers to. One can maintain the on-disk copy of the table using a man:cron[8] job which dumps the table's contents to disk at regular intervals, using a command such as `pfctl -t clients -T show >/etc/clients`. Alternatively, [.filename]#/etc/clients# can be updated with the in-memory table contents: [source,shell] .... # pfctl -t clients -T replace -f /etc/clients .... [[pftut-overload]] ==== Using Overload Tables to Protect SSH Those who run SSH on an external interface have probably seen something like this in the authentication logs: [.programlisting] .... Sep 26 03:12:34 skapet sshd[25771]: Failed password for root from 200.72.41.31 port 40992 ssh2 Sep 26 03:12:34 skapet sshd[5279]: Failed password for root from 200.72.41.31 port 40992 ssh2 Sep 26 03:12:35 skapet sshd[5279]: Received disconnect from 200.72.41.31: 11: Bye Bye Sep 26 03:12:44 skapet sshd[29635]: Invalid user admin from 200.72.41.31 Sep 26 03:12:44 skapet sshd[24703]: input_userauth_request: invalid user admin Sep 26 03:12:44 skapet sshd[24703]: Failed password for invalid user admin from 200.72.41.31 port 41484 ssh2 .... This is indicative of a brute force attack where somebody or some program is trying to discover the user name and password which will let them into the system. If external SSH access is needed for legitimate users, changing the default port used by SSH can offer some protection. However, PF provides a more elegant solution. Pass rules can contain limits on what connecting hosts can do and violators can be banished to a table of addresses which are denied some or all access. It is even possible to drop all existing connections from machines which overreach the limits. To configure this, create this table in the tables section of the ruleset: [.programlisting] .... table persist .... Then, somewhere early in the ruleset, add rules to block brute access while allowing legitimate access: [.programlisting] .... block quick from pass inet proto tcp from any to $localnet port $tcp_services \ flags S/SA keep state \ (max-src-conn 100, max-src-conn-rate 15/5, \ overload flush global) .... The part in parentheses defines the limits and the numbers should be changed to meet local requirements. It can be read as follows: `max-src-conn` is the number of simultaneous connections allowed from one host. `max-src-conn-rate` is the rate of new connections allowed from any single host (_15_) per number of seconds (_5_). `overload ` means that any host which exceeds these limits gets its address added to the `bruteforce` table. The ruleset blocks all traffic from addresses in the `bruteforce` table. Finally, `flush global` says that when a host reaches the limit, that all (`global`) of that host's connections will be terminated (`flush`). [NOTE] ==== These rules will _not_ block slow bruteforcers, as described in http://home.nuug.no/\~peter/hailmary2013/[http://home.nuug.no/~peter/hailmary2013/]. ==== This example ruleset is intended mainly as an illustration. For example, if a generous number of connections in general are wanted, but the desire is to be more restrictive when it comes to ssh, supplement the rule above with something like the one below, early on in the rule set: [.programlisting] .... pass quick proto { tcp, udp } from any to any port ssh \ flags S/SA keep state \ (max-src-conn 15, max-src-conn-rate 5/3, \ overload flush global) .... [NOTE] ==== *It May Not be Necessary to Block All Overloaders:* + It is worth noting that the overload mechanism is a general technique which does not apply exclusively to SSH, and it is not always optimal to entirely block all traffic from offenders. For example, an overload rule could be used to protect a mail service or a web service, and the overload table could be used in a rule to assign offenders to a queue with a minimal bandwidth allocation or to redirect to a specific web page. ==== Over time, tables will be filled by overload rules and their size will grow incrementally, taking up more memory. Sometimes an IP address that is blocked is a dynamically assigned one, which has since been assigned to a host who has a legitimate reason to communicate with hosts in the local network. For situations like these, pfctl provides the ability to expire table entries. For example, this command will remove `` table entries which have not been referenced for `86400` seconds: [source,shell] .... # pfctl -t bruteforce -T expire 86400 .... Similar functionality is provided by package:security/expiretable[], which removes table entries which have not been accessed for a specified period of time. Once installed, expiretable can be run to remove `` table entries older than a specified age. This example removes all entries older than 24 hours: [.programlisting] .... /usr/local/sbin/expiretable -v -d -t 24h bruteforce .... [[pftut-spamd]] ==== Protecting Against SPAM Not to be confused with the spamd daemon which comes bundled with spamassassin, package:mail/spamd[] can be configured with PF to provide an outer defense against SPAM. This spamd hooks into the PF configuration using a set of redirections. Spammers tend to send a large number of messages, and SPAM is mainly sent from a few spammer friendly networks and a large number of hijacked machines, both of which are reported to _blocklists_ fairly quickly. When an SMTP connection from an address in a blocklist is received, spamd presents its banner and immediately switches to a mode where it answers SMTP traffic one byte at a time. This technique, which is intended to waste as much time as possible on the spammer's end, is called _tarpitting_. The specific implementation which uses one byte SMTP replies is often referred to as _stuttering_. This example demonstrates the basic procedure for setting up spamd with automatically updated blocklists. Refer to the man pages which are installed with package:mail/spamd[] for more information. [.procedure] **** .Procedure: Configuring spamd . Install the package:mail/spamd[] package or port. To use spamd's greylisting features, man:fdescfs[5] must be mounted at [.filename]#/dev/fd#. Add the following line to [.filename]#/etc/fstab#: + [.programlisting] .... fdescfs /dev/fd fdescfs rw 0 0 .... + Then, mount the filesystem: + [.programlisting] .... # mount fdescfs .... . Next, edit the PF ruleset to include: + [.programlisting] .... table persist table persist rdr pass on $ext_if inet proto tcp from to \ { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025 rdr pass on $ext_if inet proto tcp from ! to \ { $ext_if, $localnet } port smtp -> 127.0.0.1 port 8025 .... + The two tables `` and `` are essential. SMTP traffic from an address listed in `` but not in `` is redirected to the spamd daemon listening at port 8025. . The next step is to configure spamd in [.filename]#/usr/local/etc/spamd.conf# and to add some [.filename]#rc.conf# parameters. + The installation of package:mail/spamd[] includes a sample configuration file ([.filename]#/usr/local/etc/spamd.conf.sample#) and a man page for [.filename]#spamd.conf#. Refer to these for additional configuration options beyond those shown in this example. + One of the first lines in the configuration file that does not begin with a `+#+` comment sign contains the block which defines the `all` list, which specifies the lists to use: + [.programlisting] .... all:\ :traplist:allowlist: .... + This entry adds the desired blocklists, separated by colons (`:`). To use an allowlist to subtract addresses from a blocklist, add the name of the allowlist _immediately_ after the name of that blocklist. For example: `:blocklist:allowlist:`. + This is followed by the specified blocklist's definition: + [.programlisting] .... traplist:\ :black:\ :msg="SPAM. Your address %A has sent spam within the last 24 hours":\ :method=http:\ :file=www.openbsd.org/spamd/traplist.gz .... + where the first line is the name of the blocklist and the second line specifies the list type. The `msg` field contains the message to display to blocklisted senders during the SMTP dialogue. The `method` field specifies how spamd-setup fetches the list data; supported methods are `http`, `ftp`, from a `file` in a mounted file system, and via `exec` of an external program. Finally, the `file` field specifies the name of the file spamd expects to receive. + The definition of the specified allowlist is similar, but omits the `msg` field since a message is not needed: + [.programlisting] .... allowlist:\ :white:\ :method=file:\ :file=/var/mail/allowlist.txt .... + [TIP] ==== *Choose Data Sources with Care:* + Using all the blocklists in the sample [.filename]#spamd.conf# will block large blocks of the Internet. Administrators need to edit the file to create an optimal configuration which uses applicable data sources and, when necessary, uses custom lists. ==== + Next, add this entry to [.filename]#/etc/rc.conf#. Additional flags are described in the man page specified by the comment: + [.programlisting] .... spamd_flags="-v" # use "" and see spamd-setup(8) for flags .... + When finished, reload the ruleset, start spamd by typing `service obspamd start`, and complete the configuration using `spamd-setup`. Finally, create a man:cron[8] job which calls `spamd-setup` to update the tables at reasonable intervals. **** On a typical gateway in front of a mail server, hosts will soon start getting trapped within a few seconds to several minutes. PF also supports _greylisting_, which temporarily rejects messages from unknown hosts with _45n_ codes. Messages from greylisted hosts which try again within a reasonable time are let through. Traffic from senders which are set up to behave within the limits set by RFC 1123 and RFC 2821 are immediately let through. More information about greylisting as a technique can be found at the http://www.greylisting.org/[greylisting.org] web site. The most amazing thing about greylisting, apart from its simplicity, is that it still works. Spammers and malware writers have been very slow to adapt to bypass this technique. The basic procedure for configuring greylisting is as follows: [.procedure] .Procedure: Configuring Greylisting . Make sure that man:fdescfs[5] is mounted as described in Step 1 of the previous Procedure. . To run spamd in greylisting mode, add this line to [.filename]#/etc/rc.conf#: + [.programlisting] .... spamd_grey="YES" # use spamd greylisting if YES .... + Refer to the spamd man page for descriptions of additional related parameters. . To complete the greylisting setup: + [.programlisting] .... # service obspamd restart # service obspamlogd start .... Behind the scenes, the spamdb database tool and the spamlogd whitelist updater perform essential functions for the greylisting feature. spamdb is the administrator's main interface to managing the block, grey, and allow lists via the contents of the [.filename]#/var/db/spamdb# database. [[pftut-hygiene]] ==== Network Hygiene This section describes how `block-policy`, `scrub`, and `antispoof` can be used to make the ruleset behave sanely. The `block-policy` is an option which can be set in the `options` part of the ruleset, which precedes the redirection and filtering rules. This option determines which feedback, if any, PF sends to hosts that are blocked by a rule. The option has two possible values: `drop` drops blocked packets with no feedback, and `return` returns a status code such as `Connection refused`. If not set, the default policy is `drop`. To change the `block-policy`, specify the desired value: [.programlisting] .... set block-policy return .... In PF, `scrub` is a keyword which enables network packet normalization. This process reassembles fragmented packets and drops TCP packets that have invalid flag combinations. Enabling `scrub` provides a measure of protection against certain kinds of attacks based on incorrect handling of packet fragments. A number of options are available, but the simplest form is suitable for most configurations: [.programlisting] .... scrub in all .... Some services, such as NFS, require specific fragment handling options. Refer to https://home.nuug.no/\~peter/pf/en/scrub.html[https://home.nuug.no/~peter/pf/en/scrub.html] for more information. This example reassembles fragments, clears the "do not fragment" bit, and sets the maximum segment size to 1440 bytes: [.programlisting] .... scrub in all fragment reassemble no-df max-mss 1440 .... The `antispoof` mechanism protects against activity from spoofed or forged IP addresses, mainly by blocking packets appearing on interfaces and in directions which are logically not possible. These rules weed out spoofed traffic coming in from the rest of the world as well as any spoofed packets which originate in the local network: [.programlisting] .... antispoof for $ext_if antispoof for $int_if .... [[pftut-unrouteables]] ==== Handling Non-Routable Addresses Even with a properly configured gateway to handle network address translation, one may have to compensate for other people's misconfigurations. A common misconfiguration is to let traffic with non-routable addresses out to the Internet. Since traffic from non-routeable addresses can play a part in several DoS attack techniques, consider explicitly blocking traffic from non-routeable addresses from entering the network through the external interface. In this example, a macro containing non-routable addresses is defined, then used in blocking rules. Traffic to and from these addresses is quietly dropped on the gateway's external interface. [.programlisting] .... martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \ 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \ 0.0.0.0/8, 240.0.0.0/4 }" block drop in quick on $ext_if from $martians to any block drop out quick on $ext_if from any to $martians .... === Enabling ALTQ On FreeBSD, ALTQ can be used with PF to provide Quality of Service (QOS). Once ALTQ is enabled, queues can be defined in the ruleset which determine the processing priority of outbound packets. Before enabling ALTQ, refer to man:altq[4] to determine if the drivers for the network cards installed on the system support it. ALTQ is not available as a loadable kernel module. If the system's interfaces support ALTQ, create a custom kernel using the instructions in crossref:kernelconfig[kernelconfig,Configuring the FreeBSD Kernel]. The following kernel options are available. The first is needed to enable ALTQ. At least one of the other options is necessary to specify the queueing scheduler algorithm: [.programlisting] .... options ALTQ options ALTQ_CBQ # Class Based Queuing (CBQ) options ALTQ_RED # Random Early Detection (RED) options ALTQ_RIO # RED In/Out options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC) options ALTQ_PRIQ # Priority Queuing (PRIQ) .... The following scheduler algorithms are available: CBQ:: Class Based Queuing (CBQ) is used to divide a connection's bandwidth into different classes or queues to prioritize traffic based on filter rules. RED:: Random Early Detection (RED) is used to avoid network congestion by measuring the length of the queue and comparing it to the minimum and maximum thresholds for the queue. When the queue is over the maximum, all new packets are randomly dropped. RIO:: In Random Early Detection In and Out (RIO) mode, RED maintains multiple average queue lengths and multiple threshold values, one for each QOS level. HFSC:: Hierarchical Fair Service Curve Packet Scheduler (HFSC) is described in http://www-2.cs.cmu.edu/\~hzhang/HFSC/main.html[http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html]. PRIQ:: Priority Queuing (PRIQ) always passes traffic that is in a higher queue first. More information about the scheduling algorithms and example rulesets are available at the https://web.archive.org/web/20151109213426/http://www.openbsd.org/faq/pf/queueing.html[OpenBSD's web archive]. [[firewalls-ipfw]] == IPFW IPFW is a stateful firewall written for FreeBSD which supports both IPv4 and IPv6. It is comprised of several components: the kernel firewall filter rule processor and its integrated packet accounting facility, the logging facility, NAT, the man:dummynet[4] traffic shaper, a forward facility, a bridge facility, and an ipstealth facility. FreeBSD provides a sample ruleset in [.filename]#/etc/rc.firewall# which defines several firewall types for common scenarios to assist novice users in generating an appropriate ruleset. IPFW provides a powerful syntax which advanced users can use to craft customized rulesets that meet the security requirements of a given environment. This section describes how to enable IPFW, provides an overview of its rule syntax, and demonstrates several rulesets for common configuration scenarios. [[firewalls-ipfw-enable]] === Enabling IPFW IPFW is included in the basic FreeBSD install as a kernel loadable module, meaning that a custom kernel is not needed in order to enable IPFW. For those users who wish to statically compile IPFW support into a custom kernel, see crossref:firewalls[firewalls-ipfw-kernelconfig, IPFW Kernel Options]. To configure the system to enable IPFW at boot time, add `firewall_enable="YES"` to [.filename]#/etc/rc.conf#: [source,shell] .... # sysrc firewall_enable="YES" .... To use one of the default firewall types provided by FreeBSD, add another line which specifies the type: [source,shell] .... # sysrc firewall_type="open" .... The available types are: * `open`: passes all traffic. * `client`: protects only this machine. * `simple`: protects the whole network. * `closed`: entirely disables IP traffic except for the loopback interface. * `workstation`: protects only this machine using stateful rules. * `UNKNOWN`: disables the loading of firewall rules. * [.filename]#filename#: full path of the file containing the firewall ruleset. If `firewall_type` is set to either `client` or `simple`, modify the default rules found in [.filename]#/etc/rc.firewall# to fit the configuration of the system. Note that the `filename` type is used to load a custom ruleset. An alternate way to load a custom ruleset is to set the `firewall_script` variable to the absolute path of an _executable script_ that includes IPFW commands. The examples used in this section assume that the `firewall_script` is set to [.filename]#/etc/ipfw.rules#: [source,shell] .... # sysrc firewall_script="/etc/ipfw.rules" .... To enable logging through man:syslogd[8], include this line: [source,shell] .... # sysrc firewall_logging="YES" .... [WARNING] ==== Only firewall rules with the `log` option will be logged. The default rules do not include this option and it must be manually added. Therefore it is advisable that the default ruleset is edited for logging. In addition, log rotation may be desired if the logs are stored in a separate file. ==== There is no [.filename]#/etc/rc.conf# variable to set logging limits. To limit the number of times a rule is logged per connection attempt, specify the number using this line in [.filename]#/etc/sysctl.conf#: [source,shell] .... # echo "net.inet.ip.fw.verbose_limit=5" >> /etc/sysctl.conf .... To enable logging through a dedicated interface named `ipfw0`, add this line to [.filename]#/etc/rc.conf# instead: [source,shell] .... # sysrc firewall_logif="YES" .... Then use tcpdump to see what is being logged: [source,shell] .... # tcpdump -t -n -i ipfw0 .... [TIP] ==== There is no overhead due to logging unless tcpdump is attached. ==== After saving the needed edits, start the firewall. To enable logging limits now, also set the `sysctl` value specified above: [source,shell] .... # service ipfw start # sysctl net.inet.ip.fw.verbose_limit=5 .... [[firewalls-ipfw-rules]] === IPFW Rule Syntax When a packet enters the IPFW firewall, it is compared against the first rule in the ruleset and progresses one rule at a time, moving from top to bottom in sequence. When the packet matches the selection parameters of a rule, the rule's action is executed and the search of the ruleset terminates for that packet. This is referred to as "first match wins". If the packet does not match any of the rules, it gets caught by the mandatory IPFW default rule number 65535, which denies all packets and silently discards them. However, if the packet matches a rule that contains the `count`, `skipto`, or `tee` keywords, the search continues. Refer to man:ipfw[8] for details on how these keywords affect rule processing. When creating an IPFW rule, keywords must be written in the following order. Some keywords are mandatory while other keywords are optional. The words shown in uppercase represent a variable and the words shown in lowercase must precede the variable that follows it. The `+#+` symbol is used to mark the start of a comment and may appear at the end of a rule or on its own line. Blank lines are ignored. `_CMD RULE_NUMBER set SET_NUMBER ACTION log LOG_AMOUNT PROTO from SRC SRC_PORT to DST DST_PORT OPTIONS_` This section provides an overview of these keywords and their options. It is not an exhaustive list of every possible option. Refer to man:ipfw[8] for a complete description of the rule syntax that can be used when creating IPFW rules. CMD:: Every rule must start with `ipfw add`. RULE_NUMBER:: Each rule is associated with a number from `1` to `65534`. The number is used to indicate the order of rule processing. Multiple rules can have the same number, in which case they are applied according to the order in which they have been added. SET_NUMBER:: Each rule is associated with a set number from `0` to `31`. Sets can be individually disabled or enabled, making it possible to quickly add or delete a set of rules. If a SET_NUMBER is not specified, the rule will be added to set `0`. ACTION:: A rule can be associated with one of the following actions. The specified action will be executed when the packet matches the selection criterion of the rule. + `allow | accept | pass | permit`: these keywords are equivalent and allow packets that match the rule. + `check-state`: checks the packet against the dynamic state table. If a match is found, execute the action associated with the rule which generated this dynamic rule, otherwise move to the next rule. A `check-state` rule does not have selection criterion. If no `check-state` rule is present in the ruleset, the dynamic rules table is checked at the first `keep-state` or `limit` rule. + `count`: updates counters for all packets that match the rule. The search continues with the next rule. + `deny | drop`: either word silently discards packets that match this rule. + Additional actions are available. Refer to man:ipfw[8] for details. LOG_AMOUNT:: When a packet matches a rule with the `log` keyword, a message will be logged to man:syslogd[8] with a facility name of `SECURITY`. Logging only occurs if the number of packets logged for that particular rule does not exceed a specified LOG_AMOUNT. If no LOG_AMOUNT is specified, the limit is taken from the value of `net.inet.ip.fw.verbose_limit`. A value of zero removes the logging limit. Once the limit is reached, logging can be re-enabled by clearing the logging counter or the packet counter for that rule, using `ipfw resetlog`. + [NOTE] ==== Logging is done after all other packet matching conditions have been met, and before performing the final action on the packet. The administrator decides which rules to enable logging on. ==== PROTO:: This optional value can be used to specify any protocol name or number found in [.filename]#/etc/protocols#. SRC:: The `from` keyword must be followed by the source address or a keyword that represents the source address. An address can be represented by `any`, `me` (any address configured on an interface on this system), `me6`, (any IPv6 address configured on an interface on this system), or `table` followed by the number of a lookup table which contains a list of addresses. When specifying an IP address, it can be optionally followed by its CIDR mask or subnet mask. For example, `1.2.3.4/25` or `1.2.3.4:255.255.255.128`. SRC_PORT:: An optional source port can be specified using the port number or name from [.filename]#/etc/services#. DST:: The `to` keyword must be followed by the destination address or a keyword that represents the destination address. The same keywords and addresses described in the SRC section can be used to describe the destination. DST_PORT:: An optional destination port can be specified using the port number or name from [.filename]#/etc/services#. OPTIONS:: Several keywords can follow the source and destination. As the name suggests, OPTIONS are optional. Commonly used options include `in` or `out`, which specify the direction of packet flow, `icmptypes` followed by the type of ICMP message, and `keep-state`. + When a `keep-state` rule is matched, the firewall will create a dynamic rule which matches bidirectional traffic between the source and destination addresses and ports using the same protocol. + The dynamic rules facility is vulnerable to resource depletion from a SYN-flood attack which would open a huge number of dynamic rules. To counter this type of attack with IPFW, use `limit`. This option limits the number of simultaneous sessions by checking the open dynamic rules, counting the number of times this rule and IP address combination occurred. If this count is greater than the value specified by `limit`, the packet is discarded. + Dozens of OPTIONS are available. Refer to man:ipfw[8] for a description of each available option. === Example Ruleset This section demonstrates how to create an example stateful firewall ruleset script named [.filename]#/etc/ipfw.rules#. In this example, all connection rules use `in` or `out` to clarify the direction. They also use `via` _interface-name_ to specify the interface the packet is traveling over. [NOTE] ==== When first creating or testing a firewall ruleset, consider temporarily setting this tunable: [.programlisting] .... net.inet.ip.fw.default_to_accept="1" .... This sets the default policy of man:ipfw[8] to be more permissive than the default `deny ip from any to any`, making it slightly more difficult to get locked out of the system right after a reboot. ==== -The firewall script begins by indicating that it is a Bourne shell script and flushes any existing rules. +The firewall script begins by indicating that it is a POSIX(R) shell script and flushes any existing rules. It then creates the `cmd` variable so that `ipfw add` does not have to be typed at the beginning of every rule. It also defines the `pif` variable which represents the name of the interface that is attached to the Internet. [.programlisting] .... #!/bin/sh # Flush out the list before we begin. ipfw -q -f flush # Set rules command prefix cmd="ipfw -q add" pif="dc0" # interface name of NIC attached to Internet .... The first two rules allow all traffic on the trusted internal interface and on the loopback interface: [.programlisting] .... # Change xl0 to LAN NIC interface name $cmd 00005 allow all from any to any via xl0 # No restrictions on Loopback Interface $cmd 00010 allow all from any to any via lo0 .... The next rule allows the packet through if it matches an existing entry in the dynamic rules table: [.programlisting] .... $cmd 00101 check-state .... The next set of rules defines which stateful connections internal systems can create to hosts on the Internet: [.programlisting] .... # Allow access to public DNS # Replace x.x.x.x with the IP address of a public DNS server # and repeat for each DNS server in /etc/resolv.conf $cmd 00110 allow tcp from any to x.x.x.x 53 out via $pif setup keep-state $cmd 00111 allow udp from any to x.x.x.x 53 out via $pif keep-state # Allow access to ISP's DHCP server for cable/DSL configurations. # Use the first rule and check log for IP address. # Then, uncomment the second rule, input the IP address, and delete the first rule $cmd 00120 allow log udp from any to any 67 out via $pif keep-state #$cmd 00120 allow udp from any to x.x.x.x 67 out via $pif keep-state # Allow outbound HTTP and HTTPS connections $cmd 00200 allow tcp from any to any 80 out via $pif setup keep-state $cmd 00220 allow tcp from any to any 443 out via $pif setup keep-state # Allow outbound email connections $cmd 00230 allow tcp from any to any 25 out via $pif setup keep-state $cmd 00231 allow tcp from any to any 110 out via $pif setup keep-state # Allow outbound ping $cmd 00250 allow icmp from any to any out via $pif keep-state # Allow outbound NTP $cmd 00260 allow udp from any to any 123 out via $pif keep-state # Allow outbound SSH $cmd 00280 allow tcp from any to any 22 out via $pif setup keep-state # deny and log all other outbound connections $cmd 00299 deny log all from any to any out via $pif .... The next set of rules controls connections from Internet hosts to the internal network. It starts by denying packets typically associated with attacks and then explicitly allows specific types of connections. All the authorized services that originate from the Internet use `limit` to prevent flooding. [.programlisting] .... # Deny all inbound traffic from non-routable reserved address spaces $cmd 00300 deny all from 192.168.0.0/16 to any in via $pif #RFC 1918 private IP $cmd 00301 deny all from 172.16.0.0/12 to any in via $pif #RFC 1918 private IP $cmd 00302 deny all from 10.0.0.0/8 to any in via $pif #RFC 1918 private IP $cmd 00303 deny all from 127.0.0.0/8 to any in via $pif #loopback $cmd 00304 deny all from 0.0.0.0/8 to any in via $pif #loopback $cmd 00305 deny all from 169.254.0.0/16 to any in via $pif #DHCP auto-config $cmd 00306 deny all from 192.0.2.0/24 to any in via $pif #reserved for docs $cmd 00307 deny all from 204.152.64.0/23 to any in via $pif #Sun cluster interconnect $cmd 00308 deny all from 224.0.0.0/3 to any in via $pif #Class D & E multicast # Deny public pings $cmd 00310 deny icmp from any to any in via $pif # Deny ident $cmd 00315 deny tcp from any to any 113 in via $pif # Deny all Netbios services. $cmd 00320 deny tcp from any to any 137 in via $pif $cmd 00321 deny tcp from any to any 138 in via $pif $cmd 00322 deny tcp from any to any 139 in via $pif $cmd 00323 deny tcp from any to any 81 in via $pif # Deny fragments $cmd 00330 deny all from any to any frag in via $pif # Deny ACK packets that did not match the dynamic rule table $cmd 00332 deny tcp from any to any established in via $pif # Allow traffic from ISP's DHCP server. # Replace x.x.x.x with the same IP address used in rule 00120. #$cmd 00360 allow udp from any to x.x.x.x 67 in via $pif keep-state # Allow HTTP connections to internal web server $cmd 00400 allow tcp from any to me 80 in via $pif setup limit src-addr 2 # Allow inbound SSH connections $cmd 00410 allow tcp from any to me 22 in via $pif setup limit src-addr 2 # Reject and log all other incoming connections $cmd 00499 deny log all from any to any in via $pif .... The last rule logs all packets that do not match any of the rules in the ruleset: [.programlisting] .... # Everything else is denied and logged $cmd 00999 deny log all from any to any .... [[in-kernel-nat]] === In-kernel NAT FreeBSD's IPFW firewall has two implementations of NAT: the userland implementation man:natd[8], and the more recent in-kernel NAT implementation. Both work in conjunction with IPFW to provide network address translation. This can be used to provide an Internet Connection Sharing solution so that several internal computers can connect to the Internet using a single public IP address. To do this, the FreeBSD machine connected to the Internet must act as a gateway. This system must have two NICs, where one is connected to the Internet and the other is connected to the internal LAN. Each machine connected to the LAN should be assigned an IP address in the private network space, as defined by https://www.ietf.org/rfc/rfc1918.txt[RFC 1918]. Some additional configuration is needed in order to enable the in-kernel NAT facility of IPFW. To enable in-kernel NAT support at boot time, the following must be set in [.filename]#/etc/rc.conf#: [.programlisting] .... gateway_enable="YES" firewall_enable="YES" firewall_nat_enable="YES" .... [NOTE] ==== When `firewall_nat_enable` is set but `firewall_enable` is not, it will have no effect and do nothing. This is because the in-kernel NAT implementation is only compatible with IPFW. ==== When the ruleset contains stateful rules, the positioning of the NAT rule is critical and the `skipto` action is used. The `skipto` action requires a rule number so that it knows which rule to jump to. The example below builds upon the firewall ruleset shown in the previous section. It adds some additional entries and modifies some existing rules in order to configure the firewall for in-kernel NAT. It starts by adding some additional variables which represent the rule number to skip to, the `keep-state` option, and a list of TCP ports which will be used to reduce the number of rules. [.programlisting] .... #!/bin/sh ipfw -q -f flush cmd="ipfw -q add" skip="skipto 1000" pif=dc0 ks="keep-state" good_tcpo="22,25,37,53,80,443,110" .... With in-kernel NAT it is necessary to disable TCP segmentation offloading (TSO) due to the architecture of man:libalias[3], a library implemented as a kernel module to provide the in-kernel NAT facility of IPFW. TSO can be disabled on a per network interface basis using man:ifconfig[8] or on a system wide basis using man:sysctl[8]. To disable TSO system wide, the following must be set it [.filename]#/etc/sysctl.conf#: [.programlisting] .... net.inet.tcp.tso="0" .... A NAT instance will also be configured. It is possible to have multiple NAT instances each with their own configuration. For this example only one NAT instance is needed, NAT instance number 1. The configuration can take a few options such as: `if` which indicates the public interface, `same_ports` which takes care that aliased ports and local port numbers are mapped the same, `unreg_only` will result in only unregistered (private) address spaces to be processed by the NAT instance, and `reset` which will help to keep a functioning NAT instance even when the public IP address of the IPFW machine changes. For all possible options that can be passed to a single NAT instance configuration consult man:ipfw[8]. When configuring a stateful NATing firewall, it is necessary to allow translated packets to be reinjected in the firewall for further processing. This can be achieved by disabling `one_pass` behavior at the start of the firewall script. [.programlisting] .... ipfw disable one_pass ipfw -q nat 1 config if $pif same_ports unreg_only reset .... The inbound NAT rule is inserted _after_ the two rules which allow all traffic on the trusted and loopback interfaces and after the reassemble rule but _before_ the `check-state` rule. It is important that the rule number selected for this NAT rule, in this example `100`, is higher than the first three rules and lower than the `check-state` rule. Furthermore, because of the behavior of in-kernel NAT it is advised to place a reassemble rule just before the first NAT rule and after the rules that allow traffic on trusted interface. Normally, IP fragmentation should not happen, but when dealing with IPSEC/ESP/GRE tunneling traffic it might and the reassembling of fragments is necessary before handing the complete packet over to the in-kernel NAT facility. [NOTE] ==== The reassemble rule was not needed with userland man:natd[8] because the internal workings of the IPFW `divert` action already takes care of reassembling packets before delivery to the socket as also stated in man:ipfw[8]. The NAT instance and rule number used in this example does not match with the default NAT instance and rule number created by [.filename]#rc.firewall#. [.filename]#rc.firewall# is a script that sets up the default firewall rules present in FreeBSD. ==== [.programlisting] .... $cmd 005 allow all from any to any via xl0 # exclude LAN traffic $cmd 010 allow all from any to any via lo0 # exclude loopback traffic $cmd 099 reass all from any to any in # reassemble inbound packets $cmd 100 nat 1 ip from any to any in via $pif # NAT any inbound packets # Allow the packet through if it has an existing entry in the dynamic rules table $cmd 101 check-state .... The outbound rules are modified to replace the `allow` action with the `$skip` variable, indicating that rule processing will continue at rule `1000`. The seven `tcp` rules have been replaced by rule `125` as the `$good_tcpo` variable contains the seven allowed outbound ports. [NOTE] ==== Remember that IPFW's performance is largely determined by the number of rules present in the ruleset. ==== [.programlisting] .... # Authorized outbound packets $cmd 120 $skip udp from any to x.x.x.x 53 out via $pif $ks $cmd 121 $skip udp from any to x.x.x.x 67 out via $pif $ks $cmd 125 $skip tcp from any to any $good_tcpo out via $pif setup $ks $cmd 130 $skip icmp from any to any out via $pif $ks .... The inbound rules remain the same, except for the very last rule which removes the `via $pif` in order to catch both inbound and outbound rules. The NAT rule must follow this last outbound rule, must have a higher number than that last rule, and the rule number must be referenced by the `skipto` action. In this ruleset, rule number `1000` handles passing all packets to our configured instance for NAT processing. The next rule allows any packet which has undergone NAT processing to pass. [.programlisting] .... $cmd 999 deny log all from any to any $cmd 1000 nat 1 ip from any to any out via $pif # skipto location for outbound stateful rules $cmd 1001 allow ip from any to any .... In this example, rules `100`, `101`, `125`, `1000`, and `1001` control the address translation of the outbound and inbound packets so that the entries in the dynamic state table always register the private LANIP address. Consider an internal web browser which initializes a new outbound HTTP session over port 80. When the first outbound packet enters the firewall, it does not match rule `100` because it is headed out rather than in. It passes rule `101` because this is the first packet and it has not been posted to the dynamic state table yet. The packet finally matches rule `125` as it is outbound on an allowed port and has a source IP address from the internal LAN. On matching this rule, two actions take place. First, the `keep-state` action adds an entry to the dynamic state table and the specified action, `skipto rule 1000`, is executed. Next, the packet undergoes NAT and is sent out to the Internet. This packet makes its way to the destination web server, where a response packet is generated and sent back. This new packet enters the top of the ruleset. It matches rule `100` and has its destination IP address mapped back to the original internal address. It then is processed by the `check-state` rule, is found in the table as an existing session, and is released to the LAN. On the inbound side, the ruleset has to deny bad packets and allow only authorized services. A packet which matches an inbound rule is posted to the dynamic state table and the packet is released to the LAN. The packet generated as a response is recognized by the `check-state` rule as belonging to an existing session. It is then sent to rule `1000` to undergo NAT before being released to the outbound interface. [NOTE] ==== Transitioning from userland man:natd[8] to in-kernel NAT might appear seamless at first but there is small catch. When using the GENERIC kernel, IPFW will load the [.filename]#libalias.ko# kernel module, when `firewall_nat_enable` is enabled in [.filename]#/etc/rc.conf#. The [.filename]#libalias.ko# kernel module only provides basic NAT functionality, whereas the userland implementation man:natd[8] has all NAT functionality available in its userland library without any extra configuration. All functionality refers to the following kernel modules that can additionally be loaded when needed besides the standard [.filename]#libalias.ko# kernel module: [.filename]#alias_ftp.ko#, [.filename]#alias_bbt.ko#, [.filename]#skinny.ko#, [.filename]#irc.ko#, [.filename]#alias_pptp.ko# and [.filename]#alias_smedia.ko# using the `kld_list` directive in [.filename]#/etc/rc.conf#. If a custom kernel is used, the full functionality of the userland library can be compiled in, in the kernel, using the `options LIBALIAS`. ==== ==== Port Redirection The drawback with NAT in general is that the LAN clients are not accessible from the Internet. Clients on the LAN can make outgoing connections to the world but cannot receive incoming ones. This presents a problem if trying to run Internet services on one of the LAN client machines. A simple way around this is to redirect selected Internet ports on the NAT providing machine to a LAN client. For example, an IRC server runs on client `A` and a web server runs on client `B`. For this to work properly, connections received on ports 6667 (IRC) and 80 (HTTP) must be redirected to the respective machines. With in-kernel NAT all configuration is done in the NAT instance configuration. For a full list of options that an in-kernel NAT instance can use, consult man:ipfw[8]. The IPFW syntax follows the syntax of natd. The syntax for `redirect_port` is as follows: [.programlisting] .... redirect_port proto targetIP:targetPORT[-targetPORT] [aliasIP:]aliasPORT[-aliasPORT] [remoteIP[:remotePORT[-remotePORT]]] .... To configure the above example setup, the arguments should be: [.programlisting] .... redirect_port tcp 192.168.0.2:6667 6667 redirect_port tcp 192.168.0.3:80 80 .... After adding these arguments to the configuration of NAT instance 1 in the above ruleset, the TCP ports will be port forwarded to the LAN client machines running the IRC and HTTP services. [.programlisting] .... ipfw -q nat 1 config if $pif same_ports unreg_only reset \ redirect_port tcp 192.168.0.2:6667 6667 \ redirect_port tcp 192.168.0.3:80 80 .... Port ranges over individual ports can be indicated with `redirect_port`. For example, _tcp 192.168.0.2:2000-3000 2000-3000_ would redirect all connections received on ports 2000 to 3000 to ports 2000 to 3000 on client `A`. ==== Address Redirection Address redirection is useful if more than one IP address is available. Each LAN client can be assigned its own external IP address by man:ipfw[8], which will then rewrite outgoing packets from the LAN clients with the proper external IP address and redirects all traffic incoming on that particular IP address back to the specific LAN client. This is also known as static NAT. For example, if IP addresses `128.1.1.1`, `128.1.1.2`, and `128.1.1.3` are available, `128.1.1.1` can be used as the man:ipfw[8] machine's external IP address, while `128.1.1.2` and `128.1.1.3` are forwarded back to LAN clients `A` and `B`. The `redirect_addr` syntax is as below, where `localIP` is the internal IP address of the LAN client, and `publicIP` the external IP address corresponding to the LAN client. [.programlisting] .... redirect_addr localIP publicIP .... In the example, the arguments would read: [.programlisting] .... redirect_addr 192.168.0.2 128.1.1.2 redirect_addr 192.168.0.3 128.1.1.3 .... Like `redirect_port`, these arguments are placed in a NAT instance configuration. With address redirection, there is no need for port redirection, as all data received on a particular IP address is redirected. The external IP addresses on the man:ipfw[8] machine must be active and aliased to the external interface. Refer to man:rc.conf[5] for details. ==== Userspace NAT Let us start with a statement: the userspace NAT implementation: man:natd[8], has more overhead than in-kernel NAT. For man:natd[8] to translate packets, the packets have to be copied from the kernel to userspace and back which brings in extra overhead that is not present with in-kernel NAT. To enable the userspace NAT daemon man:natd[8] at boot time, the following is a minimum configuration in [.filename]#/etc/rc.conf#. Where `natd_interface` is set to the name of the NIC attached to the Internet. The man:rc[8] script of man:natd[8] will automatically check if a dynamic IP address is used and configure itself to handle that. [.programlisting] .... gateway_enable="YES" natd_enable="YES" natd_interface="rl0" .... In general, the above ruleset as explained for in-kernel NAT can also be used together with man:natd[8]. The exceptions are the configuration of the in-kernel NAT instance `(ipfw -q nat 1 config ...)` which is not needed together with reassemble rule 99 because its functionality is included in the `divert` action. Rule number 100 and 1000 will have to change slightly as shown below. [.programlisting] .... $cmd 100 divert natd ip from any to any in via $pif $cmd 1000 divert natd ip from any to any out via $pif .... To configure port or address redirection, a similar syntax as with in-kernel NAT is used. Although, now, instead of specifying the configuration in our ruleset script like with in-kernel NAT, configuration of man:natd[8] is best done in a configuration file. To do this, an extra flag must be passed via [.filename]#/etc/rc.conf# which specifies the path of the configuration file. [.programlisting] .... natd_flags="-f /etc/natd.conf" .... [NOTE] ==== The specified file must contain a list of configuration options, one per line. For more information about the configuration file and possible variables, consult man:natd[8]. Below are two example entries, one per line: [.programlisting] .... redirect_port tcp 192.168.0.2:6667 6667 redirect_addr 192.168.0.3 128.1.1.3 .... ==== [[firewalls-ipfw-cmd]] === The IPFW Command `ipfw` can be used to make manual, single rule additions or deletions to the active firewall while it is running. The problem with using this method is that all the changes are lost when the system reboots. It is recommended to instead write all the rules in a file and to use that file to load the rules at boot time and to replace the currently running firewall rules whenever that file changes. `ipfw` is a useful way to display the running firewall rules to the console screen. The IPFW accounting facility dynamically creates a counter for each rule that counts each packet that matches the rule. During the process of testing a rule, listing the rule with its counter is one way to determine if the rule is functioning as expected. To list all the running rules in sequence: [source,shell] .... # ipfw list .... To list all the running rules with a time stamp of when the last time the rule was matched: [source,shell] .... # ipfw -t list .... The next example lists accounting information and the packet count for matched rules along with the rules themselves. The first column is the rule number, followed by the number of matched packets and bytes, followed by the rule itself. [source,shell] .... # ipfw -a list .... To list dynamic rules in addition to static rules: [source,shell] .... # ipfw -d list .... To also show the expired dynamic rules: [source,shell] .... # ipfw -d -e list .... To zero the counters: [source,shell] .... # ipfw zero .... To zero the counters for just the rule with number _NUM_: [source,shell] .... # ipfw zero NUM .... ==== Logging Firewall Messages Even with the logging facility enabled, IPFW will not generate any rule logging on its own. The firewall administrator decides which rules in the ruleset will be logged, and adds the `log` keyword to those rules. Normally only deny rules are logged. It is customary to duplicate the "ipfw default deny everything" rule with the `log` keyword included as the last rule in the ruleset. This way, it is possible to see all the packets that did not match any of the rules in the ruleset. Logging is a two edged sword. If one is not careful, an over abundance of log data or a DoS attack can fill the disk with log files. Log messages are not only written to syslogd, but also are displayed on the root console screen and soon become annoying. The `IPFIREWALL_VERBOSE_LIMIT=5` kernel option limits the number of consecutive messages sent to man:syslogd[8], concerning the packet matching of a given rule. When this option is enabled in the kernel, the number of consecutive messages concerning a particular rule is capped at the number specified. There is nothing to be gained from 200 identical log messages. With this option set to five, five consecutive messages concerning a particular rule would be logged to syslogd and the remainder identical consecutive messages would be counted and posted to syslogd with a phrase like the following: [.programlisting] .... last message repeated 45 times .... All logged packets messages are written by default to [.filename]#/var/log/security#, which is defined in [.filename]#/etc/syslog.conf#. [[firewalls-ipfw-rules-script]] ==== Building a Rule Script Most experienced IPFW users create a file containing the rules and code them in a manner compatible with running them as a script. The major benefit of doing this is the firewall rules can be refreshed in mass without the need of rebooting the system to activate them. This method is convenient in testing new rules as the procedure can be executed as many times as needed. Being a script, symbolic substitution can be used for frequently used values to be substituted into multiple rules. This example script is compatible with the syntax used by the man:sh[1], man:csh[1], and man:tcsh[1] shells. Symbolic substitution fields are prefixed with a dollar sign ($). Symbolic fields do not have the $ prefix. The value to populate the symbolic field must be enclosed in double quotes (""). Start the rules file like this: [.programlisting] .... ############### start of example ipfw rules script ############# # ipfw -q -f flush # Delete all rules # Set defaults oif="tun0" # out interface odns="192.0.2.11" # ISP's DNS server IP address cmd="ipfw -q add " # build rule prefix ks="keep-state" # just too lazy to key this each time $cmd 00500 check-state $cmd 00502 deny all from any to any frag $cmd 00501 deny tcp from any to any established $cmd 00600 allow tcp from any to any 80 out via $oif setup $ks $cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks $cmd 00611 allow udp from any to $odns 53 out via $oif $ks ################### End of example ipfw rules script ############ .... The rules are not important as the focus of this example is how the symbolic substitution fields are populated. If the above example was in [.filename]#/etc/ipfw.rules#, the rules could be reloaded by the following command: [source,shell] .... # sh /etc/ipfw.rules .... [.filename]#/etc/ipfw.rules# can be located anywhere and the file can have any name. The same thing could be accomplished by running these commands by hand: [source,shell] .... # ipfw -q -f flush # ipfw -q add check-state # ipfw -q add deny all from any to any frag # ipfw -q add deny tcp from any to any established # ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state # ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state # ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state .... [[firewalls-ipfw-kernelconfig]] === IPFW Kernel Options In order to statically compile IPFW support into a custom kernel, refer to the instructions in crossref:kernelconfig[kernelconfig,Configuring the FreeBSD Kernel]. The following options are available for the custom kernel configuration file: [.programlisting] .... options IPFIREWALL # enables IPFW options IPFIREWALL_VERBOSE # enables logging for rules with log keyword to syslogd(8) options IPFIREWALL_VERBOSE_LIMIT=5 # limits number of logged packets per-entry options IPFIREWALL_DEFAULT_TO_ACCEPT # sets default policy to pass what is not explicitly denied options IPFIREWALL_NAT # enables basic in-kernel NAT support options LIBALIAS # enables full in-kernel NAT support options IPFIREWALL_NAT64 # enables in-kernel NAT64 support options IPFIREWALL_NPTV6 # enables in-kernel IPv6 NPT support options IPFIREWALL_PMOD # enables protocols modification module support options IPDIVERT # enables NAT through natd(8) .... [NOTE] ==== IPFW can be loaded as a kernel module: options above are built by default as modules or can be set at runtime using tunables. ==== [[firewalls-ipf]] == IPFILTER (IPF) IPFILTER, also known as IPF, is a cross-platform, open source firewall which has been ported to several operating systems, including FreeBSD, NetBSD, OpenBSD, and Solaris(TM). IPFILTER is a kernel-side firewall and NAT mechanism that can be controlled and monitored by userland programs. Firewall rules can be set or deleted using ipf, NAT rules can be set or deleted using ipnat, run-time statistics for the kernel parts of IPFILTER can be printed using ipfstat, and ipmon can be used to log IPFILTER actions to the system log files. IPF was originally written using a rule processing logic of "the last matching rule wins" and only used stateless rules. Since then, IPF has been enhanced to include the `quick` and `keep state` options. The IPF FAQ is at http://www.phildev.net/ipf/index.html[http://www.phildev.net/ipf/index.html]. A searchable archive of the IPFilter mailing list is available at http://marc.info/?l=ipfilter[http://marc.info/?l=ipfilter]. This section of the Handbook focuses on IPF as it pertains to FreeBSD. It provides examples of rules that contain the `quick` and `keep state` options. === Enabling IPF IPF is included in the basic FreeBSD install as a kernel loadable module, meaning that a custom kernel is not needed in order to enable IPF. For users who prefer to statically compile IPF support into a custom kernel, refer to the instructions in crossref:kernelconfig[kernelconfig,Configuring the FreeBSD Kernel]. The following kernel options are available: [.programlisting] .... options IPFILTER options IPFILTER_LOG options IPFILTER_LOOKUP options IPFILTER_DEFAULT_BLOCK .... where `options IPFILTER` enables support for IPFILTER, `options IPFILTER_LOG` enables IPF logging using the [.filename]#ipl# packet logging pseudo-device for every rule that has the `log` keyword, `IPFILTER_LOOKUP` enables IP pools in order to speed up IP lookups, and `options IPFILTER_DEFAULT_BLOCK` changes the default behavior so that any packet not matching a firewall `pass` rule gets blocked. To configure the system to enable IPF at boot time, add the following entries to [.filename]#/etc/rc.conf#. These entries will also enable logging and `default pass all`. To change the default policy to `block all` without compiling a custom kernel, remember to add a `block all` rule at the end of the ruleset. [.programlisting] .... ipfilter_enable="YES" # Start ipf firewall ipfilter_rules="/etc/ipf.rules" # loads rules definition text file ipv6_ipfilter_rules="/etc/ipf6.rules" # loads rules definition text file for IPv6 ipmon_enable="YES" # Start IP monitor log ipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names .... If NAT functionality is needed, also add these lines: [.programlisting] .... gateway_enable="YES" # Enable as LAN gateway ipnat_enable="YES" # Start ipnat function ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat .... Then, to start IPF now: [.programlisting] .... # service ipfilter start .... To load the firewall rules, specify the name of the ruleset file using `ipf`. The following command can be used to replace the currently running firewall rules: [source,shell] .... # ipf -Fa -f /etc/ipf.rules .... where `-Fa` flushes all the internal rules tables and `-f` specifies the file containing the rules to load. This provides the ability to make changes to a custom ruleset and update the running firewall with a fresh copy of the rules without having to reboot the system. This method is convenient for testing new rules as the procedure can be executed as many times as needed. Refer to man:ipf[8] for details on the other flags available with this command. === IPF Rule Syntax This section describes the IPF rule syntax used to create stateful rules. When creating rules, keep in mind that unless the `quick` keyword appears in a rule, every rule is read in order, with the _last matching rule_ being the one that is applied. This means that even if the first rule to match a packet is a `pass`, if there is a later matching rule that is a `block`, the packet will be dropped. Sample rulesets can be found in [.filename]#/usr/share/examples/ipfilter#. When creating rules, a `+#+` character is used to mark the start of a comment and may appear at the end of a rule, to explain that rule's function, or on its own line. Any blank lines are ignored. The keywords which are used in rules must be written in a specific order, from left to right. Some keywords are mandatory while others are optional. Some keywords have sub-options which may be keywords themselves and also include more sub-options. The keyword order is as follows, where the words shown in uppercase represent a variable and the words shown in lowercase must precede the variable that follows it: `_ACTION DIRECTION OPTIONS proto PROTO_TYPE from SRC_ADDR SRC_PORT to DST_ADDR DST_PORT TCP_FLAG|ICMP_TYPE keep state STATE_` This section describes each of these keywords and their options. It is not an exhaustive list of every possible option. Refer to man:ipf[5] for a complete description of the rule syntax that can be used when creating IPF rules and examples for using each keyword. ACTION:: The action keyword indicates what to do with the packet if it matches that rule. Every rule _must_ have an action. The following actions are recognized: + `block`: drops the packet. + `pass`: allows the packet. + `log`: generates a log record. + `count`: counts the number of packets and bytes which can provide an indication of how often a rule is used. + `auth`: queues the packet for further processing by another program. + `call`: provides access to functions built into IPF that allow more complex actions. + `decapsulate`: removes any headers in order to process the contents of the packet. DIRECTION:: Next, each rule must explicitly state the direction of traffic using one of these keywords: + `in`: the rule is applied against an inbound packet. + `out`: the rule is applied against an outbound packet. + `all`: the rule applies to either direction. + If the system has multiple interfaces, the interface can be specified along with the direction. An example would be `in on fxp0`. OPTIONS:: Options are optional. However, if multiple options are specified, they must be used in the order shown here. + `log`: when performing the specified ACTION, the contents of the packet's headers will be written to the man:ipl[4] packet log pseudo-device. + `quick`: if a packet matches this rule, the ACTION specified by the rule occurs and no further processing of any following rules will occur for this packet. + `on`: must be followed by the interface name as displayed by man:ifconfig[8]. The rule will only match if the packet is going through the specified interface in the specified direction. + When using the `log` keyword, the following qualifiers may be used in this order: + `body`: indicates that the first 128 bytes of the packet contents will be logged after the headers. + `first`: if the `log` keyword is being used in conjunction with a `keep state` option, this option is recommended so that only the triggering packet is logged and not every packet which matches the stateful connection. + Additional options are available to specify error return messages. Refer to man:ipf[5] for more details. PROTO_TYPE:: The protocol type is optional. However, it is mandatory if the rule needs to specify a SRC_PORT or a DST_PORT as it defines the type of protocol. When specifying the type of protocol, use the `proto` keyword followed by either a protocol number or name from [.filename]#/etc/protocols#. Example protocol names include `tcp`, `udp`, or `icmp`. If PROTO_TYPE is specified but no SRC_PORT or DST_PORT is specified, all port numbers for that protocol will match that rule. SRC_ADDR:: The `from` keyword is mandatory and is followed by a keyword which represents the source of the packet. The source can be a hostname, an IP address followed by the CIDR mask, an address pool, or the keyword `all`. Refer to man:ipf[5] for examples. + There is no way to match ranges of IP addresses which do not express themselves easily using the dotted numeric form / mask-length notation. The package:net-mgmt/ipcalc[] package or port may be used to ease the calculation of the CIDR mask. Additional information is available at the utility's web page: http://jodies.de/ipcalc[http://jodies.de/ipcalc]. SRC_PORT:: The port number of the source is optional. However, if it is used, it requires PROTO_TYPE to be first defined in the rule. The port number must also be preceded by the `proto` keyword. + A number of different comparison operators are supported: `=` (equal to), `!=` (not equal to), `<` (less than), `>` (greater than), `<=` (less than or equal to), and `>=` (greater than or equal to). + To specify port ranges, place the two port numbers between `<>` (less than and greater than ), `><` (greater than and less than ), or `:` (greater than or equal to and less than or equal to). DST_ADDR:: The `to` keyword is mandatory and is followed by a keyword which represents the destination of the packet. Similar to SRC_ADDR, it can be a hostname, an IP address followed by the CIDR mask, an address pool, or the keyword `all`. DST_PORT:: Similar to SRC_PORT, the port number of the destination is optional. However, if it is used, it requires PROTO_TYPE to be first defined in the rule. The port number must also be preceded by the `proto` keyword. TCP_FLAG|ICMP_TYPE:: If `tcp` is specified as the PROTO_TYPE, flags can be specified as letters, where each letter represents one of the possible TCP flags used to determine the state of a connection. Possible values are: `S` (SYN), `A` (ACK), `P` (PSH), `F` (FIN), `U` (URG), `R` (RST), `C` (CWN), and `E` (ECN). + If `icmp` is specified as the PROTO_TYPE, the ICMP type to match can be specified. Refer to man:ipf[5] for the allowable types. STATE:: If a `pass` rule contains `keep state`, IPF will add an entry to its dynamic state table and allow subsequent packets that match the connection. IPF can track state for TCP, UDP, and ICMP sessions. Any packet that IPF can be certain is part of an active session, even if it is a different protocol, will be allowed. + In IPF, packets destined to go out through the interface connected to the public Internet are first checked against the dynamic state table. If the packet matches the next expected packet comprising an active session conversation, it exits the firewall and the state of the session conversation flow is updated in the dynamic state table. Packets that do not belong to an already active session are checked against the outbound ruleset. Packets coming in from the interface connected to the public Internet are first checked against the dynamic state table. If the packet matches the next expected packet comprising an active session, it exits the firewall and the state of the session conversation flow is updated in the dynamic state table. Packets that do not belong to an already active session are checked against the inbound ruleset. + Several keywords can be added after `keep state`. If used, these keywords set various options that control stateful filtering, such as setting connection limits or connection age. Refer to man:ipf[5] for the list of available options and their descriptions. === Example Ruleset This section demonstrates how to create an example ruleset which only allows services matching `pass` rules and blocks all others. FreeBSD uses the loopback interface ([.filename]#lo0#) and the IP address `127.0.0.1` for internal communication. The firewall ruleset must contain rules to allow free movement of these internally used packets: [.programlisting] .... # no restrictions on loopback interface pass in quick on lo0 all pass out quick on lo0 all .... The public interface connected to the Internet is used to authorize and control access of all outbound and inbound connections. If one or more interfaces are cabled to private networks, those internal interfaces may require rules to allow packets originating from the LAN to flow between the internal networks or to the interface attached to the Internet. The ruleset should be organized into three major sections: any trusted internal interfaces, outbound connections through the public interface, and inbound connections through the public interface. These two rules allow all traffic to pass through a trusted LAN interface named [.filename]#xl0#: [.programlisting] .... # no restrictions on inside LAN interface for private network pass out quick on xl0 all pass in quick on xl0 all .... The rules for the public interface's outbound and inbound sections should have the most frequently matched rules placed before less commonly matched rules, with the last rule in the section blocking and logging all packets for that interface and direction. This set of rules defines the outbound section of the public interface named [.filename]#dc0#. These rules keep state and identify the specific services that internal systems are authorized for public Internet access. All the rules use `quick` and specify the appropriate port numbers and, where applicable, destination addresses. [.programlisting] .... # interface facing Internet (outbound) # Matches session start requests originating from or behind the # firewall, destined for the Internet. # Allow outbound access to public DNS servers. # Replace x.x.x.x with address listed in /etc/resolv.conf. # Repeat for each DNS server. pass out quick on dc0 proto tcp from any to x.x.x.x port = 53 flags S keep state pass out quick on dc0 proto udp from any to x.x.x.x port = 53 keep state # Allow access to ISP's specified DHCP server for cable or DSL networks. # Use the first rule, then check log for the IP address of DHCP server. # Then, uncomment the second rule, replace z.z.z.z with the IP address, # and comment out the first rule pass out log quick on dc0 proto udp from any to any port = 67 keep state #pass out quick on dc0 proto udp from any to z.z.z.z port = 67 keep state # Allow HTTP and HTTPS pass out quick on dc0 proto tcp from any to any port = 80 flags S keep state pass out quick on dc0 proto tcp from any to any port = 443 flags S keep state # Allow email pass out quick on dc0 proto tcp from any to any port = 110 flags S keep state pass out quick on dc0 proto tcp from any to any port = 25 flags S keep state # Allow NTP pass out quick on dc0 proto tcp from any to any port = 37 flags S keep state # Allow FTP pass out quick on dc0 proto tcp from any to any port = 21 flags S keep state # Allow SSH pass out quick on dc0 proto tcp from any to any port = 22 flags S keep state # Allow ping pass out quick on dc0 proto icmp from any to any icmp-type 8 keep state # Block and log everything else block out log first quick on dc0 all .... This example of the rules in the inbound section of the public interface blocks all undesirable packets first. This reduces the number of packets that are logged by the last rule. [.programlisting] .... # interface facing Internet (inbound) # Block all inbound traffic from non-routable or reserved address spaces block in quick on dc0 from 192.168.0.0/16 to any #RFC 1918 private IP block in quick on dc0 from 172.16.0.0/12 to any #RFC 1918 private IP block in quick on dc0 from 10.0.0.0/8 to any #RFC 1918 private IP block in quick on dc0 from 127.0.0.0/8 to any #loopback block in quick on dc0 from 0.0.0.0/8 to any #loopback block in quick on dc0 from 169.254.0.0/16 to any #DHCP auto-config block in quick on dc0 from 192.0.2.0/24 to any #reserved for docs block in quick on dc0 from 204.152.64.0/23 to any #Sun cluster interconnect block in quick on dc0 from 224.0.0.0/3 to any #Class D & E multicast # Block fragments and too short tcp packets block in quick on dc0 all with frags block in quick on dc0 proto tcp all with short # block source routed packets block in quick on dc0 all with opt lsrr block in quick on dc0 all with opt ssrr # Block OS fingerprint attempts and log first occurrence block in log first quick on dc0 proto tcp from any to any flags FUP # Block anything with special options block in quick on dc0 all with ipopts # Block public pings and ident block in quick on dc0 proto icmp all icmp-type 8 block in quick on dc0 proto tcp from any to any port = 113 # Block incoming Netbios services block in log first quick on dc0 proto tcp/udp from any to any port = 137 block in log first quick on dc0 proto tcp/udp from any to any port = 138 block in log first quick on dc0 proto tcp/udp from any to any port = 139 block in log first quick on dc0 proto tcp/udp from any to any port = 81 .... Any time there are logged messages on a rule with the `log first` option, run `ipfstat -hio` to evaluate how many times the rule has been matched. A large number of matches may indicate that the system is under attack. The rest of the rules in the inbound section define which connections are allowed to be initiated from the Internet. The last rule denies all connections which were not explicitly allowed by previous rules in this section. [.programlisting] .... # Allow traffic in from ISP's DHCP server. Replace z.z.z.z with # the same IP address used in the outbound section. pass in quick on dc0 proto udp from z.z.z.z to any port = 68 keep state # Allow public connections to specified internal web server pass in quick on dc0 proto tcp from any to x.x.x.x port = 80 flags S keep state # Block and log only first occurrence of all remaining traffic. block in log first quick on dc0 all .... === Configuring NAT To enable NAT, add these statements to [.filename]#/etc/rc.conf# and specify the name of the file containing the NAT rules: [.programlisting] .... gateway_enable="YES" ipnat_enable="YES" ipnat_rules="/etc/ipnat.rules" .... NAT rules are flexible and can accomplish many different things to fit the needs of both commercial and home users. The rule syntax presented here has been simplified to demonstrate common usage. For a complete rule syntax description, refer to man:ipnat[5]. The basic syntax for a NAT rule is as follows, where `map` starts the rule and _IF_ should be replaced with the name of the external interface: [.programlisting] .... map IF LAN_IP_RANGE -> PUBLIC_ADDRESS .... The _LAN_IP_RANGE_ is the range of IP addresses used by internal clients. Usually, it is a private address range such as `192.168.1.0/24`. The _PUBLIC_ADDRESS_ can either be the static external IP address or the keyword `0/32` which represents the IP address assigned to _IF_. In IPF, when a packet arrives at the firewall from the LAN with a public destination, it first passes through the outbound rules of the firewall ruleset. Then, the packet is passed to the NAT ruleset which is read from the top down, where the first matching rule wins. IPF tests each NAT rule against the packet's interface name and source IP address. When a packet's interface name matches a NAT rule, the packet's source IP address in the private LAN is checked to see if it falls within the IP address range specified in _LAN_IP_RANGE_. On a match, the packet has its source IP address rewritten with the public IP address specified by _PUBLIC_ADDRESS_. IPF posts an entry in its internal NAT table so that when the packet returns from the Internet, it can be mapped back to its original private IP address before being passed to the firewall rules for further processing. For networks that have large numbers of internal systems or multiple subnets, the process of funneling every private IP address into a single public IP address becomes a resource problem. Two methods are available to relieve this issue. The first method is to assign a range of ports to use as source ports. By adding the `portmap` keyword, NAT can be directed to only use source ports in the specified range: [.programlisting] .... map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:60000 .... Alternately, use the `auto` keyword which tells NAT to determine the ports that are available for use: [.programlisting] .... map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto .... The second method is to use a pool of public addresses. This is useful when there are too many LAN addresses to fit into a single public address and a block of public IP addresses is available. These public addresses can be used as a pool from which NAT selects an IP address as a packet's address is mapped on its way out. The range of public IP addresses can be specified using a netmask or CIDR notation. These two rules are equivalent: [.programlisting] .... map dc0 192.168.1.0/24 -> 204.134.75.0/255.255.255.0 map dc0 192.168.1.0/24 -> 204.134.75.0/24 .... A common practice is to have a publicly accessible web server or mail server segregated to an internal network segment. The traffic from these servers still has to undergo NAT, but port redirection is needed to direct inbound traffic to the correct server. For example, to map a web server using the internal address `10.0.10.25` to its public IP address of `20.20.20.5`, use this rule: [.programlisting] .... rdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80 .... If it is the only web server, this rule would also work as it redirects all external HTTP requests to `10.0.10.25`: [.programlisting] .... rdr dc0 0.0.0.0/0 port 80 -> 10.0.10.25 port 80 .... IPF has a built in FTP proxy which can be used with NAT. It monitors all outbound traffic for active or passive FTP connection requests and dynamically creates temporary filter rules containing the port number used by the FTP data channel. This eliminates the need to open large ranges of high order ports for FTP connections. In this example, the first rule calls the proxy for outbound FTP traffic from the internal LAN. The second rule passes the FTP traffic from the firewall to the Internet, and the third rule handles all non-FTP traffic from the internal LAN: [.programlisting] .... map dc0 10.0.10.0/29 -> 0/32 proxy port 21 ftp/tcp map dc0 0.0.0.0/0 -> 0/32 proxy port 21 ftp/tcp map dc0 10.0.10.0/29 -> 0/32 .... The FTP `map` rules go before the NAT rule so that when a packet matches an FTP rule, the FTP proxy creates temporary filter rules to let the FTP session packets pass and undergo NAT. All LAN packets that are not FTP will not match the FTP rules but will undergo NAT if they match the third rule. Without the FTP proxy, the following firewall rules would instead be needed. Note that without the proxy, all ports above `1024` need to be allowed: [.programlisting] .... # Allow out LAN PC client FTP to public Internet # Active and passive modes pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state # Allow out passive mode data channel high order port numbers pass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state # Active mode let data channel in from FTP server pass in quick on rl0 proto tcp from any to any port = 20 flags S keep state .... Whenever the file containing the NAT rules is edited, run `ipnat` with `-CF` to delete the current NAT rules and flush the contents of the dynamic translation table. Include `-f` and specify the name of the NAT ruleset to load: [source,shell] .... # ipnat -CF -f /etc/ipnat.rules .... To display the NAT statistics: [source,shell] .... # ipnat -s .... To list the NAT table's current mappings: [source,shell] .... # ipnat -l .... To turn verbose mode on and display information relating to rule processing and active rules and table entries: [source,shell] .... # ipnat -v .... === Viewing IPF Statistics IPF includes man:ipfstat[8] which can be used to retrieve and display statistics which are gathered as packets match rules as they go through the firewall. Statistics are accumulated since the firewall was last started or since the last time they were reset to zero using `ipf -Z`. The default `ipfstat` output looks like this: [source,shell] .... input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0 output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0 input packets logged: blocked 99286 passed 0 output packets logged: blocked 0 passed 0 packets logged: input 0 output 0 log failures: input 3898 output 0 fragment state(in): kept 0 lost 0 fragment state(out): kept 0 lost 0 packet state(in): kept 169364 lost 0 packet state(out): kept 431395 lost 0 ICMP replies: 0 TCP RSTs sent: 0 Result cache hits(in): 1215208 (out): 1098963 IN Pullups succeeded: 2 failed: 0 OUT Pullups succeeded: 0 failed: 0 Fastroute successes: 0 failures: 0 TCP cksum fails(in): 0 (out): 0 Packet log flags set: (0) .... Several options are available. When supplied with either `-i` for inbound or `-o` for outbound, the command will retrieve and display the appropriate list of filter rules currently installed and in use by the kernel. To also see the rule numbers, include `-n`. For example, `ipfstat -on` displays the outbound rules table with rule numbers: [source,shell] .... @1 pass out on xl0 from any to any @2 block out on dc0 from any to any @3 pass out quick on dc0 proto tcp/udp from any to any keep state .... Include `-h` to prefix each rule with a count of how many times the rule was matched. For example, `ipfstat -oh` displays the outbound internal rules table, prefixing each rule with its usage count: [source,shell] .... 2451423 pass out on xl0 from any to any 354727 block out on dc0 from any to any 430918 pass out quick on dc0 proto tcp/udp from any to any keep state .... To display the state table in a format similar to man:top[1], use `ipfstat -t`. When the firewall is under attack, this option provides the ability to identify and see the attacking packets. The optional sub-flags give the ability to select the destination or source IP, port, or protocol to be monitored in real time. Refer to man:ipfstat[8] for details. === IPF Logging IPF provides `ipmon`, which can be used to write the firewall's logging information in a human readable format. It requires that `options IPFILTER_LOG` be first added to a custom kernel using the instructions in crossref:kernelconfig[kernelconfig,Configuring the FreeBSD Kernel]. This command is typically run in daemon mode in order to provide a continuous system log file so that logging of past events may be reviewed. Since FreeBSD has a built in man:syslogd[8] facility to automatically rotate system logs, the default [.filename]#rc.conf# `ipmon_flags` statement uses `-Ds`: [.programlisting] .... ipmon_flags="-Ds" # D = start as daemon # s = log to syslog # v = log tcp window, ack, seq # n = map IP & port to names .... Logging provides the ability to review, after the fact, information such as which packets were dropped, what addresses they came from, and where they were going. This information is useful in tracking down attackers. Once the logging facility is enabled in [.filename]#rc.conf# and started with `service ipmon start`, IPF will only log the rules which contain the `log` keyword. The firewall administrator decides which rules in the ruleset should be logged and normally only deny rules are logged. It is customary to include the `log` keyword in the last rule in the ruleset. This makes it possible to see all the packets that did not match any of the rules in the ruleset. By default, `ipmon -Ds` mode uses `local0` as the logging facility. The following logging levels can be used to further segregate the logged data: [source,shell] .... LOG_INFO - packets logged using the "log" keyword as the action rather than pass or block. LOG_NOTICE - packets logged which are also passed LOG_WARNING - packets logged which are also blocked LOG_ERR - packets which have been logged and which can be considered short due to an incomplete header .... In order to setup IPF to log all data to [.filename]#/var/log/ipfilter.log#, first create the empty file: [source,shell] .... # touch /var/log/ipfilter.log .... Then, to write all logged messages to the specified file, add the following statement to [.filename]#/etc/syslog.conf#: [.programlisting] .... local0.* /var/log/ipfilter.log .... To activate the changes and instruct man:syslogd[8] to read the modified [.filename]#/etc/syslog.conf#, run `service syslogd reload`. Do not forget to edit [.filename]#/etc/newsyslog.conf# to rotate the new log file. Messages generated by `ipmon` consist of data fields separated by white space. Fields common to all messages are: . The date of packet receipt. . The time of packet receipt. This is in the form HH:MM:SS.F, for hours, minutes, seconds, and fractions of a second. . The name of the interface that processed the packet. . The group and rule number of the rule in the format `@0:17`. . The action: `p` for passed, `b` for blocked, `S` for a short packet, `n` did not match any rules, and `L` for a log rule. . The addresses written as three fields: the source address and port separated by a comma, the -> symbol, and the destination address and port. For example: `209.53.17.22,80 -> 198.73.220.17,1722`. . `PR` followed by the protocol name or number: for example, `PR tcp`. . `len` followed by the header length and total length of the packet: for example, `len 20 40`. If the packet is a TCP packet, there will be an additional field starting with a hyphen followed by letters corresponding to any flags that were set. Refer to man:ipf[5] for a list of letters and their flags. If the packet is an ICMP packet, there will be two fields at the end: the first always being "icmp" and the next being the ICMP message and sub-message type, separated by a slash. For example: `icmp 3/3` for a port unreachable message. [[firewalls-blocklistd]] == Blocklistd Blocklistd is a daemon listening to sockets awaiting to receive notifications from other daemons about connection attempts that failed or were successful. It is most widely used in blocking too many connection attempts on open ports. A prime example is SSH running on the internet getting a lot of requests from bots or scripts trying to guess passwords and gain access. Using blocklistd, the daemon can notify the firewall to create a filter rule to block excessive connection attempts from a single source after a number of tries. Blocklistd was first developed on NetBSD and appeared there in version 7, it was originally called blacklistd. FreeBSD 11 imported blocklistd from NetBSD. This chapter describes how to set up blocklistd, configure it, and provides examples on how to use it. Readers should be familiar with basic firewall concepts like rules. For details, refer to the firewall chapter. PF is used in the examples, but other firewalls available on FreeBSD should be able to work with blocklistd, too. === Enabling Blocklistd The main configuration for blocklistd is stored in man:blocklistd.conf[5]. Various command line options are also available to change blocklistd's run-time behavior. Persistent configuration across reboots should be stored in [.filename]#/etc/blocklistd.conf#. To enable the daemon during system boot, add a `blocklistd_enable` line to [.filename]#/etc/rc.conf# like this: [source,shell] .... # sysrc blocklistd_enable=yes .... To start the service manually, run this command: [source,shell] .... # service blocklistd start .... === Creating a Blocklistd Ruleset Rules for blocklistd are configured in man:blocklistd.conf[5] with one entry per line. Each rule contains a tuple separated by spaces or tabs. Rules either belong to a `local` or a `remote`, which applies to the machine where blocklistd is running or an outside source, respectively. ==== Local Rules An example blocklistd.conf entry for a local rule looks like this: [.programlisting] .... [local] ssh stream * * * 3 24h .... All rules that follow the `[local]` section are treated as local rules (which is the default), applying to the local machine. When a `[remote]` section is encountered, all rules that follow it are handled as remote machine rules. Seven fields separated by either tabs or spaces define a rule. The first four fields identify the traffic that should be blocklisted. The three fields that follow define blocklistd's behavior. Wildcards are denoted as asterisks (`*`), matching anything in this field. The first field defines the location. In local rules, these are the network ports. The syntax for the location field is as follows: [.programlisting] .... [address|interface][/mask][:port] .... Addresses can be specified as IPv4 in numeric format or IPv6 in square brackets. An interface name like `_em0_` can also be used. The socket type is defined by the second field. TCP sockets are of type `stream`, whereas UDP is denoted as `dgram`. The example above uses TCP, since SSH is using that protocol. A protocol can be used in the third field of a blocklistd rule. The following protocols can be used: `tcp`, `udp`, `tcp6`, `udp6`, or numeric. A wildcard, like in the example, is typically used to match all protocols unless there is a reason to distinguish traffic by a certain protocol. In the fourth field, the effective user or owner of the daemon process that is reporting the event is defined. The username or UID can be used here, as well as a wildcard (see example rule above). The packet filter rule name is declared by the fifth field, which starts the behavior part of the rule. By default, blocklistd puts all blocks under a pf anchor called `blocklistd` in [.filename]#pf.conf# like this: [.programlisting] .... anchor "blocklistd/*" in on $ext_if block in pass out .... For separate blocklists, an anchor name can be used in this field. In other cases, the wildcard will suffice. When a name starts with a hyphen (`-`) it means that an anchor with the default rule name prepended should be used. A modified example from the above using the hyphen would look like this: [.programlisting] .... ssh stream * * -ssh 3 24h .... With such a rule, any new blocklist rules are added to an anchor called `blocklistd-ssh`. To block whole subnets for a single rule violation, a `/` in the rule name can be used. This causes the remaining portion of the name to be interpreted as the mask to be applied to the address specified in the rule. For example, this rule would block every address adjoining `/24`. [.programlisting] .... 22 stream tcp * */24 3 24h .... [NOTE] ==== It is important to specify the proper protocol here. IPv4 and IPv6 treat /24 differently, that is the reason why `*` cannot be used in the third field for this rule. ==== This rule defines that if any one host in that network is misbehaving, everything else on that network will be blocked, too. The sixth field, called `nfail`, sets the number of login failures required to blocklist the remote IP in question. When a wildcard is used at this position, it means that blocks will never happen. In the example rule above, a limit of three is defined meaning that after three attempts to log into SSH on one connection, the IP is blocked. The last field in a blocklistd rule definition specifies how long a host is blocklisted. The default unit is seconds, but suffixes like `m`, `h`, and `d` can also be specified for minutes, hours, and days, respectively. The example rule in its entirety means that after three times authenticating to SSH will result in a new PF block rule for that host. Rule matches are performed by first checking local rules one after another, from most specific to least specific. When a match occurs, the `remote` rules are applied and the `name`, `nfail`, and `duration` fields are changed by the `remote` rule that matched. ==== Remote Rules Remote rules are used to specify how blocklistd changes its behavior depending on the remote host currently being evaluated. Each field in a remote rule is the same as in a local rule. The only difference is in the way blocklistd is using them. To explain it, this example rule is used: [.programlisting] .... [remote] 203.0.113.128/25 * * * =/25 = 48h .... The address field can be an IP address (either v4 or v6), a port or both. This allows setting special rules for a specific remote address range like in this example. The fields for socket type, protocol and owner are identically interpreted as in the local rule. The name fields is different though: the equal sign (`=`) in a remote rule tells blocklistd to use the value from the matching local rule. It means that the firewall rule entry is taken and the `/25` prefix (a netmask of `255.255.255.128`) is added. When a connection from that address range is blocklisted, the entire subnet is affected. A PF anchor name can also be used here, in which case blocklistd will add rules for this address block to the anchor of that name. The default table is used when a wildcard is specified. A custom number of failures in the `nfail` column can be defined for an address. This is useful for exceptions to a specific rule, to maybe allow someone a less strict application of rules or a bit more leniency in login tries. Blocking is disabled when an asterisk is used in this sixth field. Remote rules allow a stricter enforcement of limits on attempts to log in compared to attempts coming from a local network like an office. === Blocklistd Client Configuration There are a few software packages in FreeBSD that can utilize blocklistd's functionality. The two most prominent ones are package:ftp/freebsd-ftpd[] and man:sshd[8] to block excessive connection attempts. To activate blocklistd in the SSH daemon, add the following line to [.filename]#/etc/ssh/sshd_config#: [.programlisting] .... UseBlocklist yes .... Restart sshd afterwards to make these changes take effect. Blocklisting for package:ftp/freebsd-ftpd[] is enabled using `-B`, either in [.filename]#/etc/inetd.conf# or as a flag in [.filename]#/etc/rc.conf# like this: [.programlisting] .... ftpd_flags="-B" .... That is all that is needed to make these programs talk to blocklistd. === Blocklistd Management Blocklistd provides the user with a management utility called man:blocklistctl[8]. It displays blocked addresses and networks that are blocklisted by the rules defined in man:blocklistd.conf[5]. To see the list of currently blocked hosts, use `dump` combined with `-b` like this. [source,shell] .... # blocklistctl dump -b rulename address/ma:port id nfail last access blocklistd 213.0.123.128/25:22 OK 6/3 2019/06/08 14:30:19 .... This example shows that there were 6 out of three permitted attempts on port 22 coming from the address range `213.0.123.128/25`. There are more attempts listed than are allowed because SSH allows a client to try multiple logins on a single TCP connection. A connection that is currently going on is not stopped by blocklistd. The last connection attempt is listed in the `last access` column of the output. To see the remaining time that this host will be on the blocklist, add `-r` to the previous command. [source,shell] .... # blocklistctl dump -br rulename address/ma:port id nfail remaining time blocklistd 213.0.123.128/25:22 OK 6/3 36s .... In this example, there are 36s seconds left until this host will not be blocked any more. === Removing Hosts from the Block List Sometimes it is necessary to remove a host from the block list before the remaining time expires. Unfortunately, there is no functionality in blocklistd to do that. However, it is possible to remove the address from the PF table using pfctl. For each blocked port, there is a child anchor inside the blocklistd anchor defined in [.filename]#/etc/pf.conf#. For example, if there is a child anchor for blocking port 22 it is called `blocklistd/22`. There is a table inside that child anchor that contains the blocked addresses. This table is called port followed by the port number. In this example, it would be called `port22`. With that information at hand, it is now possible to use man:pfctl[8] to display all addresses listed like this: [source,shell] .... # pfctl -a blocklistd/22 -t port22 -T show ... 213.0.123.128/25 ... .... After identifying the address to be unblocked from the list, the following command removes it from the list: [source,shell] .... # pfctl -a blocklistd/22 -t port22 -T delete 213.0.123.128/25 .... The address is now removed from PF, but will still show up in the blocklistctl list, since it does not know about any changes made in PF. The entry in blocklistd's database will eventually expire and be removed from its output. The entry will be added again if the host is matching one of the block rules in blocklistd again.