<!--
     The FreeBSD Documentation Project

     $FreeBSD: doc/ru_RU.KOI8-R/books/handbook/security/chapter.sgml,v 1.2 2001/03/11 16:45:13 phantom Exp $
     $FreeBSDru: frdp/doc/ru_RU.KOI8-R/books/handbook/security/chapter.sgml,v 1.4 2000/12/17 10:47:19 danfe Exp $
     Original revision: 1.38
-->

<chapter id="security">
  <title>Безопасность</title>

  <para><emphasis>Большинство нижеизложенной информации повторяет страницы
    &man.security.7; справочника, изначально написанного
    &a.dillon;.</emphasis></para>

  <sect1>
    <title>Краткий обзор</title>

    <para>В этой главе мы расскажем об основных сведениях, которые
      необходимо знать, затрагивающие общую безопасность системы, о том, как
      подбирать хорошие пароли, и о таких вещах как S/Key, OpenSSL, Kerberos
      и других.</para>
  </sect1>

  <sect1 id="security-intro">
    <title>Введение</title>

    <para>Несомненно, одна из важнейших задач системного администратора
      &ndash; обеспечивать безопасность системы.  Многопользовательские
      системы, такие как BSD UNIX, имеют некоторый базовый набор средств
      безопасности, однако обычно этого бывает недостаточно, и, чтобы
      построить и поддерживать безопасность системы на должном уровне,
      администратору приходится прикладывать некоторые усилия.  Безопасность
      системы целиком и полностью находится в руках системного
      администратора.  UNIX системы способны выполнять огромное число
      процессов одновременно, и многие из них являются серверами, то есть к
      ним можно обращаться извне.  Сегодня уже никого не удивишь компьютером
      на рабочем столе, а с распространением и повсеместным внедрением в
      нашу жизнь сетевых технологий проблемы безопасности становятся
      первоочередными.</para>

    <para>Лучше всего строить модель безопасности, основываясь на
      <quote>уровневом</quote> подходе.  В двух словах, это означает создание
      неких <quote>эшелонов</quote>, <quote>колец</quote> защиты, и бдительное
      наблюдение за состоянием каждого уровня.  Имейте в виду, что слишком
      <quote>перегруженная</quote> система безопасности может скорее
      помещать, нежели помочь предотвращению атаки.  Например, не стоит
      устанавливать schg-флаги (см. &man.chflags.1;) на каждый выполняемый
      системный файл, так как это, возможно, и предотвратит
      несанкционированные модификации Ваших файлов, но, в то же время, может
      лишить Вас легко детектируемых следов пребывания хакера, что ему
      только на руку.</para>

    <para>Пречислим ключевые действия, которые имеют непосредственное
      отношение к безопасности любой компьютерной системы:</para>

    <orderedlist>
      <listitem>
	<para>Атаки типа <quote>отказ от обслуживания</quote> (D.o.S.).</para>
      </listitem>

      <listitem>
	<para>Получение пользовательского аккаунта.</para>
      </listitem>

      <listitem>
	<para>Получение прав суперпользователя (root) через доступные
	  сервисы.</para>
      </listitem>

      <listitem>
	<para>Получение прав суперпользователя (root) через пользовательские
	  аккаунты.</para>
      </listitem>

      <listitem>
	<para>Создание люков (задних дверей, <quote>черных
	  ходов</quote>).</para>
      </listitem>
    </orderedlist>

    <para>При атаке на отказ от обслуживания машина лишается необходимых
      ресурсов для выполнения требуемых запросов.  Наиболее типичными
      атаками этого типа являются механизмы так называемой <quote>грубой
      силы</quote> (brute-force), которые направлены на выведение из строя
      отдельных серверов или сети в целом.  Иногда для достижения цели
      используются обнаруженые ошибки в сетевом стеке, когда даже одного
      специальным образом составленного пакета достаточно, чтобы вывести
      машину из строя.  Обычно ошибки такого рода исправляются путем
      прикладывания соответствующих <quote>патчей</quote> к ядру.  Разумно
      также тщательно подбирать сетевые опции, чтобы не допустить перегрузки
      серверов при работе с очень высоким потоком данных (например,
      каким-либо образом ограничивать этот поток).  Если же Вашу систему
      атакуют методом <quote>грубой силы</quote>, бороться с этим сложнее. 
      Например, если машину <quote>забрасывают</quote> специальным образом
      сгенерированными пакетами, то часто бывает, что практически невозможно
      остановить атакующего, кроме как полностью отключив компьютер от сети.
      Даже в этом случае, хотя Ваша машина не будет затронута, сетевой
      трафик будет сильно нарушен.</para>

    <para>Атаки, нацеленные на аккаунты рядовых пользователей распространены
      еще больше, чем атаки на отказ от обслуживания.  Многие системные
      администраторы все еще достаточно часто используют стандартные
      сервисы, такие как telnetd, rlogind, rshd и ftpd.  Эти демоны, по
      умолчанию, не используют шифрование передаваемых по сети данных при
      своей работе.  В результате, если у Вас достаточно большое число
      пользователей системы, весьма вероятно, что кто-нибудь из них
      рано или поздно <quote>засветит</quote> свой пароль.  Поэтому
      внимательный администратор всегда должен анализировать файлы системных
      журналов на предмет попыток зайти на машину
      с необычных адресов, и тем более в случае успеха таких попыток.</para>

    <para>Всегда важно помнить, что если атакующий имеет доступ к
      пользовательскомуц аккаунт, то потенциально он может получить и права
      суперпользователя.  Однако, на самом деле, на правильно и умело
      сконфигурированной и регулярно проверяемой машине, наличие
      пользовательского аккаунта вовсе не означает, что атакующий сможет
      <quote>сломать</quote> ее.  Разница между типичным пользовательским
      аккаунтом и аккаунтом суперпользователя в том, что во втором случае
      атакующий может сделать с системой что угодно, в то же время, без
      привилегий суперпользователя, можно лишь модифицировать или удалить
      файлы, принадлежащие данному пользователю, или в худшем случае
      <quote>завесить</quote> машину.  Случаи, когда атакующий получает
      (неавторизованно) пользовательские права, весьма нередки, так как
      обычно рядовые пользователи не принимают всех необходимых мер
      предосторожности, и часто в задачу системного администратора входит
      принятие этих мер.</para>

    <para>Системный администратор всегда должен иметь ввиду, что существует
      множество потенциальных путей, которыми атакующих может проникнуть в
      систему.  Например, он может знать пароль суперпользователя,
      воспользоваться ошибкой в программном обеспечении, выполняющимся с
      повышеными привилегиями, сетевом или локальном.  Если атакующий нашел
      способ проникнуть в систему (получить привелегии суперпользователя),
      то чаще всего он попытается оставить так называемый <quote>люк</quote>,
      чтобы в следующий раз ему не пришлось проделывать всю грязную работу
      заново (и затем убирать за собой).  Это дает Вам удобную возможность
      обнаружить взломщика (так как ему придется произвести кое-какие
      изменения в системе).  Если же хакер смог установить люк, это может
      губительно сказаться на безопасности Вашей системы, так как сильно
      снижаются шансы, что кто-нибудь еще попытаеся взломать ее тем же
      способом, что и в первый раз, и, таким образом, дырка в системе
      останется открытой.</para>

    <para>Как уже было сказано ранее, лучше всего строить модель безопасности,
      основываясь на <quote>уровневом</quote> подходе.  Перечислим основные
      моменты:</para>

    <orderedlist>
      <listitem>
	<para>Обеспечивание безопасности служебных аккаунтов и аккаунта суперпользователя.</para>
      </listitem>

      <listitem>
	<para>Безопасность серверов, выполняющихся с повышенными привилегиями, и исполнимых файлов, использующих SUID/SGID механизм.</para>
      </listitem>

      <listitem>
	<para>Обеспечивание безопасности пользовательских аккаунтов.</para>
      </listitem>

      <listitem>
	<para>Защита файлов, содержащих пароли.</para>
      </listitem>

      <listitem>
	<para>Защита ядра операционной системы, raw устройств и файловых
	  систем.</para>
      </listitem>

      <listitem>
	<para>Быстрое обнаружение подозрительных изменений в системе.</para>
      </listitem>

      <listitem>
	<para>Паранойя.</para>
      </listitem>
    </orderedlist>

    <para>В следующей секции все перечисленные пункты будут рассмотрены в
      подробностях.</para>
  </sect1>

  <sect1 id="securing-freebsd">
    <title>Обеспечиваем безопасность FreeBSD</title>

    <para>В этой секции мы расскажем об основных методах защиты и
      обеспечивания безопасности Вашей системы FreeBSD, которые были
      упомянуты в <link linkend="security-intro">предыдущей секции</link>
      этой главы.</para>

    <sect2 id="securing-root-and-staff">
      <title>Защита аккаутнов суперпользователя и служебного
	персонала</title>

      <para>В первую очередь нужно обеспечить безопасность
	суперпользовательского аккаунта, и уже после принимать аналочичные
	меры в отношении прочих привелигированных аккаунтов.  Во многих
	системах аккаунт суперпользователя защищен паролем.  Имейте в виду,
	что этот пароль крайне важен, а поэтому нелишним будет относиться к
	нему с очень большой осторожностью.  Прежде всего, желательно
	не использовать его кроме как за консолью, даже применяя команду
	&man.su.1;.  В частности, удостоверьтесь, что терминалы, перечисленные
	в файле <filename>/etc/ttys</filename>, помечены как insecure
	(небезопасные), чтобы запретить прямой доступ посредством команд
	<command>telnet</command> или <command>rlogin</command>.  При
	использовании других сервисов, таких, например, как
	<application>sshd</application>, также следует запретить
	непосредсвенный вход в систему с правами суперпользователя.
	Проверьте все возможные подступы к системе &ndash; сервисы типа
	FTP чато оказываются подверженными атакам.  Непосредственный
	вход в систему с правами суперпользователя следует разрешить
	только с консоли.</para>

      <para>Конечно, Вам как системному администратору необходимо иметь
	возжожность получить права суперпользователя, поэтому несколько
	путей все же есть.  Однако, очень важно защитить их использование
	дополнительными паролями.  Один из способов дать какому-либо
	пользователю повышенные привилегии &ndash; это перечислить его
	в группе <literal>wheel</literal> (в файле
	<filename>/etc/group</filename>).  Пользователь, входящий в эту
	группу, может вызвать <literal>su</literal> для получения прав
	суперпользователя.  Не следует включать всех членов служебного
	персонала в группу <literal>wheel</literal>, задавая ее как основную
	группу пользователя в файле паролей.  Вместо этого, нужно включить
	их в специальную группу <literal>staff</literal>, и затем, только
	в случае необходимости, некоторых из них включить в группу
	<literal>wheel</literal>, сделав соответсвующую запись в файле
	<filename>/etc/group</filename>.  Также возможно, при использовании
	методов аутентикации типа kerberos, использовать файл
	<filename>.k5login</filename> для того, чтобы разрешить получение
	привилегий супервозователя посредствеом команды &man.ksu.1; без
	необходимости включать кого-либо в группу <literal>wheel</literal>.
	Это может оказаться лучшим решением, так как предыдущий метод
	позволяет хакеру получить права суперпользователя, если ему удастся
	получить доступ к служебному акканту.  Тем не менее, все это лучше,
	чем ничего.</para>

      <para>Аккаунт суперпользователя можно защитить косвенным путем,
	посредством использования альтернативных методов аутентикации и
	замены хэшированных паролей служебных аккаунтов на символ
	<literal>*</literal> в файле паролей (/etc/passwd).  В этом случае,
	даже если взломщик получит этот файл, он не сможет извлечь оттуда
	пароли, включая пароль суперпользователя.  Сотрудники служебного
	персонала будут сходить в систему при помощи защищенного механизма
	аутентикации, например, &man.kerberos.1; или &man.ssh.1;, используя
	специальную пару ключей (приватный/публичный).  При использовании
	систем типа kerberos, Вам потребуется обеспечить безопасность
	kerberos-серверов и Вашей рабочей станции.  При использовании
	механизма публичного/приватного ключей, например, при работе с
	<application>ssh</application>, Вам необходимо обеспечить
	безопасность машины, <emphasis>с которой</emphasis> Вы будете
	заходить в систему (обычно это Ваша рабочая станция), но можно также
	обеспечить себе дополнительную безопасность, защитив пару ключей
	паролем в момент ее генерации (&man.ssh-keygen.1;).  Возможность
	заменять реальные хэши паролей на символ <literal>*</literal> в
	файле паролей (это особенно важно для аккаунтов служебного
	персонала, обладающего повышенными привилегиями по сравнению с
	обычными пользователями) также гарантирует, что они будут
	пользоваться только безопасными методами аутентикации, которые Вы
	предварительно настроили.  Это хорошо тем, что закрывает наиболее
	часто используемую взломщиками дыру &ndash; прослушивание
	(<quote>сниффинг</quote>) сети с менее защищенной машины (на которой
	у него уже есть все необходимые привилегии).</para>

      <para>Еще стоит обратить внимание на следующие моменты: если Ваш
	основной сервер предоставляет всевозможные сетевые сервисы, то на
	Вашей рабочей станции по возможности максимальное число сетевых
	служб должно быть отключено (а в идеале &ndash; все), и нелишним
	будет использование хранителя экрана, защищенного паролем.  Конечно,
	если у злоумышленника есть физический доступ к машине, то
	практически никакие методы защиты не помогут (хотя и могут
	значительно увеличить время взлома), однако большинство атак все же
	происходят снаружи, по сети, когда у атакующего нет
	непосредственного доступа к системе.</para>

      <para>При использовании систем аутентикации типа kerberos, у Вас есть возможность централизованно менять пароли или блокировать доступ пользователей.  Это очень полезно при подозрении, что пароль какого-либо (например, администраторского) аккаунта стал известен постороннему лицу &ndash; в этом случае можно очень быстро запретить вход на все машины, где был заведен данный пользователь.  Представьте себе, насколько труднее и дольше было бы менять пароли на каждой из N машин отдельно!  Kerberos предосталяет и другие возможности (принудительная смена пароля по истечении определенного промежутка времени, например).</para>
    </sect2>

    <sect2>
      <title>Безопасность серверов, выполняющихся с повышенными привилегиями, и исполнимых файлов, использующих SUID/SGID механизм</title>

      <para>Осторожный системный администратор конфигурирует систему так, чтобы запущены были только самые необходимые сервисы.  Не больше, не меньше.  Стоит с особой осторожностью отновиться 
      tHE prudent sysadmin only runs the servers he needs to, no more, no less.  Be aware that third party servers are often the
	most bug-prone.  For example, running an old version of imapd or
	popper is like giving a universal root ticket out to the entire
	world.  Never run a server that you have not checked out
	carefully.  Many servers do not need to be run as root.  For
	example, the <application>ntalk</application>,
	<application>comsat</application>, and
	<application>finger</application> daemons can be run in special
	user <literal>sandboxes</literal>.  A sandbox isn't perfect unless
	you go to a large amount of trouble, but the onion approach to
	security still stands:  If someone is able to break in through
	a server running in a sandbox, they still have to break out of the
	sandbox.  The more layers the attacker must break through, the
	lower the likelihood of his success.  Root holes have historically
	been found in virtually every server ever run as root, including
	basic system servers.  If you are running a machine through which
	people only login via <application>sshd</application> and never
	login via <application>telnetd</application> or
	<application>rshd</application> or
	<application>rlogind</application>, then turn off those
	services!</para>

      <para>FreeBSD now defaults to running
	<application>ntalkd</application>,
	<application>comsat</application>, and
	<application>finger</application> in a sandbox.  Another program
	which may be a candidate for running in a sandbox is &man.named.8;.
	The default <filename>rc.conf</filename> includes the arguments
	necessary to run <application>named</application>in a sandbox in a
	commented-out form.  Depending on whether you are installing a new
	system or upgrading an existing system, the special user accounts
	used by these sandboxes may not be installed.  The prudent
	sysadmin would research and implement sandboxes for servers
	whenever possible.</para>

      <para>There are a number of other servers that typically do not run
	in sandboxes: <application>sendmail</application>,
	<application>popper</application>,
	<application>imapd</application>, <application>ftpd</application>,
	and others.  There are alternatives to some of these, but
	installing them may require more work then you are willing to
	perform (the convenience factor strikes again). You may have to
	run these servers as root and rely on other mechanisms to detect
	break-ins that might occur through them.</para>

      <para>The other big potential root hole in a system are the
	suid-root and sgid binaries installed on the system.  Most of
	these binaries, such as <application>rlogin</application>, reside
	in <filename>/bin</filename>, <filename>/sbin</filename>,
	<filename>/usr/bin</filename>, or <filename>/usr/sbin</filename>.
	While nothing is 100% safe, the system-default suid and sgid
	binaries can be considered reasonably safe.  Still, root holes are
	occasionally found in these binaries.  A root hole was found in
	<literal>Xlib</literal> in 1998 that made
	<application>xterm</application> (which is typically suid)
	vulnerable.  It is better to be safe then sorry and the prudent
	sysadmin will restrict suid binaries that only staff should run to
	a special group that only staff can access, and get rid of
	(<command>chmod 000</command>) any suid binaries that nobody uses.
	A server with no display generally does not need an
	<application>xterm</application> binary.  Sgid binaries can be
	almost as dangerous.  If an intruder can break an sgid-kmem binary
	the intruder might be able to read <filename>/dev/kmem</filename>
	and thus read the crypted password file, potentially compromising
	any passworded account.  Alternatively an intruder who breaks
	group <literal>kmem</literal> can monitor keystrokes sent through
	pty's, including pty's used by users who login through secure
	methods.  An intruder that breaks the tty group can write to
	almost any user's tty.  If a user is running a terminal program or
	emulator with a keyboard-simulation feature, the intruder can
	potentially generate a data stream that causes the user's terminal
	to echo a command, which is then run as that user.</para>
    </sect2>

    <sect2 id="secure-users">
      <title>Securing User Accounts</title>

      <para>User accounts are usually the most difficult to secure.  While
	you can impose Draconian access restrictions on your staff and
	<literal>*</literal> out their passwords, you may not be able to
	do so with any general user accounts you might have.  If you do
	have sufficient control then you may win out and be able to secure
	the user accounts properly.  If not, you simply have to be more
	vigilant in your monitoring of those accounts.  Use of
	<application>ssh</application> and kerberos for user accounts is
	more problematic due to the extra administration and technical
	support required, but still a very good solution compared to a
	crypted password file.</para>
    </sect2>

    <sect2>
      <title>Securing the Password File</title>

      <para>The only sure fire way is to <literal>*</literal> out as many
	passwords as you can and use <application>ssh</application> or
	kerberos for access to those accounts.  Even though the crypted
	password file (<filename>/etc/spwd.db</filename>) can only be read
	by root, it may be possible for an intruder to obtain read access
	to that file even if the attacker cannot obtain root-write
	access.</para>

      <para>Your security scripts should always check for and report
	changes to the password file (see <link
	linkend="security-integrity">Checking file integrity</link>
	below).</para>
    </sect2>

    <sect2>
      <title>Securing the Kernel Core, Raw Devices, and
	Filesystems</title>

      <para>If an attacker breaks root he can do just about anything, but
	there are certain conveniences.  For example, most modern kernels
	have a packet sniffing device driver built in.  Under FreeBSD it
	is called the <devicename>bpf</devicename> device.  An intruder
	will commonly attempt to run a packet sniffer on a compromised
	machine.  You do not need to give the intruder the capability and
	most systems should not have the bpf device compiled in.</para>

      <para>But even if you turn off the bpf device, you still have
	<filename>/dev/mem</filename> and <filename>/dev/kmem</filename>
	to worry about.  For that matter, the intruder can still write to
	raw disk devices.  Also, there is another kernel feature called
	the module loader, &man.kldload.8;.  An enterprising intruder can
	use a KLD module to install his own bpf device or other sniffing
	device on a running kernel.  To avoid these problems you have to
	run the kernel at a higher secure level, at least securelevel 1.
	The securelevel can be set with a <command>sysctl</command> on
	the <literal>kern.securelevel</literal> variable.  Once you have
	set the securelevel to 1, write access to raw devices will be
	denied and special chflags flags, such as <literal>schg</literal>,
	will be enforced.  You must also ensure that the
	<literal>schg</literal> flag is set on critical startup binaries,
	directories, and script files &ndash; everything that gets run up
	to the point where the securelevel is set.  This might be overdoing
	it, and upgrading the system is much more difficult when you
	operate at a higher secure level.  You may compromise and run the
	system at a higher secure level but not set the
	<literal>schg</literal> flag for every system file and directory
	under the sun.  Another possibility is to simply mount
	<filename>/</filename> and <filename>/usr</filename> read-only.
	It should be noted that being too draconian in what you attempt to
	protect may prevent the all-important detection of an
	intrusion.</para>
    </sect2>

    <sect2 id="security-integrity">
      <title>Checking File Integrity: Binaires, Configuration Files,
	Etc.</title>

      <para>When it comes right down to it, you can only protect your core
	system configuration and control files so much before the
	convenience factor rears its ugly head.  For example, using
	<command>chflags</command> to set the <literal>schg</literal> bit
	on most of the files in <filename>/</filename> and
	<filename>/usr</filename> is probably counterproductive because
	while it may protect the files, it also closes a detection window.
	The last layer of your security onion is perhaps the most
	important &ndash; detection.  The rest of your security is pretty
	much useless (or, worse, presents you with a false sense of
	safety) if you cannot detect potential incursions.  Half the job
	of the onion is to slow down the attacker rather then stop him in
	order to give the detection side of the equation a chance to catch
	him in the act.</para>

      <para>The best way to detect an incursion is to look for modified,
	missing, or unexpected files.  The best way to look for modified
	files is from another (often centralized) limited-access system.
	Writing your security scripts on the extra-secure limited-access
	system makes them mostly invisible to potential hackers, and this
	is important.  In order to take maximum advantage you generally
	have to give the limited-access box significant access to the
	other machines in the business, usually either by doing a
	read-only NFS export of the other machines to the limited-access
	box, or by setting up <application>ssh</application> keypairs to
	allow the limit-access box to <application>ssh</application> to
	the other machines.  Except for its network traffic, NFS is the
	least visible method &ndash; allowing you to monitor the
	filesystems on each client box virtually undetected.  If your
	limited-access server is connected to the client boxes through a
	switch, the NFS method is often the better choice.  If your
	limited-access server is connected to the client boxes through a
	hub or through several layers of routing, the NFS method may be
	too insecure (network-wise) and using
	<application>ssh</application> may be the better choice even with
	the audit-trail tracks that <application>ssh</application>
	lays.</para>

      <para>Once you give a limit-access box at least read access to the
	client systems it is supposed to monitor, you must write scripts
	to do the actual monitoring.  Given an NFS mount, you can write
	scripts out of simple system utilities such as &man.find.1; and
	&man.md5.1;.  It is best to physically md5 the client-box files
	boxes at least once a day, and to test control files such as those
	found in <filename>/etc</filename> and
	<filename>/usr/local/etc</filename> even more often.  When
	mismatches are found relative to the base md5 information the
	limited-access machine knows is valid, it should scream at a
	sysadmin to go check it out.  A good security script will also
	check for inappropriate suid binaries and for new or deleted files
	on system partitions such as <filename>/</filename> and
	<filename>/usr</filename>.</para>

      <para>When using <application>ssh</application> rather then NFS,
	writing the security script is much more difficult.   You
	essentially have to scp the scripts to the client box in order to
	run them, making them visible, and for safety you also need to
	<command>scp</command> the binaries (such as find) that those
	scripts use.  The <application>ssh</application> daemon on the
	client box may already be compromised.  All in all, using
	<application>ssh</application> may be necessary when running over
	unsecure links, but it's also a lot harder to deal with.</para>

      <para>A good security script will also check for changes to user and
	staff members access configuration files:
	<filename>.rhosts</filename>, <filename>.shosts</filename>,
	<filename>.ssh/authorized_keys</filename> and so forth&hellip;
	files that might fall outside the purview of the
	<literal>MD5</literal> check.</para>

      <para>If you have a huge amount of user disk space it may take too
	long to run through every file on those partitions.  In this case,
	setting mount flags to disallow suid binaries and devices on those
	partitions is a good idea.  The <literal>nodev</literal> and
	<literal>nosuid</literal> options (see &man.mount.8;) are what you
	want to look into.  I would scan them anyway at least once a week,
	since the object of this layer is to detect a break-in whether or
	not the break-in is effective.</para>

      <para>Process accounting (see &man.accton.8;) is a relatively
	low-overhead feature of the operating system which I recommend
	using as a post-break-in evaluation mechanism.  It is especially
	useful in tracking down how an intruder has actually broken into
	a system, assuming the file is still intact after the break-in
	occurs.</para>

      <para>Finally, security scripts should process the log files and the
	logs themselves should be generated in as secure a manner as
	possible &ndash; remote syslog can be very useful.  An intruder
	tries to cover his tracks, and log files are critical to the
	sysadmin trying to track down the time and method of the initial
	break-in.  One way to keep a permanent record of the log files is
	to run the system console to a serial port and collect the
	information on a continuing basis through a secure machine
	monitoring the consoles.</para>
    </sect2>

    <sect2>
      <title>Паранойя</title>

      <para>A little paranoia never hurts.  As a rule, a sysadmin can add
	any number of security features as long as they do not effect
	convenience, and can add security features that do effect
	convenience with some added thought.  Even more importantly, a
	security administrator should mix it up a bit &ndash; if you use
	recommendations such as those given by this document verbatim, you
	give away your methodologies to the prospective hacker who also
	has access to this document.</para>
    </sect2>

    <sect2>
      <title>Denial of Service Attacks</title>

      <para>This section covers Denial of Service attacks.  A DOS attack
	is typically a packet attack.  While there is not much you can do
	about modern spoofed packet attacks that saturate your network,
	you can generally limit the damage by ensuring that the attacks
	cannot take down your servers.</para>

      <orderedlist>
	<listitem>
	  <para>Limiting server forks.</para>
	</listitem>

	<listitem>
	  <para>Limiting springboard attacks (ICMP response attacks, ping
	    broadcast, etc.).</para>
	</listitem>

	<listitem>
	  <para>Kernel Route Cache.</para>
	</listitem>
      </orderedlist>

      <para>A common DOS attack is against a forking server that attempts
	to cause the server to eat processes, file descriptors, and memory
	until the machine dies.  Inetd (see &man.inetd.8;) has several
	options to limit this sort of attack.  It should be noted that
	while it is possible to prevent a machine from going down it is
	not generally possible to prevent a service from being disrupted
	by the attack.  Read the inetd manual page carefully and pay
	specific attention to the <option>-c</option>, <option>-C</option>,
	and <option>-R</option> options.  Note that spoofed-IP attacks
	will circumvent the <option>-C</option> option to inetd, so
	typically a combination of options must be used.  Some standalone
	servers have self-fork-limitation parameters.</para>

      <para><application>Sendmail</application> has its
	<option>-OMaxDaemonChildren</option> option which tends to work
	much better than trying to use sendmail's load limiting options
	due to the load lag.  You should specify a
	<literal>MaxDaemonChildren</literal> parameter when you start
	<application>sendmail</application> high enough to handle your
	expected load but no so high that the computer cannot handle that
	number of <application>sendmails</application> without falling on
	its face.  It is also prudent to run sendmail in queued mode
	(<option>-ODeliveryMode=queued</option>) and to run the daemon
	(<command>sendmail -bd</command>) separate from the queue-runs
	(<command>sendmail -q15m</command>). If you still want realtime
	delivery you can run the queue at a much lower interval, such as
	<option>-q1m</option>, but be sure to specify a reasonable
	<literal>MaxDaemonChildren</literal> option for that sendmail to
	prevent cascade failures.</para>

      <para><application>Syslogd</application> can be attacked directly
	and it is strongly recommended that you use the <option>-s</option>
	option whenever possible, and the <option>-a</option> option
	otherwise.</para>

      <para>You should also be fairly careful with connect-back services
	such as <application>tcpwrapper</application>'s reverse-identd,
	which can be attacked directly.  You generally do not want to use
	the reverse-ident feature of
	<application>tcpwrappers</application> for this reason.</para>

      <para>It is a very good idea to protect internal services from
	external access by firewalling them off at your border routers.
	The idea here is to prevent saturation attacks from outside your
	LAN, not so much to protect internal services from network-based
	root compromise.  Always configure an exclusive firewall, i.e.,
	<quote>firewall everything <emphasis>except</emphasis> ports A, B,
	C, D, and M-Z</quote>.  This way you can firewall off all of your
	low ports except for certain specific services such as
	<application>named</application> (if you are primary for a zone),
	<application>ntalkd</application>,
	<application>sendmail</application>, and other internet-accessible
	services.  If you try to configure the firewall the other way
	&ndash; as an inclusive or permissive firewall, there is a good
	chance that you will forget to <quote>close</quote> a couple of
	services or that you will add a new internal service and forget
	to update the firewall.  You can still open up the high-numbered
	port range on the firewall to allow permissive-like operation
	without compromising your low ports.  Also take note that FreeBSD
	allows you to control the range of port numbers used for dynamic
	binding via the various <literal>net.inet.ip.portrange</literal>
	<command>sysctl</command>'s (<command>sysctl -a | fgrep
	portrange</command>), which can also ease the complexity of your
	firewall's configuration.  I usually use a normal first/last range
	of 4000 to 5000, and a hiport range of 49152 to 65535, then block
	everything under 4000 off in my firewall (except for certain
	specific internet-accessible ports, of course).</para>

      <para>Another common DOS attack is called a springboard attack
	&ndash; to attack a server in a manner that causes the server to
	generate responses which then overload the server, the local
	network, or some other machine.  The most common attack of this
	nature is the <emphasis>ICMP ping broadcast attack</emphasis>.
	The attacker spoofs ping packets sent to your LAN's broadcast
	address with the source IP address set to the actual machine they
	wish to attack.  If your border routers are not configured to
	stomp on ping's to broadcast addresses, your LAN winds up
	generating sufficient responses to the spoofed source address to
	saturate the victim, especially when the attacker uses the same
	trick on several dozen broadcast addresses over several dozen
	different networks at once.  Broadcast attacks of over a hundred
	and twenty megabits have been measured.  A second common
	springboard attack is against the ICMP error reporting system.
	By constructing packets that generate ICMP error responses, an
	attacker can saturate a server's incoming network and cause the
	server to saturate its outgoing network with ICMP responses.  This
	type of attack can also crash the server by running it out of
	mbuf's, especially if the server cannot drain the ICMP responses
	it generates fast enough.  The FreeBSD kernel has a new kernel
	compile option called ICMP_BANDLIM which limits the effectiveness
	of these sorts of attacks.  The last major class of springboard
	attacks is related to certain internal inetd services such as the
	udp echo service.  An attacker simply spoofs a UDP packet with the
	source address being server A's echo port, and the destination
	address being server B's echo port, where server A and B are both
	on your LAN.  The two servers then bounce this one packet back and
	forth between each other.  The attacker can overload both servers
	and their LANs simply by injecting a few packets in this manner.
	Similar problems exist with the internal chargen port.  A
	competent sysadmin will turn off all of these inetd-internal test
	services.</para>

      <para>Spoofed packet attacks may also be used to overload the kernel
	route cache.  Refer to the <literal>net.inet.ip.rtexpire</literal>,
	<literal>rtminexpire</literal>, and <literal>rtmaxcache</literal>
	<command>sysctl</command> parameters.  A spoofed packet attack
	that uses a random source IP will cause the kernel to generate a
	temporary cached route in the route table, viewable with
	<command>netstat -rna | fgrep W3</command>.  These routes
	typically timeout in 1600 seconds or so.  If the kernel detects
	that the cached route table has gotten too big it will dynamically
	reduce the rtexpire but will never decrease it to less then
	rtminexpire.  There are two problems:</para>
	
      <orderedlist>
	<listitem>
	  <para>The kernel does not react quickly enough when a lightly
	    loaded server is suddenly attacked.</para>
	</listitem>
	
	<listitem>
	  <para>The <literal>rtminexpire</literal> is not low enough for
	    the kernel to survive a sustained attack.</para>
	</listitem>
      </orderedlist>
      
      <para>If your servers are connected to the internet via a T3 or
        better it may be prudent to manually override both
	<literal>rtexpire</literal> and <literal>rtminexpire</literal>
	via &man.sysctl.8;.  Never set either parameter to zero (unless
	you want to crash the machine <!-- smiley -->:-).  Setting both
	parameters to 2 seconds should be sufficient to protect the route
	table from attack.</para>
    </sect2>

    <sect2>
      <title>Access Issues with Kerberos and SSH</title>

      <para>There are a few issues with both kerberos and
	<application>ssh</application> that need to be addressed if you
	intend to use them.  Kerberos V is an excellent authentication
	protocol but the kerberized <application>telnet</application> and
	<application>rlogin</application> suck rocks.  There are bugs that
	make them unsuitable for dealing with binary streams.  Also, by
	default kerberos does not encrypt a session unless you use the
	<option>-x</option> option.  <application>ssh</application>
	encrypts everything by default.</para>

      <para><application>ssh</application> works quite well in every
	respect except that it forwards encryption keys by default.  What
	this means is that if you have a secure workstation holding keys
	that give you access to the rest of the system, and you
	<application>ssh</application> to an unsecure machine, your keys
	becomes exposed.  The actual keys themselves are not exposed, but
	<application>ssh</application> installs a forwarding port for the
	duration of your login and if a hacker has broken root on the
	unsecure machine he can utilize that port to use your keys to gain
	access to any other machine that your keys unlock.</para>

      <para>We recommend that you use <application>ssh</application> in
	combination with kerberos whenever possible for staff logins.
	<application>ssh</application> can be compiled with kerberos
	support.  This reduces your reliance on potentially exposable
	<application>ssh</application> keys while at the same time
	protecting passwords via kerberos.  <application>ssh</application>
	keys should only be used for automated tasks from secure machines
	(something that kerberos is unsuited to).  We also recommend that
	you either turn off key-forwarding in the
	<application>ssh</application> configuration, or that you make use
	of the <literal>from=IP/DOMAIN</literal> option that
	<application>ssh</application> allows in its
	<filename>authorized_keys</filename> file to make the key only
	useable to entities logging in from specific machines.</para>
    </sect2>
  </sect1>

  <sect1 id="crypt">
    <title>DES, MD5, and Crypt</title>
    
    <para><emphasis>Parts rewritten and updated by &a.unfurl;, 21 March
      2000.</emphasis></para>

    <para>Every user on a UNIX system has a password associated with their
      account, obviously these passwords need to be known only to
      the user and the actual operating system.  In order to keep
      these passwords secret, they are encrypted with what is known
      as a 'one-way hash', that is, they can only be easily encrypted
      but not decrypted.  The only way to get the password is by
      brute force searching the space of possible passwords.
      Unfortunately the only secure way to encrypt passwords when
      UNIX came into being was based on DES, the Data Encryption
      Standard.  This is not such a problem for users that live in
      the US, but since the source code for DES cannot be exported
      outside the US, FreeBSD had to find a way to both comply with
      US law and retain compatibility with all the other UNIX
      variants that still use DES.</para>

    <para>The solution was to divide up the encryption libraries 
      so that US users could install the DES libraries and use
      DES but international users still had an encryption method
      that could be exported abroad.  This is how FreeBSD came to
      use MD5 as it's default encryption method.</para>

    <sect2>
      <title>Recognizing your crypt mechanism</title>

      <para>It is pretty easy to identify which encryption method 
	FreeBSD is set up to use.  Examining the encrypted passwords in
	the <filename>/etc/master.passwd</filename> file is one way.
	Passwords encrypted with the MD5 hash are longer than those with
	encrypted with the DES hash and also begin with the characters
	<literal>&dollar;1&dollar;</literal>.  DES password strings do not
	have any particular identifying characteristics, but they are
	shorter than MD5 passwords, and are coded in a 64-character
	alphabet which does not include the <literal>&dollar;</literal>
	character, so a relatively short string which does not begin with
	a dollar sign is very likely a DES password.</para>
  
      <para>Identifying which library is being used by the programs on
	your system is easy as well. Any program that uses crypt is linked
	against libcrypt which for each type of library is a symbolic link
	to the appropriate implementation. For example, on a system using
	the DES versions:</para>

      <screen>&prompt.user; <userinput>ls -l /usr/lib/libcrypt*</userinput>
lrwxr-xr-x  1 root  wheel  13 Mar 19 06:56 libcrypt.a -&gt; libdescrypt.a
lrwxr-xr-x  1 root  wheel  18 Mar 19 06:56 libcrypt.so.2.0 -&gt; libdescrypt.so.2.0
lrwxr-xr-x  1 root  wheel  15 Mar 19 06:56 libcrypt_p.a -&gt; libdescrypt_p.a</screen>

      <para>On a system using the MD5-based libraries, the same links will
	be present, but the target will be <filename>libscrypt</filename>
	rather than <filename>libdescrypt</filename>.</para>
    </sect2>
  </sect1>

  <sect1 id="skey">
    <title>S/Key</title>

    <para>S/Key is a one-time password scheme based on a one-way hash
      function.  FreeBSD uses the MD4 hash for compatibility but other
      systems have used MD5 and DES-MAC.  S/Key has been part of the
      FreeBSD base system since version 1.1.5 and is also used on a
      growing number of other operating systems.  S/Key is a registered
      trademark of Bell Communications Research, Inc.</para>

    <para>There are three different sorts of passwords which we will talk
      about in the discussion below.  The first is your usual UNIX-style or
      Kerberos password; we will call this a <quote>UNIX password</quote>.
      The second sort is the one-time password which is generated by the
      S/Key <command>key</command> program and accepted by the
      <command>keyinit</command> program and the login prompt; we will
      call this a <quote>one-time password</quote>.  The final sort of
      password is the secret password which you give to the
      <command>key</command> program (and sometimes the
      <command>keyinit</command> program) which it uses to generate
      one-time passwords; we will call it a <quote>secret password</quote>
      or just unqualified <quote>password</quote>.</para>

    <para>The secret password does not have anything to do with your UNIX
      password; they can be the same but this is not reccomended.  S/Key
      secret passwords are not limted to 8 characters like UNIX passwords,
      they can be as long as you like.  Passwords of six or seven word
      long phrases are fairly common.  For the most part, the S/Key system
      operates completely independently of the UNIX password
      system.</para>

    <para>Besides the password, there are two other pieces of data that
      are important to S/Key.  One is what is known as the
      <quote>seed</quote> or <quote>key</quote> and consists of two letters
      and five digits.  The other is what is called the <quote>iteration
      count</quote> and is a number between 1 and 100.  S/Key creates the
      one-time password by concatenating the seed and the secret password,
      then applying the MD4 hash as many times as specified by the
      iteration count and turning the result into six short English words.
      These six English words are your one-time password.  The
      <command>login</command> and <command>su</command> programs keep
      track of the last one-time password used, and the user is
      authenticated if the hash of the user-provided password is equal to
      the previous password.  Because a one-way hash is used it is
      impossible to generate future one-time passwords if a sucessfully
      used password is captured; the interation count is decremented after
      each sucessfull login to keep the user and the login program in
      sync.  When the iteration count gets down to 1 S/Key must be
      reinitialized.</para>

    <para>There are four programs involved in the S/Key system which we
      will discuss below.  The <command>key</command> program accepts an
      iteration count, a seed, and a secret password, and generates a
      one-time password.  The <command>keyinit</command> program is used
      to initialized S/Key, and to change passwords, iteration counts, or
      seeds; it takes either a secret password, or an iteration count,
      seed, and one-time password.  The <command>keyinfo</command> program
      examines the <filename>/etc/skeykeys</filename> file and prints out
      the invoking user's current iteration count and seed.  Finally, the
      <command>login</command> and <command>su</command> programs contain
      the necessary logic to accept S/Key one-time passwords for
      authentication.  The <command>login</command> program is also
      capable of disallowing the use of UNIX passwords on connections
      coming from specified addresses.</para>

    <para>There are four different sorts of operations we will cover.  The
      first is using the <command>keyinit</command> program over a secure
      connection to set up S/Key for the first time, or to change your
      password or seed.  The second operation is using the
      <command>keyinit</command> program over an insecure connection, in
      conjunction with the <command>key</command> program over a secure
      connection, to do the same.  The third is using the
      <command>key</command> program to log in over an insecure
      connection.  The fourth is using the <command>key</command> program
      to generate a number of keys which can be written down or printed
      out to carry with you when going to some location without secure
      connections to anywhere.</para>

    <sect2>
      <title>Secure connection initialization</title>

      <para>To initialize S/Key for the first time, change your password,
	or change your seed while logged in over a secure connection
	(e.g., on the console of a machine or via ssh), use the
	<command>keyinit</command> command without any parameters while
	logged in as yourself:</para>

      <screen>&prompt.user; <userinput>keyinit</userinput>
Adding unfurl:
Reminder - Only use this method if you are directly connected.
If you are using telnet or rlogin exit with no password and use keyinit -s.
Enter secret password: 
Again secret password: 

ID unfurl s/key is 99 to17757
DEFY CLUB PRO NASH LACE SOFT</screen>

      <para>At the <prompt>Enter secret password:</prompt> prompt you
	should enter a password or phrase.  Remember, this is not the
	password that you will use to login with, this is used to generate
	your one-time login keys.  The <quote>ID</quote> line gives the
	parameters of your particular S/Key instance; your login name, the
        iteration count, and seed.  When logging in with S/Key, the system
	will remember these parameters and present them back to you so you
	do not have to remember them.  The last line gives the particular
	one-time password which corresponds to those parameters and your
	secret password; if you were to re-login immediately, this
	one-time password is the one you would use.</para>
    </sect2>

    <sect2>
      <title>Insecure connection initialization</title>
      
      <para>To initialize S/Key or change your secret password over an
	insecure connection, you will need to already have a secure
	connection to some place where you can run the
	<command>key</command> program; this might be in the form of a
	desk accessory on a Macintosh, or a shell prompt on a machine you
	trust.  You will also need to make up an iteration count (100 is
	probably a good value), and you may make up your own seed or use a
	randomly-generated one.  Over on the insecure connection (to the
	machine you are initializing), use the <command>keyinit
	-s</command> command:</para>

      <screen>&prompt.user; <userinput>keyinit -s</userinput>
Updating unfurl:
Old key: to17758
Reminder you need the 6 english words from the key command.
Enter sequence count from 1 to 9999: <userinput>100</userinput>
Enter new key [default to17759]: 
s/key 100 to 17759
s/key access password:</screen>

      <para>To accept the default seed (which the
	<command>keyinit</command> program confusingly calls a
	<literal>key</literal>), press return.  Then before entering an
	access password, move over to your secure connection or S/Key desk
	accessory, and give it the same parameters:</para>

      <screen>&prompt.user; <userinput>key 100 to17759</userinput>
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: <userinput>&lt;secret password&gt;</userinput>
CURE MIKE BANE HIM RACY GORE</screen>

      <para>Now switch back over to the insecure connection, and copy the
	one-time password generated by <command>key</command> over to the
	<command>keyinit</command> program:</para>

      <screen>s/key access password:<userinput>CURE MIKE BANE HIM RACY GORE</userinput>
ID unfurl s/key is 100 to17759
CURE MIKE BANE HIM RACY GORE</screen>

      <para>The rest of the description from the previous section applies
	here as well.</para>
    </sect2>

    <sect2>
      <title>Generating a single one-time password</title>

      <para>Once you've initialized S/Key, when you login you will be 
	presented with a prompt like this:</para>

<screen>&prompt.user; <userinput>telnet example.com</userinput>
Trying 10.0.0.1...
Connected to example.com
Escape character is '^]'.

FreeBSD/i386 (example.com) (ttypa)

login: <userinput>&lt;username&gt;</userinput>
s/key 97 fw13894
Password: </screen>

      <para>As a side note, the S/Key prompt has a useful feature
	(not shown here): if you press return at the password prompt, the
	login program will turn echo on, so you can see what you are
	typing.  This can be extremely useful if you are attempting to
	type in an S/Key by hand, such as from a printout.  Also, if this
	machine were configured to disallow UNIX passwords over a
	connection from my machine, the prompt would have also included
	the annotation <literal>(s/key required)</literal>, indicating
	that only S/Key one-time passwords will be accepted.</para>

      <para>At this point you need to generate your one-time password to
	answer this login prompt.  This must be done on a trusted system
	that you can run the <command>key</command> command on.  (There
	are versions of the <command>key</command> program from DOS,
	Windows and MacOS as well.) The <command>key</command> program
	needs both the iteration count and the seed as command line
	options.  You can cut-and-paste these right from the login prompt
	on the machine that you are logging in to.</para>

      <para>On the trusted system:</para>

      <screen>&prompt.user; <userinput>key 97 fw13894</userinput>
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: 
WELD LIP ACTS ENDS ME HAAG</screen>

      <para>Now that you have your one-time password you can continue
	logging in:</para>

      <screen>login: <userinput>&lt;username&gt;</userinput>
s/key 97 fw13894
Password: <userinput>&lt;return to enable echo&gt;</userinput>
s/key 97 fw13894
Password [echo on]: WELD LIP ACTS ENDS ME HAAG
Last login: Tue Mar 21 11:56:41 from 10.0.0.2 ... </screen>

      <para>This is the easiest mechanism <emphasis>if</emphasis> you have
	a trusted machine.  There is a Java S/Key <command>key</command>
	applet, <ulink
	url="http://www.cs.umd.edu/~harry/jotp/src.html">The Java OTP
	Calculator</ulink>, that you can download and run locally on any
	Java supporting browser.</para>
    </sect2>

    <sect2>
      <title>Generating multiple one-time passwords</title>

      <para>Sometimes you have have to go places where you do not have
	access to a trusted machine or secure connection.  In this case,
	it is possible to use the <command>key</command> command to
	generate a number of one-time passwords before hand to be printed
	out and taken with you.  For example:</para>

      <screen>&prompt.user; <userinput>key -n 5 30 zz99999</userinput>
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password: <userinput>&lt;secret password&gt;</userinput>
26: SODA RUDE LEA LIND BUDD SILT 
27: JILT SPY DUTY GLOW COWL ROT  
28: THEM OW COLA RUNT BONG SCOT  
29: COT MASH BARR BRIM NAN FLAG  
30: CAN KNEE CAST NAME FOLK BILK</screen>

      <para>The <option>-n 5</option> requests five keys in sequence, the
	<option>30</option> specifies what the last iteration number
	should be.  Note that these are printed out in
	<emphasis>reverse</emphasis> order of eventual use.  If you are
	really paranoid, you might want to write the results down by hand;
	otherwise you can cut-and-paste into <command>lpr</command>.  Note
	that each line shows both the iteration count and the one-time
	password; you may still find it handy to scratch off passwords as
	you use them.</para>
    </sect2>

    <sect2>
      <title>Restricting use of UNIX passwords</title>

      <para>Restrictions can be placed on the use of UNIX passwords based
	on the host name, user name, terminal port, or IP address of a
	login session.  These restrictions can be found in the
	configuration file <filename>/etc/skey.access</filename>.  The
	&man.skey.access.5; manual page has more info on the complete
	format of the file and also details some security cautions to be
	aware of before depending on this file for security.</para>

      <para>If there is no <filename>/etc/skey.access</filename> file
	(this is the FreeBSD default), then all users will be allowed to
	use UNIX passwords.  If the file exists, however, then all users
	will be required to use S/Key unless explicitly permitted to do
	otherwise by configuration statements in the
	<filename>skey.access</filename> file.  In all cases, UNIX
	passwords are permitted on the console.</para>

      <para>Here is a sample configuration file which illustrates the
	three most common sorts of configuration statements:</para>

      <programlisting>
permit internet 192.168.0.0 255.255.0.0
permit user fnord
permit port ttyd0</programlisting>

      <para>The first line (<literal>permit internet</literal>) allows
	users whose IP source address (which is vulnerable to spoofing)
	matches the specified value and mask, to use UNIX passwords.  This
	should not be considered a security mechanism, but rather, a means
	to remind authorized users that they are using an insecure network
	and need to use S/Key for authentication.</para>

      <para>The second line (<literal>permit user</literal>) allows the
	specified username, in this case <literal>fnord</literal>, to use
	UNIX passwords at any time.  Generally speaking, this should only
	be used for people who are either unable to use the
	<command>key</command> program, like those with dumb terminals, or
	those who are uneducable.</para>

      <para>The third line (<literal>permit port</literal>) allows all
	users logging in on the specified terminal line to use UNIX
	passwords; this would be used for dial-ups.</para>
    </sect2>
  </sect1>

  <sect1 id="kerberos">
    <title>Kerberos</title>

    <para><emphasis>Contributed by &a.markm; (based on contribution by
	&a.md;).</emphasis></para>
    
    <para>Kerberos is a network add-on system/protocol that allows users to
      authenticate themselves through the services of a secure server.
      Services such as remote login, remote copy, secure inter-system file
      copying and other high-risk tasks are made considerably safer and more
      controllable.</para>

    <para>The following instructions can be used as a guide on how to set up
      Kerberos as distributed for FreeBSD.  However, you should refer to the
      relevant manual pages for a complete description.</para>

    <para>In FreeBSD, the Kerberos is not that from the original 4.4BSD-Lite,
      distribution, but eBones, which had been previously ported to FreeBSD
      1.1.5.1, and was sourced from outside the USA/Canada, and is thus
      available to system owners outside those countries.</para>

    <para>For those needing to get a legal foreign distribution of this
      software, please <emphasis>do not</emphasis> get it from a USA or Canada
      site.  You will get that site in <emphasis>big</emphasis> trouble! A
      legal copy of this is available from <hostid
	role="fqdn">ftp.internat.FreeBSD.org</hostid>, which is in South
      Africa and an official FreeBSD mirror site.</para>
    
    <sect2>
      <title>Creating the initial database</title>
      
      <para>This is done on the Kerberos server only.  First make sure that
	you do not have any old Kerberos databases around.  You should change
	to the directory <filename>/etc/kerberosIV</filename> and check that
	only the following files are present:</para>
	  
      <screen>&prompt.root; <userinput>cd /etc/kerberosIV</userinput>
&prompt.root; <userinput>ls</userinput>
README		krb.conf        krb.realms</screen>
	  
      <para>If any additional files (such as <filename>principal.*</filename>
	or <filename>master_key</filename>) exist, then use the
	<command>kdb_destroy</command> command to destroy the old Kerberos
	database, of if Kerberos is not running, simply delete the extra
	files.</para>
	  
      <para>You should now edit the <filename>krb.conf</filename> and
	<filename>krb.realms</filename> files to define your Kerberos realm.
	In this case the realm will be <filename>GRONDAR.ZA</filename> and the
	server is <filename>grunt.grondar.za</filename>.  We edit or create
	the <filename>krb.conf</filename> file:</para>
	  
      <screen>&prompt.root; <userinput>cat krb.conf</userinput>
GRONDAR.ZA
GRONDAR.ZA grunt.grondar.za admin server
CS.BERKELEY.EDU okeeffe.berkeley.edu
ATHENA.MIT.EDU kerberos.mit.edu
ATHENA.MIT.EDU kerberos-1.mit.edu
ATHENA.MIT.EDU kerberos-2.mit.edu
ATHENA.MIT.EDU kerberos-3.mit.edu
LCS.MIT.EDU kerberos.lcs.mit.edu
TELECOM.MIT.EDU bitsy.mit.edu
ARC.NASA.GOV trident.arc.nasa.gov</screen>
	  
      <para>In this case, the other realms do not need to be there.  They are
	here as an example of how a machine may be made aware of multiple
	realms.  You may wish to not include them for simplicity.</para>
	  
      <para>The first line names the realm in which this system works.  The
	other lines contain realm/host entries.  The first item on a line is a
	realm, and the second is a host in that realm that is acting as a
	<quote>key distribution centre</quote>.  The words <literal>admin
	  server</literal> following a hosts name means that host also
	provides an administrative database server.  For further explanation
	of these terms, please consult the Kerberos man pages.</para>
	  
      <para>Now we have to add <hostid role="fqdn">grunt.grondar.za</hostid>
	to the <filename>GRONDAR.ZA</filename> realm and also add an entry to
	put all hosts in the <hostid role="domainname">.grondar.za</hostid>
	domain in the <filename>GRONDAR.ZA</filename> realm.  The
	<filename>krb.realms</filename> file would be updated as
	follows:</para>
	  
      <screen>&prompt.root; <userinput>cat krb.realms</userinput>
grunt.grondar.za GRONDAR.ZA
.grondar.za GRONDAR.ZA
.berkeley.edu CS.BERKELEY.EDU
.MIT.EDU ATHENA.MIT.EDU
.mit.edu ATHENA.MIT.EDU</screen>
	  
      <para>Again, the other realms do not need to be there.  They are here as
	an example of how a machine may be made aware of multiple realms.  You
	may wish to remove them to simplify things.</para>
	  
      <para>The first line puts the <emphasis>specific</emphasis> system into
	the named realm.  The rest of the lines show how to default systems of
	a particular subdomain to a named realm.</para>
	  
      <para>Now we are ready to create the database.  This only needs to run
	on the Kerberos server (or Key Distribution Centre).  Issue the
	<command>kdb_init</command> command to do this:</para>
	  
      <screen>&prompt.root; <userinput>kdb_init</userinput>
<prompt>Realm name [default  ATHENA.MIT.EDU ]:</prompt> <userinput>GRONDAR.ZA</userinput>
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
		
<prompt>Enter Kerberos master key:</prompt> </screen>
	  
      <para>Now we have to save the key so that servers on the local machine
	can pick it up.  Use the <command>kstash</command> command to do
	this.</para>
	  
      <screen>&prompt.root; <userinput>kstash</userinput>
	      
<prompt>Enter Kerberos master key:</prompt>

Current Kerberos master key version is 1.

Master key entered. BEWARE!</screen>
	  
      <para>This saves the encrypted master password in
	<filename>/etc/kerberosIV/master_key</filename>.</para>
    </sect2>
    
    <sect2>
      <title>Making it all run</title>
	  
      <para>Two principals need to be added to the database for
	<emphasis>each</emphasis> system that will be secured with Kerberos.
	Their names are <literal>kpasswd</literal> and <literal>rcmd</literal>
	These two principals are made for each system, with the instance being
	the name of the individual system.</para>
	  
      <para>These daemons, <command>kpasswd</command> and
	<command>rcmd</command> allow other systems to change Kerberos
	passwords and run commands like <command>rcp</command>,
	<command>rlogin</command> and <command>rsh</command>.</para>
	  
      <para>Now let's add these entries:</para>
	    
      <screen>&prompt.root; <userinput>kdb_edit</userinput>
Opening database...

<prompt>Enter Kerberos master key:</prompt>

Current Kerberos master key version is 1.

Master key entered.  BEWARE!
Previous or default values are in [brackets] ,
enter return to leave the same, or new value.

<prompt>Principal name:</prompt> <userinput>passwd</userinput>
<prompt>Instance:</prompt> <userinput>grunt</userinput>

&lt;Not found&gt;, <prompt>Create [y] ?</prompt> <userinput>y</userinput>

Principal: passwd, Instance: grunt, kdc_key_ver: 1
<prompt>New Password:</prompt>                    &lt;---- enter RANDOM here
Verifying password

<prompt>New Password:</prompt> &lt;---- enter RANDOM here

<prompt>Random password [y] ?</prompt> <userinput>y</userinput>

Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt>
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt> <userinput>rcmd</userinput>
<prompt>Instance:</prompt> <userinput>grunt</userinput>

&lt;Not found&gt;, <prompt>Create [y] ?</prompt>

Principal: rcmd, Instance: grunt, kdc_key_ver: 1
<prompt>New Password:</prompt>		&lt;---- enter RANDOM here
Verifying password

<prompt>New Password:</prompt>           &lt;---- enter RANDOM here

<prompt>Random password [y] ?</prompt>

Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt>
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt>         &lt;---- null entry here will cause an exit</screen>
    </sect2>

    <sect2>
      <title>Creating the server file</title>
      
      <para>We now have to extract all the instances which define the services
	on each machine.  For this we use the <command>ext_srvtab</command>
	command.  This will create a file which must be copied or moved
	<emphasis>by secure means</emphasis> to each Kerberos client's
	/etc/kerberosIV directory.  This file must be present on each server
	and client, and is crucial to the operation of Kerberos.</para>
	  
	  
      <screen>&prompt.root; <userinput>ext_srvtab grunt</userinput>
<prompt>Enter Kerberos master key:</prompt>
		
Current Kerberos master key version is 1.

Master key entered. BEWARE!
Generating 'grunt-new-srvtab'....</screen>
	  
      <para>Now, this command only generates a temporary file which must be
	renamed to <filename>srvtab</filename> so that all the server can pick
	it up.  Use the <command>mv</command> command to move it into place on
	the original system:</para>
	  
      <screen>&prompt.root; <userinput>mv grunt-new-srvtab srvtab</userinput></screen>
	  
      <para>If the file is for a client system, and the network is not deemed
	safe, then copy the
	<filename><replaceable>client</replaceable>-new-srvtab</filename> to
	removable media and transport it by secure physical means.  Be sure to
	rename it to <filename>srvtab</filename> in the client's
	<filename>/etc/kerberosIV</filename> directory, and make sure it is
	mode 600:</para>
	  
      <screen>&prompt.root; <userinput>mv grumble-new-srvtab srvtab</userinput>
&prompt.root; <userinput>chmod 600 srvtab</userinput></screen>
    </sect2>
    
    <sect2>
      <title>Populating the database</title>
      
      <para>We now have to add some user entries into the database.  First
	let's create an entry for the user <username>jane</username>.  Use the
	<command>kdb_edit</command> command to do this:</para>
	  
      <screen>&prompt.root; <userinput>kdb_edit</userinput>
Opening database...

<prompt>Enter Kerberos master key:</prompt>

Current Kerberos master key version is 1.

Master key entered.  BEWARE!
Previous or default values are in [brackets] ,
enter return to leave the same, or new value.

<prompt>Principal name:</prompt> <userinput>jane</userinput>
<prompt>Instance:</prompt>

&lt;Not found&gt;, <prompt>Create [y] ?</prompt> <userinput>y</userinput>

Principal: jane, Instance: , kdc_key_ver: 1
<prompt>New Password:</prompt>                &lt;---- enter a secure password here
Verifying password

<prompt>New Password:</prompt>                &lt;---- re-enter the password here
Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt>
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt>		   &lt;---- null entry here will cause an exit</screen>
    </sect2>

    <sect2>
      <title>Testing it all out</title>
      
      <para>First we have to start the Kerberos daemons.  NOTE that if you
	have correctly edited your <filename>/etc/rc.conf</filename> then this
	will happen automatically when you reboot.  This is only necessary on
	the Kerberos server.  Kerberos clients will automagically get what
	they need from the <filename>/etc/kerberosIV</filename>
	directory.</para>
	  
      <screen>&prompt.root; <userinput>kerberos &amp;</userinput>
Kerberos server starting
Sleep forever on error
Log file is /var/log/kerberos.log
Current Kerberos master key version is 1.

Master key entered. BEWARE!

Current Kerberos master key version is 1
Local realm: GRONDAR.ZA
&prompt.root; <userinput>kadmind -n &amp;</userinput>
KADM Server KADM0.0A initializing
Please do not use 'kill -9' to kill this job, use a
regular kill instead

Current Kerberos master key version is 1.

Master key entered.  BEWARE!</screen>
	  
      <para>Now we can try using the <command>kinit</command> command to get a
	ticket for the id <username>jane</username> that we created
	above:</para>
	  
      <screen>&prompt.user; <userinput>kinit jane</userinput>
MIT Project Athena (grunt.grondar.za)
Kerberos Initialization for "jane"
<prompt>Password:</prompt> </screen>
	  
      <para>Try listing the tokens using <command>klist</command> to see if we
	really have them:</para>
	  
      <screen>&prompt.user; <userinput>klist</userinput>
Ticket file:    /tmp/tkt245
Principal:      jane@GRONDAR.ZA

  Issued           Expires          Principal
Apr 30 11:23:22  Apr 30 19:23:22  krbtgt.GRONDAR.ZA@GRONDAR.ZA</screen>
	  
      <para>Now try changing the password using <command>passwd</command> to
	check if the kpasswd daemon can get authorization to the Kerberos
	database:</para>
	  
      <screen>&prompt.user; <userinput>passwd</userinput>
realm GRONDAR.ZA
<prompt>Old password for jane:</prompt>
<prompt>New Password for jane:</prompt>
Verifying password
<prompt>New Password for jane:</prompt>
Password changed.</screen>
    </sect2>

    <sect2>
      <title>Adding <command>su</command> privileges</title>
      
      <para>Kerberos allows us to give <emphasis>each</emphasis> user who
	needs root privileges their own <emphasis>separate</emphasis>
	<command>su</command>password.  We could now add an id which is
	authorized to <command>su</command> to <username>root</username>.
	This is controlled by having an instance of <username>root</username>
	associated with a principal.  Using <command>kdb_edit</command> we can
	create the entry <literal>jane.root</literal> in the Kerberos
	database:</para>
	  
      <screen>&prompt.root; <userinput>kdb_edit</userinput>
Opening database...

<prompt>Enter Kerberos master key:</prompt>

Current Kerberos master key version is 1.

Master key entered.  BEWARE!
Previous or default values are in [brackets] ,
enter return to leave the same, or new value.

<prompt>Principal name:</prompt> <userinput>jane</userinput>
<prompt>Instance:</prompt> <userinput>root</userinput>

&lt;Not found&gt;, Create [y] ? y

Principal: jane, Instance: root, kdc_key_ver: 1
<prompt>New Password:</prompt>                    &lt;---- enter a SECURE password here
Verifying password

<prompt>New Password:</prompt>    	 	 &lt;---- re-enter the password here

Principal's new key version = 1
<prompt>Expiration date (enter yyyy-mm-dd) [ 2000-01-01 ] ?</prompt>
<prompt>Max ticket lifetime (*5 minutes) [ 255 ] ?</prompt> <userinput>12</userinput> &lt;--- Keep this short!
<prompt>Attributes [ 0 ] ?</prompt>
Edit O.K.
<prompt>Principal name:</prompt>		         &lt;---- null entry here will cause an exit</screen>
	  
      <para>Now try getting tokens for it to make sure it works:</para>
      
      <screen>&prompt.root; <userinput>kinit jane.root</userinput>
MIT Project Athena (grunt.grondar.za)
Kerberos Initialization for "jane.root"
<prompt>Password:</prompt></screen>
	  
      <para>Now we need to add the user to root's <filename>.klogin</filename>
	file:</para>
	  
      <screen>&prompt.root; <userinput>cat /root/.klogin</userinput>
jane.root@GRONDAR.ZA</screen>
	  
      <para>Now try doing the <command>su</command>:</para>
	  
      <screen>&prompt.user; <prompt>su</prompt>
<prompt>Password:</prompt></screen>
	  
      <para>and take a look at what tokens we have:</para>
	  
      <screen>&prompt.root; klist
Ticket file:	/tmp/tkt_root_245
Principal:      jane.root@GRONDAR.ZA

  Issued           Expires          Principal
May  2 20:43:12  May  3 04:43:12  krbtgt.GRONDAR.ZA@GRONDAR.ZA</screen>
    </sect2>

    <sect2>
      <title>Using other commands</title>
      
      <para>In an earlier example, we created a principal called
	<literal>jane</literal> with an instance <literal>root</literal>.
	This was based on a user with the same name as the principal, and this
	is a Kerberos default; that a
	<literal>&lt;principal&gt;.&lt;instance&gt;</literal> of the form
	<literal>&lt;username&gt;.</literal><literal>root</literal> will allow
	that <literal>&lt;username&gt;</literal> to <command>su</command> to
	root if the necessary entries are in the <filename>.klogin</filename>
	file in <username>root</username>'s home directory:</para>
	  
      <screen>&prompt.root; <userinput>cat /root/.klogin</userinput>
jane.root@GRONDAR.ZA</screen>
      
      <para>Likewise, if a user has in their own home directory lines of the
	form:</para>
      
      <screen>&prompt.user; <userinput>cat ~/.klogin</userinput>
jane@GRONDAR.ZA
jack@GRONDAR.ZA</screen>
	  
      <para>This allows anyone in the <filename>GRONDAR.ZA</filename> realm
	who has authenticated themselves to <username>jane</username> or
	<username>jack</username> (via <command>kinit</command>, see above)
	access to <command>rlogin</command> to <username>jane</username>'s
	account or files on this system (<hostid>grunt</hostid>) via
	<command>rlogin</command>, <command>rsh</command> or
	<command>rcp</command>.</para>
	  
      <para>For example, Jane now logs into another system, using
	Kerberos:</para>
	  
	    <screen>&prompt.user; <userinput>kinit</userinput>
MIT Project Athena (grunt.grondar.za)
<prompt>Password:</prompt>
%prompt.user; <userinput>rlogin grunt</userinput>
Last login: Mon May  1 21:14:47 from grumble
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
        The Regents of the University of California.   All rights reserved.

FreeBSD BUILT-19950429 (GR386) #0: Sat Apr 29 17:50:09 SAT 1995</screen>
	  
      <para>Or Jack logs into Jane's account on the same machine (Jane having
	set up the <filename>.klogin</filename> file as above, and the person
	in charge of Kerberos having set up principal
	<emphasis>jack</emphasis> with a null instance:</para>
	  
      <screen>&prompt.user; <userinput>kinit</userinput>
&prompt.user; <userinput>rlogin grunt -l jane</userinput>
MIT Project Athena (grunt.grondar.za)
<prompt>Password:</prompt>
Last login: Mon May  1 21:16:55 from grumble
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
        The Regents of the University of California.   All rights reserved.
FreeBSD BUILT-19950429 (GR386) #0: Sat Apr 29 17:50:09 SAT 1995</screen>
    </sect2>
  </sect1>
  
  <sect1 id="firewalls">
    <title>Firewalls</title>

    <para><emphasis>Contributed by &a.gpalmer; and &a.alex;.</emphasis></para>

    <para>Firewalls are an area of increasing interest for people who are
      connected to the Internet, and are even finding applications on private
      networks to provide enhanced security.  This section will hopefully
      explain what firewalls are, how to use them, and how to use the
      facilities provided in the FreeBSD kernel to implement them.</para>

    <note>
      <para>People often think that having a firewall between your
	internal network and the <quote>Big Bad Internet</quote> will solve all
	your security problems.  It may help, but a poorly setup firewall
	system is more of a security risk than not having one at all.  A
	firewall can add another layer of security to your systems, but it
	cannot stop a really determined cracker from penetrating your internal
	network.  If you let internal security lapse because you believe your
	firewall to be impenetrable, you have just made the crackers job that
	much easier.</para>
    </note>

    <sect2>
      <title>What is a firewall?</title>
      
      <para>There are currently two distinct types of firewalls in common use
	on the Internet today.  The first type is more properly called a
	<emphasis>packet filtering router</emphasis>, where the kernel on a
	multi-homed machine chooses whether to forward or block packets based
	on a set of rules.  The second type, known as a <emphasis>proxy
	  server</emphasis>, relies on daemons to provide authentication and to
	forward packets, possibly on a multi-homed machine which has kernel
	packet forwarding disabled.</para>
	  
      <para>Sometimes sites combine the two types of firewalls, so that only a
	certain machine (known as a <emphasis>bastion host</emphasis>) is
	allowed to send packets through a packet filtering router onto an
	internal network.  Proxy services are run on the bastion host, which
	are generally more secure than normal authentication
	mechanisms.</para>
	  
      <para>FreeBSD comes with a kernel packet filter (known as
	<application>IPFW</application>), which is what the rest of this
	section will concentrate on.  Proxy servers can be built on FreeBSD
	from third party software, but there is such a variety of proxy
	servers available that it would be impossible to cover them in this
	document.</para>
	  
      <sect3 id="firewalls-packet-filters">
	<title>Packet filtering routers</title>

	<para>A router is a machine which forwards packets between two or more
	  networks.  A packet filtering router has an extra piece of code in
	  its kernel which compares each packet to a list of rules before
	  deciding if it should be forwarded or not.  Most modern IP routing
	  software has packet filtering code within it that defaults to
	  forwarding all packets.  To enable the filters, you need to define a
	  set of rules for the filtering code so it can decide if the
	  packet should be allowed to pass or not.</para>
	    
	<para>To decide whether a packet should be passed on, the code looks
	  through its set of rules for a rule which matches the contents of
	  this packets headers.  Once a match is found, the rule action is
	  obeyed.  The rule action could be to drop the packet, to forward the
	  packet, or even to send an ICMP message back to the originator.
	  Only the first match counts, as the rules are searched in order.
	  Hence, the list of rules can be referred to as a <quote>rule
	  chain</quote>.</para>
	    
	<para>The packet matching criteria varies depending on the software
	  used, but typically you can specify rules which depend on the source
	  IP address of the packet, the destination IP address, the source
	  port number, the destination port number (for protocols which
	  support ports), or even the packet type (UDP, TCP, ICMP,
	  etc).</para>
      </sect3>
	  
      <sect3 id="firewalls-proxy-servers">
	<title>Proxy servers</title>
	    
	<para>Proxy servers are machines which have had the normal system
	  daemons (telnetd, ftpd, etc) replaced with special servers. These
	  servers are called <emphasis>proxy servers</emphasis> as they
	  normally only allow onward connections to be made.  This enables you
	  to run (for example) a proxy telnet server on your firewall host,
	  and people can telnet in to your firewall from the outside, go
	  through some authentication mechanism, and then gain access to the
	  internal network (alternatively, proxy servers can be used for
	  signals coming from the internal network and heading out).</para>
	    
	<para>Proxy servers are normally more secure than normal servers, and
	  often have a wider variety of authentication mechanisms available,
	  including <quote>one-shot</quote> password systems so that even if
	  someone manages to discover what password you used, they will not be
	  able to use it to gain access to your systems as the password
	  instantly expires.  As they do not actually give users access to the
	  host machine, it becomes a lot more difficult for someone to install
	  backdoors around your security system.</para>
	    
	<para>Proxy servers often have ways of restricting access further, so
	  that only certain hosts can gain access to the servers, and often
	  they can be set up so that you can limit which users can talk to
	  which destination machine.  Again, what facilities are available
	  depends largely on what proxy software you choose.</para>
      </sect3>
    </sect2>

    <sect2>
      <title>What does IPFW allow me to do?</title>
      
      <para><application>IPFW</application>, the software supplied with
	FreeBSD, is a packet filtering and accounting system which resides in
	the kernel, and has a user-land control utility,
	    &man.ipfw.8;.  Together, they allow you to define and query the
	rules currently used by the kernel in its routing decisions.</para>
	  
      <para>There are two related parts to <application>IPFW</application>.
	The firewall section allows you to perform packet filtering.  There is
	also an IP accounting section which allows you to track usage of your
	router, based on similar rules to the firewall section.  This allows
	you to see (for example) how much traffic your router is getting from
	a certain machine, or how much WWW (World Wide Web) traffic it is
	forwarding.</para>
	  
      <para>As a result of the way that <application>IPFW</application> is
	designed, you can use <application>IPFW</application> on non-router
	machines to perform packet filtering on incoming and outgoing
	connections.  This is a special case of the more general use of
	<application>IPFW</application>, and the same commands and techniques
	should be used in this situation.</para>
    </sect2>

    <sect2>
      <title>Enabling IPFW on FreeBSD</title>
      
      <para>As the main part of the <application>IPFW</application> system
	lives in the kernel, you will need to add one or more options to your
	kernel configuration file, depending on what facilities you want, and
	recompile your kernel.  See <link linkend="kernelconfig">reconfiguring
	  the kernel</link> for more details on how to recompile your
	kernel.</para>
      
      <para>There are currently three kernel configuration options relevant to
	IPFW:</para>
	  
      <variablelist>
	<varlistentry>
	  <term><literal>options IPFIREWALL</literal></term>

	  <listitem>
	    <para>Compiles into the kernel the code for packet
	      filtering.</para>
	  </listitem>
	</varlistentry>
	      
	<varlistentry>
	  <term><literal>options IPFIREWALL_VERBOSE</literal></term>
		
	  <listitem>
	    <para>Enables code to allow logging of packets through
		&man.syslogd.8;.  Without this option, even if you specify
	      that packets should be logged in the filter rules, nothing will
	      happen.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term><literal>options IPFIREWALL_VERBOSE_LIMIT=10</literal></term>
		
	  <listitem>
	    <para>Limits the number of packets logged through
		&man.syslogd.8; on a per entry basis.  You may wish to use
	      this option in hostile environments in which you want to log
	      firewall activity, but do not want to be open to a denial of
	      service attack via syslog flooding.</para>

	    <para>When a chain entry reaches the packet limit specified,
	      logging is turned off for that particular entry.  To resume
	      logging, you will need to reset the associated counter using the
		&man.ipfw.8; utility:</para>
	    
	    <screen>&prompt.root; <userinput>ipfw zero 4500</userinput></screen>
	    <para>Where 4500 is the chain entry you wish to continue
	      logging.</para>
	  </listitem>
	</varlistentry>
      </variablelist>
      
      <para>Previous versions of FreeBSD contained an
	<literal>IPFIREWALL_ACCT</literal>  option.  This is now obsolete as
	the firewall code automatically  includes accounting
	facilities.</para>
    </sect2>

    <sect2>
      <title>Configuring IPFW</title>
      
      <para>The configuration of the <application>IPFW</application> software
	is done through the &man.ipfw.8; utility.  The syntax for this
	command looks quite complicated, but it is relatively simple once you
	understand its structure.</para>

      <para>There are currently four different command categories used by the
	utility: addition/deletion, listing, flushing, and clearing.
	Addition/deletion is used to build the rules that control how packets
	are accepted, rejected, and logged.  Listing is used to examine the
	contents of your rule set (otherwise known as the chain) and packet
	counters (accounting).  Flushing is used to remove all entries from
	the chain.  Clearing is used to zero out one or more accounting
	entries.</para>
	  
      <sect3>
	<title>Altering the IPFW rules</title>

	<para>The syntax for this form of the command is:
	  <cmdsynopsis>
	    <command>ipfw</command>
	    <arg>-N</arg>
	    <arg choice="plain">command</arg>
	    <arg>index</arg>
	    <arg choice="plain">action</arg>
	    <arg>log</arg>
	    <arg choice="plain">protocol</arg>
	    <arg choice="plain">addresses</arg>
	    <arg>options</arg>
	  </cmdsynopsis></para>

	<para>There is one valid flag when using this form of the
	  command:</para>

	<variablelist>
	  <varlistentry>
	    <term>-N</term>

	    <listitem>
	      <para>Resolve addresses and service names in output.</para>
	    </listitem>
	  </varlistentry>
	</variablelist>

	<para>The <emphasis>command</emphasis> given can be shortened to the
	  shortest unique form.  The valid <emphasis>commands</emphasis>
	  are:</para>
	    
	<variablelist>
	  <varlistentry>
	    <term>add</term>

	    <listitem>
	      <para>Add an entry to the firewall/accounting rule list</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>delete</term>
	    
	    <listitem>
	      <para>Delete an entry from the firewall/accounting rule
		list</para>
	    </listitem>
	  </varlistentry>
	</variablelist>

	<para>Previous versions of <application>IPFW</application> used
	  separate firewall and accounting entries.  The present version
	  provides packet accounting with each firewall entry.</para>
	    
	<para>If an <emphasis>index</emphasis> value is supplied, it used to
	  place the entry at a specific point in the chain. Otherwise, the
	  entry is placed at the end of the chain at an index 100 greater than
	  the last chain entry (this does not include the default policy, rule
	  65535, deny).</para>
	    
	<para>The <literal>log</literal> option causes matching rules to be
	  output to the system console if the kernel was compiled with
	  <literal>IPFIREWALL_VERBOSE</literal>.</para>
	    
	<para>Valid <emphasis>actions</emphasis> are:</para>
	    
	<variablelist>
	  <varlistentry>
	    <term>reject</term>

	    <listitem>
	      <para>Drop the packet, and send an ICMP host or port unreachable
		(as appropriate) packet to the source.</para>
	    </listitem>
	  </varlistentry>
		
	  <varlistentry>
	    <term>allow</term>
	    
	    <listitem>
	      <para>Pass the packet on as normal.  (aliases:
		<literal>pass</literal> and
		<literal>accept</literal>)</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>deny</term>
	    
	    <listitem>
	      <para>Drop the packet.  The source is not notified via an
		ICMP message (thus it appears that the packet never
		arrived at the destination).</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>count</term>
	    
	    <listitem>
	      <para>Update packet counters but do not allow/deny the packet
		based on this rule.  The search continues with the next chain
		entry.</para>
	    </listitem>
	  </varlistentry>
	</variablelist>

	<para>Each <emphasis>action</emphasis> will be recognized by the
	  shortest unambiguous prefix.</para>
	    
	<para>The <emphasis>protocols</emphasis> which can be specified
	  are:</para>
	    
	<variablelist>
	  <varlistentry>
	    <term>all</term>

	    <listitem>
	      <para>Matches any IP packet</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>icmp</term>
	    
	    <listitem>
	      <para>Matches ICMP packets</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>tcp</term>
	    
	    <listitem>
	      <para>Matches TCP packets</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>udp</term>
	    
	    <listitem>
	      <para>Matches UDP packets</para>
	    </listitem>
	  </varlistentry>
	</variablelist>

	<para>The <emphasis>address</emphasis> specification is:</para>

	<cmdsynopsis>
	  <arg choice="plain">from</arg>
	  <arg choice="plain"><replaceable>address/mask</replaceable></arg><arg><replaceable>port</replaceable></arg>
	  <arg choice="plain">to</arg>
	  <arg choice="plain"><replaceable>address/mask</replaceable></arg><arg><replaceable>port</replaceable></arg>
	  <arg>via <replaceable>interface</replaceable></arg>
	</cmdsynopsis>
	    
	<para>You can only specify <replaceable>port</replaceable> in
	  conjunction with <emphasis>protocols</emphasis> which support ports
	  (UDP and TCP).</para>
	    
	<para>The <option>via</option> is optional and may specify the IP
	  address or domain name of a local IP interface, or an interface name
	  (e.g.  <devicename>ed0</devicename>) to match only packets coming
	  through this interface.  Interface unit numbers can be specified
	  with an optional wildcard.  For example, <literal>ppp*</literal>
	  would match all kernel PPP interfaces.</para>
	    
	<para>The syntax used to specify an
	  <replaceable>address/mask</replaceable> is:
	  
	  <screen><replaceable>address</replaceable></screen>
	      
	  or
	      
	  <screen><replaceable>address</replaceable>/<replaceable>mask-bits</replaceable></screen>
	      
	  or
	      
	  <screen><replaceable>address</replaceable>:<replaceable>mask-pattern</replaceable></screen>
	</para>

	<para>A valid hostname may be specified in place of the IP address.
	  <option><replaceable>mask-bits</replaceable></option> is a decimal
	  number representing how many bits in the address mask should be set.
	  e.g.  specifying <literal>192.216.222.1/24</literal> will create a
	  mask which will allow any address in a class C subnet (in this case,
	  192.216.222) to be matched.
	  <option><replaceable>mask-pattern</replaceable></option> is an IP
	  address which will be logically AND'ed with the address given. The
	  keyword <literal>any</literal> may be used to specify <quote>any IP
	  address</quote>.</para>
	    
	<para>The port numbers to be blocked are specified as:
	  
	  <cmdsynopsis>
	    <arg choice="plain"><replaceable>port</replaceable><arg>,<replaceable>port</replaceable><arg>,<replaceable>port</replaceable><arg>&hellip;</arg></arg></arg></arg>
	  </cmdsynopsis>

	  to specify either a single port or a list of ports, or
	  
	  <cmdsynopsis>
	    <arg choice="plain"><replaceable>port</replaceable>-<replaceable>port</replaceable></arg>
	  </cmdsynopsis>

	  to specify a range of ports.  You may also combine a single range
	  with a list, but the range must always be specified first.</para>
	    
	<para>The <emphasis>options</emphasis> available are:</para>

	<variablelist>
	  <varlistentry>
	    <term>frag</term>

	    <listitem>
	      <para>Matches if the packet is not the first fragment of the
		datagram.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>in</term>
	    
	    <listitem>
	      <para>Matches if the packet is on the way in.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>out</term>
	    
	    <listitem>
	      <para>Matches if the packet is on the way out.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>ipoptions <replaceable>spec</replaceable></term>
	    
	    <listitem>
	      <para>Matches if the IP header contains the comma separated list
		of options specified in <replaceable>spec</replaceable>.  The
		supported list of IP options are: <literal>ssrr</literal>
		(strict source route), <literal>lsrr</literal> (loose source
		route), <literal>rr</literal> (record packet route), and
		<literal>ts</literal> (timestamp).  The absence of a
		particular option may be denoted with a leading
		<literal>!</literal>.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>established</term>
	    
	    <listitem>
	      <para>Matches if the packet is part of an already established
		TCP connection (i.e. it has the RST or ACK bits set).  You can
		optimize the performance of the firewall by placing
		<emphasis>established</emphasis> rules early in the
		chain.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>setup</term>
	    
	    <listitem>
	      <para>Matches if the packet is an attempt to establish a TCP
		connection (the SYN bit set is set but the ACK bit is
		not).</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>tcpflags <replaceable>flags</replaceable></term>
	    
	    <listitem>
	      <para>Matches if the TCP header contains the comma separated
		list of <replaceable>flags</replaceable>.  The supported flags
		are <literal>fin</literal>, <literal>syn</literal>,
		<literal>rst</literal>, <literal>psh</literal>,
		<literal>ack</literal>, and <literal>urg</literal>.  The
		absence of a particular flag may be indicated by a leading
		<literal>!</literal>.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>icmptypes <replaceable>types</replaceable></term>
	    
	    <listitem>
	      <para>Matches if the ICMP type is present in the list
		<replaceable>types</replaceable>.  The list may be specified
		as any combination of ranges and/or individual types separated
		by commas.  Commonly used ICMP types are: <literal>0</literal>
		echo reply (ping reply), <literal>3</literal> destination
		unreachable, <literal>5</literal> redirect,
		<literal>8</literal> echo request (ping request), and
		<literal>11</literal> time exceeded (used to indicate TTL
		expiration as with &man.traceroute.8;).</para>
	    </listitem>
	  </varlistentry>
	</variablelist>
      </sect3>
      
      <sect3>
	<title>Listing the IPFW rules</title>

	<para>The syntax for this form of the command is:
	  <cmdsynopsis>
	    <command>ipfw</command>
	    <arg>-a</arg>
	    <arg>-t</arg>
	    <arg>-N</arg>
	    <arg choice="plain">l</arg>
	  </cmdsynopsis></para>

	<para>There are three valid flags when using this form of the
	  command:</para>
	    
	<variablelist>
	  <varlistentry>
	    <term>-a</term>

	    <listitem>
	      <para>While listing, show counter values.  This option is the
		only way to see accounting counters.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>-t</term>
	    
	    <listitem>
	      <para>Display the last match times for each chain entry. The
		time listing is incompatible with the input syntax used by the
		  &man.ipfw.8; utility.</para>
	    </listitem>
	  </varlistentry>
	  
	  <varlistentry>
	    <term>-N</term>
	    
	    <listitem>
	      <para>Attempt to resolve given addresses and service
		names.</para>
	    </listitem>
	  </varlistentry>
	</variablelist>
      </sect3>
      
      <sect3>
	<title>Flushing the IPFW rules</title>

	<para>The syntax for flushing the chain is:
	  <cmdsynopsis>
	    <command>ipfw</command>
	    <arg choice="plain">flush</arg>
	  </cmdsynopsis></para>

	<para>This causes all entries in the firewall chain to be removed
	  except the fixed default policy enforced by the kernel (index
	  65535).  Use caution when flushing rules, the default deny policy
	  will leave your system cut off from the network until allow entries
	  are added to the chain.</para>
      </sect3>
      
      <sect3>
	<title>Clearing the IPFW packet counters</title>

	<para>The syntax for clearing one or more packet counters is:
	  <cmdsynopsis>
	    <command>ipfw</command>
	    <arg choice="plain">zero</arg>
	    <arg choice="opt"><replaceable>index</replaceable></arg>
	  </cmdsynopsis></para>

	<para>When used without an <replaceable>index</replaceable> argument,
	  all packet counters are cleared.  If an
	  <replaceable>index</replaceable> is supplied, the clearing operation
	  only affects a specific chain entry.</para>
      </sect3>
    </sect2>

    <sect2>
      <title>Example commands for ipfw</title>
      
      <para>This command will deny all packets from the host <hostid
	  role="fqdn">evil.crackers.org</hostid> to the telnet port of the
	host <hostid role="fqdn">nice.people.org</hostid> by being forwarded
	by the router:</para>
	  	  
      <screen>&prompt.root <userinput>ipfw add deny tcp from evil.crackers.org to nice.people.org 23</userinput></screen>
	  
      <para>The next example denies and logs any TCP traffic from the entire
	<hostid role="domainname">crackers.org</hostid> network (a class C) to
	the <hostid role="fqdn">nice.people.org</hostid> machine (any
	port).</para>
	  
      <screen>&prompt.root; <userinput>ipfw add deny log tcp from evil.crackers.org/24 to nice.people.org</userinput></screen>
	  
      <para>If you do not want people sending X sessions to your internal
	network (a subnet of a class C), the following command will do the
	necessary filtering:</para>
	  
      <screen>&prompt.root; <userinput>ipfw add deny tcp from any to my.org/28 6000 setup</userinput></screen>
	  
      <para>To see the accounting records:
	    
	<screen>&prompt.root; <userinput>ipfw -a list</userinput></screen>

	or in the short form
	    
	<screen>&prompt.root; <userinput>ipfw -a l</userinput></screen>
      </para>

      <para>You can also see the last time a chain entry was matched
	with:</para>
      
      <screen>&prompt.root; <userinput>ipfw -at l</userinput></screen>
    </sect2>
    
    <sect2>
      <title>Building a packet filtering firewall</title>
      
      <note>
	<para>The following suggestions are just that: suggestions.  The
	  requirements of each firewall are different and I cannot tell you
	  how to build a firewall to meet your particular requirements.</para>
      </note>
	  
      <para>When initially setting up your firewall, unless you have a test
	bench setup where you can configure your firewall host in a controlled
	environment, I strongly recommend you use the logging version of the
	commands and enable logging in the kernel.  This will allow you to
	quickly identify problem areas and cure them without too much
	disruption.  Even after the initial setup phase is complete, I
	recommend using the logging for of `deny' as it allows tracing of
	possible attacks and also modification of the firewall rules if your
	requirements alter.</para>
	  
      <note>
	<para>If you use the logging versions of the <command>accept</command>
	  command, it can generate <emphasis>large</emphasis> amounts of log
	  data as one log line will be generated for every packet that passes
	  through the firewall, so large ftp/http transfers, etc, will really
	  slow the system down.  It also increases the latencies on those
	  packets as it requires more work to be done by the kernel before the
	  packet can be passed on.  syslogd with also start using up a lot
	  more processor time as it logs all the extra data to disk, and it
	  could quite easily fill the partition <filename>/var/log</filename>
	  is located on.</para>
      </note>
	  
      <para>You should enable your firewall from
	<filename>/etc/rc.conf.local</filename> or
	<filename>/etc/rc.conf</filename>.  The associated manpage explains
	which knobs to fiddle and lists some preset firewall configurations.
	If you do not use a preset configuration, <command>ipfw list</command>
	will output the current ruleset into a file that you can
	pass to <filename>rc.conf</filename>.  If you do not use
	<filename>/etc/rc.conf.local</filename> or
	<filename>/etc/rc.conf</filename> to enable your firewall,
	it is important to make sure your firewall is enabled before
	any IP interfaces are configured.
      </para>
	  
      <para>The next problem is what your firewall should actually
	<emphasis>do</emphasis>! This is largely dependent on what access to
	your network you want to allow from the outside, and how much access
	to the outside world you want to allow from the inside. Some general
	rules are:</para>
      
      <itemizedlist>
	<listitem>
	  <para>Block all incoming access to ports below 1024 for TCP. This is
	    where most of the security sensitive services are, like finger,
	    SMTP (mail) and telnet.</para>
	</listitem>

	<listitem>
	  <para>Block <emphasis>all</emphasis> incoming UDP traffic.  There
	    are very few useful services that travel over UDP, and what useful
	    traffic there is is normally a security threat (e.g. Suns RPC and
	    NFS protocols).  This has its disadvantages also, since UDP is a
	    connectionless protocol, denying incoming UDP traffic also blocks
	    the replies to outgoing UDP traffic.  This can cause a problem for
	    people (on the inside) using external archie (prospero) servers.
	    If you want to allow access to archie, you'll have to allow
	    packets coming from ports 191 and 1525 to any internal UDP port
	    through the firewall.  ntp is another service you may consider
	    allowing through, which comes from port 123.</para>
	</listitem>
	      
	<listitem>
	  <para>Block traffic to port 6000 from the outside.  Port 6000 is the
	    port used for access to X11 servers, and can be a security threat
	    (especially if people are in the habit of doing <command>xhost
	      +</command> on their workstations).  X11 can actually use a
	    range of ports starting at 6000, the upper limit being how many X
	    displays you can run on the machine.  The upper limit as defined
	    by RFC 1700 (Assigned Numbers) is 6063.</para>
	</listitem>
	      
	<listitem>
	  <para>Check what ports any internal servers use (e.g. SQL servers,
	    etc).  It is probably a good idea to block those as well, as they
	    normally fall outside the 1-1024 range specified above.</para>
	</listitem>
      </itemizedlist>
	  
      <para>Another checklist for firewall configuration is available from
	CERT at <ulink
	  url="ftp://ftp.cert.org/pub/tech_tips/packet_filtering">ftp://ftp.cert.org/pub/tech_tips/packet_filtering</ulink></para>
	  
      <para>As I said above, these are only <emphasis>guidelines</emphasis>.
	You will have to decide what filter rules you want to use on your
	firewall yourself.  I cannot accept ANY responsibility if someone
	breaks into your network, even if you follow the advice given
	above.</para>
    </sect2>
  </sect1>

  <sect1 id="openssl">
    <title>OpenSSL</title>

    <para>As of FreeBSD 4.0, the OpenSSL toolkit is a part of the base
      system.  <ulink url="http://www.openssl.org/">OpenSSL</ulink>
      provides a general-purpose cryptography library, as well as the
      Secure Sockets Layer v2/v3 (SSLv2/SSLv3) and Transport Layer
      Security v1 (TLSv1) network security protocols.</para>

    <para>However, some of the algorithms (specifically, RSA and IDEA)
      included in OpenSSL are protected by patents in the USA and
      elsewhere, and are not available for unrestricted use (in
      particular, IDEA is not available at all in FreeBSD's version of
      OpenSSL).  As a result, FreeBSD has available two different
      versions of the OpenSSL RSA libraries depending on geographical
      location (USA/non-USA).</para>

    <sect2>
      <title>Source Code Installations</title>
      
      <para>OpenSSL is part of the <literal>src-crypto</literal> and
	<literal>src-secure</literal>cvsup collections.  See the <link
	linkend="mirrors">Obtaining FreeBSD</link> section for more
	information about obtaining and updating FreeBSD source
	code.</para>
    </sect2>

    <sect2>
      <title>International (Non-USA) Users</title>

      <para>People who are located outside the USA, and who obtain their
	crypto sources from <hostid
	role="fqdn">internat.FreeBSD.org</hostid> (the International
	Crypto Repository) or an international mirror site, will build a
	version of OpenSSL which includes the <quote>native</quote> OpenSSL
	implementation of
	RSA, but does not include IDEA, because the latter is restricted
	in certain locations elsewhere in the world.  In the future a more
	flexible geographical identification system may allow building of
	IDEA in countries for which it is not restricted.</para>

      <para>Please be aware of any local restrictions on the import, use
	and redistribution of cryptography which may exist in your
	country.</para>
    </sect2>

    <sect2>
      <title>USA Users</title>

      <para>As noted above, RSA is patented in the USA, with terms
	preventing general use without an appropriate license.  Therefore
	the standard OpenSSL RSA code may not be used in the USA, and has been
	removed from the version of OpenSSL carried on USA mirror sites.
	The RSA patent is due to expire on September 20, 2000, at which
	time it is intended to add the <quote>full</quote> RSA code back to
	the USA version of OpenSSL.</para>

      <para>However (and fortunately), the RSA patent holder (<ulink
	url="http://www.rsasecurity.com/">RSA Security</ulink>, has
	provided a <quote>RSA reference implementation</quote> toolkit
	(RSAREF) which is available for <emphasis>certain classes of
	use</emphasis>, including <emphasis>non-commercial use</emphasis>
	(see the RSAREF license for their definition of
	non-commercial).</para>

      <para>If you meet the conditions of the RSAREF license and wish to
	use it in conjunction with OpenSSL to provide RSA support, you can
	install the rsaref port, which is located in
	<filename>/usr/ports/security/rsaref</filename>, or the
	<literal>rsaref-2.0</literal> package.  The OpenSSL library will
	then automatically detect and use the RSAREF libraries.  Please	obtain
	legal advice if you are unsure of your compliance with the license
	terms.</para>

      <para> The RSAREF implementation is inferior to the
	<quote>native</quote> OpenSSL implementation (it is much slower,
	and cannot be used with keys larger than 1024 bits).  If you are not
	located in the USA then you are doing yourself a disadvantage by
	using RSAREF.</para>

      <para>Users who have purchased an appropriate RSA source code
	license from RSA Security may use the International version of
	OpenSSL described above to obtain native RSA support.</para>

      <para>IDEA code is also removed from the USA version of OpenSSL for
	patent reasons.</para>
    </sect2>

    <sect2>
      <title>Binary Installations</title>

      <para>If your FreeBSD installation was a binary installation (e.g.,
	installed from the Walnut Creek CDROM, or from a snapshot
	downloaded from
	<hostid role="fqdn">ftp.FreeBSD.org</hostid>) and you selected to
	install the <literal>crypto</literal> collection, then the
	<literal>sysinstall</literal> utility will automatically select
	the correct version to install during the installation
	process. If the international version was selected but could
	not be installed during sysinstall (e.g. you have not
	configured network access, and the version must be downloaded
	from a FTP site) then you can add the international RSA library
	after installation as a package.</para>

      <para>The <literal>librsaintl</literal> package contains the RSA
	code for International (non-USA) users.  This is not legal for
	use in the USA, but international users should use this version
	because the RSA implementation is faster and more flexible.  It
	is available from <hostid
	role="fqdn">ftp.internat.FreeBSD.org</hostid> and does not
	require RSAREF.</para>
    </sect2>
  </sect1>

  <sect1 id="ipsec">
    <title>IPsec</title>
    <para><emphasis>Contributed by &a.shin;, 5 March
	2000.</emphasis></para>

    <para>IPsec mechanism provides secure communication either for IP
    layer and socket layer communication.  This section should
    explain how to use them.  About IPsec implementation, please
    refer <link linkend="ipsec-implementation">section 23.5.4</link>.</para>

    <para>The current IPsec implementation supports both transport mode
    and tunnel mode.  However, tunnel mode comes with some restrictions.
    <ulink url="http://www.kame.net/newsletter/">http://www.kame.net/newsletter/
    </ulink> has more comprehensive examples.</para>

    <sect2>
      <title>Transport mode example with IPv4</title>

      <para>Let's setup security association to deploy a secure channel
      between HOST A (10.2.3.4) and HOST B (10.6.7.8).  Here we show a little
      complicated example.  From HOST A to HOST B, only old AH is used.
      From HOST B to HOST A, new AH and new ESP are combined.</para>

      <para>Now we should choose algorithm to be used corresponding to
      "AH"/"new AH"/"ESP"/"new ESP".  Please refer to the &man.setkey.8; man
      page to know algorithm names.  Our choice is MD5 for AH, new-HMAC-SHA1
      for new AH, and new-DES-expIV with 8 byte IV for new ESP.</para>

      <para>Key length highly depends on each algorithm.  For example, key
      length must be equal to 16 bytes for MD5, 20 for new-HMAC-SHA1,
      and 8 for new-DES-expIV.  Now we choose "MYSECRETMYSECRET",
      "KAMEKAMEKAMEKAMEKAME", "PASSWORD", respectively.</para>

      <para>OK, let's assign SPI (Security Parameter Index) for each protocol.
      Please note that we need 3 SPIs for this secure channel since three
      security headers are produced (one for from HOST A to HOST B, two for
      from HOST B to HOST A).  Please also note that SPI MUST be greater
      than or equal to 256.  We choose, 1000, 2000, and 3000, respectively.
      </para>

      <screen>

	         (1)
	HOST A ------> HOST B

	(1)PROTO=AH
		ALG=MD5(RFC1826)
		KEY=MYSECRETMYSECRET
		SPI=1000

	         (2.1)
	HOST A <------ HOST B
	       <------
	         (2.2)

	(2.1)
	PROTO=AH
		ALG=new-HMAC-SHA1(new AH)
		KEY=KAMEKAMEKAMEKAMEKAME
		SPI=2000

	(2.2)
	PROTO=ESP
		ALG=new-DES-expIV(new ESP)
			IV length = 8
		KEY=PASSWORD
		SPI=3000

      </screen>

      <para>Now, let's setup security association.  Execute &man.setkey.8;
      on both HOST A and B:</para>

      <screen>

&prompt.root; <command>setkey -c</command>
add 10.2.3.4 10.6.7.8 ah-old  1000 -m transport -A keyed-md5 "MYSECRETMYSECRET" ;
add 10.6.7.8 10.2.3.4 ah  2000 -m transport -A hmac-sha1 "KAMEKAMEKAMEKAMEKAME" ;
add 10.6.7.8 10.2.3.4 esp 3000 -m transport -E des-cbc "PASSWORD" ;
^D

     </screen>

     <para>Actually, IPsec communication doesn't process until security policy
     entries will be defined.  In this case, you must setup each host.</para>

     <screen>

At A:

&prompt.root; <command>setkey -c</command>
spdadd 10.2.3.4 10.6.7.8 any -P out ipsec
	ah/transport/10.2.3.4-10.6.7.8/require ;
^D

At B:

&prompt.root; <command>setkey -c</command>
spdadd 10.6.7.8 10.2.3.4 any -P out ipsec
	esp/transport/10.6.7.8-10.2.3.4/require ;
spdadd 10.6.7.8 10.2.3.4 any -P out ipsec
	ah/transport/10.6.7.8-10.2.3.4/require ;
^D


   HOST A --------------------------------------> HOST E
  10.2.3.4                                       10.6.7.8
          |                                     |
          ========== old AH keyed-md5 ==========>

          <========= new AH hmac-sha1 ===========
          <========= new ESP des-cbc ============

     </screen>
    </sect2>

    <sect2>
      <title>Transport mode example with IPv6</title>

      <para>Another example using IPv6.</para>

      <para>ESP transport mode is recommended for TCP port number 110 between
      Host-A and Host-B.</para>

      <screen>

              ============ ESP ============
              |                           |
           Host-A                        Host-B
          fec0::10 -------------------- fec0::11

      </screen>

      <para>Encryption algorithm is blowfish-cbc whose key is "kamekame", and
      authentication algorithm is hmac-sha1 whose key is "this is the test
      key".  Configuration at Host-A:</para>

      <screen>

        &prompt.root; <command>setkey -c</command> &lt;&lt;<filename>EOF</filename>
        spdadd fec0::10[any] fec0::11[110] tcp -P out ipsec
                esp/transport/fec0::10-fec0::11/use ;
        spdadd fec0::11[110] fec0::10[any] tcp -P in ipsec
                esp/transport/fec0::11-fec0::10/use ;
        add fec0::10 fec0::11 esp 0x10001
                -m transport
                -E blowfish-cbc "kamekame"
                -A hmac-sha1 "this is the test key" ;
        add fec0::11 fec0::10 esp 0x10002
                -m transport
                -E blowfish-cbc "kamekame"
                -A hmac-sha1 "this is the test key" ;
        EOF

      </screen>

      <para>and at Host-B:</para>

      <screen>
        &prompt.root; <command>setkey -c</command> &lt;&lt;<filename>EOF</filename>
        spdadd fec0::11[110] fec0::10[any] tcp -P out ipsec
                esp/transport/fec0::11-fec0::10/use ;
        spdadd fec0::10[any] fec0::11[110] tcp -P in ipsec
                esp/transport/fec0::10-fec0::11/use ;
        add fec0::10 fec0::11 esp 0x10001 -m transport
                -E blowfish-cbc "kamekame"
                -A hmac-sha1 "this is the test key" ;
        add fec0::11 fec0::10 esp 0x10002 -m transport
                -E blowfish-cbc "kamekame"
                -A hmac-sha1 "this is the test key" ;
        EOF

      </screen>

      <para>Note the direction of SP.</para>
    </sect2>

    <sect2>
      <title>Tunnel mode example with IPv4</title>

      <para>Tunnel mode between two security gateways</para>

      <para>Security protocol is old AH tunnel mode, i.e. specified by
      RFC1826, with keyed-md5 whose key is "this is the test" as
      authentication algorithm.</para>

      <screen>

                             ======= AH =======
                             |                |
         Network-A       Gateway-A        Gateway-B        Network-B
        10.0.1.0/24 ---- 172.16.0.1 ----- 172.16.0.2 ---- 10.0.2.0/24

      </screen>

      <para>Configuration at Gateway-A:</para>

      <screen>

        &prompt.root; <command>setkey -c</command> &lt;&lt;<filename>EOF</filename>
        spdadd 10.0.1.0/24 10.0.2.0/24 any -P out ipsec
                ah/tunnel/172.16.0.1-172.16.0.2/require ;
        spdadd 10.0.2.0/24 10.0.1.0/24 any -P in ipsec
                ah/tunnel/172.16.0.2-172.16.0.1/require ;
        add 172.16.0.1 172.16.0.2 ah-old 0x10003 -m any
                -A keyed-md5 "this is the test" ;
        add 172.16.0.2 172.16.0.1 ah-old 0x10004 -m any
                -A keyed-md5 "this is the test" ;

        EOF

      </screen>

      <para>If port number field is omitted such above then "[any]" is
      employed. `-m' specifies the mode of SA to be used. "-m any" means
      wild-card of mode of security protocol. You can use this SA for both
      tunnel and transport mode.</para>

      <para>and at Gateway-B:</para>

      <screen>

        &prompt.root; <command>setkey -c</command> &lt;&lt;<filename>EOF</filename>
        spdadd 10.0.2.0/24 10.0.1.0/24 any -P out ipsec
                ah/tunnel/172.16.0.2-172.16.0.1/require ;
        spdadd 10.0.1.0/24 10.0.2.0/24 any -P in ipsec
                ah/tunnel/172.16.0.1-172.16.0.2/require ;
        add 172.16.0.1 172.16.0.2 ah-old 0x10003 -m any
                -A keyed-md5 "this is the test" ;
        add 172.16.0.2 172.16.0.1 ah-old 0x10004 -m any
                -A keyed-md5 "this is the test" ;

        EOF

      </screen>

      <para>Making SA bundle between two security gateways</para>

      <para>AH transport mode and ESP tunnel mode is required between
      Gateway-A and Gateway-B. In this case, ESP tunnel mode is applied first,
      and AH transport mode is next.</para>

      <screen>

                            ========== AH =========
                            |  ======= ESP =====  |
                            |  |               |  |
       Network-A          Gateway-A        Gateway-B           Network-B
    fec0:0:0:1::/64 --- fec0:0:0:1::1 ---- fec0:0:0:2::1 --- fec0:0:0:2::/64

      </screen>
    </sect2>

    <sect2>
      <title>Tunnel mode example with IPv6</title>

      <para>Encryption algorithm is 3des-cbc, and authentication algorithm
      for ESP is hmac-sha1.  Authentication algorithm for AH is hmac-md5.
      Configuration at Gateway-A:</para>

      <screen>

        &prompt.root; <command>setkey -c</command> &lt;&lt;<filename>EOF</filename>
        spdadd fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out ipsec
                esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require
                ah/transport/fec0:0:0:1::1-fec0:0:0:2::1/require ;
        spdadd fec0:0:0:2::/64 fec0:0:0:1::/64 any -P in ipsec
                esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require
                ah/transport/fec0:0:0:2::1-fec0:0:0:1::1/require ;
        add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10001 -m tunnel
                -E 3des-cbc "kamekame12341234kame1234"
                -A hmac-sha1 "this is the test key" ;
        add fec0:0:0:1::1 fec0:0:0:2::1 ah 0x10001 -m transport
                -A hmac-md5 "this is the test" ;
        add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10001 -m tunnel
                -E 3des-cbc "kamekame12341234kame1234"
                -A hmac-sha1 "this is the test key" ;
        add fec0:0:0:2::1 fec0:0:0:1::1 ah 0x10001 -m transport
                -A hmac-md5 "this is the test" ;

        EOF

      </screen>

      <para>Making SAs with the different end</para>

      <para>ESP tunnel mode is required between Host-A and Gateway-A. Encryption
      algorithm is cast128-cbc, and authentication algorithm for ESP is
      hmac-sha1.  ESP transport mode is recommended between Host-A and Host-B.
      Encryption algorithm is rc5-cbc, and authentication algorithm for ESP is
      hmac-md5.</para>

      <screen>

              ================== ESP =================
              |  ======= ESP =======                 |
              |  |                 |                 |
             Host-A            Gateway-A           Host-B
          fec0:0:0:1::1 ---- fec0:0:0:2::1 ---- fec0:0:0:2::2

      </screen>

      <para>Configuration at Host-A:</para>

      <screen>

        &prompt.root; <command>setkey -c</command> &lt;&lt;<filename>EOF</filename>
        spdadd fec0:0:0:1::1[any] fec0:0:0:2::2[80] tcp -P out ipsec
                esp/transport/fec0:0:0:1::1-fec0:0:0:2::2/use
                esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require ;
        spdadd fec0:0:0:2::1[80] fec0:0:0:1::1[any] tcp -P in ipsec
                esp/transport/fec0:0:0:2::2-fec0:0:0:l::1/use
                esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require ;
        add fec0:0:0:1::1 fec0:0:0:2::2 esp 0x10001
                -m transport
                -E cast128-cbc "12341234"
                -A hmac-sha1 "this is the test key" ;
        add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10002
                -E rc5-cbc "kamekame"
                -A hmac-md5 "this is the test" ;
        add fec0:0:0:2::2 fec0:0:0:1::1 esp 0x10003
                -m transport
                -E cast128-cbc "12341234"
                -A hmac-sha1 "this is the test key" ;
        add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10004
                -E rc5-cbc "kamekame"
                -A hmac-md5 "this is the test" ;

        EOF

      </screen>
    </sect2>
  </sect1>
</chapter>

<!-- 
     Local Variables:
     mode: sgml
     sgml-declaration: "../chapter.decl"
     sgml-indent-data: t
     sgml-omittag: nil
     sgml-always-quote-attributes: t
     sgml-parent-document: ("../book.sgml" "part" "chapter")
     End:
-->

