diff --git a/documentation/content/en/books/ipfw-primer/_index.adoc b/documentation/content/en/books/ipfw-primer/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/_index.adoc @@ -0,0 +1,59 @@ +--- +title: IPFW Primer +authors: Jim Brown +copyright: 2025 The FreeBSD Documentation Project +trademarks: ["freebsd", "general", "git", "ipfw"] +description: Primer on Using IPFW on FreeBSD +next: books/ipfw-primer/ipfw-acknowledgments +tags: ["FDP", "documentation", "FreeBSD", "Index"] +add_single_page_link: true +showBookMenu: true +weight: 3 +path: "/books/ipfw-primer/" +bookOrder: 55 +--- + += IPFW Primer +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +[.abstract-title] +Abstract + +man:ipfw[8] is a firewall application that comes standard with FreeBSD. +This book provides an introduction to IPFW and its capabilities. +These capabilities are demonstrated using QEMU virtual machines in real-world scenarios. + +Content includes descriptions of the main features of man:ipfw[8] and lab examples on using IPFW as a firewall or a network gateway. + +Like IPFW itself, this book is a work in progress. + +''' diff --git a/documentation/content/en/books/ipfw-primer/_index.po b/documentation/content/en/books/ipfw-primer/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/_index.po @@ -0,0 +1,61 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/_index.adoc:1 +#, no-wrap +msgid "Primer on Using IPFW on FreeBSD" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/_index.adoc:1 +#: documentation/content/en/books/ipfw-primer/_index.adoc:16 +#, no-wrap +msgid "IPFW Primer" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/_index.adoc:50 +msgid "Abstract" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/_index.adoc:54 +msgid "" +"man:ipfw[8] is a firewall application that comes standard with FreeBSD. " +"This book provides an introduction to IPFW and its capabilities. These " +"capabilities are demonstrated using QEMU virtual machines in real-world " +"scenarios." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/_index.adoc:56 +msgid "" +"Content includes descriptions of the main features of man:ipfw[8] and lab " +"examples on using IPFW as a firewall or a network gateway." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/_index.adoc:58 +msgid "Like IPFW itself, this book is a work in progress." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/_index.adoc:59 +msgid "'''" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/book.adoc b/documentation/content/en/books/ipfw-primer/book.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/book.adoc @@ -0,0 +1,99 @@ +--- +title: IPFW Primer +authors: Jim Brown +copyright: 2025 The FreeBSD Documentation Project +description: IPFW Primer +trademarks: ["freebsd", "general", "git", "ipfw"] +tags: ["FDP", "documentation", "FreeBSD", "Index", "ipfw"] +add_split_page_link: true +--- + += IPFW Primer +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:partnums: +:source-highlighter: rouge +:experimental: +:book: true +:pdf: false +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +:chapters-path: content/{{% lang %}}/books/ipfw-primer/ +endif::[] +ifdef::backend-pdf,backend-epub3[] +:chapters-path: +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +:chapters-path: +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +[.abstract-title] +Abstract + +man:ipfw[8] is a firewall application that comes standard with FreeBSD. +This book provides an introduction to IPFW and its capabilities. +These capabilities are demonstrated using QEMU virtual machines in real-world scenarios. + +Content includes descriptions of the main features of man:ipfw[8] and lab examples on using IPFW as a firewall or a network gateway. + +Like IPFW itself, this book is a work in progress. + +''' + +toc::[] + +:sectnums!: + +include::{chapters-path}ipfw-acknowledgments/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-preface/_index.adoc[leveloffset=+1] + +:sectnums: + +include::{chapters-path}ipfw-introduction/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-operation/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-rules/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-dummynet/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-nat/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-ipv6-nat/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-other-keywords/_index.adoc[leveloffset=+1] + +:sectnums!: + +include::{chapters-path}ipfw-appendix-a/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-appendix-b/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-appendix-c/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-appendix-d/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-appendix-e/_index.adoc[leveloffset=+1] + +include::{chapters-path}ipfw-index/_index.adoc[leveloffset=+1] + +:sectnums: diff --git a/documentation/content/en/books/ipfw-primer/book.po b/documentation/content/en/books/ipfw-primer/book.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/book.po @@ -0,0 +1,60 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/book.adoc:1 +#, no-wrap +msgid "IPFW Primer" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/book.adoc:11 +#, no-wrap +msgid "IPFW Primer 2025-01-13T17:49-05:00" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/book.adoc:50 +msgid "Abstract" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/book.adoc:54 +msgid "" +"man:ipfw[8] is a firewall application that comes standard with FreeBSD. " +"This book provides an introduction to IPFW and its capabilities. These " +"capabilities are demonstrated using QEMU virtual machines in real-world " +"scenarios." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/book.adoc:56 +msgid "" +"Content includes descriptions of the main features of man:ipfw[8] and lab " +"examples on using IPFW as a firewall or a network gateway." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/book.adoc:58 +msgid "Like IPFW itself, this book is a work in progress." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/book.adoc:60 +msgid "'''" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc @@ -0,0 +1,95 @@ +--- +title: Acknowledgments +prev: books/ipfw-primer +next: books/ipfw-primer/ipfw-preface +description: Preface for IPFW Book +tags: ["preface", "prompts", "conventions"] +showBookMenu: true +weight: 6 +path: "/books/ipfw-primer/ipfw-acknowledgments/" +--- + +[acknowledgments] +[[ipfw-acknowledgments]] += Acknowledgments +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +[[ipfw-acknowledgments-text]] + +Thanks to the FreeBSD developers who added and maintain IPFW. +indexterm:[developers] + +Also, thanks to those who took the time to read early drafts of this document and offered many valuable comments and criticisms. + +*Attributions* + +Artwork from the following sources was used in preparing this book: + +* Stylized *nginx* logo +indexterm:[nginx] + +Original image: link:https://en.wikipedia.org/wiki/Nginx#/media/File:Nginx_logo.svg[NGINX Logo] + +Obtained from Wikimedia https://en.wikipedia.org/wiki/Nginx#/media/File:Nginx_logo.svg. +Image is listed as in the Public Domain. + +The image was converted to .PNG and also to .BMP formats for use in this book and accompanying code. +Conversions were accomplished via ImageMagick's *convert* program. + +* Stylized *bind 9* logo +indexterm:[bind9] + +Original image: link:https://www.isc.org/blogs/bind-9s-new-logo/[BIND 9's New Logo] + +Obtained from https://www.isc.org/blogs/bind-9s-new-logo/ + +Logo used with permission from Internet Systems Consortium (ISC). + +The image was converted to .PNG and also to .BMP formats for use in this book and accompanying code. +Conversions were accomplished via ImageMagick's *convert* program. + +* Stylized *IPv6* logo +indexterm:[ipv6] + +Original image: link:https://www.worldipv6launch.org/wp-content/themes/ipv6/downloads/World_IPv6_launch_logo_256.png[World IPv6 Launch Logo] + +Obtained from Wikipedia: https://commons.wikimedia.org/wiki/File:World_IPv6_launch_logo.svg +Original CC 3.0 license: https://creativecommons.org/licenses/by/3.0/deed.en +Updated CC 4.0 license: https://creativecommons.org/licenses/by/4.0/deed.en + +The image was converted to .PNG and also to .BMP formats for use in this book and accompanying code. +Conversions were accomplished via ImageMagick's *convert* program. + +Use of the above artwork does not imply endorsement of any opinions expressed in this book. + +All other artwork is original artwork by the author. diff --git a/documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.po @@ -0,0 +1,139 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:1 +#, no-wrap +msgid "Preface for IPFW Book" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:1 +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:14 +#, no-wrap +msgid "Acknowledgments" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:51 +msgid "" +"Thanks to the FreeBSD developers who added and maintain IPFW. indexterm:" +"[developers]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:53 +msgid "" +"Also, thanks to those who took the time to read early drafts of this " +"document and offered many valuable comments and criticisms." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:55 +#, no-wrap +msgid "*Attributions*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:57 +msgid "Artwork from the following sources was used in preparing this book:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:60 +msgid "Stylized *nginx* logo indexterm:[nginx]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:62 +msgid "" +"Original image: link:https://en.wikipedia.org/wiki/Nginx#/media/File:" +"Nginx_logo.svg[NGINX Logo]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:65 +msgid "" +"Obtained from Wikimedia https://en.wikipedia.org/wiki/Nginx#/media/File:" +"Nginx_logo.svg. Image is listed as in the Public Domain." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:68 +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:80 +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:92 +msgid "" +"The image was converted to .PNG and also to .BMP formats for use in this " +"book and accompanying code. Conversions were accomplished via ImageMagick's " +"*convert* program." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:71 +msgid "Stylized *bind 9* logo indexterm:[bind9]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:73 +msgid "" +"Original image: link:https://www.isc.org/blogs/bind-9s-new-logo/[BIND 9's " +"New Logo]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:75 +msgid "Obtained from https://www.isc.org/blogs/bind-9s-new-logo/" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:77 +msgid "Logo used with permission from Internet Systems Consortium (ISC)." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:83 +msgid "Stylized *IPv6* logo indexterm:[ipv6]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:85 +msgid "" +"Original image: link:https://www.worldipv6launch.org/wp-content/themes/ipv6/" +"downloads/World_IPv6_launch_logo_256.png[World IPv6 Launch Logo]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:89 +msgid "" +"Obtained from Wikipedia: https://commons.wikimedia.org/wiki/File:" +"World_IPv6_launch_logo.svg Original CC 3.0 license: https://creativecommons." +"org/licenses/by/3.0/deed.en Updated CC 4.0 license: https://creativecommons." +"org/licenses/by/4.0/deed.en" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:94 +msgid "" +"Use of the above artwork does not imply endorsement of any opinions " +"expressed in this book." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-acknowledgments/_index.adoc:95 +msgid "All other artwork is original artwork by the author." +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc @@ -0,0 +1,555 @@ +--- +title: Appendix A. QEMU Setup +prev: books/ipfw-primer/ipfw-other-keywords +next: books/ipfw-primer/ipfw-appendix-b +description: Setup Procedures for QEMU Virtual Machines +tags: ["firewall", "IPFW", "Virtual Machine", "VM", "QEMU"] +showBookMenu: true +weight: 90 +path: "/books/ipfw-primer/ipfw-appendix-a/" +--- + +[appendix] +[[appendix-a]] += Appendix A: QEMU Setup +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: A +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +[NOTE] +==== +It is highly advised to read through the entire installation procedure, including all notes and tips, before proceeding. +==== + +This appendix contains helpful information for getting QEMU installed and running on FreeBSD, and instructions for common use. +The installation presumes a graphical desktop running on top of X Windows or Wayland. +indexterm:[QEMU] +indexterm:[SDL] indexterm:[virtual terminal] +Because of this, the user environment, either X Window or Wayland, must allow for use of the DISPLAY variable in the local environment. +indexterm:[DISPLAY] + +The examples in this book utilize virtual machines (VMs) using an SDL-based man:vt[4] console and also include a using a FreeBSD serial console. +Instructions for setting up the VMs are below. +Instructions for setting up and managing the serial consoles are found in crossref:ipfw-appendix-a[appendix-a-serial-console, Adding and Managing Serial Console Access to the VMs] below. + +Additional resources for understanding and using QEMU include: + +* The link:https://docs.freebsd.org/en/books/handbook/virtualization/#qemu-virtualization-host-guest[QEMU Virtualization] chapter in the FreeBSD Handbook +indexterm:[virtualization] +* The man:qemu[1] manual page +* The link:https://www.qemu.org[QEMU Home Page] +* link:https://www.jimby.name/techbits/recent/qemu[Yet Another QEMU installation guide] + +*Installation* + +QEMU is available as a package or a port. +There are a large number of build options on the port, so in most cases it is best to install the package. +man:sudo[8] will also need to be installed as well. + +Altogether, there are nine virtual machines used in this book. +The following procedure will make ready all nine VMs. +However, all nine are not needed immediately. +Most of the first half of this book can be done with just the *firewall*, *internal*, *external1*, and *external2* VMs. + +[[appendix-a-quick00]] +.Setting Up the Initial Virtual Machines +image::ipfw-introduction000.png["Setting Up the Initial Virtual Machines. Refer to paragraphs below."] + +The initial setup is that shown in crossref:ipfw-introduction[ipfw-introduction-quick00,Figure {counter:figure}]. +indexterm:[virtual machine] + +[[appendix-a-installation-process]] +== QEMU and VM Installation Process + +Follow the steps below to install and configure the QEMU virtual machines needed for this book. +Various scripts are used to create virtual machines and set up bridge and tap devices. +If desired, examine all scripts before use. +indexterm:[QEMU] + +[.procedure] +==== +. On the FreeBSD host, install the necessary packages - man:qemu[1], man:sudo[8] (or man:doas[1]). +Sudo, (or doas) is necessary for running the virtual machines as these QEMU configurations open a separate console window through SDL. +indexterm:[SDL] +The examples in this book use sudo. ++ +[subs=+quotes] +---- +# *pkg install qemu sudo* +---- ++ +indexterm:[QEMU, pkg install] indexterm:[sudo] ++ +Configure sudo as desired. ++ +. Clone the scripts for this book from the *ipfw-primer* project on GitHub. +Then fetch the current FreeBSD ISO. ++ +---- +Note: The initial path can be any directory. +All scripts use relative directory addressing. +Adjust the paths below as necessary. +---- ++ +[subs=+quotes] +---- +% *cd $HOME* +% *git clone https://github.com/jimmyb-gh/ipfw-primer.git* +% *cd ~/ipfw-primer/ipfw/ISO* +% *fetch https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/##/FreeBSD-##-RELEASE-amd64-dvd1.iso* + +The example for FreeBSD 14.2 would be: +% *fetch https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/14.2/FreeBSD-14.2-RELEASE-amd64-dvd1.iso* + +% # Link a shorter name to the ISO image. +% *ln -s FreeBSD--RELEASE-amd64-dvd1.iso fbsd.iso* +---- ++ +indexterm:[SCRIPTS] indexterm:[ISO] indexterm:[fetch] ++ +. Using *sudo*, create the bridge and tap devices for the virtual machines to use. +See the description of the *mkbr.sh* script in crossref:ipfw-appendix-a[appendix-a-quickstart-mkbr-script, Using mkbr.sh for Bridge and Tap Setup]. ++ +[subs=+quotes] +---- +% *cd ../HOST_SCRIPTS* +% *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 tap5 tap6 tap7 tap9 tap12 _hostintf_* #<--- replace _hostintf_ with host network interface (em0, bge0, etc.)# +---- ++ +indexterm:[tap] indexterm:[bridge] ++ +. As a normal user, create all VM image files. +Each VM is 4GB except for the *jail1* VM which is 12GB. ++ +[subs=+quotes] +---- +% */bin/sh _CreateAllVMs.sh* + +The next command starts the installation for the *firewall* VM. +Once finished, return to this point and repeat for the following VMs: +external1, external2, external3, firewall2, internal, dnshost, v6only. + +% *sudo /bin/sh firewall.sh* + +#Ignore the "NOTE!!! telnet server running..." message for now.# +Instructions for setting up a serial console are found later in this setup guide. + +---- ++ +indexterm:[qemu-img] indexterm:[qcow2] indexterm:[-blockdev] indexterm:[-device] indexterm:[-netdev] ++ +The FreeBSD installer should boot. +Perform a standard installation of FreeBSD. ++ +During the installation note the following: ++ +* On all VMs *_except_* the *jail1* VM, select to use UFS as the filesystem. +indexterm:[UFS] +ZFS does not perform well with small memory sizes. +The *jail1* VM has more memory and ZFS will be used to create jails on the *jail1* VM. +It is the only VM that requires ZFS. +indexterm:[ZFS] ++ +* For these installations, use DHCP for networking. +indexterm:[DHCP] +If desired, configure IPv6 if supported by the local LAN. ++ +* When adding the default user, ensure they are a member of the _wheel_ group. ++ +Once the installation completes, the virtual machine reboots into the newly installed FreeBSD image. ++ +. Login as root, update the system, and reboot. ++ +[subs=+quotes] +---- +# *freebsd-update fetch install* +# *reboot* +---- ++ +. On all virtual machines, install the packages listed below +The `nmap` package brings in the version of man:ncat[1] used by scripts on the *firewall* and *external* VMs. +indexterm:[nmap] +`nginx`, `lynx`, `cmdwatch`, `hping3`, `tsctp`, and `iperf3` will be used in later chapters. +indexterm:[nginx] indexterm:[lynx] indexterm:[cmdwatch] indexterm:[hping3] indexterm:[iperf3] ++ +[subs=+quotes] +---- +# *pkg install nmap nginx lynx cmdwatch hping3 tsctp iperf3* +---- ++ +. Finally, download `~/ipfw-primer/ipfw/VM_SCRIPTS/IPFW_root_bin.tgz` file to *_all_* VMs. +This tar file has a number of scripts needed for the virtual machines. ++ +Move the tarzip file into [.filename]#/root# and extract the contents: ++ +[subs=+quotes] +---- +On each VM, login as root, copy and untar the following file: + +# *scp user@hostip:~/ipfw-primer/ipfw/VM_SCRIPTS/IPFW_root_bin.tgz .* +# +# *mv IPFW_root_bin.tgz /root* +# +# *cd /root* +# +# *tar xvzf IPFW_root_bin.tgz* +... files are extracted into /root/bin +# +# *chmod +x /root/bin/***.sh* +---- ++ +. Repeat the installation procedure for each virtual machine. +indexterm:[VM_SCRIPTS] + + +Some additional configurations are required for examples later in the book: + +On the *firewall* and *firewall2* VMs: + + * Add *net.inet.ip.fowarding=1* and *net.inet6.ip6.fowarding=1* to */etc/sysctl.conf*. + +On the *external1* and *internal* VMs install these extra packages: + + * *pkg install git* + * *pkg install cmake* + +indexterm:[git] indexterm:[cmake] + +On each VM, navigate to [.filename]#/usr/local/www/nginx#. +Download the modified `index.html` file from the *host* system to replace the original: + + * *scp user@host:~/ipfw-primer/ipfw/VM_SCRIPTS/#VM_name#/index.html .* + +On the *firewall* VM, download the `bsdclat464.sh` script + + * *cd /root/bin* + * *scp user@host:~/ipfw-primer/ipfw/VM_SCRIPTS/firewall/bsdclat464.sh .* + + +On the *firewall2 VM, download the `bsdplat464.sh` script + + * *cd /root/bin* + * *scp user@host:~/ipfw-primer/ipfw/VM_SCRIPTS/firewall/bsdplat464.sh .* + +indexterm:[bsdclat464.sh] indexterm:[bsdplat464.sh] + +(End installation procedure.) +==== + +For this Quick Start, it is Ok to use `DHCP` for both VMs. +indexterm:[Quick Start] indexterm:[DHCP] +In later examples there will be multiple external VMs using the *203.0.113.0/24* network and other private networks, all set up the same way and attached via man:tap[4] interfaces to one or more man:if_bridge[4] interfaces on the FreeBSD host. +indexterm:[networks, private] indexterm:[bridge] indexterm:[tap] + +To ensure the first two VMs are set up correctly, ping the *firewall* VM from the *external1* VM and vice-versa. +Communications should be successful. +If not, check the above installation details and troubleshoot any network issues. +It should be possible ping in both directions, and even man:ssh[1] from one VM to the other. + +[TIP] +==== +For additional helpful information on getting QEMU set up correctly, check the link:https://docs.freebsd.org/en/books/handbook/virtualization/#qemu-virtualization-host-guest[QEMU virtualization section in the FreeBSD Handbook]. +==== + +[TIP] +==== +If the mouse is clicked in the QEMU console window, QEMU will “grab” the mouse. +If this happens,type, kbd:[Ctl]+kbd:[Alt]+kbd:[G] to release the mouse. +==== +indexterm:[mouse, grab] + +[TIP] +==== +If suddenly, the QEMU console window is full screen, you may have accidentally typed kbd:[Ctl]+kbd:[Alt]+kbd:[F]. +If this happens, retype kbd:[Ctl]+kbd:[Alt]+kbd:[F] to restore the desktop screen. +==== +indexterm:[full screen] + +=== Disabling Syslog Messages to the Console in the Virtual Machines + +It may be advantageous (even necessary) to stop syslog messages from being sent to the console (either the QEMU console, or the serial port). +indexterm:[syslog] indexterm:[console, virtual] indexterm:[console, serial] + +To configure syslog to stop logging to the console, configure a file to receive console messages: + +[subs=+quotes] +---- +# *touch /var/log/console.log* +# +# *chmod 0600 /var/log/console.log* +---- +indexterm:[console.log] + +Then, as *root*, modify the line in [.filename]#/etc/syslog.conf# to read (instead of [.filename]#/dev/console#): +indexterm:[/etc/syslog.conf] + +[subs=+quotes] +---- +**.err;kern.warning;auth.notice;mail.crit /var/log/console.log* +---- + +And, if necessary: + +indexterm:[syslogd] + +[subs=+quotes] +---- +# *service syslogd restart* +---- + +All messages previously bound for the console, will be directed to [.filename]#/var/log/console.log# instead. +indexterm:[console, virtual] + +Before continuing, there is one more piece to add to each VM - a serial console. +indexterm:[console, serial] +A serial console permits examination of the state of each VM, independent of the main console. + +[[appendix-a-serial-console]] +=== Adding and Managing Serial Console Access to the VMs + +*Adding a serial console the FreeBSD VM* + +To add a serial console to each FreeBSD VM, start up the VM and edit the file [.filename]#/boot/loader.conf# and add the line *console=“comconsole”* to allow use of the serial console. +indexterm:[/boot/loader.conf] indexterm:[comconsole] +Reboot the VM to begin using the serial console. +Note that FreeBSD diverts boot I/O to the serial console, so until the FreeBSD operating system is completely ready, output to the QEMU window will be limited. + +The startup scripts for each VM are already configured to use a serial console. +indexterm:[add a serial console] indexterm:[console, serial] +A single configuration line was added to the QEMU configuration to provide a serial console. +The serial console is actually accessed over a man:telnet[1] session. +indexterm:[telnet] +The QEMU manual page, man:qemu[1], describes how the *-serial* keyword works in detail. +indexterm:[serial keyword] + +QEMU redirects the serial port I/O to a TCP port on the host system at VM startup, and allows a man:telnet[1] connection on the configured port on the host. +indexterm:[QEMU] indexterm:[telnet] +Once the FreeBSD system starts booting and recognizes the console directive in [.filename]#/boot/loader.conf# it redirects I/O to the serial console. +QEMU detects this and manages the necessary character I/O on that serial port to the TCP port on the host. + +It is important to note that the this serial redirect over TCP takes place outside the virtual machine. +There is no interaction with any network on the virtual machine and thus it is not subject to any firewall rules. +Think of it just like a "dumb terminal" sitting on an RS-232 serial port on a real machine. +indexterm:["dumb terminal"] + +*Management of serial console windows on the FreeBSD host* + +Each QEMU VM generates a console window, and each serial device also needs its own window, potentially doubling the number of windows used. +indexterm:[serial devices] + +Possible solutions are: + +* Separate windows for each QEMU VM (doubles the number of windows) +* Use tabbed windows (available on XFCE and some other desktops) +* Use a terminal multiplexer such as man:tmux[1] or man:screen[1] +indexterm:[tmux] indexterm:[screen] + +The selected solution uses the multiplexer approach with the man:tmux[1] program for window management. +crossref:ipfw-appendix-d[appendix-d,Appendix D] provides details on using both man:tmux[1] and man:screen[1]. +indexterm:[tmux] indexterm:[screen] +The following figures and descriptions use man:tmux[1]. + +Install *tmux* on the FreeBSD #host# with: +indexterm:[tmux] + +[subs=+quotes] +---- +# *pkg install tmux* +---- + +and if necessary, copy the file *swim.sh* (or *scim.sh* for using man:screen[1]) from crossref:ipfw-appendix-b[appendix-b, Appendix B] into the HOST_SCRIPTS directory. +If using *scim.sh*, follow the instructions in the script to set up a [.filename]#.screenrc# file. +indexterm:[swim.sh] indexterm:[scim.sh] + +The figure below shows the use of the *swim.sh* tmux session manager. +Run *sh swim.sh* in the HOST_SCRIPTS directory to start up the session manager. +indexterm:[session] + +[[appendix-a-tmux-session-introduction]] +.Starting Up tmux(1) Session Manager +image::ipfw-introduction020.png["Starting Up tmux(1) Session Manager. Refer to paragraphs below."] + +The figure shows five named windows in one session (session [0]) with the *tmux* status line in green at the bottom: +indexterm:[session] + +* *0:bash* - a terminal window of the user running *swim.sh* +* *1:firewall* - a terminal window to access the *firewall* VM +* *2:external1* - a terminal window to access the *external1* VM +* *3:external2* - a terminal window to access the *external2* VM +* *4:external3* - a terminal window to access the *external3* VM + +The current window is marked with the '***' character on the status bar. +indexterm:[status bar] + +*Simplified tmux(1) Usage* + +*tmux* uses kbd:[Ctl]+kbd:[b] as its control key. +indexterm:[control key] +To move from window to window use kbd:[Ctl]+kbd:[b] kbd:[n] to move to the next window or kbd:[Ctl]+kbd:[b] kbd:[p] to move to the previous window. +Use kbd:[Ctl]+kbd:[b] kbd:[?] for a list of all key bindings. +indexterm:[binding, key] + +Type *tmux kill-server* in any host session shell window (not a VM window) to completely leave *tmux*. +indexterm:[tmux] + +Consult the *tmux* manual page man:tmux[1] for more usage details. + +*Accessing the QEMU Serial Consoles* + +To access the VM serial consoles, move to the indicated window and telnet to the port on the local host for that VM: +indexterm:[console, serial] + +[subs=+quotes] +---- +Move to the *external1* window in *tmux*, then + +% *telnet localhost 4410* +Trying ::1... +Connected to localhost. +Escape character is '^]'. + +FreeBSD/amd64 (external1) (ttyu0) + +login: +---- +indexterm:[telnet] + +[TIP] +==== +To exit out of the *telnet* session, press kbd:[Ctl]+kbd:[\]] then press kbd:[q] like this: +---- + login: (type Ctl+]) + telnet> q + Connection closed. + % +---- +==== + +There should now be two QEMU VMs (*firewall* and *external1*) started, with serial console sessions available through the *tmux* sessions as shown below. +indexterm:[tmux] + +Configure the FreeBSD *host*, *firewall* VM, and *external1* VM with DHCP addressing as shown in the figure at the beginning of this Quick Start session. +indexterm:[Quick Start] +There should be full connectivity between the FreeBSD *host*, the *firewall* VM and the *external1* VM. + +[[appendix-a-startup-with-serial-console]] +.External1 and Firewall VMs Startup with Serial Console +image::ipfw-introduction025.png["Firewall and External1 VMs Startup with Serial Console. Refer to paragraphs below."] + +Using *ipfw* to control traffic between these two QEMU VMs is discussed in the next chapter. + +[[appendix-a-quickstart-mkbr-script]] +== Using *mkbr.sh* for Bridge and Tap Setup + +Included in crossref:ipfw-appendix-b[appendix-b, Appendix B], the *mkbr.sh* script is used to set up man:if_bridge[4] and man:tap[4] devices on the FreeBSD host. +These interfaces are required to allow the virtual machines to communicate with each other and, when suitably configured, to communicate with the outside world. + +Many examples in this book include a statement such as: + +[subs=+quotes] +---- +# */bin/sh mkbr.sh reset bridge0 tap0 tap1 em0* +---- + +or something similar. + +The above invocation resets the kernel modules necessary for bridge and tap operation, then it creates one bridge, bridge0, and connects tap0, tap1, and em0. +Here, "em0" refers to a host ethernet interface, but it can be any ethernet interface on the local machine. + +The script can be used to create any number of bridges and taps for complex network designs. +For example, the following invocation creates three bridges - bridge0 with tap0 and tap1 connected, bridge1 with tap2, tap3, and tap4 connected, and bridge2 with tap5 and host interface igb0 connnected. + +[subs=+quotes] +---- +% *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 tap3 tap4 bridge2 tap5 igb0* +---- + +To add other taps to existing bridges, do not specify the "reset" parameter: + +[subs=+quotes] +---- +# */bin/sh mkbr.sh bridge0 tap10 tap11 bridge1 tap12 tap13 ... etc.* +---- + +To delete all bridge and tap devices: + +[subs=+quotes] +---- +# */bin/sh mkbr.sh reset* +---- + +Usually, the examples include an architecture diagram, like that shown earlier, and an invocation of *mkbr.sh* that will create the architecture shown. + +Below is a handy chart to show the relationship of virtual machines and *tap* devices. +Note that some virtual machines have more than one interface. +The chart also shows how all virtual machines could be attached to the same bridge if needed for administrative purposes. + +[subs=+quotes] +---- +TAPLIST.TXT + +This file contains just the taps that are needed to +connect all VMs to one bridge for admin purposes: + + +----------------------------------------------+ + | | + | bridge0 | + | | + +-+----+----+----+---+----+---+----+----+----+-+ + / / / / | | \ \ \ \ + tap0 tap1 tap2 tap3 tap5 tap6 tap7 tap9 tap12 host_interface + | | | | | | | | | + | | | | | | | | +- jail1:em0 + | | | | | | | +- firewall2:em0 + | | | | | | +- dnshost:em0 + | | | | | +- v6only:em0 + | | | | +- internal:em0 + | | | +- external3:em0 + | | +- external2:em0 + | +- external1:em0 + +- firewall:em0 + + +The remaining taps are located on the VM listed: + +tap4 - firewall:em1 +tap8 - dnshost:em1 +tap10 - firewall2:em1 +tap11 - dnshost:em2 + +---- + +indexterm:[qcow2] indexterm:[fbsd.iso] indexterm:[tap] indexterm:[bridge] indexterm:[UFS] indexterm:[ZFS] indexterm:[DHCP] + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.po @@ -0,0 +1,232 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:1 +#, no-wrap +msgid "Setup Procedures for QEMU Virtual Machines" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:1 +#, no-wrap +msgid "Appendix A. QEMU Setup" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:14 +#, no-wrap +msgid "Appendix A: QEMU Setup" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:53 +msgid "" +"This appendix contains helpful information for getting QEMU installed on " +"FreeBSD and instructions for common use. indexterm:[QEMU]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:60 +msgid "" +"QEMU can be invoked to display a man:vt[4] style virtual terminal console " +"using SDL. indexterm:[SDL] indexterm:[virtual terminal] Because of this the " +"user environment, either X Window or Wayland, must allow for use of the " +"DISPLAY variable in the local environment. indexterm:[DISPLAY] It can also " +"be invoked in `-nographics` mode, resulting is the current screen or window " +"immediately becoming the console for the QEMU instance. indexterm:[-" +"nographics]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:62 +msgid "" +"The examples in this book utilize the SDL based man:vt[4] based console and " +"also include a using a FreeBSD serial console (described crossref:ipfw-" +"introduction[ipfw-introduction-serialconsole, Adding a Serial Console])." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:64 +msgid "Additional resources for understanding and using QEMU include:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:67 +msgid "" +"The link:https://docs.freebsd.org/en/books/handbook/virtualization/#qemu-" +"virtualization-host-guest[QEMU Virtualization] chapter in the FreeBSD " +"Handbook indexterm:[virtualization]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:68 +msgid "The man:qemu[1] manual page" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:69 +msgid "The link:https://www.qemu.org[QEMU Home Page]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:70 +msgid "" +"link:https://www.jimby.name/techbits/recent/qemu[Yet Another QEMU " +"installation guide]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:73 +msgid "" +"QEMU is available as a package or a port. There are a large number of build " +"options on the port, so in most cases it is best to install the package:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:77 +#, no-wrap +msgid "# pkg install qemu sudo\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:81 +msgid "" +"Perform the following steps to get a QEMU virtual machine started. The " +"crossref:ipfw-introduction[ipfw-introduction-quickstart, Quick Start] " +"section in the Introduction has a suggested layout." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:87 +msgid "" +"Designate a destination directory for the virtual machine(s). This " +"procedure is an example that does not use the directory layout in this " +"book. Call this directory [.filename]#QVM#." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:90 +msgid "" +"Create the image files that will become the QEMU virtual machines. Use man:" +"qemu-img[1] to create the images. Using the `qcow2` format is recommended " +"as the scripts in this book use that format." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:93 +#, no-wrap +msgid "" +"# cd QVM\n" +"# qemu-img create -f qcow2 -o preallocation=full MyQemuVM 4G\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:96 +msgid "" +"Download or copy a FreeBSD installation DVD into the QVM directory and " +"rename it to *fbsd.iso*. Or, just link [.filename]#fbsd.iso# to an existing " +"DVD." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:101 +msgid "" +"Set up networking QEMU has an internal legacy based SLiRP protocol that uses " +"an internal DHCP server. Also available are the FreeBSD man:tap[4] and man:" +"if_bridge[4] interfaces to connect to a local network. This example will " +"install without a network interface, and add it later." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:103 +msgid "" +"Once the image file is complete, enter these commands to start up the " +"virtual machine:" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:115 +#, no-wrap +msgid "" +" /usr/local/bin/qemu-system-x86_64 -monitor stdio \\\n" +" -cpu qemu64 \\\n" +" -vga std \\\n" +" -m 4096 \\\n" +" -smp 2 \\\n" +" -cdrom fbsd.iso \\\n" +" -boot order=cd,menu=on \\\n" +" -blockdev driver=file,aio=threads,node-name=fbsdimg,filename=MyQemuVM.qcow2 \\\n" +" -blockdev driver=qcow2,node-name=drive0,file=fbsdimg \\\n" +" -device virtio-blk-pci,drive=drive0,bootindex=1 \\\n" +" -name \\\"FreeBSD\\\"\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:119 +msgid "" +"The virtual machine should start in a console window and load the FreeBSD " +"installation DVD. Install the system as usual, but select UFS as the " +"filesystem. If ZFS is preferred, increase the amount of memory (`-m " +"parameter`)." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:122 +msgid "" +"To add networking, configure a man:tap[4] device as `tap0`, and an man:" +"if_bridge[4] device as `bridge0` as shown in the crossref:ipfw-" +"introduction[ipfw-introduction-quickstart, Quick Start] section. To add the " +"`tap0` and `bridge0` devices to the above configuration, add these two lines " +"above the `-name` line:" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:125 +#, no-wrap +msgid "" +"-netdev tap,id=nd0,ifname=tap0,script=no,downscript=no,br=bridge0 \\\n" +"-device e1000,netdev=nd0,mac=02:55:33:12:34:56 \\\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:128 +msgid "" +"To use DHCP on the local network, add the host interface (em0, bge0, etc.) " +"to the bridge. For example, to add an `em0` host interface use:" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:130 +#, no-wrap +msgid "# ifconfig bridge0 addm em0\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:133 +msgid "" +"For additional information, check the other resources noted above. The " +"given examples should work." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-a/_index.adoc:136 +msgid "" +"indexterm:[qcow2] indexterm:[fbsd.iso] indexterm:[SLiRP] indexterm:[tap] " +"indexterm:[bridge] indexterm:[UFS] indexterm:[ZFS] indexterm:[DHCP]" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc @@ -0,0 +1,2302 @@ +--- +title: Appendix B. Scripts and Code for QEMU Lab +prev: books/ipfw-primer/ipfw-appendix-a +next: books/ipfw-primer/ipfw-appendix-c +description: Scripts and Code for QEMU Lab +tags: ["firewall", "IPFW", "Virtual Machine", "VM", "QEMU"] +showBookMenu: true +weight: 100 +path: "/books/ipfw-primer/ipfw-appendix-b/" +--- + +[appendix] +[[appendix-b]] += Appendix B: Scripts and Code for QEMU Lab +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: B +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + + +The listing below shows how the scripts are organized on the link:https://github.com/jimmyb-gh/ipfw-primer/tree/main/ipfw/SCRIPTS[GitHub ipfw-primer/SCRIPTS] site. +indexterm:[github] + +[subs=+quotes] +---- +. +|-- VM_SCRIPTS +| |-- IPFW_root_bin.tgz : common scripts for all VMs (see bin list) +| |-- Manifest_IPFW_root_bin.txt : Manifest document for IPFW_root_bin.tgz +| |-- Manifest_index.txt : Manifest document for index.html files +|-- bin +| |-- tcon.sh : TCP connection script +| |-- tconr.sh : TCP connect with random port script +| |-- tcont.sh : TCP continuous connection script +| |-- tserv.sh : TCP server script for one port +| |-- tserv3.sh : TCP server script for three ports +| |-- ucon.sh : UDP connection script +| |-- uconr.sh : UDP connect with random port script +| |-- ucont.sh : UDP continuous connection script +| |-- userv.sh : UDP server script for one port +| |-- userv3.sh : UDP server script for three ports +| `-- userv5.sh : UDP server script for five ports +| |-- dnshost : +| | |-- Manifest_namedb.txt : Manifest for dnshost /usr/local/etc/namedb +| | |-- dnshost_usrlocaletc_namedb.tgz : Files for the above +| | `-- index.html : Nginx index.html file for dnshost VM +| |-- external1 : +| | `-- index.html : Nginx index.html file for external1 VM +| |-- external2 : +| | `-- index.html : Nginx index.html file for external2 VM +| |-- external3 : +| | `-- index.html : Nginx index.html file for external3 VM +| |-- firewall : +| | |-- bsdclat464.sh : Script for Section 6.2 XLAT464 CLAT +| | `-- index.html : Nginx index.html file for firewall VM +| |-- firewall2 : +| | |-- bsdplat464.sh : Script for Section 6.2 XLAT464 CLAT +| | `-- index.html : Nginx index.html file for firewall2 VM +| |-- internal : +| | `-- index.html : Nginx index.html file for internal VM +| |-- v6only : +| | `-- index.html : Nginx index.html file for v6only VM +| `-- jail1 : +| `-- index.html : Nginx index.html file for jail1 VM +|-- _CreateAllVMs.sh : Script to create all VMs used in book +|-- dnshost.sh : QEMU startup script for dnshost VM +|-- external1.sh : QEMU startup script for external1 VM +|-- external2.sh : QEMU startup script for external2 VM +|-- external3.sh : QEMU startup script for external3 VM +|-- firewall.sh : QEMU startup script for firewall VM +|-- firewall2.sh : QEMU startup script for firewall2 VM +|-- internal.sh : QEMU startup script for internal VM +|-- jail1.sh : QEMU startup script for jail1 VM +|-- mkbr.sh : Script to make host bridge and tap devices +|-- runvm.sh : XFCE4 script to start VMs +|-- swim.sh : Script to manage serial terminals on host +|-- scim.sh : Script to manage serial terminals on host +|-- v6only.sh : QEMU startup script for v6only VM +|-- vm_envs.sh : IPFW lab environment variables +`-- CODE + `-- divert.c : C code for working with divert keyword +---- + +indexterm:[tcon.sh] indexterm:[tconr.sh] indexterm:[tcont.sh] indexterm:[tserv.sh] indexterm:[tserv3.sh] indexterm:[ucon.sh] indexterm:[uconr.sh] indexterm:[ucont.sh] indexterm:[userv.sh] indexterm:[userv3.sh] indexterm:[userv5.sh] indexterm:[dnshost.sh] indexterm:[external1.sh] indexterm:[external2.sh] indexterm:[external3.sh] indexterm:[firewall.sh] indexterm:[firewall2.sh] indexterm:[internal.sh] indexterm:[jail1.sh] indexterm:[mkbr.sh] indexterm:[runvm.sh] indexterm:[swim.sh] indexterm:[scim.sh] indexterm:[v6only.sh] indexterm:[vm_envs.sh] indexterm:[divert.c] + +All scripts are shown below in lexicographic order: + +[subs=+quotes] +---- + +*SCRIPT: VM_SCRIPTS/firewall/bsdclat464.sh* + +\#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD 464XLAT CLAT script for firewall VM. +# +# bsdclat464.sh: FreeBSD IPFW script for 464XLAT CLAT. See Section 6.2 +# Usage: # /bin/sh bsdclat464.sh (run script as root) + +set -x + +kldunload ipfw_nat64 +kldunload ipfw +sleep 1 +kldload ipfw +kldload ipfw_nat64 + +# Create the nat64clat instance +ipfw nat64clat CLAT create clat_prefix 2001:db8:aaaa::/96 plat_prefix 2001:db8:bbbb::/96 allow_private log + +# Allow neighbor discovery +ipfw add 100 allow log icmp6 from any to any icmp6types 135,136 + +# pass any ip through the nat64clat instance +ipfw add 150 nat64clat CLAT log ip from any to any + +# pass any ip through the nat64plat instance +ipfw add 200 nat64clat CLAT log ip from any to 2001:db8:bbbb::/96 + +# allow ipv6 from any to any +ipfw add 300 allow log ip6 from any to any + +# allow ipv4 from any to any +ipfw add 400 allow log ip from any to any + +# 0=log with ipfwlog0, 1=log with syslog +sysctl net.inet.ip.fw.verbose=0 + +sysctl net.inet.ip.fw.nat64_debug=1 + +# direct output: 1 enable, 0 disable (packet goes back into ruleset) +sysctl net.inet.ip.fw.nat64_direct_output=1 + +indexterm:[bsdclat464.sh] + +========================================================== + + +*SCRIPT: VM_SCRIPTS/firewall2/bsdplat464.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD 464XLAT PLAT script for firewall2 VM. +# +# bsdplat464.sh: FreeBSD IPFW script for 464XLAT CLAT. See Section 6.2 +# Usage: # /bin/sh bsdplat464.sh (run script as root) + +set -x + +kldunload ipfw_nat64 +kldunload ipfw + +sleep 1 + +kldload ipfw +kldload ipfw_nat64 + +# create the nat64 stateful instance +ipfw nat64lsn NAT64 create log prefix4 203.0.112.0/24 prefix6 2001:db8:bbbb::/96 allow_private + +# Allow neighbor discovery +ipfw add allow log icmp6 from any to any icmp6types 135,136 + +# Allow the nat64 outbound +ipfw add nat64lsn NAT64 log ip from 2001:db8:12::/64 to 2001:db8:bbbb::/96 in + +ipfw add nat64lsn NAT64 log ip from any to 2001:db8:bbbb::/96 in + +# Allow the nat64 inbound +ipfw add nat64lsn NAT64 log ip from any to 203.0.112.0/24 in + +# Allow ipv4 from any to any +ipfw add allow log ip from any to any + +# Allow ipv6 from any to any +ipfw add allow log ip6 from any to any + +# Logging: 0 interfaces, 1 syslog +sysctl net.inet.ip.fw.verbose=0 + +# Debug nat64 +sysctl net.inet.ip.fw.nat64_debug=1 + +# Direct output: 1 enable, 0 disable (packet goes back into ruleset) +sysctl net.inet.ip.fw.nat64_direct_output=1 + +indexterm:[bsdplat464.sh] + +========================================================== + + +*SCRIPT: \_CreateAllVMs.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# _CreateAllVM.sh : Create VMs for the IPFW Primer lab. +# Files are created in ../VM/ +# + +echo "Running _CreateAllVMs.sh" + +echo +echo "This script will create 8 virtual machines in ../VM/" +echo +read -p "DO YOU REALLY WANT TO CREATE NEW QEMU IMAGES OVERWRITING ANY EXISTING IMAGES? Answer YES to continue. " junk +echo [${junk}] + +if [ "X${junk}" != "XYES" ] +then + echo "Response was [${junk}]" + echo "bailing out..." + exit 1 +fi + +echo "Response was [${junk}]" +echo "Ok, continuing..." + +#exit + + +for i in dnshost external1 external2 external3 firewall firewall2 internal v6only +do + echo "Creating ${i} VM" + echo qemu-img create -f qcow2 -o preallocation=full ../VM/${i}.qcow2 4G + qemu-img create -f qcow2 -o preallocation=full ../VM/${i}.qcow2 4G +done + +echo +echo "Done." + + +========================================================== + + +*SCRIPT: tcon.sh* + + +#!/bin/sh +# +# location: external Vms +# +# sh tcon.sh PORTNUM - start up 1 connection over TCP +# + +usage() { + echo "sh tcon.sh PORTNUM" + exit 1 +} + + +#echo $# + +if [ $# -ne 1 ] +then + usage +else + export PORT1=$1 +fi + +# echo "PORT1 = [$PORT1]" + +export CONN="203.0.113.50" +export COUNT=1 + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` +export MYNAME="external1" + +echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" +echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 + +export PREVIOUS_PORT=$PORT1 + +while : +do + + COUNT=`expr $COUNT + 1` + + read -p "ncat [$COUNT] ready. Enter a valid PORTNUM: " PORT1 + + if [ "X$PORT1" = "X" ] + then + PORT1=$PREVIOUS_PORT + fi + + echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" + echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 + + if [ $? -ne 0 ] + then + echo "TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED" + fi + + PREVIOUS_PORT=$PORT1 + +done + + +========================================================== + + +*SCRIPT: tconr.sh* + +\#!/bin/sh +# +# location: external Vms +# +# sh tconr.sh PORTNUM SLEEPVAL (randomized port numbers) - start up 1 connection over TCP +# + +usage() { + echo "sh tconr.sh PORT1NUM SLEEPVAL (randomized port numbers)" + exit 1 +} + +# echo $# + +if [ $# -ne 2 ] + then + usage +fi + +PORT1=$1 +SLEEPVAL=$2 + +echo "PORT1 = [$PORT1]" +echo "SLEEPVAL = [$SLEEPVAL]" + +export CONN="203.0.113.50" +export COUNT=1 +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` +export MYNAME="external1" + +echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" +echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 + +while : +do + +COUNT=`expr $COUNT + 1` + +# use jot(1) to get a random port between 5656 and 5659. +# Connection to 5659 has no listener on firewall and will thus fail. + + PORT1=`jot -r 1 5656 5659 $RANDOM` + + echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" + echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 + + if [ $? -ne 0 ] + then + echo "TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED" + fi + + sleep $SLEEPVAL + +done + + +========================================================== + + +*SCRIPT: tcont.sh* + +\#!/bin/sh +# +# location: external Vms +# +# sh tcont.sh PORT1NUM SLEEPVAL - keep hammering same TCP port every SLEEPVAL +# + +usage() { + echo "sh tcont.sh PORT1NUM SLEEPVAL" + exit 1 +} + +#echo $# + +if [ $# -ne 2 ] + then + usage +fi + + +export PORT1=$1 +export SLEEPVAL=$2 + +echo "PORT1 = [$PORT1]" +echo "SLEEPVAL = [$SLEEPVAL]" + +export CONN="203.0.113.50" +export COUNT=1 +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` + + + +echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" +echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 + +while : +do + + COUNT=`expr $COUNT + 1` + + echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]" + echo "TCP connection from [$MYIP],[$PORT1],[$COUNT]"| ncat $CONN $PORT1 + + if [ $? -ne 0 ] + then + echo "TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED" + fi + + sleep $SLEEPVAL + +done + + +========================================================== + + +*SCRIPT: tserv.sh* + +\#!/bin/sh +# +# location: firewall VMs +# +# tserv.sh - start up 1 listener over TCP + +zapall() { +kill -TERM $PID1 +} + +trap zapall SIGINT + + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` + +export PORT1=5656 + +echo "Starting TCP listener on [$PORT1]" + +ncat -l -4 -k $MYIP $PORT1 & +PID1=$! + +wait + +exit + + +========================================================== + + +*SCRIPT: tserv3.sh* + +#!/bin/sh +# +# location: firewall VMs +# +# tserv3.sh - start up 3 listeners over TCP + +zapall() { +kill -TERM $PID1 $PID2 $PID3 +} + +trap zapall SIGINT + + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` + +export PORT1=5656 +export PORT2=5657 +export PORT3=5658 + +echo "Starting TCP listeners on [$PORT1],[$PORT2],[$PORT3]" + +ncat -l -4 -k $MYIP $PORT1 & +PID1=$! + +ncat -l -4 -k $MYIP $PORT2 & +PID2=$! + +ncat -l -4 -k $MYIP $PORT3 & +PID3=$! + +wait + +exit + + +========================================================== + + +*SCRIPT: ucon.sh* + +#!/bin/sh +# +# location: external Vms +# +# sh ucon.sh PORTNUM - start up 1 transfer over UDP +# + +usage() { + echo "sh ucon.sh PORTNUM" + exit 1 +} + +#echo $# + +if [ $# -ne 1 ] +then + usage +else + export PORT1=$1 +fi + +# echo "PORT1 = [$PORT1]" + +export CONN="203.0.113.50" +# export CONN="10.10.10.50" +export COUNT=1 + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` +export MYNAME="external1" + +echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" +echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + +export PREVIOUS_PORT=$PORT1 + +while : +do + + COUNT=`expr $COUNT + 1` + + read -p "ncat [$COUNT] ready. Enter a valid PORTNUM: " PORT1 + + if [ "X$PORT1" = "X" ] + then + PORT1=$PREVIOUS_PORT + fi + + echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" + echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + + if [ $? -ne 0 ] + then + echo "UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED" + fi + + PREVIOUS_PORT=$PORT1 + +done + + +========================================================== + + +*SCRIPT: uconr.sh* + +\#!/bin/sh +# +# location: external Vms +# + +usage() { + echo "sh uconr.sh PORT1NUM SLEEPVAL (randomized port numbers)" + exit 1 +} + + +# echo $# + +if [ $# -ne 2 ] + then + usage +fi + + +PORT1=$1 +SLEEPVAL=$2 + + +echo "PORT1 = [$PORT1]" +echo "SLEEPVAL = [$SLEEPVAL]" + + +export CONN="203.0.113.50" +export COUNT=1 +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` +export MYNAME="external1" + + +echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" +echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + +while : +do + +COUNT=`expr $COUNT + 1` + +# use jot(1) to get a random port between 5656 and 5659. +# Packet on 5659 has no listener on firewall and will thus fail. + + PORT1=`jot -r 1 5656 5659 $RANDOM` + + echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" + echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + + if [ $? -ne 0 ] + then + echo "UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED" + fi + + sleep $SLEEPVAL + +done + + +========================================================== + + +*SCRIPT: ucont.sh* + +\#!/bin/sh +# +# location: external Vms +# +# sh ucont.sh PORT1NUM SLEEPVAL - keep hammering same UDP port every SLEEPVAL +# + +usage() { + echo "sh ucont.sh PORT1NUM SLEEPVAL" + exit 1 +} + +#echo $# + +if [ $# -ne 2 ] + then + usage +fi + + +export PORT1=$1 +export SLEEPVAL=$2 + +echo "PORT1 = [$PORT1]" +echo "SLEEPVAL = [$SLEEPVAL]" + +# export CONN="10.10.10.50" +export CONN="203.0.113.50" +export COUNT=1 +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` + +echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" +echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + +while : +do + + COUNT=`expr $COUNT + 1` + +# echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" +# echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + + echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]" + echo "UDP packet from [$MYIP],[$PORT1],[$COUNT]"| ncat -u $CONN $PORT1 + + if [ $? -ne 0 ] + then + echo "UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED" + fi + + sleep $SLEEPVAL + +done + + +========================================================== + + +*SCRIPT: userv.sh* + +\#!/bin/sh +# +# location: firewall VMs +# +# userv.sh PORTNUM - start up 1 listener over UDP +# + +usage() { + echo "sh userv.sh PORTNUM" + exit 1 +} + +#echo $# + +if [ $# -ne 1 ] +then + usage +else + PORT1=$1 +fi + +echo "PORT1 = [$PORT1]" + +zapall() { +kill -TERM $PID1 +} + +trap zapall SIGINT + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` + + +echo "Starting UDP listener on [$MYIP],[$PORT1]" + +# echo nc -l -k -u $MYIP $PORT1 +nc -l -k -u $MYIP $PORT1 & +PID1=$! + +wait + +exit + + +========================================================== + + +*SCRIPT: userv3.sh* + + +\#!/bin/sh +# +# location: firewall VMs +# +# userv3.sh - start up 3 listeners over udp + +zapall() { +kill -TERM $PID1 $PID2 $PID3 +} + +trap zapall SIGINT + + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` + +export PORT1=5656 +export PORT2=5657 +export PORT3=5658 + + +echo "Starting UDP listeners on [$PORT1],[$PORT2],[$PORT3]" + +nc -l -k -u $MYIP $PORT1 & +PID1=$! + +nc -l -k -u $MYIP $PORT2 & +PID2=$! + +nc -l -k -u $MYIP $PORT3 & +PID3=$! + +wait + +exit + + +========================================================== + + +*SCRIPT: userv5.sh* + +#!/bin/sh +# +# location: firewall VMs +# +# userv5.sh - start up 5 listeners over udp + +zapall() { +kill -TERM $PID1 $PID2 $PID3 $PID4 $PID5 +} + +trap zapall SIGINT + + +export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'` +export PORT1=5656 +export PORT2=5657 +export PORT3=5658 +export PORT4=5659 +export PORT5=5660 + + +echo "Starting UDP listeners on [$PORT1],[$PORT2],[$PORT3],[$PORT4],[$PORT5]" + +nc -l -k -u $MYIP $PORT1 & +PID1=$! + +nc -l -k -u $MYIP $PORT2 & +PID2=$! + +nc -l -k -u $MYIP $PORT3 &cd +PID3=$! + +nc -l -k -u $MYIP $PORT4 & +PID4=$! + +nc -l -k -u $MYIP $PORT5 & +PID5=$! + +wait + +exit + + +========================================================== + + +*SCRIPT: dnshost.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for dnshost VM. +# +# dnshost.sh: FreeBSD QEMU VM startup script for dnshost VM. +# Usage: sudo /bin/sh dnshost.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [ISO=${_DNSHOST_ISO}] +echo [mem=${_DNSHOST_mem}] +echo [hdsize=${_DNSHOST_hdsize}] +echo [img=${_DNSHOST_img}] +echo [mac1=${_DNSHOST_mac1}] +echo [mac2=${_DNSHOST_mac2}] +echo [name=${_DNSHOST_name}] +echo [tap7=${_DNSHOST_tap7}] +echo [tap8=${_DNSHOST_tap8}] +echo [tap11=${_DNSHOST_tap11}] +echo [telnetport=${_DNSHOST_telnetport}] + +#exit + +# Note - the dnshost has two interfaces - em0 and em1. +# em0 is considered the ipv4 interface and +# em1 is considered the ipv6 interface. + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_DNSHOST_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_DNSHOST_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_DNSHOST_mem} \ + -cdrom ${_DNSHOST_ISO} \ + -boot order=cd,menu=on,splash=${_DNS_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_DNSHOST_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_DNSHOST_tap7},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_DNSHOST_mac1} \ + -netdev tap,id=nd1,ifname=${_DNSHOST_tap8},script=no,downscript=no \ + -device e1000,netdev=nd1,mac=${_DNSHOST_mac2} \ + -netdev tap,id=nd2,ifname=${_DNSHOST_tap11},script=no,downscript=no \ + -device e1000,netdev=nd2,mac=${_DNSHOST_mac3} \ + -name \"${_DNSHOST_name}\" & + + +========================================================== + + +*SCRIPT: external1.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for external1 VM. +# +# external1.sh: FreeBSD QEMU VM startup script for external1 VM. +# Usage: sudo /bin/sh external1.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +# FreeBSD QEMU VM startup script +# +# external1.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [$_EXTERNAL1_ISO] +echo [$_EXTERNAL1_mem] +echo [$_EXTERNAL1_hdsize] +echo [$_EXTERNAL1_img] +echo [$_EXTERNAL1_mac] +echo [$_EXTERNAL1_name] +echo [$_EXTERNAL1_tap1] +echo [$_EXTERNAL1_telnetport] + +# +#exit +# + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL1_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_EXTERNAL1_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_EXTERNAL1_mem} \ + -cdrom ${_EXTERNAL1_ISO} \ + -boot order=cd,menu=on,splash=${_EX1_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL1_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_EXTERNAL1_tap1},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_EXTERNAL1_mac} \ + -name \"${_EXTERNAL1_name}\" & + + +========================================================== + + +*SCRIPT: external2.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for external2 VM. +# +# external2.sh: FreeBSD QEMU VM startup script for external2 VM. +# Usage: sudo /bin/sh external2.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# + +# FreeBSD qemu vm startup script +# +# external2.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [ISO=${_EXTERNAL2_ISO}] +echo [mem=${_EXTERNAL2_mem}] +echo [hdsize=${_EXTERNAL2_hdsize}] +echo [img=${_EXTERNAL2_img}] +echo [mac=${_EXTERNAL2_mac}] +echo [name=${_EXTERNAL2_name}] +echo [tap2=${_EXTERNAL2_tap2}] +echo [telnetport=${_EXTERNAL2_telnetport}] + +# +#exit +# + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL2_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_EXTERNAL2_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_EXTERNAL2_mem} \ + -cdrom ${_EXTERNAL2_ISO} \ + -boot order=cd,menu=on,splash=${_EX2_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL2_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_EXTERNAL2_tap2},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_EXTERNAL2_mac} \ + -name \"${_EXTERNAL2_name}\" & + + +========================================================== + + +*SCRIPT: external3.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for external3 VM. +# +# external3.sh: FreeBSD QEMU VM startup script for external3 VM. +# Usage: sudo /bin/sh external3.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +# FreeBSD QEMU VM startup script +# +# external3.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [ISO=${_EXTERNAL3_ISO}] +echo [mem=${_EXTERNAL3_mem}] +echo [hdsize=${_EXTERNAL3_hdsize}] +echo [img=${_EXTERNAL3_img}] +echo [mac=${_EXTERNAL3_mac}] +echo [name=${_EXTERNAL3_name}] +echo [tap3=${_EXTERNAL3_tap3}] +echo [telnetport=${_EXTERNAL3_telnetport}] + +# +#exit +# + + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL3_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_EXTERNAL3_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_EXTERNAL3_mem} \ + -cdrom ${_EXTERNAL3_ISO} \ + -boot order=cd,menu=on,splash=${_EX3_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL3_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_EXTERNAL3_tap3},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_EXTERNAL3_mac} \ + -name \"${_EXTERNAL3_name}\" & + + + + + +========================================================== + + +*SCRIPT: firewall.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for firewall VM. +# +# firewall.sh: FreeBSD QEMU VM startup script for firewall VM. +# Usage: sudo /bin/sh firewall.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +# FreeBSD QEMU VM startup script +# +# firewall.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [$_FIREWALL_ISO] +echo [$_FIREWALL_mem] +echo [$_FIREWALL_hdsize] +echo [$_FIREWALL_img] +echo [$_FIREWALL_mac1] +echo [$_FIREWALL_mac2] +echo [$_FIREWALL_name] +echo [$_FIREWALL_tap0] +echo [$_FIREWALL_tap4] +echo [$_FIREWALL_telnetport] + +#exit + +# Note - the firewall has two interfaces - em0 and em1. +# em0 is considered the 'external' interface and +# em1 is considered the 'internal' interface. + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_FIREWALL_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_FIREWALL_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -display gtk \ + -vga cirrus \ + -m ${_FIREWALL_mem} \ + -cdrom ${_FIREWALL_ISO} \ + -boot order=cd,menu=on,splash=${_FW_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_FIREWALL_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_FIREWALL_tap0},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_FIREWALL_mac1} \ + -netdev tap,id=nd1,ifname=${_FIREWALL_tap4},script=no,downscript=no \ + -device e1000,netdev=nd1,mac=${_FIREWALL_mac2} \ + -name \"${_FIREWALL_name}\" & + + +========================================================== + + +*SCRIPT: firewall2.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for firewall2 VM. +# +# firewall2.sh: FreeBSD QEMU VM startup script for firewall2 VM. +# Usage: sudo /bin/sh firewall2.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +# FreeBSD QEMU VM startup script +# +# firewall2.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [ISO=${_FIREWALL2_ISO}] +echo [mem=${_FIREWALL2_mem}] +echo [hdsize=${_FIREWALL2_hdsize}] +echo [img=${_FIREWALL2_img}] +echo [mac1=${_FIREWALL2_mac1}] +echo [mac2=${_FIREWALL2_mac2}] +echo [name=${_FIREWALL2_name}] +echo [tap9=${_FIREWALL2_tap9}] +echo [tap10=${_FIREWALL2_tap10}] +echo [telnetport=${_FIREWALL2_telnetport}] + +#exit + +# Note - the firewall has two interfaces - em0 and em1. +# em0 is considered the 'external' interface and +# em1 is considered the 'internal' interface. + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_FIREWALL2_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_FIREWALL2_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -display gtk \ + -vga cirrus \ + -m ${_FIREWALL2_mem} \ + -cdrom ${_FIREWALL_ISO} \ + -boot order=cd,menu=on,splash=${_FW2_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_FIREWALL2_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_FIREWALL2_tap9},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_FIREWALL2_mac1} \ + -netdev tap,id=nd1,ifname=${_FIREWALL2_tap10},script=no,downscript=no \ + -device e1000,netdev=nd1,mac=${_FIREWALL2_mac2} \ + -name \"${_FIREWALL2_name}\" & + + +========================================================== + + +*SCRIPT: internal.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for internal VM. +# +# internal.sh: FreeBSD QEMU VM startup script for internal VM. +# Usage: sudo /bin/sh internal.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +# FreeBSD QEMU VM startup script +# +# internal.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + + +echo [ISO=${_INTERNAL_ISO}] +echo [mem=${_INTERNAL_mem}] +echo [hdsize=${_INTERNAL_hdsize}] +echo [img=${_INTERNAL_img}] +echo [mac=${_INTERNAL_mac}] +echo [name=${_INTERNAL_name}] +echo [tap5=${_INTERNAL_tap5}] +echo [telnetport=${_INTERNAL_telnetport}] + +# +#exit + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_INTERNAL_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${\_INTERNAL_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_INTERNAL_mem} \ + -cdrom ${_INTERNAL_ISO} \ + -boot order=cd,menu=on,splash=${_INT_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_INTERNAL_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_INTERNAL_tap5},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_INTERNAL_mac} \ + -name \"${_INTERNAL_name}\" & + + +========================================================== + + +#!/bin/sh +# FreeBSD qemu vm startup script +# +# jail1.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + +echo [ISO=${_JAIL1_ISO}] +echo [mem=${_JAIL1_mem}] +echo [hdsize=${_JAIL1_hdsize}] +echo [img=${_JAIL1_img}] +echo [mac=${_JAIL1_mac}] +echo [name=${_JAIL1_name}] +echo [tap2=${_JAIL1_tap2}] +echo [telnetport=${_JAIL1_telnetport}] + +# +#exit +# + +# minimal check that environment is sane +#if [ "X${_FBSD_ISO}" = "X" -o ! -s ${_FBSD_ISO} ] +#then +# echo "Parameter or file failure on _FBSD_ISO [${_FBSD_ISO}]" +# echo "Check vm_envs.sh" +# exit 1 +#fi +# +# + + +#echo +#echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_JAIL1_telnetport" +#echo +# -serial telnet:localhost:${_JAIL1_telnetport},server=on,wait=on \ + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_JAIL1_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_JAIL1_mem} \ + -cdrom ${_JAIL1_ISO} \ + -boot order=cd,menu=on,splash=${_JAIL1_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_JAIL1_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_JAIL1_tap12},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${\_JAIL1_mac} \ + -name \"${_JAIL1_name}\" & + + +========================================================== + + +*SCRIPT: mkbr.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD startup script for bridge and tap devices. +# +# mkbr.sh: FreeBSD startup script for bridge and tap devices. +# EXAMPLE Usage: sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 bridge2 tap3 tap4 tap5 em0 +# +# mkbr.sh - manage bridge and tap interfaces for FreeBSD. +# +# Have fun, but don't blame me if it smokes your machine. +# +# This script is used to start the bridge and tap interfaces. +# +# To create one bridge, two tap interfaces, and connect the +# local ethernet interace (here em0), run under sudo as follows: +# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 em0 +# +# The script can be used to create any number of bridges and taps +# for any internal network design: +# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 tap3 tap4 bridge2 tap5 em0 ... etc. +# +# To add other taps to existing bridges, do not specify the "reset" parameter. +# sudo /bin/sh mkbr.sh bridge0 tap10 tap11 bridge1 tap12 tap13 ... etc. +# +# To delete all bridge and tap devices: +# sudo /bin/sh mkbr.sh reset +# +# + +#set -x + + +usage() { + echo "Usage: mkbr.sh ["reset"] [[] ...]" + echo "You must be root to run this script." + exit 1 +} + + +if [ "X0" != "X`id -u`" ] +then + usage + fi + +if [ $# = 0 ] +then + usage; +fi + +if [ $1 = "reset" ] +then + echo + echo "Note - if_bridge and/or if_tap may be compiled into the kernel and can't be unloaded. Adjust interfaces manually if necessary." + echo + echo "unloading..." + kldunload if_bridge + kldunload if_tap + echo + echo "Deleting any remaining bridge and tap devices:" + + for i in `ifconfig -l` + do + echo "Interface: ${i}" + + case ${i} in + + bridge*) + echo " ... destroying bridge ${i}" + ifconfig ${i} destroy + ;; + tap*) + echo " ... destroying tap ${i}" + ifconfig ${i} destroy + ;; + esac + done + + sleep 1 + echo "loading..." + kldload if_bridge + kldload if_tap + shift + RESET="Y" + echo "RESET=Y" + # Before using the tap devices in QEMU, two sysctls require adjustment: + sysctl net.link.tap.user_open=1 + sysctl net.link.tap.up_on_open=1 +else + RESET="N" + echo "RESET=N" +fi + + +PARAM=$1 + +while [ "X${PARAM}" != "X" ] +do +# echo "PARAM=[$PARAM]" + + case $PARAM in + + bridge*) BRIDGE=$1 + + # if [ "$RESET" = "Y" ] + # then + echo ifconfig $BRIDGE create + ifconfig $BRIDGE create + echo ifconfig $BRIDGE + ifconfig $BRIDGE + # fi + echo ifconfig $BRIDGE up + ifconfig $BRIDGE up + ;; + + tap*) TAP=$1 + # if [ "$RESET" = "Y" ] + # then + echo ifconfig $TAP create + ifconfig $TAP create + # fi + echo "ifconfig $BRIDGE addm $TAP " + ifconfig $BRIDGE addm $TAP + ;; + + \*) echo "\*** Checking to see if $1 is a valid interface" + TMPINT=$1 + RESULT="IS NOT" + for i in `ifconfig -l` + do +# echo $i + if [ "${i}X" = "${TMPINT}X" ] + then + echo "Found a valid interface: ${TMPINT} Adding it to the bridge. Check results." + echo "ifconfig $BRIDGE addm $TMPINT" + ifconfig $BRIDGE addm $TMPINT + RESULT="IS" + break; + else + echo -n "." + fi + done + + echo "Interface ${TMPINT} $RESULT a valid interface." + ;; + esac + + shift + PARAM=$1 +done + +exit 0 + + +========================================================== + + +*SCRIPT: runvm.sh* + +\#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for multiple VMs at once. +# +# runvm.sh: FreeBSD QEMU VM startup script for multiple VMs. +# EXAMPLE Usage: /bin/sh runvm.sh firewall external1 external2 internal +# +# location: FreeBSD Host +# +# runvm.sh - run virtual machines specified on the command line. +# +# To use this script, run mkbr.sh first to set up the bridge and +# tap configurations for the desired network architecture. +# +# NOTE: this script works best on XFCE4 desktop as it takes advantage of the +# xfce4-terminal and it's ability to use multiple tabs. +# +# >>>> It is unlikely to work on another desktop. <<<< +# +# Essentially, this script is a big case statement. It gets the +# command line names of the virtual machines and calls a function +# that starts the virtual machine. +# + + +# pick up environment for this run +. ./vm_envs.sh + + +#set -x + +#WKDIR=$HOME/LAB/SCRIPTS +export WKDIR=$HOME/ipfw + +echo "[${WKDIR}]" + + +usage() { + echo "Usage: /bin/sh runvm.sh vmname [vmname ...]" + echo "Each virtual machine opens up on xfce4-terminal with two tabs -" + echo " one for the qemu virtual machine, and one for the serial" + echo " terminal interface." + echo "" + exit 1 +} + + +CURDIR=`pwd` + +if [ "X${CURDIR}" != "X${WKDIR}/SCRIPTS" ] +then + usage; +fi + + +if [ $# = 0 ] +then + usage; +fi + +# Functions for each VM + +dnshost_vm () { + # DNS host + echo "in function: [${_DNSHOST_telnetport}]" + xfce4-terminal --window --geometry="80x24+50+50" --zoom="-1" \ + -T "${_DNSHOST_name}" -e "bash -c \"cd ${WKDIR}/SCRIPTS && sudo /bin/sh dnshost.sh ; bash\"" \ + --tab -T "${_DNSHOST_name}" -e "bash -c \"cd ${WKDIR}/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet -4 localhost ${_DNSHOST_telnetport}); bash\"" + return +} + +external1_vm () { + # external1 + echo "in function: [${_EXTERNAL1_telnetport}]" + xfce4-terminal --window --geometry="80x24+75+75" --zoom="-1" \ + -T "${_EXTERNAL1_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh external1.sh ; bash\"" \ + --tab -T "${_EXTERNAL1_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL1_telnetport}); bash\"" + return +} + +external2_vm () { + # external2 + echo "in function: [${_EXTERNAL2_telnetport}]" + xfce4-terminal --window --geometry="80x24+100+100" --zoom="-1" \ + -T "${_EXTERNAL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh external2.sh ; bash\"" \ + --tab -T "${_EXTERNAL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL2_telnetport}); bash\"" + return +} + +external3_vm () { + # external3 + echo "in function: [${_EXTERNAL3_telnetport}]" + xfce4-terminal --window --geometry="80x24+125+125" --zoom="-1" \ + -T "${_EXTERNAL3_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh external3.sh ; bash\"" \ + --tab -T "${_EXTERNAL3_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL3_telnetport}); bash\"" + return +} + +firewall_vm () { + # Firewall + echo "in function: [${_FIREWALL_telnetport}]" + xfce4-terminal --window --geometry="80x24+150+150" --zoom="-1" \ + -T "${_FIREWALL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh firewall.sh ; bash\"" \ + --tab -T "${_FIREWALL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh; telnet localhost ${_FIREWALL_telnetport}); bash\"" + return +} + +firewall2_vm () { + # Firewall2 + echo "in function: [${_FIREWALL2_telnetport}]" + xfce4-terminal --window --geometry="80x24+175+175" --zoom="-1" \ + -T "${_FIREWALL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh firewall2.sh ; bash\"" \ + --tab -T "${_FIREWALL2_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_FIREWALL2_telnetport}); bash\"" + return +} + +internal_vm () { + # internal + echo "in function: [${_INTERNAL_telnetport}]" + xfce4-terminal --window --geometry="80x24+200+200" --zoom="-1" \ + -T "${_INTERNAL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh internal.sh ; bash\"" \ + --tab -T "${_INTERNAL_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_INTERNAL_telnetport}); bash\"" + return +} + +v6only_vm () { + # v6only + echo "in function: [${_V6ONLY_telnetport}]" + xfce4-terminal --window --geometry="80x24+225+225" --zoom="-1" \ + -T "${_V6ONLY_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sudo /bin/sh v6only.sh ; bash\"" \ + --tab -T "${_V6ONLY_name}" -e "bash -c \"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_V6ONLY_telnetport}); bash\"" + return +} + + +# +# Startup the requested VMs +# + + +PARAM=$1 + +while [ "X${PARAM}" != "X" ] +do + echo "PARAM = [${PARAM}]" + + case ${PARAM} in + + dnshost) + echo "dnshost ..." + echo "_DNSHOST_telnetport = [${_DNSHOST_telnetport}]" + dnshost_vm + ;; + + external1) + echo "external1 ..." + echo "_EXTERNAL1_telnetport = [${_EXTERNAL1_telnetport}]" + external1_vm + ;; + + external2) + echo "external2 ..." + echo "_EXTERNAL2_telnetport = [${_EXTERNAL2_telnetport}]" + external2_vm + ;; + + external3) + echo "external3 ..." + echo "_EXTERNAL3_telnetport = [${_EXTERNAL3_telnetport}]" + external3_vm + ;; + + firewall) + echo "firewall ..." + echo "_FIREWALL_telnetport = [${_FIREWALL_telnetport}]" + firewall_vm + ;; + + firewall2) + echo "firewall2 ..." + echo "_FIREWALL2_telnetport = [${_FIREWALL2_telnetport}]" + firewall2_vm + ;; + + internal) + echo "internal ..." + echo "_INTERNAL_telnetport = [${_INTERNAL_telnetport}]" + internal_vm + ;; + + v6only) + echo "v6only ..." + echo "_V6ONLY_telnetport = [${_V6ONLY_telnetport}]" + v6only_vm + ;; + + \*) + echo "" + echo "*** ERROR: NO VM NAMED [$PARAM]" + echo "" + ;; + + esac + + shift + + sleep 3 + + PARAM=$1 +done + +exit 0 + + +========================================================== + + +*SCRIPT: swim.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# Serial Window Management Script Using tmux. (swim.sh) +# +# Usage: /bin/sh swim.sh +# Note: This program manages multiple serial termainal windows for QEMU +# VMs on the host. +# Make sure to uncomment the lines below for the windows you want. +#set -x + +# Check for an existing tmux session +tmux has-session -t 0 2>/dev/null + +if [ $? != 0 ]; then + tmux new-session -d -s 0 + + tmux new-window -t 0:1 -n 'firewall' 'echo; echo Use \"telnet localhost 4450\" for firewall ; echo; /bin/sh' + tmux new-window -t 0:2 -n 'external1' 'echo; echo Use \"telnet localhost 4410\" for external1; echo; /bin/sh' + tmux new-window -t 0:3 -n 'external2' 'echo; echo Use \"telnet localhost 4420\" for external2; echo; /bin/sh' + tmux new-window -t 0:4 -n 'external3' 'echo; echo Use \"telnet localhost 4430\" for external3; echo; /bin/sh' +# tmux new-window -t 0:5 -n 'internal' 'echo; echo Use \"telnet localhost 44200\" for internal; echo; /bin/sh' +# tmux new-window -t 0:6 -n 'firewall2' 'echo; echo Use \"telnet localhost 4250\" for firewall2; echo; /bin/sh' +# tmux new-window -t 0:7 -n 'v6only' 'echo; echo Use \"telnet localhost 4460\" for v6only; echo; /bin/sh' +# tmux new-window -t 0:8 -n 'dnshost' 'echo; echo Use \"telnet localhost 4453\" for dnshost; echo; /bin/sh' +# tmux new-window -t 0:9 -n 'jail1' 'echo; echo Use \"telnet localhost 4470\" for jail1; echo; /bin/sh' + + # Set the default command shell + set-option -g default-command "/bin/sh" +fi + +# Set the focus on window 0:0, your existing shell. +tmux select-window -t 0:0 + +# Attach to the session +tmux attach-session -t 0 + +exit + + +========================================================== + + +*SCRIPT: scim.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# Serial Window Management Script Using screen. (scim.sh) +# +# Usage: /bin/sh scim.sh +# Note: This program manages multiple serial termainal windows for QEMU VMs. +# Make sure to uncomment the lines below for the windows you want. +# +# Note: +# In order to show the status line for the list of active windows, +# this program requires a .screenrc file in the $HOME directory with +# the following directives: +# +# hardstatus alwayslastline +# hardstatus string "%{= bw}%-w%{= rW}[%n %t]%{-}%+w %=%{= kW} %H | %Y-%m-%d %c" +# + +screen -list 2> /dev/null + +# Check if the session is already live +if [ $? != 0 ]; then + + # Create a new session and add windows + screen -dmS newsession # Start a new session + + # Uncomment windows as needed. + screen -S newsession -X screen -t "firewall" sh -c "echo; echo Use \"telnet localhost 4450\" for firewall ; echo; /bin/sh" + screen -S newsession -X screen -t "external1" sh -c "echo; echo Use \"telnet localhost 4410\" for external1 ; echo; /bin/sh" + screen -S newsession -X screen -t "external2" sh -c "echo; echo Use \"telnet localhost 4420\" for external1 ; echo; /bin/sh" + screen -S newsession -X screen -t "external3" sh -c "echo; echo Use \"telnet localhost 4430\" for external1 ; echo; /bin/sh" +# screen -S newsession -X screen -t "internal" sh -c "echo; echo Use \"telnet localhost 44200\" for external1 ; echo; /bin/sh" +# screen -S newsession -X screen -t "firewall2" sh -c "echo; echo Use \"telnet localhost 4250\" for external1 ; echo; /bin/sh" +# screen -S newsession -X screen -t "v6only" sh -c "echo; echo Use \"telnet localhost 4460\" for external1 ; echo; /bin/sh" +# screen -S newsession -X screen -t "dnshost" sh -c "echo; echo Use \"telnet localhost 4453\" for external1 ; echo; /bin/sh" +# screen -S newsession -X screen -t "jail1" sh -c "echo; echo Use \"telnet localhost 4470\" for external1 ; echo; /bin/sh" + +# Focus on window 0 + screen -S newsession -X select 0 +fi + +# Light it up. +screen -x newsession -p 0 + + +========================================================== + + +*SCRIPT: v6only.sh* + +#!/bin/sh +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM startup script for v6only VM. +# +# v6only.sh: FreeBSD QEMU VM startup script for v6only VM. +# Usage: sudo /bin/sh v6only.sh +# Note: Set up for serial console. Start another session and telnet to the port shown. +# +# FreeBSD QEMU VM startup script +# +# v6only.sh +# +#set -x + +# pick up environment for this run +. ./vm_envs.sh + + +echo [ISO=${_V6ONLY_ISO}] +echo [mem=${_V6ONLY_mem}] +echo [hdsize=${_V6ONLY_hdsize}] +echo [img=${_V6ONLY_img}] +echo [mac=${_V6ONLY_mac}] +echo [name=${_V6ONLY_name}] +echo [tap6=${_V6ONLY_tap6}] +echo [telnetport=${_V6ONLY_telnetport}] + +# +#exit + +echo +echo "NOTE!!! telnet server running! To start QEMU telnet to localhost $_V6ONLY_telnetport" +echo + +/usr/local/bin/qemu-system-x86_64 -monitor none \ + -serial telnet:localhost:${_V6ONLY_telnetport},server=on,wait=off \ + -cpu qemu64 \ + -vga cirrus \ + -m ${_V6ONLY_mem} \ + -cdrom ${_V6ONLY_ISO} \ + -boot order=cd,menu=on,splash=${_V6_splash},splash-time=3000 \ + -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_V6ONLY_img} \ + -device virtio-blk,drive=drive0 \ + -netdev tap,id=nd0,ifname=${_V6ONLY_tap6},script=no,downscript=no \ + -device e1000,netdev=nd0,mac=${_V6ONLY_mac} \ + -name \"${_V6ONLY_name}\" & + + +========================================================== + + +*SCRIPT: vm_envs.sh* + +# IPFW Primer +# License: 3-clause BSD +# Author: Jim Brown, jpb@jimby.name +# Code: https://github.com/jimmyb-gh/ipfw-primer +# +# FreeBSD QEMU VM environment script. +# +# vmenv.sh: FreeBSD QEMU VM environment setup script. +# Usage: ./bin/sh vmenv.sh +# +# vm_envs.sh - environment for setting up virtual machines +# for the IPFW examples lab. +# +# Set the environment variables below (or keep the defaults) +# Note that the default disk size for each virtual machine is +# 4GB - so all five VMs will take up about 32GB if you preallocate +# space. +# +# In brief: +# +# Install FreeBSD on the host machine and update to latest patch level. +# Install desktop software. +# Install QEMU (latest) +# Install nmap (needed for ncat) +# Install sudo +# +# +# The script mkbr.sh should be run before starting +# the virtual machines. mkbr.sh sets up the bridge and tap +# devices needed by the VMs. +# +# sudo /bin/sh ./mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 em0 bridge1 tap4 tap5 +# +# This will set up the devices needed by QEMU. +# +# +#The file directory layout for the examples is: +# +# ~/ipfw +# /SCRIPTS +# _CreateAllVMs.sh (create Qemu disks images) +# dnshost.sh (run script for dns server VM) +# external1.sh (run scripts for external VMs) +# external2.sh " +# external3.sh " +# firewall.sh (run script for firewall VM) +# firewall2.sh (run script for firewall2 VM) +# internal.sh (script to setup internal host) +# jail1.sh (script to setup jail1 host) +# v6only.sh (run script for IPv6 only VM) +# mkbr.sh (script to create bridge and tap devices) +# vm_envs.sh (script to manage all parameters) +# runvm.sh (script to manage all virtual machines) +# /BMP +# dns_splash_640x480.bmp +# external1_splash_640x480.bmp +# external2_splash_640x480.bmp +# external3_splash_640x480.bmp +# internal_splash_640x480.bmp +# jail1_splash_640x480.bmp +# ipfw2_splash_640x480.bmp +# ipfw_splash_640x480.bmp +# v6only_splash_640x480.bmp +# dnshost_splash_640x480.bmp +# /ISO +# fbsd.iso (latest FreeBSD install iso) +# /VM +# dnshost.qcow2 (Qemu disk image for dns host) +# external1.qcow2 (Qemu disk image for external hosts) +# external2.qcow2 " +# external3.qcow2 " +# firewall.qcow2 (Qemu disk image for firewall) +# firewall2.qcow2 (Qemu disk image for firewall2) +# internal.qcow2 (Qemu disk image for an internal host) +# jail1.qcow2 (Qemu disk image for an jail1 host) +# v6only.qcow2 (Qemu disk image for an ipv6only host) +# +# +# Start the VMs and install / test one at a time. +# +# sudo /bin/sh firewall.sh +# sudo /bin/sh firewall2.sh +# sudo /bin/sh external1.sh +# sudo /bin/sh external2.sh +# sudo /bin/sh external3.sh +# sudo /bin/sh internal.sh +# sudo /bin/sh jail1.sh +# sudo /bin/sh v6only.sh +# sudo /bin/sh dnshost.sh +# +# Each install should first utilize DHCP to get a valid IP address +# After install, proceed to update FreeBSD with "freebsd-update fetch install" +# Install packages: +# Use whatever shell you prefer. Bash is listed below. +# Firewall - pkg install bash cmdwatch lynx iperf3 nmap hping3 nginx +# All others - pkg install bash cmdwatch lynx iperf3 nmap hping3 nginx +# DNS host - pkg install bind918 dual-dhclient bash cmdwatch lynx nginx +# +# Reset all IP addresses for static usage: +# +# Host interface: add 172.16.10.100/24 alias +# Disable any firewall (pf, ipfw, etc.) on the host. +# BE SURE this is Ok for your environment. +# +# Firewall em0 172.16.10.50/24, default gateway 172.16.10.100 +# em1 10.10.10.50/24 +# +# Firewall2 em0 as needed +# em1 as needed +# +# External1: em0 172.16.10.10/24, default gateway 172.16.10.100 +# External2: em0 172.16.10.20/24, default gateway 172.16.10.100 +# External3: em0 172.16.10.30/24, default gateway 172.16.10.100 +# Internal: em0 10.10.10.200/24, default gateway 10.10.10.50 +# +# v6only as needed +# dnshost as needed +# jail1 as needed +# +# + +export _BASE=/home/jpb/ipfw + +# Bridge and tap info +export _FIREWALL_tap0=tap0 +export _EXTERNAL1_tap1=tap1 +export _EXTERNAL2_tap2=tap2 +export _EXTERNAL3_tap3=tap3 +export _FIREWALL_tap4=tap4 +export _INTERNAL_tap5=tap5 +export _JAIL1_tap12=tap12 +export _V6ONLY_tap6=tap6 +export _DNSHOST_tap7=tap7 +export _DNSHOST_tap8=tap8 +export _FIREWALL2_tap9=tap9 +export _FIREWALL2_tap10=tap10 +export _DNSHOST_tap11=tap11 + +export _bridge0_=bridge0 +export _bridge1_=bridge1 +export _bridge2_=bridge2 + + +# Disk sizes +export _EXTERNAL1_hdsize=4G +export _EXTERNAL2_hdsize=4G +export _EXTERNAL3_hdsize=4G +export _FIREWALL_hdsize=4G +export _FIREWALL2_hdsize=4G +export _INTERNAL_hdsize=4G +export _JAIL1_hdsize=8G # Note larger size disk +export _V6ONLY_hdsize=4G +export _DNSHOST_hdsize=4G + +# Is this needed anymore? +export _FBSD_ISO=${_BASE}/ISO/fbsd.iso + +# Boot iso locations +export _DNSHOST_ISO=${_BASE}/ISO/fbsd.iso +export _EXTERNAL1_ISO=${_BASE}/ISO/fbsd.iso +export _EXTERNAL2_ISO=${_BASE}/ISO/fbsd.iso +export _EXTERNAL3_ISO=${_BASE}/ISO/fbsd.iso +export _FIREWALL_ISO=${_BASE}/ISO/fbsd.iso +export _FIREWALL2_ISO=${_BASE}/ISO/fbsd.iso +export _INTERNAL_ISO=${_BASE}/ISO/fbsd.iso +export _JAIL1_ISO=${_BASE}/ISO/fbsd.iso +export _V6ONLY_ISO=${_BASE}/ISO/fbsd.iso + +# Memory sizes +export _DNSHOST_mem=1024 +export _EXTERNAL1_mem=1024 # lower all to 512 if necessary +export _EXTERNAL2_mem=1024 +export _EXTERNAL3_mem=1024 +export _FIREWALL_mem=1024 +export _FIREWALL2_mem=1024 +export _INTERNAL_mem=1024 +export _JAIL1_mem=8192 # Note larger size memory for using ZFS +export _V6ONLY_mem=1024 + + +# Qemu disk image locations. +export _DNSHOST_img=${_BASE}/VM/dnshost.qcow2 +export _EXTERNAL1_img=${_BASE}/VM/external1.qcow2 +export _EXTERNAL2_img=${_BASE}/VM/external2.qcow2 +export _EXTERNAL3_img=${_BASE}/VM/external3.qcow2 +export _FIREWALL_img=${_BASE}/VM/firewall.qcow2 +export _FIREWALL2_img=${_BASE}/VM/firewall2.qcow2 +export _INTERNAL_img=${_BASE}/VM/internal.qcow2 +export _JAIL1_img=${_BASE}/VM/jail1.qcow2 +export _V6ONLY_img=${_BASE}/VM/v6only.qcow2 + +# MAC addresses +export _DNSHOST_mac1=02:49:53:53:53:53 +export _DNSHOST_mac2=02:49:53:53:54:54 +export _DNSHOST_mac3=02:49:53:53:55:55 +export _EXTERNAL1_mac=02:45:58:54:31:10 +export _EXTERNAL2_mac=02:45:58:54:32:20 +export _EXTERNAL3_mac=02:45:58:54:33:30 +export _FIREWALL_mac1=02:49:50:46:57:41 +export _FIREWALL2_mac1=02:49:50:00:22:22 +export _FIREWALL_mac2=02:49:50:46:57:42 +export _FIREWALL2_mac2=02:49:50:22:22:22 +export _INTERNAL_mac=02:49:4E:54:0a:42 +export _JAIL1_mac=02:49:ba:ad:ba:be +export _V6ONLY_mac=02:49:de:ad:be:ef + +# VM names +export _DNSHOST_name=DNSHOST +export _EXTERNAL1_name=EXTERNAL1 +export _EXTERNAL2_name=EXTERNAL2 +export _EXTERNAL3_name=EXTERNAL3 +export _FIREWALL_name=FIREWALL +export _FIREWALL2_name=FIREWALL2 +export _INTERNAL_name=INTERNAL +export _JAIL1_name=JAIL1 +export _V6ONLY_name=V6ONLY + +# Slash images +export _DNS_splash=${_BASE}/BMP/dns_splash_640x480.bmp +export _EX1_splash=${_BASE}/BMP/external1_splash_640x480.bmp +export _EX2_splash=${_BASE}/BMP/external2_splash_640x480.bmp +export _EX3_splash=${_BASE}/BMP/external3_splash_640x480.bmp +export _FW_splash=${_BASE}/BMP/ipfw_splash_640x480.bmp +export _FW2_splash=${_BASE}/BMP/ipfw2_splash_640x480.bmp +export _INT_splash=${_BASE}/BMP/internal_splash_640x480.bmp +export _JAIL1_splash=${_BASE}/BMP/jail1_splash_640x480.bmp +export _V6_splash=${_BASE}/BMP/ipv6_splash_640x480.bmp + +# +# Telnet ports +export _DNSHOST_telnetport=4453 +export _EXTERNAL1_telnetport=4410 +export _EXTERNAL2_telnetport=4420 +export _EXTERNAL3_telnetport=4430 +export _FIREWALL_telnetport=4450 +export _FIREWALL2_telnetport=4250 +export _INTERNAL_telnetport=44200 +export _V6ONLY_telnetport=4460 +export _JAIL1_telnetport=4470 + + +# Bridge and Tap configurations. +# +# Note: em0 is used for the host interface. +# Change as needed. +# +# Two bridge configuration +# Standard examples +# +# em0 +# | +# External1(tap1) -----bridge0------(tap0)Firewall +# External2(tap2) -----+ | (tap4) +# External3(tap3) -------+ | +# bridge1 +# | +# Internal(tap5) -----------------------------+ +# +# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 em0 +# +# +# +# Two bridge configuration +# NAT & LSNAT examples +# +# +# +# (firewall does LSNAT load balancing) +# External1(tap1) -----bridge0------(tap0)Firewall +# External2(tap2) -----+ | (tap4) +# External3(tap3) -------+ | +# (these function as internal machines) bridge1----em0 +# | +# Internal(tap5) -----------------------------+ +# (this functions as an external machine) +# +# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 bridge1 tap4 tap5 em0 +# +# +# +# Two bridge configuration +# NAT64/DNS64 example +# +# ipv4 only NAT64 Translator +# External1(tap1) ------bridge0-----(tap0)Firewall +# (ipv4 only) + (tap4) +# (webserver) | + +# dnshost(tap7) | +# (DNS server) | +# (running DNS64) | +# (tap8) | +# | | +# + | +# ipv6 only | +# v6only(tap6) --------bridge1----------------+ +# (v6 only host) +# +# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap7 bridge1 tap4 tap6 tap8 +# +# + + +========================================================== + + +*CODE: divert.c* + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DIVERT_PORT 700 + +void hexdump(void \*ptr, int length, const char *hdr, int flags); + +int +main(int argc, char *argv[]) +{ + int fd, s; + struct sockaddr_in sin; + socklen_t sin_len; + + + printf("Opening divert on port %d\n",DIVERT_PORT); + + fd = socket(PF_DIVERT, SOCK_RAW, 0); + if (fd == -1) + err(1, "socket"); + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(DIVERT_PORT); + sin.sin_addr.s_addr = 0; + + sin_len = sizeof(struct sockaddr_in); + + s = bind(fd, (struct sockaddr *) &sin, sin_len); + if (s == -1) + err(1, "bind"); + + for (;;) { + ssize_t n; + char packet[IP_MAXPACKET]; + struct ip *ip; + struct tcphdr *th; + int hlen; + char src[64], dst[64], printbuff[12]; + + + memset(src, 0, sizeof(src)); + memset(dst, 0, sizeof(dst)); + memset(printbuff, 0, sizeof(printbuff)); + + memset(packet, 0, sizeof(packet)); + n = recvfrom(fd, packet, sizeof(packet), 0, + (struct sockaddr *) &sin, &sin_len); + if (n == -1) { + warn("recvfrom"); + continue; + } + if (n < sizeof(struct ip)) { + warnx("packet is too short"); + continue; + } + + ip = (struct ip *) packet; + hlen = ip->ip_hl << 2; + if (hlen < sizeof(struct ip) || ntohs(ip->ip_len) < hlen || + n < ntohs(ip->ip_len)) { + warnx("invalid IPv4 packet"); + continue; + } + + th = (struct tcphdr *) (packet + hlen); + + if (inet_ntop(AF_INET, &ip->ip_src, src, + sizeof(src)) == NULL) + (void)strlcpy(src, "?", sizeof(src)); + + if (inet_ntop(AF_INET, &ip->ip_dst, dst, + sizeof(dst)) == NULL) + (void)strlcpy(dst, "?", sizeof(dst)); + + printf("%s:%u -> %s:%u\n", + src, + ntohs(th->th_sport), + dst, + ntohs(th->th_dport) + ); + + + /* + * dump the packet in hex and ascii with hexdump(3) + */ + + hexdump((void *)packet, n, "|",0); + + n = sendto(fd, packet, n, 0, (struct sockaddr *) &sin, + sin_len); + if (n == -1) + warn("sendto"); + } + + return 0; +} + +---- + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.po @@ -0,0 +1,3276 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1 +#, no-wrap +msgid "Scripts and Code for QEMU Lab" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1 +#, no-wrap +msgid "Appendix B. Scripts and Code for QEMU Lab" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:14 +#, no-wrap +msgid "Appendix B: Scripts and Code for QEMU Lab" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:55 +msgid "" +"The listing below shows how the scripts are organized on the link:https://" +"github.com/jimmyb-gh/ipfw-primer/tree/main/ipfw/SCRIPTS[GitHub ipfw-primer/" +"SCRIPTS] site. indexterm:[github]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:114 +#, no-wrap +msgid "" +".\n" +"|-- VM_SCRIPTS\n" +"| |-- IPFW_root_bin.tgz : common scripts for all VMs (see bin list)\n" +"| |-- Manifest_IPFW_root_bin.txt : Manifest document for IPFW_root_bin.tgz\n" +"| |-- Manifest_index.txt : Manifest document for index.html files\n" +"|-- bin\n" +"| |-- tcon.sh : TCP connection script\n" +"| |-- tconr.sh : TCP connect with random port script\n" +"| |-- tcont.sh : TCP continuous connection script\n" +"| |-- tserv.sh : TCP server script for one port\n" +"| |-- tserv3.sh : TCP server script for three ports\n" +"| |-- ucon.sh : UDP connection script\n" +"| |-- uconr.sh : UDP connect with random port script\n" +"| |-- ucont.sh : UDP continuous connection script\n" +"| |-- userv.sh : UDP server script for one port\n" +"| |-- userv3.sh : UDP server script for three ports\n" +"| `-- userv5.sh : UDP server script for five ports\n" +"| |-- dnshost :\n" +"| | |-- Manifest_namedb.txt : Manifest for dnshost /usr/local/etc/namedb\n" +"| | |-- dnshost_usrlocaletc_namedb.tgz : Files for the above\n" +"| | `-- index.html : Nginx index.html file for dnshost VM\n" +"| |-- external1 :\n" +"| | `-- index.html : Nginx index.html file for external1 VM\n" +"| |-- external2 :\n" +"| | `-- index.html : Nginx index.html file for external2 VM\n" +"| |-- external3 :\n" +"| | `-- index.html : Nginx index.html file for external3 VM\n" +"| |-- firewall :\n" +"| | |-- bsdclat464.sh : Script for Section 6.2 XLAT464 CLAT\n" +"| | `-- index.html : Nginx index.html file for firewall VM\n" +"| |-- firewall2 :\n" +"| | |-- bsdplat464.sh : Script for Section 6.2 XLAT464 CLAT\n" +"| | `-- index.html : Nginx index.html file for firewall2 VM\n" +"| |-- internal :\n" +"| | `-- index.html : Nginx index.html file for internal VM\n" +"| |-- v6only :\n" +"| | `-- index.html : Nginx index.html file for v6only VM\n" +"| `-- jail1 :\n" +"| `-- index.html : Nginx index.html file for jail1 VM\n" +"|-- _CreateAllVMs.sh : Script to create all VMs used in book\n" +"|-- dnshost.sh : QEMU startup script for dnshost VM\n" +"|-- external1.sh : QEMU startup script for external1 VM\n" +"|-- external2.sh : QEMU startup script for external2 VM\n" +"|-- external3.sh : QEMU startup script for external3 VM\n" +"|-- firewall.sh : QEMU startup script for firewall VM\n" +"|-- firewall2.sh : QEMU startup script for firewall2 VM\n" +"|-- internal.sh : QEMU startup script for internal VM\n" +"|-- jail1.sh : QEMU startup script for jail1 VM\n" +"|-- mkbr.sh : Script to make host bridge and tap devices\n" +"|-- runvm.sh : XFCE4 script to start VMs\n" +"|-- swim.sh : Script to manage serial terminals on host\n" +"|-- scim.sh : Script to manage serial terminals on host\n" +"|-- v6only.sh : QEMU startup script for v6only VM\n" +"|-- vm_envs.sh : IPFW lab environment variables\n" +"`-- CODE\n" +" `-- divert.c : C code for working with divert keyword\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:117 +msgid "" +"indexterm:[tcon.sh] indexterm:[tconr.sh] indexterm:[tcont.sh] indexterm:" +"[tserv.sh] indexterm:[tserv3.sh] indexterm:[ucon.sh] indexterm:[uconr.sh] " +"indexterm:[ucont.sh] indexterm:[userv.sh] indexterm:[userv3.sh] indexterm:" +"[userv5.sh] indexterm:[dnshost.sh] indexterm:[external1.sh] indexterm:" +"[external2.sh] indexterm:[external3.sh] indexterm:[firewall.sh] indexterm:" +"[firewall2.sh] indexterm:[internal.sh] indexterm:[jail1.sh] indexterm:[mkbr." +"sh] indexterm:[runvm.sh] indexterm:[swim.sh] indexterm:[scim.sh] indexterm:" +"[v6only.sh] indexterm:[vm_envs.sh] indexterm:[divert.c]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:119 +msgid "All scripts are shown below in lexicographic order:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:124 +#, no-wrap +msgid "*SCRIPT: VM_SCRIPTS/firewall/bsdclat464.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:135 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD 464XLAT CLAT script for firewall VM.\n" +"#\n" +"# bsdclat464.sh: FreeBSD IPFW script for 464XLAT CLAT. See Section 6.2\n" +"# Usage: # /bin/sh bsdclat464.sh (run script as root)\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:137 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:189 +#, no-wrap +msgid "set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:143 +#, no-wrap +msgid "" +"kldunload ipfw_nat64\n" +"kldunload ipfw\n" +"sleep 1\n" +"kldload ipfw\n" +"kldload ipfw_nat64\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:146 +#, no-wrap +msgid "" +"# Create the nat64clat instance\n" +"ipfw nat64clat CLAT create clat_prefix 2001:db8:aaaa::/96 plat_prefix 2001:db8:bbbb::/96 allow_private log\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:149 +#, no-wrap +msgid "" +"# Allow neighbor discovery\n" +"ipfw add 100 allow log icmp6 from any to any icmp6types 135,136\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:152 +#, no-wrap +msgid "" +"# pass any ip through the nat64clat instance\n" +"ipfw add 150 nat64clat CLAT log ip from any to any\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:155 +#, no-wrap +msgid "" +"# pass any ip through the nat64plat instance\n" +"ipfw add 200 nat64clat CLAT log ip from any to 2001:db8:bbbb::/96\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:158 +#, no-wrap +msgid "" +"# allow ipv6 from any to any\n" +"ipfw add 300 allow log ip6 from any to any\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:161 +#, no-wrap +msgid "" +"# allow ipv4 from any to any\n" +"ipfw add 400 allow log ip from any to any\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:164 +#, no-wrap +msgid "" +"# 0=log with ipfwlog0, 1=log with syslog\n" +"sysctl net.inet.ip.fw.verbose=0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:166 +#, no-wrap +msgid "sysctl net.inet.ip.fw.nat64_debug=1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:169 +#, no-wrap +msgid "" +"# direct output: 1 enable, 0 disable (packet goes back into ruleset)\n" +"sysctl net.inet.ip.fw.nat64_direct_output=1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:171 +#, no-wrap +msgid "indexterm:[bsdclat464.sh]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:173 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:230 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:277 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:343 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:404 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:462 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:494 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:534 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:599 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:663 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:723 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:771 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:813 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:861 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:923 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:980 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1038 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1099 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1163 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1227 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1284 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1340 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1502 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1725 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1773 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1830 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2137 +#, no-wrap +msgid "==========================================================\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:176 +#, no-wrap +msgid "*SCRIPT: VM_SCRIPTS/firewall2/bsdplat464.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:187 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD 464XLAT PLAT script for firewall2 VM.\n" +"#\n" +"# bsdplat464.sh: FreeBSD IPFW script for 464XLAT CLAT. See Section 6.2\n" +"# Usage: # /bin/sh bsdplat464.sh (run script as root)\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:192 +#, no-wrap +msgid "" +"kldunload ipfw_nat64\n" +"kldunload ipfw\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:194 +#, no-wrap +msgid "sleep 1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:197 +#, no-wrap +msgid "" +"kldload ipfw\n" +"kldload ipfw_nat64\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:200 +#, no-wrap +msgid "" +"# create the nat64 stateful instance\n" +"ipfw nat64lsn NAT64 create log prefix4 203.0.112.0/24 prefix6 2001:db8:bbbb::/96 allow_private\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:203 +#, no-wrap +msgid "" +"# Allow neighbor discovery\n" +"ipfw add allow log icmp6 from any to any icmp6types 135,136\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:206 +#, no-wrap +msgid "" +"# Allow the nat64 outbound\n" +"ipfw add nat64lsn NAT64 log ip from 2001:db8:12::/64 to 2001:db8:bbbb::/96 in\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:208 +#, no-wrap +msgid "ipfw add nat64lsn NAT64 log ip from any to 2001:db8:bbbb::/96 in\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:211 +#, no-wrap +msgid "" +"# Allow the nat64 inbound\n" +"ipfw add nat64lsn NAT64 log ip from any to 203.0.112.0/24 in\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:214 +#, no-wrap +msgid "" +"# Allow ipv4 from any to any\n" +"ipfw add allow log ip from any to any\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:217 +#, no-wrap +msgid "" +"# Allow ipv6 from any to any\n" +"ipfw add allow log ip6 from any to any\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:220 +#, no-wrap +msgid "" +"# Logging: 0 interfaces, 1 syslog\n" +"sysctl net.inet.ip.fw.verbose=0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:223 +#, no-wrap +msgid "" +"# Debug nat64\n" +"sysctl net.inet.ip.fw.nat64_debug=1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:226 +#, no-wrap +msgid "" +"# Direct output: 1 enable, 0 disable (packet goes back into ruleset)\n" +"sysctl net.inet.ip.fw.nat64_direct_output=1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:228 +#, no-wrap +msgid "indexterm:[bsdplat464.sh]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:233 +#, no-wrap +msgid "*SCRIPT: \\_CreateAllVMs.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:243 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# _CreateAllVM.sh : Create VMs for the IPFW Primer lab.\n" +"# Files are created in ../VM/\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:245 +#, no-wrap +msgid "echo \"Running _CreateAllVMs.sh\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:251 +#, no-wrap +msgid "" +"echo\n" +"echo \"This script will create 8 virtual machines in ../VM/\"\n" +"echo\n" +"read -p \"DO YOU REALLY WANT TO CREATE NEW QEMU IMAGES OVERWRITING ANY EXISTING IMAGES? Answer YES to continue. \" junk\n" +"echo [${junk}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:258 +#, no-wrap +msgid "" +"if [ \"X${junk}\" != \"XYES\" ]\n" +"then\n" +" echo \"Response was [${junk}]\"\n" +" echo \"bailing out...\"\n" +" exit 1\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:261 +#, no-wrap +msgid "" +"echo \"Response was [${junk}]\"\n" +"echo \"Ok, continuing...\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:263 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:895 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1136 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1200 +#, no-wrap +msgid "#exit\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:271 +#, no-wrap +msgid "" +"for i in dnshost external1 external2 external3 firewall firewall2 internal v6only\n" +"do\n" +" echo \"Creating ${i} VM\"\n" +" echo qemu-img create -f qcow2 -o preallocation=full ../VM/${i}.qcow2 4G\n" +" qemu-img create -f qcow2 -o preallocation=full ../VM/${i}.qcow2 4G\n" +"done\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:274 +#, no-wrap +msgid "" +"echo\n" +"echo \"Done.\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:280 +#, no-wrap +msgid "*SCRIPT: tcon.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:288 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"#\n" +"# location: external Vms\n" +"#\n" +"# sh tcon.sh PORTNUM - start up 1 connection over TCP\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:293 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh tcon.sh PORTNUM\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:296 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:421 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:551 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:680 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:740 +#, no-wrap +msgid "#echo $#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:303 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:558 +#, no-wrap +msgid "" +"if [ $# -ne 1 ]\n" +"then\n" +" usage\n" +"else\n" +" export PORT1=$1\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:305 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:560 +#, no-wrap +msgid "# echo \"PORT1 = [$PORT1]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:308 +#, no-wrap +msgid "" +"export CONN=\"203.0.113.50\"\n" +"export COUNT=1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:311 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:567 +#, no-wrap +msgid "" +"export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'`\n" +"export MYNAME=\"external1\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:314 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:379 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:442 +#, no-wrap +msgid "" +"echo \"TCP connection from [$MYIP],[$PORT1],[$COUNT]\"\n" +"echo \"TCP connection from [$MYIP],[$PORT1],[$COUNT]\"| ncat $CONN $PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:316 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:572 +#, no-wrap +msgid "export PREVIOUS_PORT=$PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:319 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:382 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:445 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:575 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:641 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:703 +#, no-wrap +msgid "" +"while :\n" +"do\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:321 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:447 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:577 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:705 +#, no-wrap +msgid " COUNT=`expr $COUNT + 1`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:323 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:579 +#, no-wrap +msgid " read -p \"ncat [$COUNT] ready. Enter a valid PORTNUM: \" PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:328 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:584 +#, no-wrap +msgid "" +" if [ \"X$PORT1\" = \"X\" ]\n" +" then\n" +" PORT1=$PREVIOUS_PORT\n" +" fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:331 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:392 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:450 +#, no-wrap +msgid "" +" echo \"TCP connection from [$MYIP],[$PORT1],[$COUNT]\"\n" +" echo \"TCP connection from [$MYIP],[$PORT1],[$COUNT]\"| ncat $CONN $PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:336 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:397 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:455 +#, no-wrap +msgid "" +" if [ $? -ne 0 ]\n" +" then\n" +" echo \"TCP connection [$MYIP],[$PORT1],[$COUNT] FAILED\"\n" +" fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:338 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:594 +#, no-wrap +msgid " PREVIOUS_PORT=$PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:340 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:401 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:459 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:596 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:660 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:720 +#, no-wrap +msgid "done\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:346 +#, no-wrap +msgid "*SCRIPT: tconr.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:353 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: external Vms\n" +"#\n" +"# sh tconr.sh PORTNUM SLEEPVAL (randomized port numbers) - start up 1 connection over TCP\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:358 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh tconr.sh PORT1NUM SLEEPVAL (randomized port numbers)\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:360 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:615 +#, no-wrap +msgid "# echo $#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:365 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:426 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:620 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:685 +#, no-wrap +msgid "" +"if [ $# -ne 2 ]\n" +" then\n" +" usage\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:368 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:624 +#, no-wrap +msgid "" +"PORT1=$1\n" +"SLEEPVAL=$2\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:371 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:628 +#, no-wrap +msgid "" +"echo \"PORT1 = [$PORT1]\"\n" +"echo \"SLEEPVAL = [$SLEEPVAL]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:376 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:634 +#, no-wrap +msgid "" +"export CONN=\"203.0.113.50\"\n" +"export COUNT=1\n" +"export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'`\n" +"export MYNAME=\"external1\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:384 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:643 +#, no-wrap +msgid "COUNT=`expr $COUNT + 1`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:387 +#, no-wrap +msgid "" +"# use jot(1) to get a random port between 5656 and 5659.\n" +"# Connection to 5659 has no listener on firewall and will thus fail.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:389 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:648 +#, no-wrap +msgid " PORT1=`jot -r 1 5656 5659 $RANDOM`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:399 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:457 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:658 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:718 +#, no-wrap +msgid " sleep $SLEEPVAL\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:407 +#, no-wrap +msgid "*SCRIPT: tcont.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:414 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: external Vms\n" +"#\n" +"# sh tcont.sh PORT1NUM SLEEPVAL - keep hammering same TCP port every SLEEPVAL\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:419 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh tcont.sh PORT1NUM SLEEPVAL\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:430 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:689 +#, no-wrap +msgid "" +"export PORT1=$1\n" +"export SLEEPVAL=$2\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:433 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:692 +#, no-wrap +msgid "" +"echo \"PORT1 = [$PORT1]\"\n" +"echo \"SLEEPVAL = [$SLEEPVAL]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:437 +#, no-wrap +msgid "" +"export CONN=\"203.0.113.50\"\n" +"export COUNT=1\n" +"export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:465 +#, no-wrap +msgid "*SCRIPT: tserv.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:471 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: firewall VMs\n" +"#\n" +"# tserv.sh - start up 1 listener over TCP\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:475 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:753 +#, no-wrap +msgid "" +"zapall() {\n" +"kill -TERM $PID1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:477 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:509 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:755 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:787 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:828 +#, no-wrap +msgid "trap zapall SIGINT\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:480 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:512 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:757 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:790 +#, no-wrap +msgid "export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:482 +#, no-wrap +msgid "export PORT1=5656\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:484 +#, no-wrap +msgid "echo \"Starting TCP listener on [$PORT1]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:487 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:521 +#, no-wrap +msgid "" +"ncat -l -4 -k $MYIP $PORT1 &\n" +"PID1=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:489 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:529 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:766 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:808 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:856 +#, no-wrap +msgid "wait\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:491 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:531 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:768 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:810 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:858 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1770 +#, no-wrap +msgid "exit\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:497 +#, no-wrap +msgid "*SCRIPT: tserv3.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:503 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"#\n" +"# location: firewall VMs\n" +"#\n" +"# tserv3.sh - start up 3 listeners over TCP\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:507 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:785 +#, no-wrap +msgid "" +"zapall() {\n" +"kill -TERM $PID1 $PID2 $PID3\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:516 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:794 +#, no-wrap +msgid "" +"export PORT1=5656\n" +"export PORT2=5657\n" +"export PORT3=5658\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:518 +#, no-wrap +msgid "echo \"Starting TCP listeners on [$PORT1],[$PORT2],[$PORT3]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:524 +#, no-wrap +msgid "" +"ncat -l -4 -k $MYIP $PORT2 &\n" +"PID2=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:527 +#, no-wrap +msgid "" +"ncat -l -4 -k $MYIP $PORT3 &\n" +"PID3=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:537 +#, no-wrap +msgid "*SCRIPT: ucon.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:544 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"#\n" +"# location: external Vms\n" +"#\n" +"# sh ucon.sh PORTNUM - start up 1 transfer over UDP\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:549 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh ucon.sh PORTNUM\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:564 +#, no-wrap +msgid "" +"export CONN=\"203.0.113.50\"\n" +"# export CONN=\"10.10.10.50\"\n" +"export COUNT=1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:570 +#, no-wrap +msgid "" +"echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"\n" +"echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"| ncat -u $CONN $PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:587 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:651 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:711 +#, no-wrap +msgid "" +" echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"\n" +" echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"| ncat -u $CONN $PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:592 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:656 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:716 +#, no-wrap +msgid "" +" if [ $? -ne 0 ]\n" +" then\n" +" echo \"UDP packet [$MYIP],[$PORT1],[$COUNT] FAILED\"\n" +" fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:602 +#, no-wrap +msgid "*SCRIPT: uconr.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:607 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: external Vms\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:612 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh uconr.sh PORT1NUM SLEEPVAL (randomized port numbers)\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:638 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:700 +#, no-wrap +msgid "" +"echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"\n" +"echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"| ncat -u $CONN $PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:646 +#, no-wrap +msgid "" +"# use jot(1) to get a random port between 5656 and 5659.\n" +"# Packet on 5659 has no listener on firewall and will thus fail.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:666 +#, no-wrap +msgid "*SCRIPT: ucont.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:673 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: external Vms\n" +"#\n" +"# sh ucont.sh PORT1NUM SLEEPVAL - keep hammering same UDP port every SLEEPVAL\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:678 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh ucont.sh PORT1NUM SLEEPVAL\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:697 +#, no-wrap +msgid "" +"# export CONN=\"10.10.10.50\"\n" +"export CONN=\"203.0.113.50\"\n" +"export COUNT=1\n" +"export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:708 +#, no-wrap +msgid "" +"# echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"\n" +"# echo \"UDP packet from [$MYIP],[$PORT1],[$COUNT]\"| ncat -u $CONN $PORT1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:726 +#, no-wrap +msgid "*SCRIPT: userv.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:733 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: firewall VMs\n" +"#\n" +"# userv.sh PORTNUM - start up 1 listener over UDP\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:738 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"sh userv.sh PORTNUM\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:747 +#, no-wrap +msgid "" +"if [ $# -ne 1 ]\n" +"then\n" +" usage\n" +"else\n" +" PORT1=$1\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:749 +#, no-wrap +msgid "echo \"PORT1 = [$PORT1]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:760 +#, no-wrap +msgid "echo \"Starting UDP listener on [$MYIP],[$PORT1]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:764 +#, no-wrap +msgid "" +"# echo nc -l -k -u $MYIP $PORT1\n" +"nc -l -k -u $MYIP $PORT1 &\n" +"PID1=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:774 +#, no-wrap +msgid "*SCRIPT: userv3.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:781 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"#\n" +"# location: firewall VMs\n" +"#\n" +"# userv3.sh - start up 3 listeners over udp\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:797 +#, no-wrap +msgid "echo \"Starting UDP listeners on [$PORT1],[$PORT2],[$PORT3]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:800 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:842 +#, no-wrap +msgid "" +"nc -l -k -u $MYIP $PORT1 &\n" +"PID1=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:803 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:845 +#, no-wrap +msgid "" +"nc -l -k -u $MYIP $PORT2 &\n" +"PID2=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:806 +#, no-wrap +msgid "" +"nc -l -k -u $MYIP $PORT3 &\n" +"PID3=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:816 +#, no-wrap +msgid "*SCRIPT: userv5.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:822 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"#\n" +"# location: firewall VMs\n" +"#\n" +"# userv5.sh - start up 5 listeners over udp\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:826 +#, no-wrap +msgid "" +"zapall() {\n" +"kill -TERM $PID1 $PID2 $PID3 $PID4 $PID5\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:836 +#, no-wrap +msgid "" +"export MYIP=`ifconfig em0 | grep inet | grep -v inet6 | awk '{print $2}'`\n" +"export PORT1=5656\n" +"export PORT2=5657\n" +"export PORT3=5658\n" +"export PORT4=5659\n" +"export PORT5=5660\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:839 +#, no-wrap +msgid "echo \"Starting UDP listeners on [$PORT1],[$PORT2],[$PORT3],[$PORT4],[$PORT5]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:848 +#, no-wrap +msgid "" +"nc -l -k -u $MYIP $PORT3 &cd\n" +"PID3=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:851 +#, no-wrap +msgid "" +"nc -l -k -u $MYIP $PORT4 &\n" +"PID4=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:854 +#, no-wrap +msgid "" +"nc -l -k -u $MYIP $PORT5 &\n" +"PID5=$!\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:864 +#, no-wrap +msgid "*SCRIPT: dnshost.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:878 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for dnshost VM.\n" +"#\n" +"# dnshost.sh: FreeBSD QEMU VM startup script for dnshost VM.\n" +"# Usage: sudo /bin/sh dnshost.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:881 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:947 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1005 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1062 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1123 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1187 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1251 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1295 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1537 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1797 +#, no-wrap +msgid "" +"# pick up environment for this run\n" +". ./vm_envs.sh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:893 +#, no-wrap +msgid "" +"echo [ISO=${_DNSHOST_ISO}]\n" +"echo [mem=${_DNSHOST_mem}]\n" +"echo [hdsize=${_DNSHOST_hdsize}]\n" +"echo [img=${_DNSHOST_img}]\n" +"echo [mac1=${_DNSHOST_mac1}]\n" +"echo [mac2=${_DNSHOST_mac2}]\n" +"echo [name=${_DNSHOST_name}]\n" +"echo [tap7=${_DNSHOST_tap7}]\n" +"echo [tap8=${_DNSHOST_tap8}]\n" +"echo [tap11=${_DNSHOST_tap11}]\n" +"echo [telnetport=${_DNSHOST_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:899 +#, no-wrap +msgid "" +"# Note - the dnshost has two interfaces - em0 and em1.\n" +"# em0 is considered the ipv4 interface and\n" +"# em1 is considered the ipv6 interface.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:903 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_DNSHOST_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:920 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_DNSHOST_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_DNSHOST_mem} \\\n" +" -cdrom ${_DNSHOST_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_DNS_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_DNSHOST_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_DNSHOST_tap7},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_DNSHOST_mac1} \\\n" +" -netdev tap,id=nd1,ifname=${_DNSHOST_tap8},script=no,downscript=no \\\n" +" -device e1000,netdev=nd1,mac=${_DNSHOST_mac2} \\\n" +" -netdev tap,id=nd2,ifname=${_DNSHOST_tap11},script=no,downscript=no \\\n" +" -device e1000,netdev=nd2,mac=${_DNSHOST_mac3} \\\n" +" -name \\\"${_DNSHOST_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:926 +#, no-wrap +msgid "*SCRIPT: external1.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:944 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for external1 VM.\n" +"#\n" +"# external1.sh: FreeBSD QEMU VM startup script for external1 VM.\n" +"# Usage: sudo /bin/sh external1.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"# FreeBSD QEMU VM startup script\n" +"#\n" +"# external1.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:956 +#, no-wrap +msgid "" +"echo [$_EXTERNAL1_ISO]\n" +"echo [$_EXTERNAL1_mem]\n" +"echo [$_EXTERNAL1_hdsize]\n" +"echo [$_EXTERNAL1_img]\n" +"echo [$_EXTERNAL1_mac]\n" +"echo [$_EXTERNAL1_name]\n" +"echo [$_EXTERNAL1_tap1]\n" +"echo [$_EXTERNAL1_telnetport]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:960 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1018 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1075 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1308 +#, no-wrap +msgid "" +"#\n" +"#exit\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:964 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL1_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:977 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_EXTERNAL1_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_EXTERNAL1_mem} \\\n" +" -cdrom ${_EXTERNAL1_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_EX1_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL1_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_EXTERNAL1_tap1},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_EXTERNAL1_mac} \\\n" +" -name \\\"${_EXTERNAL1_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:983 +#, no-wrap +msgid "*SCRIPT: external2.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:996 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for external2 VM.\n" +"#\n" +"# external2.sh: FreeBSD QEMU VM startup script for external2 VM.\n" +"# Usage: sudo /bin/sh external2.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1002 +#, no-wrap +msgid "" +"# FreeBSD qemu vm startup script\n" +"#\n" +"# external2.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1014 +#, no-wrap +msgid "" +"echo [ISO=${_EXTERNAL2_ISO}]\n" +"echo [mem=${_EXTERNAL2_mem}]\n" +"echo [hdsize=${_EXTERNAL2_hdsize}]\n" +"echo [img=${_EXTERNAL2_img}]\n" +"echo [mac=${_EXTERNAL2_mac}]\n" +"echo [name=${_EXTERNAL2_name}]\n" +"echo [tap2=${_EXTERNAL2_tap2}]\n" +"echo [telnetport=${_EXTERNAL2_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1022 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL2_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1035 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_EXTERNAL2_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_EXTERNAL2_mem} \\\n" +" -cdrom ${_EXTERNAL2_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_EX2_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL2_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_EXTERNAL2_tap2},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_EXTERNAL2_mac} \\\n" +" -name \\\"${_EXTERNAL2_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1041 +#, no-wrap +msgid "*SCRIPT: external3.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1059 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for external3 VM.\n" +"#\n" +"# external3.sh: FreeBSD QEMU VM startup script for external3 VM.\n" +"# Usage: sudo /bin/sh external3.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"# FreeBSD QEMU VM startup script\n" +"#\n" +"# external3.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1071 +#, no-wrap +msgid "" +"echo [ISO=${_EXTERNAL3_ISO}]\n" +"echo [mem=${_EXTERNAL3_mem}]\n" +"echo [hdsize=${_EXTERNAL3_hdsize}]\n" +"echo [img=${_EXTERNAL3_img}]\n" +"echo [mac=${_EXTERNAL3_mac}]\n" +"echo [name=${_EXTERNAL3_name}]\n" +"echo [tap3=${_EXTERNAL3_tap3}]\n" +"echo [telnetport=${_EXTERNAL3_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1080 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_EXTERNAL3_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1093 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_EXTERNAL3_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_EXTERNAL3_mem} \\\n" +" -cdrom ${_EXTERNAL3_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_EX3_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_EXTERNAL3_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_EXTERNAL3_tap3},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_EXTERNAL3_mac} \\\n" +" -name \\\"${_EXTERNAL3_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1102 +#, no-wrap +msgid "*SCRIPT: firewall.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1120 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for firewall VM.\n" +"#\n" +"# firewall.sh: FreeBSD QEMU VM startup script for firewall VM.\n" +"# Usage: sudo /bin/sh firewall.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"# FreeBSD QEMU VM startup script\n" +"#\n" +"# firewall.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1134 +#, no-wrap +msgid "" +"echo [$_FIREWALL_ISO]\n" +"echo [$_FIREWALL_mem]\n" +"echo [$_FIREWALL_hdsize]\n" +"echo [$_FIREWALL_img]\n" +"echo [$_FIREWALL_mac1]\n" +"echo [$_FIREWALL_mac2]\n" +"echo [$_FIREWALL_name]\n" +"echo [$_FIREWALL_tap0]\n" +"echo [$_FIREWALL_tap4]\n" +"echo [$_FIREWALL_telnetport]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1140 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1204 +#, no-wrap +msgid "" +"# Note - the firewall has two interfaces - em0 and em1.\n" +"# em0 is considered the 'external' interface and\n" +"# em1 is considered the 'internal' interface.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1144 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_FIREWALL_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1160 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_FIREWALL_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -display gtk \\\n" +" -vga cirrus \\\n" +" -m ${_FIREWALL_mem} \\\n" +" -cdrom ${_FIREWALL_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_FW_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_FIREWALL_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_FIREWALL_tap0},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_FIREWALL_mac1} \\\n" +" -netdev tap,id=nd1,ifname=${_FIREWALL_tap4},script=no,downscript=no \\\n" +" -device e1000,netdev=nd1,mac=${_FIREWALL_mac2} \\\n" +" -name \\\"${_FIREWALL_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1166 +#, no-wrap +msgid "*SCRIPT: firewall2.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1184 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for firewall2 VM.\n" +"#\n" +"# firewall2.sh: FreeBSD QEMU VM startup script for firewall2 VM.\n" +"# Usage: sudo /bin/sh firewall2.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"# FreeBSD QEMU VM startup script\n" +"#\n" +"# firewall2.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1198 +#, no-wrap +msgid "" +"echo [ISO=${_FIREWALL2_ISO}]\n" +"echo [mem=${_FIREWALL2_mem}]\n" +"echo [hdsize=${_FIREWALL2_hdsize}]\n" +"echo [img=${_FIREWALL2_img}]\n" +"echo [mac1=${_FIREWALL2_mac1}]\n" +"echo [mac2=${_FIREWALL2_mac2}]\n" +"echo [name=${_FIREWALL2_name}]\n" +"echo [tap9=${_FIREWALL2_tap9}]\n" +"echo [tap10=${_FIREWALL2_tap10}]\n" +"echo [telnetport=${_FIREWALL2_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1208 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_FIREWALL2_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1224 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_FIREWALL2_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -display gtk \\\n" +" -vga cirrus \\\n" +" -m ${_FIREWALL2_mem} \\\n" +" -cdrom ${_FIREWALL_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_FW2_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_FIREWALL2_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_FIREWALL2_tap9},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_FIREWALL2_mac1} \\\n" +" -netdev tap,id=nd1,ifname=${_FIREWALL2_tap10},script=no,downscript=no \\\n" +" -device e1000,netdev=nd1,mac=${_FIREWALL2_mac2} \\\n" +" -name \\\"${_FIREWALL2_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1230 +#, no-wrap +msgid "*SCRIPT: internal.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1248 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for internal VM.\n" +"#\n" +"# internal.sh: FreeBSD QEMU VM startup script for internal VM.\n" +"# Usage: sudo /bin/sh internal.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"# FreeBSD QEMU VM startup script\n" +"#\n" +"# internal.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1261 +#, no-wrap +msgid "" +"echo [ISO=${_INTERNAL_ISO}]\n" +"echo [mem=${_INTERNAL_mem}]\n" +"echo [hdsize=${_INTERNAL_hdsize}]\n" +"echo [img=${_INTERNAL_img}]\n" +"echo [mac=${_INTERNAL_mac}]\n" +"echo [name=${_INTERNAL_name}]\n" +"echo [tap5=${_INTERNAL_tap5}]\n" +"echo [telnetport=${_INTERNAL_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1264 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1810 +#, no-wrap +msgid "" +"#\n" +"#exit\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1268 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_INTERNAL_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1281 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${\\_INTERNAL_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_INTERNAL_mem} \\\n" +" -cdrom ${_INTERNAL_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_INT_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_INTERNAL_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_INTERNAL_tap5},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_INTERNAL_mac} \\\n" +" -name \\\"${_INTERNAL_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1292 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# FreeBSD qemu vm startup script\n" +"#\n" +"# jail1.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1304 +#, no-wrap +msgid "" +"echo [ISO=${_JAIL1_ISO}]\n" +"echo [mem=${_JAIL1_mem}]\n" +"echo [hdsize=${_JAIL1_hdsize}]\n" +"echo [img=${_JAIL1_img}]\n" +"echo [mac=${_JAIL1_mac}]\n" +"echo [name=${_JAIL1_name}]\n" +"echo [tap2=${_JAIL1_tap2}]\n" +"echo [telnetport=${_JAIL1_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1318 +#, no-wrap +msgid "" +"# minimal check that environment is sane\n" +"#if [ \"X${_FBSD_ISO}\" = \"X\" -o ! -s ${_FBSD_ISO} ]\n" +"#then\n" +"# echo \"Parameter or file failure on _FBSD_ISO [${_FBSD_ISO}]\"\n" +"# echo \"Check vm_envs.sh\"\n" +"# exit 1\n" +"#fi\n" +"#\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1324 +#, no-wrap +msgid "" +"#echo\n" +"#echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_JAIL1_telnetport\"\n" +"#echo\n" +"# -serial telnet:localhost:${_JAIL1_telnetport},server=on,wait=on \\\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1337 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_JAIL1_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_JAIL1_mem} \\\n" +" -cdrom ${_JAIL1_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_JAIL1_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_JAIL1_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_JAIL1_tap12},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${\\_JAIL1_mac} \\\n" +" -name \\\"${_JAIL1_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1343 +#, no-wrap +msgid "*SCRIPT: mkbr.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1376 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD startup script for bridge and tap devices.\n" +"#\n" +"# mkbr.sh: FreeBSD startup script for bridge and tap devices.\n" +"# EXAMPLE Usage: sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 bridge2 tap3 tap4 tap5 em0\n" +"#\n" +"# mkbr.sh - manage bridge and tap interfaces for FreeBSD.\n" +"#\n" +"# Have fun, but don't blame me if it smokes your machine.\n" +"#\n" +"# This script is used to start the bridge and tap interfaces.\n" +"#\n" +"# To create one bridge, two tap interfaces, and connect the\n" +"# local ethernet interace (here em0), run under sudo as follows:\n" +"# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 em0\n" +"#\n" +"# The script can be used to create any number of bridges and taps\n" +"# for any internal network design:\n" +"# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 bridge1 tap2 tap3 tap4 bridge2 tap5 em0 ... etc.\n" +"#\n" +"# To add other taps to existing bridges, do not specify the \"reset\" parameter.\n" +"# sudo /bin/sh mkbr.sh bridge0 tap10 tap11 bridge1 tap12 tap13 ... etc.\n" +"#\n" +"# To delete all bridge and tap devices:\n" +"# sudo /bin/sh mkbr.sh reset\n" +"#\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1378 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1540 +#, no-wrap +msgid "#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1385 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"Usage: mkbr.sh [\"reset\"] [[] ...]\"\n" +" echo \"You must be root to run this script.\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1391 +#, no-wrap +msgid "" +"if [ \"X0\" != \"X`id -u`\" ]\n" +"then\n" +"\t usage\n" +" fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1396 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1569 +#, no-wrap +msgid "" +"if [ $# = 0 ]\n" +"then\n" +" usage;\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1407 +#, no-wrap +msgid "" +"if [ $1 = \"reset\" ]\n" +"then\n" +" echo\n" +" echo \"Note - if_bridge and/or if_tap may be compiled into the kernel and can't be unloaded. Adjust interfaces manually if necessary.\"\n" +" echo\n" +" echo \"unloading...\"\n" +" kldunload if_bridge\n" +" kldunload if_tap\n" +" echo\n" +" echo \"Deleting any remaining bridge and tap devices:\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1411 +#, no-wrap +msgid "" +" for i in `ifconfig -l`\n" +" do\n" +" echo \"Interface: ${i}\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1413 +#, no-wrap +msgid " case ${i} in\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1424 +#, no-wrap +msgid "" +" bridge*)\n" +" echo \" ... destroying bridge ${i}\"\n" +" ifconfig ${i} destroy\n" +" ;;\n" +" tap*)\n" +" echo \" ... destroying tap ${i}\"\n" +" ifconfig ${i} destroy\n" +" ;;\n" +" esac\n" +" done\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1439 +#, no-wrap +msgid "" +" sleep 1\n" +" echo \"loading...\"\n" +" kldload if_bridge\n" +" kldload if_tap\n" +" shift\n" +" RESET=\"Y\"\n" +" echo \"RESET=Y\"\n" +" # Before using the tap devices in QEMU, two sysctls require adjustment:\n" +" sysctl net.link.tap.user_open=1\n" +" sysctl net.link.tap.up_on_open=1\n" +"else\n" +" RESET=\"N\"\n" +" echo \"RESET=N\"\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1442 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1651 +#, no-wrap +msgid "PARAM=$1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1446 +#, no-wrap +msgid "" +"while [ \"X${PARAM}\" != \"X\" ]\n" +"do\n" +"# echo \"PARAM=[$PARAM]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1448 +#, no-wrap +msgid " case $PARAM in\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1450 +#, no-wrap +msgid " bridge*) BRIDGE=$1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1461 +#, no-wrap +msgid "" +" # if [ \"$RESET\" = \"Y\" ]\n" +" # then\n" +" echo ifconfig $BRIDGE create\n" +" ifconfig $BRIDGE create\n" +" echo ifconfig $BRIDGE\n" +" ifconfig $BRIDGE\n" +" # fi\n" +" echo ifconfig $BRIDGE up\n" +" ifconfig $BRIDGE up\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1471 +#, no-wrap +msgid "" +" tap*) TAP=$1\n" +" # if [ \"$RESET\" = \"Y\" ]\n" +" # then\n" +" echo ifconfig $TAP create\n" +" ifconfig $TAP create\n" +" # fi\n" +" echo \"ifconfig $BRIDGE addm $TAP \"\n" +" ifconfig $BRIDGE addm $TAP\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1489 +#, no-wrap +msgid "" +" \\*) echo \"\\*** Checking to see if $1 is a valid interface\"\n" +" TMPINT=$1\n" +" RESULT=\"IS NOT\"\n" +" for i in `ifconfig -l`\n" +" do\n" +"# echo $i\n" +" if [ \"${i}X\" = \"${TMPINT}X\" ]\n" +" then\n" +" echo \"Found a valid interface: ${TMPINT} Adding it to the bridge. Check results.\"\n" +" echo \"ifconfig $BRIDGE addm $TMPINT\"\n" +" ifconfig $BRIDGE addm $TMPINT\n" +" RESULT=\"IS\"\n" +" break;\n" +" else\n" +" echo -n \".\"\n" +" fi\n" +" done\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1493 +#, no-wrap +msgid "" +" echo \"Interface ${TMPINT} $RESULT a valid interface.\"\n" +" ;;\n" +" esac\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1497 +#, no-wrap +msgid "" +" shift\n" +" PARAM=$1\n" +"done\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1499 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1722 +#, no-wrap +msgid "exit 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1505 +#, no-wrap +msgid "*SCRIPT: runvm.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1533 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for multiple VMs at once.\n" +"#\n" +"# runvm.sh: FreeBSD QEMU VM startup script for multiple VMs.\n" +"# EXAMPLE Usage: /bin/sh runvm.sh firewall external1 external2 internal\n" +"#\n" +"# location: FreeBSD Host\n" +"#\n" +"# runvm.sh - run virtual machines specified on the command line.\n" +"#\n" +"# To use this script, run mkbr.sh first to set up the bridge and\n" +"# tap configurations for the desired network architecture.\n" +"#\n" +"# NOTE: this script works best on XFCE4 desktop as it takes advantage of the\n" +"# xfce4-terminal and it's ability to use multiple tabs.\n" +"#\n" +"# >>>> It is unlikely to work on another desktop. <<<<\n" +"#\n" +"# Essentially, this script is a big case statement. It gets the\n" +"# command line names of the virtual machines and calls a function\n" +"# that starts the virtual machine.\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1543 +#, no-wrap +msgid "" +"#WKDIR=$HOME/LAB/SCRIPTS\n" +"export WKDIR=$HOME/ipfw\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1545 +#, no-wrap +msgid "echo \"[${WKDIR}]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1555 +#, no-wrap +msgid "" +"usage() {\n" +" echo \"Usage: /bin/sh runvm.sh vmname [vmname ...]\"\n" +" echo \"Each virtual machine opens up on xfce4-terminal with two tabs -\"\n" +" echo \" one for the qemu virtual machine, and one for the serial\"\n" +" echo \" terminal interface.\"\n" +" echo \"\"\n" +" exit 1\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1558 +#, no-wrap +msgid "CURDIR=`pwd`\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1563 +#, no-wrap +msgid "" +"if [ \"X${CURDIR}\" != \"X${WKDIR}/SCRIPTS\" ]\n" +"then\n" +" usage;\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1571 +#, no-wrap +msgid "# Functions for each VM\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1580 +#, no-wrap +msgid "" +"dnshost_vm () {\n" +" # DNS host\n" +" echo \"in function: [${_DNSHOST_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+50+50\" --zoom=\"-1\" \\\n" +" -T \"${_DNSHOST_name}\" -e \"bash -c \\\"cd ${WKDIR}/SCRIPTS && sudo /bin/sh dnshost.sh ; bash\\\"\" \\\n" +" --tab -T \"${_DNSHOST_name}\" -e \"bash -c \\\"cd ${WKDIR}/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet -4 localhost ${_DNSHOST_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1589 +#, no-wrap +msgid "" +"external1_vm () {\n" +" # external1\n" +" echo \"in function: [${_EXTERNAL1_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+75+75\" --zoom=\"-1\" \\\n" +" -T \"${_EXTERNAL1_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh external1.sh ; bash\\\"\" \\\n" +" --tab -T \"${_EXTERNAL1_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL1_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1598 +#, no-wrap +msgid "" +"external2_vm () {\n" +" # external2\n" +" echo \"in function: [${_EXTERNAL2_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+100+100\" --zoom=\"-1\" \\\n" +" -T \"${_EXTERNAL2_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh external2.sh ; bash\\\"\" \\\n" +" --tab -T \"${_EXTERNAL2_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL2_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1607 +#, no-wrap +msgid "" +"external3_vm () {\n" +" # external3\n" +" echo \"in function: [${_EXTERNAL3_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+125+125\" --zoom=\"-1\" \\\n" +" -T \"${_EXTERNAL3_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh external3.sh ; bash\\\"\" \\\n" +" --tab -T \"${_EXTERNAL3_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_EXTERNAL3_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1616 +#, no-wrap +msgid "" +"firewall_vm () {\n" +" # Firewall\n" +" echo \"in function: [${_FIREWALL_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+150+150\" --zoom=\"-1\" \\\n" +" -T \"${_FIREWALL_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh firewall.sh ; bash\\\"\" \\\n" +" --tab -T \"${_FIREWALL_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh; telnet localhost ${_FIREWALL_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1625 +#, no-wrap +msgid "" +"firewall2_vm () {\n" +" # Firewall2\n" +" echo \"in function: [${_FIREWALL2_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+175+175\" --zoom=\"-1\" \\\n" +" -T \"${_FIREWALL2_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh firewall2.sh ; bash\\\"\" \\\n" +" --tab -T \"${_FIREWALL2_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_FIREWALL2_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1634 +#, no-wrap +msgid "" +"internal_vm () {\n" +" # internal\n" +" echo \"in function: [${_INTERNAL_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+200+200\" --zoom=\"-1\" \\\n" +" -T \"${_INTERNAL_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh internal.sh ; bash\\\"\" \\\n" +" --tab -T \"${_INTERNAL_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_INTERNAL_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1643 +#, no-wrap +msgid "" +"v6only_vm () {\n" +" # v6only\n" +" echo \"in function: [${_V6ONLY_telnetport}]\"\n" +" xfce4-terminal --window --geometry=\"80x24+225+225\" --zoom=\"-1\" \\\n" +" -T \"${_V6ONLY_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sudo /bin/sh v6only.sh ; bash\\\"\" \\\n" +" --tab -T \"${_V6ONLY_name}\" -e \"bash -c \\\"cd $WKDIR/SCRIPTS && sleep 2 && (. ./vm_envs.sh;telnet localhost ${_V6ONLY_telnetport}); bash\\\"\"\n" +" return\n" +"}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1648 +#, no-wrap +msgid "" +"#\n" +"# Startup the requested VMs\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1655 +#, no-wrap +msgid "" +"while [ \"X${PARAM}\" != \"X\" ]\n" +"do\n" +" echo \"PARAM = [${PARAM}]\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1657 +#, no-wrap +msgid " case ${PARAM} in\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1663 +#, no-wrap +msgid "" +" dnshost)\n" +" echo \"dnshost ...\"\n" +"\techo \"_DNSHOST_telnetport = [${_DNSHOST_telnetport}]\"\n" +" dnshost_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1669 +#, no-wrap +msgid "" +" external1)\n" +" echo \"external1 ...\"\n" +"\techo \"_EXTERNAL1_telnetport = [${_EXTERNAL1_telnetport}]\"\n" +" external1_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1675 +#, no-wrap +msgid "" +" external2)\n" +" echo \"external2 ...\"\n" +"\techo \"_EXTERNAL2_telnetport = [${_EXTERNAL2_telnetport}]\"\n" +" external2_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1681 +#, no-wrap +msgid "" +" external3)\n" +" echo \"external3 ...\"\n" +"\techo \"_EXTERNAL3_telnetport = [${_EXTERNAL3_telnetport}]\"\n" +" external3_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1687 +#, no-wrap +msgid "" +" firewall)\n" +" echo \"firewall ...\"\n" +"\techo \"_FIREWALL_telnetport = [${_FIREWALL_telnetport}]\"\n" +" firewall_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1693 +#, no-wrap +msgid "" +" firewall2)\n" +" echo \"firewall2 ...\"\n" +"\techo \"_FIREWALL2_telnetport = [${_FIREWALL2_telnetport}]\"\n" +" firewall2_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1699 +#, no-wrap +msgid "" +" internal)\n" +" echo \"internal ...\"\n" +"\techo \"_INTERNAL_telnetport = [${_INTERNAL_telnetport}]\"\n" +" internal_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1705 +#, no-wrap +msgid "" +" v6only)\n" +" echo \"v6only ...\"\n" +"\techo \"_V6ONLY_telnetport = [${_V6ONLY_telnetport}]\"\n" +" v6only_vm\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1711 +#, no-wrap +msgid "" +" \\*)\n" +" echo \"\"\n" +" echo \"*** ERROR: NO VM NAMED [$PARAM]\"\n" +" echo \"\"\n" +" ;;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1713 +#, no-wrap +msgid " esac\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1715 +#, no-wrap +msgid " shift\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1717 +#, no-wrap +msgid " sleep 3\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1720 +#, no-wrap +msgid "" +" PARAM=$1\n" +"done\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1728 +#, no-wrap +msgid "*SCRIPT: swim.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1742 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# Serial Window Management Script Using tmux. (swim.sh)\n" +"#\n" +"# Usage: /bin/sh swim.sh\n" +"# Note: This program manages multiple serial termainal windows for QEMU\n" +"# VMs on the host.\n" +"# Make sure to uncomment the lines below for the windows you want.\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1745 +#, no-wrap +msgid "" +"# Check for an existing tmux session\n" +"tmux has-session -t 0 2>/dev/null\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1748 +#, no-wrap +msgid "" +"if [ $? != 0 ]; then\n" +" tmux new-session -d -s 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1758 +#, no-wrap +msgid "" +" tmux new-window -t 0:1 -n 'firewall' 'echo; echo Use \\\"telnet localhost 4450\\\" for firewall ; echo; /bin/sh'\n" +" tmux new-window -t 0:2 -n 'external1' 'echo; echo Use \\\"telnet localhost 4410\\\" for external1; echo; /bin/sh'\n" +" tmux new-window -t 0:3 -n 'external2' 'echo; echo Use \\\"telnet localhost 4420\\\" for external2; echo; /bin/sh'\n" +" tmux new-window -t 0:4 -n 'external3' 'echo; echo Use \\\"telnet localhost 4430\\\" for external3; echo; /bin/sh'\n" +"# tmux new-window -t 0:5 -n 'internal' 'echo; echo Use \\\"telnet localhost 44200\\\" for internal; echo; /bin/sh'\n" +"# tmux new-window -t 0:6 -n 'firewall2' 'echo; echo Use \\\"telnet localhost 4250\\\" for firewall2; echo; /bin/sh'\n" +"# tmux new-window -t 0:7 -n 'v6only' 'echo; echo Use \\\"telnet localhost 4460\\\" for v6only; echo; /bin/sh'\n" +"# tmux new-window -t 0:8 -n 'dnshost' 'echo; echo Use \\\"telnet localhost 4453\\\" for dnshost; echo; /bin/sh'\n" +"# tmux new-window -t 0:9 -n 'jail1' 'echo; echo Use \\\"telnet localhost 4470\\\" for jail1; echo; /bin/sh'\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1762 +#, no-wrap +msgid "" +" # Set the default command shell\n" +" set-option -g default-command \"/bin/sh\"\n" +"fi\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1765 +#, no-wrap +msgid "" +"# Set the focus on window 0:0, your existing shell.\n" +"tmux select-window -t 0:0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1768 +#, no-wrap +msgid "" +"# Attach to the session\n" +"tmux attach-session -t 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1776 +#, no-wrap +msgid "*SCRIPT: v6only.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1794 +#, no-wrap +msgid "" +"#!/bin/sh\n" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM startup script for v6only VM.\n" +"#\n" +"# v6only.sh: FreeBSD QEMU VM startup script for v6only VM.\n" +"# Usage: sudo /bin/sh v6only.sh\n" +"# Note: Set up for serial console. Start another session and telnet to the port shown.\n" +"#\n" +"# FreeBSD QEMU VM startup script\n" +"#\n" +"# v6only.sh\n" +"#\n" +"#set -x\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1807 +#, no-wrap +msgid "" +"echo [ISO=${_V6ONLY_ISO}]\n" +"echo [mem=${_V6ONLY_mem}]\n" +"echo [hdsize=${_V6ONLY_hdsize}]\n" +"echo [img=${_V6ONLY_img}]\n" +"echo [mac=${_V6ONLY_mac}]\n" +"echo [name=${_V6ONLY_name}]\n" +"echo [tap6=${_V6ONLY_tap6}]\n" +"echo [telnetport=${_V6ONLY_telnetport}]\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1814 +#, no-wrap +msgid "" +"echo\n" +"echo \"NOTE!!! telnet server running! To start QEMU telnet to localhost $_V6ONLY_telnetport\"\n" +"echo\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1827 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" -serial telnet:localhost:${_V6ONLY_telnetport},server=on,wait=off \\\n" +" -cpu qemu64 \\\n" +" -vga cirrus \\\n" +" -m ${_V6ONLY_mem} \\\n" +" -cdrom ${_V6ONLY_ISO} \\\n" +" -boot order=cd,menu=on,splash=${_V6_splash},splash-time=3000 \\\n" +" -drive if=none,id=drive0,cache=none,aio=threads,format=raw,file=${_V6ONLY_img} \\\n" +" -device virtio-blk,drive=drive0 \\\n" +" -netdev tap,id=nd0,ifname=${_V6ONLY_tap6},script=no,downscript=no \\\n" +" -device e1000,netdev=nd0,mac=${_V6ONLY_mac} \\\n" +" -name \\\"${_V6ONLY_name}\\\" &\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1833 +#, no-wrap +msgid "*SCRIPT: vm_envs.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1954 +#, no-wrap +msgid "" +"# IPFW Primer\n" +"# License: 3-clause BSD\n" +"# Author: Jim Brown, jpb@jimby.name\n" +"# Code: https://github.com/jimmyb-gh/ipfw-primer\n" +"#\n" +"# FreeBSD QEMU VM environment script.\n" +"#\n" +"# vmenv.sh: FreeBSD QEMU VM environment setup script.\n" +"# Usage: ./bin/sh vmenv.sh\n" +"#\n" +"# vm_envs.sh - environment for setting up virtual machines\n" +"# for the IPFW examples lab.\n" +"#\n" +"# Set the environment variables below (or keep the defaults)\n" +"# Note that the default disk size for each virtual machine is\n" +"# 4GB - so all five VMs will take up about 32GB if you preallocate\n" +"# space.\n" +"#\n" +"# In brief:\n" +"#\n" +"# Install FreeBSD on the host machine and update to latest patch level.\n" +"# Install desktop software.\n" +"# Install QEMU (latest)\n" +"# Install nmap (needed for ncat)\n" +"# Install sudo\n" +"#\n" +"#\n" +"# The script mkbr.sh should be run before starting\n" +"# the virtual machines. mkbr.sh sets up the bridge and tap\n" +"# devices needed by the VMs.\n" +"#\n" +"# sudo /bin/sh ./mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 em0 bridge1 tap4 tap5\n" +"#\n" +"# This will set up the devices needed by QEMU.\n" +"#\n" +"#\n" +"#The file directory layout for the examples is:\n" +"#\n" +"# ~/ipfw\n" +"# /SCRIPTS\n" +"# _CreateAllVMs.sh (create Qemu disks images)\n" +"# dnshost.sh (run script for dns server VM)\n" +"# external1.sh (run scripts for external VMs)\n" +"# external2.sh \"\n" +"# external3.sh \"\n" +"# firewall.sh (run script for firewall VM)\n" +"# firewall2.sh (run script for firewall2 VM)\n" +"# internal.sh (script to setup internal host)\n" +"# jail1.sh (script to setup jail1 host)\n" +"# v6only.sh (run script for IPv6 only VM)\n" +"# mkbr.sh (script to create bridge and tap devices)\n" +"# vm_envs.sh (script to manage all parameters)\n" +"# runvm.sh (script to manage all virtual machines)\n" +"# /BMP\n" +"# dns_splash_640x480.bmp\n" +"# external1_splash_640x480.bmp\n" +"# external2_splash_640x480.bmp\n" +"# external3_splash_640x480.bmp\n" +"# internal_splash_640x480.bmp\n" +"# jail1_splash_640x480.bmp\n" +"# ipfw2_splash_640x480.bmp\n" +"# ipfw_splash_640x480.bmp\n" +"# v6only_splash_640x480.bmp\n" +"# dnshost_splash_640x480.bmp\n" +"# /ISO\n" +"# fbsd.iso (latest FreeBSD install iso)\n" +"# /VM\n" +"# dnshost.qcow2 (Qemu disk image for dns host)\n" +"# external1.qcow2 (Qemu disk image for external hosts)\n" +"# external2.qcow2 \"\n" +"# external3.qcow2 \"\n" +"# firewall.qcow2 (Qemu disk image for firewall)\n" +"# firewall2.qcow2 (Qemu disk image for firewall2)\n" +"# internal.qcow2 (Qemu disk image for an internal host)\n" +"# jail1.qcow2 (Qemu disk image for an jail1 host)\n" +"# v6only.qcow2 (Qemu disk image for an ipv6only host)\n" +"#\n" +"#\n" +"# Start the VMs and install / test one at a time.\n" +"#\n" +"# sudo /bin/sh firewall.sh\n" +"# sudo /bin/sh firewall2.sh\n" +"# sudo /bin/sh external1.sh\n" +"# sudo /bin/sh external2.sh\n" +"# sudo /bin/sh external3.sh\n" +"# sudo /bin/sh internal.sh\n" +"# sudo /bin/sh jail1.sh\n" +"# sudo /bin/sh v6only.sh\n" +"# sudo /bin/sh dnshost.sh\n" +"#\n" +"# Each install should first utilize DHCP to get a valid IP address\n" +"# After install, proceed to update FreeBSD with \"freebsd-update fetch install\"\n" +"# Install packages:\n" +"# Use whatever shell you prefer. Bash is listed below.\n" +"# Firewall - pkg install bash cmdwatch lynx iperf3 nmap hping3 nginx\n" +"# All others - pkg install bash cmdwatch lynx iperf3 nmap hping3 nginx\n" +"# DNS host - pkg install bind918 dual-dhclient bash cmdwatch lynx nginx\n" +"#\n" +"# Reset all IP addresses for static usage:\n" +"#\n" +"# Host interface: add 172.16.10.100/24 alias\n" +"# Disable any firewall (pf, ipfw, etc.) on the host.\n" +"# BE SURE this is Ok for your environment.\n" +"#\n" +"# Firewall em0 172.16.10.50/24, default gateway 172.16.10.100\n" +"# em1 10.10.10.50/24\n" +"#\n" +"# Firewall2 em0 as needed\n" +"# em1 as needed\n" +"#\n" +"# External1: em0 172.16.10.10/24, default gateway 172.16.10.100\n" +"# External2: em0 172.16.10.20/24, default gateway 172.16.10.100\n" +"# External3: em0 172.16.10.30/24, default gateway 172.16.10.100\n" +"# Internal: em0 10.10.10.200/24, default gateway 10.10.10.50\n" +"#\n" +"# v6only as needed\n" +"# dnshost as needed\n" +"# jail1 as needed\n" +"#\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1956 +#, no-wrap +msgid "export _BASE=/home/jpb/ipfw\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1971 +#, no-wrap +msgid "" +"# Bridge and tap info\n" +"export _FIREWALL_tap0=tap0\n" +"export _EXTERNAL1_tap1=tap1\n" +"export _EXTERNAL2_tap2=tap2\n" +"export _EXTERNAL3_tap3=tap3\n" +"export _FIREWALL_tap4=tap4\n" +"export _INTERNAL_tap5=tap5\n" +"export _JAIL1_tap12=tap12\n" +"export _V6ONLY_tap6=tap6\n" +"export _DNSHOST_tap7=tap7\n" +"export _DNSHOST_tap8=tap8\n" +"export _FIREWALL2_tap9=tap9\n" +"export _FIREWALL2_tap10=tap10\n" +"export _DNSHOST_tap11=tap11\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1975 +#, no-wrap +msgid "" +"export _bridge0_=bridge0\n" +"export _bridge1_=bridge1\n" +"export _bridge2_=bridge2\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1987 +#, no-wrap +msgid "" +"# Disk sizes\n" +"export _EXTERNAL1_hdsize=4G\n" +"export _EXTERNAL2_hdsize=4G\n" +"export _EXTERNAL3_hdsize=4G\n" +"export _FIREWALL_hdsize=4G\n" +"export _FIREWALL2_hdsize=4G\n" +"export _INTERNAL_hdsize=4G\n" +"export _JAIL1_hdsize=8G # Note larger size disk\n" +"export _V6ONLY_hdsize=4G\n" +"export _DNSHOST_hdsize=4G\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:1990 +#, no-wrap +msgid "" +"# Is this needed anymore?\n" +"export _FBSD_ISO=${_BASE}/ISO/fbsd.iso\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2001 +#, no-wrap +msgid "" +"# Boot iso locations\n" +"export _DNSHOST_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _EXTERNAL1_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _EXTERNAL2_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _EXTERNAL3_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _FIREWALL_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _FIREWALL2_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _INTERNAL_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _JAIL1_ISO=${_BASE}/ISO/fbsd.iso\n" +"export _V6ONLY_ISO=${_BASE}/ISO/fbsd.iso\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2012 +#, no-wrap +msgid "" +"# Memory sizes\n" +"export _DNSHOST_mem=1024\n" +"export _EXTERNAL1_mem=1024 # lower all to 512 if necessary\n" +"export _EXTERNAL2_mem=1024\n" +"export _EXTERNAL3_mem=1024\n" +"export _FIREWALL_mem=1024\n" +"export _FIREWALL2_mem=1024\n" +"export _INTERNAL_mem=1024\n" +"export _JAIL1_mem=8192 # Note larger size memory for using ZFS\n" +"export _V6ONLY_mem=1024\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2024 +#, no-wrap +msgid "" +"# Qemu disk image locations.\n" +"export _DNSHOST_img=${_BASE}/VM/dnshost.qcow2\n" +"export _EXTERNAL1_img=${_BASE}/VM/external1.qcow2\n" +"export _EXTERNAL2_img=${_BASE}/VM/external2.qcow2\n" +"export _EXTERNAL3_img=${_BASE}/VM/external3.qcow2\n" +"export _FIREWALL_img=${_BASE}/VM/firewall.qcow2\n" +"export _FIREWALL2_img=${_BASE}/VM/firewall2.qcow2\n" +"export _INTERNAL_img=${_BASE}/VM/internal.qcow2\n" +"export _JAIL1_img=${_BASE}/VM/jail1.qcow2\n" +"export _V6ONLY_img=${_BASE}/VM/v6only.qcow2\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2039 +#, no-wrap +msgid "" +"# MAC addresses\n" +"export _DNSHOST_mac1=02:49:53:53:53:53\n" +"export _DNSHOST_mac2=02:49:53:53:54:54\n" +"export _DNSHOST_mac3=02:49:53:53:55:55\n" +"export _EXTERNAL1_mac=02:45:58:54:31:10\n" +"export _EXTERNAL2_mac=02:45:58:54:32:20\n" +"export _EXTERNAL3_mac=02:45:58:54:33:30\n" +"export _FIREWALL_mac1=02:49:50:46:57:41\n" +"export _FIREWALL2_mac1=02:49:50:00:22:22\n" +"export _FIREWALL_mac2=02:49:50:46:57:42\n" +"export _FIREWALL2_mac2=02:49:50:22:22:22\n" +"export _INTERNAL_mac=02:49:4E:54:0a:42\n" +"export _JAIL1_mac=02:49:ba:ad:ba:be\n" +"export _V6ONLY_mac=02:49:de:ad:be:ef\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2050 +#, no-wrap +msgid "" +"# VM names\n" +"export _DNSHOST_name=DNSHOST\n" +"export _EXTERNAL1_name=EXTERNAL1\n" +"export _EXTERNAL2_name=EXTERNAL2\n" +"export _EXTERNAL3_name=EXTERNAL3\n" +"export _FIREWALL_name=FIREWALL\n" +"export _FIREWALL2_name=FIREWALL2\n" +"export _INTERNAL_name=INTERNAL\n" +"export _JAIL1_name=JAIL1\n" +"export _V6ONLY_name=V6ONLY\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2061 +#, no-wrap +msgid "" +"# Slash images\n" +"export _DNS_splash=${_BASE}/BMP/dns_splash_640x480.bmp\n" +"export _EX1_splash=${_BASE}/BMP/external1_splash_640x480.bmp\n" +"export _EX2_splash=${_BASE}/BMP/external2_splash_640x480.bmp\n" +"export _EX3_splash=${_BASE}/BMP/external3_splash_640x480.bmp\n" +"export _FW_splash=${_BASE}/BMP/ipfw_splash_640x480.bmp\n" +"export _FW2_splash=${_BASE}/BMP/ipfw2_splash_640x480.bmp\n" +"export _INT_splash=${_BASE}/BMP/internal_splash_640x480.bmp\n" +"export _JAIL1_splash=${_BASE}/BMP/jail1_splash_640x480.bmp\n" +"export _V6_splash=${_BASE}/BMP/ipv6_splash_640x480.bmp\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2073 +#, no-wrap +msgid "" +"#\n" +"# Telnet ports\n" +"export _DNSHOST_telnetport=4453\n" +"export _EXTERNAL1_telnetport=4410\n" +"export _EXTERNAL2_telnetport=4420\n" +"export _EXTERNAL3_telnetport=4430\n" +"export _FIREWALL_telnetport=4450\n" +"export _FIREWALL2_telnetport=4250\n" +"export _INTERNAL_telnetport=44200\n" +"export _V6ONLY_telnetport=4460\n" +"export _JAIL1_telnetport=4470\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2134 +#, no-wrap +msgid "" +"# Bridge and Tap configurations.\n" +"#\n" +"# Note: em0 is used for the host interface.\n" +"# Change as needed.\n" +"#\n" +"# Two bridge configuration\n" +"# Standard examples\n" +"#\n" +"# em0\n" +"# |\n" +"# External1(tap1) -----bridge0------(tap0)Firewall\n" +"# External2(tap2) -----+ | (tap4)\n" +"# External3(tap3) -------+ |\n" +"# bridge1\n" +"# |\n" +"# Internal(tap5) -----------------------------+\n" +"#\n" +"# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 em0\n" +"#\n" +"#\n" +"#\n" +"# Two bridge configuration\n" +"# NAT & LSNAT examples\n" +"#\n" +"#\n" +"#\n" +"# (firewall does LSNAT load balancing)\n" +"# External1(tap1) -----bridge0------(tap0)Firewall\n" +"# External2(tap2) -----+ | (tap4)\n" +"# External3(tap3) -------+ |\n" +"# (these function as internal machines) bridge1----em0\n" +"# |\n" +"# Internal(tap5) -----------------------------+\n" +"# (this functions as an external machine)\n" +"#\n" +"# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2 tap3 bridge1 tap4 tap5 em0\n" +"#\n" +"#\n" +"#\n" +"# Two bridge configuration\n" +"# NAT64/DNS64 example\n" +"#\n" +"# ipv4 only NAT64 Translator\n" +"# External1(tap1) ------bridge0-----(tap0)Firewall\n" +"# (ipv4 only) + (tap4)\n" +"# (webserver) | +\n" +"# dnshost(tap7) |\n" +"# (DNS server) |\n" +"# (running DNS64) |\n" +"# (tap8) |\n" +"# | |\n" +"# + |\n" +"# ipv6 only |\n" +"# v6only(tap6) --------bridge1----------------+\n" +"# (v6 only host)\n" +"#\n" +"# sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap7 bridge1 tap4 tap6 tap8\n" +"#\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2140 +#, no-wrap +msgid "*CODE: divert.c*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2152 +#, no-wrap +msgid "" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +"#include \n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2154 +#, no-wrap +msgid "#define DIVERT_PORT 700\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2156 +#, no-wrap +msgid "void hexdump(void \\*ptr, int length, const char *hdr, int flags);\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2163 +#, no-wrap +msgid "" +"int\n" +"main(int argc, char *argv[])\n" +"{\n" +"\tint fd, s;\n" +"\tstruct sockaddr_in sin;\n" +"\tsocklen_t sin_len;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2166 +#, no-wrap +msgid "\tprintf(\"Opening divert on port %d\\n\",DIVERT_PORT);\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2170 +#, no-wrap +msgid "" +"\tfd = socket(PF_DIVERT, SOCK_RAW, 0);\n" +"\tif (fd == -1)\n" +"\t\terr(1, \"socket\");\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2175 +#, no-wrap +msgid "" +"\tmemset(&sin, 0, sizeof(sin));\n" +"\tsin.sin_family = AF_INET;\n" +"\tsin.sin_port = htons(DIVERT_PORT);\n" +"\tsin.sin_addr.s_addr = 0;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2177 +#, no-wrap +msgid "\tsin_len = sizeof(struct sockaddr_in);\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2181 +#, no-wrap +msgid "" +"\ts = bind(fd, (struct sockaddr *) &sin, sin_len);\n" +"\tif (s == -1)\n" +"\t\terr(1, \"bind\");\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2189 +#, no-wrap +msgid "" +"\tfor (;;) {\n" +"\t\tssize_t n;\n" +"\t\tchar packet[IP_MAXPACKET];\n" +"\t\tstruct ip *ip;\n" +"\t\tstruct tcphdr *th;\n" +"\t\tint hlen;\n" +"\t\tchar src[64], dst[64], printbuff[12];\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2194 +#, no-wrap +msgid "" +"\t\tmemset(src, 0, sizeof(src));\n" +"\t\tmemset(dst, 0, sizeof(dst));\n" +"\t\tmemset(printbuff, 0, sizeof(printbuff));\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2206 +#, no-wrap +msgid "" +"\t\tmemset(packet, 0, sizeof(packet));\n" +"\t\tn = recvfrom(fd, packet, sizeof(packet), 0,\n" +"\t\t (struct sockaddr *) &sin, &sin_len);\n" +"\t\tif (n == -1) {\n" +"\t\t\twarn(\"recvfrom\");\n" +"\t\t\tcontinue;\n" +"\t\t}\n" +"\t\tif (n < sizeof(struct ip)) {\n" +"\t\t\twarnx(\"packet is too short\");\n" +"\t\t\tcontinue;\n" +"\t\t}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2214 +#, no-wrap +msgid "" +"\t\tip = (struct ip *) packet;\n" +"\t\thlen = ip->ip_hl << 2;\n" +"\t\tif (hlen < sizeof(struct ip) || ntohs(ip->ip_len) < hlen ||\n" +"\t\t n < ntohs(ip->ip_len)) {\n" +"\t\t\twarnx(\"invalid IPv4 packet\");\n" +"\t\t\tcontinue;\n" +"\t\t}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2216 +#, no-wrap +msgid "\t\tth = (struct tcphdr *) (packet + hlen);\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2220 +#, no-wrap +msgid "" +"\t\tif (inet_ntop(AF_INET, &ip->ip_src, src,\n" +"\t\t sizeof(src)) == NULL)\n" +"\t\t\t(void)strlcpy(src, \"?\", sizeof(src));\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2224 +#, no-wrap +msgid "" +"\t\tif (inet_ntop(AF_INET, &ip->ip_dst, dst,\n" +"\t\t sizeof(dst)) == NULL)\n" +"\t\t\t(void)strlcpy(dst, \"?\", sizeof(dst));\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2231 +#, no-wrap +msgid "" +"\t\tprintf(\"%s:%u -> %s:%u\\n\",\n" +"\t\t src,\n" +"\t\t ntohs(th->th_sport),\n" +"\t\t dst,\n" +"\t\t ntohs(th->th_dport)\n" +"\t\t);\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2236 +#, no-wrap +msgid "" +"\t\t/*\n" +"\t\t* dump the packet in hex and ascii with hexdump(3)\n" +"\t\t*/\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2238 +#, no-wrap +msgid "\t\thexdump((void *)packet, n, \"|\",0);\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2244 +#, no-wrap +msgid "" +"\t\tn = sendto(fd, packet, n, 0, (struct sockaddr *) &sin,\n" +"\t\t sin_len);\n" +"\t\tif (n == -1)\n" +"\t\t\twarn(\"sendto\");\n" +"\t}\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-b/_index.adoc:2247 +#, no-wrap +msgid "" +"\treturn 0;\n" +"}\n" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc @@ -0,0 +1,144 @@ +--- +title: Appendix C. Networking References +prev: books/ipfw-primer/ipfw-appendix-b +next: books/ipfw-primer/ipfw-appendix-d +description: Networking References +tags: ["firewall", "IPFW", "Virtual Machine", "VM", "QEMU"] +showBookMenu: true +weight: 110 +path: "/books/ipfw-primer/ipfw-appendix-c/" +--- + +[appendix] +[[appendix-c]] += Appendix C: Networking References +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: C +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + + +References for understanding IP based communications and building firewalls. + +From /etc/rc.firewall: + +[subs=+quotes] +---- + Building Internet Firewalls, 2nd Edition + Brent Chapman and Elizabeth Zwicky + + O'Reilly & Associates, Inc + ISBN 1-56592-871-7 + http://www.ora.com/ + http://www.oreilly.com/catalog/fire2/ + + For a more advanced treatment of Internet Security read: + + Firewalls and Internet Security: Repelling the Wily Hacker, 2nd Edition + William R. Cheswick, Steven M. Bellowin, Aviel D. Rubin + + Addison-Wesley / Prentice Hall + ISBN 0-201-63466-X + http://www.pearsonhighered.com/ + http://www.pearsonhighered.com/educator/academic/product/0,3110,020163466X,00.html +---- + +Additional references: + +[subs=+quotes] +---- + TCP/IP Illustrated, Volume 1: The Protocols + Author: W. Richard Stevens + Publisher: Addison-Wesley Professional + Publisher Website: Addison-Wesley Professional + Date Published: November 1994 + ISBN: 978-0201633467 + + The TCP/IP Guide: A Comprehensive, Illustrated Internet Protocols Reference + Author: Charles M. Kozierok + Publisher: No Starch Press + Publisher Website: No Starch Press + Date Published: October 2005 + ISBN: 978-1593270476 + + Internetworking with TCP/IP Volume One: Principles, Protocols, and Architecture + Author: Douglas E. Comer + Publisher: Pearson + Publisher Website: Pearson + Date Published: 6th Edition, 2013 + ISBN: 978-0136085300 + + Computer Networks: A Systems Approach + Authors: Larry L. Peterson and Bruce S. Davie + Publisher: Morgan Kaufmann + Publisher Website: Morgan Kaufmann + Date Published: 6th Edition, 2021 + ISBN: 978-0128182000 +---- + +Additional resources regarding firewalls: + +[subs=+quotes] +---- + Network Security, Firewalls, and VPNs + Authors: J. Michael Stewart, Denise Kinsey + Publisher: Jones & Bartlett Learning + Publisher Website: Jones & Bartlett Learning + Date Published: October 2020 + ISBN: 978-1284183696 + + Firewall Fundamentals + Author: David W. Chapman Jr. + Publisher: Cisco Press + Publisher Website: Cisco Press + Date Published: June 2006 + ISBN: 978-1587052213 + + The Best Damn Firewall Book Period + Author: Thomas W. Shinder + Publisher: Syngress + Publisher Website: Syngress + Date Published: January 2008 + ISBN: 978-1597492188 + + Guide to Firewalls and Network Security: Intrusion Detection and VPNs + Authors: Michael E. Whitman, Herbert J. Mattord, Richard Austin, Greg Holden + Publisher: Cengage Learning + Publisher Website: Cengage Learning + Date Published: 2008 + ISBN: 978-1435420168 +---- + + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.po @@ -0,0 +1,194 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:1 +#, no-wrap +msgid "Networking References" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:1 +#, no-wrap +msgid "Appendix C. Networking References" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:14 +#, no-wrap +msgid "Appendix C: Networking References" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:54 +msgid "" +"References for understanding IP based communications and building firewalls." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:56 +msgid "From /etc/rc.firewall:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:61 +#, no-wrap +msgid "" +" Building Internet Firewalls, 2nd Edition\n" +" Brent Chapman and Elizabeth Zwicky\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:66 +#, no-wrap +msgid "" +" O'Reilly & Associates, Inc\n" +" ISBN 1-56592-871-7\n" +" http://www.ora.com/\n" +" http://www.oreilly.com/catalog/fire2/\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:68 +#, no-wrap +msgid " For a more advanced treatment of Internet Security read:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:71 +#, no-wrap +msgid "" +" Firewalls and Internet Security: Repelling the Wily Hacker, 2nd Edition\n" +" William R. Cheswick, Steven M. Bellowin, Aviel D. Rubin\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:76 +#, no-wrap +msgid "" +" Addison-Wesley / Prentice Hall\n" +" ISBN 0-201-63466-X\n" +" http://www.pearsonhighered.com/\n" +" http://www.pearsonhighered.com/educator/academic/product/0,3110,020163466X,00.html\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:79 +msgid "Additional references:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:88 +#, no-wrap +msgid "" +" TCP/IP Illustrated, Volume 1: The Protocols\n" +" Author: W. Richard Stevens\n" +" Publisher: Addison-Wesley Professional\n" +" Publisher Website: Addison-Wesley Professional\n" +" Date Published: November 1994\n" +" ISBN: 978-0201633467\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:95 +#, no-wrap +msgid "" +" The TCP/IP Guide: A Comprehensive, Illustrated Internet Protocols Reference\n" +" Author: Charles M. Kozierok\n" +" Publisher: No Starch Press\n" +" Publisher Website: No Starch Press\n" +" Date Published: October 2005\n" +" ISBN: 978-1593270476\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:102 +#, no-wrap +msgid "" +" Internetworking with TCP/IP Volume One: Principles, Protocols, and Architecture\n" +" Author: Douglas E. Comer\n" +" Publisher: Pearson\n" +" Publisher Website: Pearson\n" +" Date Published: 6th Edition, 2013\n" +" ISBN: 978-0136085300\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:109 +#, no-wrap +msgid "" +" Computer Networks: A Systems Approach\n" +" Authors: Larry L. Peterson and Bruce S. Davie\n" +" Publisher: Morgan Kaufmann\n" +" Publisher Website: Morgan Kaufmann\n" +" Date Published: 6th Edition, 2021\n" +" ISBN: 978-0128182000\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:112 +msgid "Additional resources regarding firewalls:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:121 +#, no-wrap +msgid "" +" Network Security, Firewalls, and VPNs\n" +" Authors: J. Michael Stewart, Denise Kinsey\n" +" Publisher: Jones & Bartlett Learning\n" +" Publisher Website: Jones & Bartlett Learning\n" +" Date Published: October 2020\n" +" ISBN: 978-1284183696\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:128 +#, no-wrap +msgid "" +" Firewall Fundamentals\n" +" Author: David W. Chapman Jr.\n" +" Publisher: Cisco Press\n" +" Publisher Website: Cisco Press\n" +" Date Published: June 2006\n" +" ISBN: 978-1587052213\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:135 +#, no-wrap +msgid "" +" The Best Damn Firewall Book Period\n" +" Author: Thomas W. Shinder\n" +" Publisher: Syngress\n" +" Publisher Website: Syngress\n" +" Date Published: January 2008\n" +" ISBN: 978-1597492188\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-c/_index.adoc:142 +#, no-wrap +msgid "" +" Guide to Firewalls and Network Security: Intrusion Detection and VPNs\n" +" Authors: Michael E. Whitman, Herbert J. Mattord, Richard Austin, Greg Holden\n" +" Publisher: Cengage Learning\n" +" Publisher Website: Cengage Learning\n" +" Date Published: 2008\n" +" ISBN: 978-1435420168\n" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc @@ -0,0 +1,198 @@ +--- +title: Appendix D. Managing Serial Terminals with tmux and screen +prev: books/ipfw-primer/ipfw-appendix-c +next: books/ipfw-primer/ipfw-appendix-e +description: Additional Material +tags: ["firewall", "IPFW", "Virtual Machine", "VM", "QEMU"] +showBookMenu: true +weight: 120 +path: "/books/ipfw-primer/ipfw-appendix-d/" +--- + +[appendix] +[[appendix-d]] += Appendix D. Managing Serial Terminals with tmux and screen +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: D +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +== Using man:tmux[1] for Managing Serial Terminals + +Install *tmux* with: +indexterm:[tmux] + +[subs=+quotes] +---- +# *pkg install tmux* +---- + +Run *sh swim.sh* in the SCRIPTS directory to start up the session manager running *tmux*. +indexterm:[tmux] + +[[ipfw-tmux-session-appendix-]] +.Starting Up tmux(1) Session Manager +image::ipfw-introduction020.png["Starting Up tmux(1) Session Manager. Refer to paragraphs below".] + +The figure shows five named windows in one session (session [0]) with the *tmux* status line in green at the bottom: +indexterm:[tmux] + +*Simplified tmux(1) Usage* + +*tmux* has a hierarchical organization. + +. *Sessions* - starts a session implicitly when *tmux* is run +indexterm:[session] +.. *Windows* - adds a window with the command "tmux add-window" which can take a number of parameters +indexterm:[window] +*tmux* allows multiple windows in a session at the same time. +The current window is starred ("***") in the status bar at the bottom of the main window. +... *Panes* - splits a window into one or more panes either horizontally, or vertically +indexterm:[pane] + +The *swim.sh* script shows how to set up one session with several windows. +Panes are not used. + +*tmux* is controlled by the user typing in any open window or pane. +*tmux* uses kbd:[Ctl]+kbd:[b] as its control key. +indexterm:[control key] +Give *tmux* commands by typing the control key followed by one or more letters. +To move from window to window use kbd:[Ctl]+kbd:[b] kbd:[n] to move to the next window or kbd:[Ctl]+kbd:[b] kbd:[p] to move to the previous window. +Use kbd:[Ctl]+kbd:[b] kbd:[?] for a list of all key bindings. +indexterm:[binding, key] + +Type *tmux kill-server* in any session window to completely leave *tmux*. +indexterm:[tmux] + +Consult the *tmux* manual page man:tmux[1] for more usage details. + +*Accessing the QEMU Serial Consoles* + +To access the VM serial consoles, move to the indicated window and telnet to the port on the local host for that VM: +indexterm:[console,serial] + +[subs=+quotes] +---- +Move to the *external1* window in *tmux*, then + +~/ipfw/SCRIPTS $ telnet localhost 4410 +Trying ::1... +Connected to localhost. +Escape character is '^]'. + +FreeBSD/amd64 (external1) (ttyu0) + +login: +---- + +The *swim.sh* script has the following un-commented lines. +Un-comment additional lines as needed + +* *0:bash* - a terminal window of the user running *swim.sh* +* *1:firewall* - a terminal window to access the *firewall* VM +* *2:external1* - a terminal window to access the *external1* VM +* *3:external2* - a terminal window to access the *external2* VM +* *4:external3* - a terminal window to access the *external3* VM + +The current window is marked with the '***' character in the status bar. +indexterm:[status bar] + +Note that the *swim.sh* script has entries for all windows used in this book. +indexterm:[swim.sh] +Uncomment the entries needed. + +Run *sh swim.sh* in the SCRIPTS directory to start up the session manager running *tmux*. + +== Using man:screen[1] for Managing Serial Terminals + +Install *screen* with: +indexterm:[screen] + +[subs=+quotes] +---- +# *pkg install screen* +---- + +*screen*, like *tmux*, is a terminal window manager. +*screen* has its own control key - kbd:[Ctl]+kbd:[a], and like *tmux* a list of key bindings is available at kbd:[Ctl]+kbd:[a] kbd:[?]. +indexterm:[control key] + +By default, it does not use a status line, and once activated, it looks like no manager is active at all. +Type *screen -ls* to determine if there is an active screen session running. +indexterm:[session] + +To display a status line in a live session use: + +kbd:[Ctrl]+kbd:[a] kbd:[:] hardstatus alwayslastline + +kbd:[Ctrl]+kbd:[a] kbd:[:] hardstatus string "%{= bw}%-w%{= rW}[%n %t]%{-}%+w %=%{= kW} %H | %Y-%m-%d %c" + +To always display the highlighted status line, edit the [.filename]#.screenrc# file in the user '$HOME` directory and add: +indexterm:[.screenrc] + +[subs=+quotes] +---- +hardstatus alwayslastline +hardstatus string "%{= bw}%-w%{= rW}[%n %t]%{-}%+w %=%{= kW} %H | %Y-%m-%d %c" +---- + +To close all *screen* windows immediately and exit: +indexterm:[screen] + +[subs=+quotes] +---- +% *screen -X quit* +---- + +The *scim.sh* script has the following un-commented lines. +indexterm:[scim.sh] +Un-comment additional lines as needed + +* *0:bash* - a terminal window of the user running *scim.sh* +* *1:firewall* - a terminal window to access the *firewall* VM +* *2:external1* - a terminal window to access the *external1* VM +* *3:external2* - a terminal window to access the *external2* VM +* *4:external3* - a terminal window to access the *external3* VM + +The current window is highlighted in the status bar. +indexterm:[status bar] + +Note that the *scim.sh* script has entries for all windows used in this book. +indexterm:[scim.sh] +Uncomment the entries needed. + +Run *sh scim.sh* in the SCRIPTS directory to start up the session manager running *screen*. +indexterm:[scim.sh] + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.po @@ -0,0 +1,362 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:1 +#, no-wrap +msgid "Additional Material" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:1 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:14 +#, no-wrap +msgid "Appendix D. Managing Serial Terminals with tmux and screen" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:52 +#, no-wrap +msgid "Using man:tmux[1] for Managing Serial Terminals" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:56 +msgid "Install *tmux* with: indexterm:[tmux]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:60 +#, no-wrap +msgid "# *pkg install tmux*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:64 +msgid "" +"Run *sh swim.sh* in the SCRIPTS directory to start up the session manager " +"running *tmux*. indexterm:[tmux]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:66 +#, no-wrap +msgid "Starting Up tmux(1) Session Manager" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:67 +#, no-wrap +msgid "Starting Up tmux(1) Session Manager. Refer to paragraphs below" +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:67 +#, no-wrap +msgid "ipfw-introduction020.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:71 +msgid "" +"The figure shows five named windows in one session (session [0]) with the " +"*tmux* status line in green at the bottom: indexterm:[tmux]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:73 +#, no-wrap +msgid "*Simplified tmux(1) Usage*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:75 +#, no-wrap +msgid "*tmux* has a hierarchical organization.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:78 +#, no-wrap +msgid "" +"*Sessions* - starts a session implicitly when *tmux* is run\n" +"indexterm:[session]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:82 +#, no-wrap +msgid "" +"*Windows* - adds a window with the command \"tmux add-window\" which can take a number of parameters\n" +"indexterm:[window]\n" +"*tmux* allows multiple windows in a session at the same time.\n" +"The current window is starred (\"***\") in the status bar at the bottom of the main window.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:84 +#, no-wrap +msgid "" +"*Panes* - splits a window into one or more panes either horizontally, or vertically\n" +"indexterm:[pane]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:87 +msgid "" +"The *swim.sh* script shows how to set up one session with several windows. " +"Panes are not used." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:95 +#, no-wrap +msgid "" +"*tmux* is controlled by the user typing in any open window or pane.\n" +"*tmux* uses kbd:[Ctl]+kbd:[b] as its control key.\n" +"indexterm:[control key]\n" +"Give *tmux* commands by typing the control key followed by one or more letters.\n" +"To move from window to window use kbd:[Ctl]+kbd:[b] kbd:[n] to move to the next window or kbd:[Ctl]+kbd:[b] kbd:[p] to move to the previous window.\n" +"Use kbd:[Ctl]+kbd:[b] kbd:[?] for a list of all key bindings.\n" +"indexterm:[binding, key]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:98 +msgid "" +"Type *tmux kill-server* in any session window to completely leave *tmux*. " +"indexterm:[tmux]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:100 +msgid "Consult the *tmux* manual page man:tmux[1] for more usage details." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:102 +#, no-wrap +msgid "*Accessing the QEMU Serial Consoles*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:105 +msgid "" +"To access the VM serial consoles, move to the indicated window and telnet to " +"the port on the local host for that VM: indexterm:[console,serial]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:109 +#, no-wrap +msgid "Move to the *external1* window in *tmux*, then\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:114 +#, no-wrap +msgid "" +"~/ipfw/SCRIPTS $ telnet localhost 4410\n" +"Trying ::1...\n" +"Connected to localhost.\n" +"Escape character is '^]'.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:116 +#, no-wrap +msgid "FreeBSD/amd64 (external1) (ttyu0)\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:118 +#, no-wrap +msgid "login:\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:122 +msgid "" +"The *swim.sh* script has the following un-commented lines. Un-comment " +"additional lines as needed" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:124 +#, no-wrap +msgid "*0:bash* - a terminal window of the user running *swim.sh*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:125 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:185 +#, no-wrap +msgid "*1:firewall* - a terminal window to access the *firewall* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:126 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:186 +#, no-wrap +msgid "*2:external1* - a terminal window to access the *external1* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:127 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:187 +#, no-wrap +msgid "*3:external2* - a terminal window to access the *external2* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:128 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:188 +#, no-wrap +msgid "*4:external3* - a terminal window to access the *external3* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:131 +msgid "" +"The current window is marked with the '***' character in the status bar. " +"indexterm:[status bar]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:135 +msgid "" +"Note that the *swim.sh* script has entries for all windows used in this " +"book. indexterm:[swim.sh] Uncomment the entries needed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:137 +msgid "" +"Run *sh swim.sh* in the SCRIPTS directory to start up the session manager " +"running *tmux*." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:138 +#, no-wrap +msgid "Using man:screen[1] for Managing Serial Terminals" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:142 +msgid "Install *screen* with: indexterm:[screen]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:146 +#, no-wrap +msgid "# *pkg install screen*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:151 +#, no-wrap +msgid "" +"*screen*, like *tmux*, is a terminal window manager.\n" +"*screen* has its own control key - kbd:[Ctl]+kbd:[a], and like *tmux* a list of key bindings is available at kbd:[Ctl]+kbd:[a] kbd:[?].\n" +"indexterm:[control key]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:155 +msgid "" +"By default, it does not use a status line, and once activated, it looks like " +"no manager is active at all. Type *screen -ls* to determine if there is an " +"active screen session running. indexterm:[session]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:157 +msgid "To display a status line in a live session use:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:159 +msgid "kbd:[Ctrl]+kbd:[a] kbd:[:] hardstatus alwayslastline" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:161 +msgid "" +"kbd:[Ctrl]+kbd:[a] kbd:[:] hardstatus string \"%{= bw}%-w%{= rW}[%n %t]%{-}%" +"+w %=%{= kW} %H | %Y-%m-%d %c\"" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:164 +msgid "" +"To always display the highlighted status line, edit the [.filename]#." +"screenrc# file in the user '$HOME` directory and add: indexterm:[.screenrc]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:169 +#, no-wrap +msgid "" +"hardstatus alwayslastline\n" +"hardstatus string \"%{= bw}%-w%{= rW}[%n %t]%{-}%+w %=%{= kW} %H | %Y-%m-%d %c\"\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:173 +msgid "To close all *screen* windows immediately and exit: indexterm:[screen]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:177 +#, no-wrap +msgid "% *screen -X quit*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:182 +msgid "" +"The *scim.sh* script has the following un-commented lines. indexterm:[scim." +"sh] Un-comment additional lines as needed" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:184 +#, no-wrap +msgid "*0:bash* - a terminal window of the user running *scim.sh*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:191 +msgid "" +"The current window is highlighted in the status bar. indexterm:[status bar]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:195 +msgid "" +"Note that the *scim.sh* script has entries for all windows used in this " +"book. indexterm:[scim.sh] Uncomment the entries needed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-d/_index.adoc:198 +msgid "" +"Run *sh scim.sh* in the SCRIPTS directory to start up the session manager " +"running *screen*. indexterm:[scim.sh]" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc @@ -0,0 +1,530 @@ +--- +title: Appendix E. DNS Server Configuration +prev: books/ipfw-primer/ipfw-appendix-d/ +next: books/ipfw-primer/ipfw-index/ +description: DNS Server Configuration +tags: ["firewall", "IPFW", "Virtual Machine", "VM", "QEMU"] +showBookMenu: true +weight: 130 +path: "/books/ipfw-primer/ipfw-appendix-e/" +--- + +[appendix] +[[appendix-e]] += Appendix E: DNS Server Configuration +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: E +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +DNS configuration for IPFW Primer book. + +[subs=+quotes] +---- + +*Manifest of dnshost scripts and file.* + +File: dnshost_usrlocaletc_namedb.tgz + + Description: Contains the configuration for the BIND 9 DNS services that run on this machine. + + Installation: + + Install bind9 package first, then untar this collection as follows: + + # cd /usr/local/etc + # tar xvzf dnshost_usrlocaletc_namedb.tgz + + Contents: + + % tar tvzf dnshost_usrlocaletc_namedb.tgz + drwxr-xr-x 0 root wheel 0 Nov 19 12:00 namedb/ + -rw-r--r-- 0 bind bind 2403 Nov 19 11:59 namedb/bind.keys + drwxr-xr-x 0 bind bind 0 Nov 19 11:59 namedb/dynamic/ + -rw-r--r-- 0 bind bind 2618 Dec 2 12:34 namedb/named.conf + -rw-r--r-- 0 bind bind 21992 Nov 19 11:59 namedb/named.conf.sample + -rw-r--r-- 0 bind bind 927 Nov 19 11:59 namedb/named.root + -rw-r--r-- 0 bind bind 3317 Nov 19 11:59 namedb/named.root.SAVE + drwxr-xr-x 0 bind bind 0 Dec 2 15:35 namedb/primary/ + -rw------- 0 bind bind 100 Nov 19 11:59 namedb/rndc.key + drwxr-xr-x 0 bind bind 0 Nov 19 11:59 namedb/secondary/ + drwxr-xr-x 0 bind bind 0 Nov 19 11:59 namedb/working/ + -rw-r--r-- 0 bind bind 297 Nov 19 11:59 namedb/working/managed-keys.bind + -rw-r--r-- 0 bind bind 355 Nov 19 11:59 namedb/primary/ptr_198.51 + -rw-r--r-- 0 bind bind 465 Nov 19 11:59 namedb/primary/ptr_203.0 + -rw-r--r-- 0 bind bind 693 Dec 1 19:29 namedb/primary/example.com + -rw-r--r-- 0 bind bind 148 Nov 19 11:59 namedb/primary/empty + -rw-r--r-- 0 bind bind 407 Nov 19 14:12 namedb/primary/ptr_ipv6 + -rw-r--r-- 0 bind bind 287 Dec 2 15:35 namedb/primary/managed-keys.bind + -rw-r--r-- 0 bind bind 226 Nov 19 11:59 namedb/primary/localhost-reverse + -rw-r--r-- 0 bind bind 158 Nov 19 11:59 namedb/primary/localhost-forward + -rw-r--r-- 0 bind bind 351 Dec 1 19:30 namedb/primary/ptr_192.168 + % + + + ===================================================================================== + +*bind.keys* + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# The bind.keys file is used to override the built-in DNSSEC trust anchors +# which are included as part of BIND 9. The only trust anchors it contains +# are for the DNS root zone ("."). Trust anchors for any other zones MUST +# be configured elsewhere; if they are configured here, they will not be +# recognized or used by named. +# +# To use the built-in root key, set "dnssec-validation auto;" in the +# named.conf options, or else leave "dnssec-validation" unset. If +# "dnssec-validation" is set to "yes", then the keys in this file are +# ignored; keys will need to be explicitly configured in named.conf for +# validation to work. "auto" is the default setting, unless named is +# built with "configure --disable-auto-validation", in which case the +# default is "yes". +# +# This file is NOT expected to be user-configured. +# +# Servers being set up for the first time can use the contents of this file +# as initializing keys; thereafter, the keys in the managed key database +# will be trusted and maintained automatically. +# +# These keys are current as of Mar 2019. If any key fails to initialize +# correctly, it may have expired. In that event you should replace this +# file with a current version. The latest version of bind.keys can always +# be obtained from ISC at https://www.isc.org/bind-keys. +# +# See https://data.iana.org/root-anchors/root-anchors.xml for current trust +# anchor information for the root zone. + +trust-anchors { + # This key (20326) was published in the root zone in 2017. + . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; + + + + ===================================================================================== + + +*named.conf* + +// Refer to the named.conf(5) and named(8) man pages, and the documentation +// in /usr/local/share/doc/bind for more details. + +acl trusted-queriers { + 203.0.113.0/24; + 2001:db8:12::/64; + 127.0.0.1; + ::1; + localhost; +}; + +acl v6only-networks { + 2001:db8:12::/64; +}; + + +options { + directory "/usr/local/etc/namedb/primary"; + pid-file "/var/run/named/pid"; + dump-file "/var/dump/named_dump.db"; + statistics-file "/var/stats/named.stats"; + listen-on { any; }; + listen-on-v6 { any; }; + recursion no; + allow-transfer { trusted-queriers; }; + +// NOTE: Remove comments when using DNS64 +// dns64 64:FF9B::/96 { +// clients { any; }; +// exclude { 64:FF9B::/96; ::ffff:0000:0000/96; }; +// suffix ::; +// }; + +}; + + + +// forward zone +zone "example.com" { + type primary; + file "/usr/local/etc/namedb/primary/example.com"; + allow-transfer {trusted-queriers;}; +}; + +// reverse zones for 203.0, 198.51, 192.168, and 2001:0db8 +zone "0.203.in-addr.arpa" { + type primary; + file "/usr/local/etc/namedb/primary/ptr_203.0"; + allow-transfer {trusted-queriers;}; +}; + +zone "51.198.in-addr.arpa"{ + type primary; + file "/usr/local/etc/namedb/primary/ptr_198.51"; + allow-transfer {trusted-queriers;}; +}; + +zone "2.1.0.0.8.b.d.0.1.0.0.2.ip6.arpa" { + type primary; + file "/usr/local/etc/namedb/primary/ptr_ipv6"; + allow-transfer {trusted-queriers; }; +}; + +zone "168.192.in-addr.arpa" { + type primary; + file "/usr/local/etc/namedb/primary/ptr_192.168"; + allow-transfer {trusted-queriers;}; +}; + + +// Block below added by BIND9 +// RFCs 1912, 5735 and 6303 (and BCP 32 for localhost) +zone "localhost" { type primary; file "/usr/local/etc/namedb/primary/localhost-forward"; }; +zone "127.in-addr.arpa" { type primary; file "/usr/local/etc/namedb/primary/localhost-reverse"; }; +zone "255.in-addr.arpa" { type primary; file "/usr/local/etc/namedb/primary/empty"; }; +// RFC 1912-style zone for IPv6 localhost address (RFC 6303) +zone "0.ip6.arpa" { type primary; file "/usr/local/etc/namedb/primary/localhost-reverse"; }; +// "This" Network (RFCs 1912, 5735 and 6303) +zone "0.in-addr.arpa" { type primary; file "/usr/local/etc/namedb/primary/empty"; }; + + + +// Our own root zone file so we don't leak out to the Internet +zone "." { + type master; + file "/usr/local/etc/namedb/named.root"; + allow-transfer {trusted-queriers; }; + }; + + + + ===================================================================================== + + +*named.root* + +; This file holds the information on root name servers needed to +; initialize cache of Internet domain name servers +; (e.g. reference this file in the "cache . " +; configuration file of BIND domain name servers). +; +; This file is made available by InterNIC +; under anonymous FTP as +; file /domain/named.cache +; on server FTP.INTERNIC.NET +; -OR- RS.INTERNIC.NET +; +; last update: November 16, 2017 +; related version of root zone: 2017111601 +; +; FORMERLY NS.INTERNIC.NET +; + + +$TTL 3600 + +. 3600 IN SOA dnshost.example.com. jpb.dnshost.example.com ( + 100 ; serial + 14400 ; refresh + 7200 ; retry + 28800 ; expire + 64000 ) ; min neg cache expire + +. 3600 NS dnshost.example.com. +dnshost.example.com. 3600 A 203.0.113.53 +dnshost.example.com. 3600 AAAA 2001:db8:12::53 + + + ===================================================================================== + + +*rndc.key* + + +key "rndc-key" { + algorithm hmac-sha256; + secret "wesiGsTgu7OwV44aA6C2P8XmZdW4z/YdPJ4D/vRNPTM="; +}; + + + + ===================================================================================== + + +*empty* + + +$TTL 3h +@ SOA @ nobody.localhost. 42 1d 12h 1w 3h + ; Serial, Refresh, Retry, Expire, Neg. cache TTL + +@ NS @ + +; Silence a BIND warning +@ A 127.0.0.1 + + + ===================================================================================== + + +*example.com* + + +$TTL 3600 +@ IN SOA example.com. jpb.example.com. ( + 5 ; Serial + 3h ; Refresh + 1h ; Retry + 1w ; Expire + 1h ) ; Negative Cache TTL +; +; name servers - NS records +@ IN NS dnshost.example.com. + +; name servers - A records +dnshost IN A 203.0.113.53 +;external1 IN A 203.0.113.10 +external1 IN A 192.168.1.2 +external2 IN A 203.0.113.20 +external3 IN A 203.0.113.30 +firewall IN A 203.0.113.50 +firewall-em0 IN A 203.0.113.50 +firewall-em1 IN A 198.51.100.50 +firewall-em1 IN AAAA 2001:db8:12::50 +internal IN A 198.51.100.200 + +; name servers - AAAA records +dnshost IN AAAA 2001:db8:12::53 +v6only IN AAAA 2001:db8:12::6 + + + ===================================================================================== + + +*localhost-forward* + + +$TTL 3h +localhost. SOA localhost. nobody.localhost. 42 1d 12h 1w 3h + ; Serial, Refresh, Retry, Expire, Neg. cache TTL + + NS localhost. + + A 127.0.0.1 + AAAA ::1 + + + ===================================================================================== + + +*localhost-reverse* + + +$TTL 3h +@ SOA localhost. nobody.localhost. 42 1d 12h 1w 3h + ; Serial, Refresh, Retry, Expire, Neg. cache TTL + + NS localhost. + +1.0.0 PTR localhost. + +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 PTR localhost. + + + + ===================================================================================== + + +*managed-keys.bind* + + +$TTL 0 ; 0 seconds +. IN SOA . . ( + 100 ; serial + 0 ; refresh (0 seconds) + 0 ; retry (0 seconds) + 0 ; expire (0 seconds) + 0 ; minimum (0 seconds) + ) + KEYDATA 20241202213508 19700101000000 19700101000000 0 0 0 ; placeholder + + + ===================================================================================== + + +*ptr_192.168* + + + +$TTL 3600 +@ IN SOA example.com. jpb.example.com. ( + 3 ; Serial + 3h ; Refresh + 1h ; Retry + 1w ; Expire + 1h ) ; Negative Cache TTL +; + + +; name servers - NS records + IN NS dnshost.example.com. + +; PTR Records + +53.1 IN PTR dnshost.example.com. +2.1 IN PTR external1.example.com. + + + + ===================================================================================== + + +*ptr_198.51* + + +$TTL 3600 +@ IN SOA example.com. jpb.example.com. ( + 3 ; Serial + 3h ; Refresh + 1h ; Retry + 1w ; Expire + 1h ) ; Negative Cache TTL +; + + +; name servers - NS records + IN NS dnshost.example.com. + +; PTR Records + +50.100 IN PTR firewall-em1.example.com. +200.100 IN PTR internal.example.com. + + + + ===================================================================================== + + +*ptr_203.0* + + + +$TTL 3600 +@ IN SOA example.com. jpb.example.com. ( + 3 ; Serial + 3h ; Refresh + 1h ; Retry + 1w ; Expire + 1h ) ; Negative Cache TTL +; + + +; name servers - NS records + IN NS dnshost.example.com. + +; PTR Records + +53.113 IN PTR dnshost.example.com. +10.113 IN PTR external1.example.com. +20.113 IN PTR external2.example.com. +30.113 IN PTR external3.example.com. +50.113 IN PTR firewall-em0.example.com. + + + + ===================================================================================== + + +*ptr_ipv6* + + +$TTL 3600 +@ IN SOA example.com. jpb.example.com. ( + 3 ; Serial + 3h ; Refresh + 1h ; Retry + 1w ; Expire + 1h ) ; Negative Cache TTL +; + +@ IN NS dnshost.example.com. + + +$ORIGIN 0.0.0.0.2.1.0.0.8.b.d.0.1.0.0.2.ip6.arpa. +3.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR dnshost.example.com. +6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR v6only.example.com. + + + + ===================================================================================== + + +*managed-keys.bind* + + +$ORIGIN . +$TTL 0 ; 0 seconds +@ IN SOA . . ( + 100 ; serial + 0 ; refresh (0 seconds) + 0 ; retry (0 seconds) + 0 ; expire (0 seconds) + 0 ; minimum (0 seconds) + ) + KEYDATA 20220502020339 19700101000000 19700101000000 0 0 0 ; placeholder + + + + ===================================================================================== + +---- + + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.po @@ -0,0 +1,701 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:1 +#, no-wrap +msgid "DNS Server Configuration" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:1 +#, no-wrap +msgid "Appendix E. DNS Server Configuration" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:14 +#, no-wrap +msgid "Appendix E: DNS Server Configuration" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:53 +msgid "DNS configuration for IPFW Primer book." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:58 +#, no-wrap +msgid "*Manifest of dnshost scripts and file.*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:60 +#, no-wrap +msgid "File: dnshost_usrlocaletc_namedb.tgz\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:62 +#, no-wrap +msgid " Description: Contains the configuration for the BIND 9 DNS services that run on this machine.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:64 +#, no-wrap +msgid " Installation:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:66 +#, no-wrap +msgid " Install bind9 package first, then untar this collection as follows:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:69 +#, no-wrap +msgid "" +" # cd /usr/local/etc\n" +" # tar xvzf dnshost_usrlocaletc_namedb.tgz\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:71 +#, no-wrap +msgid " Contents:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:95 +#, no-wrap +msgid "" +" % tar tvzf dnshost_usrlocaletc_namedb.tgz\n" +" drwxr-xr-x 0 root wheel 0 Nov 19 12:00 namedb/\n" +" -rw-r--r-- 0 bind bind 2403 Nov 19 11:59 namedb/bind.keys\n" +" drwxr-xr-x 0 bind bind 0 Nov 19 11:59 namedb/dynamic/\n" +" -rw-r--r-- 0 bind bind 2618 Dec 2 12:34 namedb/named.conf\n" +" -rw-r--r-- 0 bind bind 21992 Nov 19 11:59 namedb/named.conf.sample\n" +" -rw-r--r-- 0 bind bind 927 Nov 19 11:59 namedb/named.root\n" +" -rw-r--r-- 0 bind bind 3317 Nov 19 11:59 namedb/named.root.SAVE\n" +" drwxr-xr-x 0 bind bind 0 Dec 2 15:35 namedb/primary/\n" +" -rw------- 0 bind bind 100 Nov 19 11:59 namedb/rndc.key\n" +" drwxr-xr-x 0 bind bind 0 Nov 19 11:59 namedb/secondary/\n" +" drwxr-xr-x 0 bind bind 0 Nov 19 11:59 namedb/working/\n" +" -rw-r--r-- 0 bind bind 297 Nov 19 11:59 namedb/working/managed-keys.bind\n" +" -rw-r--r-- 0 bind bind 355 Nov 19 11:59 namedb/primary/ptr_198.51\n" +" -rw-r--r-- 0 bind bind 465 Nov 19 11:59 namedb/primary/ptr_203.0\n" +" -rw-r--r-- 0 bind bind 693 Dec 1 19:29 namedb/primary/example.com\n" +" -rw-r--r-- 0 bind bind 148 Nov 19 11:59 namedb/primary/empty\n" +" -rw-r--r-- 0 bind bind 407 Nov 19 14:12 namedb/primary/ptr_ipv6\n" +" -rw-r--r-- 0 bind bind 287 Dec 2 15:35 namedb/primary/managed-keys.bind\n" +" -rw-r--r-- 0 bind bind 226 Nov 19 11:59 namedb/primary/localhost-reverse\n" +" -rw-r--r-- 0 bind bind 158 Nov 19 11:59 namedb/primary/localhost-forward\n" +" -rw-r--r-- 0 bind bind 351 Dec 1 19:30 namedb/primary/ptr_192.168\n" +" %\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:98 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:154 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:250 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:287 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:300 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:316 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:350 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:366 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:384 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:401 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:428 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:454 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:484 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:508 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:527 +#, no-wrap +msgid " =====================================================================================\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:100 +#, no-wrap +msgid "*bind.keys*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:111 +#, no-wrap +msgid "" +"# Copyright (C) Internet Systems Consortium, Inc. (\"ISC\")\n" +"#\n" +"# SPDX-License-Identifier: MPL-2.0\n" +"#\n" +"# This Source Code Form is subject to the terms of the Mozilla Public\n" +"# License, v. 2.0. If a copy of the MPL was not distributed with this\n" +"# file, you can obtain one at https://mozilla.org/MPL/2.0/.\n" +"#\n" +"# See the COPYRIGHT file distributed with this work for additional\n" +"# information regarding copyright ownership.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:139 +#, no-wrap +msgid "" +"# The bind.keys file is used to override the built-in DNSSEC trust anchors\n" +"# which are included as part of BIND 9. The only trust anchors it contains\n" +"# are for the DNS root zone (\".\"). Trust anchors for any other zones MUST\n" +"# be configured elsewhere; if they are configured here, they will not be\n" +"# recognized or used by named.\n" +"#\n" +"# To use the built-in root key, set \"dnssec-validation auto;\" in the\n" +"# named.conf options, or else leave \"dnssec-validation\" unset. If\n" +"# \"dnssec-validation\" is set to \"yes\", then the keys in this file are\n" +"# ignored; keys will need to be explicitly configured in named.conf for\n" +"# validation to work. \"auto\" is the default setting, unless named is\n" +"# built with \"configure --disable-auto-validation\", in which case the\n" +"# default is \"yes\".\n" +"#\n" +"# This file is NOT expected to be user-configured.\n" +"#\n" +"# Servers being set up for the first time can use the contents of this file\n" +"# as initializing keys; thereafter, the keys in the managed key database\n" +"# will be trusted and maintained automatically.\n" +"#\n" +"# These keys are current as of Mar 2019. If any key fails to initialize\n" +"# correctly, it may have expired. In that event you should replace this\n" +"# file with a current version. The latest version of bind.keys can always\n" +"# be obtained from ISC at https://www.isc.org/bind-keys.\n" +"#\n" +"# See https://data.iana.org/root-anchors/root-anchors.xml for current trust\n" +"# anchor information for the root zone.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:150 +#, no-wrap +msgid "" +"trust-anchors {\n" +" # This key (20326) was published in the root zone in 2017.\n" +" . initial-key 257 3 8 \"AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3\n" +" +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv\n" +" ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF\n" +" 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e\n" +" oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd\n" +" RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN\n" +" R1AkUTV74bU=\";\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:157 +#, no-wrap +msgid "*named.conf*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:160 +#, no-wrap +msgid "" +"// Refer to the named.conf(5) and named(8) man pages, and the documentation\n" +"// in /usr/local/share/doc/bind for more details.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:168 +#, no-wrap +msgid "" +"acl trusted-queriers {\n" +"\t203.0.113.0/24;\n" +"\t2001:db8:12::/64;\n" +"\t127.0.0.1;\n" +"\t::1;\n" +"\tlocalhost;\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:172 +#, no-wrap +msgid "" +"acl v6only-networks {\n" +"\t2001:db8:12::/64;\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:183 +#, no-wrap +msgid "" +"options {\n" +"\tdirectory\t\"/usr/local/etc/namedb/primary\";\n" +"\tpid-file\t\"/var/run/named/pid\";\n" +"\tdump-file\t\"/var/dump/named_dump.db\";\n" +"\tstatistics-file\t\"/var/stats/named.stats\";\n" +"\tlisten-on\t{ any; };\n" +"\tlisten-on-v6\t{ any; };\n" +"\trecursion \tno;\n" +" \tallow-transfer { trusted-queriers; };\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:190 +#, no-wrap +msgid "" +"// NOTE: Remove comments when using DNS64\n" +"//\tdns64 64:FF9B::/96 {\n" +"//\tclients { any; };\n" +"//\texclude { 64:FF9B::/96; ::ffff:0000:0000/96; };\n" +"//\tsuffix ::;\n" +"//\t};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:192 +#, no-wrap +msgid "};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:201 +#, no-wrap +msgid "" +"// forward zone\n" +"zone \"example.com\" {\n" +"\ttype primary;\n" +"\tfile \"/usr/local/etc/namedb/primary/example.com\";\n" +"\tallow-transfer {trusted-queriers;};\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:208 +#, no-wrap +msgid "" +"// reverse zones for 203.0, 198.51, 192.168, and 2001:0db8\n" +"zone \"0.203.in-addr.arpa\" {\n" +"\ttype primary;\n" +"\tfile \"/usr/local/etc/namedb/primary/ptr_203.0\";\n" +"\tallow-transfer {trusted-queriers;};\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:214 +#, no-wrap +msgid "" +"zone \"51.198.in-addr.arpa\"{\n" +"\ttype primary;\n" +"\tfile \"/usr/local/etc/namedb/primary/ptr_198.51\";\n" +"\tallow-transfer {trusted-queriers;};\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:220 +#, no-wrap +msgid "" +"zone \"2.1.0.0.8.b.d.0.1.0.0.2.ip6.arpa\" {\n" +"\ttype primary;\n" +"\tfile \"/usr/local/etc/namedb/primary/ptr_ipv6\";\n" +"\tallow-transfer {trusted-queriers; };\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:226 +#, no-wrap +msgid "" +"zone \"168.192.in-addr.arpa\" {\n" +"\ttype primary;\n" +"\tfile \"/usr/local/etc/namedb/primary/ptr_192.168\";\n" +"\tallow-transfer {trusted-queriers;};\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:237 +#, no-wrap +msgid "" +"// Block below added by BIND9\n" +"// RFCs 1912, 5735 and 6303 (and BCP 32 for localhost)\n" +"zone \"localhost\"\t\t{ type primary; file \"/usr/local/etc/namedb/primary/localhost-forward\"; };\n" +"zone \"127.in-addr.arpa\"\t{ type primary; file \"/usr/local/etc/namedb/primary/localhost-reverse\"; };\n" +"zone \"255.in-addr.arpa\"\t{ type primary; file \"/usr/local/etc/namedb/primary/empty\"; };\n" +"// RFC 1912-style zone for IPv6 localhost address (RFC 6303)\n" +"zone \"0.ip6.arpa\"\t{ type primary; file \"/usr/local/etc/namedb/primary/localhost-reverse\"; };\n" +"// \"This\" Network (RFCs 1912, 5735 and 6303)\n" +"zone \"0.in-addr.arpa\"\t{ type primary; file \"/usr/local/etc/namedb/primary/empty\"; };\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:246 +#, no-wrap +msgid "" +"// Our own root zone file so we don't leak out to the Internet\n" +"zone \".\" {\n" +"\ttype master;\n" +"\tfile \"/usr/local/etc/namedb/named.root\";\n" +"\tallow-transfer {trusted-queriers; };\n" +" };\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:253 +#, no-wrap +msgid "*named.root*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:270 +#, no-wrap +msgid "" +"; This file holds the information on root name servers needed to\n" +"; initialize cache of Internet domain name servers\n" +"; (e.g. reference this file in the \"cache . \"\n" +"; configuration file of BIND domain name servers).\n" +";\n" +"; This file is made available by InterNIC\n" +"; under anonymous FTP as\n" +"; file /domain/named.cache\n" +"; on server FTP.INTERNIC.NET\n" +"; -OR- RS.INTERNIC.NET\n" +";\n" +"; last update: November 16, 2017\n" +"; related version of root zone: 2017111601\n" +";\n" +"; FORMERLY NS.INTERNIC.NET\n" +";\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:273 +#, no-wrap +msgid "$TTL 3600\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:280 +#, no-wrap +msgid "" +".\t3600\tIN\tSOA\tdnshost.example.com. jpb.dnshost.example.com (\n" +"\t\t\t\t100 \t; serial\n" +"\t\t\t\t14400\t; refresh\n" +"\t\t\t\t7200\t; retry\n" +"\t\t\t\t28800\t; expire\n" +"\t\t\t\t64000\t) ; min neg cache expire\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:284 +#, no-wrap +msgid "" +". 3600\tNS\tdnshost.example.com.\n" +"dnshost.example.com.\t3600\tA\t203.0.113.53\n" +"dnshost.example.com.\t3600\tAAAA\t2001:db8:12::53\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:290 +#, no-wrap +msgid "*rndc.key*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:296 +#, no-wrap +msgid "" +"key \"rndc-key\" {\n" +"\talgorithm hmac-sha256;\n" +"\tsecret \"wesiGsTgu7OwV44aA6C2P8XmZdW4z/YdPJ4D/vRNPTM=\";\n" +"};\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:303 +#, no-wrap +msgid "*empty*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:308 +#, no-wrap +msgid "" +"$TTL 3h\n" +"@ SOA @ nobody.localhost. 42 1d 12h 1w 3h\n" +"\t; Serial, Refresh, Retry, Expire, Neg. cache TTL\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:310 +#, no-wrap +msgid "@\tNS\t@\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:313 +#, no-wrap +msgid "" +"; Silence a BIND warning\n" +"@\tA\t127.0.0.1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:319 +#, no-wrap +msgid "*example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:331 +#, no-wrap +msgid "" +"$TTL 3600\n" +"@ IN SOA example.com. jpb.example.com. (\n" +"\t\t\t 5\t\t; Serial\n" +"\t\t\t 3h\t\t; Refresh\n" +"\t\t\t 1h\t\t; Retry\n" +"\t\t\t 1w\t\t; Expire\n" +"\t\t\t 1h )\t; Negative Cache TTL\n" +";\n" +"; name servers - NS records\n" +"@ IN NS dnshost.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:343 +#, no-wrap +msgid "" +"; name servers - A records\n" +"dnshost\t\t\tIN\tA\t203.0.113.53\n" +";external1\t\tIN\tA\t203.0.113.10\n" +"external1\t\tIN\tA\t192.168.1.2\n" +"external2\t\tIN\tA\t203.0.113.20\n" +"external3\t\tIN\tA\t203.0.113.30\n" +"firewall\t\tIN\tA\t203.0.113.50\n" +"firewall-em0\t\tIN\tA\t203.0.113.50\n" +"firewall-em1\t\tIN\tA\t198.51.100.50\n" +"firewall-em1\t\tIN\tAAAA\t2001:db8:12::50\n" +"internal\t\tIN\tA\t198.51.100.200\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:347 +#, no-wrap +msgid "" +"; name servers - AAAA records\n" +"dnshost\t\t\tIN\tAAAA\t2001:db8:12::53\n" +"v6only\t\t\tIN\tAAAA\t2001:db8:12::6\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:353 +#, no-wrap +msgid "*localhost-forward*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:358 +#, no-wrap +msgid "" +"$TTL 3h\n" +"localhost. SOA localhost. nobody.localhost. 42 1d 12h 1w 3h\n" +"\t; Serial, Refresh, Retry, Expire, Neg. cache TTL\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:360 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:376 +#, no-wrap +msgid "\tNS\tlocalhost.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:363 +#, no-wrap +msgid "" +"\tA\t127.0.0.1\n" +"\tAAAA\t::1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:369 +#, no-wrap +msgid "*localhost-reverse*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:374 +#, no-wrap +msgid "" +"$TTL 3h\n" +"@ SOA localhost. nobody.localhost. 42 1d 12h 1w 3h\n" +"\t; Serial, Refresh, Retry, Expire, Neg. cache TTL\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:378 +#, no-wrap +msgid "1.0.0\tPTR\tlocalhost.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:380 +#, no-wrap +msgid "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 PTR localhost.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:387 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:511 +#, no-wrap +msgid "*managed-keys.bind*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:398 +#, no-wrap +msgid "" +"$TTL 0\t; 0 seconds\n" +".\t\t\tIN SOA\t. . (\n" +"\t\t\t\t100 ; serial\n" +"\t\t\t\t0 ; refresh (0 seconds)\n" +"\t\t\t\t0 ; retry (0 seconds)\n" +"\t\t\t\t0 ; expire (0 seconds)\n" +"\t\t\t\t0 ; minimum (0 seconds)\n" +"\t\t\t\t)\n" +"\t\t\tKEYDATA\t20241202213508 19700101000000 19700101000000 0 0 0 ; placeholder\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:404 +#, no-wrap +msgid "*ptr_192.168*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:415 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:441 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:468 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:497 +#, no-wrap +msgid "" +"$TTL 3600\n" +"@ IN SOA example.com. jpb.example.com. (\n" +"\t\t\t 3\t\t; Serial\n" +"\t\t\t 3h\t\t; Refresh\n" +"\t\t\t 1h\t\t; Retry\n" +"\t\t\t 1w\t\t; Expire\n" +"\t\t\t 1h )\t; Negative Cache TTL\n" +";\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:419 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:445 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:472 +#, no-wrap +msgid "" +"; name servers - NS records\n" +" IN NS dnshost.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:421 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:447 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:474 +#, no-wrap +msgid "; PTR Records\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:424 +#, no-wrap +msgid "" +"53.1 \tIN\tPTR\tdnshost.example.com.\n" +"2.1 \tIN\tPTR\texternal1.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:431 +#, no-wrap +msgid "*ptr_198.51*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:450 +#, no-wrap +msgid "" +"50.100\tIN\tPTR\tfirewall-em1.example.com.\n" +"200.100\tIN\tPTR\tinternal.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:457 +#, no-wrap +msgid "*ptr_203.0*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:480 +#, no-wrap +msgid "" +"53.113\tIN\tPTR\tdnshost.example.com.\n" +"10.113\tIN\tPTR\texternal1.example.com.\n" +"20.113\tIN\tPTR\texternal2.example.com.\n" +"30.113\tIN\tPTR\texternal3.example.com.\n" +"50.113\tIN\tPTR\tfirewall-em0.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:487 +#, no-wrap +msgid "*ptr_ipv6*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:499 +#, no-wrap +msgid "@\tIN\tNS\tdnshost.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:504 +#, no-wrap +msgid "" +"$ORIGIN 0.0.0.0.2.1.0.0.8.b.d.0.1.0.0.2.ip6.arpa.\n" +"3.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR dnshost.example.com.\n" +"6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR v6only.example.com.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-appendix-e/_index.adoc:523 +#, no-wrap +msgid "" +"$ORIGIN .\n" +"$TTL 0\t; 0 seconds\n" +"@\t\t\tIN SOA\t. . (\n" +"\t\t\t\t100 ; serial\n" +"\t\t\t\t0 ; refresh (0 seconds)\n" +"\t\t\t\t0 ; retry (0 seconds)\n" +"\t\t\t\t0 ; expire (0 seconds)\n" +"\t\t\t\t0 ; minimum (0 seconds)\n" +"\t\t\t\t)\n" +"\t\t\tKEYDATA\t20220502020339 19700101000000 19700101000000 0 0 0 ; placeholder\n" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc @@ -0,0 +1,1192 @@ +--- +title: Chapter 4. IPFW Dummynet and Traffic Shaping +prev: books/ipfw-primer/ipfw-rules +next: books/ipfw-primer/ipfw-nat +description: IPFW Dummynet +tags: ["IPFW", "dummynet"] +showBookMenu: true +weight: 50 +path: "/books/ipfw-primer/ipfw-dummynet/" +--- + +[[dummynet]] += IPFW Dummynet and Traffic Shaping +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 4 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +FreeBSD's *dummynet* is not a network for dummies. +indexterm:[dummynet] +It is a sophisticated network traffic shaping tool for bandwidth usage and scheduling algorithms. +In this use of *ipfw*, the focus is not on ruleset development, although rules are still used to select traffic to pass to *dummynet* objects. +Instead, the focus is on setting up a system to shape traffic flows. +*dummynet* provides tools to model scheduling, queuing, and similar tasks similar to the real-world Internet. + +*dummynet* works with three main types of objects - a *pipe*, a *queue*, and a *sched* (short for scheduler) which also happen to be the three keywords to now examine. +indexterm:[pipe] indexterm:[queue] indexterm:[sched] + +A *pipe* (_not to be confused with a Unix pipe(2)!_) is a model of a network link with a configurable bandwidth, and propagation delay. + +A *queue* is an abstraction used to implement packet scheduling using one of several different scheduling algorithms. +Packets sent to a queue are first grouped into flows according to a mask on a 5-tuple (protocol, source address, source port, destination address, destination port) specification. +Flows are then passed to the scheduler associated with the queue, and each flow uses scheduling parameters (weight, bandwidth, etc.) as configured in the queue itself. +A *sched* (scheduler) in turn is connected to a *pipe* (an emulated link) and arbitrates the link's bandwidth among backlogged flows according to weights and to the features of the scheduling algorithm in use. + +Network performance testing is a complex subject that can encompass many variables across many different testing strategies. +To understand the basics behind *dummynet*, it is not necessary to dive into the deepest levels of network performance testing - only enough to understand how to use *dummynet*. +Also, these tests are restricted to using IP and TCP exclusively. + +*Setting Up for Traffic Measurement* + +Most of the examples in this section can be done with the architecture used in the crossref:ipfw-operation[ipfw-intro-simple-lab, original lab setup] in Chapter 2, copied here for reference: + +[[ipfw-dummynet-lab]] +.IPFW Lab for *dummynet* Examples +image::ipfw-dummynet100.png["IPFW Lab for *dummynet* Examples. Refer to paragraphs below."] + +Use this *bridge* and *tap* configuration on the FreeBSD host system: + +[subs=+quotes] +---- +% *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap2* +% */bin/sh swim.sh* # or scim.sh for screen(1) +% */bin/sh runvm.sh firewall external1 external2* +---- + +Apply the correct addressing for each VM in this example. + +Where necessary, additional virtual machines can be created and added to the bridge. + +== Measuring Default Throughput + +The idea behind *dummynet* is that it lets one model and/or shape network speeds, available bandwidth, and scheduling algorithms. +indexterm:[dummynet] indexterm:[scheduling algorithm] +But it is first necessary to know what the current transfer speeds are for the current environment (QEMU virtual machines over a FreeBSD bridge). +To find out, here is a short detour to learn *iperf3*, the network bandwidth testing tool used to perform simple transfer and bitrate calculations. +indexterm:[iperf3] + +*iperf3*, can determine the effective throughput of data transfer for a network. +Sometimes called "goodput", this is the basic speed the user sees for transferring data across the network - the value that is unencumbered by protocol type and overhead. +indexterm:[goodput] + +To use *iperf3*, ensure that the software is installed on both the *firewall* VM system, and the *external1* VM (and *external2* and *external3*), and that *ipfw* on the *firewall* VM is disabled (# *kldunload ipfw*). +indexterm:[iperf3] + +The basic operation of *iperf3* is as a client-server architecture, so on the *external1* VM system, start the *iperf3* software in server mode: + +[subs=+quotes] +---- +# *iperf3 -s* #<--- run *iperf3* in server mode# +----------------------------------------------------------- +Server listening on 5201 (test #1) +----------------------------------------------------------- + . . . +---- + +Then, on the *firewall* VM, run the client: + +[subs=+quotes] +---- +# *iperf3 -c 203.0.113.10* #<--- connect to external1 server and send test data# +Connecting to host 203.0.113.10, port 5201 +[ 5] local 203.0.113.50 port 19359 connected to 203.0.113.10 port 5201 +[ ID] Interval Transfer Bitrate Retr Cwnd +[ 5] 0.00-1.03 sec 12.5 MBytes 102 Mbits/sec 0 1.07 MBytes +[ 5] 1.03-2.09 sec 13.8 MBytes 108 Mbits/sec 0 1.07 MBytes +[ 5] 2.09-3.07 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes +[ 5] 3.07-4.09 sec 12.5 MBytes 103 Mbits/sec 0 1.07 MBytes +[ 5] 4.09-5.08 sec 12.5 MBytes 106 Mbits/sec 0 1.07 MBytes +[ 5] 5.08-6.09 sec 12.5 MBytes 105 Mbits/sec 0 1.07 MBytes +[ 5] 6.09-7.07 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes +[ 5] 7.07-8.05 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes +[ 5] 8.05-9.04 sec 12.5 MBytes 106 Mbits/sec 0 1.07 MBytes +[ 5] 9.04-10.02 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes +- - - - - - - - - - - - - - - - - - - - - - - - - +[ ID] Interval Transfer Bitrate Retr +[ 5] 0.00-10.02 sec 126 MBytes 106 Mbits/sec 0 sender +[ 5] 0.00-10.02 sec 126 MBytes 106 Mbits/sec receiver + +iperf Done. +# +---- + +A key test for measuring throughput is to send a file of data and measure the transfer speed. +indexterm:[throughput] indexterm:[transfer speed] +To create the file, use man:jot[1] on the *firewall* VM: +indexterm:[jot] + +[subs=+quotes] +---- +# *jot -r -s "" 10000000 0 9 > A.bin* +---- + +This command creates a file of random ASCII digits exactly 10,000,001 bytes long. +(Note that it can take anywhere from 30 seconds to two minutes to create the file on a QEMU virtual machine.) + +To transfer the file to the server on the *external1* VM use this command: + +[subs=+quotes] +---- +# *iperf3 -F A.bin -c 203.0.113.10 -t 10* +Connecting to host 203.0.113.10, port 5201 +[ 5] local 203.0.113.50 port 51657 connected to 203.0.113.10 port 5201 +[ ID] Interval Transfer Bitrate Retr Cwnd +[ 5] 0.00-1.04 sec 12.5 MBytes 101 Mbits/sec 0 490 KBytes +[ 5] 1.04-1.52 sec 5.81 MBytes 101 Mbits/sec 0 490 KBytes +- - - - - - - - - - - - - - - - - - - - - - - - - +[ ID] Interval Transfer Bitrate Retr +[ 5] 0.00-1.52 sec 18.3 MBytes 101 Mbits/sec 0 sender + Sent 18.3 MByte / 18.3 MByte (100%) of A.bin +[ 5] 0.00-1.52 sec 18.3 MBytes 101 Mbits/sec receiver +iperf Done. +# +---- + +Running this command several times shows that a consistent average bitrate for throughput on this system is about 101Mbits/second - or about 18.3 MBytes/second. +(Your values will differ on your local machine.) + +There is now a baseline TCP-based "goodput" value for testing *dummynet* traffic shaping commands. +indexterm:[goodput] indexterm:[dummynet] indexterm:[traffic shaping] + +== IPFW Commands for Dummynet + +To use *dummynet*, load the kernel module *dummynet.ko* in addition to the *ipfw.ko* module on the *firewall* VM: + +[subs=+quotes] +---- +# *kldload ipfw* +# *kldload dummynet* +load_dn_sched dn_sched FIFO loaded +load_dn_sched dn_sched QFQ loaded +load_dn_sched dn_sched RR loaded +load_dn_sched dn_sched WF2Q+ loaded +load_dn_sched dn_sched PRIO loaded +load_dn_sched dn_sched FQ_CODEL loaded +load_dn_sched dn_sched FQ_PIE loaded +load_dn_aqm dn_aqm CODEL loaded +load_dn_aqm dn_aqm PIE loaded +# +---- + +*dummynet* announces the schedulers it is configured to use. + +=== Simple Pipe Configuration + +Recall that *dummynet* uses *pipes*, *queues*, and *sched* (schedulers) to shape traffic. +indexterm:[pipe] indexterm:[queue] indexterm:[sched] + +To see *dummynet* in action, create a *pipe* with limited bandwidth, and assign it to a rule matching traffic to the *external1* VM: +indexterm:[bandwidth] + +[subs=+quotes] +---- +# Load the *ipfw* kernel module if needed: +# *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +# +# *ipfw pipe 1 config bw #300Kbit/s#* +# *ipfw pipe 1 show* +00001: #300.000 Kbit/s# 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +# +---- + +The above output shows the *pipe* configration limiting bandwidth (bw) to 300Kbits/sec. + +[NOTE] +==== +Recent versions of FreeBSD now use the command alias *dnctl* for configuration of pipes, queues, and schedulers. +See man:dnctl[8] for details. +==== + +indexterm:[dnctl] + +Now add *ipfw* rules to send traffic between the *firewall* VM and the *external1* VM through the *pipe*: + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +00100 check-state :default +# +# *ipfw add 1000 pipe 1 ip from any to any* +01000 pipe 1 ip from any to any +# +# *ipfw list* +00100 check-state :default +01000 pipe 1 ip from any to any +65535 deny ip from any to any +# +---- + +By adding the matching phrase *"ip from any to any"* and assigning it to *pipe 1*, the *firewall* VM is directed to send all ip-based traffic through *pipe 1*, now configured as a 300K bps link. + +By re-running the basic file transfer command for *iperf3* these difference take shape: +indexterm:[iperf3] + +[subs=+quotes] +---- +# *iperf3 -F A.bin -c 203.0.113.10 -t 10 --length 1460* +Connecting to host 203.0.113.10, port 5201 +[ 5] local 203.0.113.50 port 39558 connected to 203.0.113.10 port 5201 +[ ID] Interval Transfer Bitrate Retr Cwnd +[ 5] 0.00-1.01 sec 75.6 KBytes 612 Kbits/sec 0 25.6 KBytes +[ 5] 1.01-2.01 sec 41.3 KBytes 339 Kbits/sec 0 51.0 KBytes +[ 5] 2.01-3.01 sec 45.6 KBytes 374 Kbits/sec 0 62.3 KBytes +[ 5] 3.01-4.01 sec 27.1 KBytes 222 Kbits/sec 0 66.6 KBytes +[ 5] 4.01-5.01 sec 35.6 KBytes 292 Kbits/sec 0 66.6 KBytes +[ 5] 5.01-6.01 sec 44.2 KBytes 362 Kbits/sec 0 66.6 KBytes +[ 5] 6.01-7.01 sec 21.4 KBytes 175 Kbits/sec 0 66.6 KBytes +[ 5] 7.01-8.01 sec 37.1 KBytes 304 Kbits/sec 0 66.6 KBytes +[ 5] 8.01-9.01 sec 48.5 KBytes 397 Kbits/sec 0 66.6 KBytes +[ 5] 9.01-10.01 sec 22.8 KBytes 187 Kbits/sec 0 66.6 KBytes +- - - - - - - - - - - - - - - - - - - - - - - - - +[ ID] Interval Transfer Bitrate Retr +[ 5] 0.00-10.01 sec 399 KBytes 327 Kbits/sec 0 sender + Sent 399 KByte / 9.54 MByte (4%) of A.bin +[ 5] 0.00-10.73 sec 379 KBytes 289 Kbits/sec receiver + +iperf Done. +---- + +[TIP] +==== +If the systems returns the error "iperf3: error - control socket has closed unexpectedly", simply re-run the command. +==== + +Here, during *iperf3*'s 10-second run, the *ipfw* *dummynet* configuration limited the transfer speed to an average of about 327 Kbits/sec, and only about 4% of the entire 10MB file was transferred. +indexterm:[iperf3] indexterm:[dummynet] + +To see how to use *dummynet* to configure different link speeds, set up a second *pipe*: + +[subs=+quotes] +---- +# *ipfw pipe 2 config bw 3Mbit/s* +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +00002: 3.000 Mbit/s 0 ms burst 0 +q131074 50 sl. 0 flows (1 buckets) sched 65538 weight 0 lmax 0 pri 0 droptail + sched 65538 type FIFO flags 0x0 0 buckets 0 active +# +---- + +This *pipe* is set up to be 10 times faster (3Mb/sec instead of 300Kb/sec) than *pipe 1*. +indexterm:[pipe] +To test this pipe, start up the *external2* VM and run *iperf3 -s*. +Then reconfigure the *ipfw* rules to send to the *external2* VM through *pipe 2*: + + +[subs=+quotes] +---- +# *ipfw list* +00100 check-state :default +01000 pipe 1 ip from any to any +65535 deny ip from any to any +# +# *ipfw delete 1000* +# +# *ipfw add 1000 pipe 1 ip from me to 203.0.113.10 // external1* +01000 pipe 1 ip from me to 203.0.113.10 +# +# *ipfw add 1100 pipe 1 ip from 203.0.113.10 to me // external1* +01100 pipe 1 ip from 203.0.113.10 to me +# +# *ipfw add 2000 pipe 2 ip from me to 203.0.113.20 // external2* +02000 pipe 2 ip from me to 203.0.113.20 +# +# *ipfw add 2100 pipe 2 ip from 203.0.113.20 to me // external2* +02100 pipe 2 ip from 203.0.113.20 to me +# +# *ipfw list* +00100 check-state :default +01000 pipe 1 ip from me to 203.0.113.10 +01100 pipe 1 ip from 203.0.113.10 to me +02000 pipe 2 ip from me to 203.0.113.20 +02100 pipe 2 ip from 203.0.113.20 to me +65535 deny ip from any to any +# +---- + +As expected, *pipe 2* is approximately 10 times faster than *pipe 1*: +indexterm:[pipe] + +[subs=+quotes] +---- +# *iperf3 -F A.bin -c 203.0.113.20 -t 10 --length 1460* +Connecting to host 203.0.113.20, port 5201 +[ 5] local 203.0.113.50 port 48108 connected to 203.0.113.20 port 5201 +[ ID] Interval Transfer Bitrate Retr Cwnd +[ 5] 0.00-1.01 sec 399 KBytes 3.24 Mbits/sec 0 64.0 KBytes +[ 5] 1.01-2.01 sec 358 KBytes 2.93 Mbits/sec 0 64.0 KBytes +[ 5] 2.01-3.01 sec 359 KBytes 2.94 Mbits/sec 0 64.0 KBytes +[ 5] 3.01-4.01 sec 364 KBytes 2.98 Mbits/sec 0 64.0 KBytes +[ 5] 4.01-5.01 sec 368 KBytes 3.01 Mbits/sec 0 66.9 KBytes +[ 5] 5.01-6.01 sec 332 KBytes 2.72 Mbits/sec 0 66.9 KBytes +[ 5] 6.01-7.01 sec 362 KBytes 2.97 Mbits/sec 0 66.9 KBytes +[ 5] 7.01-8.01 sec 355 KBytes 2.91 Mbits/sec 0 66.9 KBytes +[ 5] 8.01-9.01 sec 345 KBytes 2.83 Mbits/sec 0 66.9 KBytes +[ 5] 9.01-10.01 sec 344 KBytes 2.81 Mbits/sec 0 66.9 KBytes +- - - - - - - - - - - - - - - - - - - - - - - - - +[ ID] Interval Transfer Bitrate Retr +[ 5] 0.00-10.01 sec 3.50 MBytes 2.93 Mbits/sec 0 sender + Sent 3.50 MByte / 9.54 MByte (36%) of A.bin +[ 5] 0.00-10.06 sec 3.48 MBytes 2.90 Mbits/sec receiver + +iperf Done. +---- + +Next, change the *pipe* configuration without changing the ruleset. +indexterm:[ruleset] +Below, the *pipe 1* bandwidth is changed to the equivalent of a telecommunications T1 line as in the days of old: +indexterm:[T1 line] + +[subs=+quotes] +---- +# *ipfw pipe 1 config bw 1544Kbit/s* +# *ipfw pipe show* +00001: #1.544 Mbit/s# 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +00002: 3.000 Mbit/s 0 ms burst 0 +q131074 50 sl. 0 flows (1 buckets) sched 65538 weight 0 lmax 0 pri 0 droptail + sched 65538 type FIFO flags 0x0 0 buckets 0 active +# +---- + +Resending the 10MB file across the T1 configured line shows these results: + +[subs=+quotes] +---- +root@firewall:~ # iperf3 -F A.bin -c 203.0.113.10 -t 10 --length 1460 +Connecting to host 203.0.113.10, port 5201 +[ 5] local 203.0.113.50 port 35768 connected to 203.0.113.10 port 5201 +[ ID] Interval Transfer Bitrate Retr Cwnd +[ 5] 0.00-1.01 sec 235 KBytes 1.91 Mbits/sec 0 25.6 KBytes +[ 5] 1.01-2.01 sec 173 KBytes 1.41 Mbits/sec 0 25.6 KBytes +[ 5] 2.01-3.01 sec 195 KBytes 1.60 Mbits/sec 0 27.0 KBytes +[ 5] 3.01-4.01 sec 174 KBytes 1.42 Mbits/sec 0 45.0 KBytes +[ 5] 4.01-5.01 sec 182 KBytes 1.50 Mbits/sec 0 62.1 KBytes +[ 5] 5.01-6.01 sec 178 KBytes 1.46 Mbits/sec 0 62.1 KBytes +[ 5] 6.01-7.01 sec 174 KBytes 1.42 Mbits/sec 0 62.1 KBytes +[ 5] 7.01-8.01 sec 180 KBytes 1.47 Mbits/sec 0 62.1 KBytes +[ 5] 8.01-9.01 sec 204 KBytes 1.67 Mbits/sec 0 62.1 KBytes +[ 5] 9.01-10.01 sec 178 KBytes 1.46 Mbits/sec 0 62.1 KBytes +- - - - - - - - - - - - - - - - - - - - - - - - - +[ ID] Interval Transfer Bitrate Retr +[ 5] #0.00-10.01 sec 1.83 MBytes 1.53 Mbits/sec 0 sender# + #Sent 1.83 MByte / 9.54 MByte (19%) of A.bin# +[ 5] #0.00-10.21 sec 1.81 MBytes 1.48 Mbits/sec receiver# + +iperf Done. +---- + +About half of the 3Mbits/sec speed of *pipe 2*, again as expected. + +indexterm:[pipe] +By definition, a *pipe* has just one *queue*, and it is subject to "First In First Out" (FIFO) operation. +indexterm:[queue] indexterm:[FIFO] +All traffic that flows through this *pipe* shares the same characteristics. + +However, creating a *pipe* also does something else. +It creates a default *sched* (scheduler) that governs the *pipe*: +indexterm:[sched] + +[subs=+quotes] +---- +Start with no pipes or schedulers + +# +# *ipfw pipe list* +# +# *ipfw sched list* +# + +Create a simple pipe. + +# *ipfw pipe 1 config bw 100KBit/s* +# +# *ipfw pipe list* +00001: 100.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +# + +Observe the default scheduler for this pipe + +# *ipfw sched list* +#00001: 100.000 Kbit/s 0 ms burst 0# + #sched 1 type WF2Q+ flags 0x0 0 buckets 0 active# +# +---- + +indexterm:[WF2Q+ algorithm] + +The default scheduler for a new *pipe* is of type `WF2Q+`, a version of the Weighted Fair Queueing algorithm for packet transfer. +indexterm:[WF2Q+ algorithm] + +This is now a single *pipe* of type FIFO operation that is managed by a `WF2Q+` scheduling algorithm. + +The man:ipfw[8] man page makes note of several other scheduling algorithms. +These can be selected by using the "type" keyword on the *pipe* command. +The *type* keyword selects the type of scheduler applied to the *pipe* - not the type of the *pipe* itself (the *pipe* remains FIFO): + +[subs=+quotes] +---- +# *ipfw pipe list* +# +# *ipfw sched list* +# + +Create a pipe and assign a scheduler of type Round Robin (Deficit Round Robin) + +# *ipfw pipe 1 config bw 100KBit/s #type rr#* +# +# *ipfw pipe list* +00001: 100.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +# + +View the new sheduler of type RR (Deficit Round Robin) + +# *ipfw sched list* +00001: 100.000 Kbit/s 0 ms burst 0 + sched 1 type #RR# flags 0x0 0 buckets 0 active +# +---- + +indexterm:[Round Robin scheduler] + +*pipes and *sched*s (schedulers) are tightly bound. +indexterm:[pipe] indexterm:[sched] +In fact, there is no command to delete a scheduler. +The scheduler is deleted when the pipe is deleted. + +Note however that the scheduler can be configured independently if desired. +Here is a change to the scheduler type from the above type RR to QFQ, a variant of WF2Q+: +indexterm:[QFQ algorithm] + +[subs=+quotes] +---- +# +# *ipfw sched 1 config #type qfq#* +Bump qfq weight to 1 (was 0) +Bump qfq maxlen to 1500 (was 0) +# +# *ipfw sched list* +00001: 100.000 Kbit/s 0 ms burst 0 + sched 1 type #QFQ# flags 0x0 0 buckets 0 active +# +---- + +There are other keywords that can be added to a *pipe* specification: *delay*, *burst*, *profile*, *weight*, *buckets*, *mask*, *noerror*, *plr*, *queue*, *red* or *gred*, *codel*, and *pie*. +These are described in the man:ipfw[8] man page. + +A contrived example might be: + +[subs=+quotes] +---- + +Start fresh + +# *ipfw pipe 1 delete* +# +# *ipfw pipe 1 config bw 100kbit/s delay 20 burst 2000 weight 40 buckets 256 mask src-ip 0x000000ff noerror plr 0.01 queue 75 red .3/25/30/.5 type qfq* +# +# *ipfw pipe list* +00001: 100.000 Kbit/s 20 ms burst 2000 +q131073 75 sl.plr 0.010000 0 flows (1 buckets) sched 65537 weight 40 lmax 0 pri 0 + RED w_q 0.299988 min_th 25 max_th 30 max_p 0.500000 + sched 65537 type FIFO flags 0x1 256 buckets 0 active + mask: 0x00 0x000000ff/0x0000 -> 0x00000000/0x0000 +# +# *ipfw sched list* +00001: 100.000 Kbit/s 20 ms burst 2000 + sched 1 type QFQ flags 0x1 256 buckets 0 active + mask: 0x00 0x000000ff/0x0000 -> 0x00000000/0x0000 +# +---- + +indexterm:[delay] indexterm:[burst] indexterm:[weight] indexterm:[buckets] indexterm:[red] indexterm:[qfq] + +Setting up two separate *pipes* to send data to the same destination is overkill. +It is like setting up two separate network links between the two points. +While that may be desirable for redundancy or high-availability, it makes no difference for bandwidth allocation. +(Yes, link aggregation is possible, but that is not being considered here.) + +What is usually needed is a way to separate traffic into different _"lanes"_ and assign different _"speed limits"_ to each lane. +That is exactly what *queues* are for. +indexterm:[queue] + + +=== Simple Pipe and Queue Configuration + +Before going further, it is useful to disambiguate the two meanings of the word *"queue"*. + +In a *pipe* definition, by default, the *pipe* is assigned a *queue* where incoming packets are held before processing and transit. +The size of this "pipe queue" is by default 50 packets, but can be changed with the *queue* keyword on the *pipe* definition: + +[subs=+quotes] +---- +# *ipfw pipe 1 config bw 200Kbit/s* +# +# *ipfw pipe list* +00001: 200.000 Kbit/s 0 ms burst 0 +q131073 #50# sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +# +# *ipfw pipe 2 config bw 200Kbit/s queue 75* +# +# *ipfw pipe list* +00001: 200.000 Kbit/s 0 ms burst 0 +q131073 #50# sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +00002: 200.000 Kbit/s 0 ms burst 0 +q131074 #75# sl. 0 flows (1 buckets) sched 65538 weight 0 lmax 0 pri 0 droptail + sched 65538 type FIFO flags 0x0 0 buckets 0 active +# +---- + +indexterm:[FIFO] indexterm:[buckets] + +In contrast, *dummynet* has the concept of *_flow queues_* which are virtual groupings of packets assigned to a flow according to a mask in their definition with *ipfw queue* statements. +indexterm:[flow queue] + +Configuring a *queue* is almost as simple as configuring a *pipe*. +indexterm:[queue] + +Start with a clean slate (all objects and rules deleted): + +[subs=+quotes] +---- +# *kldunload dummynet* +# *kldunload ipfw* +# *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +# *kldload dummynet* +load_dn_sched dn_sched FIFO loaded +load_dn_sched dn_sched QFQ loaded +load_dn_sched dn_sched RR loaded +load_dn_sched dn_sched WF2Q+ loaded +load_dn_sched dn_sched PRIO loaded +load_dn_sched dn_sched FQ_CODEL loaded +load_dn_sched dn_sched FQ_PIE loaded +load_dn_aqm dn_aqm CODEL loaded +load_dn_aqm dn_aqm PIE loaded +# +# *ipfw queue 1 config pipe 1* +# +# *ipfw queue show* +q00001 50 sl. 0 flows (1 buckets) sched 1 weight 0 lmax 0 pri 0 droptail +---- + +indexterm:[module, dummynet] + +Here is one *queue* of size 50 packets that was created and assigned to *pipe 1*. +Since there is no assigned *weight*, the *weight* is 0 (zero), which is the least weight possible. +indexterm:[weight] +The *queue* currently has 0 flows, meaning that this *queue* has no traffic flowing through it. +indexterm:[queue] + +Notice however, that the *queue* was created _before_ the *pipe*. +That is why the weight is 0. +The default queue weight is 1. +This configuration was actually done out of order. +To maintain a readable configuration, it is best to configure the objects in the following order: + +. *pipes* (also creates a scheduler, which can be assigned a specific scheduler type) +. *queues* - create queues and assign weights, source and destination masks, delay, and other characteristics to the queue +. Assign *rules* to match traffic using standard 5-tuples or as needed +indexterm:[5-tuple] + +*dummynet* also has the ability to separate out different flows within the same pipe to perform different scheduling algorithms. +An example of this capability is shown later in this section. +indexterm:[dummynet] + +When transferring a file to the *external1* VM and attempting to type interactively on the *external1* VM at the same time, the ability to type at speed is dramatically reduced. +The file transfer packets, being much larger than interactive typing packets are hogging all the bandwidth. +indexterm:[bandwidth] +This effect is a well known phenomenon to anyone who edits documents on a remote site. +Since packets are created much faster by a file transfer program than anyone can type, the outbound queue is almost always full of large packets, leaving keystrokes to be separated by large amounts of file transfer data in the queue. + +[TIP] +==== +Try this out on the *firewall* VM by resetting the *pipe 1* bandwidth to 300Kbit/sec, and in one session, run iperf3 as *iperf3 -c 203.0.113.10 -t 60*. +Then in another session, add rules for ssh traffic and ssh to *external1* VM and try to enter text into a scratch file. +The typing delay is almost unbearable. +==== + +indexterm:[iperf3] + +To control traffic flow between the *firewall* VM and any external VM host, set up individual *queues* to separate traffic within a *pipe*. +*queues* can be either static - defined with *ipfw queue config ...* - or they can be dynamic. +indexterm:[static queue] indexterm:[dynamic queue] +Dynamic queues are created when using the *mask* keyword. +indexterm:[mask] +Masks for *queues* are called *flow masks*. +indexterm:[flow mask] +The mask determines if a packet entering or leaving the *firewall* is selected to be entered into a *queue*. +Consider the following example: + +[subs=+quotes] +---- +# *ipfw pipe 1 config bw 200Kbit/s mask src-ip 0x000000ff* +---- + +Each /24 host transferring data through *pipe 1* (based on suitable rules) will have its own dynamic queue, all sharing the bandwidth in the *pipe* according to the configration of the queue. +indexterm:[dynamic queue] indexterm:[bandwidth] + +If a different data transfer that is not related to the pipe, queue, and flow mask is started, it will not have any effect on the data in the pipe and queue. +indexterm:[flow mask] +Dummynet keeps such transfers separate from the pipe and queue operations. + +If instead, the goal is to create separate individual *queues* with different characteristics such as different *weights* or *delay*, create static *queues* and then assign them to individual *pipes* as desired: +indexterm:[weight] indexterm:[delay] + +[subs=+quotes] +---- +# +# *ipfw pipe 1 config bw 300kbit/s* +# +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x0 0 buckets 0 active +# +# *ipfw queue 1 config pipe 1 #weight 10 mask dst-ip 0xffffffff dst-port 5201*# +Bump flowset buckets to 64 (was 0) +# +# *ipfw queue 2 config pipe 1 #weight 10 mask dst-ip 0xffffffff dst-port 5202*# +Bump flowset buckets to 64 (was 0) +# +# *ipfw queue show* +q00001 50 sl. 0 flows (64 buckets) sched 1 #weight 10# lmax 0 pri 0 droptail + #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1451# +q00002 50 sl. 0 flows (64 buckets) sched 1 #weight 10# lmax 0 pri 0 droptail + #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1452# +# +# *ipfw add 10 allow icmp from any to any* +00010 allow icmp from any to any +# +# *ipfw add 100 check-state* +00100 check-state :default +# +# *ipfw add 1000 queue 1 tcp from me to 203.0.113.10 5201 setup keep-state* +01000 queue 1 tcp from me to 203.0.113.10 5201 setup keep-state :default +# +# *ipfw add 1100 queue 2 tcp from me to 203.0.113.20 5202 setup keep-state* +01100 queue 2 tcp from me to 203.0.113.20 5202 setup keep-state :default +# +# *ipfw list* +00010 allow icmp from any to any +00100 check-state :default +01000 queue 1 tcp from me to #203.0.113.10 5201# setup keep-state :default +01100 queue 2 tcp from me to #203.0.113.20 5202# setup keep-state :default +65535 deny ip from any to any +# +---- + +[NOTE] +==== +Later versions of FreeBSD may not return any output on *ipfw queue* configuration statements. +The configuration is completed successfully, though without any output. +==== + +Running + +[subs=+quotes] +---- +# *iperf3 -c 203.0.113.10 -p 5201 -t 30 -O 5 --length 1460* +---- + +indexterm:[iperf3] + +produces the output below. + +The output is the result of using the "omit" flag (-O) on the sender to ignore the first five seconds of output. +indexterm:[omit flag] +This removes the "slow start" portion of the TCP test, and focuses instead on the "steady state" that occurs after slow start gets up to speed. +indexterm:[slow start] indexterm:[steady state] + +[[ipfw-dummynet-separate-static-queues-and-pipes]] +.Testing Separate Static Queues and Pipes +image::ipfw-dummynet055.png["Testing Separate Static Queues and Pipes. Refer to paragraphs below."] + +This example shows the steady state results of transmitting data through one queue - *queue 1*. +indexterm:[queue] +The bitrate was consistently about 293Kbits/sec. + +[NOTE] +==== +Later versions of FreeBSD and *iperf3* may differ from the display in the above figure. +Assess the correctness of the queue setup by examining the transfer summary printed at the end of the *iperf3* command output. +Use of the *iperf3 --length* parameter may provide additional clarity for transfers. +==== + +indexterm:[iperf3] + +During the transmission, a view of the queue status was: + +[subs=+quotes] +---- +# *ipfw queue show* +q00001 50 sl. 2 flows (64 buckets) sched 1 weight 10 lmax 0 pri 0 droptail + #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1451# +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp +136 ip 0.0.0.0/0 203.0.113.10/5201 2293 3425216 42 63000 0 + 50 ip 0.0.0.0/0 203.0.113.50/1040 752 39104 1 52 0 +q00002 50 sl. 0 flows (64 buckets) sched 1 weight 10 lmax 0 pri 0 droptail + mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1452 +# +---- + +The *queue mask*, set to show the full destination address and destination port is highlighted. +indexterm:[queue mask] + +[NOTE] +==== +Note that port numbers are displayed in hexadecimal. +A decimal/hexadecimal calculator may be helpful when looking at a lot of queue displays. +==== + +indexterm:[port number] + +The next example shows the result of starting two transmissions, one for each queue. + +On the *external1* VM, set up the command *iperf3 -s -p 5201*, and on *external2* use the command *iperf3 -s -p 5202*. +indexterm:[iperf3] + +Start the transfer to *external1* on the *firewall* VM with the command: + +[subs=+quotes] +---- +# *iperf3 -c 203.0.113.10 -p 5201 -t 180 -O 30* +---- + +and start the second transfer from a different session on the *firewall* VM with the command: + +[subs=+quotes] +---- +# *iperf3 -c 203.0.113.20 -p 5202 -t 180 -O 30* +---- + +indexterm:[iperf3] + +Notice how the queue is adjusted to accommodate the presence of a second queue of equal weight: + +[[ipfw-dummynet-two-static-queues-and-pipes-equally-weighted]] +.Testing Two Static Queues and Pipes +image::ipfw-dummynet060.png["Testing Separate Static Queues and Pipes Equally Weighted. Refer to paragraphs below."] + +Since the queues were equally weighted, the result was that the transmission bitrate for both queues was reduced to about half of the transmission bitrate before the second transmission started. + +The highlighted area shows how the first queue adapted. + +Queue characteristics can be changed at any time, even during an active flow. +Consider the case below where, during simultaneous transmission through queues of equal weight, the queue weight of the second queue was modified as follows: +indexterm:[queue weight] + +queue 1: original weight 10 modified weight 10 (no change) + +queue 2: original weight 10 modified weight 50 (increased) + +This change can be effected by the command: + +[subs=+quotes] +---- +# *ipfw queue 2 config weight 50* +---- + +[[ipfw-dummynet-two-static-queues-and-pipes-changed-inflight]] +.Testing Two Static Queues and Pipes Changed In-flight +image::ipfw-dummynet065.png["Testing Two Static Queues and Queue 2 Changed In-flight. Refer to paragraphs below."] + +The transmission bitrate for *queue 1* dropped from an average of about 140Kbits/sec to an average of about 50Kbits/sec; while the rate for *queue 2* expanded during and after the reconfiguration. + +Note however, that the above command had a side effect: + +[subs=+quotes] +---- +# *ipfw queue show* +q00001 50 sl. 0 flows (64 buckets) sched 1 weight 10 lmax 0 pri 0 droptail + mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1451 +q00002 50 sl. 0 flows (1 buckets) sched 1 weight 50 lmax 0 pri 0 droptail +# +---- + +indexterm:[queue] + +The *flow mask* for *queue 2* has been deleted. +indexterm:[flow mask] +In fact, *all* settings not explicitly reset will revert to their default settings. +Here is a complicated queue setup: + +[subs=+quotes] +---- +# *ipfw queue 1 config pipe 1 weight 40 buckets 256 mask src-ip 0x000000ff dst-ip 0x0000ffff noerror plr 0.01 queue 75 red .3/25/30/.5* +# +# *ipfw queue show* +#q00001 75 sl.plr 0.010000 0 flows (256 buckets) sched 1 weight 40 lmax 0 pri 0# + #RED w_q 0.299988 min_th 25 max_th 30 max_p 0.500000# + #mask: 0x00 0x000000ff/0x0000 -> 0x0000ffff/0x0000# +# +---- + +indexterm:[pipe] indexterm:[weight] indexterm:[queue] indexterm:[red] + +And if, similar to the previous example, only the weight is changed: +indexterm:[weight] + +[subs=+quotes] +---- +# *ipfw queue 1 config weight 20* +# +# *ipfw queue show* +#q00001 50 sl. 0 flows (1 buckets) sched 1 weight 20 lmax 0 pri 0 droptail# +# +---- + +All the other parameters of the queue are reset to their defaults. +Therefore, *_it is best to retain the original commands used to construct queues, pipes, and schedulers, even if changing only one parameter._* +That way, all other parameters can be replicated on the command line. +Otherwise it may be necessary to reconstruct the parameters from the output of *ipfw queue show* which can be quite tedious. + +=== Relationships + +As described throughout this section, *pipes*, *queues*, and *scheds* (schedulers) are interrelated. +Here are some simplified principles: + +* *Bandwidth* - the bandwidth of a particular pipe determines the highest rate at which all data will move through the pipe with optimal conditions. +With lower configured bandwidth, less data will be transferred. +This has an effect on *queue* size. +* *Queue size* - the number of packets, or if expressed in K or Mbytes, the amount of data waiting to be transferred though a pipe. +If the queue fills up or overflows, packets are dropped which may result in retransmissions, depending on the protocol or application involved. +That being said, best practice is to configure for smaller, rather than larger queue sizes. +See link:https://datatracker.ietf.org/doc/html/rfc2309[RFC 2309] for a thorough discussion. +* *Delay* - delay can be configured in a pipe to inject additional time between individual transfers. +It is distinct from bandwidth in that it can only slow down traffic, not speed it up. +* *Packet Loss* - packet loss can be configured in a pipe to simulate lossy transmission media. +It simulates how well the receiver can correctly "hear" the transmissions. +Packet loss may also result in retransmissions. +* *Scheduling* - scheduling determines the allocation of bandwidth among flows. +If there is only one queue in a pipe, and one flow in that queue, the scheduler does not really have much to do. +However, if there are multiple queues in a pipe each with their own flow, the scheduler determines the order of service based on the selected algorithm (RR, QFQ, WFQ+, etc.) and queue *weights*. +* *Queue weight* - a numerical value that can be used to influence the scheduler to prefer certain flows ahead of other flows. +Higher weights result in increased traffic in a flow. +However, even with a very minimal weight, a flow will never starve - that is, it will still eventually get serviced by the scheduler. + +Additional detail is contained in man:ipfw[8]. + +=== Dynamic Pipes + +Here, note that the simplest setup for *pipes* creates *dynamic pipes* when needed: +indexterm:[dynamic pipe] + +[subs=+quotes] +---- +# *ipfw pipe 1 config bw 300kbit/s weight 10 mask src-ip 0x0000ffff dst-ip 0xffffffff* +Bump sched buckets to 64 (was 0) +# +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 10 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 0 active + mask: 0x00 0x0000ffff/0x0000 -> 0xffffffff/0x0000 +# +# *ipfw list* +00050 allow icmp from any to any +00100 check-state :default +65535 deny ip from any to any +# +# *ipfw add 1000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state* +01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default +# +# *ipfw list* +01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default +65535 deny ip from any to any +# +---- + +Sending some data with this configuration: + +[subs=+quotes] +---- +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 10 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 4 active + mask: 0x00 0x0000ffff/0x0000 -> 0xffffffff/0x0000 +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 6 ip 0.0.10.10/0 203.0.113.50/0 236 12272 0 0 0 + 78 ip 0.0.10.50/0 203.0.113.10/0 1493 2225216 43 64500 0 + 80 ip 0.0.10.50/0 203.0.113.20/0 1355 2018216 42 63000 0 + 58 ip 0.0.10.20/0 203.0.113.50/0 366 19032 0 0 0 +# +# *ipfw list* +00050 allow icmp from any to any +00100 check-state :default +01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default +65535 deny ip from any to any +# +---- + +All three transmissions running together, single *pipe*: +indexterm:[pipe] + +[subs=+quotes] +---- +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 10 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 6 active + mask: 0x00 0x0000ffff/0x0000 -> 0xffffffff/0x0000 +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 6 ip 0.0.10.10/0 203.0.113.50/0 588 30576 0 0 0 + 78 ip 0.0.10.50/0 203.0.113.10/0 1508 2247716 43 64500 0 + 80 ip 0.0.10.50/0 203.0.113.20/0 1357 2021216 43 64500 0 + 90 ip 0.0.10.50/0 203.0.113.30/0 1322 1981552 41 61500 0 + 46 ip 0.0.10.30/0 203.0.113.50/0 34 1768 0 0 0 + 58 ip 0.0.10.20/0 203.0.113.50/0 702 36504 0 0 0 +---- + +Because of the *ipfw* rule: + +[subs=+quotes] +---- +01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default +---- + +All are getting 290 Kbit/sec from *iperf3* and they are all sharing the *pipe* equally. +indexterm:[pipe] indexterm:[iperf3] + +If *iperf3* is changed to send to different ports for each system (5201, 5202, 5203) on the *external1*, *external2*, and *external3* VMs respectively, there is no change. +It is only with *queues*, and setting the individual flow rate, that can effect change. +indexterm:[flow rate] + +Below are examples of different masks and their effect on traffic flow: + +[subs=+quotes] +---- +* dst-ip 0x0000ffff + +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 4 active + #mask: 0x00 0x00000000/0x0000 -> 0x0000ffff/0x0000# +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 10 ip 0.0.0.0/0 0.0.10.10/0 1183 1760218 43 64500 0 + 20 ip 0.0.0.0/0 0.0.10.20/0 974 1446718 42 63000 0 + 30 ip 0.0.0.0/0 0.0.10.30/0 688 1017718 35 52500 0 + 50 ip 0.0.0.0/0 0.0.10.50/0 1717 89284 0 0 0 + + +* dst-ip 0xffffffff + +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 4 active + #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x0000# +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 18 ip 0.0.0.0/0 203.0.113.50/0 402 20888 0 0 0 + 42 ip 0.0.0.0/0 203.0.113.10/0 144 204722 0 0 0 + 52 ip 0.0.0.0/0 203.0.113.20/0 359 525971 0 0 0 + 62 ip 0.0.0.0/0 203.0.113.30/0 562 843000 37 55500 0 + + +* src-ip 0x0000ffff + +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 4 active + #mask: 0x00 0x0000ffff/0x0000 -> 0x00000000/0x0000# +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 20 ip 0.0.10.10/0 0.0.0.0/0 361 19348 0 0 0 +100 ip 0.0.10.50/0 0.0.0.0/0 2102 3079974 36 54000 27 + 40 ip 0.0.10.20/0 0.0.0.0/0 193 10416 0 0 0 + 60 ip 0.0.10.30/0 0.0.0.0/0 47 2612 0 0 0 + + +* mask src-ip 0x0000ffff dst-ip 0x0000ffff <-only one keyword mask needs to be specified + +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 6 active + #mask: 0x00 0x0000ffff/0x0000 -> 0x0000ffff/0x0000# +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 14 ip 0.0.10.30/0 0.0.10.50/0 253 13156 0 0 0 + 26 ip 0.0.10.20/0 0.0.10.50/0 61 3172 0 0 0 + 38 ip 0.0.10.10/0 0.0.10.50/0 771 40094 0 0 0 +110 ip 0.0.10.50/0 0.0.10.10/0 853 1265218 40 60000 0 +112 ip 0.0.10.50/0 0.0.10.20/0 723 1083052 37 55500 0 +122 ip 0.0.10.50/0 0.0.10.30/0 644 951718 34 51000 0 + + +* mask src-ip 0x0000ffff dst-ip 0x0000ffff dst-port 5201 + +# *ipfw pipe show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 6 active + #mask: 0x00 0x0000ffff/0x0000 -> 0x0000ffff/0x1451# +BKT Prot Source IP/port Dest. IP/port ot_pkt/bytes Pkt/Byte Drp +204 ip 0.0.10.50/0 0.0.10.10/5201 2132 3183718 43 64500 0 + 14 ip 0.0.10.30/0 0.0.10.50/4096 823 42796 0 0 0 +210 ip 0.0.10.50/0 0.0.10.20/5201 2001 2987218 43 64500 0 +152 ip 0.0.10.20/0 0.0.10.50/4161 663 34476 0 0 0 +216 ip 0.0.10.50/0 0.0.10.30/5201 1981 2957218 43 64500 0 +164 ip 0.0.10.10/0 0.0.10.50/65 471 24492 0 0 0 + + +* mask src-ip 0xffffffff dst-ip 0xffffffff + +# *ipfw pipe 1 show* +00001: 300.000 Kbit/s 0 ms burst 0 +q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail + sched 65537 type FIFO flags 0x1 64 buckets 6 active + #mask: 0x00 0xffffffff/0x0000 -> 0xffffffff/0x0000# +BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp + 64 ip 203.0.113.50/0 203.0.113.20/0 1215 1808218 43 64500 0 + 74 ip 203.0.113.50/0 203.0.113.30/0 1023 1533052 43 64500 0 + 22 ip 203.0.113.10/0 203.0.113.50/0 746 38792 0 0 0 + 94 ip 203.0.113.50/0 203.0.113.10/0 1863 2780218 42 63000 0 + 42 ip 203.0.113.20/0 203.0.113.50/0 481 25012 0 0 0 + 62 ip 203.0.113.30/0 203.0.113.50/0 159 8268 0 0 0 +---- + +=== Other Pipe and Queue Commands + +To delete pipes and queues use the following syntax: + +[subs=+quotes] +---- +For queues, specify the queue number on the command line: + +# *ipfw queue delete 1* + +For pipes, specify the pipe number on the command line: + +# *ipfw pipe delete 1* +---- + +indexterm:[pipe, delete] +indexterm:[queue, delete] + + +Note however that: + +[subs=+quotes] +---- +# *ipfw delete pipe 1* #<----- does not throw error, and does not delete the pipe.# +---- + +The same is true for the corresponding *queue* keyword. +Take care to use the proper syntax. + +[IMPORTANT] +==== +It is possible to delete a *pipe* with a *pipe* statement still in the ruleset. +*ipfw* will not throw an error - but any data transfer matching the *pipe* statement will not work. +==== + +indexterm:[pipe, delete] + +*scheds* (schedulers) and *pipes* are tightly bound. +indexterm:[sched, delete] +To delete a scheduler, first delete the *pipe*, and then re-create the *pipe*. +The scheduler for the new *pipe* is reset to the default scheduler. +However, it is possible to change the current scheduler type at any time: + +[subs=+quotes] +---- +To change the scheduler type: +# *ipfw sched config 1 type wfq2* # or *rr* or any other *sched* type +---- + +indexterm:[scheduler type] indexterm:[wfq2] + +== Adding Additional Virtual Machines + +Up to this point, only two or three virtual machines have been used for exploring *ipfw*. +The later material in this book requires the use of several additional virtual machines. + +The NAT chapter calls for several more VMs for: +indexterm:[NAT] + +--- + +indexterm:[simple NAT] + +[[ipfw-simple-nat-figure-scaled-down]] +.Setting Up Simple NAT +image::ipfw-nat070-scaled-down.png["Setting Up Simple NAT. Refer to paragraphs below."] + +--- + +indexterm:[load sharing NAT] indexterm:[LSNAT] + +[[ipfw-lsnat-figure-scaled-down]] +.Setting up Load Sharing NAT +image::ipfw-nat075-scaled-down.png["Setting Up Load Sharing NAT. Refer to paragraphs below."] + +--- + +indexterm:[NAT64] indexterm:[DNS64] + +[[ipfw-nat64-and-dns64-figure-scaled-down]] +.Setting Up NAT64 and DNS64 +image::ipfw-nat080-scaled-down.png["Setting Up NAT64 and DNS64. Refer to paragraphs below."] + +--- + +indexterm:[464XLAT] + +[[ipfw-464xlat-figure-scaled-down]] +.Setting Up 464XLAT +image::ipfw-nat090-scaled-down.png["Setting Up 464XLAT. Refer to paragraphs below."] + +If you have not already done so, finish setting up the remaining VMs as described in crossref:ipfw-appendix-a[appendix-a, Appendix A]. +indexterm:[SCRIPTS] indexterm:[ISO] indexterm:[VM] indexterm:[BMP] indexterm:[Appendix A] + +Also, ensure each virtual machine is set up to boot a serial console by adding "console=comconsole" to [.filename]#/boot/loader.conf#. +indexterm:[console, serial] + +Finally, adjust the number of active windows in *swim.sh* (or *scim.sh*) by uncommenting the appropriate lines in the script. diff --git a/documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.po @@ -0,0 +1,1992 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1 +#, no-wrap +msgid "IPFW Dummynet" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1 +#, no-wrap +msgid "Chapter 4. IPFW Dummynet and Traffic Shaping" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:13 +#, no-wrap +msgid "IPFW Dummynet and Traffic Shaping" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:57 +msgid "" +"FreeBSD's *dummynet* is not a network for dummies. indexterm:[dummynet] It " +"is a sophisticated network traffic shaping tool for bandwidth usage and " +"scheduling algorithms. In this use of *ipfw*, the focus is not on ruleset " +"development, although rules are still used to select traffic to pass to " +"*dummynet* objects. Instead, the focus is on setting up a system to shape " +"traffic flows. *dummynet* provides tools to model scheduling, queuing, and " +"similar tasks similar to the real-world Internet." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:60 +#, no-wrap +msgid "" +"*dummynet* works with three main types of objects - a *pipe*, a *queue*, and a *sched* (short for scheduler) which also happen to be the three keywords to now examine.\n" +"indexterm:[pipe] indexterm:[queue] indexterm:[sched]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:62 +msgid "" +"A *pipe* (_not to be confused with a Unix pipe(2)_) is a model of a network " +"link with a configurable bandwidth, and propagation delay." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:67 +msgid "" +"A *queue* is an abstraction used to implement packet scheduling using one of " +"several different scheduling algorithms. Packets sent to a queue are first " +"grouped into flows according to a mask on a 5-tuple (protocol, source " +"address, source port, destination address, destination port) specification. " +"Flows are then passed to the scheduler associated with the queue, and each " +"flow uses scheduling parameters (weight, bandwidth, etc.) as configured in " +"the queue itself. A *sched* (scheduler) in turn is connected to a *pipe* " +"(an emulated link) and arbitrates the link's bandwidth among backlogged " +"flows according to weights and to the features of the scheduling algorithm " +"in use." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:71 +msgid "" +"Network performance testing is a complex subject that can encompass many " +"variables across many different testing strategies. To understand the " +"basics behind *dummynet*, it is not necessary to dive into the deepest " +"levels of network performance testing - only enough to understand how to use " +"*dummynet*. Also, these tests are restricted to using IP and TCP " +"exclusively." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:73 +#, no-wrap +msgid "*Setting Up for Traffic Measurement*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:75 +msgid "" +"Most of the examples in this section can be done with the architecture used " +"in the crossref:ipfw-operation[ipfw-intro-simple-lab, original lab setup] in " +"Chapter 2, copied here for reference:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:77 +#, no-wrap +msgid "IPFW Lab for *dummynet* Examples" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:78 +#, no-wrap +msgid "IPFW Lab for *dummynet* Examples. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:78 +#, no-wrap +msgid "ipfw-operation017.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:81 +msgid "" +"Where necessary, additional virtual machines can be created and added to the " +"bridge." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:82 +#, no-wrap +msgid "Measuring Default Throughput" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:89 +msgid "" +"The idea behind *dummynet* is that it lets one model and/or shape network " +"speeds, available bandwidth, and scheduling algorithms. indexterm:" +"[dummynet] indexterm:[scheduling algorithm] But it is first necessary to " +"know what the current transfer speeds are for the current environment (QEMU " +"virtual machines over a FreeBSD bridge). To find out, here is a short " +"detour to learn *iperf3*, the network bandwidth testing tool to perform " +"simple transfer and bitrate calculations. indexterm:[iperf3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:93 +#, no-wrap +msgid "" +"*iperf3*, can determine the effective throughput of data transfer for a network.\n" +"Sometimes called \"goodput\", this is the basic speed the user sees for transferring data across the network - the value that is unencumbered by protocol type and overhead.\n" +"indexterm:[goodput]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:96 +msgid "" +"To use *iperf3*, ensure that the software is installed on both the " +"*firewall* VM system, and the *external1* VM (and *external2* and " +"*external3*), and that *ipfw* on the *firewall* VM is disabled (# *kldunload " +"ipfw*). indexterm:[iperf3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:98 +msgid "" +"The basic operation of *iperf3* is as a client-server architecture, so on " +"the *external1* VM system, start the *iperf3* software in server mode:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:106 +#, no-wrap +msgid "" +"# *iperf3 -s* \t\t#<--- run *iperf3* in server mode#\n" +"-----------------------------------------------------------\n" +"Server listening on 5201 (test #1)\n" +"-----------------------------------------------------------\n" +" . . .\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:109 +msgid "Then, on the *firewall* VM, run the client:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:130 +#, no-wrap +msgid "" +"# *iperf3 -c 203.0.113.10* #<--- connect to external1 server and send test data#\n" +"Connecting to host 203.0.113.10, port 5201\n" +"[ 5] local 203.0.113.50 port 19359 connected to 203.0.113.10 port 5201\n" +"[ ID] Interval Transfer Bitrate Retr Cwnd\n" +"[ 5] 0.00-1.03 sec 12.5 MBytes 102 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 1.03-2.09 sec 13.8 MBytes 108 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 2.09-3.07 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 3.07-4.09 sec 12.5 MBytes 103 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 4.09-5.08 sec 12.5 MBytes 106 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 5.08-6.09 sec 12.5 MBytes 105 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 6.09-7.07 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 7.07-8.05 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 8.05-9.04 sec 12.5 MBytes 106 Mbits/sec 0 1.07 MBytes\n" +"[ 5] 9.04-10.02 sec 12.5 MBytes 107 Mbits/sec 0 1.07 MBytes\n" +"- - - - - - - - - - - - - - - - - - - - - - - - -\n" +"[ ID] Interval Transfer Bitrate Retr\n" +"[ 5] 0.00-10.02 sec 126 MBytes 106 Mbits/sec 0 sender\n" +"[ 5] 0.00-10.02 sec 126 MBytes 106 Mbits/sec receiver\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:133 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:274 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:409 +#, no-wrap +msgid "" +"iperf Done.\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:139 +msgid "" +"A key test for measuring throughput is to send a file of data and measure " +"the transfer speed. indexterm:[throughput] indexterm:[transfer speed] To " +"create the file, use man:jot[1] on the *firewall* VM: indexterm:[jot]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:143 +#, no-wrap +msgid "# *jot -r -s \"\" 10000000 0 9 > A.bin*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:147 +msgid "" +"This command creates a file of random ASCII digits exactly 10,000,001 bytes " +"long. (Note that this takes roughly 30 seconds to a minute to create the " +"file on a QEMU virtual machine.)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:149 +msgid "" +"To transfer the file to the server on the *firewall* VM use this command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:165 +#, no-wrap +msgid "" +"# *iperf3 -F A.bin -c 203.0.113.10 -t 10*\n" +"Connecting to host 203.0.113.10, port 5201\n" +"[ 5] local 203.0.113.50 port 51657 connected to 203.0.113.10 port 5201\n" +"[ ID] Interval Transfer Bitrate Retr Cwnd\n" +"[ 5] 0.00-1.04 sec 12.5 MBytes 101 Mbits/sec 0 490 KBytes\n" +"[ 5] 1.04-1.52 sec 5.81 MBytes 101 Mbits/sec 0 490 KBytes\n" +"- - - - - - - - - - - - - - - - - - - - - - - - -\n" +"[ ID] Interval Transfer Bitrate Retr\n" +"[ 5] 0.00-1.52 sec 18.3 MBytes 101 Mbits/sec 0 sender\n" +" Sent 18.3 MByte / 18.3 MByte (100%) of A.bin\n" +"[ 5] 0.00-1.52 sec 18.3 MBytes 101 Mbits/sec receiver\n" +"iperf Done.\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:169 +msgid "" +"Running this command several times shows that a consistent average bitrate " +"for throughput on this system is about 101Mbits/second - or about 18.3 " +"MBytes/second. (Your values will differ on your local machine.)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:172 +msgid "" +"There is now a baseline TCP-based \"goodput\" value for testing *dummynet* " +"traffic shaping commands. indexterm:[goodput] indexterm:[dummynet] " +"indexterm:[traffic shaping]" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:173 +#, no-wrap +msgid "IPFW Commands for Dummynet" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:176 +msgid "" +"To use *dummynet*, load the kernel module dummynet.ko on the *firewall* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:190 +#, no-wrap +msgid "" +"# *kldload dummynet*\n" +"load_dn_sched dn_sched FIFO loaded\n" +"load_dn_sched dn_sched QFQ loaded\n" +"load_dn_sched dn_sched RR loaded\n" +"load_dn_sched dn_sched WF2Q+ loaded\n" +"load_dn_sched dn_sched PRIO loaded\n" +"load_dn_sched dn_sched FQ_CODEL loaded\n" +"load_dn_sched dn_sched FQ_PIE loaded\n" +"load_dn_aqm dn_aqm CODEL loaded\n" +"load_dn_aqm dn_aqm PIE loaded\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:193 +#, no-wrap +msgid "*dummynet* announces the schedulers it is configured to use.\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:196 +#, no-wrap +msgid "Simple Pipe Configuration" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:200 +msgid "" +"Recall that *dummynet* uses *pipes*, *queues*, and *sched* (schedulers) to " +"shape traffic. indexterm:[pipe] indexterm:[queue] indexterm:[sched]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:203 +msgid "" +"To see *dummynet* in action, create a *pipe* with limited bandwidth, and " +"assign it to a rule matching traffic to the *external1* VM: indexterm:" +"[bandwidth]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:216 +#, no-wrap +msgid "" +"# Load the *ipfw* kernel module if needed:\n" +"# *kldload ipfw*\n" +"ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled\n" +"#\n" +"# *ipfw pipe 1 config bw #300Kbit/s#*\n" +"# *ipfw pipe 1 show*\n" +"00001: #300.000 Kbit/s# 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:219 +msgid "" +"The above output shows the *pipe* configration limiting bandwidth (bw) to " +"300Kbits/sec." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:224 +msgid "" +"Recent versions of FreeBSD now use the command alias *dnctl* for " +"configuration of pipes, queues, and schedulers. See man:dnctl[8] for " +"details." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:227 +msgid "indexterm:[dnctl]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:229 +msgid "" +"Now add *ipfw* rules to send traffic between the *firewall* VM and the " +"*external1* VM through the *pipe*:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:243 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"#\n" +"# *ipfw add 1000 pipe 1 ip from any to any*\n" +"01000 pipe 1 ip from any to any\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 pipe 1 ip from any to any\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:246 +msgid "" +"By adding the matching phrase *\"ip from any to any\"* and assigning it to " +"*pipe 1*, the *firewall* VM is directed to send all ip-based traffic through " +"the *pipe*, now configured as a 300K bps link." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:249 +msgid "" +"By re-running the basic file transfer command for *iperf3* these difference " +"take shape: indexterm:[iperf3]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:271 +#, no-wrap +msgid "" +"# *iperf3 -F A.bin -c 203.0.113.10 -t 10*\n" +"Connecting to host 203.0.113.10, port 5201\n" +"[ 5] local 203.0.113.50 port 22303 connected to 203.0.113.10 port 5201\n" +"[ ID] Interval Transfer Bitrate Retr Cwnd\n" +"[ 5] 0.00-1.00 sec 69.1 KBytes 564 Kbits/sec 0 15.6 KBytes\n" +"[ 5] 1.00-2.01 sec 36.3 KBytes 294 Kbits/sec 0 18.4 KBytes\n" +"[ 5] 2.01-3.01 sec 33.9 KBytes 278 Kbits/sec 0 21.3 KBytes\n" +"[ 5] 3.01-4.00 sec 47.6 KBytes 394 Kbits/sec 0 24.1 KBytes\n" +"[ 5] 4.00-5.01 sec 26.9 KBytes 218 Kbits/sec 0 25.5 KBytes\n" +"[ 5] 5.01-6.00 sec 37.7 KBytes 312 Kbits/sec 0 27.0 KBytes\n" +"[ 5] 6.00-7.00 sec 43.8 KBytes 360 Kbits/sec 0 28.4 KBytes\n" +"[ 5] 7.00-8.01 sec 34.9 KBytes 282 Kbits/sec 0 29.8 KBytes\n" +"[ 5] 8.01-9.00 sec 29.7 KBytes 246 Kbits/sec 0 31.2 KBytes\n" +"[ 5] 9.00-10.00 sec 46.2 KBytes 378 Kbits/sec 0 32.7 KBytes\n" +"- - - - - - - - - - - - - - - - - - - - - - - - -\n" +"[ ID] Interval Transfer Bitrate Retr\n" +"[ 5] #0.00-10.00 sec 406 KBytes 332 Kbits/sec 0 sender#\n" +" #Sent 406 KByte / 18.3 MByte (2%) of A.bin#\n" +"[ 5] #0.00-10.55 sec 358 KBytes 278 Kbits/sec receiver#\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:279 +msgid "" +"If the systems returns the error \"iperf3: error - control socket has closed " +"unexpectedly\", simply re-run the command." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:284 +msgid "" +"Here, during *iperf3*'s 10-second run, the *ipfw* *dummynet* configuration " +"limited the transfer speed to an average of about 332 Kbits/sec, and only " +"about 2% of the entire 10MB file was transferred. indexterm:[iperf3] " +"indexterm:[dummynet]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:286 +msgid "" +"To see how to use *dummynet* to configure different link speeds, set up a " +"second *pipe*:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:298 +#, no-wrap +msgid "" +"# *ipfw pipe 2 config bw 3Mbit/s*\n" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"00002: 3.000 Mbit/s 0 ms burst 0\n" +"q131074 50 sl. 0 flows (1 buckets) sched 65538 weight 0 lmax 0 pri 0 droptail\n" +" sched 65538 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:304 +msgid "" +"This *pipe* is set up to be 10 times faster (3Mb/sec instead of 300Kb/sec) " +"than *pipe 1*. indexterm:[pipe] To test this pipe, start up the *external2* " +"VM and run *iperf3 -s*. Then reconfigure the *ipfw* rules to send to the " +"*external2* VM through *pipe 2*:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:335 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 pipe 1 ip from any to any\n" +"65535 deny ip from any to any\n" +"#\n" +"# *ipfw delete 1000*\n" +"#\n" +"# *ipfw add 1000 pipe 1 ip from me to 203.0.113.10 // external1*\n" +"01000 pipe 1 ip from me to 203.0.113.10\n" +"#\n" +"# *ipfw add 1100 pipe 1 ip from 203.0.113.10 to me // external1*\n" +"01100 pipe 1 ip from 203.0.113.10 to me\n" +"#\n" +"# *ipfw add 2000 pipe 2 ip from me to 203.0.113.20 // external2*\n" +"02000 pipe 2 ip from me to 203.0.113.20\n" +"#\n" +"# *ipfw add 2100 pipe 2 ip from 203.0.113.20 to me // external2*\n" +"02100 pipe 2 ip from 203.0.113.20 to me\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 pipe 1 ip from me to 203.0.113.10\n" +"01100 pipe 1 ip from 203.0.113.10 to me\n" +"02000 pipe 2 ip from me to 203.0.113.20\n" +"02100 pipe 2 ip from 203.0.113.20 to me\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:339 +msgid "" +"As expected, *pipe 2* is approximately 10 times faster than *pipe 1*: " +"indexterm:[pipe]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:363 +#, no-wrap +msgid "" +"# *iperf3 -F A.bin -c 203.0.113.20 -t 10*\n" +"Connecting to host 203.0.113.20, port 5201\n" +"[ 5] local 203.0.113.50 port 21569 connected to 203.0.113.20 port 5201\n" +"[ ID] Interval Transfer Bitrate Retr Cwnd\n" +"[ 5] 0.00-1.00 sec 417 KBytes 3.41 Mbits/sec 0 34.1 KBytes\n" +"[ 5] 1.00-2.00 sec 325 KBytes 2.66 Mbits/sec 0 45.5 KBytes\n" +"[ 5] 2.00-3.00 sec 373 KBytes 3.06 Mbits/sec 0 55.5 KBytes\n" +"[ 5] 3.00-4.00 sec 334 KBytes 2.73 Mbits/sec 0 64.0 KBytes\n" +"[ 5] 4.00-5.00 sec 348 KBytes 2.85 Mbits/sec 0 64.0 KBytes\n" +"[ 5] 5.00-6.00 sec 337 KBytes 2.76 Mbits/sec 0 64.0 KBytes\n" +"[ 5] 6.00-7.00 sec 339 KBytes 2.78 Mbits/sec 0 64.0 KBytes\n" +"[ 5] 7.00-8.00 sec 348 KBytes 2.85 Mbits/sec 0 64.0 KBytes\n" +"[ 5] 8.00-9.00 sec 351 KBytes 2.87 Mbits/sec 0 64.0 KBytes\n" +"[ 5] 9.00-10.00 sec 351 KBytes 2.88 Mbits/sec 0 64.0 KBytes\n" +"- - - - - - - - - - - - - - - - - - - - - - - - -\n" +"[ ID] Interval Transfer Bitrate Retr\n" +"[ 5] #0.00-10.00 sec 3.44 MBytes 2.89 Mbits/sec 0 sender#\n" +" #Sent 3.44 MByte / 18.3 MByte (18%) of A.bin#\n" +"[ 5] #0.00-10.12 sec 3.42 MBytes 2.83 Mbits/sec receiver#\n" +"iperf Done.\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:369 +msgid "" +"Next, change the *pipe* configuration without changing the ruleset. " +"indexterm:[ruleset] Below, the *pipe 1* bandwidth is changed to the " +"equivalent of a telecommunications T1 line as in the days of old: indexterm:" +"[T1 line]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:381 +#, no-wrap +msgid "" +"# *ipfw pipe 1 config bw 1544Kbit/s*\n" +"# *ipfw pipe show*\n" +"00001: #1.544 Mbit/s# 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"00002: 3.000 Mbit/s 0 ms burst 0\n" +"q131074 50 sl. 0 flows (1 buckets) sched 65538 weight 0 lmax 0 pri 0 droptail\n" +" sched 65538 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:384 +msgid "" +"Resending the 10MB file across the T1 configured line shows these results:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:406 +#, no-wrap +msgid "" +"# *iperf3 -F A.bin -c 203.0.113.10 -t 10*\n" +"Connecting to host 203.0.113.10, port 5201\n" +"[ 5] local 203.0.113.50 port 16696 connected to 203.0.113.10 port 5201\n" +"[ ID] Interval Transfer Bitrate Retr Cwnd\n" +"[ 5] 0.00-1.00 sec 222 KBytes 1.82 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 1.00-2.00 sec 181 KBytes 1.48 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 2.00-3.00 sec 181 KBytes 1.48 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 3.00-4.00 sec 184 KBytes 1.51 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 4.00-5.00 sec 181 KBytes 1.48 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 5.00-6.00 sec 181 KBytes 1.48 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 6.00-7.00 sec 178 KBytes 1.46 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 7.00-8.00 sec 178 KBytes 1.46 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 8.00-9.00 sec 181 KBytes 1.48 Mbits/sec 0 65.0 KBytes\n" +"[ 5] 9.00-10.00 sec 175 KBytes 1.44 Mbits/sec 0 65.0 KBytes\n" +"- - - - - - - - - - - - - - - - - - - - - - - - -\n" +"[ ID] Interval Transfer Bitrate Retr\n" +"[ 5] #0.00-10.00 sec 1.80 MBytes 1.51 Mbits/sec 0 sender#\n" +" #Sent 1.80 MByte / 18.3 MByte (9%) of A.bin#\n" +"[ 5] #0.00-10.18 sec 1.78 MBytes 1.46 Mbits/sec receiver#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:412 +msgid "About half of the 3Mbits/sec speed of *pipe 2*, again as expected." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:417 +msgid "" +"indexterm:[pipe] By definition, a *pipe* has just one *queue*, and it is " +"subject to \"First In First Out\" (FIFO) operation. indexterm:[queue] " +"indexterm:[FIFO] All traffic that flows through this *pipe* shares the same " +"characteristics." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:421 +msgid "" +"However, creating a *pipe* also does something else. It creates a default " +"*sched* (scheduler) that governs the *pipe*: indexterm:[sched]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:425 +#, no-wrap +msgid "Start with no pipes or schedulers\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:431 +#, no-wrap +msgid "" +"#\n" +"# *ipfw pipe list*\n" +"#\n" +"# *ipfw sched list*\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:433 +#, no-wrap +msgid "Create a simple pipe.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:441 +#, no-wrap +msgid "" +"# *ipfw pipe 1 config bw 100KBit/s*\n" +"#\n" +"# *ipfw pipe list*\n" +"00001: 100.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:443 +#, no-wrap +msgid "Observe the default scheduler for this pipe\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:448 +#, no-wrap +msgid "" +"# *ipfw sched list*\n" +"#00001: 100.000 Kbit/s 0 ms burst 0#\n" +" #sched 1 type WF2Q+ flags 0x0 0 buckets 0 active#\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:451 +msgid "indexterm:[WF2Q+ algorithm]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:454 +msgid "" +"The default scheduler for a new *pipe* is of type `WF2Q+`, a version of the " +"Weighted Fair Queueing algorithm for packet transfer. indexterm:[WF2Q+ " +"algorithm]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:456 +msgid "" +"This is now a single *pipe* of type FIFO operation that is managed by a " +"`WF2Q+` scheduling algorithm." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:460 +msgid "" +"The man:ipfw[8] man page makes note of several other scheduling algorithms. " +"These can be selected by using the \"type\" keyword on the *pipe* command. " +"The *type* keyword selects the type of scheduler applied to the *pipe* - not " +"the type of the *pipe* itself (the *pipe* remains FIFO):" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:467 +#, no-wrap +msgid "" +"# *ipfw pipe list*\n" +"#\n" +"# *ipfw sched list*\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:469 +#, no-wrap +msgid "Create a pipe and assign a scheduler of type Round Robin (Deficit Round Robin)\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:477 +#, no-wrap +msgid "" +"# *ipfw pipe 1 config bw 100KBit/s #type rr#*\n" +"#\n" +"# *ipfw pipe list*\n" +"00001: 100.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:479 +#, no-wrap +msgid "View the new sheduler of type RR (Deficit Round Robin)\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:484 +#, no-wrap +msgid "" +"# *ipfw sched list*\n" +"00001: 100.000 Kbit/s 0 ms burst 0\n" +" sched 1 type #RR# flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:487 +msgid "indexterm:[Round Robin scheduler]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:492 +#, no-wrap +msgid "" +"*pipes and *sched*s (schedulers) are tightly bound.\n" +"indexterm:[pipe] indexterm:[sched]\n" +"In fact, there is no command to delete a scheduler.\n" +"The scheduler is deleted when the pipe is deleted.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:496 +msgid "" +"Note however that the scheduler can be configured independently if desired. " +"Here is a change to the scheduler type from the above type RR to QFQ, a " +"variant of WF2Q+: indexterm:[QFQ algorithm]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:508 +#, no-wrap +msgid "" +"#\n" +"# *ipfw sched 1 config #type qfq#*\n" +"Bump qfq weight to 1 (was 0)\n" +"Bump qfq maxlen to 1500 (was 0)\n" +"#\n" +"# *ipfw sched list*\n" +"00001: 100.000 Kbit/s 0 ms burst 0\n" +" sched 1 type #QFQ# flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:512 +msgid "" +"There are other keywords that can be added to a *pipe* specification: " +"*delay*, *burst*, *profile*, *weight*, *buckets*, *mask*, *noerror*, *plr*, " +"*queue*, *red* or *gred*, *codel*, and *pie*. These are described in the " +"man:ipfw[8] man page." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:514 +msgid "A contrived example might be:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:519 +#, no-wrap +msgid "Start fresh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:536 +#, no-wrap +msgid "" +"# *ipfw pipe 1 delete*\n" +"#\n" +"# *ipfw pipe 1 config bw 100kbit/s delay 20 burst 2000 weight 40 buckets 256 mask src-ip 0x000000ff noerror plr 0.01 queue 75 red .3/25/30/.5 type qfq*\n" +"#\n" +"# *ipfw pipe list*\n" +"00001: 100.000 Kbit/s 20 ms burst 2000\n" +"q131073 75 sl.plr 0.010000 0 flows (1 buckets) sched 65537 weight 40 lmax 0 pri 0\n" +" RED w_q 0.299988 min_th 25 max_th 30 max_p 0.500000\n" +" sched 65537 type FIFO flags 0x1 256 buckets 0 active\n" +" mask: 0x00 0x000000ff/0x0000 -> 0x00000000/0x0000\n" +"#\n" +"# *ipfw sched list*\n" +"00001: 100.000 Kbit/s 20 ms burst 2000\n" +" sched 1 type QFQ flags 0x1 256 buckets 0 active\n" +" mask: 0x00 0x000000ff/0x0000 -> 0x00000000/0x0000\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:539 +msgid "" +"indexterm:[delay] indexterm:[burst] indexterm:[weight] indexterm:[buckets] " +"indexterm:[red] indexterm:[qfq]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:544 +msgid "" +"Setting up two separate *pipes* to send data to the same destination is " +"overkill. It is like setting up two separate network links between the two " +"points. While that may be desirable for redundancy or high-availability, it " +"makes no difference for bandwidth allocation. (Yes, link aggregation is " +"possible, but that is not being considered here.)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:548 +msgid "" +"What is usually needed is a way to separate traffic into different " +"_\"lanes\"_ and assign different _\"speed limits\"_ to each lane. That is " +"exactly what *queues* are for. indexterm:[queue]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:550 +#, no-wrap +msgid "Simple Pipe and Queue Configuration" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:553 +msgid "" +"Before going further, it is useful to disambiguate the two meanings of the " +"word *\"queue\"*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:556 +msgid "" +"In a *pipe* definition, by default, the *pipe* is assigned a *queue* where " +"incoming packets are held before processing and transit. The size of this " +"\"pipe queue\" is by default 50 packets, but can be changed with the *queue* " +"keyword on the *pipe* definition:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:576 +#, no-wrap +msgid "" +"# *ipfw pipe 1 config bw 200Kbit/s*\n" +"#\n" +"# *ipfw pipe list*\n" +"00001: 200.000 Kbit/s 0 ms burst 0\n" +"q131073 #50# sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +"# *ipfw pipe 2 config bw 200Kbit/s queue 75*\n" +"#\n" +"# *ipfw pipe list*\n" +"00001: 200.000 Kbit/s 0 ms burst 0\n" +"q131073 #50# sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"00002: 200.000 Kbit/s 0 ms burst 0\n" +"q131074 #75# sl. 0 flows (1 buckets) sched 65538 weight 0 lmax 0 pri 0 droptail\n" +" sched 65538 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:579 +msgid "indexterm:[FIFO] indexterm:[buckets]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:582 +msgid "" +"In contrast, *dummynet* has the concept of *_flow queues_* which are virtual " +"groupings of packets assigned to a flow according to a mask in their own " +"definition with an *ipfw queue* statements. indexterm:[flow queue]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:585 +msgid "" +"Configuring a *queue* is almost as simple as configuring a *pipe*. " +"indexterm:[queue]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:587 +msgid "Start with a clean slate (all objects and rules deleted):" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:609 +#, no-wrap +msgid "" +"# *kldunload dummynet*\n" +"# *kldunload ipfw*\n" +"# *kldload ipfw*\n" +"ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled\n" +"# *kldload dummynet*\n" +"load_dn_sched dn_sched FIFO loaded\n" +"load_dn_sched dn_sched QFQ loaded\n" +"load_dn_sched dn_sched RR loaded\n" +"load_dn_sched dn_sched WF2Q+ loaded\n" +"load_dn_sched dn_sched PRIO loaded\n" +"load_dn_sched dn_sched FQ_CODEL loaded\n" +"load_dn_sched dn_sched FQ_PIE loaded\n" +"load_dn_aqm dn_aqm CODEL loaded\n" +"load_dn_aqm dn_aqm PIE loaded\n" +"#\n" +"# *ipfw queue 1 config pipe 1*\n" +"#\n" +"# *ipfw queue show*\n" +"q00001 50 sl. 0 flows (1 buckets) sched 1 weight 0 lmax 0 pri 0 droptail\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:612 +msgid "indexterm:[module, dummynet]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:618 +msgid "" +"Here is one *queue* of size 50 packets that was created and assigned to " +"*pipe 1*. Since there is no assigned *weight*, the default *weight* is 0 " +"(zero), which is the least weight possible. indexterm:[weight] The *queue* " +"currently has 0 flows, meaning that this *queue* has no traffic flowing " +"through it. indexterm:[queue]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:623 +msgid "" +"Notice however, that the *queue* was created before the *pipe*. That is why " +"the weight is zero. This configuration was actually done out of order. To " +"maintain a readable configuration, it is best to configure the objects in " +"the following order:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:625 +#, no-wrap +msgid "*pipes* (also creates a scheduler, which can be assigned a specific scheduler type)\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:626 +#, no-wrap +msgid "*queues* - create queues and assign weights, source and destination masks, delay, and other characteristics to the queue\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:628 +#, no-wrap +msgid "" +"Assign rules to match traffic using standard 5-tuples or as needed\n" +"indexterm:[5-tuple]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:632 +#, no-wrap +msgid "" +"*dummynet* also has the ability to separate out different flows within the same pipe to perform different scheduling algorithms.\n" +"indexterm:[dummynet]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:639 +msgid "" +"When transferring a file to the *external1* VM and attempting to type " +"interactively on the *external1* VM at the same time, the ability to type at " +"speed is dramatically reduced. The file transfer packets, being much larger " +"than interactive typing packets are hogging all the bandwidth. indexterm:" +"[bandwidth] This effect is a well known limitation to anyone who edits " +"documents on a remote site. Since packets are created much faster by a file " +"transfer program than anyone can type, the outbound queue is almost always " +"full of large packets, leaving keystrokes to be separated by large amounts " +"of file transfer data in the queue." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:645 +msgid "" +"Try this out on the *firewall* VM by resetting the *pipe 1* bandwidth to " +"300Kbit/sec, and in one session, run iperf3 as *iperf3 -c 203.0.113.10 -t " +"60*. Then in another session, add rules for ssh traffic and ssh to " +"*external1* VM and try to enter text into a scratch file. The typing delay " +"is almost unbearable." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:648 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:731 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:754 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:801 +msgid "indexterm:[iperf3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:658 +msgid "" +"To control traffic flow between the *firewall* VM and any external VM host, " +"set up individual *queues* to separate traffic within a *pipe*. *queues* " +"can be either static - defined with *ipfw queue config ...* - or they can be " +"dynamic. indexterm:[static queue] indexterm:[dynamic queue] Dynamic queues " +"are created when using the *mask* keyword. indexterm:[mask] Masks for " +"*queues* are called *flow masks*. indexterm:[flow mask] The mask determines " +"if a packet entering or leaving the *firewall* is selected to be entered " +"into a *queue*. Consider the following example:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:662 +#, no-wrap +msgid "# *ipfw pipe 1 config bw 200Kbit/s mask src-ip 0x000000ff*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:666 +msgid "" +"Each /24 host transferring data through *pipe 1* (based on suitable rules) " +"will have its own dynamic queue, all sharing the bandwidth in the *pipe* " +"according to the configration of the queue. indexterm:[dynamic queue] " +"indexterm:[bandwidth]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:670 +msgid "" +"If a different data transfer that is not related to the pipe, queue, and " +"flow mask is started, it will not have any effect on the data in the pipe " +"and queue. indexterm:[flow mask] Dummynet keeps such transfers separate " +"from the pipe and queue operations." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:673 +msgid "" +"If instead, the goal is to create separate individual *queues* with " +"different characteristics such as different *weights* or *delay*, create " +"static *queues* and then assign them to individual *pipes* as desired: " +"indexterm:[weight] indexterm:[delay]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:715 +#, no-wrap +msgid "" +"#\n" +"# *ipfw pipe 1 config bw 300kbit/s*\n" +"#\n" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x0 0 buckets 0 active\n" +"#\n" +"# *ipfw queue 1 config pipe 1 #weight 10 mask dst-ip 0xffffffff dst-port 5201*#\n" +"Bump flowset buckets to 64 (was 0)\n" +"#\n" +"# *ipfw queue 2 config pipe 1 #weight 10 mask dst-ip 0xffffffff dst-port 5202*#\n" +"Bump flowset buckets to 64 (was 0)\n" +"#\n" +"# *ipfw queue show*\n" +"q00001 50 sl. 0 flows (64 buckets) sched 1 #weight 10# lmax 0 pri 0 droptail\n" +" #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1451#\n" +"q00002 50 sl. 0 flows (64 buckets) sched 1 #weight 10# lmax 0 pri 0 droptail\n" +" #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1452#\n" +"#\n" +"# *ipfw add 10 allow icmp from any to any*\n" +"00010 allow icmp from any to any\n" +"#\n" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"#\n" +"# *ipfw add 1000 queue 1 tcp from me to 203.0.113.10 5201 setup keep-state*\n" +"01000 queue 1 tcp from me to 203.0.113.10 5201 setup keep-state :default\n" +"#\n" +"# *ipfw add 1100 queue 2 tcp from me to 203.0.113.20 5202 setup keep-state*\n" +"01100 queue 2 tcp from me to 203.0.113.20 5202 setup keep-state :default\n" +"#\n" +"# *ipfw list*\n" +"00010 allow icmp from any to any\n" +"00100 check-state :default\n" +"01000 queue 1 tcp from me to #203.0.113.10 5201# setup keep-state :default\n" +"01100 queue 2 tcp from me to #203.0.113.20 5202# setup keep-state :default\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:721 +msgid "" +"Later versions of FreeBSD may not return any output on *ipfw queue* " +"configuration statements. The configuration is completed successfully, " +"though without any output." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:724 +msgid "Running" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:728 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:791 +#, no-wrap +msgid "# *iperf3 -c 203.0.113.10 -p 5201 -t 180 -O 30*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:733 +msgid "produces the output below." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:738 +msgid "" +"The output is the result of using the \"omit\" flag (-O) on the sender to " +"ignore the first 30 seconds of output. indexterm:[omit flag] This removes " +"the \"slow start\" portion of the TCP test, and focuses instead on the " +"\"steady state\" that occurs after slow start gets up to speed. indexterm:" +"[slow start] indexterm:[steady state]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:740 +#, no-wrap +msgid "Testing Separate Static Queues and Pipes" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:741 +#, no-wrap +msgid "Testing Separate Static Queues and Pipes. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:741 +#, no-wrap +msgid "ipfw-dummynet055.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:746 +msgid "" +"This example shows the steady state results of transmitting data through one " +"queue - *queue 1*. indexterm:[queue] Throughput was consistently about " +"277Kbits/sec." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:751 +msgid "" +"Later versions of FreeBSD and *iperf3* may differ from the display in the " +"above figure. Assess the correctness of the queue setup by examining the " +"transfer summary printed at the end of the *iperf3* command output." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:756 +msgid "During the transmission, a view of the queue status was:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:768 +#, no-wrap +msgid "" +"# *ipfw queue show*\n" +"q00001 50 sl. 2 flows (64 buckets) sched 1 weight 10 lmax 0 pri 0 droptail\n" +" #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1451#\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +"136 ip 0.0.0.0/0 203.0.113.10/5201 2293 3425216 42 63000 0\n" +" 50 ip 0.0.0.0/0 203.0.113.50/1040 752 39104 1 52 0\n" +"q00002 50 sl. 0 flows (64 buckets) sched 1 weight 10 lmax 0 pri 0 droptail\n" +" mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1452\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:772 +msgid "" +"The *queue mask*, set to show the full destination address and destination " +"port is highlighted. indexterm:[queue mask]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:777 +msgid "" +"Note that port numbers are displayed in hexadecimal. A decimal/hexadecimal " +"calculator may be helpful when looking at a lot of queue displays." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:780 +msgid "indexterm:[port number]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:782 +msgid "" +"The next example shows the result of starting two transmissions, one for " +"each queue." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:785 +msgid "" +"On the *external1* VM, set up the command *iperf3 -s -p 5201*, and on " +"*external2* use the command *iperf3 -s -p 5202*. indexterm:[iperf3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:787 +msgid "" +"Start the transfer to *external1* on the *firewall* VM with the command:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:794 +msgid "" +"and start the second transfer from a different session on the *firewall* VM " +"with the command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:798 +#, no-wrap +msgid "# *iperf3 -c 203.0.113.20 -p 5202 -t 180 -O 30*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:803 +msgid "" +"Notice how the queue is adjusted to accommodate the presence of a second " +"queue of equal weight:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:805 +#, no-wrap +msgid "Testing Two Static Queues and Pipes" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:806 +#, no-wrap +msgid "Testing Separate Static Queues and Pipes Equally Weighted. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:806 +#, no-wrap +msgid "ipfw-dummynet060.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:809 +msgid "" +"Since the queues were equally weighted, the result was that the transmission " +"rate for both ended up at about 139Kbits/sec or roughly half of the previous " +"transmission." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:813 +msgid "" +"Queue characteristics can be changed at any time, even during an active " +"flow. Consider the case below where, during simultaneous transmission " +"through queues of equal weight, the queue weights were modifed as follows: " +"indexterm:[queue weight]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:815 +msgid "queue 1: original weight 10\t\tmodified weight 10" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:817 +msgid "queue 2: original weight 10\t\tmodified weight 50" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:819 +msgid "This change can be effected by the command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:823 +#, no-wrap +msgid "# *ipfw queue 2 config weight 50*\n" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:826 +#, no-wrap +msgid "Testing Two Static Queues and Pipes Changed In-flight" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:827 +#, no-wrap +msgid "Testing Two Static Queues and Pipes Changed In-flight. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:827 +#, no-wrap +msgid "ipfw-dummynet065.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:831 +msgid "" +"The transmission rate for *queue 1* dropped from an average of 139 Kbits/sec " +"to an average of 46.3 Kbits/sec; while *queue 2*, after restarting the " +"transmission with the new queue weight, expanded from an average of 139Kbits/" +"sec to an average of 232 Kbits/sec. As expected, 232 Kbits is about five " +"times the transmission rate of 46.3 Kbits/sec." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:833 +msgid "Note however, that the above command had a side effect:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:841 +#, no-wrap +msgid "" +"# *ipfw queue show*\n" +"q00001 50 sl. 0 flows (64 buckets) sched 1 weight 10 lmax 0 pri 0 droptail\n" +" mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x1451\n" +"q00002 50 sl. 0 flows (1 buckets) sched 1 weight 50 lmax 0 pri 0 droptail\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:844 +msgid "indexterm:[queue]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:849 +msgid "" +"The *flow mask* for *queue 2* has been deleted. indexterm:[flow mask] In " +"fact, *all* settings not explicitly reset will revert to their default " +"settings. Here is a complicated queue setup:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:859 +#, no-wrap +msgid "" +"# *ipfw queue 1 config pipe 1 weight 40 buckets 256 mask src-ip 0x000000ff dst-ip 0x0000ffff noerror plr 0.01 queue 75 red .3/25/30/.5*\n" +"#\n" +"# *ipfw queue show*\n" +"#q00001 75 sl.plr 0.010000 0 flows (256 buckets) sched 1 weight 40 lmax 0 pri 0#\n" +" #RED w_q 0.299988 min_th 25 max_th 30 max_p 0.500000#\n" +" #mask: 0x00 0x000000ff/0x0000 -> 0x0000ffff/0x0000#\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:862 +msgid "indexterm:[pipe] indexterm:[weight] indexterm:[queue] indexterm:[red]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:865 +msgid "" +"And if, similar to the previous example, only the weight is changed: " +"indexterm:[weight]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:873 +#, no-wrap +msgid "" +"# *ipfw queue 1 config weight 20*\n" +"#\n" +"# ipfw queue show\n" +"#q00001 50 sl. 0 flows (1 buckets) sched 1 weight 20 lmax 0 pri 0 droptail#\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:879 +msgid "" +"All the other parameters of the queue are reset to their defaults. " +"Therefore, *_it is best to retain the original commands used to construct " +"queues, pipes, and schedulers, even if changing only one parameter._* That " +"way, all other parameters can be replicated on the command line. Otherwise " +"it may be necessary to reconstruct the parameters from the output of *ipfw " +"queue show* which can be quite tedious." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:880 +#, no-wrap +msgid "Dynamic Pipes" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:884 +msgid "" +"Here, note that the simplest setup for *pipes* creates *dynamic pipes* when " +"needed: indexterm:[dynamic pipe]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:908 +#, no-wrap +msgid "" +"# *ipfw pipe 1 config bw 300kbit/s weight 10 mask src-ip 0x0000ffff dst-ip 0xffffffff*\n" +"Bump sched buckets to 64 (was 0)\n" +"#\n" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 10 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 0 active\n" +" mask: 0x00 0x0000ffff/0x0000 -> 0xffffffff/0x0000\n" +"#\n" +"# *ipfw list*\n" +"00050 allow icmp from any to any\n" +"00100 check-state :default\n" +"65535 deny ip from any to any\n" +"#\n" +"# *ipfw add 1000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state*\n" +"01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default\n" +"#\n" +"# *ipfw list*\n" +"01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:911 +msgid "Sending some data with this configuration:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:931 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 10 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 4 active\n" +" mask: 0x00 0x0000ffff/0x0000 -> 0xffffffff/0x0000\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 6 ip 0.0.10.10/0 203.0.113.50/0 236 12272 0 0 0\n" +" 78 ip 0.0.10.50/0 203.0.113.10/0 1493 2225216 43 64500 0\n" +" 80 ip 0.0.10.50/0 203.0.113.20/0 1355 2018216 42 63000 0\n" +" 58 ip 0.0.10.20/0 203.0.113.50/0 366 19032 0 0 0\n" +"#\n" +"# *ipfw list*\n" +"00050 allow icmp from any to any\n" +"00100 check-state :default\n" +"01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:935 +msgid "" +"All three transmissions running together, single *pipe*: indexterm:[pipe]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:950 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 10 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 6 active\n" +" mask: 0x00 0x0000ffff/0x0000 -> 0xffffffff/0x0000\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 6 ip 0.0.10.10/0 203.0.113.50/0 588 30576 0 0 0\n" +" 78 ip 0.0.10.50/0 203.0.113.10/0 1508 2247716 43 64500 0\n" +" 80 ip 0.0.10.50/0 203.0.113.20/0 1357 2021216 43 64500 0\n" +" 90 ip 0.0.10.50/0 203.0.113.30/0 1322 1981552 41 61500 0\n" +" 46 ip 0.0.10.30/0 203.0.113.50/0 34 1768 0 0 0\n" +" 58 ip 0.0.10.20/0 203.0.113.50/0 702 36504 0 0 0\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:953 +msgid "Because of the *ipfw* rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:957 +#, no-wrap +msgid "01000 pipe 1 tcp from me to 203.0.113.0/24 5201-5203 setup keep-state :default\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:961 +msgid "" +"All are getting 290 Kbit/sec from *iperf3* and they are all sharing the " +"*pipe* equally. indexterm:[pipe] indexterm:[iperf3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:965 +msgid "" +"If *iperf3* is changed to send to different ports for each system (5201, " +"5202, 5203) on the *external1*, *external2*, and *external3* VMs " +"respectively, there is no change. It is only with *queues*, and setting the " +"individual flow rate, that can effect change. indexterm:[flow rate]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:967 +msgid "Below are examples of different masks and their effect on traffic flow:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:971 +#, no-wrap +msgid "* dst-ip 0x0000ffff\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:982 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 4 active\n" +" #mask: 0x00 0x00000000/0x0000 -> 0x0000ffff/0x0000#\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 10 ip 0.0.0.0/0 0.0.10.10/0 1183 1760218 43 64500 0\n" +" 20 ip 0.0.0.0/0 0.0.10.20/0 974 1446718 42 63000 0\n" +" 30 ip 0.0.0.0/0 0.0.10.30/0 688 1017718 35 52500 0\n" +" 50 ip 0.0.0.0/0 0.0.10.50/0 1717 89284 0 0 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:985 +#, no-wrap +msgid "* dst-ip 0xffffffff\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:996 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 4 active\n" +" #mask: 0x00 0x00000000/0x0000 -> 0xffffffff/0x0000#\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 18 ip 0.0.0.0/0 203.0.113.50/0 402 20888 0 0 0\n" +" 42 ip 0.0.0.0/0 203.0.113.10/0 144 204722 0 0 0\n" +" 52 ip 0.0.0.0/0 203.0.113.20/0 359 525971 0 0 0\n" +" 62 ip 0.0.0.0/0 203.0.113.30/0 562 843000 37 55500 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:999 +#, no-wrap +msgid "* src-ip 0x0000ffff\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1010 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 4 active\n" +" #mask: 0x00 0x0000ffff/0x0000 -> 0x00000000/0x0000#\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 20 ip 0.0.10.10/0 0.0.0.0/0 361 19348 0 0 0\n" +"100 ip 0.0.10.50/0 0.0.0.0/0 2102 3079974 36 54000 27\n" +" 40 ip 0.0.10.20/0 0.0.0.0/0 193 10416 0 0 0\n" +" 60 ip 0.0.10.30/0 0.0.0.0/0 47 2612 0 0 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1013 +#, no-wrap +msgid "* mask src-ip 0x0000ffff dst-ip 0x0000ffff <-only one keyword mask needs to be specified\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1026 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 6 active\n" +" #mask: 0x00 0x0000ffff/0x0000 -> 0x0000ffff/0x0000#\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 14 ip 0.0.10.30/0 0.0.10.50/0 253 13156 0 0 0\n" +" 26 ip 0.0.10.20/0 0.0.10.50/0 61 3172 0 0 0\n" +" 38 ip 0.0.10.10/0 0.0.10.50/0 771 40094 0 0 0\n" +"110 ip 0.0.10.50/0 0.0.10.10/0 853 1265218 40 60000 0\n" +"112 ip 0.0.10.50/0 0.0.10.20/0 723 1083052 37 55500 0\n" +"122 ip 0.0.10.50/0 0.0.10.30/0 644 951718 34 51000 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1029 +#, no-wrap +msgid "* mask src-ip 0x0000ffff dst-ip 0x0000ffff dst-port 5201\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1042 +#, no-wrap +msgid "" +"# *ipfw pipe show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 6 active\n" +" #mask: 0x00 0x0000ffff/0x0000 -> 0x0000ffff/0x1451#\n" +"BKT Prot Source IP/port Dest. IP/port ot_pkt/bytes Pkt/Byte Drp\n" +"204 ip 0.0.10.50/0 0.0.10.10/5201 2132 3183718 43 64500 0\n" +" 14 ip 0.0.10.30/0 0.0.10.50/4096 823 42796 0 0 0\n" +"210 ip 0.0.10.50/0 0.0.10.20/5201 2001 2987218 43 64500 0\n" +"152 ip 0.0.10.20/0 0.0.10.50/4161 663 34476 0 0 0\n" +"216 ip 0.0.10.50/0 0.0.10.30/5201 1981 2957218 43 64500 0\n" +"164 ip 0.0.10.10/0 0.0.10.50/65 471 24492 0 0 0\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1045 +#, no-wrap +msgid "* mask src-ip 0xffffffff dst-ip 0xffffffff\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1058 +#, no-wrap +msgid "" +"# *ipfw pipe 1 show*\n" +"00001: 300.000 Kbit/s 0 ms burst 0\n" +"q131073 50 sl. 0 flows (1 buckets) sched 65537 weight 0 lmax 0 pri 0 droptail\n" +" sched 65537 type FIFO flags 0x1 64 buckets 6 active\n" +" #mask: 0x00 0xffffffff/0x0000 -> 0xffffffff/0x0000#\n" +"BKT Prot Source IP/port Dest. IP/port Tot_pkt/bytes Pkt/Byte Drp\n" +" 64 ip 203.0.113.50/0 203.0.113.20/0 1215 1808218 43 64500 0\n" +" 74 ip 203.0.113.50/0 203.0.113.30/0 1023 1533052 43 64500 0\n" +" 22 ip 203.0.113.10/0 203.0.113.50/0 746 38792 0 0 0\n" +" 94 ip 203.0.113.50/0 203.0.113.10/0 1863 2780218 42 63000 0\n" +" 42 ip 203.0.113.20/0 203.0.113.50/0 481 25012 0 0 0\n" +" 62 ip 203.0.113.30/0 203.0.113.50/0 159 8268 0 0 0\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1060 +#, no-wrap +msgid "Other Pipe and Queue Commands" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1063 +msgid "To delete pipes and queues use the following syntax:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1067 +#, no-wrap +msgid "For queues, specify the queue number on the command line:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1069 +#, no-wrap +msgid "# *ipfw queue delete 1*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1071 +#, no-wrap +msgid "For pipes, specify the pipe number on the command line:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1073 +#, no-wrap +msgid "# *ipfw pipe delete 1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1077 +msgid "indexterm:[pipe, delete] indexterm:[queue, delete]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1080 +msgid "Note however that:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1084 +#, no-wrap +msgid "# *ipfw delete pipe 1* #<----- does not throw error, and does not delete the pipe.#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1088 +msgid "" +"The same is true for the corresponding *queue* keyword. Take care to use " +"the proper syntax." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1093 +msgid "" +"It is possible to delete a *pipe* with a *pipe* statement still in the " +"ruleset. *ipfw* will not throw an error - but any data transfer matching " +"the *pipe* statement will not work." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1096 +msgid "indexterm:[pipe, delete]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1101 +#, no-wrap +msgid "" +"*scheds* (schedulers) and *pipes* are tightly bound.\n" +"indexterm:[sched, delete]\n" +"To delete a scheduler, first delete the *pipe*, and then re-create the *pipe*.\n" +"The scheduler for the new *pipe* is reset to the default scheduler.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1106 +#, no-wrap +msgid "" +"To change the scheduler type:\n" +"# *ipfw sched config 1 type wfq2* # or *rr* or any other *sched* type\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1109 +msgid "indexterm:[scheduler type] indexterm:[wfq2]" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1110 +#, no-wrap +msgid "Adding Additional Virtual Machines" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1114 +msgid "" +"Up to this point, only two or three virtual machines have been used for " +"exploring *ipfw*. The later material in this book requires the use of " +"several additional virtual machines." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1117 +msgid "The NAT chapter calls for several more VMs for: indexterm:[NAT]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1118 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1126 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1134 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1142 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1150 +#, no-wrap +msgid "---\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1121 +msgid "indexterm:[simple NAT]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1123 +#, no-wrap +msgid "Setting Up Simple NAT" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1124 +#, no-wrap +msgid "Setting Up Simple NAT. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1124 +#, no-wrap +msgid "ipfw-nat070-scaled-down.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1129 +msgid "indexterm:[load sharing NAT] indexterm:[LSNAT]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1131 +#, no-wrap +msgid "Setting up Load Sharing NAT" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1132 +#, no-wrap +msgid "Setting Up Load Sharing NAT. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1132 +#, no-wrap +msgid "ipfw-nat075-scaled-down.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1137 +msgid "indexterm:[NAT64] indexterm:[DNS64]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1139 +#, no-wrap +msgid "Setting Up NAT64 and DNS64" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1140 +#, no-wrap +msgid "Setting Up NAT64 and DNS64. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1140 +#, no-wrap +msgid "ipfw-nat080-scaled-down.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1145 +msgid "indexterm:[464XLAT]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1147 +#, no-wrap +msgid "Setting Up 464XLAT" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1148 +#, no-wrap +msgid "Setting Up 464XLAT. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1148 +#, no-wrap +msgid "ipfw-nat090-scaled-down.png" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1152 +#, no-wrap +msgid "Setting Up The Entire IPFW Lab" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1156 +msgid "" +"A suggested host machine file directory layout for these machines is shown " +"below. All scripts use relative path names, so the directory can be located " +"anywhere." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1195 +#, no-wrap +msgid "" +" ~/ipfw\n" +" /SCRIPTS\n" +" _CreateAllVMs.sh (script to create QEMU disks images)\n" +" mkbr.sh (script to create bridge and tap devices)\n" +" vm_envs.sh (script to manage all parameters)\n" +" dnshost.sh (script for running a BIND 9 DNS server)\n" +" external1.sh (scripts for running 'external VM host' VMs)\n" +" external2.sh \"\n" +" external3.sh \"\n" +" firewall.sh (script for running a firewall VM)\n" +" firewall2.sh (script for running a firewall VM)\n" +" internal.sh (script for running an internal VM)\n" +" v6only.sh (script for running an IPv6 only VM)\n" +" jail1.sh (script for running a jails VM)\n" +" /ISO\n" +" fbsd.iso (link to latest FreeBSD install iso)\n" +" /VM\n" +" dnshost.qcow2 (QEMU disk image for a BIND 9 DNS server)\n" +" external1.qcow2 (QEMU disk image for 'external' hosts)\n" +" external2.qcow2 \"\n" +" external3.qcow2 \"\n" +" firewall.qcow2 (QEMU disk image for the 'firewall')\n" +" firewall2.qcow2 (QEMU disk image for the 'firewall2' VM)\n" +" internal.qcow2 (QEMU disk image for an internal VM)\n" +" v6only.qcow2 (QEMU disk image for an IPv6 only VM)\n" +" jail1.qcow2 (QEMU disk image for the jails VM)\n" +" /BMP\n" +" dns_splash_640x480.bmp (QEMU splash image)\n" +" external1_splash_640x480.bmp \"\n" +" external2_splash_640x480.bmp \"\n" +" external3_splash_640x480.bmp \"\n" +" firewall_splash_640x480.bmp \"\n" +" firewall2_splash_640x480.bmp \"\n" +" internal_splash_640x480.bmp \"\n" +" v6only_splash_640x480.bmp \"\n" +" jail1_splash_640x480.bmp \"\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1198 +msgid "indexterm:[SCRIPTS] indexterm:[ISO] indexterm:[VM] indexterm:[BMP]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1202 +msgid "" +"Finish setting up the entire lab by referring to the instructions found in " +"Section crossref:ipfw-introduction[ipfw-introduction-quickstart, Quick " +"Start]. indexterm:[Quick Start]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-dummynet/_index.adoc:1205 +msgid "" +"Also, ensure each virtual machine is set up to boot a serial console by " +"adding \"console=comconsole\" to [.filename]#/boot/loader.conf#. indexterm:" +"[console, serial]" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-index/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-index/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-index/_index.adoc @@ -0,0 +1,50 @@ +--- +title: Index +prev: books/ipfw-primer/ipfw-appendix-e +description: Index +tags: ["firewall", "IPFW", "Virtual Machine", "VM", "QEMU"] +showBookMenu: true +weight: 140 +path: "/books/ipfw-primer/ipfw-index/" +--- + +[AnIndex] +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: D +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +[index] += Index + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-index/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-index/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-index/_index.po @@ -0,0 +1,24 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-index/_index.adoc:1 +#: documentation/content/en/books/ipfw-primer/ipfw-index/_index.adoc:49 +#, no-wrap +msgid "Index" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc @@ -0,0 +1,135 @@ +--- +title: Chapter 1. Introduction +prev: books/ipfw-primer/ipfw-preface +next: books/ipfw-primer/ipfw-operation +description: Introduction about IPFW +tags: ["introduction", "IPFW", "firewall"] +showBookMenu: true +weight: 20 +path: "/books/ipfw-primer/ipfw-introduction/" +--- + +[[ipfw-introduction]] += Introduction +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 1 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +This book is about one of the native firewalls included with FreeBSD, man:ipfw[8] - the Internet Protocol FireWall. +*ipfw* is designed to operate on a FreeBSD host with multiple network interfaces, to filter out unwanted traffic and pass through desired traffic. +It does this based on a collection of rules (numbered, text based statements) that are entered into the system from the command line. +indexterm:[rules] +This usage model is different from many other firewall products that employ Graphical User Interfaces (GUIs), or separate control programs. +indexterm:[GUI] +All *ipfw* statements are entered into the user shell, typically by a user with root privileges or access to root privilege by means of programs that elevate normal user privileges such as man:sudo[8] or man:doas[1]. +indexterm:[privilege] indexterm:[sudo] indexterm:[doas] + +*ipfw* reads network traffic from the interfaces it knows about and processes them inside the FreeBSD kernel. +*ipfw* itself is a kernel module that can be either compiled into the kernel or loaded at run time. +indexterm:[module, ipfw] +It includes a number of other kernel modules (*ipfw_nat*, *ipfw_nptv6*, etc.) many of which are discussed in this book. +indexterm:[module, ipfw_nat] indexterm:[module, ipfw_nptv6] + +A bird's-eye view of *ipfw* operation notes that: + +. Rules are organized into a sorted list based on a rule number +. Packets entering the kernel from a network interface or leaving the kernel via a network interface are checked against the ruleset +indexterm:[ruleset] +. Rules are checked one by one and the first rule that matches the packet characteristics wins - that is, *ipfw* accepts the packet for processing - allowing transit through the firewall, denying transit, updating a counter, or moving the packet into userspace for specialized processing. + +The book makes frequent reference to the man:ipfw[8] manual page and the reader is advised to become familiar with the manual page alongside this book. +There is also a section on *ipfw* in the link:https://docs.freebsd.org/en/books/handbook/firewalls/#firewalls-ipfw[FreeBSD Handbook Page on IPFW]. +The intent with this book is to provide examples and informative material beyond the manual page and handbook to increase understanding and usage of *ipfw*. + +Throughout this book are many examples of using *ipfw* with virtual machines to simulate actual hardware. +indexterm:[virtual machine] indexterm:[QEMU] +These examples were developed with link:https://www.qemu.org[QEMU] version 9.2.0. +It is, of course, entirely possible to perform all the examples in this book with real hardware. +QEMU provides a way to perform the examples without spending any money for hardware. +In either case, some setup is required. + +[NOTE] +==== +Note that QEMU command syntax with some of the examples may have changed slightly by the time this book becomes available. +Use the latest QEMU release where possible, and check the QEMU documentation if the examples in this book do not work correctly. +==== + +Also used are a number of scripts that allow easy man:if_bridge[4] and man:tap[4] setup, virtual machine setup, and data transfer from external VMs to or through a firewall VM. +indexterm:[bridge] indexterm:[tap] +In the early examples, data transfer is accomplished with the *netcat* program, specifically the version distributed with the link:https://www.nmap.org[nmap] package (www.nmap.org). +indexterm:[netcat] indexterm:[nmap] +This version, man:ncat[1], has the best coverage of features that are used throughout the book. +indexterm:[ncat] +A familiarity with the man page for man:ncat[1] is helpful, but not required. + +All scripts used in this book are found in crossref:ipfw-appendix-b[appendix-b,Appendix B] and published under the BSD 3-clause license. +indexterm:[scripts] +The scripts are also available on the GitHub link:https://github.com/jimmyb-gh/ipfw-primer[IPFW Primer] page. +indexterm:[github] + +When copy/pasting examples, be aware that some desktop copy/paste functions add an extra space (or multiple spaces) to the end of a line, messing up the Unix continuation character convention ' ... \' at the end of a line. +Ensure that the paste function does not introduce extra spaces at the end of the line. + +[NOTE] +==== +The examples in this book involve passing data between interfaces on the host system. +A running firewall on the host such as *pf*, *ipfw*, or *ipfilter* (also known as *ipf*) may interfere with data transfer, so ensure that any host system firewall is disabled. +In addition, take any necessary steps to ensure that this does not compromise the security of the host. +==== + +[[ipfw-introduction-quickstart]] +== Quick Start + +Instructions for setting up all virtual machines (VMs) are found in crossref:ipfw-appendix-a[appendix-a, Appendix A]. +indexterm:[Quick Start] indexterm:[QEMU] + +In general you will need the following: + +* Intel(R)/AMD(R) machine with a 64-bit processor. +Any machine manufactured to recent Microsoft Windows(R) specifications should work. +Processor speed will determine how responsive the virtual machines appear, so the faster, the better. + +* At minimum, 8GB RAM. +Each virtual machine is configured to use 1GB and for the first half of the book, only four VMs are used at the same time. +In later chapters, the *jail1* VM, will require more memory (8GB). + +* At least 50GB of free disk space to install all virtual machines. +Each virtual machine uses 4GB and the *jail1* VM uses 12GB. + + +For the first half of this book, only four virtual machines are necessary - the *firewall* VM, and the *internal*, *external1* and *external2* VMs. + +Additional detail, along with setup instructions for all virtual machines, is provided in crossref:ipfw-appendix-a[appendix-a, Appendix A]. diff --git a/documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.po @@ -0,0 +1,1093 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:1 +#, no-wrap +msgid "Introduction about IPFW" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:1 +#, no-wrap +msgid "Chapter 1. Introduction" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:13 +#, no-wrap +msgid "Introduction" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:59 +msgid "" +"This book is about one of the native firewalls included with FreeBSD, man:" +"ipfw[8] - the Internet Protocol FireWall. *ipfw* is designed to operate on " +"a FreeBSD host with multiple network interfaces, to filter out unwanted " +"traffic and pass through desired traffic. It does this based on a " +"collection of rules (numbered, text based statements) that are entered into " +"the system from the command line. indexterm:[rules] This usage model is " +"different from many other firewall products that employ Graphical User " +"Interfaces (GUIs), or separate control programs. indexterm:[GUI] All *ipfw* " +"statements are entered into the user shell, typically by a user with root " +"privileges or access to root privilege by means of programs that elevate " +"normal user privileges such as man:sudo[8] or man:doas[1]. indexterm:" +"[privilege] indexterm:[sudo] indexterm:[doas]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:65 +#, no-wrap +msgid "" +"*ipfw* reads network traffic from the interfaces it knows about and processes them inside the FreeBSD kernel.\n" +"*ipfw* itself is a kernel module that can be either compiled into the kernel or loaded at run time.\n" +"indexterm:[module, ipfw]\n" +"It includes a number of other kernel modules (*ipfw_nat*, *ipfw_nptv6*, etc.) many of which are discussed in this book.\n" +"indexterm:[module, ipfw_nat] indexterm:[module, ipfw_nptv6]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:67 +msgid "A bird's-eye view of *ipfw* operation notes that:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:69 +msgid "Rules are organized into a sorted list based on a rule number" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:71 +msgid "" +"Packets entering the kernel from a network interface or leaving the kernel " +"via a network interface are checked against the ruleset indexterm:[ruleset]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:72 +msgid "" +"Rules are checked one by one and the first rule that matches the packet " +"characteristics wins - that is, it accepts the packet for processing, either " +"allowing transit through the firewall, denying transit, or moving the packet " +"into userspace for specialized processing." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:76 +msgid "" +"The book makes frequent reference to the man:ipfw[8] manual page and the " +"reader is advised to become familiar with the manual page alongside this " +"book. There is also a section on *ipfw* in the link:https://docs.freebsd." +"org/en/books/handbook/firewalls/#firewalls-ipfw[FreeBSD Handbook Page on " +"IPFW]. The intent with this book is to provide examples and informative " +"material beyond the manual page and handbook to increase understanding and " +"usage of *ipfw*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:83 +msgid "" +"Throughout this book are many examples of using *ipfw* with virtual machines " +"to simulate actual hardware. indexterm:[virtual machine] indexterm:[QEMU] " +"These examples were developed with link:https://www.qemu.org[QEMU] version " +"9.0.2. It is, of course, entirely possible to perform all the examples in " +"this book with real hardware. QEMU provides a way to perform the examples " +"without spending any money for hardware. In either case, some setup is " +"required." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:88 +msgid "" +"Note that QEMU command syntax with some of the examples may have changed " +"slightly by the time this book becomes available. Use the latest QEMU " +"release where possible, and check the QEMU documentation if the examples in " +"this book do not work correctly." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:97 +msgid "" +"Also used are a number of scripts that allow easy man:if_bridge[4] and man:" +"tap[4] setup, virtual machine setup, and data transfer from external VMs to " +"or through a firewall VM. indexterm:[bridge] indexterm:[tap] In the early " +"examples, data transfer is accomplished with the *netcat* program, " +"specifically the version distributed with the link:https://www.nmap." +"org[nmap] package (www.nmap.org). indexterm:[netcat] indexterm:[nmap] This " +"version, man:ncat[1], has the best coverage of features that are used " +"throughout the book. indexterm:[ncat] A familiarity with the man page for " +"man:ncat[1] is helpful, but not required." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:102 +msgid "" +"All scripts used in this book are found in crossref:ipfw-appendix-b[appendix-" +"b,Appendix B] and published under the BSD 3-clause license. indexterm:" +"[scripts] The scripts are also available on the GitHub link:https://github." +"com/jimmyb-gh/ipfw-primer[IPFW Primer] page. indexterm:[github]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:105 +msgid "" +"When copy/pasting examples, be aware that some desktop copy/paste functions " +"add an extra space (or multiple spaces) to the end of a line, messing up the " +"Unix continuation character convention ' ... \\' at the end of a line. " +"Ensure that the paste function does not introduce extra spaces at the end of " +"the line." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:111 +msgid "" +"The lab examples in this book involve passing data between interfaces on the " +"host system. A running firewall on the host such as *pf*, *ipfw*, or " +"*ipfilter* (also known as *ipf*) may interfere with data transfer, so ensure " +"that any host system firewall is disabled. In addition, take any necessary " +"steps to ensure that this does not compromise the security of the host." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:114 +#, no-wrap +msgid "Quick Start" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:120 +msgid "" +"This section details the steps to quickly begin using two QEMU virtual " +"machines, one named \"*firewall*\" and the other named \"*external1*\". " +"indexterm:[Quick Start] indexterm:[QEMU] These are the first two of several " +"that will be used throughout this book. Additional detail, along with setup " +"instructions for all virtual machines, is provided in crossref:ipfw-appendix-" +"a[appendix-a, Appendix A]." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:122 +#, no-wrap +msgid "Setting Up the Initial Virtual Machines" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:123 +#, no-wrap +msgid "Setting Up the Initial Virtual Machines. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:123 +#, no-wrap +msgid "ipfw-introduction001.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:127 +msgid "" +"The initial setup is that shown in crossref:ipfw-introduction[ipfw-" +"introduction-quick00,Figure {counter:figure}]. indexterm:[virtual machine]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:129 +#, no-wrap +msgid "QEMU VM Installation Process" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:133 +msgid "" +"Follow the steps below to install and configure the QEMU virtual machines " +"for this example. indexterm:[QEMU]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:140 +msgid "" +"On the FreeBSD host, install the necessary packages - man:qemu[1], man:" +"sudo[8] (or man:doas[1]). Sudo, (or doas) is necessary for running the " +"virtual machines as these QEMU configurations open a separate console window " +"through SDL. indexterm:[SDL] The examples in this book use sudo." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:144 +#, no-wrap +msgid "# *pkg install qemu sudo*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:147 +msgid "indexterm:[QEMU, pkg install] indexterm:[sudo]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:149 +msgid "Configure sudo as desired." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:151 +msgid "" +"Create a directory layout for virtual machines and scripts, and download an " +"install ISO for FreeBSD." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:157 +#, no-wrap +msgid "" +"% *mkdir -p ~/ipfw/VM ~/ipfw/SCRIPTS ~/ipfw/ISO*\n" +"% *cd ~/ipfw/ISO*\n" +"% *fetch https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/##/FreeBSD-##-RELEASE-amd64-dvd1.iso*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:160 +msgid "indexterm:[SCRIPTS] indexterm:[ISO] indexterm:[fetch]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:162 +msgid "" +"Create the bridge and tap devices for the virtual machines (VMs) to use." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:174 +#, no-wrap +msgid "" +"# *ifconfig tap0 create*\n" +"# *ifconfig tap1 create*\n" +"# *sysctl net.link.tap.up_on_open=1*\n" +"net.link.tap.up_on_open: 0 -> 1\n" +"# *sysctl net.link.tap.user_open=1*\n" +"net.link.tap.user_open: 0 -> 1\n" +"# *ifconfig bridge0 create*\n" +"# *ifconfig bridge0 addm tap0 addm tap1 addm _hostintf_* #<--- replace _hostintf_ with host network interface (em0, bge0, etc.)#\n" +"# *ifconfig bridge0 up*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:177 +msgid "indexterm:[tap] indexterm:[bridge]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:179 +msgid "" +"A script for creating and managing bridge and tap devices is introduced in " +"the next section." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:181 +msgid "Create two new VM image files and install FreeBSD on one." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:191 +#, no-wrap +msgid "" +"% *cd ~/ipfw/VM*\n" +"% *qemu-img create -f qcow2 -o preallocation=full firewall.qcow2 8G*\n" +"% *qemu-img create -f qcow2 -o preallocation=full external1.qcow2 8G*\n" +"% *cd ~/ipfw/ISO*\n" +"% # Link a shorter name to the ISO image.\n" +"% *ln -s FreeBSD--RELEASE-amd64-dvd1.iso fbsd.iso*\n" +"% *cd ~/ipfw/SCRIPTS*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:193 +#, no-wrap +msgid "Copy the below text into a file (say, [.filename]#firewall.sh#) and run:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:195 +#, no-wrap +msgid "% *sudo /bin/sh firewall.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:199 +#, no-wrap +msgid "" +"-------\n" +"#!/bin/sh\n" +"# firewall.sh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:213 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor stdio \\\n" +" -cpu qemu64 \\\n" +" -vga std \\\n" +" -m 4096 \\\n" +" -smp 4 \\\n" +" -cdrom ../ISO/fbsd.iso \\\n" +" -boot order=cd,menu=on \\\n" +" -blockdev driver=file,aio=threads,node-name=imgright,filename=../VM/firewall.qcow2 \\\n" +" -blockdev driver=qcow2,node-name=drive0,file=imgright \\\n" +" -device virtio-blk-pci,drive=drive0,bootindex=1 \\\n" +" -netdev tap,id=nd0,ifname=tap0,script=no,downscript=no,br=bridge0 \\\n" +" -device e1000,netdev=nd0,mac=02:69:70:66:77:00 \\\n" +" -name \\\"Firewall\\\"\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:216 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:268 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:532 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:565 +#, no-wrap +msgid "" +"exit\n" +"-------\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:219 +msgid "" +"indexterm:[qemu-img] indexterm:[qcow2] indexterm:[-blockdev] indexterm:[-" +"device] indexterm:[-netdev]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:222 +msgid "" +"The FreeBSD installer should boot. Perform a standard installation of " +"FreeBSD." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:224 +msgid "During the installation note the following:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:229 +msgid "" +"Select to use UFS as the filesystem. indexterm:[UFS] ZFS does not perform " +"well with small memory sizes. indexterm:[ZFS]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:233 +msgid "" +"In this Quick Start, use DHCP for networking. indexterm:[DHCP] If desired, " +"configure IPv6 if supported by the local LAN." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:235 +msgid "" +"When adding the default user, ensure they are a member of the _wheel_ group." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:237 +msgid "" +"Once the installation completes, the virtual machine reboots into the newly " +"installed FreeBSD image." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:239 +msgid "Login as root and update the system if desired." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:241 +msgid "" +"Repeat the above step to create another QEMU script file, and perform " +"another installation with these changes:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:245 +#, no-wrap +msgid "Copy the below text into a file (say, [.filename]#external1.sh#) and run:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:247 +#, no-wrap +msgid "% *sudo /bin/sh external1.sh*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:251 +#, no-wrap +msgid "" +"-------\n" +"#!/bin/sh\n" +"# external1.sh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:265 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor stdio \\\n" +" -cpu qemu64 \\\n" +" -vga std \\\n" +" -m 4096 \\\n" +" -smp 4 \\\n" +" -cdrom ../ISO/fbsd.iso \\\n" +" -boot order=cd,menu=on \\\n" +" -blockdev driver=file,aio=threads,node-name=imgleft,filename=../VM/external1.qcow2 \\\n" +" -blockdev driver=qcow2,node-name=drive0,file=imgleft \\\n" +" -device virtio-blk-pci,drive=drive0,bootindex=1 \\\n" +" -netdev tap,id=nd0,ifname=tap1,script=no,downscript=no,br=bridge0 \\\n" +" -device e1000,netdev=nd0,mac=02:20:65:78:74:31 \\\n" +" -name \\\"External1\\\"\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:271 +msgid "As above, login and update the system if desired." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:277 +msgid "" +"On both virtual machines (and all later installed VMs) , install the " +"packages listed below The `nmap` package brings in the version of man:" +"ncat[1] used by scripts on the *firewall* and *external* VMs. indexterm:" +"[nmap] `nginx`, `lynx`, `cmdwatch`, `hping3`, and `iperf3` will be used in " +"later chapters. indexterm:[nginx] indexterm:[lynx] indexterm:[cmdwatch] " +"indexterm:[hping3] indexterm:[iperf3]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:281 +#, no-wrap +msgid "# *pkg install nmap nginx lynx cmdwatch hping3 iperf3*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:285 +msgid "" +"Finally, download link:https://raw.githubusercontent.com/jimmyb-gh/ipfw-" +"primer/main/ipfw/SCRIPTS/VM_SCRIPTS/IPFW_root_bin.tgz[IPFW_root_bin.tgz] " +"file to *_both_* VMs. This tar file has a number of scripts needed for the " +"virtual machines." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:287 +msgid "Move the tarzip file into [.filename]#/root# and extract the contents:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:300 +#, no-wrap +msgid "" +"# *fetch https://raw.githubusercontent.com/jimmyb-gh/ipfw-primer/main/ipfw/SCRIPTS/VM_SCRIPTS/IPFW_root_bin.tgz*\n" +"#\n" +"# *mv IPFW_root_bin.tgz /root*\n" +"#\n" +"# *cd /root*\n" +"#\n" +"# *tar xvzf IPFW_root_bin.tgz*\n" +"... files are extracted into /root/bin\n" +"#\n" +"# *chmod +x /root/bin/***.sh*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:303 +msgid "indexterm:[VM_SCRIPTS]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:305 +msgid "(End installation procedure.)" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:312 +msgid "" +"For this Quick Start, it is Ok to use `DHCP` for both VMs. indexterm:[Quick " +"Start] indexterm:[DHCP] In later examples there will be multiple external " +"VMs using the *203.0.113.0/24* network and other private networks, all set " +"up the same way and attached via man:tap[4] interfaces to one or more man:" +"if_bridge[4] interfaces on the FreeBSD host. indexterm:[networks, private] " +"indexterm:[bridge] indexterm:[tap]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:317 +msgid "" +"To ensure the first two VMs are set up correctly, ping the *firewall* VM " +"from the *external1* VM and vice-versa. Communications should be " +"successful. If not, check the above installation details and troubleshoot " +"any network issues. It should be possible ping in both directions, and even " +"man:ssh[1] from one VM to the other." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:321 +msgid "" +"For additional helpful information on getting QEMU set up correctly, check " +"the link:https://docs.freebsd.org/en/books/handbook/virtualization/#qemu-" +"virtualization-host-guest[QEMU virtualization section in the FreeBSD " +"Handbook]." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:327 +msgid "" +"If the mouse is clicked in the QEMU console window, QEMU will “grab” the " +"mouse. If this happens,type, kbd:[Ctl]+kbd:[Alt]+kbd:[G] to release the " +"mouse." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:329 +msgid "indexterm:[mouse, grab]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:334 +msgid "" +"If suddenly, the QEMU console window is full screen, you have accidentally " +"typed kbd:[Ctl]+kbd:[Alt]+kbd:[F]. If this happens, retype kbd:[Ctl]+kbd:" +"[Alt]+kbd:[F] to restore the desktop screen." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:336 +msgid "indexterm:[full screen]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:337 +#, no-wrap +msgid "Disabling Syslog Messages to the Console in the Virtual Machines" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:341 +msgid "" +"It may be advantageous (even necessary) to stop syslog messages from being " +"sent to the console (either the QEMU console, or the serial port). " +"indexterm:[syslog] indexterm:[console, virtual] indexterm:[console, serial]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:343 +msgid "" +"To configure syslog to stop logging to the console, configure a file to " +"receive console messages:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:349 +#, no-wrap +msgid "" +"# *touch /var/log/console.log*\n" +"#\n" +"# *chmod 0600 /var/log/console.log*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:351 +msgid "indexterm:[console.log]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:354 +msgid "" +"Then, as *root*, modify the line in [.filename]#/etc/syslog.conf# to read " +"(instead of [.filename]#/dev/console#): indexterm:[/etc/syslog.conf]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:358 +#, no-wrap +msgid "**.err;kern.warning;auth.notice;mail.crit /var/log/console.log*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:361 +msgid "And, if necessary:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:363 +msgid "indexterm:[syslogd]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:367 +#, no-wrap +msgid "# *service syslogd restart*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:371 +msgid "" +"All messages previously bound for the console, will be directed to [." +"filename]#/var/log/console.log# instead. indexterm:[console, virtual]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:375 +msgid "" +"Before continuing, there is one more piece to add to each VM - a serial " +"console. indexterm:[console, serial] A serial console permits examination " +"of the state of each VM, independent of the main console." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:377 +#, no-wrap +msgid "Adding and Managing Serial Console Access to the VMs" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:380 +#, no-wrap +msgid "*Adding a serial console to FreeBSD*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:385 +msgid "" +"To add a serial console to each FreeBSD VM, start up the VM and edit the " +"file [.filename]#/boot/loader.conf# and add *console=“comconsole”* to allow " +"use of the serial console. indexterm:[/boot/loader.conf] indexterm:" +"[comconsole] Reboot the VM to begin using the serial console. Note that " +"FreeBSD diverts boot I/O to the serial console, so until the FreeBSD " +"operating system is completely ready, output to the QEMU window will be " +"limited." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:387 +#, no-wrap +msgid "*Adding a serial device to QEMU*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:394 +msgid "" +"Adding a serial console to QEMU is fairly straightforward. indexterm:[add a " +"serial console] indexterm:[console, serial] A single configuration line is " +"added to the QEMU configuration to provide a serial device that is actually " +"accessed over a man:telnet[1] session. indexterm:[telnet] The QEMU manual " +"page, man:qemu[1], describes how the *-serial* keyword works in detail. " +"indexterm:[serial keyword]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:399 +msgid "" +"QEMU redirects the serial port I/O to a TCP port on the host system at VM " +"startup, and the QEMU monitor allows a man:telnet[1] connection on the " +"configured port on the host. indexterm:[QEMU] indexterm:[QEMU, monitor] " +"indexterm:[telnet] Once the FreeBSD system starts booting and recognizes the " +"console directive in [.filename]#/boot/loader.conf# it redirects I/O to the " +"serial console. The QEMU monitor detects this and manages the necessary " +"character I/O on that serial port to the TCP port on the host." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:404 +msgid "" +"It is important to note that the this serial redirect over TCP takes place " +"outside the virtual machine. There is no interaction with any network on " +"the virtual machine and thus it is not subject to any firewall rules. Think " +"of it just like a \"dumb terminal\" sitting on an RS-232 serial port on a " +"real machine. indexterm:[\"dumb terminal\"]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:406 +#, no-wrap +msgid "*Management of serial console windows on the FreeBSD host*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:409 +msgid "" +"Each QEMU VM generates a console window, and each serial device also needs " +"its own window, potentially doubling the number of windows used. indexterm:" +"[serial devices]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:411 +msgid "Possible solutions are:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:413 +msgid "Separate windows for each QEMU VM (doubles the number of windows)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:414 +msgid "Use tabbed windows (available on XFCE and some other desktops)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:416 +msgid "" +"Use a terminal multiplexer such as man:tmux[1] or man:screen[1] indexterm:" +"[tmux] indexterm:[screen]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:421 +msgid "" +"The selected solution uses the multiplexer approach with the man:tmux[1] " +"program for window management. crossref:ipfw-appendix-d[appendix-d,Appendix " +"D] provides details on using both man:tmux[1] and man:screen[1]. indexterm:" +"[tmux] indexterm:[screen] The following figures and descriptions use man:" +"tmux[1]." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:424 +msgid "Install *tmux* on the FreeBSD host with: indexterm:[tmux]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:428 +#, no-wrap +msgid "# *pkg install tmux*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:432 +msgid "" +"and review the file *swim.sh* in the SCRIPTS directory. indexterm:[swim.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:436 +msgid "" +"The figure below shows the use of the *swim.sh* tmux session manager. Run " +"*sh swim.sh* in the SCRIPTS directory to start up the session manager. " +"indexterm:[session]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:438 +#, no-wrap +msgid "Starting Up tmux(1) Session Manager" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:439 +#, no-wrap +msgid "Starting Up tmux(1) Session Manager. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:439 +#, no-wrap +msgid "ipfw-introduction020.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:443 +msgid "" +"The figure shows five named windows in one session (session [0]) with the " +"*tmux* status line in green at the bottom: indexterm:[session]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:445 +#, no-wrap +msgid "*0:bash* - a terminal window of the user running *swim.sh*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:446 +#, no-wrap +msgid "*1:firewall* - a terminal window to access the *firewall* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:447 +#, no-wrap +msgid "*2:external1* - a terminal window to access the *external1* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:448 +#, no-wrap +msgid "*3:external2* - a terminal window to access the *external2* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:449 +#, no-wrap +msgid "*4:external3* - a terminal window to access the *external3* VM\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:452 +msgid "" +"The current window is marked with the '***' character on the status bar. " +"indexterm:[status bar]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:456 +msgid "Uncomment additional window lines in *swim.sh* as needed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:458 +msgid "indexterm:[swim.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:460 +#, no-wrap +msgid "*Simplified tmux(1) Usage*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:466 +#, no-wrap +msgid "" +"*tmux* uses kbd:[Ctl]+kbd:[b] as its control key.\n" +"indexterm:[control key]\n" +"To move from window to window use kbd:[Ctl]+kbd:[b] kbd:[n] to move to the next window or kbd:[Ctl]+kbd:[b] kbd:[p] to move to the previous window.\n" +"Use kbd:[Ctl]+kbd:[b] kbd:[?] for a list of all key bindings.\n" +"indexterm:[binding, key]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:469 +msgid "" +"Type *tmux kill-server* in any session window to completely leave *tmux*. " +"indexterm:[tmux]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:471 +msgid "Consult the *tmux* manual page man:tmux[1] for more usage details." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:473 +#, no-wrap +msgid "*Accessing the QEMU Serial Consoles*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:476 +msgid "" +"To access the VM serial consoles, move to the indicated window and telnet to " +"the port on the local host for that VM: indexterm:[console, serial]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:480 +#, no-wrap +msgid "Move to the *external1* window in *tmux*, then\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:485 +#, no-wrap +msgid "" +"~/ipfw/SCRIPTS % telnet localhost 4410\n" +"Trying ::1...\n" +"Connected to localhost.\n" +"Escape character is '^]'.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:487 +#, no-wrap +msgid "FreeBSD/amd64 (external1) (ttyu0)\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:489 +#, no-wrap +msgid "login:\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:491 +msgid "indexterm:[telnet]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:495 +msgid "" +"Exit out of the *telnet* session by pressing kbd:[Ctl]+kbd:[\\]] then " +"pressing kbd:[q] like this:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:500 +#, no-wrap +msgid "" +" login: (type Ctl+])\n" +" telnet> q\n" +" Connection closed.\n" +" ~/ipfw/SCRIPTS %\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:504 +msgid "Edits for the *firewall* VM to use the serial console are shown below:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:509 +#, no-wrap +msgid "" +"\\#!/bin/sh\n" +"## firewall.sh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:514 +#, no-wrap +msgid "" +"#echo#\n" +"#echo \"NOTE!!! QEMU telnet server running!\"#\n" +"#echo \"To access QEMU, telnet to localhost 4450\"#\n" +"#echo#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:529 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" #-serial telnet:localhost:4450,server=on,wait=off \\#\n" +" -cpu qemu64 \\\n" +" -vga std \\\n" +" -m 4096 \\\n" +" -smp 4 \\\n" +" -cdrom ../ISO/fbsd.iso \\\n" +" -boot order=cd,menu=on \\\n" +" -blockdev driver=file,aio=threads,node-name=imgright,filename=../VM/firewall.qcow2 \\\n" +" -blockdev driver=qcow2,node-name=drive0,file=imgright \\\n" +" -device virtio-blk-pci,drive=drive0,bootindex=1 \\\n" +" -netdev tap,id=nd0,ifname=tap0,script=no,downscript=no,br=bridge0 \\\n" +" -device e1000,netdev=nd0,mac=02:69:70:66:77:00 \\\n" +" -name \\\"Firewall\\\" #&#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:534 +msgid "indexterm:[telnet] indexterm:[QEMU]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:536 +msgid "Edits for the *external1* VM to use the serial console:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:542 +#, no-wrap +msgid "" +"-------\n" +"\\#!/bin/sh\n" +"## external1.sh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:547 +#, no-wrap +msgid "" +"#echo#\n" +"#echo \"NOTE!!! QEMU telnet server running!\"#\n" +"#echo \"To access QEMU, telnet to localhost 4410\"#\n" +"#echo#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:562 +#, no-wrap +msgid "" +"/usr/local/bin/qemu-system-x86_64 -monitor none \\\n" +" #-serial telnet:localhost:4410,server=on,wait=off \\#\n" +" -cpu qemu64 \\\n" +" -vga std \\\n" +" -m 4096 \\\n" +" -smp 4 \\\n" +" -cdrom ../ISO/fbsd.iso \\\n" +" -boot order=cd,menu=on \\\n" +" -blockdev driver=file,aio=threads,node-name=imgleft,filename=../VM/external1.qcow2 \\\n" +" -blockdev driver=qcow2,node-name=drive0,file=imgleft \\\n" +" -device virtio-blk-pci,drive=drive0,bootindex=1 \\\n" +" -netdev tap,id=nd0,ifname=tap1,script=no,downscript=no,br=bridge0 \\\n" +" -device e1000,netdev=nd0,mac=02:20:65:78:74:31 \\\n" +" -name \\\"External1\\\" #&#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:569 +msgid "" +"There should now be two QEMU VMs (*firewall* and *external1*) started, with " +"serial console sessions available through the *tmux* sessions as shown " +"below. indexterm:[tmux]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:573 +msgid "" +"Configure the FreeBSD *host*, *firewall* VM, and *external1* VM with DHCP " +"addressing as shown in the figure at the beginning on this Quick Start " +"session. indexterm:[Quick Start] There should be full connectivity between " +"the FreeBSD *host*, the *firewall* VM and the *external1* VM." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:575 +#, no-wrap +msgid "External1 and Firewall VMs Startup with Serial Console" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:576 +#, no-wrap +msgid "Firewall and External1 VMs Startup with Serial Console. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:576 +#, no-wrap +msgid "ipfw-introduction025.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-introduction/_index.adoc:579 +msgid "Scripts used by the two QEMU VMs are discussed in the next section." +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc @@ -0,0 +1,831 @@ +--- +title: Chapter 6. IPv6 Network Address Translation (IPv6NAT) +prev: books/ipfw-primer/ipfw-nat +next: books/ipfw-primer/ipfw-other-keywords +description: IPFW IPv6 NAT +tags: ["IPFW", "firewall", "IPv6", "NAT"] +showBookMenu: true +weight: 70 +path: "/books/ipfw-primer/ipfw-ipv6-nat/" +--- + +[[ipv6-nat]] += IPv6 Network Address Translation (IPv6NAT) +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 6 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +*ipfw* supports both stateful and stateless IPv6 / IPv4 translation. +indexterm:[ipv6] + +From the ipfw(8) man page: + +[subs=+quotes] +---- + *Stateful translation* + *ipfw* supports in-kernel IPv6/IPv4 network address and protocol transla- + tion. Stateful NAT64 translation allows IPv6-only clients to contact + IPv4 servers using unicast TCP, UDP or ICMP protocols. One or more IPv4 + addresses assigned to a stateful NAT64 translator are shared among sev- + eral IPv6-only clients. When stateful NAT64 is used in conjunction with + DNS64, no changes are usually required in the IPv6 client or the IPv4 + server. The kernel module *ipfw_nat64* should be loaded or kernel should + have options `IPFIREWALL_NAT64` to be able use stateful NAT64 translator. +---- + +*Stateful* translation is suitable for deployment at the client side or at the service provider, allowing IPv6-only client hosts to reach remote IPv4-only nodes. +indexterm:[stateful translation] + +*Stateless* translation is appropriate when a NAT64 translator is used in front of IPv4-only servers to allow them to be reached by remote IPv6-only clients. +indexterm:[stateless translation] + +Specific requirements for these translation services are found in a collection of RFCs: + +* Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers - link:https://datatracker.ietf.org/doc/html/rfc6146[RFC 6146] +indexterm:[NAT64] indexterm:[RFC, 6146] + +* IPv6 Addressing of IPv4/IPv6 Translators - link:https://datatracker.ietf.org/doc/html/rfc6052[RFC 6052] +indexterm:[RFC, 6052] + +* IPv6 Address Prefix Reserved for Documentation - link:https://www.rfc-editor.org/rfc/rfc3849.html[RFC 3849] +indexterm:[RFC, 3849] + +There are a couple of bugs registered for NAT64. +See the following: +NAT64 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=255928 (NAT64 issue on 13.0) + + +The lab examples for all IPv6 / IPv4 translations will use two new virtual machines: + +* *dnshost* - this virtual machine runs a configured copy of BIND 9. +indexterm:[bind9] +Some experience with DNS setup with BIND 9 is helpful but not required. +* *v6only* - this virtual machine only uses IPv6. +It is not configured for IPv4 addressing at all. + +Readers should have a basic understanding of IPv6 and its addressing characteristics. +These resources may be helpful: + +* https://en.wikipedia.org/wiki/IPv6_transition_mechanism +* https://en.wikipedia.org/wiki/IPv6_address + +indexterm:[NAT64] indexterm:[NAT64LSN] indexterm:[DNS64] + +== Stateful NAT64 (NAT64LSN) With DNS64 + +NAT64, described in RFC 6146 is one of a number of transition mechanisms that companies can take as they introduce IPv6 into their environment, or move wholesale into IPv6 locally. +indexterm:[RFC, 6146] +The idea with NAT64 is to provide a mechanism to allow an IPv6-only host to make a connection to a remote IPv4-only host. +This includes the ability to do a DNS lookup on the remote host, and through the features of DNS64 (a companion transition service described in RFC 6147), translate a received IPv4 address into a special IPv6 address that provides a way to connect using the Network Address Translation variant called NAT64. + +A logical view of NAT64 and DNS64 is shown in the figure below: + +[[ipfw-nat64-dns64-logical-view]] +.Logical View of NAT64 and DNS64 +image::ipfw-nat085.png["Logical View of NAT64 and DNS64. Refer to paragraphs below."] + +The process works like this: + +. An IPv6 only host wants to access a resource from host *external1.example.com* which only uses IPv4. +A DNS lookup for "external1.example.com" is sent to the locally configured DNS64 server. +This lookup is for an "AAAA" record for the external1 VM. +. The DNS64 server forwards the request to an authoritative server for "example.com". +indexterm:[DNS64] +. The authoritative server returns an IPv4 address back to the DNS64 server. +. The DNS64 server converts the IPv4 address into an IPv6 address using the transition service described in RFC 6147. +. The IPv6 only host, receives the IPv6 address and sends a connection request (SYN) to its local IPV6 router running NAT64. +indexterm:[flags, SYN] +. The NAT64 router converts the IPv6 packet back to IPv4 and forwards the packet to external1.example.com. + +The remaining conversions between the IPv6 VM and external1 VM happen in a similar fashion. + +In step 4, the DNS64 server converts the IPv4 address into IPv6 by using the "Well Known Prefix" `64:ff9b::` and encapsulating the IPv6 address into the last 4 octets of the address. +indexterm:["Well Known Prefix"] indexterm:["64:ff9b::"] +In the figure above, "203.0.113.10" has been converted to "cb00:710a" and added as the last four octets of the new address. + +Note that this is one instance of a larger selection of translation algorithms to translate an IPv4 address into an IPv6 address. +In this implementation, the DNS64 server and the authoritative server are essentially merged together following the description of "Example of 'an IPv6 Network to the IPv4 Internet' Setup with DNS64 in Stub-Resolver Mode" in Section 7.2 of RFC 6147. +indexterm:[RFC, 6147] + +=== Setting Up for NAT64 / DNS64 + +To exercise the NAT64 capabilities of *ipfw*, it is first necessary to restart all lab virtual machines and reconfigure the *ipfw* lab. + +The figure below shows the new configuration needed. + +[[ipfw-nat64-dns64-physical-view]] +.Network Setup for NAT64 and DNS64 Examples +image::ipfw-nat080.png["Network Setup for NAT64 and DNS64 Examples. Refer to paragraphs below."] + +On the FreeBSD host system, the appropriate bridge and tap setup is given by this command: + +[subs=+quotes] +---- +$ *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap7 bridge1 tap4 tap6 tap8* +---- + +Start up the required virtual machines with: + +[subs=+quotes] +---- +$ */bin/sh runvm.sh firewall dnshost external1 v6only* +---- + +As before, configure all interfaces and ensure connectivity of adjacent interfaces. +The *firewall* VM should be set for both IPv4 forwarding and IPv6 forwarding: + +[subs=+quotes] +---- +# sysctl net.inet.ip.forwarding=1 +# sysctl net.inet6.ip6.forwarding=1 +---- + +The *external1* VM default route should point to 203.0.113.50 and the v6only host default IPv6 route should point to 2001:db8:12::50 as follows: + +On external1: + +[subs=+quotes] +---- +# *route add default 203.0.113.50* +---- + +On v6only: + +[subs=+quotes] +---- +# *route -6 add default 2001:db8:12::50* +---- + +[NOTE] +==== +RFC 5737 describes the use of the 203.0.113.0/24 network for documentation and example purposes. +RFC 3849 describes the use of the 2001:db8::/32 network for the same purposes. +==== + +indexterm:[RFC, 5737] indexterm:[RFC, 3849] + +=== Setting Up the dnshost VM + +First, set up the *dnshost* VM to provide DNS64 services. +indexterm:[DNS64] +ISC's bind9 (9.18 and above) provides this capability. +indexterm:[bind9] +Setting up bind9, while not trivial, is not impossible. +Install the following packages: + +* *bind9* Use the latest supported version. +The server running here is using bind 9.20.5 +* *bind-tools* Same note as above. +The tools used here are bind-tools-9.20.5 + +These packages will install a modest number of dependencies. + +Included with the VM_SCRIPTS, copy the `.tgz` file [.filename]#~/ipfw-primer/ipfw/VM_SCRIPTS/dnshost/dnshost_usrlocaletc_namedb.tgz# for the bind9 configuration files needed. +Use the following commands to retrieve and untar the files: + +[subs=+quotes] +---- +# *scp user@host:~/ipfw-primer/ipfw/VM_SCRIPTS/dnshost/dnshost_usrlocaletc_namedb.tgz .* +# *tar xvzf dnshost_userlocaletc_namedb.tgz -C /usr/local/etc* +---- + +This will install all the needed DNS files. +Otherwise see the zone files in crossref:ipfw-appendix-e[appendix-e,Appendix E], and try to set up DNS. +Note that the files include a stub root zone. +This provides a locally complete DNS setup. + +Start the *named* service with: + +[subs=+quotes] +---- +# *service named onestart* +---- + +There should not be any errors, but if there are, track down and fix. + +Test the dnshost configuration with these commands. +The first lookup returns the A resource record with an IPv4 address. +The second lookup returns the AAAA resource record with the DNS64 configured "Well-known Prefix" 64:ff9b that is used in this section. +indexterm:[DNS64] + +indexterm:["64:ff9b::"] + +[subs=+quotes] +---- +root@dnshost:~ # *#dig @localhost external1.example.com#* + +; <<>> DiG 9.16.27 <<>> @localhost external1.example.com +; (2 servers found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61764 +;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 +;; WARNING: recursion requested but not available + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 1232 +; COOKIE: 96f573e1a62ce4380100000062884cacf9b86d6e9f54b542 (good) +;; QUESTION SECTION: +;external1.example.com. IN A + +;; ANSWER SECTION: +#external1.example.com. 3600 IN A 203.0.113.10# + +;; Query time: 58 msec +;; SERVER: ::1#53(::1) +;; WHEN: Fri May 20 22:21:32 EDT 2022 +;; MSG SIZE rcvd: 94 +# +# +root@dnshost:~ # *#dig @localhost external1.example.com aaaa#* + +; <<>> DiG 9.16.27 <<>> @localhost external1.example.com aaaa +; (2 servers found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5865 +;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 +;; WARNING: recursion requested but not available + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 1232 +; COOKIE: 0ad6c60faab12f7f0100000062884cb0be6e6bd00f7e482f (good) +;; QUESTION SECTION: +;external1.example.com. IN AAAA + +;; ANSWER SECTION: +#external1.example.com. 3600 IN AAAA 64:ff9b::cb00:710a# +# +---- + +The last test is the most important. +The dnshost must return the Well-Known Prefix "64:ff9b::" with the corresponding bits for the embedded IPv4 address. +indexterm:["Well Known Prefix"] +If the test does not return this value, reconfigure the DNS service (named.conf and the primary forward zone "example.com") to fix. + +Since the *v6only* machine will only ever request AAAA lookups, the configuration is complete for this section. +Ensure that the [.filename]#/etc/resolv.conf# file on the *v6only* VM is correctly configured: + +[subs=+quotes] +---- +root@v6only: # *cat /etc/resolv.conf* +nameserver 2001:db8:12::53 + +root@v6only: # +---- + +Next to set up are the *firewall*, the IPV6 only host *v6only*, and the external VM host, *external1*. +Test connectivity without any *ipfw* running on the *firewall* host. +Refer to the above diagram for network addressing. + +Finally, proceed with the installation of NAT64 on the *ipfw firewall*. + +On the firewall VM: + +[subs=+quotes] +---- +# *kldload ipfw* + +The next line loads the NAT64 module. + +# *kldload ipfw_nat64* +---- + +indexterm:[module, ipfw] indexterm:[NAT64] indexterm:[module, ipfw_nat64] + +Configuring NAT64 is similar to configuring NAT. +Create an instance of the NAT64 translator first. + +[subs=+quotes] +---- +# *ipfw nat64lsn foo create prefix4 203.0.112.0/24 allow_private* +---- + +indexterm:[nat64lsn] + +The use of the "*allow_private*" keyword is required. +indexterm:[allow_private] +The man:ipfw[8] manual page notes that the NAT64 translator, by default, will not handle addresses whose destination matches those listed in RFC 1918. +indexterm:[RFC, 1918] +The addressing scheme in this lab uses special purpose addresses as noted in RFC 6890 which are *_also_* considered "private addresses" by the ipfw NAT64 translator. +indexterm:[RFC, 6890] + +Note that the prefix4 address pool (*203.0.112.0/24* above) should not be manually configured as an alias on any interface. +These addresses are used internally by *ipfw*. +The only requirement is that they be reserved from deployment elsewhere in the local network so they do not cause a routing conflict with *ipfw*. +This allows for 254 simultaneous NAT64 addresses. +If more are needed due to high volume, add another prefix4, or increase the existing prefix4 address space. + +Continue configuring the NAT64 / DNS64 translator: +indexterm:[NAT64] indexterm:[DNS64] + +[subs=+quotes] +---- +# *ipfw add allow log ipv6-icmp from any to any icmp6types 135,136* +# *ipfw add nat64lsn foo log ip from 2001:db8:12::/64 to 64:ff9b::/96 in* +# *ipfw add nat64lsn foo log ip from any to 203.0.112.0/24 in* +# *ipfw add allow log ip from any to any* +---- + +indexterm:[icmptypes] + +and the direct_output sysctl must be set to 1 (not zero): + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.nat64_direct_output=1* +---- + +indexterm:[sysctl, net.inet.ip.fw.nat64_direct_output] + +If desired, also set the nat64_debug sysctl and the firewall verbose sysctl: + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.nat64_debug=1* +# *sysctl net.inet.ip.fw.verbose=1* +---- + +indexterm:[sysctl, net.inet.ip.fw.nat64_debug] +indexterm:[sysctl, net.inet.ip.fw.verbose] + +Use *tail -f /var/log/security* to view the `nat64lsn` translations. + +With these prerequisites completed the following tests on the *v6only* VM should be successful: + +[subs=+quotes] +---- +root@v6only# *ping6 -c 3 64:ff9b::203.0.113.10* +PING6(56=40+8+8 bytes) 2001:db8:12::30 --> 64:ff9b::cb00:710a +16 bytes from 64:ff9b::cb00:710a, icmp_seq=0 hlim=63 time=8.401 ms +16 bytes from 64:ff9b::cb00:710a, icmp_seq=1 hlim=63 time=3.429 ms +16 bytes from 64:ff9b::cb00:710a, icmp_seq=2 hlim=63 time=3.398 ms + +--- 64:ff9b::203.0.113.10 ping6 statistics --- +3 packets transmitted, 3 packets received, 0.0% packet loss +round-trip min/avg/max/std-dev = 3.398/5.076/8.401/2.351 ms +---- + +indexterm:[ping6] indexterm:["64:ff9b::"] + +and using lynx to grab the *external1.example.com* home page should be successful: + +[subs=+quotes] +---- +[root@v6only ~]# *lynx external1.example.com* +---- + +indexterm:[lynx] + +[[ipfw-nat64-viewing-external1-webpage]] +.Viewing the IPv4 Webpage of *external1* VM from IPv6 *v6only* VM. +image::ipfw-ipv6nat110.png["Viewing the IPv4 Webpage of *external1* VM from IPv6 *v6only* VM. Refer to paragraphs below."] + +=== Setting Up for Stateless NAT64 - NAT64STL + +indexterm:[NAT64] indexterm:[NAT64STL] + +The previous *ipfw_nat64* examples used "stateful" address translation. +*ipfw* is also capable of performing "stateless" address translation. + +Stateless translation is appropriate when a NAT64 translator is used in front of IPv4-only servers to allow them to be reached by remote IPv6-only clients. +Stateful translation is suitable for deployment at the client side or at the service provider, allowing IPv6-only client hosts to reach remote IPv4-only nodes. + +Stateless configuration of NAT64 is possible with the same architecture as the previous stateful example. +Configuration details however, are different. +In the stateless case, *ipfw* uses two tables for translating addresses in either direction: *IPv4 -> IPv6* and *IPv6 -> IPv4*. +A typical configuration is shown below. + +[subs=+quotes] +---- +Start fresh + +# *kldunload ipfw_nat64* + +# *kldunload ipfw* + +# *kldload ipfw* + +# *kldload ipfw_nat64* + +Create the tables used for ipfw_nat64stl + +# *ipfw table T4to6 create type addr valtype ipv6* + +# *ipfw table T6to4 create type addr valtype ipv4* + +# *ipfw table T4to6 add 203.0.112.1 2001:db8:12::6* + +# *ipfw table T6to4 add 2001:db8:12::6 203.0.112.1* + +# *ipfw nat64stl NAT64 create table4 T4to6 table6 T6to4 allow_private* + +Add rules for ipfw_nat64stl + +# *ipfw add allow log icmp6 from any to any icmp6types 135, 136* + +# *ipfw add nat64stl NAT64 log ip from any to 'table(T4to6)'* + +# *ipfw add nat64stl NAT64 log ip6 from 'table(T6to4)' to 64:ff9b::/96* + +# *ipfw add allow log ip from any to any* + +Adjust sysctls + +# *sysctl net.inet.ip.fw.verbose=1* + +# *sysctl net.inet.ip.fw.nat64_debug=1* + +# *sysctl net.inet.ip.fw.nat64_direct_output=1* +---- + +indexterm:[module, ipfw] indexterm:[module, ipfw_nat64] indexterm:[ipfw_nat64stl] indexterm:[allow_private] indexterm:["64:ff9b::"] +indexterm:[sysctl, net.inet.ip.fw.verbose] indexterm:[sysctl, net.inet.ip.fw.nat64_debug] indexterm:[sysctl, net.inet.ip.fw.nat64_direct_output] + +Only the *net.inet.ip.fw.nat64_direct_output* sysctl is required. + +Use the same tests as in the stateful NAT64 example: + +[subs=+quotes] +---- +[root@v6only ~]# *ping6 -c 3 64:ff9b::203.0.113.10* + +and + +[root@v6only ~]# *lynx external1.example.com* +---- + +indexterm:[ping6] indexterm:[lynx] indexterm:["64:ff9b::"] + +Both tests should be successful. + +It may seem limiting to have to use tables to effect communication for stateless NAT64. +However, in considering the architecture involved, the above statements about stateless translation being appropriate when a NAT64 translator is used in front of IPv4-only servers to allow them to be reached by remote IPv6-only clients makes sense. +The entire IPv6 cloud can reach a specified server. + +This can be accomplished by, for example, changing the T4to6 and T6to4 tables to read: + +[subs=+quotes] +---- +# *ipfw table T4to6 add 203.0.112.0/31 2001:db8:12::30* + +# *ipfw table T6to4 add 2000:0000:0000::/8 203.0.112.0* + +# *ipfw table T6to4 add 2100:0000:0000::/8 203.0.112.1* +---- + +The T4to6 table allocates two addresses in the address pool: 203.0.112.0 and 203.0.112.1. +These are used separately in the T6to4 table to cover vast ranges of IPv6 address space. + +Certainly using just one IPv4 pool address is not going to be sufficient to translate such a large range of IPv6 addresses. +The point here is that by carefully constructing the translation pool addresses and the T4to6 and T6to4 address tables, *ipfw* can manage translation to as many IPv6 addresses as needed. + +Note that stateless NAT64 shares the same limitations of stateful NAT64. +indexterm:[NAT64] + +Next is the most important IPv6 / IPv4 translation mechanism NAT64 CLAT. +indexterm:[CLAT] + +== 464XLAT + +indexterm:[XLAT464] + +*ipfw* supports 464XLAT (RFC 6877) calling it "XLAT464 CLAT". +indexterm:[RFC, 6877] indexterm:[XLAT464 CLAT] +This transition mechanism provides connectivity for IPv4 edge devices across an IPv6 only network. +It does this by combining stateful translation in the core and stateless translation at the edge. +464XLAT only supports IPv4 in the client-server model, so it does not support IPv4 peer-to-peer communication or inbound IPv4 connections. + +[NOTE] +==== +See diagrams and explanation here: +https://www.juniper.net/documentation/us/en/software/junos/interfaces-adaptive-services/topics/topic-map/ipv4-connect-ipv6-464xlat.html#id-464xlat-overview + +The RFC for this mechanism is more enlightening. +See link:https://datatracker.ietf.org/doc/html/rfc6877[RFC 6877] +==== + +indexterm:[juniper] indexterm:[RFC, 6877] + +The discussion on Wikipedia is somewhat sparse: + +[subs=+quotes] +---- +*464XLAT* + +464XLAT (RFC 6877) allows clients on IPv6-only networks to access IPv4-only Internet services, such as Skype.[13][14] +The client uses a SIIT translator to convert packets from IPv4 to IPv6. +These are then sent to a NAT64 translator which translates them from IPv6 back into IPv4 and on to an IPv4-only server. +The client translator may be implemented on the client itself or on an intermediate device and is known as the CLAT (Customer-side transLATor). +The NAT64 translator, or PLAT (Provider-side transLATor), must be able to reach both the server and the client (through the CLAT). +The use of NAT64 limits connections to a client-server model using UDP, TCP, and ICMP. +---- + +indexterm:[CLAT] indexterm:[PLAT] + +The figure below shows a diagram for implementing 464XLAT. +indexterm:[464XLAT] + +[[ipfw-nat64xlat-design]] +.*ipfw* 464XLAT Design +image::ipfw-ipv6464xlat090.png["*ipfw* 464XLAT Design. Refer to paragraphs below."] + +As earlier, shutdown all virtual machines and for this example, reset all the bridge and tap devices to the new architecture. + +This example will require two firewalls. +The *firewall* VM and *firewall2* VM will both be used as shown in the diagram. +In this example, the *firewall* VM is the CLAT translator (stateless translation) and the *firewall2* VM is the PLAT translator (stateful translation). + +To start, set up the bridge and tap interfaces with this command on the FreeBSD host: + +[subs=+quotes] +---- +$ *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap11 bridge1 tap4 tap6 tap7 tap9 \* + *bridge2 tap2 tap8 tap10* +---- + + +Start up the virtual machines with: + +[subs=+quotes] +---- +$ */bin/sh runvm.sh external1 firewall firewall2 dnshost v6only external2* +---- + +As earlier, configure all interfaces according to the diagram and ensure connectivity with adjacent interfaces. + +This example is more complex than past examples. +There are a number of additional configuration steps needed as follows: + +* *external1.example.com* + +[subs=+quotes] +---- +On external1.example.com: + +*route add default 192.168.1.1* +*echo "nameserver 192.168.1.53" > /etc/resolv.conf* +*echo "nameserver 203.0.113.53" >> /etc/resolv.conf* +---- +* *firewall.example.com* + +[subs=+quotes] +---- +On firewall.example.com: + +*/bin/sh /root/bin/bsdclat464.sh* +*echo "nameserver 2001:db8:12::53" > /etc/resolv.conf* +*echo "nameserver 192.168.1.53" >> /etc/resolv.conf* +*route -6 add 2001:db8:bbbb::/96 2001:db8:12::1* +*sysctl net.inet.ip.forwarding=1* +*sysctl net.inet6.ip6.forwarding=1* +*sysctl net.inet.ip.fw.verbose=1* +*sysctl net.inet.ip.fw.nat64_direct_output=1* +---- + +indexterm:[bsdclat464.sh] +indexterm:[sysctl, net.inet.ip.forwarding] indexterm:[sysctl, net.inet6.ip6.forwarding] indexterm:[sysctl, net.inet.ip.fw.nat64_direct_output] + +* *firewall2.example.com* + +[subs=+quotes] +---- +On firewall2.example.com + +*/bin/sh /root/bin/bsdplat464.sh* +*route -6 add 2001:db8:aaaa::/96 2001:db8:12::2* +*echo "nameserver 2001:db8:12::53" > /etc/resolv.conf* +*sysctl net.inet.ip.forwarding=1* +*sysctl net.inet6.ip6.forwarding=1* +*sysctl net.inet.ip.fw.verbose=1* +*sysctl net.inet.ip.fw.nat64_direct_output=1* +---- +* *external2.example.com* + +[subs=+quotes] +---- +On external2.example.com + +*route add default 203.0.113.1* +*echo "nameserver 203.0.113.53" > /etc/resolv.conf* +*service nginx onestart* +---- + +indexterm:[nginx] + +* *dnshost.example.com* + +The DNS64 capability is not used for this example. + +[subs=+quotes] +---- +On dnshost.example.com: + +Remove DNS64: + +*vi /usr/local/etc/namedb/named.conf* + + Comment out the dns64 clause in the _options_ section: + *. . .* + // dns64 64:FF9B::/96 { + // clients { any; }; + // exclude { 64:FF9B::/96; ::ffff:0000:0000/96; }; + // suffix ::; + // }; + *. . .* + +*echo "nameserver 127.0.0.1" > /etc/resolv.conf* +*echo "nameserver 2001:db8:12::53" >> /etc/resolv.conf* +*service named onestart* +*route add default 203.0.113.1* +*route add -net 192.168.1.0/24 192.168.1.1* +*sysctl net.inet.ip.forwarding=0* +*sysctl net.inet6.ip6.forwarding=0* +---- + +indexterm:[sysctl, net.inet.ip.forwarding] +indexterm:[sysctl, net.inet6.ip6.forwarding] + +* *v6only.example.com* + +[subs=+quotes] +---- +On v6only.example.com: + +*echo "nameserver 2001:db8:12::53" > /etc/resolv.conf* +*route -6 add 2001:db8:bbbb::/96 2001:db8:12::1* +*route -6 add 2001:db8:aaaa::/96 2001:db8:12::2* +---- + +Due to the complex nature of these *ipfw* configurations, the *bsdclat464.sh* and *bsdplat464.sh* scripts are provided. +However, do try to understand the configration details. + +Once all the above commands are entered on their respective VMs, test the configuration with a ping from the *external1* VM to the *external2* VM: + +[subs=+quotes] +---- +root@external1:# *ping -c 2 external2.example.com* +PING external2.example.com (203.0.113.20): 56 data bytes +64 bytes from 203.0.113.20: icmp_seq=0 ttl=62 time=5.578 ms +64 bytes from 203.0.113.20: icmp_seq=1 ttl=62 time=8.002 ms + +--- external2.example.com ping statistics --- +2 packets transmitted, 2 packets received, 0.0% packet loss +round-trip min/avg/max/stddev = 5.578/6.790/8.002/1.212 ms +root@external1:# +---- +indexterm:[ping] indexterm:[464XLAT] + +While the above results look unremarkable, what has actually happened is that an IPV4 host (the *external1* VM) initiated an IPV4 communication (*ping*) to the IPV4 *external2* VM. +This communication was translated into IPV6 by the edge *firewall* VM and forwarded over the IPV6 network to the *firewall2* VM which translated it back to IPv4 and forwarded it to the *external1* VM. +The IPV4 reply took a similar path, getting translated into IPV6 and routed over the IPV6 network. +The packet was finally translated back to IPv4 by the edge device, *firewall* VM. + +The snippets below show at each step, how the request was transformed. + +[NOTE] +==== +The examples below are taken from multiple different invocations of the *ping* command. +However, the data transformations are correct. +==== + +[subs=+quotes] +---- +On interface *em0* on the *firewall* VM: + +root@firewall:~/bin # tcpdump -n -i em0 +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +14:38:07.254114 IP 192.168.1.2 > 203.0.113.20: ICMP echo request, id 46395, seq 0, length 64 +14:38:07.256893 IP 203.0.113.20 > 192.168.1.2: ICMP echo reply, id 46395, seq 0, length 64 +14:38:08.322597 IP 192.168.1.2 > 203.0.113.20: ICMP echo request, id 46395, seq 1, length 64 +14:38:08.326715 IP 203.0.113.20 > 192.168.1.2: ICMP echo reply, id 46395, seq 1, length 64 + +On interface *em1* on the *firewall* VM: + +root@firewall:~/bin # tcpdump -n -i em1 +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on em1, link-type EN10MB (Ethernet), snapshot length 262144 bytes +14:54:45.140746 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 38233, seq 0, length 64 +14:54:45.142995 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 38233, seq 0, length 64 +14:54:46.171754 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 38233, seq 1, length 64 +14:54:46.173925 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 38233, seq 1, length 64 + +On interface *em0* on the *firewall2* VM: + +root@firewall2:~/bin # tcpdump -n -i em0 +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +14:57:32.519334 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 17270, seq 0, length 64 +14:57:32.529066 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 17270, seq 0, length 64 +14:57:33.560392 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 17270, seq 1, length 64 +14:57:33.561596 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 17270, seq 1, length 64 + +On interface *em1* on the *firewall2* VM: + +root@firewall2:~/bin # tcpdump -n -i em1 +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on em1, link-type EN10MB (Ethernet), snapshot length 262144 bytes +14:58:37.139612 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1025, seq 0, length 64 +14:58:37.141043 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1025, seq 0, length 64 +14:58:38.187477 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1025, seq 1, length 64 +14:58:38.188308 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1025, seq 1, length 64 + +On interface *em0* on the *external2* VM: + +root@external2:~ # tcpdump -n -i em0 +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +15:00:44.171439 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1024, seq 0, length 64 +15:00:44.172313 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1024, seq 0, length 64 +15:00:45.200883 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1024, seq 1, length 64 +15:00:45.201035 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1024, seq 1, length 64 +---- + +indexterm:[tcpdump] + +The firewall log sysctl was reset to log to man:syslogd[8] and captured these logs: + +[subs=+quotes] +---- +Logs on the *firewall* VM: + +root@firewall:~/bin # cat /var/log/security +Dec 2 15:14:04 firewall kernel: ipfw: 150 Eaction nat64clat ICMP:8.0 192.168.1.2 203.0.113.20 in via em0 +Dec 2 15:14:04 firewall kernel: ipfw: 150 Eaction nat64clat ICMPv6:129.0 [2001:db8:bbbb::cb00:7114] [2001:db8:aaaa::c0a8:102] in via em1 +Dec 2 15:14:04 firewall kernel: ipfw: 150 Eaction nat64clat ICMP:8.0 192.168.1.2 203.0.113.20 in via em0 +Dec 2 15:14:05 firewall kernel: ipfw: 150 Eaction nat64clat ICMPv6:129.0 [2001:db8:bbbb::cb00:7114] [2001:db8:aaaa::c0a8:102] in via em1 +Dec 2 15:14:08 firewall kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::1] [2001:db8:12::2] in via em1 +Dec 2 15:14:08 firewall kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::2] [2001:db8:12::1] out via em1 +Dec 2 15:14:09 firewall kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::2] [2001:db8:12::1] out via em1 +Dec 2 15:14:09 firewall kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::1] [2001:db8:12::2] in via em1 + +Logs on the *firewall2* VM: + +root@firewall2:~/bin # cat /var/log/security +Dec 2 15:10:25 firewall2 kernel: ipfw: 300 Eaction nat64lsn ICMPv6:128.0 [2001:db8:aaaa::c0a8:102] [2001:db8:bbbb::cb00:7114] in via em0 +Dec 2 15:10:25 firewall2 kernel: ipfw: 400 Eaction nat64lsn ICMP:0.0 203.0.113.20 203.0.112.22 in via em1 +Dec 2 15:10:26 firewall2 kernel: ipfw: 300 Eaction nat64lsn ICMPv6:128.0 [2001:db8:aaaa::c0a8:102] [2001:db8:bbbb::cb00:7114] in via em0 +Dec 2 15:10:26 firewall2 kernel: ipfw: 400 Eaction nat64lsn ICMP:0.0 203.0.113.20 203.0.112.22 in via em1 +Dec 2 15:10:29 firewall2 kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::1] [2001:db8:12::2] out via em0 +Dec 2 15:10:29 firewall2 kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::2] [2001:db8:12::1] in via em0 +Dec 2 15:10:30 firewall2 kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::2] [2001:db8:12::1] in via em0 +Dec 2 15:10:30 firewall2 kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::1] [2001:db8:12::2] out via em0 +---- + +indexterm:[nat64clat] +indexterm:[nat64lsn] + +Finally, a webpage request was made with: + +[subs=+quotes] +---- +# *lynx external2.example.com* +---- + +indexterm:[lynx] + +as shown below: + +[[ipfw-nat64xlat-retrieve-webpage]] +.Retrieving the Webpage at *external2.example.com* +image::ipfw-ipv6464xlat095.png["Retrieving the Webpage at external2.example.com. Refer to paragraphs below."] + +[NOTE] +==== +As noted in the Juniper documentation link above, "464XLAT only supports IPv4 in the client-server model, so it does not support IPv4 peer-to-peer communication or inbound IPv4 connections." +Other technologies provide peer-to-peer communications. +==== + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.po @@ -0,0 +1,1593 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:1 +#, no-wrap +msgid "IPFW IPv6 NAT" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:1 +#, no-wrap +msgid "Chapter 6. IPv6 Network Address Translation (IPv6NAT)" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:13 +#, no-wrap +msgid "IPv6 Network Address Translation (IPv6NAT)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:52 +#, no-wrap +msgid "" +"*ipfw* supports both stateful and stateless IPv6 / IPv4 translation.\n" +"indexterm:[ipv6]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:54 +msgid "From the ipfw(8) man page:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:66 +#, no-wrap +msgid "" +" *Stateful translation*\n" +" *ipfw* supports in-kernel IPv6/IPv4 network address and protocol transla-\n" +" tion. Stateful NAT64 translation allows IPv6-only clients to contact\n" +" IPv4 servers using unicast TCP, UDP or ICMP protocols. One or more IPv4\n" +" addresses assigned to a stateful NAT64 translator are shared among sev-\n" +" eral IPv6-only clients. When stateful NAT64 is used in conjunction with\n" +" DNS64, no changes are usually required in the IPv6 client or the IPv4\n" +" server. The kernel module *ipfw_nat64* should be loaded or kernel should\n" +" have options `IPFIREWALL_NAT64` to be able use stateful NAT64 translator.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:70 +#, no-wrap +msgid "" +"*Stateful* translation is suitable for deployment at the client side or at the service provider, allowing IPv6-only client hosts to reach remote IPv4-only nodes.\n" +"indexterm:[stateful translation]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:73 +#, no-wrap +msgid "" +"*Stateless* translation is appropriate when a NAT64 translator is used in front of IPv4-only servers to allow them to be reached by remote IPv6-only clients.\n" +"indexterm:[stateless translation]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:75 +msgid "" +"Specific requirements for these translation services are found in a " +"collection of RFCs:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:78 +msgid "" +"Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients " +"to IPv4 Servers - link:https://datatracker.ietf.org/doc/html/rfc6146[RFC " +"6146] indexterm:[NAT64] indexterm:[RFC, 6146]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:81 +msgid "" +"IPv6 Addressing of IPv4/IPv6 Translators - link:https://datatracker.ietf.org/" +"doc/html/rfc6052[RFC 6052] indexterm:[RFC, 6052]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:84 +msgid "" +"IPv6 Address Prefix Reserved for Documentation - link:https://www.rfc-editor." +"org/rfc/rfc3849.html[RFC 3849] indexterm:[RFC, 3849]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:88 +msgid "" +"There are a couple of bugs registered for NAT64. See the following: NAT64 " +"https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=255928 (NAT64 issue on " +"13.0)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:91 +msgid "" +"The lab examples for all IPv6 / IPv4 translations will use two new virtual " +"machines:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:95 +#, no-wrap +msgid "" +"*dnshost* - this virtual machine runs a configured copy of BIND 9.\n" +"indexterm:[bind9]\n" +"Some experience with DNS setup with BIND 9 is helpful but not required.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:97 +#, no-wrap +msgid "" +"*v6only* - this virtual machine only uses IPv6.\n" +"It is not configured for IPv4 addressing at all.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:100 +msgid "" +"Readers should have a basic understanding of IPv6 and its addressing " +"characteristics. These resources may be helpful:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:102 +msgid "https://en.wikipedia.org/wiki/IPv6_transition_mechanism" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:103 +msgid "https://en.wikipedia.org/wiki/IPv6_address" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:105 +msgid "indexterm:[NAT64] indexterm:[NAT64LSN] indexterm:[DNS64]" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:106 +#, no-wrap +msgid "Stateful NAT64 (NAT64LSN) With DNS64" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:112 +msgid "" +"NAT64, described in RFC 6146 is one of a number of transition mechanisms " +"that companies can take as they introduce IPv6 into their environment, or " +"move wholesale into IPv6 locally. indexterm:[RFC, 6146] The idea with NAT64 " +"is to provide a mechanism to allow an IPv6-only host to make a connection to " +"a remote IPv4-only host. This includes the ability to do a DNS lookup on " +"the remote host, and through the features of DNS64 (a companion transition " +"service described in RFC 6147), translate a received IPv4 address into a " +"special IPv6 address that provides a way to connect using the Network " +"Address Translation variant called NAT64." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:114 +msgid "A logical view of NAT64 and DNS64 is shown in the figure below:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:116 +#, no-wrap +msgid "Logical View of NAT64 and DNS64" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:117 +#, no-wrap +msgid "Logical View of NAT64 and DNS64. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:117 +#, no-wrap +msgid "ipfw-nat085.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:120 +msgid "The process works like this:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:124 +msgid "" +"An IPv6 only host wants to access a resource from host *external1.example." +"com* which only uses IPv4. A DNS lookup for \"external1.example.com\" is " +"sent to the locally configured DNS64 server. This lookup is for an \"AAAA\" " +"record for the external1 VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:126 +msgid "" +"The DNS64 server forwards the request to an authoritative server for " +"\"example.com\". indexterm:[DNS64]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:127 +msgid "" +"The authoritative server returns an IPv4 address back to the DNS64 server." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:128 +msgid "" +"The DNS64 server converts the IPv4 address into an IPv6 address using the " +"transition service described in RFC 6147." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:130 +msgid "" +"The IPv6 only host, receives the IPv6 address and sends a connection request " +"(SYN) to its local IPV6 router running NAT64. indexterm:[flags, SYN]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:131 +msgid "" +"The NAT64 router converts the IPv6 packet back to IPv4 and forwards the " +"packet to external1.example.com." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:133 +msgid "" +"The remaining conversions between the IPv6 VM and external1 VM happen in a " +"similar fashion." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:137 +msgid "" +"In step 4, the DNS64 server converts the IPv4 address into IPv6 by using the " +"\"Well Known Prefix\" `64:ff9b::` and encapsulating the IPv6 address into " +"the last 4 octets of the address. indexterm:[\"Well Known Prefix\"] " +"indexterm:[\"64:ff9b::\"] In the figure above, \"203.0.113.10\" has been " +"converted to \"cb00:710a\" and added as the last four octets of the new " +"address." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:141 +msgid "" +"Note that this is one instance of a larger selection of translation " +"algorithms to translate an IPv4 address into an IPv6 address. In this " +"implementation, the DNS64 server and the authoritative server are " +"essentially merged together following the description of \"Example of 'an " +"IPv6 Network to the IPv4 Internet' Setup with DNS64 in Stub-Resolver Mode\" " +"in Section 7.2 of RFC 6147. indexterm:[RFC, 6147]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:142 +#, no-wrap +msgid "Setting Up for NAT64 / DNS64" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:145 +msgid "" +"To exercise the NAT64 capabilities of *ipfw*, it is first necessary to " +"restart all lab virtual machines and reconfigure the *ipfw* lab." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:147 +msgid "The figure below shows the new configuration needed." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:149 +#, no-wrap +msgid "Network Setup for NAT64 and DNS64 Examples" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:150 +#, no-wrap +msgid "Network Setup for NAT64 and DNS64 Examples. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:150 +#, no-wrap +msgid "ipfw-nat080.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:153 +msgid "" +"On the FreeBSD host system, the appropriate bridge and tap setup is given by " +"this command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:157 +#, no-wrap +msgid "$ *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap7 bridge1 tap4 tap6 tap8*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:160 +msgid "Start up the required virtual machines with:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:164 +#, no-wrap +msgid "$ */bin/sh runvm.sh firewall dnshost external1 v6only*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:168 +msgid "" +"As before, configure all interfaces and ensure connectivity of adjacent " +"interfaces. The *firewall* VM should be set for both IPv4 forwarding and " +"IPv6 forwarding:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:173 +#, no-wrap +msgid "" +"# sysctl net.inet.ip.forwarding=1\n" +"# sysctl net.inet6.ip6.forwarding=1\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:176 +msgid "" +"The *external1* VM's default route should point to 203.0.113.1 and the " +"v6only host's default IPv6 route should point to 2001:db8:12::1 as follows:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:178 +msgid "On external1:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:182 +#, no-wrap +msgid "# *route add default 203.0.113.50*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:185 +msgid "On v6only:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:189 +#, no-wrap +msgid "# *route -6 add default 2001:db8:12::50*\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:195 +msgid "" +"RFC 5737 describes the use of the 203.0.113.0/24 network for documentation " +"and example purposes. RFC 3849 describes the use of the 2001:db8::/32 " +"network the same purposes." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:198 +msgid "indexterm:[RFC, 5737] indexterm:[RFC, 3849]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:199 +#, no-wrap +msgid "Setting Up the dnshost VM" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:207 +msgid "" +"First, set up the *dnshost* VM to provide DNS64 services. indexterm:[DNS64] " +"ISC's bind9 (9.18 and above) provides this capability. indexterm:[bind9] " +"Setting up bind9, while not trivial, is not impossible. Install the " +"following packages:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:210 +#, no-wrap +msgid "" +"*bind9* Use the latest supported version.\n" +"The server running here is using bind 9.18.1\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:212 +#, no-wrap +msgid "" +"*bind-tools* Same note as above.\n" +"The server here uses bind-tools-9.16.27\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:214 +msgid "These packages will install a modest number of dependencies." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:217 +msgid "" +"Included with the practice kit, see the tar file [.filename]#dnshost.tar# " +"for the bind9 configuration files needed. Use the following command to " +"untar the files:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:221 +#, no-wrap +msgid "# *tar xvzf dhshost_userlocaletc_namedb.tgz -C /usr/local/etc*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:227 +msgid "" +"This will install all the needed DNS files. Otherwise see the zone files in " +"crossref:ipfw-appendix-e:[appendix-e,Appendix E], and try to set up DNS. " +"Note that the files include a stub root zone. This provides a locally " +"complete DNS setup." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:229 +msgid "Restart the named service with:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:233 +#, no-wrap +msgid "# *service named restart*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:236 +msgid "There should not be any errors, but if there are, track down and fix." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:241 +msgid "" +"Test the dnshost configuration with these commands. The first lookup " +"returns the A resource record with an IPv4 address. The second lookup " +"returns the AAAA resource record with the DNS64 configured \"Well-known " +"Prefix\" 64:ff9b that is used in this section. indexterm:[DNS64]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:243 +msgid "indexterm:[\"64:ff9b::\"]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:247 +#, no-wrap +msgid "root@dnshost:~ # *#dig @localhost external1.example.com#*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:255 +#, no-wrap +msgid "" +"; <<>> DiG 9.16.27 <<>> @localhost external1.example.com\n" +"; (2 servers found)\n" +";; global options: +cmd\n" +";; Got answer:\n" +";; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61764\n" +";; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1\n" +";; WARNING: recursion requested but not available\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:261 +#, no-wrap +msgid "" +";; OPT PSEUDOSECTION:\n" +"; EDNS: version: 0, flags:; udp: 1232\n" +"; COOKIE: 96f573e1a62ce4380100000062884cacf9b86d6e9f54b542 (good)\n" +";; QUESTION SECTION:\n" +";external1.example.com. IN A\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:264 +#, no-wrap +msgid "" +";; ANSWER SECTION:\n" +"#external1.example.com. 3600 IN A 203.0.113.10#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:272 +#, no-wrap +msgid "" +";; Query time: 58 msec\n" +";; SERVER: ::1#53(::1)\n" +";; WHEN: Fri May 20 22:21:32 EDT 2022\n" +";; MSG SIZE rcvd: 94\n" +"#\n" +"#\n" +"root@dnshost:~ # *#dig @localhost external1.example.com aaaa#*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:280 +#, no-wrap +msgid "" +"; <<>> DiG 9.16.27 <<>> @localhost external1.example.com aaaa\n" +"; (2 servers found)\n" +";; global options: +cmd\n" +";; Got answer:\n" +";; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5865\n" +";; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1\n" +";; WARNING: recursion requested but not available\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:286 +#, no-wrap +msgid "" +";; OPT PSEUDOSECTION:\n" +"; EDNS: version: 0, flags:; udp: 1232\n" +"; COOKIE: 0ad6c60faab12f7f0100000062884cb0be6e6bd00f7e482f (good)\n" +";; QUESTION SECTION:\n" +";external1.example.com. IN AAAA\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:290 +#, no-wrap +msgid "" +";; ANSWER SECTION:\n" +"#external1.example.com. 3600 IN AAAA 64:ff9b::cb00:710a#\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:296 +msgid "" +"The last test is the most important. The dnshost must return the Well-Known " +"Prefix \"64:ff9b::\" with the corresponding bits for the embedded IPv4 " +"address. indexterm:[\"Well Known Prefix\"] If the test does not return this " +"value, reconfigure the DNS service (named.conf and the primary forward zone " +"\"example.com\") to fix." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:298 +msgid "" +"Since the *v6only* machine will only ever request AAAA lookups, the " +"configuration is complete for this section." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:301 +msgid "" +"Next to set up are the *firewall*, the IPV6 only host *v6only*, and the " +"external VM host, *external1*. Boot all three VMs and test connectivity " +"without any *ipfw* running on the *firewall* host." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:303 +msgid "Proceed with the installation of NAT64 on the *ipfw firewall*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:305 +msgid "On the firewall VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:309 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:429 +#, no-wrap +msgid "# *kldload ipfw*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:311 +#, no-wrap +msgid "The next line loads the NAT64 module.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:313 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:431 +#, no-wrap +msgid "# *kldload ipfw_nat64*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:316 +msgid "" +"indexterm:[module, ipfw] indexterm:[NAT64] indexterm:[module, ipfw_nat64]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:319 +msgid "" +"Configuring NAT64 is similar to configuring NAT. Create an instance of the " +"NAT64 translator first." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:323 +#, no-wrap +msgid "# *ipfw nat64lsn foo create prefix4 203.0.112.0/24 allow_private*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:326 +msgid "indexterm:[nat64lsn]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:333 +msgid "" +"The use of the \"*allow_private*\" keyword is required. indexterm:" +"[allow_private] The man:ipfw[8] manual page notes that the NAT64 translator, " +"by default, will not handle addresses whose destination matches those listed " +"in RFC 1918. indexterm:[RFC, 1918] The addressing scheme in this lab uses " +"special purpose addresses as noted in RFC 6890 which are *_also_* considered " +"\"private addresses\" by the ipfw NAT64 translator. indexterm:[RFC, 6890]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:339 +msgid "" +"Note that the prefix4 address pool (*203.0.112.0/24* above) should not be " +"manually configured as an alias on any interface. These addresses are used " +"internally by *ipfw*. The only requirement is that they be reserved from " +"deployment elsewhere in the local network so they do not cause a routing " +"conflict with *ipfw*. This allows for 254 simultaneous NAT64 addresses. If " +"more are needed due to high volume, add another prefix4, or increase the " +"existing prefix4 address space." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:342 +msgid "" +"Continue configuring the NAT64 / DNS64 translator: indexterm:[NAT64] " +"indexterm:[DNS64]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:349 +#, no-wrap +msgid "" +"# *ipfw add allow log ipv6-icmp from any to any icmp6types 135,136*\n" +"# *ipfw add nat64lsn foo log ip from 2001:db8:12::/64 to 64:ff9b::/96 in*\n" +"# *ipfw add nat64lsn foo log ip from any to 203.0.112.0/24 in*\n" +"# *ipfw add allow log ip from any to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:352 +msgid "indexterm:[icmptypes]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:354 +msgid "and the direct_output sysctl must be set to 1 (not zero):" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:358 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:461 +#, no-wrap +msgid "# *sysctl net.inet.ip.fw.nat64_direct_output=1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:361 +msgid "indexterm:[sysctl, net.inet.ip.fw.nat64_direct_output]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:363 +msgid "" +"If desired, also set the nat64_debug sysctl and the firewall verbose sysctl:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:368 +#, no-wrap +msgid "" +"# *sysctl net.inet.ip.fw.nat64_debug=1*\n" +"# *sysctl net.inet.ip.fw.verbose=1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:372 +msgid "" +"indexterm:[sysctl, net.inet.ip.fw.nat64_debug] indexterm:[sysctl, net.inet." +"ip.fw.verbose]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:374 +msgid "See /var/log/security for output." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:376 +msgid "" +"With these prerequisites completed the following tests on the *v6only* VM " +"should be successful:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:384 +#, no-wrap +msgid "" +"root@v6only# *ping6 -c 3 64:ff9b::203.0.113.10*\n" +"PING6(56=40+8+8 bytes) 2001:db8:12::30 --> 64:ff9b::cb00:710a\n" +"16 bytes from 64:ff9b::cb00:710a, icmp_seq=0 hlim=63 time=8.401 ms\n" +"16 bytes from 64:ff9b::cb00:710a, icmp_seq=1 hlim=63 time=3.429 ms\n" +"16 bytes from 64:ff9b::cb00:710a, icmp_seq=2 hlim=63 time=3.398 ms\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:388 +#, no-wrap +msgid "" +"--- 64:ff9b::203.0.113.10 ping6 statistics ---\n" +"3 packets transmitted, 3 packets received, 0.0% packet loss\n" +"round-trip min/avg/max/std-dev = 3.398/5.076/8.401/2.351 ms\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:391 +msgid "indexterm:[ping6] indexterm:[\"64:ff9b::\"]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:393 +msgid "" +"and using lynx to grab the *external1.example.com* home page should be " +"successful:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:397 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:477 +#, no-wrap +msgid "[root@v6only ~]# *lynx external1.example.com*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:400 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:779 +msgid "indexterm:[lynx]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:402 +#, no-wrap +msgid "Viewing the IPv4 Webpage of *external1* VM from IPv6 *v6only* VM." +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:403 +#, no-wrap +msgid "Viewing the IPv4 Webpage of *external1* VM from IPv6 *v6only* VM. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:403 +#, no-wrap +msgid "ipfw-ipv6nat110.png" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:405 +#, no-wrap +msgid "Setting Up for Stateless NAT64 - NAT64STL" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:408 +msgid "indexterm:[NAT64] indexterm:[NAT64STL]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:411 +msgid "" +"The previous *ipfw_nat64* examples used \"stateful\" address translation. " +"*ipfw* is also capable of performing \"stateless\" address translation." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:414 +msgid "" +"Stateless translation is appropriate when a NAT64 translator is used in " +"front of IPv4-only servers to allow them to be reached by remote IPv6-only " +"clients. Stateful translation is suitable for deployment at the client side " +"or at the service provider, allowing IPv6-only client hosts to reach remote " +"IPv4-only nodes." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:419 +msgid "" +"Stateless configuration of NAT64 is possible with the same architecture as " +"the previous stateful example. Configuration details however, are " +"different. In the stateless case, *ipfw* uses two tables for translating " +"addresses in either direction: *IPv4 -> IPv6* and *IPv6 -> IPv4*. A typical " +"configuration is shown below." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:423 +#, no-wrap +msgid "Start fresh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:425 +#, no-wrap +msgid "# *kldunload ipfw_nat64*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:427 +#, no-wrap +msgid "# *kldunload ipfw*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:433 +#, no-wrap +msgid "Create the tables used for ipfw_nat64stl\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:435 +#, no-wrap +msgid "# *ipfw table T4to6 create type addr valtype ipv6*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:437 +#, no-wrap +msgid "# *ipfw table T6to4 create type addr valtype ipv4*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:439 +#, no-wrap +msgid "# *ipfw table T4to6 add 203.0.112.1 2001:db8:12::6*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:441 +#, no-wrap +msgid "# *ipfw table T6to4 add 2001:db8:12::6 203.0.112.1*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:443 +#, no-wrap +msgid "# *ipfw nat64stl NAT64 create table4 T4to6 table6 T6to4 allow_private*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:445 +#, no-wrap +msgid "Add rules for ipfw_nat64stl\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:447 +#, no-wrap +msgid "# *ipfw add allow log icmp6 from any to any icmp6types 135, 136*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:449 +#, no-wrap +msgid "# *ipfw add nat64stl NAT64 log ip from any to 'table(T4to6)'*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:451 +#, no-wrap +msgid "# *ipfw add nat64stl NAT64 log ip6 from 'table(T6to4)' to 64:ff9b::/96*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:453 +#, no-wrap +msgid "# *ipfw add allow log ip from any to any*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:455 +#, no-wrap +msgid "Adjust sysctls\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:457 +#, no-wrap +msgid "# *sysctl net.inet.ip.fw.verbose=1*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:459 +#, no-wrap +msgid "# *sysctl net.inet.ip.fw.nat64_debug=1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:465 +msgid "" +"indexterm:[module, ipfw] indexterm:[module, ipfw_nat64] indexterm:" +"[ipfw_nat64stl] indexterm:[allow_private] indexterm:[\"64:ff9b::\"] " +"indexterm:[sysctl, net.inet.ip.fw.verbose] indexterm:[sysctl, net.inet.ip.fw." +"nat64_debug] indexterm:[sysctl, net.inet.ip.fw.nat64_direct_output]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:467 +msgid "Only the *net.inet.ip.fw.nat64_direct_output* sysctl is required." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:469 +msgid "Use the same tests as in the stateful NAT64 example:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:473 +#, no-wrap +msgid "[root@v6only ~]# *ping6 -c 3 64:ff9b::203.0.113.10*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:475 +#, no-wrap +msgid "and\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:480 +msgid "indexterm:[ping6] indexterm:[lynx] indexterm:[\"64:ff9b::\"]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:482 +msgid "Both tests should be successful." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:486 +msgid "" +"It may seem limiting to have to use tables to effect communication for " +"stateless NAT64. However, in considering the architecture involved, the " +"above statements about stateless translation being appropriate when a NAT64 " +"translator is used in front of IPv4-only servers to allow them to be reached " +"by remote IPv6-only clients makes sense. The entire IPv6 cloud can reach a " +"specified server." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:488 +msgid "" +"This can be accomplished by, for example, changing the T4to6 and T6to4 " +"tables to read:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:492 +#, no-wrap +msgid "# *ipfw table T4to6 add 203.0.112.0/31 2001:db8:12::30*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:494 +#, no-wrap +msgid "# *ipfw table T6to4 add 2000:0000:0000::/8 203.0.112.0*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:496 +#, no-wrap +msgid "# *ipfw table T6to4 add 2100:0000:0000::/8 203.0.112.1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:500 +msgid "" +"The T4to6 table allocates two addresses in the address pool: 203.0.112.0 and " +"203.0.112.1. These are used separately in the T6to4 table to cover vast " +"ranges of IPv6 address space." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:503 +msgid "" +"Certainly using just one IPv4 pool address is not going to be sufficient to " +"translate such a large range of IPv6 addresses. The point here is that by " +"carefully constructing the translation pool addresses and the T4to6 and " +"T6to4 address tables, *ipfw* can manage translation to as many IPv6 " +"addresses as needed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:506 +msgid "" +"Note that stateless NAT64 shares the same limitations of stateful NAT64. " +"indexterm:[NAT64]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:509 +msgid "" +"Next is the most important IPv6 / IPv4 translation mechanism NAT64 CLAT. " +"indexterm:[CLAT]" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:510 +#, no-wrap +msgid "XLAT464" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:513 +msgid "indexterm:[XLAT464]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:519 +#, no-wrap +msgid "" +"*ipfw* supports 464XLAT (RFC 6877) calling it \"XLAT464 CLAT\".\n" +"indexterm:[RFC, 6877] indexterm:[XLAT464 CLAT]\n" +"This transition mechanism provides connectivity for IPv4 edge devices across an IPv6 only network.\n" +"It does this by combining stateful translation in the core and stateless translation at the edge.\n" +"464XLAT only supports IPv4 in the client-server model, so it does not support IPv4 peer-to-peer communication or inbound IPv4 connections.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:524 +msgid "" +"See diagrams and explanation here: https://www.juniper.net/documentation/us/" +"en/software/junos/interfaces-adaptive-services/topics/topic-map/ipv4-connect-" +"ipv6-464xlat.html#id-464xlat-overview" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:527 +msgid "" +"The RFC for this mechanism is more enlightening. See link:https://" +"datatracker.ietf.org/doc/html/rfc6877[RFC 6877]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:530 +msgid "indexterm:[juniper] indexterm:[RFC, 6877]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:532 +msgid "The discussion on Wikipedia1 is somewhat sparse:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:536 +#, no-wrap +msgid "*464XLAT*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:543 +#, no-wrap +msgid "" +"464XLAT (RFC 6877) allows clients on IPv6-only networks to access IPv4-only Internet services, such as Skype.[13][14]\n" +"The client uses a SIIT translator to convert packets from IPv4 to IPv6.\n" +"These are then sent to a NAT64 translator which translates them from IPv6 back into IPv4 and on to an IPv4-only server.\n" +"The client translator may be implemented on the client itself or on an intermediate device and is known as the CLAT (Customer-side transLATor).\n" +"The NAT64 translator, or PLAT (Provider-side transLATor), must be able to reach both the server and the client (through the CLAT).\n" +"The use of NAT64 limits connections to a client-server model using UDP, TCP, and ICMP.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:546 +msgid "indexterm:[CLAT] indexterm:[PLAT]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:549 +msgid "" +"The figure below shows a diagram for implementing 464XLAT. indexterm:" +"[464XLAT]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:551 +#, no-wrap +msgid "*ipfw* 464XLAT Design" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:552 +#, no-wrap +msgid "*ipfw* 464XLAT Design. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:552 +#, no-wrap +msgid "ipfw-ipv6464xlat090.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:555 +msgid "" +"As earlier, shutdown all virtual machines and for this example, reset all " +"the bridge and tap devices to the new architecture." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:559 +msgid "" +"This example will require two firewalls. The *firewall* VM and *firewall2* " +"VM will both be used as shown in the diagram. In this example, the " +"*firewall* VM is the CLAT translator (stateless translation) and the " +"*firewall2* VM is the PLAT translator (stateful translation)." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:561 +msgid "" +"To start, set up the bridge and tap interfaces with this command on the " +"FreeBSD host:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:566 +#, no-wrap +msgid "" +"$ *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1 tap11 bridge1 tap4 tap6 tap7 tap9 \\*\n" +" *bridge2 tap2 tap8 tap10*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:570 +msgid "Start up the virtual machines with:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:574 +#, no-wrap +msgid "$ */bin/sh runvm.sh external1 firewall firewall2 dnshost v6only external2*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:577 +msgid "" +"As earlier, configure all interfaces according to the diagram and ensure " +"connectivity with adjacent interfaces." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:580 +msgid "" +"This example is more complex than past examples. There are a number of " +"additional configuration steps needed as follows:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:582 +#, no-wrap +msgid "*external1.example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:586 +#, no-wrap +msgid "On external1.example.com:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:590 +#, no-wrap +msgid "" +"*route add default 192.168.1.1*\n" +"*echo \"nameserver 192.168.1.53\" > /etc/resolv.conf*\n" +"*echo \"nameserver 203.0.113.53\" >> /etc/resolv.conf*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:592 +#, no-wrap +msgid "*firewall.example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:596 +#, no-wrap +msgid "On firewall.example.com:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:604 +#, no-wrap +msgid "" +"*/bin/sh /root/bin/bsdclat464.sh*\n" +"*echo \"nameserver 2001:db8:12::53\" > /etc/resolv.conf*\n" +"*echo \"nameserver 192.168.1.53\" >> /etc/resolv.conf*\n" +"*route -6 add 2001:db8:bbbb::/96 2001:db8:12::1*\n" +"*sysctl net.inet.ip.forwarding=1*\n" +"*sysctl net.inet6.ip6.forwarding=1*\n" +"*sysctl net.inet.ip.fw.nat64_direct_output=1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:608 +msgid "" +"indexterm:[bsdclat464.sh] indexterm:[sysctl, net.inet.ip.forwarding] " +"indexterm:[sysctl, net.inet6.ip6.forwarding] indexterm:[sysctl, net.inet.ip." +"fw.nat64_direct_output]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:610 +#, no-wrap +msgid "*firewall2.example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:614 +#, no-wrap +msgid "On firewall2.example.com\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:621 +#, no-wrap +msgid "" +"*/bin/sh /root/bin/bsdplat464.sh*\n" +"*route -6 add 2001:db8:aaaa::/96 2001:db8:12::2*\n" +"*echo \"nameserver 2001:db8:12::53\" > /etc/resolv.conf*\n" +"*sysctl net.inet.ip.forwarding=1*\n" +"*sysctl net.inet6.ip6.forwarding=1*\n" +"*sysctl net.inet.ip.fw.nat64_direct_output=1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:623 +#, no-wrap +msgid "*external2.example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:627 +#, no-wrap +msgid "On external2.example.com\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:631 +#, no-wrap +msgid "" +"*route add default 203.0.113.1*\n" +"*echo \"nameserver 203.0.113.53\" > /etc/resolv.conf*\n" +"*service nginx onestart*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:634 +msgid "indexterm:[nginx]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:636 +#, no-wrap +msgid "*dnshost.example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:640 +#, no-wrap +msgid "On dnshost.example.com:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:648 +#, no-wrap +msgid "" +"*echo \"nameserver 127.0.0.1\" > /etc/resolv.conf*\n" +"*echo \"nameserver 2001:db8:12::53\" >> /etc/resolv.conf*\n" +"*service named onestart*\n" +"*route add default 203.0.113.1*\n" +"*route add -net 192.168.1.0/24 192.168.1.1*\n" +"*sysctl net.inet.ip.forwarding=0*\n" +"*sysctl net.inet6.ip6.forwarding=0*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:652 +msgid "" +"indexterm:[sysctl, net.inet.ip.forwarding] indexterm:[sysctl, net.inet6.ip6." +"forwarding]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:654 +#, no-wrap +msgid "*v6only.example.com*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:658 +#, no-wrap +msgid "On v6only.example.com:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:662 +#, no-wrap +msgid "" +"*echo \"nameserver 2001:db8:12::53\" > /etc/resolv.conf*\n" +"*route -6 add 2001:db8:bbbb::/96 2001:db8:12::1*\n" +"*route -6 add 2001:db8:aaaa::/96 2001:db8:12::2*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:666 +msgid "" +"Due to the complex nature of these firewall configurations, a script is " +"available for copy and paste. However, do try to understand the " +"configration details." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:668 +msgid "" +"Once all the above commands are entered on their respective VMs, test the " +"configuration with the following command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:672 +#, no-wrap +msgid "# ping -c 2 external2.example.com\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:675 +msgid "indexterm:[ping]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:677 +msgid "The snippets below show at each step, how the request was transformed." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:682 +msgid "" +"The examples below are taken from multiple different invocations of the " +"*ping* command. However, the data transformations are correct." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:687 +#, no-wrap +msgid "On interface *em0* on the *firewall* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:695 +#, no-wrap +msgid "" +"root@firewall:~/bin # tcpdump -n -i em0\n" +"tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\n" +"listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"14:38:07.254114 IP 192.168.1.2 > 203.0.113.20: ICMP echo request, id 46395, seq 0, length 64\n" +"14:38:07.256893 IP 203.0.113.20 > 192.168.1.2: ICMP echo reply, id 46395, seq 0, length 64\n" +"14:38:08.322597 IP 192.168.1.2 > 203.0.113.20: ICMP echo request, id 46395, seq 1, length 64\n" +"14:38:08.326715 IP 203.0.113.20 > 192.168.1.2: ICMP echo reply, id 46395, seq 1, length 64\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:697 +#, no-wrap +msgid "On interface *em1* on the *firewall* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:705 +#, no-wrap +msgid "" +"root@firewall:~/bin # tcpdump -n -i em1\n" +"tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\n" +"listening on em1, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"14:54:45.140746 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 38233, seq 0, length 64\n" +"14:54:45.142995 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 38233, seq 0, length 64\n" +"14:54:46.171754 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 38233, seq 1, length 64\n" +"14:54:46.173925 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 38233, seq 1, length 64\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:707 +#, no-wrap +msgid "On interface *em0* on the *firewall2* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:715 +#, no-wrap +msgid "" +"root@firewall2:~/bin # tcpdump -n -i em0\n" +"tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\n" +"listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"14:57:32.519334 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 17270, seq 0, length 64\n" +"14:57:32.529066 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 17270, seq 0, length 64\n" +"14:57:33.560392 IP6 2001:db8:aaaa::c0a8:102 > 2001:db8:bbbb::cb00:7114: ICMP6, echo request, id 17270, seq 1, length 64\n" +"14:57:33.561596 IP6 2001:db8:bbbb::cb00:7114 > 2001:db8:aaaa::c0a8:102: ICMP6, echo reply, id 17270, seq 1, length 64\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:717 +#, no-wrap +msgid "On interface *em1* on the *firewall2* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:725 +#, no-wrap +msgid "" +"root@firewall2:~/bin # tcpdump -n -i em1\n" +"tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\n" +"listening on em1, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"14:58:37.139612 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1025, seq 0, length 64\n" +"14:58:37.141043 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1025, seq 0, length 64\n" +"14:58:38.187477 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1025, seq 1, length 64\n" +"14:58:38.188308 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1025, seq 1, length 64\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:727 +#, no-wrap +msgid "On interface *em0* on the *external2* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:735 +#, no-wrap +msgid "" +"root@external2:~ # tcpdump -n -i em0\n" +"tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\n" +"listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"15:00:44.171439 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1024, seq 0, length 64\n" +"15:00:44.172313 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1024, seq 0, length 64\n" +"15:00:45.200883 IP 203.0.112.22 > 203.0.113.20: ICMP echo request, id 1024, seq 1, length 64\n" +"15:00:45.201035 IP 203.0.113.20 > 203.0.112.22: ICMP echo reply, id 1024, seq 1, length 64\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:738 +msgid "indexterm:[tcpdump]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:740 +msgid "" +"The firewall log sysctl was reset to log to man:syslogd[8] and captured " +"these logs:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:744 +#, no-wrap +msgid "Logs on the *firewall* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:754 +#, no-wrap +msgid "" +"root@firewall:~/bin # cat /var/log/security\n" +"Dec 2 15:14:04 firewall kernel: ipfw: 150 Eaction nat64clat ICMP:8.0 192.168.1.2 203.0.113.20 in via em0\n" +"Dec 2 15:14:04 firewall kernel: ipfw: 150 Eaction nat64clat ICMPv6:129.0 [2001:db8:bbbb::cb00:7114] [2001:db8:aaaa::c0a8:102] in via em1\n" +"Dec 2 15:14:04 firewall kernel: ipfw: 150 Eaction nat64clat ICMP:8.0 192.168.1.2 203.0.113.20 in via em0\n" +"Dec 2 15:14:05 firewall kernel: ipfw: 150 Eaction nat64clat ICMPv6:129.0 [2001:db8:bbbb::cb00:7114] [2001:db8:aaaa::c0a8:102] in via em1\n" +"Dec 2 15:14:08 firewall kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::1] [2001:db8:12::2] in via em1\n" +"Dec 2 15:14:08 firewall kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::2] [2001:db8:12::1] out via em1\n" +"Dec 2 15:14:09 firewall kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::2] [2001:db8:12::1] out via em1\n" +"Dec 2 15:14:09 firewall kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::1] [2001:db8:12::2] in via em1\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:756 +#, no-wrap +msgid "Logs on the *firewall2* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:766 +#, no-wrap +msgid "" +"root@firewall2:~/bin # cat /var/log/security\n" +"Dec 2 15:10:25 firewall2 kernel: ipfw: 300 Eaction nat64lsn ICMPv6:128.0 [2001:db8:aaaa::c0a8:102] [2001:db8:bbbb::cb00:7114] in via em0\n" +"Dec 2 15:10:25 firewall2 kernel: ipfw: 400 Eaction nat64lsn ICMP:0.0 203.0.113.20 203.0.112.22 in via em1\n" +"Dec 2 15:10:26 firewall2 kernel: ipfw: 300 Eaction nat64lsn ICMPv6:128.0 [2001:db8:aaaa::c0a8:102] [2001:db8:bbbb::cb00:7114] in via em0\n" +"Dec 2 15:10:26 firewall2 kernel: ipfw: 400 Eaction nat64lsn ICMP:0.0 203.0.113.20 203.0.112.22 in via em1\n" +"Dec 2 15:10:29 firewall2 kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::1] [2001:db8:12::2] out via em0\n" +"Dec 2 15:10:29 firewall2 kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::2] [2001:db8:12::1] in via em0\n" +"Dec 2 15:10:30 firewall2 kernel: ipfw: 100 Accept ICMPv6:135.0 [2001:db8:12::2] [2001:db8:12::1] in via em0\n" +"Dec 2 15:10:30 firewall2 kernel: ipfw: 100 Accept ICMPv6:136.0 [2001:db8:12::1] [2001:db8:12::2] out via em0\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:770 +msgid "indexterm:[nat64clat] indexterm:[nat64lsn]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:772 +msgid "Finally, a webpage request was made with:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:776 +#, no-wrap +msgid "# *lynx external2.example.com*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:781 +msgid "as shown below:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:783 +#, no-wrap +msgid "Retrieving the Webpage at *external2.example.com*" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:784 +#, no-wrap +msgid "Retrieving the Webpage at external2.example.com. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-ipv6-nat/_index.adoc:784 +#, no-wrap +msgid "ipfw-ipv6464xlat095.png" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc @@ -0,0 +1,756 @@ +--- +title: Chapter 5. Network Address Translation - NAT +prev: books/ipfw-primer/ipfw-dummynet +next: books/ipfw-primer/ipfw-ipv6-nat +description: Describes IPFW NAT +tags: ["IPFW", "firewall", "NAT"] +showBookMenu: true +weight: 60 +path: "/books/ipfw-primer/ipfw-nat/" +--- + +[[ipfw-nat]] += *ipfw* NAT +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 5 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +Network Address Translation (*NAT*) is the process of changing the source or destination address of a packet as it flows through the firewall. +indexterm:[NAT] +This is done chiefly to segregate internal networks and subnets from external networks. + +FreeBSD has two capabilities for NAT - man:natd[8] a daemon process that can perform these translations, and in-kernel NAT with *ipfw*. +indexterm:[natd] +Both of these capabilities use the `libalias(3)` library. +indexterm:[libalias] +This section will focus primarily on in-kernel NAT with *ipfw*. + + +== General Procedures for Working NAT Examples + +This section uses more than two virtual machines (VMs). +Begin the setup for simple NAT by following the directions on crossref:ipfw-dummynet[ipfw-dummynet-setting-up-entire-lab, Setting Up the Entire IPFW Lab]. + +The examples in this section and later sections grow increasingly complex. +Follow this standard procedure for startup with each new example: + +[[ipfw-nat-startup-procedure]] +. On the host, set up the bridge and tap setup needed for the examples. +Use *mkbr.sh* to configure bridge and tap devices on the host. +indexterm:[mkbr.sh] +Examine the figure, and run the script with all bridges and taps accounted for. +. Start up *swim.sh* (or *scim.sh*) for access to VM serial consoles. +. Start up the required VMs. +Use *runvm.sh* to start up several VMs at one time. +indexterm:[runvm.sh] +. On each VM, set up the required addressing. +Check the diagram in each Section for addressing requirements. +. Ensure all VMs have connectivity to their local network peers. +. If there are additional scripts to load onto the *firewall*, *external*, *internal*, *dnshost*, or *v6only* VMs, load them. +. If there are specific DNS entries that are required for an example, load them into the *dnshost* and test the entries from another VM. +. Other VMs in some examples require adding additional routes. +. On the *firewall* VM, unload and reload the firewall: (*kldunload ipfw* and *kldload ipfw*). +. Check whether any sysctl entries are required for the example. +. Follow the procedure given for each section. +. Troubleshoot as necessary. + + +== Setting Up for Simple NAT + +[[ipfw-simple-nat-figure]] +.Setting Up Simple NAT +image::ipfw-nat070.png["Setting Up Simple NAT. Refer to paragraphs below."] + +Shut down the existing VMs from the previous examples and reload *ipfw*. +To set up the correct network bridge and tap architecture as shown in +the figure above, use this command: + +[subs=+quotes] +---- +# *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5* +---- + +indexterm:[mkbr.sh] + +Restart the desired VMs with: + +[subs=+quotes] +---- +# */bin/sh runvm.sh firewall external1 internal* +---- + +indexterm:[runvm.sh] + +Use the above figure to set up the correct addresses for each VM and ping adjacent interfaces. + +For routing, the *external1* VM should have the default route set to 203.0.113.50. +The *internal* VM should have its default route set to 10.10.10.50. +The *firewall* should have its default route set to 203.0.113.10 (*external1*) since this example wants all traffic to exit via the *firewall* `em1` interface. + +The *firewall* should already be set up for IP forwarding (*sysctl net.inet.ip.forwarding=1*), but if not, set the sysctl as indicated. +indexterm:[sysctl, net.inet.ip.forwarding] +Try to ping em0 on *external1* VM from the *internal* VM host and vice-versa. +Check all addressing, the host bridge and tap devices, and the sysctl net.inet.ip.forwarding=1 on the firewall if something is not working. + +On the *firewall* VM, restart *ipfw* with + +[subs=+quotes] +---- +# *kldload ipfw* +---- + +indexterm:[module, ipfw] + +To use in-kernel NAT, first load the *ipfw_nat* kernel module: + +[subs=+quotes] +---- +# *kldload ipfw_nat* +---- + +indexterm:[module, ipfw_nat] + +Running *kldstat* should now show output similar to: + +[subs=+quotes] +---- +# *kldstat* +Id Refs Address Size Name + 1 11 0xffffffff80200000 1f370e8 kernel + 2 1 0xffffffff82818000 3220 intpm.ko + 3 1 0xffffffff8281c000 2178 smbus.ko + 4 2 0xffffffff8281f000 27450 ipfw.ko + 5 1 0xffffffff82847000 42d0 ipfw_nat.ko + 6 1 0xffffffff8284c000 c962 libalias.ko +# +---- + +The example is ready to explore *ipfw_nat*. + +Similar to other *ipfw* entities such as _pipes_ and _queues_, *ipfw_nat* works with a NAT *_object_*. +indexterm:[pipe] indexterm:[queue] indexterm:[NAT] +A NAT object is a single entry in the packet aliasing database. + +First, create a NAT object: + +[subs=+quotes] +---- +# *ipfw nat 25 config ip 198.51.100.50* +ipfw nat 25 config ip 198.51.100.50 +# +# *ipfw nat show config* +ipfw nat 25 config ip 198.51.100.50 +---- + +indexterm:[NAT, object] + +Note that the NAT object identifier *_must be numeric_*, not alphabetic or alphanumeric. +A NAT object identifier such as `foo` or `25foo` will be rejected by *ipfw*. + +Next, load two rules that will use that instance: + +[subs=+quotes] +---- +# *ipfw add 1000 nat 25 tcp from any to any* +# *ipfw add 2000 nat 25 icmp from any to any* +---- + +Listing the ruleset shows the NAT object and the rule body. + +[subs=+quotes] +---- +# *ipfw list* +01000 nat 25 tcp from any to any +02000 nat 25 icmp from any to any +65535 deny ip from any to any +---- + +There is now an *ipfw_nat* instance in the packet aliasing database and rules that will engage that instance. +This is generally referred to as "static NAT". +indexterm:[NAT, static] + +The *ipfw_nat* instance will replace the IP source address of any packet exiting the firewall with 198.51.100.50, provided that packet has reached the *ipfw_nat* rule and matches its configuration. + +To test, start man:tcpdump[1] on the host system monitoring *bridge0*. +indexterm:[tcpdump] indexterm:[bridge] +(Ensure once again that the host system is not running a firewall.) + +[subs=+quotes] +---- +host_system# *tcpdump -n -i bridge0 -v* +---- + +Then, from the *firewall* VM, man:telnet[1] to any IP address *not* used in the lab: + +[subs=+quotes] +---- +# *telnet 172.16.10.10* +Trying 172.16.10.10... +^C +---- + +indexterm:[telnet] + +A few seconds to attempt the connection (which will not succeed anyway) shows the host `tcpdump` output: + +[subs=+quotes] +---- +host_system# tcpdump -n -i bridge0 -v +tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +19:58:34.099782 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #198.51.100.50.62143 > 172.16.10.10.23: Flags [S],# cksum 0x89d4 (correct), seq 3107170690, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 384725297 ecr 0], length 0 +19:58:38.300043 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #198.51.100.50.62143 > 172.16.10.10.23: Flags [S],# cksum 0x796b (correct), seq 3107170690, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 384729498 ecr 0], length 0 +19:58:46.500217 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #198.51.100.50.62143 > 172.16.10.10.23: Flags [S],# cksum 0x5964 (correct), seq 3107170690, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 384737697 ecr 0], length 0 +^C +---- + +indexterm:[tcpdump] indexterm:[flags, SYN] + +The source address has been changed from 203.0.113.50 to 198.51.100.50 as per the *ipfw_nat* instance. +Note however, that with the configuration binding NAT to an IP address, as opposed to an interface, the NAT aliasing takes place on *_all_* configured interfaces, internal and external. +Verify this by repeating the above tcpdump on bridge1, and running a similar command for an existing host on the internal network. +This time the destination sends a TCP reset (RST), since the packet reached the destination but the service on the destination was not open. + +[subs=+quotes] +---- +# *telnet 10.10.10.20* +---- + +indexterm:[telnet] indexterm:[tcpdump] + +[subs=+quotes] +---- +host_system# *tcpdump -n -i bridge1 -v* +tcpdump: listening on bridge1, link-type EN10MB (Ethernet), snapshot length 262144 bytes +20:12:13.706505 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #198.51.100.50.32825 > 10.10.10.20.23: Flags [S],# cksum 0x6039 (correct), seq 1314409263, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 3924141446 ecr 0], length 0 +20:12:13.710494 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40) + #10.10.10.20.23 > 198.51.100.50.32825: Flags [R.],# cksum 0x5774 (correct), seq 0, ack 1314409264, win 0, length 0 +20:12:29.573756 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) +^C +---- + +To specify that only the outside interface is to be NATed, use the keyword *if* (interface) on the *ipfw* NAT configuration statement and specify the correct external interface: + +[subs=+quotes] +---- +# *ipfw nat 25 config if em1* +# *ipfw nat show config* +ipfw nat 25 config if em1 +---- + +*ipfw* does not permit the use of *ip ip_addr* and *if interf_name* options at the same time on the same NAT instance. +Use one or the other. + +What happens in this case is that the NAT instance will ensure that the IP address of interface *em1* will always be used on traffic exiting through that interface - even if the address changes (because of DHCP or an administrative addressing change): + +Traffic destined externally from the *internal* VM host via: + +[subs=+quotes] +---- +root@internal:~ # *telnet 172.16.10.10* +Trying 172.16.10.10... +^C +---- + +indexterm:[telnet] + +On the FreeBSD host: + +[subs=+quotes] +---- +host_system# *tcpdump -n -i bridge0 -v* +tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +20:24:41.147755 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #203.0.113.50.40001 > 172.16.10.10.23: Flags [S],# cksum 0x5962 (correct), seq 950423268, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 2027118491 ecr 0], length 0 +20:24:42.189806 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #203.0.113.50.40001 > 172.16.10.10.23: Flags [S],# cksum 0x554b (correct), seq 950423268, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 2027119538 ecr 0], length 0 +20:24:44.394747 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60) + #203.0.113.50.40001 > 172.16.10.10.23: Flags [S],# cksum 0x4caa (correct), seq 950423268, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 2027121747 ecr 0], length 0 +^C +---- + +indexterm:[flags, SYN] + +Though it does not look like it, *ipfw* _is_ translating the packets as they exit the firewall. + +Consider this exchange where the *internal* VM host pings the *external1* VM: + +[subs=+quotes] +---- +root@internal:~ # *ping 203.0.113.10* +PING 203.0.113.10 (203.0.113.10): 56 data bytes +64 bytes from 203.0.113.10: icmp_seq=0 ttl=63 time=2.742 ms +64 bytes from 203.0.113.10: icmp_seq=1 ttl=63 time=2.675 ms +^C +---- + +indexterm:[ping] + +The traffic on the internal bridge (bridge1) shows the packets from the *internal1* VM: + +[subs=+quotes] +---- +host_system# tcpdump -n -i bridge1 -v +tcpdump: listening on bridge1, link-type EN10MB (Ethernet), snapshot length 262144 bytes +20:29:27.048162 IP (tos 0x0, ttl 64, id 58916, offset 0, flags [none], proto ICMP (1), length 84) + #10.10.10.20 > 203.0.113.10: ICMP echo request,# id 15077, seq 0, length 64 +20:29:27.052446 IP (tos 0x0, ttl 63, id 36018, offset 0, flags [none], proto ICMP (1), length 84) + #203.0.113.10 > 10.10.10.20: ICMP echo reply,# id 15077, seq 0, length 64 +20:29:28.104133 IP (tos 0x0, ttl 64, id 58917, offset 0, flags [none], proto ICMP (1), length 84) + #10.10.10.20 > 203.0.113.10: ICMP echo request,# id 15077, seq 1, length 64 +20:29:28.105732 IP (tos 0x0, ttl 63, id 36019, offset 0, flags [none], proto ICMP (1), length 84) + #203.0.113.10 > 10.10.10.20: ICMP echo reply,# id 15077, seq 1, length 64 +---- + +whereas the traffic on the external bridge (bridge0) shows the correct translation: + +[subs=+quotes] +---- +host_system# tcpdump -n -i bridge0 -v +tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +20:33:19.695939 IP (tos 0x0, ttl 63, id 58919, offset 0, flags [none], proto ICMP (1), length 84) + #203.0.113.50 > 203.0.113.10: ICMP echo request,# id 58206, seq 0, length 64 +20:33:19.696546 IP (tos 0x0, ttl 64, id 36021, offset 0, flags [none], proto ICMP (1), length 84) + #203.0.113.10 > 203.0.113.50: ICMP echo reply,# id 58206, seq 0, length 64 +20:33:20.715148 IP (tos 0x0, ttl 63, id 58920, offset 0, flags [none], proto ICMP (1), length 84) + #203.0.113.50 > 203.0.113.10: ICMP echo request,# id 58206, seq 1, length 64 +20:33:20.715824 IP (tos 0x0, ttl 64, id 36022, offset 0, flags [none], proto ICMP (1), length 84) + #203.0.113.10 > 203.0.113.50: ICMP echo reply,# id 58206, seq 1, length 64 +^C +---- + +indexterm:[tcpdump] + +The *unreg_only* and *unreg_cgn* configuration options allow bypassing the NAT operation if the source IP of the packet is _not_ one of the RFC 1918 addresses (unreg_only) or the RFC 6598 addresses (unreg_cgn - carrier grade NAT). +indexterm:[unreg_only] indexterm:[unreg_cgn] +In these cases, the original source address will be maintained in the packet, even though there is an *ipfw_nat* instance and a matching rule. + +[subs=+quotes] +---- +# *ipfw nat 25 show config* +ipfw nat 25 config if em1 +# +# *ipfw nat 25 config if em1 unreg_only* +ipfw nat 25 config if em1 unreg_only +# +# *ipfw nat 25 show config* +ipfw nat 25 config if em1 unreg_only +# +---- + +To try the *unreg_only* option, on the *internal* VM, change its IP address on `em0` to a registered number, say 140.140.140.140/24, and change the corresponding link on the firewall (`em1`) to a compatible address - 140.140.140.1/24. +The *internal* VM will need a new default route: 140.140.140.1. +Ensure that the default route on the *firewall* VM remains 203.0.113.10. + +[subs=+quotes] +---- +root@internal:~ # *ifconfig em0 140.140.140.140/24* +root@internal:~ # *route add default 140.140.140.1* +add net default: gateway 140.140.140.1 +root@internal:~ # + +and on the firewall + +root@firewall:~ # *ifconfig em0 140.140.140.1/24* +---- + +From the *internal* VM, try to ping an external address not in the lab: + +[subs=+quotes] +---- +# *ping 5.5.5.5* +---- + +indexterm:[ping] + +and observe on the host system that the *ipfw_nat* instance _did not_ replace the source address with the configured IP: + +[subs=+quotes] +---- +host_system# *tcpdump -n -i bridge0 -v* +tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +21:07:18.154319 IP (tos 0x0, ttl 63, id 58943, offset 0, flags [none], proto ICMP (1), length 84) + #140.140.140.140 > 5.5.5.5: ICMP echo request,# id 38569, seq 0, length 64 +21:07:19.180094 IP (tos 0x0, ttl 63, id 58944, offset 0, flags [none], proto ICMP (1), length 84) + #140.140.140.140 > 5.5.5.5: ICMP echo request,# id 38569, seq 1, length 64 +21:07:20.194988 IP (tos 0x0, ttl 63, id 58945, offset 0, flags [none], proto ICMP (1), length 84) + #140.140.140.140 > 5.5.5.5: ICMP echo request,# id 38569, seq 2, length 64 +---- + +indexterm:[tcpdump] + +Not all the options available to *ipfw_nat* are described in the NAT section of the man:ipfw[8] man page. + +Some of the options usable from man:natd[8] are available to *ipfw_nat*. +indexterm:[natd] indexterm:[ipfw_nat] +These include: + +[subs=+quotes] +---- + +*redirect_port* _proto targetIP:targetPORT[-targetPORT]_ + _[aliasIP:]aliasPORT[-aliasPORT]_ + _[remoteIP[:remotePORT[-remotePORT]]]_ +*redirect_proto* _proto localIP [publicIP [remoteIP]]_ + +*redirect_address* _localIP publicIP_ +---- + +indexterm:[redirect_port] indexterm:[redirect_proto] indexterm:[redirect_address] + +The below options are used for Load Sharing NAT (*LSNAT*) as described in link:https://www.rfc-editor.org/rfc/rfc2391.html[RFC 2391]. +indexterm:[LSNAT] indexterm:[RFC, 2391] + +[subs=+quotes] +---- +*redirect_port* _proto targetIP:targetPORT[,targetIP:targetPORT[,...]]_ + _[aliasIP:]aliasPORT [remoteIP[:remotePORT]]_ +*redirect_address* _localIP[,localIP[,...]] publicIP_ +---- + +`LSNAT` is discussed in the next section. + +== Setting Up for LSNAT + +indexterm:[LSNAT] +This example uses the three VMs *external1*, *external2*, and *external3* and pretends they are on the *_inside_* of the network; and *internal* VM is on the *_outside_* of the network. + +The figure below shows the architecture setup for working with LSNAT. + +[[ipfw-lsnat-figure]] +.Setting Up for LSNAT +image::ipfw-nat075.png["Setting Up for LSNAT. Refer to paragraphs below."] + +As before, shutdown all virtual machines and rebuild the network from scratch. + +Use this command to set up the network bridge and tap architecture. + +[subs=+quotes] +---- +# *sudo /bin/sh mkbr.sh reset bridge0 tap4 tap5 bridge1 tap0 tap1 tap2 tap3* +---- + +indexterm:[mkbr.sh] indexterm:[runvm.sh] + +Note that the host interface is not needed for this example. + +Restart the virtual machines with: + +[subs=+quotes] +---- +# */bin/sh runvm.sh firewall internal external1 external2 external3* +---- + +or start them up individually. + +Configure each virtual machine to ensure its network configuration matches the above figure and test connectivity between adjacent systems with man:ping[8]. +indexterm:[ping] + +Throughout this section, remember that the "external" VMs are now *internal* web servers load balancing between .10, .20, .30, and the "internal" server VM is the *outside* host accessing the internal webservers. + +On each *inside* VM the following commands are necessary to perform the examples in this section: + +[subs=+quotes] +---- +# *route delete default* +# +# *route add default 10.10.10.50* +---- + +On the *outside* VM perform these commands: + +[subs=+quotes] +---- +# *route delete default* +# +# *route add default 198.51.100.50* +---- + +Also, on each inside VM, edit the *nginx* [.filename]#index.html# page and insert a line of text that has the VM name or IP address of the VM - something like this: + +[subs=+quotes] +---- +File: */usr/local/www/nginx/index.html*: + +

Welcome to nginx!

+

If you see this page, the nginx web server is successfully installed and +working. Further configuration is required.

+#

This is VM EXTERNAL1

# +---- + +indexterm:[nginx] + +and start *nginx* on each inside VM: + +[subs=+quotes] +---- +# *service nginx onestart* +Performing sanity check on nginx configuration: +nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok +nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful +Starting nginx. +# +---- + +[[ipfw-lsnat-allvms]] +.LSNAT Setup Showing All VMs +image::ipfw-nat095.png["LSNAT Setup Showing All VMs. Refer to paragraphs below."] + +indexterm:[LSNAT] + +With no *ipfw* loaded on the firewall, it should be possible to ping all *inside* addresses (10.10.10.10, .20, .30) from the *outside* host (198.51.100.20). +And it should be possible to access each web server via: + +[subs=+quotes] +---- +# *lynx 10.10.10.10* # (or .20 or .30) +---- + +indexterm:[lynx] + +=== Setting up LSNAT- One address (10.10.10.10) + +Begin with loading *ipfw* and *ipfw_nat* on the *firewall* VM + +[subs=+quotes] +---- +# *kldload ipfw* +# +# *kldload ipfw_nat* +---- + +indexterm:[module, ipfw_nat] + +The first configuration is similar to static NAT, though from the _outside_ to the _inside_. +The command redirects incoming traffic from the outside VM sent to destination IP 3.3.3.3 to inside VM 10.10.10.10. + +[subs=+quotes] +---- +# *ipfw nat 25 config redirect_addr 10.10.10.10 3.3.3.3* +ipfw nat 25 config redirect_addr 10.10.10.10 3.3.3.3 +---- + +Next create a ruleset that utilizes this NAT instance: + +[subs=+quotes] +---- +# *ipfw add 50 check-state* +# *ipfw add 1000 nat 25 tcp from any to any* +# +# *ipfw list* +00050 check-state :default +01000 nat 25 tcp from any to any +65535 deny ip from any to any +# +---- + +[NOTE] +==== +Do not use the *setup* keyword on the *ipfw* rule referencing LSNAT. +The *setup* keyword causes the final ACK of the TCP 3-way handshake to be never received and the connection is never established. +==== + +indexterm:[setup] + +From the outside VM, access the web server using: + +[subs=+quotes] +---- +# *lynx 3.3.3.3* +---- + +indexterm:[lynx] + +brings up the web page on 10.10.10.10. + +[[ipfw-lsnat-accessing-nginx-with-lsnat]] +.Accessing Nginx on 10.10.10.10 With LSNAT via 3.3.3.3 +image::ipfw-nat100.png["Accessing Nginx on 10.10.10.10 With LSNAT via 3.3.3.3. Refer to paragraphs below."] + +NAT with one address is working. + +=== Engaging Multiple Hosts With LSNAT + +indexterm:[LSNAT] + +Next, reconfigure the *nat 25* instance to utilize all of the inside hosts: + +[subs=+quotes] +---- +# *ipfw nat 25 config redirect_addr #10.10.10.10,10.10.10.20,10.10.10.30# 3.3.3.3* +---- + +indexterm:[keyword, redirect_addr] + +(Note that adding a modification to a NAT instance just overwrites the existing instance. +It does not create a new instance with the same number.) + +On the outside VM, running *lynx 3.3.3.3* repeatedly retrieves the home page of each internal server - in round-robin fashion, without regard for any network load, or server utilization. +indexterm:[lynx] + +[TIP] +==== +In the lynx browser, reload the current page by pressing kbd:[Ctl+R]. +==== + +[subs=+quotes] +---- +# *ipfw nat 25 show config* +ipfw nat 25 config log redirect_addr 10.10.10.10,10.10.10.20,10.10.10.30 3.3.3.3 +# +---- + +By adding a rule to redirect icmp traffic, both icmp and tcp will be load shared across the firewall. + +[subs=+quotes] +---- +# *ipfw add 2000 nat 25 icmp from any to any* +# +# *ipfw list* +00050 check-state :default +01000 nat 25 tcp from any to any +02000 nat 25 icmp from any to any +65535 deny ip from any to any +---- + +Test this by running *tcpdump -n -i em0* on each inside VM, and running *ping -c 1 3.3.3.3* on the outside VM a few times. +indexterm:[tcpdump] indexterm:[ping] +The incoming ping will hit each inside VM in turn. + +However, on running *ping 3.3.3.3*, the result is that these pings hit only one internal VM. +The reason is that the aliasing engine treats ICMP differently from TCP and UDP. +The aliasing engine recognizes the ICMP id number, and if this number does not change, it uses the same alias. +indexterm:[aliasing] +If the command *ping -c 1 3.3.3.3* is used repeatedly, the ICMP id number changes, and this creates a new entry in the aliasing database resulting in redirection to a different VM. + +It is common to want to balance the load across servers according to certain characteristics such as system load. +indexterm:[load balancing] +This is possible - manually - by reconfiguring the NAT statement and adding multiple instances of the same host to give that host more traffic. +Consider this ruleset created with the Unix line continuation character '\' to close the space between successive IP addresses except for the last one and the alias address: + +[subs=+quotes] +---- +# *ipfw nat 25 config log redirect_addr* \ +*10.10.10.30,*\ +*10.10.10.20,10.10.10.20,*\ +*10.10.10.10,10.10.10.10,10.10.10.10,10.10.10.10 3.3.3.3* +---- + +This configuration shifts the NAT load heavily toward 10.10.10.10 and moderately toward 10.10.10.20, with 10.10.10.30 having a lot less traffic. +Repeat the above single ping example above to see the result. +While this works, it is a bit of a hack. + +It would be better to have a range assignment feature similar to the sparse address feature already in *ipfw*, something like: + +[subs=+quotes] +---- +# *ipfw nat 25 config redirect_addr 10.10.10.0/24{10,20-25,30-50} 3.3.3.3* +ipfw: unknown host 10.10.10.0/24{10 +---- + +but this feature does not work with LSNAT. + +However, it is possible to use the *prob* keyword to address load balancing. +indexterm:[prob] +In a rule with the *prob* keyword, if the rule matches *and* the probability is "true", the action of the rule is taken and processing stops for that packet. +If the rule matches, and the probability is "not true", the action is not taken, and processing continues with the next rule. +Verify this with a simple test ruleset and the *ucont.sh* shell rule from an external host. + +[subs=+quotes] +---- +03000 prob 0.200000 allow udp from any to me 5656 // set probability to 20% chance of matching +04000 count udp from any to me // count how many were not chosen by rule 3000 +05000 prob 0.400000 allow udp from any to me 5656 // set probability to 40% chance of matching +06000 count udp from any to me // count how many were not chosen by 3000 and 5000 +07000 prob 0.999000 allow udp from any to me 5656 // set probability to 99.9% chance of matching +08000 count udp from any to me // count how many were not chosen by all 3 rules +09000 allow udp from any to me 5656 // unconditional matching +65535 deny ip from any to any // default rule deny +---- + +After a run of 200 entries from *sh ucont.sh 5656 1* the counts are: + +[subs=+quotes] +---- +03000 47 3314 prob 0.200000 allow udp from any to me 5656 +04000 153 10776 count udp from any to me +05000 64 4505 prob 0.400000 allow udp from any to me 5656 +06000 89 6271 count udp from any to me +07000 89 6271 prob 0.999000 allow udp from any to me 5656 +08000 0 0 count udp from any to me +09000 0 0 allow udp from any to me 5656 +65535 0 0 deny ip from any to any +---- + +From the above data, out of 200 packets sent from *ucont.sh*, 47 were matched by rule 3000, but 153 were not matched (rule 4000). +Then, 64 were matched at rule 5000, but 89 were not matched. +Finally, 89 where matched at rule 7000. + +[TIP] +==== +If there are some packets hitting the default deny rule (65535), delete the host interface from the bridge and re-run the test. +*ipfw* is then unlikely to have any stray UDP packets hitting the default rule. +==== + +While the above works for UDP, it does not work for TCP. +The TCP 3-way handshake is broken because some packets will match, but others will not. + +Other load balancing solutions exist for FreeBSD and those should be used instead. + +*Other NAT Keywords* + +The other keywords in the NAT section of man:ipfw[8] are straightforward: + +* *deny_in* : deny incoming packets +indexterm:[deny_in] +* *same_ports* : keep the same ports after redirection +indexterm:[same_ports] +* *reset* : clear the aliasing table when the address changes +indexterm:[reset] +* *reverse* : reverse the direction of the NAT +indexterm:[reverse] +* *proxy_only* : packet aliasing is not performed +indexterm:[proxy_only] +* *skip_global* +indexterm:[skip_global] +* *global* +indexterm:[global] +* *tablearg* : discussed in crossref:ipfw-rules[ipfw-rules-understanding-tablearg, Understanding the Word Tablearg] +indexterm:[tablearg] + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-nat/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-nat/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-nat/_index.po @@ -0,0 +1,1383 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:1 +#, no-wrap +msgid "Describes IPFW NAT" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:1 +#, no-wrap +msgid "Chapter 5. Network Address Translation - NAT" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:13 +#, no-wrap +msgid "*ipfw* NAT" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:54 +msgid "" +"Network Address Translation (*NAT*) is the process of changing the source or " +"destination address of a packet as it flows through the firewall. indexterm:" +"[NAT] This is done chiefly to segregate internal networks and subnets from " +"external networks." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:60 +msgid "" +"FreeBSD has two capabilities for NAT - man:natd[8] a daemon process that can " +"perform these translations, and in-kernel NAT with *ipfw*. indexterm:[natd] " +"Both of these capabilities use the `libalias(3)` library. indexterm:" +"[libalias] This section will focus primarily on in-kernel NAT with *ipfw*." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:62 +#, no-wrap +msgid "General Procedures for Working NAT Examples" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:66 +msgid "" +"This section uses more than two virtual machines (VMs). Begin the setup for " +"simple NAT by following the directions on crossref:ipfw-dummynet[ipfw-" +"dummynet-setting-up-entire-lab, Setting Up the Entire IPFW Lab]." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:69 +msgid "" +"The examples in this section and later sections grow increasingly complex. " +"Follow this standard procedure for startup with each new example:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:75 +msgid "" +"On the host, set up the bridge and tap setup needed for the examples. Use " +"*mkbr.sh* to configure bridge and tap devices on the host. indexterm:[mkbr." +"sh] Examine the figure, and run the script with all bridges and taps " +"accounted for." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:78 +msgid "" +"Start up the required VMs. Use *runvm.sh* to start up several VMs at one " +"time. indexterm:[runvm.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:80 +msgid "" +"On each VM, set up the required addressing. Check the diagram in each " +"Section for addressing requirements." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:81 +msgid "Ensure all VMs have connectivity to their local network peers." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:82 +msgid "" +"If there are additional scripts to load onto the *firewall*, *external*, " +"*internal*, *dnshost*, or *v6only* VMs, load them." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:83 +msgid "" +"If there are specific DNS entries that are required for an example, load " +"them into the *dnshost* and test the entries from another VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:84 +msgid "Other VMs in some examples require adding additional routes." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:85 +msgid "" +"On the *firewall* VM, unload and reload the firewall: (*kldunload ipfw* and " +"*kldload ipfw*)." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:86 +msgid "Check whether any sysctl entries are required for the example." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:87 +msgid "Follow the procedure given for each section." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:88 +msgid "Troubleshoot as necessary." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:90 +#, no-wrap +msgid "Setting Up for Simple NAT" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:93 +#, no-wrap +msgid "Setting Up Simple NAT" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:94 +#, no-wrap +msgid "Setting Up Simple NAT. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:94 +#, no-wrap +msgid "ipfw-nat070.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:99 +msgid "" +"Shut down the existing VMs from the previous examples and reload *ipfw*. To " +"set up the correct network bridge and tap architecture as shown in the " +"figure above, use this command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:103 +#, no-wrap +msgid "# *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:106 +msgid "indexterm:[mkbr.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:108 +msgid "Restart the desired VMs with:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:112 +#, no-wrap +msgid "# */bin/sh runvm.sh firewall external1 internal*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:115 +msgid "indexterm:[runvm.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:117 +msgid "" +"Use the above figure to set up the correct addresses for each VM and ping " +"adjacent interfaces." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:121 +msgid "" +"For routing, the *external1* VM should have the default route set to " +"203.0.113.50. The *internal* VM should have its default route set to " +"10.10.10.50. The *firewall* should have its default route set to " +"203.0.113.10 (*external1*) since this exmaple wants all traffic to exit via " +"the *firewall* `em1` interface." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:126 +msgid "" +"The *firewall* should already be set up for IP forwarding (*sysctl net.inet." +"ip.forwarding=1*), but if not, set the sysctl as indicated. indexterm:" +"[sysctl, net.inet.ip.forwarding] Try to ping em0 on *external1* VM from the " +"*internal* VM host and vice-versa. Check all addressing, the host bridge " +"and tap devices, and the sysctl net.inet.ip.forwarding=1 on the firewall if " +"something is not working." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:128 +msgid "On the *firewall* VM, restart *ipfw* with" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:132 +#, no-wrap +msgid "# *kldload ipfw*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:135 +msgid "indexterm:[module, ipfw]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:137 +msgid "To use in-kernel NAT, first load the *ipfw_nat* kernel module:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:141 +#, no-wrap +msgid "# *kldload ipfw_nat*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:144 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:557 +msgid "indexterm:[module, ipfw_nat]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:146 +msgid "Running *kldstat* should now show output similar to:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:158 +#, no-wrap +msgid "" +"# *kldstat*\n" +"Id Refs Address Size Name\n" +" 1 11 0xffffffff80200000 1f370e8 kernel\n" +" 2 1 0xffffffff82818000 3220 intpm.ko\n" +" 3 1 0xffffffff8281c000 2178 smbus.ko\n" +" 4 2 0xffffffff8281f000 27450 ipfw.ko\n" +" 5 1 0xffffffff82847000 42d0 ipfw_nat.ko\n" +" 6 1 0xffffffff8284c000 c962 libalias.ko\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:161 +msgid "The example is ready to explore *ipfw_nat*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:165 +msgid "" +"Similar to other *ipfw* entities such as _pipes_ and _queues_, *ipfw_nat* " +"works with a NAT *_object_*. indexterm:[pipe] indexterm:[queue] indexterm:" +"[NAT] A NAT object is a single entry in the packet aliasing database." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:167 +msgid "First, create a NAT object:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:175 +#, no-wrap +msgid "" +"# *ipfw nat 25 config ip 198.51.100.50*\n" +"ipfw nat 25 config ip 198.51.100.50\n" +"#\n" +"# *ipfw nat show config*\n" +"ipfw nat 25 config ip 198.51.100.50\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:178 +msgid "indexterm:[NAT, object]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:181 +msgid "" +"Note that the NAT object identifier *_must be numeric_*, not alphabetic or " +"alphanumeric. A NAT object identifier such as `foo` or `25foo` will be " +"rejected by *ipfw*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:183 +msgid "Next, load two rules that will use that instance:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:188 +#, no-wrap +msgid "" +"# *ipfw add 1000 nat 25 tcp from any to any*\n" +"# *ipfw add 2000 nat 25 icmp from any to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:191 +msgid "Listing the ruleset shows the NAT object and the rule body." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:198 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"01000 nat 25 tcp from any to any\n" +"02000 nat 25 icmp from any to any\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:203 +msgid "" +"There is now an *ipfw_nat* instance in the packet aliasing database and " +"rules that will engage that instance. This is generally referred to as " +"\"static NAT\". indexterm:[NAT, static]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:205 +msgid "" +"The *ipfw_nat* instance will replace the IP source address of any packet " +"exiting the firewall with 198.51.100.50, provided that packet has reached " +"the *ipfw_nat* rule and matches its configuration." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:209 +msgid "" +"To test, start man:tcpdump[1] on the host system monitoring *bridge0*. " +"indexterm:[tcpdump] indexterm:[bridge] (Ensure once again that the host " +"system is not running a firewall.)" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:213 +#, no-wrap +msgid "host_system# *tcpdump -n -i bridge0 -v*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:216 +msgid "" +"Then, from the *firewall* VM, man:telnet[1] to any IP address *not* used in " +"the lab:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:222 +#, no-wrap +msgid "" +"# *telnet 172.16.10.10*\n" +"Trying 172.16.10.10...\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:225 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:291 +msgid "indexterm:[telnet]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:227 +msgid "" +"A few seconds to attempt the connection (which will not succeed anyway) " +"shows the host `tcpdump` output:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:239 +#, no-wrap +msgid "" +"host_system# tcpdump -n -i bridge0 -v\n" +"tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"19:58:34.099782 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #198.51.100.50.62143 > 172.16.10.10.23: Flags [S],# cksum 0x89d4 (correct), seq 3107170690, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 384725297 ecr 0], length 0\n" +"19:58:38.300043 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #198.51.100.50.62143 > 172.16.10.10.23: Flags [S],# cksum 0x796b (correct), seq 3107170690, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 384729498 ecr 0], length 0\n" +"19:58:46.500217 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #198.51.100.50.62143 > 172.16.10.10.23: Flags [S],# cksum 0x5964 (correct), seq 3107170690, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 384737697 ecr 0], length 0\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:242 +msgid "indexterm:[tcpdump] indexterm:[flags, SYN]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:247 +msgid "" +"The source address has been changed from 203.0.113.50 to 198.51.100.50 as " +"per the *ipfw_nat* instance. Note however, that with the configuration " +"binding NAT to an IP address, as opposed to an interface, the NAT aliasing " +"takes place on *all* configured interfaces, internal and external. Verify " +"this by repeating the above tcpdump on bridge1, and running a similar " +"command for an existing host on the internal network. This time the " +"destination sends a TCP reset (RST), since the packet reached the " +"destination but the service on the destination was not open." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:251 +#, no-wrap +msgid "# *telnet 10.10.10.20*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:254 +msgid "indexterm:[telnet] indexterm:[tcpdump]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:265 +#, no-wrap +msgid "" +"host_system# *tcpdump -n -i bridge1 -v*\n" +"tcpdump: listening on bridge1, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"20:12:13.706505 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #198.51.100.50.32825 > 10.10.10.20.23: Flags [S],# cksum 0x6039 (correct), seq 1314409263, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 3924141446 ecr 0], length 0\n" +"20:12:13.710494 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)\n" +" #10.10.10.20.23 > 198.51.100.50.32825: Flags [R.],# cksum 0x5774 (correct), seq 0, ack 1314409264, win 0, length 0\n" +"20:12:29.573756 IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:268 +msgid "" +"To specify that only the outside interface is to be NATed, use the keyword " +"*if* on the *ipfw* NAT configuration statement and specify the correct " +"external interface:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:274 +#, no-wrap +msgid "" +"# *ipfw nat 25 config if em1*\n" +"# *ipfw nat show config*\n" +"ipfw nat 25 config if em1\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:278 +#, no-wrap +msgid "" +"*ipfw* does not permit the use of *ip ip_addr* and *if interf_name* options at the same time on the same NAT instance.\n" +"Use one or the other.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:280 +msgid "" +"What happens in this case is that the NAT instance will ensure that the IP " +"address of interface *em1* will always be used on traffic exiting through " +"that interface - even if the address changes (because of DHCP or an " +"administrative addressing change):" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:282 +msgid "Traffic destined externally from the *internal* VM host via:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:288 +#, no-wrap +msgid "" +"root@internal:~ # *telnet 172.16.10.10*\n" +"Trying 172.16.10.10...\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:293 +msgid "On the FreeBSD host:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:305 +#, no-wrap +msgid "" +"host_system# *tcpdump -n -i bridge0 -v*\n" +"tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"20:24:41.147755 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #203.0.113.50.40001 > 172.16.10.10.23: Flags [S],# cksum 0x5962 (correct), seq 950423268, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 2027118491 ecr 0], length 0\n" +"20:24:42.189806 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #203.0.113.50.40001 > 172.16.10.10.23: Flags [S],# cksum 0x554b (correct), seq 950423268, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 2027119538 ecr 0], length 0\n" +"20:24:44.394747 IP (tos 0x10, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" #203.0.113.50.40001 > 172.16.10.10.23: Flags [S],# cksum 0x4caa (correct), seq 950423268, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 2027121747 ecr 0], length 0\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:308 +msgid "indexterm:[flags, SYN]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:310 +msgid "" +"Though it does not look like it, *ipfw* _is_ translating the packets as they " +"exit the firewall." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:312 +msgid "" +"Consider this exchange where the *internal* VM host pings the *external1* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:320 +#, no-wrap +msgid "" +"root@internal:~ # *ping 203.0.113.10*\n" +"PING 203.0.113.10 (203.0.113.10): 56 data bytes\n" +"64 bytes from 203.0.113.10: icmp_seq=0 ttl=63 time=2.742 ms\n" +"64 bytes from 203.0.113.10: icmp_seq=1 ttl=63 time=2.675 ms\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:323 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:399 +msgid "indexterm:[ping]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:325 +msgid "" +"The traffic on the internal bridge (bridge1) shows the packets from the " +"*internal1* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:338 +#, no-wrap +msgid "" +"host_system# tcpdump -n -i bridge1 -v\n" +"tcpdump: listening on bridge1, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"20:29:27.048162 IP (tos 0x0, ttl 64, id 58916, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #10.10.10.20 > 203.0.113.10: ICMP echo request,# id 15077, seq 0, length 64\n" +"20:29:27.052446 IP (tos 0x0, ttl 63, id 36018, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #203.0.113.10 > 10.10.10.20: ICMP echo reply,# id 15077, seq 0, length 64\n" +"20:29:28.104133 IP (tos 0x0, ttl 64, id 58917, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #10.10.10.20 > 203.0.113.10: ICMP echo request,# id 15077, seq 1, length 64\n" +"20:29:28.105732 IP (tos 0x0, ttl 63, id 36019, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #203.0.113.10 > 10.10.10.20: ICMP echo reply,# id 15077, seq 1, length 64\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:341 +msgid "" +"whereas the traffic on the external bridge (bridge0) shows the correct " +"translation:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:355 +#, no-wrap +msgid "" +"host_system# tcpdump -n -i bridge0 -v\n" +"tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"20:33:19.695939 IP (tos 0x0, ttl 63, id 58919, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #203.0.113.50 > 203.0.113.10: ICMP echo request,# id 58206, seq 0, length 64\n" +"20:33:19.696546 IP (tos 0x0, ttl 64, id 36021, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #203.0.113.10 > 203.0.113.50: ICMP echo reply,# id 58206, seq 0, length 64\n" +"20:33:20.715148 IP (tos 0x0, ttl 63, id 58920, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #203.0.113.50 > 203.0.113.10: ICMP echo request,# id 58206, seq 1, length 64\n" +"20:33:20.715824 IP (tos 0x0, ttl 64, id 36022, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #203.0.113.10 > 203.0.113.50: ICMP echo reply,# id 58206, seq 1, length 64\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:358 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:415 +msgid "indexterm:[tcpdump]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:362 +msgid "" +"The *unreg_only* and *unreg_cgn* configuration options allow bypassing the " +"NAT operation if the source IP of the packet is _not_ one of the RFC 1918 " +"addresses (unreg_only) or the RFC 6598 addresses (unreg_cgn - carrier grade " +"NAT). indexterm:[unreg_only] indexterm:[unreg_cgn] In these cases, the " +"original source address will be maintained in the packet, even though there " +"is an *ipfw_nat* instance and a matching rule." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:374 +#, no-wrap +msgid "" +"# *ipfw nat 25 show config*\n" +"ipfw nat 25 config if em1\n" +"#\n" +"# *ipfw nat 25 config if em1 unreg_only*\n" +"ipfw nat 25 config if em1 unreg_only\n" +"#\n" +"# *ipfw nat 25 show config*\n" +"ipfw nat 25 config if em1 unreg_only\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:378 +msgid "" +"To try the *unreg_only* option, on the *internal* VM, change its IP address " +"on `em0` to a registered number, say 140.140.140.140/24, and change the " +"corresponding link on the firewall (`em1`) to a compatible address - " +"140.140.140.1/24. The *internal* VM will need a new default route: " +"140.140.140.1" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:385 +#, no-wrap +msgid "" +"root@internal:~ # *ifconfig em0 140.140.140.140/24*\n" +"root@internal:~ # *route add default 140.140.140.1*\n" +"add net default: gateway 140.140.140.1\n" +"root@internal:~ #\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:387 +#, no-wrap +msgid "and on the firewall\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:389 +#, no-wrap +msgid "root@firewall:~ # *ifconfig em0 140.140.140.1/24*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:392 +msgid "From the *internal* VM, try to ping an external address not in the lab:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:396 +#, no-wrap +msgid "# *ping 5.5.5.5*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:401 +msgid "" +"and observe on the host system that the *ipfw_nat* instance _did not_ " +"replace the source address with the configured IP:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:412 +#, no-wrap +msgid "" +"host_system# *tcpdump -n -i bridge0 -v*\n" +"tcpdump: listening on bridge0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"21:07:18.154319 IP (tos 0x0, ttl 63, id 58943, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #140.140.140.140 > 5.5.5.5: ICMP echo request,# id 38569, seq 0, length 64\n" +"21:07:19.180094 IP (tos 0x0, ttl 63, id 58944, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #140.140.140.140 > 5.5.5.5: ICMP echo request,# id 38569, seq 1, length 64\n" +"21:07:20.194988 IP (tos 0x0, ttl 63, id 58945, offset 0, flags [none], proto ICMP (1), length 84)\n" +" #140.140.140.140 > 5.5.5.5: ICMP echo request,# id 38569, seq 2, length 64\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:417 +msgid "" +"Not all the options available to *ipfw_nat* are described in the NAT section " +"of the man:ipfw[8] man page." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:421 +msgid "" +"Some of the options usable from man:natd[8] are available to *ipfw_nat*. " +"indexterm:[natd] indexterm:[ipfw_nat] These include:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:429 +#, no-wrap +msgid "" +"*redirect_port* _proto targetIP:targetPORT[-targetPORT]_\n" +" _[aliasIP:]aliasPORT[-aliasPORT]_\n" +" _[remoteIP[:remotePORT[-remotePORT]]]_\n" +"*redirect_proto* _proto localIP [publicIP [remoteIP]]_\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:431 +#, no-wrap +msgid "*redirect_address* _localIP publicIP_\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:434 +msgid "" +"indexterm:[redirect_port] indexterm:[redirect_proto] indexterm:" +"[redirect_address]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:437 +msgid "" +"The below options are used for Load Sharing NAT (*LSNAT*) as described in " +"link:https://www.rfc-editor.org/rfc/rfc2391.html[RFC 2391]. indexterm:" +"[LSNAT] indexterm:[RFC, 2391]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:443 +#, no-wrap +msgid "" +"*redirect_port* _proto targetIP:targetPORT[,targetIP:targetPORT[,...]]_\n" +" _[aliasIP:]aliasPORT [remoteIP[:remotePORT]]_\n" +"*redirect_address* _localIP[,localIP[,...]] publicIP_\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:446 +msgid "`LSNAT` is discussed in the next section." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:447 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:455 +#, no-wrap +msgid "Setting Up for LSNAT" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:451 +msgid "" +"indexterm:[LSNAT] This example uses the three VMs *external1*, *external2*, " +"and *external3* and pretends they are on the *_inside_* of the network; and " +"*internal* VM is on the *_outside_* of the network." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:453 +msgid "The figure below shows the architecture setup for working with LSNAT." +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:456 +#, no-wrap +msgid "Setting Up for LSNAT. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:456 +#, no-wrap +msgid "ipfw-nat075.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:459 +msgid "" +"As before, shutdown all virtual machines and rebuild the network from " +"scratch." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:461 +msgid "Use this command to set up the network bridge and tap architecture." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:465 +#, no-wrap +msgid "# *sudo /bin/sh mkbr.sh reset bridge0 tap4 tap5 bridge1 tap0 tap1 tap2 tap3*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:468 +msgid "indexterm:[mkbr.sh] indexterm:[runvm.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:470 +msgid "Note that the host interface is not needed for this example." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:472 +msgid "Restart the virtual machines with:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:476 +#, no-wrap +msgid "# */bin/sh runvm.sh firewall internal external1 external2 external3*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:479 +msgid "or start them up individually." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:482 +msgid "" +"Configure each virtual machine to ensure its network configuration matches " +"the above figure and test connectivity between adjacent systems with man:" +"ping[8]. indexterm:[ping]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:484 +msgid "" +"Throughout this section, remember that the \"external\" VMs are now " +"*internal* web servers load balancing between .10, .20, .30, and the " +"\"internal\" server VM is the *outside* host accessing the internal " +"webservers." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:486 +msgid "" +"On each *inside* VM the following commands are necessary to perform the " +"examples in this section:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:492 +#, no-wrap +msgid "" +"# *route delete default*\n" +"#\n" +"# *route add default 10.10.10.50*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:495 +msgid "On the *outside* VM perform these commands:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:501 +#, no-wrap +msgid "" +"# *route delete default*\n" +"#\n" +"# *route add default 198.51.100.50*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:504 +msgid "" +"Also, on each VM, edit the *nginx* [.filename]#index.html# page and insert a " +"line of text that has the VM name or IP address of the VM - something like " +"this:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:508 +#, no-wrap +msgid "File: */usr/local/www/nginx/index.html*:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:513 +#, no-wrap +msgid "" +"

Welcome to nginx!

\n" +"

If you see this page, the nginx web server is successfully installed and\n" +"working. Further configuration is required.

\n" +"#

This is VM EXTERNAL1

#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:516 +msgid "indexterm:[nginx]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:518 +msgid "and start *nginx* on each inside VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:527 +#, no-wrap +msgid "" +"# *service nginx onestart*\n" +"Performing sanity check on nginx configuration:\n" +"nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok\n" +"nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful\n" +"Starting nginx.\n" +"#\n" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:530 +#, no-wrap +msgid "LSNAT Setup Showing All VMs" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:531 +#, no-wrap +msgid "LSNAT Setup Showing All VMs. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:531 +#, no-wrap +msgid "ipfw-nat095.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:534 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:609 +msgid "indexterm:[LSNAT]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:537 +msgid "" +"With no *ipfw* loaded on the firewall, it should be possible to ping all " +"*inside* addresses (10.10.10.10, .20, .30) from the *outside* host " +"(198.51.100.20). And it should be possible to access each web server via:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:541 +#, no-wrap +msgid "# *lynx 203.0.113.10* # (or .20 or .30)\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:544 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:597 +msgid "indexterm:[lynx]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:545 +#, no-wrap +msgid "Setting up LSNAT- One address (10.10.10.10)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:548 +msgid "Begin with loading *ipfw* and *ipfw_nat* on the *firewall* VM" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:554 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"#\n" +"# *kldload ipfw_nat*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:560 +msgid "" +"The first configuration is similar to static NAT, though from the _outside_ " +"to the _inside_. The command redirects incoming traffic from the outside VM " +"sent to destination IP 3.3.3.3 to inside VM 10.10.10.10." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:565 +#, no-wrap +msgid "" +"# *ipfw nat 25 config redirect_addr 10.10.10.10 3.3.3.3*\n" +"ipfw nat 25 config redirect_addr 10.10.10.10 3.3.3.3\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:568 +msgid "Next create a ruleset that utilizes this NAT instance:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:579 +#, no-wrap +msgid "" +"# *ipfw add 50 check-state*\n" +"# *ipfw add 1000 nat 25 tcp from any to any*\n" +"#\n" +"# *ipfw list*\n" +"00050 check-state :default\n" +"01000 nat 25 tcp from any to any\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:585 +msgid "" +"Do not use the *setup* keyword on the *ipfw* rule referencing LSNAT. The " +"*setup* keyword causes the final ACK of the TCP 3-way handshake to be never " +"received and the connection is never established." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:588 +msgid "indexterm:[setup]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:590 +msgid "From the outside VM, access the web server using:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:594 +#, no-wrap +msgid "# *lynx 3.3.3.3*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:599 +msgid "brings up the web page on 10.10.10.10." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:601 +#, no-wrap +msgid "Accessing Nginx on 10.10.10.10 With LSNAT via 3.3.3.3" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:602 +#, no-wrap +msgid "Accessing Nginx on 10.10.10.10 With LSNAT via 3.3.3.3. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:602 +#, no-wrap +msgid "ipfw-nat100.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:605 +msgid "NAT with one address is working." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:606 +#, no-wrap +msgid "Engaging Multiple Hosts With LSNAT" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:611 +msgid "" +"Next, reconfigure the *nat 25* instance to utilize all of the inside hosts:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:615 +#, no-wrap +msgid "# *ipfw nat 25 config redirect_addr #10.10.10.10,10.10.10.20,10.10.10.30# 3.3.3.3*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:618 +msgid "indexterm:[keyword, redirect_addr]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:621 +msgid "" +"(Note that adding a modification to a NAT instance just overwrites the " +"existing instance. It does not create a new instance with the same number.)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:624 +msgid "" +"On the outside VM, running *lynx 3.3.3.3* repeatedly retrieves the home page " +"of each internal server - in round-robin fashion, without regard for any " +"network load, or server utilization. indexterm:[lynx]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:628 +msgid "In the lynx browser, reload the current page by pressing kbd:[Ctl+R]." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:635 +#, no-wrap +msgid "" +"# *ipfw nat 25 show config*\n" +"ipfw nat 25 config log redirect_addr 10.10.10.10,10.10.10.20,10.10.10.30 3.3.3.3\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:638 +msgid "" +"By adding a rule to redirect icmp traffic, both icmp and tcp will be load " +"shared across the firewall." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:648 +#, no-wrap +msgid "" +"# *ipfw add 2000 nat 25 icmp from any to any*\n" +"#\n" +"# *ipfw list*\n" +"00050 check-state :default\n" +"01000 nat 25 tcp from any to any\n" +"02000 nat 25 icmp from any to any\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:653 +msgid "" +"Test this by running *tcpdump -n -i em0* on each inside VM, and running " +"*ping -c 1 3.3.3.3* on the outside VM a few times. indexterm:[tcpdump] " +"indexterm:[ping] The incoming ping will hit each inside VM in turn." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:659 +msgid "" +"However, on running *ping 3.3.3.3*, the result is that these pings hit only " +"one internal VM. The reason is that the aliasing engine treats ICMP " +"differently from TCP and UDP. The aliasing engine recognizes the ICMP id " +"number, and if this number does not change, it uses the same alias. " +"indexterm:[aliasing] If the command *ping -c 1 3.3.3.3* is used repeatedly, " +"the ICMP id number changes, and this creates a new entry in the aliasing " +"database resulting in redirection to a different VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:664 +msgid "" +"It is common to want to balance the load across servers according to certain " +"characteristics such as system load. indexterm:[load balancing] This is " +"possible - manually - by reconfiguring the NAT statement and adding multiple " +"instances of the same host to give that host more traffic. Consider this " +"ruleset created with the Unix line continuation character '\\' to close the " +"space between successive IP addresses except for the last one and the alias " +"address:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:671 +#, no-wrap +msgid "" +"# *ipfw nat 25 config log redirect_addr* \\\n" +"*10.10.10.30,*\\\n" +"*10.10.10.20,10.10.10.20,*\\\n" +"*10.10.10.10,10.10.10.10,10.10.10.10,10.10.10.10 3.3.3.3*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:676 +msgid "" +"This configuration shifts the NAT load heavily toward 10.10.10.10 and " +"moderately toward 10.10.10.20, with 10.10.10.30 having a lot less traffic. " +"Repeat the above single ping example above to see the result. While this " +"works, it is a bit of a hack." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:678 +msgid "" +"It would be better to have a range assignment feature similar to the sparse " +"address feature already in *ipfw*, something like:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:683 +#, no-wrap +msgid "" +"# *ipfw nat 25 config redirect_addr 10.10.10.0/24{10,20-25,30-50} 3.3.3.3*\n" +"ipfw: unknown host 10.10.10.0/24{10\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:686 +msgid "but this feature does not work with LSNAT." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:692 +msgid "" +"However, it is possible to use the *prob* keyword to address load " +"balancing. indexterm:[prob] In a rule with the *prob* keyword, if the rule " +"matches *and* the probability is \"true\", the action of the rule is taken " +"and processing stops for that packet. If the rule matches, and the " +"probability is \"not true\", the action is not taken, and processing " +"continues with the next rule. Verify this with a simple test ruleset and " +"the *ucont.sh* shell rule from an external host." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:703 +#, no-wrap +msgid "" +"03000 prob 0.200000 allow udp from any to me 5656 // set probability to 20% chance of matching\n" +"04000 count udp from any to me // count how many were not chosen by rule 3000\n" +"05000 prob 0.400000 allow udp from any to me 5656 // set probability to 40% chance of matching\n" +"06000 count udp from any to me // count how many were not chosen by 3000 and 5000\n" +"07000 prob 0.999000 allow udp from any to me 5656 // set probability to 99.9% chance of matching\n" +"08000 count udp from any to me // count how many were not chosen by all 3 rules\n" +"09000 allow udp from any to me 5656 // unconditional matching\n" +"65535 deny ip from any to any // default rule deny\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:706 +msgid "After a run of 200 entries from *sh ucont.sh 5656 1* the counts are:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:717 +#, no-wrap +msgid "" +"03000 47 3314 prob 0.200000 allow udp from any to me 5656\n" +"04000 153 10776 count udp from any to me\n" +"05000 64 4505 prob 0.400000 allow udp from any to me 5656\n" +"06000 89 6271 count udp from any to me\n" +"07000 89 6271 prob 0.999000 allow udp from any to me 5656\n" +"08000 0 0 count udp from any to me\n" +"09000 0 0 allow udp from any to me 5656\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:722 +msgid "" +"From the above data, out of 200 packets sent from *ucont.sh*, 47 were " +"matched by rule 3000, but 153 were not matched (rule 4000). Then, 64 were " +"matched at rule 5000, but 89 were not matched. Finally, 89 where matched at " +"rule 7000." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:727 +msgid "" +"If there are some packets hitting the default deny rule (65535), delete the " +"host interface from the bridge and re-run the test. *ipfw* is then unlikely " +"to have any stray UDP packets hitting the default rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:731 +msgid "" +"While the above works for UDP, it does not work for TCP. The TCP 3-way " +"handshake is broken because some packets will match, but others will not." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:733 +#, no-wrap +msgid "*Other NAT Keywords*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:735 +msgid "" +"The other keywords in the NAT section of man:ipfw[8] are straightforward:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:738 +#, no-wrap +msgid "" +"*deny_in* : deny incoming packets\n" +"indexterm:[deny_in]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:740 +#, no-wrap +msgid "" +"*same_ports* : keep the same ports after redirection\n" +"indexterm:[same_ports]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:742 +#, no-wrap +msgid "" +"*reset* : clear the aliasing table when the address changes\n" +"indexterm:[reset]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:744 +#, no-wrap +msgid "" +"*reverse* : reverse the direction of the NAT\n" +"indexterm:[reverse]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:746 +#, no-wrap +msgid "" +"*proxy_only* : packet aliasing is not performed\n" +"indexterm:[proxy_only]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:748 +#, no-wrap +msgid "" +"*skip_global*\n" +"indexterm:[skip_global]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:750 +#, no-wrap +msgid "" +"*global*\n" +"indexterm:[global]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-nat/_index.adoc:752 +#, no-wrap +msgid "" +"*tablearg* : discussed in crossref:ipfw-rules[ipfw-rules-understanding-tablearg, Understanding the Word Tablearg]\n" +"indexterm:[tablearg]\n" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc @@ -0,0 +1,226 @@ +--- +title: Chapter 2. IPFW Operation +prev: books/ipfw-primer/ipfw-introduction +next: books/ipfw-primer/ipfw-rules +description: IPFW Operation +tags: ["firewall", "IPFW", "tools"] +showBookMenu: true +weight: 30 +path: "/books/ipfw-primer/ipfw-operation/" +--- + +[[ipfw-operation]] += IPFW Operation +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 2 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +So far, the initial lab setup should be that shown in the figure below except for IP addressing. +All the examples in this book use "Special Use Addresses" for both IPv4 and IPv6. +indexterm:[Special Use Addresses] +Address references used are described link:https://www.rfc-editor.org/rfc/rfc5737.html[here for IPv4 Addresses] (RFC 5737) and link:https://www.rfc-editor.org/rfc/rfc3849.html[here for IPv6 Addresses] (RFC 3849). +indexterm:[RFC, 5737] indexterm:[RFC, 3849] + +Configure both VMs to use the addresses shown in the figure below. +Once these addresses are in place on the VMs, it is unlikely that the VMs will be able to access sites on the Internet. +The *203.0.113.0/24* network is considered non-routable by Internet service providers and major telecom carriers on the Internet. +However, this does not really matter, since all the communications for this book are local to the VMs running on the FreeBSD host. +Bottom line - if the VMs need to access the Internet, leave them on DHCP, but for the examples in this book, use manual addressing as shown in the figure below. +[TIP] +==== +An easy, efficient way to rapidly change IP addresses is to edit [.filename]#/etc/rc.conf# and modify the address lines for the individual interfaces. +After saving the file, run *service netif restart* to restart the interfaces with the new addresses. +Check and reset the default route if needed. +==== + +[[ipfw-intro-simple-lab]] +.*external1*, and *firewall* VMs With Special Use Addresses +image::ipfw-operation017.png["*ipfw*, *external1*, and *firewall* VMs With Special Use addresses. Refer to paragraphs below."] + +Setup instructions for the example: + +[subs=+quotes] +---- +% *cd ~/ipfw-primer/ipfw/HOST_SCRIPTS* +% *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap1* +% */bin/sh runvm.sh firewall external1* +---- + +[[firewall-server-scripts]] +== Firewall Server Scripts + +To demonstrate the firewall capabilities of *ipfw*, the *firewall* runs one of four basic scripts. +Recall that these are located in [.filename]#/root/bin#: + +* *tserv.sh* (*userv.sh*): Script that opens one TCP (UDP) port and listens for incoming traffic. +indexterm:[tserv.sh] indexterm:[userv.sh] +* *tserv3.sh* (*userv3.sh*): Script that opens 3 TCP (UDP) ports and listens for incoming traffic. +indexterm:[tserv3.sh] indexterm:[userv3.sh] + +These scripts will listen for an incoming connection and print whatever is sent over during the connection. +When the connection is closed, the script will continue to listen for the next connection. + +These script provide the basic mechanism for receiving a TCP or UDP connection. +Once *ipfw* is running and populated with a ruleset, the effect each rule has on a connection can be shown. +indexterm:[ruleset] + +[[external-vm-scripts]] +== External VM Scripts + +Likewise, there are other basic scripts the *external1* (and later, *external2* and *external3*) VMs use for initiating or establishing communications with or through the *firewall* VM. +The TCP and UDP versions perform similarly: + +* *tcon.sh* (*ucon.sh*): Connect via TCP (or UDP). +indexterm:[tcon.sh] indexterm:[ucon.sh] +This script takes a single argument, a port number to use for the connection. +The external VM host can change the port number at each prompt. +If there is no script listening on the port on the firewall, the script will indicate a "connection refused" or timeout error. +* *tconr.sh* (*uconr.sh*): Connection takes a random port number and a sleep value. +indexterm:[tconr.sh] indexterm:[uconr.sh] +The script randomly selects one of three ports for its connection in a loop, controlled by the sleep value. +If there is a listener on the firewall active on the port, the connection succeeds - otherwise the connection is refused. +* *tcont.sh* (*ucont.sh*): Connection takes a port number and sleep value. +indexterm:[tcont.sh] indexterm:[ucont.sh] +The communication uses the same port in a loop, controlled by the sleep value. + +These are simple scripts, but they allow for independent activity by the *external* VMs, while the *firewall* VM admin creates and tests *ipfw* rulesets. +Most of the examples in the first part of this book can be done with just these scripts, so it is a good idea to become familiar with their operation. +Later scripts will use man:hping3[8] and man:iperf3[1], versatile tools used in network analysis. +indexterm:[hping3] indexterm:[iperf3] + +By default, the *external* VMs and *firewall* VM scripts work on ports `5656`, `5657`, and `5658`. +The randomized communication scripts also utilize port `5659`, but in most cases, since no services are listening on that port on the *firewall* VM, the connection fails. + +It is important to understanding the underlying network activity. +If Internet protocols, network traffic, monitoring, and similar topics are unfamiliar, there are a number of excellent books, white papers, and tutorials, many free over the Internet. +Check crossref:ipfw-appendix-c[appendix-c,Appendix C] for a modest selection. + +== Loading IPFW + +*ipfw* can be built into the FreeBSD kernel directly, or it can be loaded as a kernel module. +The *ipfw.ko* loadable kernel module is used for most of the examples in this book. +Load *ipfw* as root with the command: + +[subs=+quotes] +---- +# *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +---- + +indexterm:[module, ipfw] + +Notice the kernel display output - _“ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled”_. +This gives a quick summary of this host's *ipfw* capabilities. +The most important to note is _"default to deny"_ which indicates that, by default, the firewall has an immutable rule located at the end of the ruleset that denies all Internet Protocol (IP) traffic. +This rule depends on how the kernel was configured when it was built. +By default it is _"default to deny"_. +However, when working on a FreeBSD system where its provenance is unknown, use the *ipfw list* command to make sure: + +[subs=+quotes] +---- +# *ipfw list* +65535 deny ip from any to any +# +---- + +Note that this does not mean it denies all network traffic, only traffic that is based on the Internet Protocol (RFC 791), and all of its derivatives (TCP, UDP, ICMP, etc). +If a hacker had the capability to send and receive non-IP based traffic they could possibly still send and receive it. +The firewall administrator would need special rules to deny all traffic, similar to the example later in this book. + +To begin the next section, start with the *ipfw* firewall unloaded: + +[subs=+quotes] +---- +# *kldunload ipfw* +IP firewall unloaded +# +---- + +[TIP] +==== +Unloading (*kldunload ipfw*) and loading (*kldload ipfw*) the *ipfw* kernel module is a handy way of completely re-initializing *ipfw*. +This removes all *rules*, *sets*, *queues*, *pipes*, and other *ipfw* objects. +See man:kldload[8], man:kldunload[8], and man:kldstat[8] for details. +==== + +[[initial-firewall-setup]] +== Initial Firewall Setup + +This section introduces the operation of the scripts described above and demonstrates simple traffic filtering. + +In the first example, the firewall host runs `tserv.sh` (in [.filename]#/root/bin#) which opens TCP port 5656. +indexterm:[tserv.sh] + +[[ipfw-intro-simple-xmit]] +.Simple Transmit with No *ipfw* In Place +image::ipfw-introduction005.png["Simple Transmit With No *ipfw* In Place. Refer to paragraphs below."] + +The *external1* VM runs `tcon.sh`, which repetitively opens a TCP connection and sends data to the *firewall* VM. +indexterm:[tcon.sh] +Since there is no firewall in place, all TCP connections succeed. + +On the host machine, it is possible to run man:tcpdump[1] on the *bridge0* device to see the traffic in real time. +Shown below is one successful transfer, i.e there are no firewall rules preventing the connection. + +It follows the basic TCP connection sequence: 3-way handshake setup, send data, and close the connection: + +[[ipfw-intro-tcpdump]] +.tcpdump(1) of Bridge Traffic During Transfer +image::ipfw-introduction010.png["tcpdump(1) of Bridge Traffic During Transfer. Refer to paragraphs below."] + +Now load the *ipfw* firewall on the *firewall* VM and retry the communication. + +[subs=+quotes] +---- +# *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +# +# *ipfw list* +65535 deny ip from any to any +# +---- + +[[ipfw-intro-simple-xmit-with-ipfw]] +.Simple Transmit with Default Rule In Place +image::ipfw-introduction015.png["Simple Transmit With Default Rule In Place. Refer to paragraphs below."] + +No communications were successful - the connections time out because the *ipfw* firewall has denied traffic with the `default deny` rule as described above. +The *external1* VM host sends SYN packets to start the connection, but they never reach the *firewall* VM’s TCP service on port 5656. +The TCP 3-way handshake is never completed. + +These same techniques are used throughout this book. +They show how communications and data transfer operate and how firewall rules affect those communications. + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-operation/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-operation/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-operation/_index.po @@ -0,0 +1,431 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:1 +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:13 +#, no-wrap +msgid "IPFW Operation" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:1 +#, no-wrap +msgid "Chapter 2. IPFW Operation" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:56 +msgid "" +"So far, the initial lab setup should be that shown in the figure below " +"except for IP addressing. All the examples in this book use \"Special Use " +"Addresses\" for both IPv4 and IPv6. indexterm:[Special Use Addresses] " +"Address references used are described link:https://www.rfc-editor.org/rfc/" +"rfc5737.html[here for IPv4 Addresses] (RFC 5737) and link:https://www.rfc-" +"editor.org/rfc/rfc3849.html[here for IPv6 Addresses] (RFC 3849). indexterm:" +"[RFC, 5737] indexterm:[RFC, 3849]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:62 +msgid "" +"Configure both VMs to use the addresses shown. Once these addresses are in " +"place on the VMs (and the alias address on the FreeBSD host), it is unlikely " +"that the VMs will be able to access sites on the Internet. The " +"*203.0.113.0/24* network is considered non-routable by Internet service " +"providers and major telecom carriers on the Internet. However, this does " +"not really matter, since all the communications for this book are local to " +"the VMs running on the FreeBSD host. Bottom line - if the VMs need to " +"access the Internet, leave them on DHCP, but for the examples in this book, " +"use manual addressing as shown in the figure below." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:64 +#, no-wrap +msgid "*ipfw*, *external1*, and *firewall* VMs With Special Use Addresses" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:65 +#, no-wrap +msgid "*ipfw*, *external1*, and *firewall* VMs With Special Use addresses. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:65 +#, no-wrap +msgid "ipfw-operation017.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:68 +msgid "Scripts used by the two VMs are discussed in the next section." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:70 +#, no-wrap +msgid "Firewall Server Scripts" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:75 +msgid "" +"To demonstrate the firewall capabilities of *ipfw*, the *firewall* VM runs " +"certain scripts that open local UDP and TCP ports using man:ncat[1] for TCP " +"operation, and man:nc[1] for UDP operation. While the commands perform " +"similar functions, the *nc* version on the base system is the one that " +"performs best for receiving UDP traffic as it supports the keep-open option " +"(-k). indexterm:[nc]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:78 +msgid "" +"The *firewall* VM runs one of four basic scripts. Recall that these are " +"located in [.filename]#/root/bin#:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:81 +#, no-wrap +msgid "" +"*tserv.sh* (*userv.sh*): Script that opens one TCP (UDP) port and listens for incoming traffic.\n" +"indexterm:[tserv.sh] indexterm:[userv.sh]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:83 +#, no-wrap +msgid "" +"*tserv3.sh* (*userv3.sh*): Script that opens 3 TCP (UDP) ports and listens for incoming traffic.\n" +"indexterm:[tserv3.sh] indexterm:[userv3.sh]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:86 +msgid "" +"These scripts will listen for an incoming connection and print whatever is " +"sent over during the connection. When the connection is closed, the script " +"will continue to listen for the next connection." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:90 +msgid "" +"These script provide the basic mechanism for receiving a TCP or UDP " +"connection. Once *ipfw* is running and populated with a ruleset, the effect " +"each rule has on a connection can be shown. indexterm:[ruleset]" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:92 +#, no-wrap +msgid "External VM Scripts" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:96 +msgid "" +"Likewise, there are other basic scripts the *external1* (and later, " +"*external2* and *external3*) VMs use for initiating or establishing " +"communications with or through the *firewall* VM. The TCP and UDP versions " +"perform similarly:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:102 +#, no-wrap +msgid "" +"*tcon.sh* (*ucon.sh*): Connect via TCP (or UDP).\n" +"indexterm:[tcon.sh] indexterm:[ucon.sh]\n" +"This script takes a single argument, a port number to use for the connection.\n" +"The external VM host can change the port number at each prompt.\n" +"If there is no script listening on the port on the firewall, the script will indicate a \"connection refused\" or timeout error.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:106 +#, no-wrap +msgid "" +"*tconr.sh* (*uconr.sh*): Connection takes a random port number and a sleep value.\n" +"indexterm:[tconr.sh] indexterm:[uconr.sh]\n" +"The script randomly selects one of three ports for its connection in a loop, controlled by the sleep value.\n" +"If there is a listener on the firewall active on the port, the connection succeeds - otherwise the connection is refused.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:109 +#, no-wrap +msgid "" +"*tcont.sh* (*ucont.sh*): Connection takes a port number and sleep value.\n" +"indexterm:[tcont.sh] indexterm:[ucont.sh]\n" +"The communication uses the same port in a loop, controlled by the sleep value.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:114 +msgid "" +"These are simple scripts, but they allow for independent activity by the " +"*external* VMs, while the *firewall* VM admin creates and tests *ipfw* " +"rulesets. Most of the examples in the first part of this book can be done " +"with just these scripts, so it is a good idea to become familiar with their " +"operation. Later scripts will use man:hping3[8] and man:iperf3[1], " +"versatile tools used in network analysis. indexterm:[hping3] indexterm:" +"[iperf3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:117 +msgid "" +"By default, the *external* VMs and *firewall* VM scripts work on ports " +"`5656`, `5657`, and `5658`. The randomized communication scripts also " +"utilize port `5659`, but since no services are listening on that port on the " +"*firewall* VM, the connection fails." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:121 +msgid "" +"It is important to understanding the underlying network activity. If " +"Internet protocols, network traffic, monitoring, and similar topics are " +"unfamiliar, there are a number of excellent books, white papers, and " +"tutorials, many free over the Internet. Check crossref:ipfw-appendix-" +"c[appendix-c,Appendix C] for a modest selection." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:122 +#, no-wrap +msgid "Loading IPFW" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:127 +#, no-wrap +msgid "" +"*ipfw* can be built into the FreeBSD kernel directly, or it can be loaded as a kernel module.\n" +"The *ipfw.ko* loadable kernel module is used for most of the examples in this book.\n" +"Load *ipfw* as root with the command:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:132 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:135 +msgid "indexterm:[module, ipfw]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:142 +msgid "" +"Notice the kernel display output - _“ipfw2 (+ipv6) initialized, divert " +"loadable, nat loadable, default to deny, logging disabled”_. This gives a " +"quick summary of this host's *ipfw* capabilities. The most important to " +"note is _\"default to deny\"_ which indicates that, by default, the firewall " +"has an immutable rule located at the end of the ruleset that denies all " +"Internet Protocol (IP) traffic. This rule depends on how the kernel was " +"configured when it was built. By default it is _\"default to deny\"_. " +"However, when working on a FreeBSD system where its provenance is unknown, " +"use the *ipfw list* command to make sure:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:148 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:153 +msgid "" +"Note that this does not mean it denies all network traffic, only traffic " +"that is based on the Internet Protocol (RFC 791), and all of its derivatives " +"(TCP, UDP, ICMP, etc). If a hacker had the capability to send and receive " +"non-IP based traffic they could possibly still send and receive it. The " +"firewall administrator would need special rules to deny all traffic, similar " +"to the example later in this book." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:155 +msgid "To begin the next section, start with the *ipfw* firewall unloaded:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:161 +#, no-wrap +msgid "" +"# *kldunload ipfw*\n" +"IP firewall unloaded\n" +"#\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:168 +msgid "" +"Unloading (# *kldunload ipfw*) and loading (# *kldload ipfw*) the *ipfw* " +"kernel module is a handy way of completely re-initializing *ipfw*. This " +"removes all *rules*, *sets*, *queues*, *pipes*, and other *ipfw* " +"operations. See man:kldload[8], man:kldunload[8], and man:kldstat[8] for " +"details." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:171 +#, no-wrap +msgid "Initial Firewall Setup" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:174 +msgid "" +"This section introduces the operation of the scripts described above and " +"demonstrates simple traffic filtering." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:177 +msgid "" +"In the first example, the firewall host runs `tserv.sh` which opens TCP port " +"5656. indexterm:[tserv.sh]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:179 +#, no-wrap +msgid "Simple Transmit with No *ipfw* In Place" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:180 +#, no-wrap +msgid "Simple Transmit With No *ipfw* In Place. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:180 +#, no-wrap +msgid "ipfw-introduction005.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:185 +msgid "" +"The *external1* VM runs `tcon.sh`, which repetitively opens a TCP connection " +"and sends data to the *firewall* VM. indexterm:[tcon.sh] Since there is no " +"firewall in place, all TCP connections succeed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:188 +msgid "" +"On the host machine, it is possible to run man:tcpdump[1] on the *bridge0* " +"device to see the traffic in real time. Shown below is one successful " +"transfer, i.e there are no firewall rules preventing the connection." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:190 +msgid "" +"It follows the basic TCP connection sequence: 3-way handshake setup, send " +"data, and close the connection:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:192 +#, no-wrap +msgid "tcpdump(1) of Bridge Traffic During Transfer" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:193 +#, no-wrap +msgid "tcpdump(1) of Bridge Traffic During Transfer. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:193 +#, no-wrap +msgid "ipfw-introduction010.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:196 +msgid "" +"Now load the *ipfw* firewall on the *firewall* VM and retry the " +"communication." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:205 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled\n" +"#\n" +"# *ipfw list*\n" +"65535 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:208 +#, no-wrap +msgid "Simple Transmit with Default Rule In Place" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:209 +#, no-wrap +msgid "Simple Transmit With Default Rule In Place. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:209 +#, no-wrap +msgid "ipfw-introduction015.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:214 +msgid "" +"No communications were successful - the connections time out because the " +"*ipfw* firewall has denied traffic with the `default deny` rule as described " +"above. The *external1* VM host sends SYN packets to start the connection, " +"but they never reach the *firewall* VM’s TCP service on port 5656. The TCP " +"3-way handshake is never completed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-operation/_index.adoc:217 +msgid "" +"These same techniques are used throughout this book. They show how " +"communications and data transfer operate and how firewall rules affect those " +"communications." +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc @@ -0,0 +1,981 @@ +--- +title: Chapter 7. Other Keywords +prev: books/ipfw-primer/ipfw-ipv6-nat +next: books/ipfw-primer/ipfw-appendix-a +description: IPFW See Also +tags: ["IPFW", "firewall", "references"] +showBookMenu: true +weight: 80 +path: "/books/ipfw-primer/ipfw-other-keywords/" +--- + +[[other-keywords]] += Other Keywords +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 7 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +This section covers some other lesser used keywords. + +== abort / abort6 + +indexterm:[abort] indexterm:[abort6] + +The *abort* and *abort6* keywords interrupt the data stream between two endpoints. +The effect of this keyword, is similar to the *reset* keyword, but there are important differences. + +[[ipfw-abort-keyword]] +.Abort and abort6 keywords +image::ipfw-other-keywords010.png["Abort and abort6 keywords. Refer to paragraphs below."] + +The above figure shows the effect of inserting the *firewall* rule: + +[subs=+quotes] +---- +# *ipfw add 50 abort tcp from 203.0.113.30 to me* +---- + +Unlike the *reset* keyword, there is no packet sent from the firewall to the source. +What happens is that *ipfw* just starts dropping packets that match the rule. +Since there are no more replies coming from the destination (here the firewall itself), the source endpoint issues retransmissions over and over. +Eventually the source concludes that the connection is irrevocably broken and it closes the connection. + +[NOTE] +==== +In the rule above, *_all_* TCP connections will be interrupted between the two systems. +==== + +[TIP] +==== +In a TCP connection, *ipfw* will use dynamic rules if a *check-state* rule is already in place. +If this is the case, issue the *abort* rule at a rule number *_before_* the check-state rule. +Otherwise, it will have no effect. +==== + +== mark / setmark + +indexterm:[mark] indexterm:[setmark] + +The *setmark* keyword functions similar to the *tag* keyword. +If the packet matches the rule, *ipfw* applies a 32-bit identifier to the packet. +This identifier (the "mark") is held with the packet internally inside *ipfw*. +It is not sent with the packet on the wire and is not visible to any network monitoring from tools like man:tcpdump[1] or man:wireshark[1]. + +Like *tags*, a *mark* can be used as another filtering device with other *ipfw* rules to do policy based routing or filtering. +Note that only one mark can be applied at a time. + +A big advantage of marks over tags are their ability to be matched as a lookup key in a table. +Also, a mark can have a bitmask applied to it. + +To explore *mark* and *setmark*, use the architecture of Simple NAT shown in crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT]. +Begin by creating the network with the *mkbr.sh* script and starting the VMs with the *runvm.sh* script shown in crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT]. +indexterm:[mkbr.sh] + +[subs=+quotes] +---- +# *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5* +# */bin/sh runvm.sh firewall external1 internal* +---- +indexterm:[mkbr.sh] + +Assign the IP addresses as shown, and ensure all VMs have connectivity with adjacent systems. + +On the *internal* VM, start up the *userv.sh* script with port number 5656. +indexterm:[userv.sh] +Then, on the *external1* VM, start up the *ucont.sh* server with the same port and a time value of 1 second. +With no *ipfw* module loaded, the communications should succeed. + +[TIP] +==== +It may be necessary to examine the *ucont.sh* script and assign the correct address for the connection. +==== + +indexterm:[ucont.sh] + +Before placing a *setmark* value on a packet, load the *ipfw* module and redirect the output of the *ipfw* log by setting the sysctl to log to syslog: +indexterm:[syslog] + +[subs=+quotes] +---- +# *kldload ipfw* +# *sysctl net.inet.ip.fw.verbose=1* +---- + +indexterm:[sysctl, net.inet.ip.fw.verbose] + +Now insert the following firewall rules and examine the log file [.filename]#/var/log/security#: +indexterm:[log file] + +[subs=+quotes] +---- + +# *ipfw add 1000 allow log udp from any to 10.10.10.20 dst-port 5656* +01000 allow log udp from any to 10.10.10.20 5656 +# +# *tail -f /var/log/security* +Dec 29 22:32:33 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:30463 10.10.10.20:5656 in via em1 +Dec 29 22:32:33 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:30463 10.10.10.20:5656 out via em0 +Dec 29 22:32:36 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:24588 10.10.10.20:5656 in via em1 +Dec 29 22:32:36 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:24588 10.10.10.20:5656 out via em0 +---- + +Now add the following rule to apply the *mark* value of 20 (decimal) and observe the change in the logs: +indexterm:[mark] indexterm:[setmark] + +[subs=+quotes] +---- +# *ipfw add 500 setmark 20 log udp from any to 10.10.10.20 dst-port 5656* +00500 setmark 0x14 log udp from any to 10.10.10.20 5656 +# +# *tail -f /var/log/security* +Dec 29 22:41:20 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:27955 10.10.10.20:5656 in via em1 +Dec 29 22:41:20 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:27955 10.10.10.20:5656 out via em0 +Dec 29 22:41:23 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:37423 10.10.10.20:5656 in via em1 +Dec 29 22:41:23 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:37423 10.10.10.20:5656 out via em0 +Dec 29 22:41:25 firewall kernel: ipfw: #500 SetMark 0x14 UDP 203.0.113.10:45176 10.10.10.20:5656 in via em1# +Dec 29 22:41:25 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:45176 10.10.10.20:5656 mark:0x14 in via em1 +Dec 29 22:41:25 firewall kernel: ipfw: #500 SetMark 0x14 UDP 203.0.113.10:45176 10.10.10.20:5656 out via em0# +Dec 29 22:41:25 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:45176 10.10.10.20:5656 mark:0x14 out via em0 +Dec 29 22:41:27 firewall kernel: ipfw: #500 SetMark 0x14 UDP 203.0.113.10:21444 10.10.10.20:5656 in via em1# +Dec 29 22:41:27 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:21444 10.10.10.20:5656 mark:0x14 in via em1 +---- + +== NPTv6 + +indexterm:[NPTv6] + +IPv6-to-IPv6 Network Prefix Translation (NPTv6) is the process of translating IPv6 header source and destination addresses. +Functionally, it is similar to the more well understood Network Address Translation, but without the need to maintain state. +It is only the IPv6 source and destination addresses that are translated. +The idea here is to allow an edge network to have its own independent addressing scheme while being able to exchange IPv6 traffic with external IPv6 networks through the use of an NPTv6 Translator + +link:https://www.rfc-editor.org/rfc/rfc6296.html[RFC 6296] is the definitive document on NPTv6. +indexterm:[RFC, 6296] +The example in this section is taken from Sections 2.1 of that document. + +The architecture for these examples is based on Simple NAT as in the previous section. + +=== NPTv6 Setup + +Use the setup instructions shown in crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT] but use the IPv6 addressing as shown below: + +[[ipfw-nptv6-keyword]] +.NPTv6 Simple Case +image::ipfw-other-keywords100.png["NPTv6 Simple Case. Refer to paragraphs below."] + +At first glance, this appears to be a simple IPv6 forwarding example. +However in this case, *NPTv6* changes the actual packet source and destination addresses, so no forwarding is needed. + +man:ipfw[8] explains the syntax of the NPTv6 command and options, but there are a number of details that need to be set up correctly. +Use the following as a guide: + +[subs=+quotes] +---- +On the FreeBSD host: + +$ *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5* +$ */bin/sh runvm.sh external1 firewall internal* + +Ensure all IPv6 addresses on all VMs are set up correctly. + +On the *firewall* VM: + +# *kldunload ipfw_nptv6* +# *kldunload ipfw* + +# *kldload ipfw* +# *kldload ipfw_nptv6* + +# *sysctl net.inet.ip.fw.one_pass=0* +# *sysctl net.inet.ip.fw.verbose=1* + +# *ipfw -q flush* + +# Set up the NPTv6 instance. +# *ipfw nptv6 foo create int_prefix fd01:0203:0405:: ext_prefix 2001:0db8:0001:: prefixlen 48* + +# Rules for nptv6 +# *ipfw add 500 allow log ipv6-icmp from any to any icmp6types 135,136 // allow neighbor solicitation +# *ipfw add 2000 nptv6 foo log ip6 from fd01:0203:0405::/48 to any* +# *ipfw add 3000 allow ip6 from any to any* +---- + +indexterm:[bridge] indexterm:[tap] indexterm:[mkbr.sh] indexterm:[runvm.sh] indexterm:[module, ipfw] indexterm:[module, ipfw_nptv6] indexterm:[sysctl, net.inet.ip.fw.one_pass] indexterm:[sysctl, net.inet.ip.fw.verbose] + +As noted in man:ipfw[8], the sysctl `net.inet6.ip6.forwarding=1` must be applied or NPTv6 will silently stop working. +indexterm:[sysctl, net.inet6.ip6.forwarding] + +=== NPTv6 Testing + +Set up a UDP listener on the *external1* VM. +Using the *userv.sh* (and its *ucon.sh* partner) is possible, but that would require editing the scripts to set up an IPv6 address. +Try this method instead: + +[subs=+quotes] +---- +On the *external1* VM: +# Listen for a UDP packet +$ *ncat -l -k -u -6 2001:0db8:0001::10 5656* + +On the *internal* VM: +# Set up the default route for IPv6 +# *route -6 add default fd01:0203:0405::0050* +# +# Send the desired UDP packet. +$ *echo "testing123" | ncat -6 -u 2001:0db8:0001::10 5656* +---- + +indexterm:[ncat] + +In the setup section above, logging to `syslogd` was set up, so the results can be seen by examining the tail end of [.filename]#/var/log/security#: +indexterm:[syslogd] + +[subs=+quotes] +---- +Dec 31 19:51:44 firewall kernel: ipfw: 2000 Eaction nptv6 UDP [fd01:203:405::20]:52451 [2001:db8:1::10]:5656 in via em0 +---- + +The output of a `tcpdump` on *external1* shows: + +[subs=+quotes] +---- +root@external1:~ # tcpdump -n -i em0 -X "udp" +tcpdump: verbose output suppressed, use -v[v]... for full protocol decode +listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +19:51:43.827543 IP6 #2001:db8:1:d54f::20.52451# > 2001:db8:1::10.5656: UDP, length 11 + 0x0000: 600a 145a 0013 113f 2001 0db8 0001 d54f `..Z...?.......O + 0x0010: 0000 0000 0000 0020 2001 0db8 0001 0000 ................ + 0x0020: 0000 0000 0000 0010 cce3 1618 0013 f72b ...............+ + 0x0030: 7465 7374 696e 6731 3233 0a testing123. +---- + +indexterm:[tcpdump] + +The highlighted section shows the effect of the NPTv6 translation. +indexterm:[NPTv6] +(See link:https://www.rfc-editor.org/rfc/rfc6296.html[RFC 6296], Section 3, for details.) +indexterm:[RFC, 6296] + +== ipttl + +indexterm:[ipttl] + +The *ipttl* (Time to Live or TTL) keyword identifies packets that have specific TTL characteristics. +man:ipfw[8] notes that the *ipttl* keyword will accept a single value, a list of values, or a range of values, in the same syntax as that used for the *ports* keyword. +(Recall the discussion of lists and ranges in the crossref:ipfw-rules[ipfw-rules-numbering-notes, Notes on Rule Numbering].) + +*ipttl* is one of a number of *ipfw* keywords that work on individual fields of packets flowing through the firewall. +Similar keywords include *ipid*, *iplen*, *ipprecedence*, etc. +The *ipttl* keyword controls the lifetime of the packet on the network (see below). +indexterm:[ipid] indexterm:[iplen] indexterm:[ipprecedence] + +=== ipttl Setup + +Use the setup instructions shown in crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT] with IPv4 addressing, not IPv6. + +Also, this example will use the *hping3* command. +indexterm:[hping3] +(To downloaded the *hping3* package, reset the *internal* VM for access to the Internet, and download the package with *pkg install hping3*. +Remember to reset for Simple NAT IP addressing for this example.) + +Refer to man:hping3[8] for details. + +[subs=+quotes] +---- +On the *external1* VM: + +# Listen for a UDP packet +# *ncat -l -k -u 203.0.113.10 5656* + +On the *internal* VM: + +# Send the desired UDP packet. +Now, deliberately set the initial TTL to 13. +# *hping3 --sign "test for ttl 13" --count 1 --udp --ttl 13 --destport 5656 203.0.113.10* +---- + +indexterm:[ncat] indexterm:[hping3] + +Without *ipfw* in place, the result should be similar to: + +[subs=+quotes] +---- +root@external1:~ # tcpdump -n -i em0 -X -vv "udp" +tcpdump: listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +14:49:16.658160 IP (tos 0x0, #ttl 12#, id 6642, offset 0, flags [none], proto UDP (17), length 43) + 10.10.10.20.2472 > 203.0.113.10.5656: [udp sum ok] UDP, length 15 + 0x0000: 4500 002b 19f2 0000 0c11 44a8 0a0a 0a14 E..+......D..... + 0x0010: cb00 710a 09a8 1618 0017 3013 7465 7374 ..q.......0.test + 0x0020: 2066 6f72 2074 746c 2031 3300 0000 .for.ttl.13... +---- + +The IP Time to Live option was set up to prevent IP packets from bouncing around the Internet forever. +link:https://www.ietf.org/rfc/rfc791.txt[RFC 791] initially intended that the value would be considered an actual time value (number of seconds) and that each module processing the packet would subtract processing time from the initial value. +indexterm:[RFC, 791] +This was later changed to an integer identifying a "hop count" where the initial value (now 64) is decremented by every router or gateway or forwarding device, such as a firewall. +indexterm:[ttl] + +In this case the *firewall* VM, even though it is not running firewall software, is still a 'forwarding device' and decrements the count as it forwards the packet. + +=== ipttl Testing + +To examine the *ipttl* keyword follow this example: + +[subs=+quotes] +---- +# *kldload ipfw* +# *sysctl net.inet.ip.fw.verbose=1* + +# Count all packets as the flow through +# *ipfw add 800 count ip from any to any* + +# Count all packets with TTL of exactly 13 as they enter em0. +# *ipfw add 900 count ip from any to any ipttl 13* + +# Allow and log packets with TTL of exactly 13 as they enter em0. +# *ipfw add 1000 allow log udp from any to any ipttl 13* + +# Just before the packet exits, the IP stack decrements the ttl, +# so the following rule is also needed for the packet to exit out em1. +# *ipfw add 1050 allow log udp from any to any ipttl 12* + +# Count any other ip packets after the ipttl rule +# *ipfw add 1100 count ip from any to any* +---- + +indexterm:[sysctl, net.inet.ip.fw.verbose] indexterm:[ipttl] + +Below is a sample run of *ncat* and *hping3* commands to test the above rules: + +[subs=+quotes] +---- +# *echo "UDP with default TTL" | ncat -u 203.0.113.10 5656* +# *echo "UDP with default TTL" | ncat -u 203.0.113.10 5656* + +# *hping3 --sign "UDP with TTL=13" --count 1 --udp --ttl 13 --destport 5656 203.0.113.10* +# *hping3 --sign "UDP with TTL=13" --count 1 --udp --ttl 13 --destport 5656 203.0.113.10* +---- + +The results show the first two packets with default TTL values (64) were not passed by the firewall. +The third and fourth packets were passed. +The traces below show the input packet in interface *em0* with ttl 13, and the output packet on *em1* with ttl 12. + +[subs=+quotes] +---- +# *tcpdump -n -i em0 -X -vvv "udp"* +tcpdump: listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes +03:26:42.875634 IP (tos 0x0, #ttl 13#, id 17385, offset 0, flags [none], proto UDP (17), length 43) + 10.10.10.20.1648 > 203.0.113.10.5656: [udp sum ok] UDP, length 15 + 0x0000: 4500 002b 43e9 0000 0c11 1ab1 0a0a 0a14 E..+C........... + 0x0010: cb00 710a 0670 1618 0017 1d07 5544 5020 ..q..p......UDP. + 0x0020: 7769 7468 2054 544c 3d31 3300 0000 with.TTL=13... +# +# +# *tcpdump -n -i em1 -X -vvv "udp"* +tcpdump: listening on em1, link-type EN10MB (Ethernet), snapshot length 262144 bytes +03:27:37.903863 IP (tos 0x0, #ttl 12#, id 33936, offset 0, flags [none], proto UDP (17), length 43) + 10.10.10.20.2539 > 203.0.113.10.5656: [udp sum ok] UDP, length 15 + 0x0000: 4500 002b 8490 0000 0c11 da09 0a0a 0a14 E..+............ + 0x0010: cb00 710a 09eb 1618 0017 198c 5544 5020 ..q.........UDP. + 0x0020: 7769 7468 2054 544c 3d31 3300 0000 with.TTL=13... +---- +indexterm:[ncat] indexterm:[hping3] indexterm:[ttl] indexterm:[tcpdump] + +== tcpdatalen + +indexterm:[tcpdatalen] + +The *tcpdatalen* keyword is one of several related keywords: + +* *tcpack*, *tcpdatalen*, *tcpflags*, *tcpmss*, *tcpseq*, *tcpwin*, *tcpoptions* +indexterm:[tcpack] indexterm:[tcpflags] indexterm:[tcpmss] indexterm:[tcpseq] indexterm:[tcpwin] indexterm:[tcpoptions] + +These keywords are not often used. + +However, there is one very important use case. +From time to time, an Internet worm - a malicious packet that gets resent to all local and remote hosts matching some criteria - makes its way onto the Internet. +Quick thinking network security administrators can sometimes identify a unique characteristic of these malicious packets such as all packets having the same length - akin to *tcpdatalen*, or a certain set of *tcpoptions*. + +In this example, the *firewall* VM is running the *tserv.sh 5656* script. +indexterm:[tserv.sh] + +[TIP] +==== +It may be necessary to edit the *tserv.sh* script to listen on the correct interface (em1) for this example. +==== + +The example below, using the crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT] setup and addressing, configures *ipfw* to deny all packets having a TCP data length of a certain value range. +But, it also allows the completion of the TCP 3-way handshake. +When the handshake is completed, one of these ranges will cause the malicious packet to be denied. +Keep in mind, this is the length of the TCP data payload, not the overall length of the packet. + +[subs=+quotes] +---- +# *ipfw -q flush* +# *ipfw add 10 deny tcp from any to me tcpdatalen 10-19* +# *ipfw add 20 deny tcp from any to me tcpdatalen 20-29* +# *ipfw add 30 deny tcp from any to me tcpdatalen 30-39* +# *ipfw add 40 deny tcp from any to me tcpdatalen 40-49* +# *ipfw add 50 deny tcp from any to me tcpdatalen 50-59* +# *ipfw add 60 deny tcp from any to me tcpdatalen 60-69* +# *ipfw add 70 deny tcp from any to me tcpdatalen 70-79* +# *ipfw add 80 deny tcp from any to me tcpdatalen 80-89* +# *ipfw add 90 deny tcp from any to me tcpdatalen 90-99* +# *ipfw add 500 check-state* +# *ipfw add 1000 allow tcp from any to any 5656 setup keep-state* +# +# *ipfw show* +00010 0 0 deny log tcp from any to me tcpdatalen 10-19 +00020 0 0 deny log tcp from any to me tcpdatalen 20-29 +00030 0 0 deny log tcp from any to me tcpdatalen 30-39 +00040 0 0 deny log tcp from any to me tcpdatalen 40-49 +00050 0 0 deny log tcp from any to me tcpdatalen 50-59 +00060 0 0 deny log tcp from any to me tcpdatalen 60-69 +00070 0 0 deny log tcp from any to me tcpdatalen 70-79 +00080 0 0 deny log tcp from any to me tcpdatalen 80-89 +00090 0 0 deny log tcp from any to me tcpdatalen 90-99 +00500 0 0 check-state :default +01000 0 0 allow log tcp from any to any setup keep-state :default +65535 0 0 deny ip from any to any +---- + +And a test using *ncat* directly from *external1*: + +[subs=+quotes] +---- +# *echo "1234567890123456789012345678901234" | ncat 203.0.113.50 5656* +---- + +indexterm:[ncat] + +The TCP 3-way handshake completes, but the packet containing the data payload is stopped by rule 30 as shown below: + +[subs=+quotes] +---- +# *ipfw show* +00010 0 0 deny log tcp from any to me tcpdatalen 10-19 +00020 0 0 deny log tcp from any to me tcpdatalen 20-29 +00030 13 1066 deny log tcp from any to me tcpdatalen 30-39 +00040 0 0 deny log tcp from any to me tcpdatalen 40-49 +00050 0 0 deny log tcp from any to me tcpdatalen 50-59 +00060 0 0 deny log tcp from any to me tcpdatalen 60-69 +00070 0 0 deny log tcp from any to me tcpdatalen 70-79 +00080 0 0 deny log tcp from any to me tcpdatalen 80-89 +00090 0 0 deny log tcp from any to me tcpdatalen 90-99 +00500 0 0 check-state :default +01000 8 420 allow log tcp from any to any 5656 setup keep-state :default +65535 0 0 deny ip from any to any +---- + +The reason for the excessive number of packets denied is TCP retransmission trying to account for the dropped packet as shown in the man:wireshark[1] trace below. + +[[ipfw-tcpdatalen-keyword]] +.Denying Packet Based on TCP Data Length +image::ipfw-other-keywords020.png["Denying Packets Based on TCP Data Length. Refer to paragraphs below."] + +Eventually TCP gives up and shuts down the connection. + +== verrevpath / versrcreach / antispoof + +indexterm:[verrevpath] indexterm:[versrcreach] indexterm:[antispoof] + +These keywords all work to determine if an incoming packet is legitimate. + +As noted in man:ipfw[8], *verrevpath* ("verify reverse path") looks up the incoming packet's source address in the routing table. + +Quoting: +_"If the interface on which the packet entered the system matches the outgoing interface for the route, the packet matches. +If the interfaces do not match up, the packet does not match. +All outgoing packets or packets with no incoming interface match."_ + + +[subs=+quotes] +---- +Setting up on the FreeBSD host: + +% *cd ~/ipfw-primer/ipfw/HOST_SCRIPTS* +% *sudo /bin/sh mkbr.sh reset bridge0 tap0 tap5 bridge1 tap4 tap1* +% */bin/sh runvm.sh external1 firewall internal* +---- + +Consider the figure below (same as Simple NAT): + +[[ipfw-antispoofall-keyword]] +.verrevpath Example +image::ipfw-other-keywords030.png["verrevpath Example. Refer to paragraphs below."] + +In this figure, the firewall has interface *em0* directly connected to the `10.10.10.0/24` network and the *em1* interface directly connected to the `203.0.113.0/24` network. + +The *firewall* VM interfaces and routing table are shown in the text below: + +[subs=+quotes] +---- +root@firewall:~ # *ifconfig em0* +em0: flags=1008843 metric 0 mtu 1500 + options=48525bb + ether 02:49:50:46:57:41 + inet #10.10.10.50# netmask 0xffffff00 broadcast 10.10.10.255 + media: Ethernet autoselect (1000baseT ) + status: active + nd6 options=29 +root@firewall:~ # +root@firewall:~ # *ifconfig em1* +em1: flags=1008843 metric 0 mtu 1500 + options=48525bb + ether 02:49:50:46:57:42 + inet #203.0.113.50# netmask 0xffffff00 broadcast 203.0.113.255 + media: Ethernet autoselect (1000baseT ) + status: active + nd6 options=29 +root@firewall:~ # +root@firewall:~ # *netstat -rn* +Routing tables + +Internet: +Destination Gateway Flags Netif Expire +#10.10.10.0/24 link#1 U em0# +#10.10.10.50 link#3 UHS lo0# +127.0.0.1 link#3 UH lo0 +#203.0.113.0/24 link#2 U em1# +#203.0.113.50 link#3 UHS lo0# + +Internet6: +Destination Gateway Flags Netif Expire +::/96 link#3 URS lo0 +::1 link#3 UHS lo0 +::ffff:0.0.0.0/96 link#3 URS lo0 +fe80::%lo0/10 link#3 URS lo0 +fe80::%lo0/64 link#3 U lo0 +fe80::1%lo0 link#3 UHS lo0 +ff02::/16 link#3 URS lo0 +root@firewall:~ # +---- + +If a packet came in on the *em0* interface with a source address that was not in the `10.10.10.0/24` network, the above quote says the packet should be dropped. + +The following example tests this with the *ncat* program which has an option to set the source IP. +indexterm:[ncat] + +First, set up *ipfw* on the *firewall* VM to allow any UDP packets as shown. + +Then, set up the *firewall* VM to run *sh userv.sh 5656*, the service to receive UDP packets on the identified port. +Next, send one packet from the *internal* VM with *echo "hello from internal VM" | ncat -u 10.10.10.50 5656*. +indexterm:[userv.sh] + +[subs=+quotes] +---- +root@firewall:~/bin # *ipfw add 1000 allow udp from any to me verrevpath* +01000 allow udp from any to me verrevpath +root@firewall:~/bin # +root@firewall:~/bin # *ipfw show* +01000 0 0 allow udp from any to me verrevpath +65535 0 0 deny ip from any to any +root@firewall:~/bin # +root@firewall:~/bin # *sh userv.sh 5656* +PORT1 = [5656] +Starting UDP listener on [10.10.10.50],[5656] +#hello from internal VM# +^Croot@firewall:~/bin # +root@firewall:~/bin # *ipfw show* +#01000 1 51 allow udp from any to me verrevpath# +65535 0 0 deny ip from any to any +root@firewall:~/bin # +---- + +So far, so good. +This is expected behavior. + +Now zero the rule counts on the *firewall* VM and send a similar message from the *internal* VM, but this time spoof the source address. +This requires adding an alias IP address to the interface on the *internal* VM: +indexterm:[alias] + +[subs=+quotes] +---- +root@internal:~/bin # *ifconfig em0 4.4.4.4/32 alias* +root@internal:~/bin # +root@internal:~/bin # *echo "hello 2 from internal VM" | ncat -u -s 4.4.4.4 10.10.10.50 5656* +root@internal:~/bin # +---- + +indexterm:[ncat] + +Now, rule 1000 prevents the matching of the incoming packet with a spoofed source address and no packet is received by the *userv.sh* service. +indexterm:[userv.sh] +Instead, the packet is handled by the default deny rule: + +[subs=+quotes] +---- +root@firewall:~/bin # *sh userv.sh 5656* +PORT1 = [5656] +Starting UDP listener on [10.10.10.50],[5656] +^Croot@firewall:~/bin # +root@firewall:~/bin # +root@firewall:~/bin # *ipfw show* +#01000 0 0 allow udp from any to me verrevpath# +#65535 1 53 deny ip from any to any# +root@firewall:~/bin # +---- + +The other keywords in this section, *versrcreach* and *antispoof* operate in a similar manner. +Check the man page for the slight differences between them. + +== jail + +indexterm:[jail] + +Jails are an important component of FreeBSD and have been a part of the base system since FreeBSD 4. +*ipfw* works in tandem with jails to provide networking security. +As discussed in the link:https://docs.freebsd.org/en/books/handbook/jails/#jails-networking[FreeBSD Handbook Section on Jails and Networking], there are three types of jail networking setups. +This section discusses the first two: + +* Host Networking Setup + +* Virtual Networking (VNET) Setup + +=== Host-based Jail Networking + +In this type of networking setup, the jail shares the host networking stack. +The jail has the same IP address and interface as the host. + +Recall that the *jail1* VM has different characteristics than the standard VMs used in this book. +It has 8GB memory, a bigger disk, and is running ZFS for its filesystem. + +Instructions for setting up this type of jail are found in the FreeBSD Handbook Section link:https://docs.freebsd.org/en/books/handbook/jails/#creating-thin-jail-openzfs-snapshots[Creating a Thin Jail Using OpenZFS Snapshots]. + +[subs=+quotes] +---- +% *cd ~/ipfw-primer/ipfw/HOST_SCRIPTS* +% *sudo /bin/sh mkbr.sh reset bridge0 tap12 #_host_interface_#* +% */bin/sh runvm.sh jail1* +---- + +Set up the *jail1* VM to use DHCP addressing and follow the instructions in the handbook to create a *thinjail* using ZFS, including creating [.filename]#/etc/jail.conf# with the parameters shown in that section. + +Once that is completed, reconfigure the FreeBSD host for this example. + +Set up the *external1* and *jail1* VMs with these commands on the FreeBSD host: + +[subs=+quotes] +---- +% *cd ~/ipfw-primer/ipfw/HOST_SCRIPTS* +% *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap12* +% */bin/sh runvm.sh external1 jail1* +---- + +and use the addressing shown in the figure below. + +[[ipfw-jails020-keyword]] +.Jail With Host Based Networking +image::ipfw-jails020.png["Jail With Host Based Networking. Refer to paragraphs below."] + +The typical jail configuration file for this setup uses the following network configuration: +indexterm:[jail, configuration] + +[subs=+quotes] +---- + jailname { + . . . + # Network + ip4 = inherit; + interface = em0; + . . . + } + +Login to the *jail1* VM and start the jail with: + +# *service jail onestart thinjail* + +Access the jail with the *jexec* command: + +# *jexec -u root thinjail* +---- + +The jail named *thinjail* is now using the host [.filename]#/etc/jail.conf# example, which uses the inherited IPv4 network stack, for the jail. + +[TIP] +==== +There are now _three_ different command line environments - the FreeBSD *host*, the QEMU *jail1* VM, and the *thinjail* running inside the *jail1* VM. +Keep track of which command line you are using by watching the shell prompt. +==== + +Here, it is the host that controls the network stack and all *ipfw* commands (loading, unloading, adding/deleteing rules, etc.) must be done from the host. +The jail root user does not have permission to operate *ipfw* inside the jail. + +[[ipfw-jails010-keyword]] +.Jail With Host Based Networking +image::ipfw-jails010.png["Jail With Host Based Networking. Refer to paragraphs below."] + +All *ipfw* configuration for the jail must be done on the host. +*ipfw* provides the *jail* keyword for this purpose. +For IP communications, this keyword applys primarily to *_outbound_* packets from the jail. +Inbound packets to the jail, follow the normal host rules. + +By default, if the *thinjail* runs *nc -l 203.0.113.75 5656*, it opens up a TCP socket listening on port 5656 in the *jail1* VM. +If instead, the *jail1* VM runs the identical command in the *jail1* VM, the listening socket is not visible to the *thinjail*. + + +indexterm:[tserv.sh] +The conditions for outside access to *thinjail* rely on the host network, and the *jail _jailname_* keyword is not needed. + +[subs=+quotes] +---- +root@jail1:# *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +root@jail1:# +root@jail1:# *ipfw add 100 check-state* +root@jail1:# *ipfw add 1000 allow tcp from any to me dst-port 5656 setup keep-state* +---- + +This rule on the host system will allow a connection from the *external1* VM to reach the above *nc -l 203.0.113.75 5656* running inside *thinjail*. + +For outbound TCP communication, rule 2000 below, using the *jail thinjail* keyword is required. +For the most part, the *ipfw* rules used elsewhere in this book are applicable here with the addition of the *jail* _jailname_ keyword. + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +# *ipfw add 1000 allow tcp from any to me dst-port 5656 setup keep-state* +# *ipfw add 2000 allow tcp from me to any setup keep-state jail thinjail* +---- + +[IMPORTANT] +==== +Always provide the jail *_name_* rather than a numeric ID. +If the jail is restarted for any reason it may get a new jail ID number and an existing rule with a jail number will be immediately out of date. +The rule will have to be re-entered using the jail name. +==== + +indexterm:[jail, name] indexterm:[jail, jailid] + +[NOTE] +==== +When entering a rule with a jail name, *ipfw* will lookup the name and reply with the number. +So even when listing or showing the ruleset, *ipfw* will always show the number not the name. +Use the `jls` command to show the jail ID name and number. +==== + +[TIP] +==== +It is a good idea to compartmentalize the rules for each jail in a file with the jail name. +That way, if a jail is restarted, the specific file can be rerun to update the *ipfw* rules on the host. +==== + +=== Virtual Network (VNET) Jail Networking + +indexterm:[jail, VNET] + +A more advanced setup is using the VNET networking capabilities of FreeBSD for the jail. +There are many good online tutorials on setting up VNET jails. +This section is focused on the use of *ipfw* with a VNET network for the jail. + +The architecture for this setup is shown in the figure below and is similar to that used in the last section. + +[[ipfw-jails030-keyword]] +.Jail With VNET Based Networking +image::ipfw-jails030.png["Jail With VNET Based Networking. Refer to paragraphs below."] + +[NOTE] +==== +While there are two `bridge0` interfaces shown in the diagram, they are completely unrelated. +The top `bridge0` resides on the FreeBSD host and connects the *external1* and *jail1* VMs. +The bottom `bridge0` resides _inside_ the *jail1* VM and connects the *jail1* em0 interface with the man:epair[4] interface attached to the *vnetjail* jail. +==== + +For this section, create a second thinjail named *vnetjail* as follows: + +[subs=+quotes] +---- +root@jail1:# *zfs clone zroot/jails/templates/14.2-RELEASE@base zroot/jails/containers/vnetjail* + +See below for configuring */etc/jail.conf*. +---- +indexterm:[bridge] indexterm:[jail, vnet] + +[TIP] +==== +Configuring multiple jails can be done with separate sections in [.filename]#/etc/jail.conf#, or by creating separate configuration files in [.filename]#/etc/jail.d/_jailname_.conf#. +See man:jail.conf[5] for details. +==== + +The *vnetjail* configuration sets up a VNET network as follows: +indexterm:[jail, configuration] + +[subs=+quotes] +---- +# +# vnetjail.conf - handbook/jails - setting up a thin jail under ZFS +# +vnetjail { + # Startup / Logging + exec.start = "/bin/sh /etc/rc"; + exec.stop = "/bin/sh /etc/rc.shutdown"; + exec.consolelog = "/var/log/jail_console_${name}.log"; + + # Permissions + allow.raw_sockets; + exec.clean; + mount.devfs; + devfs_ruleset = 5; + + # Hostname / Path + host.hostname = "${name}"; + path = "/usr/local/jails/containers/${name}"; + + # VNET / VIMAGE + vnet; + vnet.interface = "${epair}b"; + + # Network + $id = "90"; + $ip = "203.0.113.${id}/24"; + $gateway = "203.0.113.50"; + $bridge = "bridge0"; + $epair = "epair${id}"; + + # ADD TO bridge INTERFACE + exec.prestart = "/sbin/ifconfig ${bridge} create up"; + exec.prestart += "/sbin/ifconfig ${epair} create up"; + exec.prestart += "/sbin/ifconfig ${epair}a up descr jail:${name}"; + exec.prestart += "/sbin/ifconfig ${bridge} addm ${epair}a up"; + exec.prestart += "/sbin/ifconfig ${bridge} addm em0"; + exec.start += "/sbin/ifconfig ${epair}b ${ip} up"; + exec.start += "/sbin/route add default ${gateway}"; + exec.poststop = "/sbin/ifconfig ${bridge} deletem ${epair}a"; + exec.poststop += "/sbin/ifconfig ${bridge} deletem em0"; + exec.poststop += "/sbin/ifconfig ${epair}a destroy"; + exec.poststop += "/sbin/ifconfig ${bridge} destroy"; +} +---- + +In this instance, the network stack is completely separate from the host network stack. +However, achieving and managing connectivity happens _inside_ the *vnetjail* jail. + +Testing connectivity with the jail can be accomplished by +indexterm:[jail, vnet] + +. Ensuring *ipfw* is not loaded on *jail1*, +. Entering the *vnetjail*, and +. Starting up a listening service using man:nc[1]: +indexterm:[nc] + +[subs=+quotes] +---- +root@#jail1#:~ # *kldunload ipfw* +IP firewall unloaded +root@#jail1#:~ # *service jail onestart vnetjail* +root@#jail1#:~ # +root@#jail1#:~ # *jexec -u root vnetjail* +root@#vnetjail#:/ # *cd* +root@#vnetjail#:~ # +root@#vnetjail#:~ # *nc -l -k 5656* + +---- + +Connecting from *external1* using man:nc[1]: + +[subs=+quotes] +---- +root@#external1#:~ # *nc 203.0.113.90 5656* +hello from external1 +^C +# +---- + +With no *ipfw* firewall in place, the test is successful. + +To apply *ipfw* rules for the *vnetjail* jail, start *ipfw* in the *jail1* VM. + +[TIP] +==== +In VNET jails, *ipfw* is *_started_* from outside the jail, but rules are added from *_inside_* the jail. +*ipfw* is also stopped from outside the jail. +==== + +Then, from inside the *vnetjail* jail, start up a listener using man:nc[1]: + +[subs=+quotes] +---- +root@#vnetjail#:~ # *nc -l -k 5656* +root@#vnetjail#:~ # +---- + +Since the *vnetjail* jail has a separate IP address and network stack from the *jail1* VM, orient *ipfw* rules around the *vnetjail* IP address: +indexterm:[jail, vnet] + +[subs=+quotes] +---- +root@#jail1#:~ # *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +root@#jail1#:~ # +root@#jail1#:~ # *jexec -u root vnetjail* +root@#vnetjail#:/ # *cd* +root@#vnetjail#:~ # +root@#vnetjail#:~ # *ipfw show* +65535 0 0 deny ip from any to any +root@#vnetjail#:~ # +root@#vnetjail#:~ # *ipfw add 100 check-state* +00100 check-state :default +root@#vnetjail#:~ # +root@#vnetjail#:~ # *ipfw add 1000 allow tcp from any to me dst-port 5656 setup keep-state* +01000 allow tcp from any to me 5656 setup keep-state :default +root@#vnetjail#:~ # +root@#vnetjail#:~ # *ipfw show* +00100 0 0 check-state :default +01000 0 0 allow tcp from any to me 5656 setup keep-state :default +65535 0 0 deny ip from any to any + +The single rule above is enough to set up a TCP connection. + +From *external1*: + +root@#external1#:~ # *nc 203.0.113.90 5656* +Hello from external1 after ipfw rules have been set up. +^C +root@external1:~ # + +After the above: + +root@#vnetjail#:~ # +root@#vnetjail#:~ # *ipfw show* +00100 0 0 check-state :default +01000 18 1012 allow tcp from any to me 5656 setup keep-state :default +65535 0 0 deny ip from any to any +root@#vnetjail#:~ # +---- + +Setting up rules in the *vnetjail* is left as an exercise to the reader. + + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.po @@ -0,0 +1,1654 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:1 +#, no-wrap +msgid "IPFW See Also" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:1 +#, no-wrap +msgid "Chapter 7. Other Keywords" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:13 +#, no-wrap +msgid "Other Keywords" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:52 +msgid "This section covers some other lesser used keywords." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:53 +#, no-wrap +msgid "abort / abort6" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:56 +msgid "indexterm:[abort] indexterm:[abort6]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:59 +msgid "" +"The *abort* and *abort6* keywords interrupt the data stream between two " +"endpoints. The effect of this keyword, is similar to the *reset* keyword, " +"but there are important differences." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:61 +#, no-wrap +msgid "Abort and abort6 keywords" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:62 +#, no-wrap +msgid "Abort and abort6 keywords. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:62 +#, no-wrap +msgid "ipfw-other-keywords010.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:65 +msgid "The above figure shows the effect of inserting the *firewall* rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:69 +#, no-wrap +msgid "# *ipfw add 50 abort tcp from 203.0.113.30 to me*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:75 +msgid "" +"Unlike the *reset* keyword, there is no packet sent from the firewall to the " +"source. What happens is that *ipfw* just starts dropping packets that match " +"the rule. Since there are no more replies coming from the destination (here " +"the firewall itself), the source endpoint issues retransmissions over and " +"over. Eventually the source concludes that the connection is irrevocably " +"broken and it closes the connection." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:79 +msgid "" +"In the rule above, *_all_* TCP connections will be interrupted between the " +"two systems." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:86 +msgid "" +"In a TCP connection, *ipfw* will use dynamic rules if a *check-state* rule " +"is already in place. If this is the case, issue the *abort* rule at a rule " +"number *_before_* the check-state rule. Otherwise, it will have no effect." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:88 +#, no-wrap +msgid "mark / setmark" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:91 +msgid "indexterm:[mark] indexterm:[setmark]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:96 +msgid "" +"The *setmark* keyword functions similar to the *tag* keyword. If the packet " +"matches the rule, *ipfw* applies a 32-bin identifier to the packet. This " +"identifier (the \"mark\") is held with the packet internally inside *ipfw*. " +"It is not sent with the packet on the wire and is not visible to any network " +"monitoring from tools like man:tcpdump[1] or man:[wireshark]." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:99 +msgid "" +"Like tags, a mark can be used as another filtering device with other *ipfw* " +"rules to do policy base routing or filtering. Note that only one mark can " +"be applied at a time." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:102 +msgid "" +"A big advantage of marks over tags are their ability to be matched as a " +"lookup key in a table. Also, a mark can have a bitmask applied to it." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:106 +msgid "" +"To explore *mark* and *setmark*, use the architecture of Simple NAT shown in " +"crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT]. Begin by creating " +"the network with the *mkbr.sh* script and starting the VMs with the *runvm." +"sh* script shown in crossref:ipfw-nat[ipfw-simple-nat-figure, Simple NAT]. " +"indexterm:[mkbr.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:108 +msgid "" +"Assign the IP addresses as shown, and ensure all VMs have connectivity with " +"adjacent systems." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:113 +msgid "" +"On the *internal* VM, start up the *userv.sh* script with port number 5656. " +"indexterm:[userv.sh] Then, on the *external1* VM, start up the *ucont.sh* " +"server with the same port and a time value of 1 second. indexterm:[ucont.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:116 +msgid "" +"Before placing a *setmark* value on a packet, start the data communications " +"scripts and examine the output of the *ipfw* log by setting the sysctl to " +"log to syslog: indexterm:[syslog]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:120 +#, no-wrap +msgid "# *sysctl net.inet.ip.fw.verbose=1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:123 +msgid "indexterm:[sysctl, net.inet.ip.fw.verbose]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:126 +msgid "" +"Now insert the following firewall rules and examine the log file [." +"filename]#/var/log/security#: indexterm:[log file]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:138 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow log udp from any to 10.10.10.20 dst-port 5656*\n" +"01000 allow log udp from any to 10.10.10.20 5656\n" +"#\n" +"# *tail -f /var/log/security*\n" +"Dec 29 22:32:33 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:30463 10.10.10.20:5656 in via em1\n" +"Dec 29 22:32:33 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:30463 10.10.10.20:5656 out via em0\n" +"Dec 29 22:32:36 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:24588 10.10.10.20:5656 in via em1\n" +"Dec 29 22:32:36 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:24588 10.10.10.20:5656 out via em0\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:142 +msgid "" +"Now add the following rule to apply the *mark* value of 20 (decimal) and " +"observe the change in the logs: indexterm:[mark] indexterm:[setmark]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:160 +#, no-wrap +msgid "" +"# *ipfw add 500 setmark 20 log udp from any to 10.10.10.20 dst-port 5656*\n" +"00500 setmark 0x14 log udp from any to 10.10.10.20 5656\n" +"#\n" +"#\n" +"# *tail -f /var/log/security*\n" +"Dec 29 22:41:20 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:27955 10.10.10.20:5656 in via em1\n" +"Dec 29 22:41:20 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:27955 10.10.10.20:5656 out via em0\n" +"Dec 29 22:41:23 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:37423 10.10.10.20:5656 in via em1\n" +"Dec 29 22:41:23 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:37423 10.10.10.20:5656 out via em0\n" +"Dec 29 22:41:25 firewall kernel: ipfw: #500 SetMark 0x14 UDP 203.0.113.10:45176 10.10.10.20:5656 in via em1#\n" +"Dec 29 22:41:25 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:45176 10.10.10.20:5656 mark:0x14 in via em1\n" +"Dec 29 22:41:25 firewall kernel: ipfw: #500 SetMark 0x14 UDP 203.0.113.10:45176 10.10.10.20:5656 out via em0#\n" +"Dec 29 22:41:25 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:45176 10.10.10.20:5656 mark:0x14 out via em0\n" +"Dec 29 22:41:27 firewall kernel: ipfw: #500 SetMark 0x14 UDP 203.0.113.10:21444 10.10.10.20:5656 in via em1#\n" +"Dec 29 22:41:27 firewall kernel: ipfw: 1000 Accept UDP 203.0.113.10:21444 10.10.10.20:5656 mark:0x14 in via em1\n" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:162 +#, no-wrap +msgid "NPTv6" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:165 +msgid "indexterm:[NPTv6]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:170 +msgid "" +"IPv6-to-IPv6 Network Prefix Translation (NPTv6) is the process of " +"translating IPv6 header source and destination addresses. Functionally, it " +"is similar to the more well understood Network Address Translation, but " +"without the need to maintain state. It is only the IPv6 source and " +"destination addresses that are translated. The idea here is to allow an " +"edge network to have its own independent addressing scheme while being able " +"to exchange IPv6 traffic with external IPv6 networks through the use of an " +"NPTv6 Translator" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:174 +msgid "" +"link:https://www.rfc-editor.org/rfc/rfc6296.html[RFC 6296] is the definitive " +"document on NPTv6. indexterm:[RFC, 6296] The example in this section is " +"taken from Sections 2.1 of that document." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:176 +msgid "" +"The architecture for these examples is based on Simple NAT as in the " +"previous section." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:177 +#, no-wrap +msgid "NPTv6 Setup" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:180 +msgid "" +"Use the setup instructions shown in crossref:ipfw-nat[ipfw-simple-nat-" +"figure, Simple NAT] but use the IPv6 addressing as shown below:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:182 +#, no-wrap +msgid "NPTv6 Simple Case" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:183 +#, no-wrap +msgid "NPTv6 Simple Case. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:183 +#, no-wrap +msgid "ipfw-other-keywords100.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:187 +msgid "" +"At first glance, this appears to be a simple IPv6 forwarding example. " +"However in this case, *NPTv6* changes the actual packet source and " +"destination addresses, so no forwarding is needed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:190 +msgid "" +"man:ipfw[8] explains the syntax of the NPTv6 command and options, but there " +"are a number of details that need to be set up correctly. Use the following " +"as a guide:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:194 +#, no-wrap +msgid "On the FreeBSD host:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:197 +#, no-wrap +msgid "" +"$ *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5*\n" +"$ */bin/sh runvm.sh external1 firewall internal*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:199 +#, no-wrap +msgid "Ensure all IPv6 addresses on all VMs are set up correctly.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:201 +#, no-wrap +msgid "On the *firewall* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:204 +#, no-wrap +msgid "" +"# *kldunload ipfw_nptv6*\n" +"# *kldunload ipfw*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:207 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"# *kldload ipfw_nptv6*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:210 +#, no-wrap +msgid "" +"# *sysctl net.inet.ip.fw.one_pass=0*\n" +"# *sysctl net.inet.ip.fw.verbose=1*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:212 +#, no-wrap +msgid "# *ipfw -q flush*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:215 +#, no-wrap +msgid "" +"# Set up the NPTv6 instance.\n" +"# *ipfw nptv6 foo create int_prefix fd01:0203:0405:: ext_prefix 2001:0db8:0001:: prefixlen 48*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:219 +#, no-wrap +msgid "" +"# Rule for outbound\n" +"# *ipfw add 2000 nptv6 foo log ip6 from fd01:0203:0405::/48 to any*\n" +"# *ipfw add 3000 allow ip6 from any to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:222 +msgid "" +"indexterm:[bridge] indexterm:[tap] indexterm:[mkbr.sh] indexterm:[runvm.sh] " +"indexterm:[module, ipfw] indexterm:[module, ipfw_nptv6] indexterm:[sysctl, " +"net.inet.ip.fw.one_pass] indexterm:[sysctl, net.inet.ip.fw.verbose]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:225 +msgid "" +"As noted in man:ipfw[8], the sysctl `net.inet6.ip6.forwarding=1` must be " +"applied or NPTv6 will silently stop working. indexterm:[sysctl, net.inet6." +"ip6.forwarding]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:226 +#, no-wrap +msgid "NPTv6 Testing" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:231 +msgid "" +"Set up a UDP listener on the *external1* VM. Using the *userv.sh* (and its " +"*ucon.sh* partner) is possible, but that would require editing the scripts " +"to set up an IPv6 address. Try this method instead:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:235 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:302 +#, no-wrap +msgid "On the *external1* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:238 +#, no-wrap +msgid "" +"# Listen for a UDP packet\n" +"$ ncat -l -k -u -6 2001:0db8:0001::10 5656\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:240 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:307 +#, no-wrap +msgid "On the *internal* VM:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:243 +#, no-wrap +msgid "" +"# Send the desired UDP packet.\n" +"$ echo \"testing123\" | ncat -6 -u 2001:0db8:0001::10 5656\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:246 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:458 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:599 +msgid "indexterm:[ncat]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:249 +msgid "" +"In the setup section above, logging to `syslogd` was set up, so the results " +"can be seen by examining the tail end of [.filename]#/var/log/security#: " +"indexterm:[syslogd]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:253 +#, no-wrap +msgid "Dec 31 19:51:44 firewall kernel: ipfw: 2000 Eaction nptv6 UDP [fd01:203:405::20]:52451 [2001:db8:1::10]:5656 in via em0\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:256 +msgid "The output of a `tcpdump` on *external1* shows:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:267 +#, no-wrap +msgid "" +"root@external1:~ # tcpdump -n -i em0 -X \"udp\"\n" +"tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\n" +"listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"19:51:43.827543 IP6 #2001:db8:1:d54f::20.52451# > 2001:db8:1::10.5656: UDP, length 11\n" +" 0x0000: 600a 145a 0013 113f 2001 0db8 0001 d54f `..Z...?.......O\n" +" 0x0010: 0000 0000 0000 0020 2001 0db8 0001 0000 ................\n" +" 0x0020: 0000 0000 0000 0010 cce3 1618 0013 f72b ...............+\n" +" 0x0030: 7465 7374 696e 6731 3233 0a testing123.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:270 +msgid "indexterm:[tcpdump]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:275 +msgid "" +"The highlighted section shows the effect of the NPTv6 translation. " +"indexterm:[NPTv6] (See link:https://www.rfc-editor.org/rfc/rfc6296.html[RFC " +"6296], Section 3, for details.) indexterm:[RFC, 6296]" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:276 +#, no-wrap +msgid "ipttl" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:279 +msgid "indexterm:[ipttl]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:283 +msgid "" +"The *ipttl* (Time to Live or TTL) keyword identifies packets that have " +"specific TTL characteristics. man:ipfw[8] notes that the *ipttl* keyword " +"will accept a single value, a list of values, or a range of values, in the " +"same syntax as that used for the *ports* keyword. (Recall the discussion of " +"lists and ranges in the crossref:ipfw-rules[ipfw-rules-numbering-notes, " +"Notes on Rule Numbering].)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:287 +#, no-wrap +msgid "" +"*ipttl* is one of a number of *ipfw* keywords that work on individual fields of packets flowing through the firewall.\n" +"Similar keywords include *ipid*, *iplen*, *ipprecedence*, etc.\n" +"indexterm:[ipid] indexterm:[iplen] indexterm:[ipprecedence]\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:288 +#, no-wrap +msgid "ipttl Setup" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:291 +msgid "" +"Use the setup instructions shown in crossref:ipfw-nat[ipfw-simple-nat-" +"figure, Simple NAT] with IPv4 addressing, not IPv6." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:296 +msgid "" +"Also, this example will use the *hping3* command. indexterm:[hping3] (To " +"downloaded the *hping3* package, reset the *internal* VM for access to the " +"Internet, and download the package with *pkg install hping3*. Remember to " +"reset for Simple NAT IP addressing for this example.)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:298 +msgid "Refer to man:hping3[8] for details." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:305 +#, no-wrap +msgid "" +"# Listen for a UDP packet\n" +"$ ncat -l -k -u -6 203.0.113.10 5656\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:311 +#, no-wrap +msgid "" +"# Send the desired UDP packet.\n" +"Now, deliberately set the initial TTL to 13.\n" +"$ hping3 --sign \"test for ttl 13\" --count 1 --udp --ttl 13 --destport 5656 203.00.113.10\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:314 +msgid "indexterm:[ncat] indexterm:[hping3]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:316 +msgid "Without *ipfw* in place, the result should be similar to:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:324 +#, no-wrap +msgid "" +"01:50:00.765310 IP (tos 0x0, #ttl 12#, id 27704, offset 0, flags [none], proto UDP (17), length 43)\n" +" 10.10.10.20.2600 > 203.0.113.10.5656: [udp sum ok] UDP, length 15\n" +" 0x0000: 4500 002b 6c38 0000 0c11 f261 0a0a 0a14 E..+l8.....a....\n" +" 0x0010: cb00 710a 0a28 1618 0017 2f93 7465 7374 ..q..(..../.test\n" +" 0x0020: 2066 6f72 2074 746c 2031 3300 0000 .for.ttl.13...\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:331 +msgid "" +"The IP Time to Live option was set up to prevent IP packets from bouncing " +"around the Internet forever. link:https://www.ietf.org/rfc/rfc791.txt[RFC " +"791] initially intended that the value would be considered an actual time " +"value (number of seconds) and that each module processing the packet would " +"subtract processing time from the initial value. indexterm:[RFC, 791] This " +"was later changed to an integer identifying a \"hop count\" where the " +"initial value (now 64) is decremented by every router or gateway or " +"forwarding device, such as a firewall. indexterm:[ttl]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:333 +msgid "" +"In this case the *firewall* VM, even though it is not running firewall " +"software, is still a 'forwarding device' and decrements the count as it " +"forwards the packet." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:334 +#, no-wrap +msgid "ipttl Testing" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:337 +msgid "To examine the *ipttl* keyword follow this example:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:342 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"# *sysctl net.inet.ip.fw.verbose=1*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:345 +#, no-wrap +msgid "" +"# Count all packets as the flow through\n" +"# *ipfw add 800 count ip from any to any*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:348 +#, no-wrap +msgid "" +"# Count all packets with TTL of exactly 13 as the flow through\n" +"# *ipfw add 900 count ip from any to any ipttl 13*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:351 +#, no-wrap +msgid "" +"# Allow and log packets with TTL of exactly 13.\n" +"# *ipfw add 1000 allow log udp from any to any ipttl 13*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:354 +#, no-wrap +msgid "" +"# Count any other ip packets after the ipttl rule\n" +"# *ipfw add 1100 count ip from any to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:357 +msgid "indexterm:[sysctl, net.inet.ip.fw.verbose] indexterm:[ipttl]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:359 +msgid "" +"Below is a sample run of *ncat* and *hping3* commands to test the above " +"rules:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:365 +#, no-wrap +msgid "" +"# *echo \"UDP with default TTL\" | ncat -u 203.0.113.10 5656*\n" +"# *echo \"UDP with default TTL\" | ncat -u 203.0.113.10 5656*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:368 +#, no-wrap +msgid "" +"# *hping3 --sign \"UDP with TTL=13\" --count 1 --udp --ttl 13 --destport 5656 203.0.113.10*\n" +"# *hping3 --sign \"UDP with TTL=13\" --count 1 --udp --ttl 13 --destport 5656 203.0.113.10*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:371 +#, no-wrap +msgid "" +"The results show the first two packets with default TTL values (64) were not passed by the firewall.\n" +"The third and fourth packets were passed.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:384 +#, no-wrap +msgid "" +"# *tcpdump -n -i em0 -X -vvv \"udp\"\n" +"tcpdump: listening on em0, link-type EN10MB (Ethernet), snapshot length 262144 bytes\n" +"03:26:42.875634 IP (tos 0x0, #ttl 12#, id 17385, offset 0, flags [none], proto UDP (17), length 43)\n" +" 10.10.10.20.1648 > 203.0.113.10.5656: [udp sum ok] UDP, length 15\n" +" 0x0000: 4500 002b 43e9 0000 0c11 1ab1 0a0a 0a14 E..+C...........\n" +" 0x0010: cb00 710a 0670 1618 0017 1d07 5544 5020 ..q..p......UDP.\n" +" 0x0020: 7769 7468 2054 544c 3d31 3300 0000 with.TTL=13...\n" +"03:26:47.903863 IP (tos 0x0, #ttl 12#, id 33936, offset 0, flags [none], proto UDP (17), length 43)\n" +" 10.10.10.20.2539 > 203.0.113.10.5656: [udp sum ok] UDP, length 15\n" +" 0x0000: 4500 002b 8490 0000 0c11 da09 0a0a 0a14 E..+............\n" +" 0x0010: cb00 710a 09eb 1618 0017 198c 5544 5020 ..q.........UDP.\n" +" 0x0020: 7769 7468 2054 544c 3d31 3300 0000 with.TTL=13...\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:387 +msgid "indexterm:[ncat] indexterm:[hping3] indexterm:[ttl] indexterm:[tcpdump]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:389 +msgid "But it is the *ipfw show* results that reveal how things really worked:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:399 +#, no-wrap +msgid "" +"# *ipfw show*\n" +"00800 6 270 count ip from any to any\n" +"00900 2 86 count ip from any to any ipttl 13\n" +"01000 2 86 allow log udp from any to any ipttl 13\n" +"01100 4 184 count ip from any to any\n" +"01200 2 86 allow log udp from any to any ipttl 12\n" +"65535 2 98 deny ip from any to any\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:404 +msgid "" +"The count of 6 packets on rule 800 above accounts for the inbound and " +"outbound packets for those that matched later rules." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:406 +#, no-wrap +msgid "tcpdatalen" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:409 +msgid "indexterm:[tcpdatalen]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:411 +msgid "The *tcpdatalen* keyword is one of several related keywords:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:414 +#, no-wrap +msgid "" +"*tcpack*, *tcpdatalen*, *tcpflags*, *tcpmss*, *tcpseq*, *tcpwin*, *tcpoptions*\n" +"indexterm:[tcpack] indexterm:[tcpflags] indexterm:[tcpmss] indexterm:[tcpseq] indexterm:[tcpwin] indexterm:[tcpoptions]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:416 +msgid "These keywords are not often used." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:420 +msgid "" +"However, there is one very important use case. From time to time, an " +"Internet worm - a malicious packet that gets resent to all local and remote " +"hosts matching some criteria - makes its way onto the Internet. Quick " +"thinking network security administrators can sometimes identify a unique " +"characteristic of these malicious packets such as all packets having the " +"same length - akin to *tcpdatalen*, or a certain set of *tcpoptions*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:423 +msgid "" +"In this example, the *firewall* VM is running the *tserv.sh 5656* script. " +"indexterm:[tserv.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:427 +msgid "" +"The example below configures *ipfw* to deny all packets having a TCP data " +"length of a certain value range. One of these ranges will cause the " +"malicious packet to be denied. Keep in mind, this is the length of the TCP " +"data payload, not the overall length of the packet." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:432 +#, no-wrap +msgid "" +"# *ipfw add 10 deny tcp from any to me tcpdatalen 10-19*\n" +"# *ipfw add 20 deny tcp from any to me tcpdatalen 20-29*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:434 +#, no-wrap +msgid "*. . .*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:448 +#, no-wrap +msgid "" +"root@firewall:~/bin # ipfw show\n" +"00010 0 0 deny tcp from any to me tcpdatalen 10-19\n" +"00020 0 0 deny tcp from any to me tcpdatalen 20-29\n" +"00030 0 0 deny tcp from any to me tcpdatalen 30-39\n" +"00040 0 0 deny tcp from any to me tcpdatalen 40-49\n" +"00050 0 0 deny tcp from any to me tcpdatalen 50-59\n" +"00060 0 0 deny tcp from any to me tcpdatalen 60-69\n" +"00070 0 0 deny tcp from any to me tcpdatalen 70-79\n" +"00080 0 0 deny tcp from any to me tcpdatalen 80-89\n" +"00090 0 0 deny tcp from any to me tcpdatalen 90-99\n" +"08000 0 0 check-state :default\n" +"09000 0 0 allow tcp from any to me setup keep-state :default\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:451 +msgid "And a test using *ncat* directly from *external3*:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:455 +#, no-wrap +msgid "# *echo \"123456789012345678901234567890\" | ncat 203.0.113.50 5656*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:460 +msgid "" +"The TCP 3-way handshake completes, but the packet containing the data " +"payload is stopped by rule 30 as shown below:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:476 +#, no-wrap +msgid "" +"root@firewall:~/bin # ipfw show\n" +"00010 0 0 deny tcp from any to me tcpdatalen 10-19\n" +"00020 0 0 deny tcp from any to me tcpdatalen 20-29\n" +"00030 13 1079 deny tcp from any to me tcpdatalen 30-39\n" +"00040 0 0 deny tcp from any to me tcpdatalen 40-49\n" +"00050 0 0 deny tcp from any to me tcpdatalen 50-59\n" +"00060 0 0 deny tcp from any to me tcpdatalen 60-69\n" +"00070 0 0 deny tcp from any to me tcpdatalen 70-79\n" +"00080 0 0 deny tcp from any to me tcpdatalen 80-89\n" +"00090 0 0 deny tcp from any to me tcpdatalen 90-99\n" +"08000 0 0 check-state :default\n" +"09000 8 420 allow tcp from any to me setup keep-state :default\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:479 +msgid "" +"The reason for the excessive number of packets denied is TCP retransmission " +"trying to account for the dropped packet as shown in the figure below." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:481 +#, no-wrap +msgid "Denying Packet Based on TCP Data Length" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:482 +#, no-wrap +msgid "Denying Packets Based on TCP Data Length. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:482 +#, no-wrap +msgid "ipfw-other-keywords020.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:485 +msgid "Eventually TCP gives up and shuts down the connection." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:486 +#, no-wrap +msgid "verrevpath / versrcreach / antispoof" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:489 +msgid "indexterm:[verrevpath] indexterm:[versrcreach] indexterm:[antispoof]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:491 +msgid "" +"These keywords all work to determine if an incoming packet is legitimate." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:493 +msgid "" +"As noted in man:ipfw[8], *verrevpath* (\"verify reverse path\") looks up the " +"incoming packet's source address in the routing table." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:498 +msgid "" +"Quoting: _\"If the interface on which the packet entered the system matches " +"the outgoing interface for the route, the packet matches. If the interfaces " +"do not match up, the packet does not match. All outgoing packets or packets " +"with no incoming interface match.\"_" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:500 +msgid "Consider the figure below:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:502 +#, no-wrap +msgid "verrevpath Example" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:503 +#, no-wrap +msgid "verrevpath Example. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:503 +#, no-wrap +msgid "ipfw-other-keywords030.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:506 +msgid "" +"In this figure, the firewall has interface *em0* directly connected to the " +"`10.10.10.0/24` network and the *em1* interface directly connected to the " +"`203.0.113.0/24` network." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:508 +msgid "" +"The *firewall* VM interfaces and routing table are shown in the text below:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:531 +#, no-wrap +msgid "" +"root@firewall:~ # ifconfig em0\n" +"em0: flags=1008843 metric 0 mtu 1500\n" +" options=48525bb\n" +" ether 02:49:50:46:57:41\n" +" inet 10.10.10.50 netmask 0xffffff00 broadcast 10.10.10.255\n" +" media: Ethernet autoselect (1000baseT )\n" +" status: active\n" +" nd6 options=29\n" +"root@firewall:~ #\n" +"root@firewall:~ # ifconfig em1\n" +"em1: flags=1008843 metric 0 mtu 1500\n" +" options=48525bb\n" +" ether 02:49:50:46:57:42\n" +" inet 203.0.113.50 netmask 0xffffff00 broadcast 203.0.113.255\n" +" media: Ethernet autoselect (1000baseT )\n" +" status: active\n" +" nd6 options=29\n" +"root@firewall:~ #\n" +"root@firewall:~ # netstat -rn\n" +"Routing tables\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:539 +#, no-wrap +msgid "" +"Internet:\n" +"Destination Gateway Flags Netif Expire\n" +"#10.10.10.0/24 link#1 U em0#\n" +"#10.10.10.50 link#3 UHS lo0#\n" +"127.0.0.1 link#3 UH lo0\n" +"#203.0.113.0/24 link#2 U em1#\n" +"#203.0.113.50 link#3 UHS lo0#\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:550 +#, no-wrap +msgid "" +"Internet6:\n" +"Destination Gateway Flags Netif Expire\n" +"::/96 link#3 URS lo0\n" +"::1 link#3 UHS lo0\n" +"::ffff:0.0.0.0/96 link#3 URS lo0\n" +"fe80::%lo0/10 link#3 URS lo0\n" +"fe80::%lo0/64 link#3 U lo0\n" +"fe80::1%lo0 link#3 UHS lo0\n" +"ff02::/16 link#3 URS lo0\n" +"root@firewall:~ #\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:553 +msgid "" +"If a packet came in on the *em0* interface with a source address that was " +"not in the `10.10.10.0/24` network, the above quote says the packet should " +"be dropped." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:556 +msgid "" +"Test this with the *ncat* program which has an option to set the source IP. " +"indexterm:[ncat]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:558 +msgid "First, set up the *firewall* VM to allow any UDP packets as shown." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:561 +msgid "" +"Then, set up the *firewall* VM to run *sh userv.sh 5656*, the service to " +"receive UDP packets on the identified port, and send one packet from the " +"*internal* VM with *echo \"hello from internal VM\" | ncat -u 10.10.10.50 " +"5656*. indexterm:[userv.sh]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:581 +#, no-wrap +msgid "" +"root@firewall:~/bin # *ipfw add 1000 allow udp from any to me verrevpath*\n" +"01000 allow udp from any to me verrevpath\n" +"root@firewall:~/bin #\n" +"root@firewall:~/bin # *ipfw show*\n" +"01000 0 0 allow udp from any to me verrevpath\n" +"65535 0 0 deny ip from any to any\n" +"root@firewall:~/bin #\n" +"root@firewall:~/bin # *sh userv.sh 5656*\n" +"PORT1 = [5656]\n" +"Starting UDP listener on [10.10.10.50],[5656]\n" +"#hello from internal VM#\n" +"^Croot@firewall:~/bin #\n" +"root@firewall:~/bin # *ipfw show*\n" +"#01000 1 51 allow udp from any to me verrevpath#\n" +"65535 0 0 deny ip from any to any\n" +"root@firewall:~/bin #\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:585 +msgid "So far, so good. This is expected behavior." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:589 +msgid "" +"Now restart the service on the *firewall* VM and send a similar message from " +"the *internal* VM, but this time spoof the source address. This requires " +"adding an alias IP address to the interface on the *internal* VM: indexterm:" +"[alias]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:596 +#, no-wrap +msgid "" +"root@internal:~/bin # *ifconfig em0 4.4.4.4/32 alias*\n" +"root@internal:~/bin #\n" +"root@internal:~/bin # *echo \"hello 2 from internal VM\" | ncat -u -s 4.4.4.4 10.10.10.50 5656*\n" +"root@internal:~/bin #\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:603 +msgid "" +"Now, rule 1000 prevents the matching of the incoming packet with a spoofed " +"source address and no packet is received by the *userv.sh* service. " +"indexterm:[userv.sh] Instead, the packet is handled by the default deny rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:615 +#, no-wrap +msgid "" +"root@firewall:~/bin # *sh userv.sh 5656*\n" +"PORT1 = [5656]\n" +"Starting UDP listener on [10.10.10.50],[5656]\n" +"^Croot@firewall:~/bin #\n" +"root@firewall:~/bin #\n" +"root@firewall:~/bin # *ipfw show*\n" +"#01000 0 0 allow udp from any to me verrevpath#\n" +"#65535 1 53 deny ip from any to any#\n" +"root@firewall:~/bin #\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:619 +msgid "" +"The other keywords in this section, *versrcreach* and *antispoof* operate in " +"a similar manner. Check the man page for the slight differences between " +"them." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:620 +#, no-wrap +msgid "jail" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:623 +msgid "indexterm:[jail]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:628 +msgid "" +"Jails are an important component of FreeBSD and have been a part of the base " +"system since FreeBSD 4. *ipfw* works in tandem with jails to provide " +"networking security. As discussed in the link:https://docs.freebsd.org/en/" +"books/handbook/jails/#jails-networking[FreeBSD Handbook Section on Jails and " +"Networking], there are three types of jail networking setups. This section " +"discusses the first two:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:630 +msgid "Host Networking Setup" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:632 +msgid "Virtual Networking (VNET) Setup" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:633 +#, no-wrap +msgid "Host-based Jail Networking" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:637 +msgid "" +"In this type of networking setup, the jail shares the host networking " +"stack. The jail has the same IP address and interface as the host." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:640 +msgid "" +"The typical jail configuration file for this set uses the following network " +"configuration: indexterm:[jail, configuration]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:650 +#, no-wrap +msgid "" +" jailname {\n" +" . . .\n" +" # Network\n" +" ip4 = inherit;\n" +" interface = em0;\n" +" . . .\n" +" }\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:654 +msgid "" +"Here, it is the host that controls the network stack and all *ipfw* commands " +"(loading, unloading, adding/deleteing rules, etc.) must be done from the " +"host. The jail root user does not have permission to operate *ipfw* inside " +"the jail." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:656 +#, no-wrap +msgid "Jail With Host Based Networking" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:657 +#, no-wrap +msgid "Jail With Host Based Networking. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:657 +#, no-wrap +msgid "ipfw-jails010.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:663 +msgid "" +"All *ipfw* configuration for the jail must be done on the host. *ipfw* " +"provides the *jail* keyword. For TCP communications, this keyword applys " +"primarily to *_outbound_* packets from the jail. Inbound packets to the " +"jail, follow the normal host rules." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:667 +msgid "" +"If the jail runs *sh tserv.sh 5656*, it opens up a TCP socket listening on " +"port 5656 in the jail. indexterm:[tserv.sh] The rule for outside access to " +"this jail relies on the host network, and the *jail _jailname_* keyword is " +"not needed." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:672 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"# *ipfw add 1000 allow tcp from any to me dst-port 5656 setup keep-state*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:675 +msgid "" +"This rule will allow a connection from an external host to port 5656 in the " +"jail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:678 +msgid "" +"For the most part, the *ipfw* rules used elsewhere in this book are " +"applicable here with the addition of the *jail* _jailname_ keyword. For " +"outbound communication, the added rule below, using the *jail thinjail* " +"keyword succeeds." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:684 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"# *ipfw add 1000 allow tcp from any to me dst-port 5656 setup keep-state*\n" +"# *ipfw add 2000 allow tcp from me to any setup keep-state jail thinjail*\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:691 +msgid "" +"Always provide the jail *_name_* rather than a numeric ID. If the jail is " +"restarted for any reason it may get a new jail ID number and an existing " +"rule with a jail number will be immediately out of date. The rule will have " +"to be re-entered using the jail name." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:694 +msgid "indexterm:[jail, name] indexterm:[jail, jailid]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:700 +msgid "" +"When entering a rule with a jail name, *ipfw* will lookup the name and reply " +"with the number. So even when listing or showing the ruleset, *ipfw* will " +"always show the number not the name. Use the `jls` command to show the jail " +"ID name and number." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:706 +msgid "" +"It is a good idea to compartmentalize the rules for each jail in a file with " +"the jail name. That way, if a jail is restarted, the specific file can be " +"rerun to update the *ipfw* rules on the host." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:708 +#, no-wrap +msgid "Virtual Network (VNET) Jail Networking" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:711 +msgid "indexterm:[jail, VNET]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:715 +msgid "" +"A more advanced setup is using the VNET networking capabilities of FreeBSD " +"for the jail. There are many good tutorials on setting up VNET jails. This " +"section is focused on the use of *ipfw* with the vnet network for the jail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:717 +msgid "The architecture for this setup is shown in the figure below:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:719 +#, no-wrap +msgid "Jail With VNET Based Networking" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:720 +#, no-wrap +msgid "Jail With VNET Based Networking. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:720 +#, no-wrap +msgid "ipfw-jails030.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:724 +msgid "" +"The architecture shows the FreeBSD host, with two QEMU virtual machines, " +"*external1* and *jail1*. The two VMs are connected by *bridge0* and share " +"the `203.0.113.0/24` network." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:727 +#, no-wrap +msgid "" +"*jail1* has different characteristics than the standard VMs used in this book.\n" +"It has 8GB memory, and is running ZFS for its filesystem.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:730 +msgid "" +"The *jail1* VM has set up a FreeBSD thin jail _inside the VM_ following the " +"directions in the FreeBSD handbook on link:https://docs.freebsd.org/en/books/" +"handbook/jails/#thin-jail[Creating a Thin Jail Using OpenZFS Snapshots]. " +"indexterm:[jail, snapshots]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:736 +msgid "" +"While there are two `bridge0` interfaces shown in the diagram, they are " +"completely unrelated. The top `bridge0` resides on the FreeBSD host and " +"connects the *external1* and *jail1* VMs. The bottom `bridge0` resides " +"inside the *jail1* VM and connects the *jail1* em0 interface with the man:" +"epair[4] interface attached to the *vnetjail* jail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:739 +msgid "indexterm:[bridge] indexterm:[jail, vnet]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:742 +msgid "" +"The jail configuration sets up a *vnet* jail as follows: indexterm:[jail, " +"configuration]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:753 +#, no-wrap +msgid "" +"#\n" +"# vnetjail.conf - handbook/jails - setting up a thin jail under ZFS\n" +"#\n" +"vnetjail {\n" +" # Startup / Logging\n" +" exec.start = \"/bin/sh /etc/rc\";\n" +" exec.stop = \"/bin/sh /etc/rc.shutdown\";\n" +" exec.consolelog = \"/var/log/jail_console_${name}.log\";\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:759 +#, no-wrap +msgid "" +" # Permissions\n" +" allow.raw_sockets;\n" +" exec.clean;\n" +" mount.devfs;\n" +" devfs_ruleset = 5;\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:763 +#, no-wrap +msgid "" +" # Hostname / Path\n" +" host.hostname = \"${name}\";\n" +" path = \"/usr/local/jails/containers/${name}\";\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:767 +#, no-wrap +msgid "" +" # VNET / VIMAGE\n" +" vnet;\n" +" vnet.interface = \"${epair}b\";\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:774 +#, no-wrap +msgid "" +" # Network\n" +" $id = \"90\";\n" +" $ip = \"203.0.113.${id}/24\";\n" +" $gateway = \"203.0.113.50\";\n" +" $bridge = \"bridge0\";\n" +" $epair = \"epair${id}\";\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:786 +#, no-wrap +msgid "" +" # ADD TO bridge INTERFACE\n" +" exec.prestart = \"/sbin/ifconfig ${bridge} create up\";\n" +" exec.prestart += \"/sbin/ifconfig ${epair} create up\";\n" +" exec.prestart += \"/sbin/ifconfig ${epair}a up descr jail:${name}\";\n" +" exec.prestart += \"/sbin/ifconfig ${bridge} addm ${epair}a up\";\n" +" exec.prestart += \"/sbin/ifconfig ${bridge} addm em0\";\n" +" exec.start += \"/sbin/ifconfig ${epair}b ${ip} up\";\n" +" exec.start += \"/sbin/route add default ${gateway}\";\n" +" exec.poststop = \"/sbin/ifconfig ${bridge} deletem ${epair}a\";\n" +" exec.poststop += \"/sbin/ifconfig ${epair}a destroy\";\n" +"}\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:790 +msgid "" +"This time, the network stack is completely separate from the host network " +"stack. However, achieving and managing connectivity happens _inside_ the " +"*vnetjail* jail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:793 +msgid "" +"Testing connectivity with the jail can be accomplished by indexterm:[jail, " +"vnet]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:795 +msgid "Ensuring *ipfw* is not loaded on *jail1*," +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:796 +msgid "Entering the *vnetjail*, and" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:798 +msgid "Starting up a listening service using man:nc[1]: indexterm:[nc]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:808 +#, no-wrap +msgid "" +"root@#jail1#:~ # *kldunload ipfw*\n" +"IP firewall unloaded\n" +"root@#jail1#:~ #\n" +"root@#jail1#:~ # *jexec -u root vnetjail*\n" +"root@#vnetjail#:/ # *cd*\n" +"root@#vnetjail#:~ #\n" +"root@#vnetjail#:~ # *nc -l -k 5656*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:812 +msgid "Connecting from *external1* using man:nc[1]:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:819 +#, no-wrap +msgid "" +"root@#external1#:~ # *nc 203.0.113.90 5656*\n" +"hello from external1\n" +"^C\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:822 +msgid "With no *ipfw* firewall in place, the test is successful." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:824 +msgid "" +"To apply *ipfw* rules for the *vnetjail* jail, start *ipfw* in the *jail1* " +"VM." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:829 +msgid "" +"In VNET jails, *ipfw* is *_started_* from outside the jail, but rules are " +"added from *_inside_* the jail. *ipfw* is also stopped from outside the " +"jail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:832 +msgid "" +"Then, from inside the *vnetjail* jail, start up a listener using man:nc[1]:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:837 +#, no-wrap +msgid "" +"root@#vnetjail#:~ # *nc -l -k 5656*\n" +"root@#vnetjail#:~ #\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:841 +msgid "" +"Since the *vnetjail* jail has a separate IP address and network stack from " +"the *jail1* VM, orient *ipfw* rules around the *vnetjail* IP address: " +"indexterm:[jail, vnet]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:863 +#, no-wrap +msgid "" +"root@#jail1#:~ # *kldload ipfw*\n" +"ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled\n" +"root@#jail1#:~ #\n" +"root@#jail1#:~ # *jexec -u root vnetjail*\n" +"root@#vnetjail#:/ # cd\n" +"root@#vnetjail#:~ #\n" +"root@#vnetjail#:~ # *ipfw show*\n" +"65535 0 0 deny ip from any to any\n" +"root@#vnetjail#:~ #\n" +"root@#vnetjail#:~ # *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"root@#vnetjail#:~ #\n" +"root@#vnetjail#:~ # *ipfw add 1000 allow tcp from any to me dst-port 5656 setup keep-state*\n" +"01000 allow tcp from any to me 5656 setup keep-state :default\n" +"root@#vnetjail#:~ #\n" +"root@#vnetjail#:~ # *ipfw show*\n" +"00100 0 0 check-state :default\n" +"01000 0 0 allow tcp from any to me 5656 setup keep-state :default\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:865 +#, no-wrap +msgid "The single rule above is enough to set up a TCP connection.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:867 +#, no-wrap +msgid "From *external1*:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:872 +#, no-wrap +msgid "" +"root@#external1#:~ # *nc 203.0.113.90 5656*\n" +"Hello from external1 after ipfw rules have been set up.\n" +"^C\n" +"root@external1:~ #\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:874 +#, no-wrap +msgid "After the above:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-other-keywords/_index.adoc:881 +#, no-wrap +msgid "" +"root@#vnetjail#:~ #\n" +"root@#vnetjail#:~ # *ipfw show*\n" +"00100 0 0 check-state :default\n" +"01000 18 1012 allow tcp from any to me 5656 setup keep-state :default\n" +"65535 0 0 deny ip from any to any\n" +"root@#vnetjail#:~ #\n" +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc @@ -0,0 +1,147 @@ +--- +title: Preface +prev: books/ipfw-acknowledgments +next: books/ipfw-primer/ipfw-introduction +description: Preface for IPFW Book +tags: ["preface", "prompts", "conventions"] +showBookMenu: true +weight: 10 +path: "/books/ipfw-primer/ipfw-preface/" +--- + +[preface] +[[ipfw-preface]] += Preface +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + +[[preface-conventions]] + +This page describes the conventions used in this book. + +[[preface-prompts]] +== Shell Prompts + +This table shows the default system prompt and superuser prompt. +The examples use these prompts to indicate which type of user is running the example. + +[.informaltable] +[cols="1,2", frame="none", options="header"] +|=== +| User +| Prompt +|Normal user +|% +|`root` +|# +|=== + +== Typographic Conventions +This table shows various typographic conventions used throughout the text. + +[.informaltable] +[cols="1,2", frame="none", options="header"] +|=== +| Meaning +| Examples + + +|Data, sysctls, things to note. +|`1234`, `net.inet.ip.forwarding`, `em0` + +|The names of files. +|Edit [.filename]#.login#. + +|On-screen computer output. +Output #highlighting#. +a| + +[subs=+quotes] +---- +You have mail. +Read it #very closely#. +---- + +|What the user types, contrasted with on-screen computer output. +a| + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +00100 check-state :default +---- + +|Manual page references. +|Use man:su[1] to change user identity. + +|Emphasis levels +|_Emphasis_. *Stronger emphasis*. *_Strongest emphasis_*. + +|Environment variables. +|`$HOME` is set to the user's home directory. +|=== + +[[preface-notes]] +== Notes, Tips, Important Information, Warnings, and Examples + +Notes, warnings, and examples appear within the text. + +[NOTE] +==== +Notes are represented like this, and contain information to take note of, as it may affect what the user does. +==== + +[TIP] +==== + +Tips are represented like this, and contain information helpful to the user, such as showing an easier way to do something. +==== + +[IMPORTANT] +==== +Important information is represented like this. +Typically, these show extra steps the user may need to take. +==== + +[WARNING] +==== + +Warnings are represented like this, and contain information warning about possible damage if the instructions are not followed. +This damage may be physical, to the hardware or the user, or it may be non-physical, such as the inadvertent deletion of important files. +==== + +.A Sample Example +[example] +==== +Examples are represented like this, and typically contain examples showing a walkthrough, or the results of a particular action. +==== + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-preface/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-preface/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-preface/_index.po @@ -0,0 +1,259 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:1 +#, no-wrap +msgid "Preface for IPFW Book" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:1 +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:14 +#, no-wrap +msgid "Preface" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:50 +msgid "This page describes the conventions used in this book." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:52 +#, no-wrap +msgid "Shell Prompts" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:56 +msgid "" +"This table shows the default system prompt and superuser prompt. The " +"examples use these prompts to indicate which type of user is running the " +"example." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:61 +#, no-wrap +msgid "User" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:62 +#, no-wrap +msgid "Prompt" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:63 +#, no-wrap +msgid "Normal user" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:64 +#, no-wrap +msgid "%" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:65 +#, no-wrap +msgid "`root`" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:66 +#, no-wrap +msgid "#" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:68 +#, no-wrap +msgid "Typographic Conventions" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:70 +msgid "" +"This table shows various typographic conventions used throughout the text." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:75 +#, no-wrap +msgid "Meaning" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:78 +#, no-wrap +msgid "Examples" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:79 +#, no-wrap +msgid "Data, sysctls, things to note." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:81 +#, no-wrap +msgid "`1234`, `net.inet.ip.forwarding`, `em0`" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:82 +#, no-wrap +msgid "The names of files." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:84 +#, no-wrap +msgid "Edit [.filename]#.login#." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:86 +#, no-wrap +msgid "" +"On-screen computer output.\n" +"Output #highlighting#." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:94 +#, no-wrap +msgid "" +"[subs=+quotes]\n" +"----\n" +"You have mail.\n" +"Read it #very closely#.\n" +"----" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:95 +#, no-wrap +msgid "What the user types, contrasted with on-screen computer output." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:103 +#, no-wrap +msgid "" +"[subs=+quotes]\n" +"----\n" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"----" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:104 +#, no-wrap +msgid "Manual page references." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:106 +#, no-wrap +msgid "Use man:su[1] to change user identity." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:107 +#, no-wrap +msgid "Emphasis levels" +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:109 +#, no-wrap +msgid "_Emphasis_. *Stronger emphasis*. *_Strongest emphasis_*." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:110 +#, no-wrap +msgid "Environment variables." +msgstr "" + +#. type: Table +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:111 +#, no-wrap +msgid "`$HOME` is set to the user's home directory." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:114 +#, no-wrap +msgid "Notes, Tips, Important Information, Warnings, and Examples" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:117 +msgid "Notes, warnings, and examples appear within the text." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:121 +msgid "" +"Notes are represented like this, and contain information to take note of, as " +"it may affect what the user does." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:127 +msgid "" +"Tips are represented like this, and contain information helpful to the user, " +"such as showing an easier way to do something." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:133 +msgid "" +"Important information is represented like this. Typically, these show extra " +"steps the user may need to take." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:140 +msgid "" +"Warnings are represented like this, and contain information warning about " +"possible damage if the instructions are not followed. This damage may be " +"physical, to the hardware or the user, or it may be non-physical, such as " +"the inadvertent deletion of important files." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:142 +#, no-wrap +msgid "A Sample Example" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-preface/_index.adoc:146 +msgid "" +"Examples are represented like this, and typically contain examples showing a " +"walkthrough, or the results of a particular action." +msgstr "" diff --git a/documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc b/documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc @@ -0,0 +1,3526 @@ +--- +title: Chapter 3. IPFW Rules +prev: books/ipfw-primer/ipfw-operation +next: books/ipfw-primer/ipfw-dummynet +description: Creating and Using IPFW Rules +tags: ["rules", "IPFW", "firewall", "git"] +showBookMenu: true +weight: 40 +path: "/books/ipfw-primer/ipfw-rules/" +--- + +[[ipfw-rules]] += IPFW Rules +:doctype: book +:toc: macro +:toclevels: 4 +:icons: font +:sectnums: +:sectnumlevels: 4 +:sectnumoffset: 3 +:partnums: +:source-highlighter: rouge +:experimental: +:images-path: books/ipfw-primer/ + +ifdef::env-beastie[] +ifdef::backend-html5[] +:imagesdir: ../../../../images/{images-path} +endif::[] +ifndef::book[] +include::shared/authors.adoc[] +include::shared/mirrors.adoc[] +include::shared/releases.adoc[] +include::shared/attributes/attributes-{{% lang %}}.adoc[] +include::shared/{{% lang %}}/teams.adoc[] +include::shared/{{% lang %}}/mailing-lists.adoc[] +include::shared/{{% lang %}}/urls.adoc[] +toc::[] +endif::[] +ifdef::backend-pdf,backend-epub3[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] +endif::[] + +ifndef::env-beastie[] +toc::[] +include::../../../../../shared/asciidoctor.adoc[] +endif::[] + + +The manual page for man:ipfw[8] lists the entire command syntax including those for general ruleset construction. +In this book, basic traffic rules are discussed first and more complex capabilities are discussed in later sections. +Each section builds on the previous sections so the reader will be better positioned to understand the advanced material later in the book. + +Almost all the examples in this section can be run on the architecture used in the previous chapter, specifically that of crossref:ipfw-operation[ipfw-intro-simple-lab, "Chapter 2, Figure 1"]. +See that section for guidance on setting things back up. +indexterm:[Quick Start] +Ensure IPv4 addressing is set up as shown in crossref:ipfw-operation[ipfw-intro-simple-lab, "Chapter 2, Figure 1"]. + +*ipfw* rules have the general format of: +indexterm:[rule, general format] + +==== +# *ipfw* command [rule_number] [*set* set_number] [*prob* match_probability] _action_ + [*log* [*logamount* number]] [*altq* queue] [{*tag* | *untag*} number] _body_ +==== + +Bolded keywords indicate literal option text that is added to a rule. +Italicized keywords indicate a block of additional content that is rule dependent. + +The rule body has its own syntax format: +indexterm:[rule, rule body] + +==== +[ proto *from* src *to* dst ] [ options ] +==== + +Here is an example with basic syntax for an entire rule: +indexterm:[rule, example syntax] + +[[ipfw-rules-rulecallouts]] +.Description of *ipfw* Rule Syntax +image::ipfw-rules-rulecallouts.png["Description of *ipfw* Rule Syntax. Refer to paragraphs below."] + +. The FreeBSD *ipfw* shell command +. The *ipfw* rule command (add) +. The optional rule number (1000) +. An optional set keyword and value (set 2) +. An optional probability keyword and value (prob 0.5) +. The rule action keyword (deny) +. An optional log keyword (log) +. An optional logamount keyword and value (logamount 50000) +. An optional altq keyword and value (altq red) +. An optional tag keyword and value (tag 27) +. The body of the rule starting with a protocol keyword (tcp) +. A source direction keyword (from) +. A source address (any internet address) +. A destination keyword (to) +. A destination address (any interface on the local system) +. A destination port number (8081) +. A comment. +Note that comments are only valid in the match pattern section of a rule. + +The example in the above figure would not actually load - there is no man:altq[9] queue named `red` set up yet - but it does show the overall format of how rules are constructed. +This example also shows the use of the Unix line continuation convention using a single backslash at the end of the line (with no following spaces) to continue to the next line. + +The essence of *ipfw* rule processing is found when patterns that are defined in the rule body are matched on incoming or outgoing packets, one at a time and the action keywords are processed in turn. + +In other words, *ipfw* directs traffic flow by first matching each incoming or outgoing packet against patterns supplied within the body of the rule. +The patterns include protocols (tcp, udp, igmp, eigrp, etc.), source and destination addresses and ports, and options that apply to the context of the traffic. + +== Practical Ruleset Development + +This section concentrates on the basic commands and actions. +indexterm:[ruleset, development] + +The basic command keywords are these: +indexterm:[rule, basic keywords] + +[programlisting] +==== +* *enable/disable* - commands to disable or enable *ipfw* rule processing. +The kernel module remains loaded - the effect is to suspend or resume rule processing. +This is important to understand early as these commands function like an 'on/off' switch to firewall operation. +* *add* - adds a rule. +* *delete* - deletes a rule. +The rule number must be specified - for example, *ipfw delete 1000*. +* *list* - lists the contents of the current ruleset. +Even if there have been no rules added, the list command should always list out the default rule, by default, `65535 deny ip from any to any`. +* *show* - similar to the *list* command, *show* includes counters for each rule. +* *flush* - delete all the rules in the ruleset except for rules in set 31. +(Sets are described later in this Chapter.) +Since this is a command with enormous impact, a *_Yes/No_* prompt is issued before continuing. +==== + +indexterm:[enable/disable] indexterm:[add] indexterm:[delete] indexterm:[list] indexterm:[show] indexterm:[flush] + +The basic traffic flow action keywords are these: + +[programlisting] +==== +* *allow* | *accept* | *pass* | *permit* - direct *ipfw* to allow a packet through this rule should the packet match the rule body. +* *count* - increment a counter applied to a rule. +No other processing is applied to the packet. +* *deny* | *drop* - do not allow a packet to pass through this rule should the packet match the rule body. +* *check-state* [*:flowname* | *:any*] - check if a dynamic rule already exists. +* *reset* - resets Network Address Translation tables. +==== + +indexterm:[allow/accept/pass/permit] indexterm:[count] indexterm:[deny/drop] indexterm:[check-state] indexterm:[reset] + +The man:ipfw[8] man page has the complete list of action keywords, and describes each in detail. + +This text also examines these keywords in the rules section: + +[programlisting] +==== +* *prob* - assign a probability (a value between 0 and 1) to the rule action +* *set* - use a collection of rules +* *tag* and *untag* - apply an internal tag to a packet affected by the rule +* *log* and *logamount* - log keywords + +* *reset* - send a TCP reset on a connection +* *tee* - cause packets to flow in multiple ways +* *unreach* - specify an action if a packet's destination is unreachable +* *setdscp* - set DiffServe parameters for outbound packets +* *skipto* - jump around a ruleset +* *divert* - pull packets into userspace for programmatic purposes +* *limit* - limit the number of active connections +* *call* and *return* - another way to jump around a ruleset +* *lookup tables* and the *lookup* keyword - value selection keywords +==== + +indexterm:[prob] indexterm:[set] indexterm:[tag] indexterm:[log/logamount] indexterm:[reset] indexterm:[tee] indexterm:[unreach] indexterm:[setdscp] indexterm:[skipto] indexterm:[divert] indexterm:[limit] indexterm:[call/return] indexterm:[lookup tables] indexterm:[lookup] + +Most action keywords, such as `allow` or `deny`, determine traffic flow. +It is important to become familiar with these actions as they will be used in almost every rule. +In addition, carefully note what *ipfw* does _after_ it matches a packet and applies an action - it either terminates its search, or it goes on to the next rule. + +Other action keywords perform an activity that does not have any impact on traffic flow. +For example, the *count* action simply updates counters that apply to a rule. +It has no effect on traffic flow and *ipfw* continues processing with the next rule. + +Recall that *ipfw* is a command line program that uses all the words on the command line as parameters. +In developing rules, remember that certain constructs such as braces ({,}), brackets ([,]) and even parentheses themselves are all recognized by the shell and must be escaped with a backslash '\'. +indexterm:[rule, syntax constructs] +The man:ipfw[8] man page has additional caveats on rule syntax. + +To begin, shutdown all VMs and create the network architecture shown in crossref:ipfw-operation[ipfw-intro-simple-lab, "Chapter 2, Figure 1"], including the required IP addresses. + +[subs=+quotes] +---- +# */bin/sh mkbr.sh reset bridge0 tap0 tap1 _intf_* <--- use the appropriate interface on the FreeBSD host +---- + +Start up the *firewall* VM, *external1* VM, and the *tmux* multiplexer for use with both VMs: + +[subs=+quotes] +---- +% *sudo /bin/sh firewall.sh* +% *sudo /bin/sh external.sh* +% */bin/sh swim.sh* +---- + +On the *firewall* VM, load the *ipfw.ko* kernel module and start the *tserv.sh* service to listen for incoming connections. +indexterm:[tserv.sh] + +Below is the smallest possible ruleset that permits the *external1* VM to make a TCP connection to the service running on the *firewall* VM. + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +00100 check-state :default +# *ipfw add 1000 allow tcp from any to me 5656 in via em0 setup keep-state* +01000 allow tcp from any to me 5656 in via em0 setup keep-state :default +---- + +Test this ruleset immediately by again running *sh tserv.sh* on the *firewall* VM and *sh tcon.sh 5656* script on the *external1* VM as described in the previous chapter. +indexterm:[tserv.sh] indexterm:[tcon.sh] +The connection should succeed. + +Rule 100 contains the *check-state* option. +It checks to see if a connection is already established and a dynamic rule is in place. +indexterm:[rule, dynamic] +If so, any additional packets matching the dynamic rule would be passed. +"Dynamic rules" are discussed shortly. + +Rule 1000 contains the *add* command. +This command inserts the requested rule into the *ipfw* ruleset where it can process packets against the specified actions in the rule body. +indexterm:[rule, add] +The rule itself contains the *allow* keyword, which permits traffic to pass. +indexterm:[rule, allow] + +The rule also uses the *setup* and *keep-state* options to create a dynamic rule for the connection. +indexterm:[rule, setup] indexterm:[rule, keep-state] + +In a stateful firewall like *ipfw*, once a connection from an external host to an internal host is established, the firewall creates a dynamic rule permitting continued traffic along this path until the connection is reset. + +Note that without the `check-state` keyword, no check for a dynamic rule is performed and without the `keep-state`, no creation of a dynamic rule is performed. + +Consider this ruleset with just a single rule: + + +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from any to me 5656* +---- + +This rule looks like it should work, *_but it does not_*. +A TCP packet entering *ipfw* has no pre-existing dynamic rule. +Further, the rule does not create one. +And, because there is no corresponding rule for outbound traffic, no TCP 3-way handshake is ever completed. +indexterm:[TCP, 3-way handshake] +Note that a SYN packet _is_ received by the firewall, but _not_ by the destination service. + +By adding the rule: + +[subs=+quotes] +---- +# *ipfw add 2000 allow tcp from me to any* +---- + +the TCP 3-way handshake *is* allowed to complete and the data is sent from the *external1* VM host to the *tserv.sh* process running on the *firewall* VM. + +While this method works, it uses two rules instead of one. +In this case, the better solution is to use the *setup*, *keep-state*, and *check-state* options early in the ruleset as shown in the original example in this section. + +== Dynamic Rules + +So, what exactly are "dynamic rules"? +indexterm:[rule, dynamic] +The scripts being used close the TCP connection each time, so the dynamic rules are short lived, and cannot be easily examined. + +To see dynamic rules in action, unload and reload the *ipfw* kernel module, and re-enter the original ruleset from the previous section. + +Then manually set up an `ncat` listener on the *firewall* VM and send data with an `ncat` sender on the *external1* VM: +indexterm:[ncat] + +On the *firewall* VM, start up the listener service manually: + +[subs=+quotes] +---- +# *ncat -l 203.0.113.50 5656* +---- + +Then, on the *external1* VM, use ncat to connect to the service on the firewall and type a message: + +[subs=+quotes] +---- +# *ncat 203.0.113.50 5656* +*hello there* +^C +---- + +The message should appear on the console of the *firewall* VM. +If it does not, ensure that the original rule from the previous section is active. + +[[ipfw-rules-dynamic01]] +.Manually Creating Traffic to Examine Dynamic Rules +image::ipfw-rules020.png["Manually Creating Traffic to Examine Dynamic Rules. Refer to paragraphs below."] + +The above figure shows the connection is open between the *external1* and *firewall* VMs. +indexterm:[rule, manually create dynamic] + +While the connection is still open, run the following command on the *firewall* VM serial console: +indexterm:[rule, viewing dynamic] + +[[ipfw-rules-dynamic02]] +.Viewing Dynamic Rules +image::ipfw-rules025.png["Viewing Dynamic Rules. Refer to paragraphs below."] + +Output is similar to that in the above figure. + +The `-d` option displays dynamic rules in addition to regular rules. +indexterm:[ipfw, -d] indexterm:[ipfw, -D] +The `-D` option displays just dynamic rules. + +[[ipfw-rules-numbering-notes]] +=== Notes on Rule Numbering + +Each rule is assigned a rule number, even if one is not specified. +indexterm:[rule, numbering] +The details for rule number handing are found in the man:ipfw[8] man page. +Note that rules are assigned numbers in increments specified by the sysctl `net.inet.ip.fw.autoinc_step`. +indexterm:[sysctl, net.inet.ip.fw.autoinc_step] + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.autoinc_step* +net.inet.ip.fw.autoinc_step: 100 +---- + +Restart with a simple check-state rule and note that *ipfw* has assigned a number associated with the increment sysctl shown above: + +[subs=+quotes] +---- +Flush the *ipfw* ruleset first. + +# *ipfw -q flush* +# *ipfw add check-state* +00000 check-state :default + +# *ipfw list* +00100 check-state :default +65535 deny ip from any to any00000 check-state :default +---- + +*ipfw* has automatically assigned the rule number 100. +While it can be convenient to have *ipfw* add a rule number automatically, it is best to *_always_* assign rule numbers yourself. +This ensures a deliberate decision was made to put a rule in a specific place within the ruleset. +With large rulesets this is critical. +A rule automatically assigned by *ipfw* can be placed where it can have an unexpected effect. + +Consider this ruleset: + +[subs=+quotes] +---- +# *ipfw list* +00300 deny ip from any to 200.200.200.200 +00400 deny ip from any to 200.200.200.201 +00500 deny ip from any to 200.200.200.202 +00600 deny ip from any to 200.200.200.203 +00700 deny ip from any to 200.200.200.204 +00800 deny ip from any to 200.200.200.205 +00800 deny ip from any to 200.200.200.206 +65535 deny ip from any to any +---- + +Having forgotten to add the check-state rule the firewall admin quickly adds it: + +[subs=+quotes] +---- +# *ipfw add check-state* +00000 check-state :default +---- + +resulting in the unintentional placement: + +[subs=+quotes] +---- +# *ipfw list* +00300 deny ip from any to 200.200.200.200 +00400 deny ip from any to 200.200.200.200 +00500 deny ip from any to 200.200.200.200 +00600 deny ip from any to 200.200.200.200 +00700 deny ip from any to 200.200.200.200 +00800 deny ip from any to 200.200.200.200 +00800 deny ip from any to 200.200.200.200 +#00900 check-state :default# +65535 deny ip from any to any +---- + +Also, *ipfw* allows rules with the same rule number to be added to the ruleset, and it will keep track of the rules in the order they were entered. +indexterm:[rule, same number] +This is easy to forget when manually entering rules from the command line and using command line editing to change something simple like the last byte of an IP address. + +It is important to remember that all such rules are affected by commands that operate on one or more lines, such as the *delete* command: + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +00100 check-state :default +# *ipfw add #1000# allow tcp from 203.0.113.10 to me 5656 setup keep-state* +01000 allow tcp from 203.0.113.10 to me 5656 keep-state :default +# *ipfw add #1000# allow tcp from 203.0.113.20 to me 5656 setup keep-state* +01000 allow tcp from 203.0.113.20 to me 5656 keep-state :default +# *ipfw add #1000# allow tcp from 203.0.113.30 to me 5656 setup keep-state* +01000 allow tcp from 203.0.113.30 to me 5656 keep-state :default +# *ipfw add #1000# allow tcp from 203.0.113.40 to me 5656 setup keep-state* +01000 allow tcp from 203.0.113.40 to me 5656 keep-state :default +# +# *ipfw list* +00100 check-state :default +01000 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +01000 allow tcp from 203.0.113.20 to me 5656 setup keep-state :default +01000 allow tcp from 203.0.113.30 to me 5656 setup keep-state :default +01000 allow tcp from 203.0.113.40 to me 5656 setup keep-state :default +65535 deny ip from any to any +# +# *ipfw delete 1000* +# +# *ipfw list* +00100 check-state :default +65535 deny ip from any to any +---- + +The *delete* command can also process both ranges and lists of rules. +indexterm:[rule, delete] + +Consider the following ruleset: + +[subs=+quotes] +---- +# *ipfw list* +00100 check-state :default +01000 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +01100 allow tcp from 203.0.113.11 to me 5656 setup keep-state :default +01200 allow tcp from 203.0.113.12 to me 5656 setup keep-state :default +01300 allow tcp from 203.0.113.13 to me 5656 setup keep-state :default +02000 allow tcp from 203.0.113.20 to me 5656 setup keep-state :default +02100 allow tcp from 203.0.113.21 to me 5656 setup keep-state :default +02200 allow tcp from 203.0.113.22 to me 5656 setup keep-state :default +02300 allow tcp from 203.0.113.23 to me 5656 setup keep-state :default +03000 allow tcp from 203.0.113.30 to me 5656 setup keep-state :default +03100 allow tcp from 203.0.113.31 to me 5656 setup keep-state :default +03200 allow tcp from 203.0.113.32 to me 5656 setup keep-state :default +03300 allow tcp from 203.0.113.33 to me 5656 setup keep-state :default +04000 allow tcp from 203.0.113.40 to me 5656 setup keep-state :default +04100 allow tcp from 203.0.113.41 to me 5656 setup keep-state :default +04200 allow tcp from 203.0.113.42 to me 5656 setup keep-state :default +04300 allow tcp from 203.0.113.43 to me 5656 setup keep-state :default +04400 allow tcp from 203.0.113.44 to me 5656 setup keep-state :default +04500 allow tcp from 203.0.113.45 to me 5656 setup keep-state :default +04600 allow tcp from 203.0.113.46 to me 5656 setup keep-state :default +04700 allow tcp from 203.0.113.47 to me 5656 setup keep-state :default +04800 allow tcp from 203.0.113.48 to me 5656 setup keep-state :default +04900 allow tcp from 203.0.113.49 to me 5656 setup keep-state :default +65535 deny ip from any to any +---- + +A *range* is specified by two number separated by a dash: for example 5000-7350; whereas a *list* is a space-separated collection of numbers on the command line. +indexterm:[rule, number range] indexterm:[rule, number list] + +The following command deletes rules from 1000 to 2999 and certain rules between 4000 and 5000: + +[subs=+quotes] +---- +# *ipfw delete 1000-2999 4100 4300 4500 4700 4900* +# +# *ipfw list* +00100 check-state :default +03000 allow tcp from 203.0.113.30 to me 5656 keep-state :default +03100 allow tcp from 203.0.113.31 to me 5656 keep-state :default +03200 allow tcp from 203.0.113.32 to me 5656 keep-state :default +03300 allow tcp from 203.0.113.33 to me 5656 keep-state :default +04000 allow tcp from 203.0.113.40 to me 5656 keep-state :default +04200 allow tcp from 203.0.113.42 to me 5656 keep-state :default +04400 allow tcp from 203.0.113.44 to me 5656 keep-state :default +04600 allow tcp from 203.0.113.46 to me 5656 keep-state :default +04800 allow tcp from 203.0.113.48 to me 5656 keep-state :default +65535 deny ip from any to any +---- + +Note that the *delete* command _will_ operate on comma separated values, but the *delete* command will only remove the *_first_* value in a comma separated list, not the entire list. +The command does not throw an error, but it does not delete all the lines requested. + +[subs=+quotes] +---- +# *ipfw delete 3100,3200,3300* +# *echo $?* +0 #<--- No error found with the previous command.# +# +# *ipfw list* +00100 check-state :default +03000 allow tcp from 203.0.113.30 to me 5656 keep-state :default +#03200 allow tcp from 203.0.113.32 to me 5656 keep-state :default# +#03300 allow tcp from 203.0.113.33 to me 5656 keep-state :default# +04000 allow tcp from 203.0.113.40 to me 5656 keep-state :default +04200 allow tcp from 203.0.113.42 to me 5656 keep-state :default +04400 allow tcp from 203.0.113.44 to me 5656 keep-state :default +04600 allow tcp from 203.0.113.46 to me 5656 keep-state :default +04800 allow tcp from 203.0.113.48 to me 5656 keep-state :default +65535 deny ip from any to any +---- + +The *show* command is similar to the *list* command but it also includes a packet count and byte count for each rule. +indexterm:[rule, show] + +Stop any existing scripts on the *firewall* VM and run *sh userv3.sh*. +indexterm:[userv3.sh] +Then create the following ruleset on the *firewall* VM: +indexterm:[rule, flush] indexterm:[rule, list] + +[subs=+quotes] +---- +# *ipfw -q flush* +# +# *ipfw add 100 check-state* +00100 check-state :default +# *ipfw add 1000 allow udp from 203.0.113.10 to me 5656* +01000 allow udp from 203.0.113.10 to me 5656 +# *ipfw add 2000 allow udp from 203.0.113.10 to me 5657* +02000 allow udp from 203.0.113.10 to me 5657 +# *ipfw add 3000 allow udp from 203.0.113.10 to me 5658* +03000 allow udp from 203.0.113.10 to me 5658 +# *ipfw add 4000 allow udp from 203.0.113.10 to me 5659* +04000 allow udp from 203.0.113.10 to me 5659 +# +# *ipfw list* +00100 check-state :default +01000 allow udp from 203.0.113.10 to me 5656 +02000 allow udp from 203.0.113.10 to me 5657 +03000 allow udp from 203.0.113.10 to me 5658 +04000 allow udp from 203.0.113.10 to me 5659 +65535 deny ip from any to any +---- + +Then, on the *external1* VM, run *sh uconr.sh 5656 1* script to send packets to ports 5656, 5657, and 5658, randomly: +indexterm:[uconr.sh] + +[subs=+quotes] +---- +# *sh uconr.sh 5656 1* +PORT1 = [5656] +SLEEPVAL = [1] +UDP packet from [203.0.113.10],[5656],[1] +UDP packet from [203.0.113.10],[5656],[2] +UDP packet from [203.0.113.10],[5658],[3] +UDP packet from [203.0.113.10],[5657],[4] +UDP packet from [203.0.113.10],[5659],[5] +UDP packet from [203.0.113.10],[5659],[6] +UDP packet from [203.0.113.10],[5659],[7] +UDP packet from [203.0.113.10],[5656],[8] +UDP packet from [203.0.113.10],[5658],[9] +UDP packet from [203.0.113.10],[5659],[10] +UDP packet from [203.0.113.10],[5658],[11] +UDP packet from [203.0.113.10],[5656],[12] +UDP packet from [203.0.113.10],[5656],[13] +UDP packet from [203.0.113.10],[5656],[14] +UDP packet from [203.0.113.10],[5659],[15] +UDP packet from [203.0.113.10],[5656],[16] +UDP packet from [203.0.113.10],[5657],[17] +UDP packet from [203.0.113.10],[5659],[18] +UDP packet from [203.0.113.10],[5659],[19] +UDP packet from [203.0.113.10],[5657],[20] +UDP packet from [203.0.113.10],[5659],[21] +^C +---- + +Running the *ipfw show* command outputs: +indexterm:[rule, show] + +[subs=+quotes] +---- +# *ipfw show* +00100 #0 0# check-state :default +01000 #7 494# allow udp from 203.0.113.10 to me 5656 +02000 #3 212# allow udp from 203.0.113.10 to me 5657 +03000 #3 211# allow udp from 203.0.113.10 to me 5658 +04000 #8 565# allow udp from 203.0.113.10 to me 5659 +65535 #11 897# deny ip from any to any +---- + +The output shows the number of packets and the number of bytes processed by each rule, including the default rule which may have processed many more packets. + +This is a useful tool for debugging. +Paired with the *zero* command which can clear counters with precise rule selection, it can show what rules are still processing a rule match. +indexterm:[rule, zero] + +The *zero* command takes a space separated list of rules (similar to the *delete* command) to clear counters. +indexterm:[clear counters] +However, unlike the *delete* command, ranges (e.g 2000-3000) are not allowed. + +[subs=+quotes] +---- +# *ipfw zero 2000 3000* +# +# *ipfw show* +00100 0 0 check-state :default +01000 7 494 allow udp from 203.0.113.10 to me 5656 +02000 #0 0# allow udp from 203.0.113.10 to me 5657 +03000 #0 0# allow udp from 203.0.113.10 to me 5658 +04000 8 565 allow udp from 203.0.113.10 to me 5659 +65535 11 897 deny ip from any to any +---- + +Clearing all rule match counters can be done with *ipfw zero* with no parameters. + +Clearing the default rule match counter can be done with *ipfw zero 65535*. +indexterm:[rule, zero default rule] + +Counters are also a feature of rules that specify the *log* keyword. +indexterm:[log] indexterm:[counters] +An example of this is shown below when discussing the *log* and *logamount* keywords. + +== Keywords + +=== Protocols +Protocols are those defined by link:https://www.iana.org/[IANA - the Internet Assigned Numbers Authority (https://www.iana.org)] and are included in Unix systems in [.filename]#/etc/protocols#. +indexterm:[IANA] +This file identifies what numbers are assigned to common (and some very obscure) protocols - *ip* (0), *tcp* (6), *udp* (17), *icmp* (1), and many others. +indexterm:[protocol, /etc/protocols] + +Source and destination protocols can be the conventional IP or IPv6 addresses. +However, the man:ipfw[8] manual page has this more detailed explanation: + +==== +"The first part (proto from src to dst) is for backward compatibility with earlier versions of FreeBSD. +In modern FreeBSD any match pattern (including MAC headers, IP protocols, addresses and ports) can be specified in the options section." +==== + +The *ipfw* keywords for common protocols include: +indexterm:[protocol, keywords] +==== +*ip4* | *ipv4* Matches IPv4 packets. + +*ip6* | *ipv6* Matches IPv6 packets. + +*ip* | *all* Matches any IP packet. +==== + +The logical operator "*or*" can be use to combine multiple protocols where any one of them applies. +indexterm:[operator, or] +The "*{*" and "*}*" braces can be used to group "*or*" conditions (known as "*or-blocks*"). +indexterm:[or-block] +Only one level of braces can be used. +Braces must be escaped with a backslash '\' to prevent them from being interpreted directly by the command line shell: + +[subs=+quotes] +---- +# *ipfw add 1100 deny \{ tcp or udp or eigrp or chaos \} from 1.2.3.4 to 5.6.7.8* +01100 deny { tcp or udp or eigrp or chaos } from 1.2.3.4 to 5.6.7.8 +---- + +Consider this ruleset in a shell script: +indexterm:[protocol, list] + +--- + +#!/bin/sh + +ipfw add 5000 deny \{ icmp or ip or igmp or ggp or ipencap or st2 or tcp or cbt or egp or igp or bbn-rcc or nvp or pup or argus or emcon or xnet or chaos or udp or mux or dcn or hmp or prm or xns-idp or trunk-1 or trunk-2 or leaf-1 or leaf-2 or rdp or irtp or iso-tp4 or netblt or mfe-nsp or merit-inp or dccp or 3pc or idpr or xtp or ddp or idpr-cmtp or tp++ or il or ipv6 or sdrp or ipv6-route or ipv6-frag or idrp or rsvp or gre or dsr or bna or esp or ah or i-nlsp or swipe or narp or mobile or tlsp or skip or ipv6-icmp or ipv6-nonxt or ipv6-opts or cftp or sat-expak or kryptolan or rvd or ippc or sat-mon or visa or ipcv or cpnx or cphb or wsn or pvp or br-sat-mon or sun-nd or wb-mon or wb-expak or iso-ip or vmtp or secure-vmtp or vines or ttp or nsfnet-igp or dgp or tcf or eigrp or ospf or sprite-rpc or larp or mtp or ax.25 or ipip or micp or scc-sp or etherip or encap or gmtp or ifmp or pnni or pim or aris or scps or qnx or a/n or ipcomp or snp or compaq-peer or ipx-in-ip or carp or pgm or l2tp or ddx or iatp or stp or srp or uti or smp or sm or ptp or isis or fire or crtp or crudp or sscopmce or iplt or sps or pipe or sctp or fc or rsvp-e2e-ignore or mobility-header or udplite or mpls-in-ip or manet or hip or shim6 or wesp or rohc or pfsync or divert \} from any to me + +exit + +--- + +Note that the above file is shown as one very long line and does not use the Unix line continuation convention. + +This command will deny all traffic using all protocols defined in [.filename]#/etc/protocols#. +The above command will complete successfully. +However, due to a bug in the "*or-block*" parser, the rule cannot have the "*ip*" protocol first. +indexterm:[or-block] +Swapping the first two protocols - *icmp* and *ip* - the command throws an error. + +For example, + +[subs=+quotes] +---- +# *ipfw add 1000 deny \{ igmp or ip or eigrp \} from any to me* +---- + +works Ok but + +[subs=+quotes] +---- +# *ipfw add 1000 deny \{ ip or igmp or eigrp \} from any to me* +ipfw: invalid OR block +---- + +fails. + + +The use of the logical "*and*" operator in a protocol block is an error. +indexterm:[keyword, and] +A packet can be in only one protocol at a time. +However, the use of the logical "*not*" operator *is* permitted in front of a protocol identifier: +indexterm:[keyword, not] + +[subs=+quotes] +---- +# *ipfw add 1000 deny \{ icmp or not igmp \} from any to me* +---- + +Careful consideration of all logical conditions is essential to correct operation of a ruleset. + +[NOTE] +==== +In later versions of FreeBSD, the use of the protocol "*or-block*" is noted as deprecated in man:ipfw[8] but the operation may still complete successfully until the feature is removed completely. +==== + +=== Addresses + +Source and destination addresses can be any of the following: +indexterm:[rule, addresses] indexterm:[keyword, any] indexterm:[keyword, me] indexterm:[me6] + +==== +* *IPv4* or *IPv6* addresses +* *any* - matches any IP address. +* *me* - matches any IP address configured on an interface in the system. +==== + +Note that the interface does not have to have an IP or IPv6 address, *_nor does it have to be up or even exist_* at the time the rule is entered. +Thus, be aware that a rule with keyword *me* may affect traffic on interfaces that are configured at a later time. +Consider the following system interface list: + +[subs=+quotes] +---- +# *ifconfig -a* +em0: flags=8863 metric 0 mtu 1500 + options=481209b + ether 02:49:50:46:57:41 + inet 203.0.113.50 netmask 0xffffff00 broadcast 203.0.113.255 + media: Ethernet autoselect (1000baseT ) + status: active + nd6 options=29 +lo0: flags=8049 metric 0 mtu 16384 + options=680003 + inet6 ::1 prefixlen 128 + inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 + inet 127.0.0.1 netmask 0xff000000 + groups: lo +---- + +The following attempt to add a rule with a non-existent interface succeeds even though there is no `wlan0` interface defined: + +[subs=+quotes] +---- +# *ipfw add 1000 deny tcp from 1.2.4.4 to me via wlan0* +01000 deny tcp from 1.2.4.4 to me via wlan0 +---- + +==== +* *me6* - matches any IPv6 address similarly to the above me keyword. +* *table(name[,value])* - matches any IPv4 or IPv6 address for an entry in the named table. +==== + +indexterm:[table] + +Tables are discussed below in crossref:ipfw-rules[ipfw-rules-lookup-tables-intro, Lookup Tables]. +indexterm:[lookup table] + +IPv4 and IPv6 addresses follow the usual conventions regarding address and mask or prefix length. +Addresses can also be grouped into a list, similar to the capability discussed for protocols above. + +[subs=+quotes] +---- +# *ipfw add 2000 allow tcp from \{ 2.3.4.5/32, 3.4.5.0/24, 10.0.0.0/8 \} to me* + +# *ipfw add 2000 allow tcp from \{ 2607:fcc0:0:35::dd/64, 2608:abcd:0:2300::9eac/64 \} to me* +---- + + +However, IPv4 and IPv6 addresses *_cannot_* be mixed in the same list. +Use two different rules instead. + +For sparse collections of addresses, consider the alternate form allowed by +indexterm:[address, sparse addressing] + +==== +*addr-set: addr[/masklen]{list}* +==== + +such as: + +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from 1.2.3.0/24\{128,9,35-45,7\} to me* +---- + +In this form, lists and increasing ranges are allowed. +indexterm:[address, range] indexterm:[address, list] +*ipfw* will consolidate overlapping ranges, and will reorder the list in the display to show increasing addresses from left to right. +Note that spaces are only allowed after commas between list elements, nowhere else. + +This example does not work due to incorrect placement of spaces: + +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from 1.2.4.0/24\{## ##128,9,25-45,7-25## ##\} to me* +ipfw: missing ``to'' +---- + +This example works by correcting where spaces occur on the command line. + +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from 1.2.4.0/24\{128,9,25-45,7-25\} to me* +01000 allow tcp from 1.2.4.0/24{7-45,128} to me +---- + +As noted, *ipfw* will simplify, reorder, and display the list: + +[subs=+quotes] +---- +# *ipfw list* +01000 allow tcp from 1.2.4.0/24{7-45,128} to me +65535 deny ip from any to any +---- + +Note that ranges *_must_* be defined as increasing. +indexterm:[address, range increasing] +Also, as noted in man:ipfw[8], there is *no* support for sets of IPv6 addresses. + +=== Ports + +Ports may be specified by number or by service name. +indexterm:[keyword, ports] +Service names, also under the provenance of link:https://www.iana.org/[IANA], are found in [.filename]#/etc/services# on Unix systems. +indexterm:[ports, /etc/services] + +Ports can be specified as individual items, lists, or ranges. +Typically ports are used to determine a destination service and so apply to the destination address (although specifying source ports is also permitted): +indexterm:[ports, examples] + +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from 1.2.3.4 to me daytime* +01000 allow tcp from 1.2.3.4 to me 13 + +# *ipfw add 2000 allow tcp from 2.3.4.5 to me ssh, telnet, smtp* +02000 allow tcp from 2.3.4.5 to me 22,23,25 + +# *ipfw add 3000 allow tcp from 3.4.5.6 to me auditd-domain* +03000 allow tcp from 3.4.5.6 to me 48-53 + +# This example uses source and destination ports. +# *ipfw add 4000 allow tcp from 7.8.9.10 3030 to me ssh* +04000 allow tcp from 7.8.9.10 3030 to me 22 +---- + +*General Notes on Port Ranges* +indexterm:[ports, ranges] + +. A range such as that shown above (`auditd-domain`) may accidentally include ports not wanted. +In this case, ports `tacacs (49)`, `re-mail-ck (50)`, `la-maint (51)`, and `xns-time (52)` would be included. +Therefore, always check actual port numbers when using named ranges for ports. ++ +. Some service names include the dash character '-' as part of the name, as in the point above. +In these cases a _double backslash_, is required, one for the shell and one for *ipfw*: ++ +[subs=+quotes] +---- +# *ipfw add 4000 allow tcp from 4.5.6.7 to me ftp, #ftp\\-data#* +04000 allow tcp from 4.5.6.7 to me 21,20 +---- ++ +. Some applications require a range of source and destination ports in both directions. +This is easy to accomplish with ranges and a `keep-state` rule: ++ +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state* +01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default +# +# *ipfw list* +01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default +65535 deny ip from any to any +---- ++ +. The syntactic sugar provided by the match keywords `dst-port` and `src-port` are both part of the match section of the rule: +indexterm:[dst-port] indexterm:[src-port] ++ +[subs=+quotes] +---- +# *ipfw add 1000 allow tcp from 203.0.113.10 to me src-port 3030 dst-port 1010* +01000 allow tcp from 203.0.113.10 3030 to me 1010 +---- + +To test common ports in both directions, manually connect using `ncat`, setting up the source and destination ports as needed: +indexterm:[ncat] + +[subs=+quotes] +---- +# *ipfw -q flush* +# *ipfw add 1000 allow tcp from 203.0.113.10 to me src-port 5200=5205 dst-port 5656-5658 keep-state* +01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default +# *ipfw list* +01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default +65535 deny ip from any to any +---- + +Note: the transmission and reception lines have been aligned on each side. + +[[ipfw-rules-ports00]] +.Manually Testing Common Ports in Both Directions +image::ipfw-rules030.png["Manually Testing Common Ports in Both Directions. Refer to paragraphs below."] + +Note that no connection was achieved when the destination port was out of bounds (5659) and when the source port was out of bounds (5206). + +=== Prob + +The *prob* keyword is used to assign a chance, that is, a probability (a floating point value between 0 and 1), that an incoming packet will be matched. +indexterm:[keyword, prob] indexterm:[prob] +If the chance is successful, the corresponding rule performs the required action. +If the chance is not successful, the rule is not matched and rule processing continues to the next rule. + +To test this keyword, use "*sh ucont.sh 5656 1*" script on the *external1* VM's side to repeatedly send a UDP packet to the *firewall* VM, who is listening on UDP port 5656. +indexterm:[ucont.sh] +Using the *prob* keyword, set a probability of .5 (a 50% chance) that the packet will be matched. +The action is to let the packet pass to the service, which just prints the contents of the packet. + +As shown below, there were 24 out of 50 packets received, very close to 50% for such a small sample: +indexterm:[userv.sh] + +[subs=+quotes] +---- +# *ipfw -q flush* +# +# *ipfw add 3000 prob 0.5 allow udp from any to me 5656* +03000 prob 0.500000 allow udp from any to me 5656 +# +# *ipfw list* +03000 prob 0.500000 allow udp from any to me 5656 +65535 deny ip from any to any +# +# *sh userv.sh 5656* +PORT1 = [5656] +Starting UDP listener on [203.0.113.50],[5656] +UDP packet from [203.0.113.10],[5656],[5] +UDP packet from [203.0.113.10],[5656],[6] +UDP packet from [203.0.113.10],[5656],[7] +UDP packet from [203.0.113.10],[5656],[10] +UDP packet from [203.0.113.10],[5656],[11] +UDP packet from [203.0.113.10],[5656],[13] +UDP packet from [203.0.113.10],[5656],[14] +UDP packet from [203.0.113.10],[5656],[16] +UDP packet from [203.0.113.10],[5656],[19] +UDP packet from [203.0.113.10],[5656],[20] +UDP packet from [203.0.113.10],[5656],[22] +UDP packet from [203.0.113.10],[5656],[28] +UDP packet from [203.0.113.10],[5656],[29] +UDP packet from [203.0.113.10],[5656],[32] +UDP packet from [203.0.113.10],[5656],[33] +UDP packet from [203.0.113.10],[5656],[34] +UDP packet from [203.0.113.10],[5656],[35] +UDP packet from [203.0.113.10],[5656],[37] +UDP packet from [203.0.113.10],[5656],[38] +UDP packet from [203.0.113.10],[5656],[39] +UDP packet from [203.0.113.10],[5656],[41] +UDP packet from [203.0.113.10],[5656],[43] +UDP packet from [203.0.113.10],[5656],[45] +UDP packet from [203.0.113.10],[5656],[49] +^C# +---- + +=== Sets + +Firewall rules can be grouped into different *sets* which can be switched atomically. +indexterm:[keyword, set] indexterm:[sets] +Why use this feature? +Consider a datacenter with two sets of identical servers on separate networks. +One set must be taken down for maintenance. +But first, traffic must be transferred to the other set of servers. +Using *sets* is a practical solution for this problem. + +*Sets* are useful, but they do come with some caveats which are described throughout this section. +indexterm:[sets, caveats] + +The default *set* is *set* 0. +To begin, create rules in *set* 0 and *set* 1 with slight differences between the two. +Note that this example also shows the use of the *ipfw* comment feature - allowing comments on a per-rule basis. +indexterm:[rule, comments] + +[subs=+quotes] +---- +# *ipfw -q flush* +# +# *ipfw add 1000 set 0 check-state* +01000 check-state :default +# +# *ipfw add 1100 set 0 allow tcp from any to me 5656 setup keep-state // 5656 only* +01100 allow tcp from any to me 5656 setup keep-state :default // 5656 only +# +# *ipfw add 2000 set 1 check-state* +02000 check-state :default +# +# *ipfw add 2100 set 1 allow tcp from any to me 5657 setup keep-state // 5657 only* +02100 allow tcp from any to me 5657 setup keep-state :default // 5657 only +# +# *ipfw set show* +enable 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 +---- + +The above *ipfw set show* command lists all enabled sets, here showing both 0 and 1 as enabled. + +From the *external1* VM, commence communications using the *tcon.sh* script as shown below. +indexterm:[tcon.sh] +The first two communications ([1], [2]) are to port 5656, the next two communications are to port 5657 ([3],[4]). +The firewall host shows all four communications received: + +[[ipfw-rules-sets00]] +.Use of Sets +image::ipfw-rules035.png["Use of Sets. Refer to paragraphs below."] + +Right before communication 5, the firewall host admin disabled *set* 0, (*# ipfw set disable 0*) effectively blocking access to port 5656. +indexterm:[set, disable] indexterm:[set, enable] +Disabling *set* 0, effectively removes the rules for port 5656 and so the communications [5] and [6] fail. +The *external1* VM goes back to port 5657 for communications [7] and [8], which are successful. + +Notice that when listing the firewall ruleset with just *ipfw list*, only the *sets* that are enabled actually show up. +To make sure which *sets* are enabled / disabled, use the `-S` flag on the *ipfw* command as shown below. +indexterm:[ipfw, -S] + +[subs=+quotes] +---- +# *ipfw set enable 0* +# +# *ipfw set show* +enable 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 +# +# *ipfw -S list* +01000 set 0 check-state :default +01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only +02000 set 1 check-state :default +02100 set 1 allow tcp from any to me 5657 setup keep-state :default // 5657 only +65535 set 31 deny ip from any to any +# +# *ipfw set disable 0* +# +# *ipfw set show* +disable 0 enable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 +# +# *ipfw -S list* +# DISABLED 01000 set 0 check-state :default +# DISABLED 01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only +02000 set 1 check-state :default +02100 set 1 allow tcp from any to me 5657 setup keep-state :default // 5657 only +65535 set 31 deny ip from any to any +# +---- + +To atomically change from one set to the other use the *ipfw set swap* command: +indexterm:[set, swap] + +[subs=+quotes] +---- +# *ipfw set swap 0 1* +---- + +What actually happens is that *_the rules in the sets get swapped_*; that is, all the rules in *set 0* get put in *set 1* and all the rules in *set 1* get put in *set 0*. + +[subs=+quotes] +---- +# +# *ipfw -S list* +# DISABLED 01000 set 0 check-state :default +# DISABLED 01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only +02000 set 1 check-state :default +02100 set 1 allow tcp from any to me 5657 setup keep-state :default // 5657 only +65535 set 31 deny ip from any to any +# +# *ipfw set swap 0 1* +# +# *ipfw -S list* +01000 set 1 check-state :default +01100 set 1 allow tcp from any to me 5656 setup keep-state :default // 5656 only +# DISABLED 02000 set 0 check-state :default +# DISABLED 02100 set 0 allow tcp from any to me 5657 setup keep-state :default // 5657 only +65535 set 31 deny ip from any to any +---- + +Note carefully that when swapping *sets* where one of the *sets* is disabled, *the set number is still disabled after the swap*, even though the rules are now different. +indexterm:[set, swap disabled] +This can lead to unexpected consequences such as the following: + +[subs=+quotes] +---- +# *ipfw -S list* +01000 set 0 check-state :default +01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only +02000 set 1 check-state :default +02100 set 1 allow tcp from any to me 5660 setup keep-state :default // 5660 only +65535 set 31 deny ip from any to any +# +# *ipfw set disable 0* +# +# *ipfw -S list* +# DISABLED 01000 set 0 check-state :default +# DISABLED 01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only +02000 set 1 check-state :default +02100 set 1 allow tcp from any to me 5660 setup keep-state :default // 5660 only +65535 set 31 deny ip from any to any +# +# *ipfw set swap 0 1* +# +# *ipfw -S list* +01000 set 1 check-state :default +01100 set 1 allow tcp from any to me 5656 setup keep-state :default // 5656 only +# DISABLED 02000 set 0 check-state :default +# DISABLED 02100 set 0 allow tcp from any to me 5660 setup keep-state :default // 5660 only +65535 set 31 deny ip from any to any +---- + +Here *set 0* is disabled, and then swapped. +After the swap, *set 0 is still disabled*, though the rules have changed. + +Note that all sets are initially enabled. +When a set is disabled, say *set 3*, all other sets are still active, even if no rule references them. +Sets are analogous to the pieces on the back row of a chess board. +If a knight or a bishop is removed, that one piece is not able to play, but all the others are able to play. + +*set 31* cannot be deleted or changed. +indexterm:[set, set 31] +It can however partially participate in a swap. + +[subs=+quotes] +---- +# *ipfw set swap 1 31* +---- + +This swap will complete successfully (return code 0), but the effect is not the same as the swaps above. +The default rule in *set 31* is not swapped, but the set number for the other rules (rules in *set 1*) are set to 31: + +[subs=+quotes] +---- +# *ipfw -S list* +01000 set 1 check-state :default +01100 set 1 allow tcp from 1.2.3.4 to me 8080 +01200 set 1 allow tcp from 1.2.3.4 to me 8081 +65535 set 31 deny ip from any to any +# +# *ipfw set swap 1 31* +# +# *ipfw -S list* +01000 set 31 check-state :default +01100 set 31 allow tcp from 1.2.3.4 to me 8080 +01200 set 31 allow tcp from 1.2.3.4 to me 8081 +65535 set 31 deny ip from any to any +---- + +As noted in the man:ipfw[8] manual page, rules in *set 31* cannot be flushed. +indexterm:[set, set 31] +There are now 4 rules in *set 31*: + +[subs=+quotes] +---- +# *ipfw -f flush* +Flushed all rules. +# +# *ipfw -S list* +01000 set 31 check-state :default +01100 set 31 allow tcp from 1.2.3.4 to me 8080 +01200 set 31 allow tcp from 1.2.3.4 to me 8081 +65535 set 31 deny ip from any to any +---- + +While *ipfw flush* did not clean out rules in *set* 31, the command *ipfw delete set 31* will clean out all but the default rule: + +[subs=+quotes] +---- +# *ipfw delete set 31* +# +# *ipfw -S list* +65535 set 31 deny ip from any to any +---- + +Further, note that any *set* that is disabled, remains disabled after a flush. +Thus, when disabling a *set* and then flushing the entire ruleset, any rules added back into the disabled *set* number *_will still be disabled_*. +This includes *set 0*, the default set. +indexterm:[set, set 0 default] + +Consider the following: + +[subs=+quotes] +---- +# *ipfw list* +01000 check-state :default +01100 allow tcp from any to me 1111 +02000 allow tcp from any to me 2222 +03000 allow tcp from any to me 3333 +65535 deny ip from any to any +# +# *ipfw set disable 0* +# +# *ipfw -S list* +# DISABLED 01000 set 0 check-state :default +# DISABLED 01100 set 0 allow tcp from any to me 1111 +# DISABLED 02000 set 0 allow tcp from any to me 2222 +# DISABLED 03000 set 0 allow tcp from any to me 3333 +65535 set 31 deny ip from any to any +# +# *ipfw -f flush* +Flushed all rules. +# +# *ipfw add 100 check-state* +00100 check-state :default +# *ipfw add 200 allow tcp from any to me 5555* +00200 allow tcp from any to me 5555 +# *ipfw add 300 allow tcp from any to me 6666* +00300 allow tcp from any to me 6666 +# *ipfw add 400 allow tcp from any to me 7777* +00400 allow tcp from any to me 7777 +# +# *ipfw -S list* +# #DISABLED 00100 set 0# check-state :default +# #DISABLED 00200 set 0# allow tcp from any to me 5555 +# #DISABLED 00300 set 0# allow tcp from any to me 6666 +# #DISABLED 00400 set 0# allow tcp from any to me 7777 +65535 set 31 deny ip from any to any +# +---- + +Because *set 0* was disabled before the flush, the flush has no effect on the enable/disable state of that *set*. +indexterm:[keyword, flush] + +Note that it is even possible to disable sets of rules _that do not yet exist_: + +[subs=+quotes] +---- +# *kldload ipfw* +ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled +# +# *ipfw -S list* +65535 set 31 deny ip from any to any +# +# *ipfw set show* +enable 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 +# +# *ipfw set disable 4 5 6 7 8 9* +# +# *ipfw set show* +disable 4 5 6 7 8 9 enable 0 1 2 3 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 +# +---- + +Using *sets* can be very helpful, as long as their properties and limitations are clearly understood. + +[[ipfw-rules-tags]] +=== Tags + +*Tags* allow for marking incoming packets in such a way that later rules can be applied based on the *tag*. +indexterm:[rule, tag] indexterm:[tag] + +For a simple example, consider tagging incoming packets from different networks. +Later rules determine if the tagged packets are allowed or denied: +indexterm:[tag, example] + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +00100 check-state :default +# +# *ipfw add 1000 count tag 10 tcp from 172.16.200.0/24 to me 5656* +01000 count tag 10 tcp from 172.16.200.0/24 to me 5656 +# +# *ipfw add 1100 count tag 20 tcp from 172.16.225.0/24 to me 5656* +01100 count tag 20 tcp from 172.16.225.0/24 to me 5656 +# +# *ipfw add 1200 count tag 30 tcp from 203.0.113.0/24 to me 5656* +01200 count tag 30 tcp from 203.0.113.0/24 to me 5656 +# +# *ipfw add 3000 allow tcp from any to me tagged 30 setup keep-state* +03000 allow tcp from any to me tagged 30 setup keep-state :default +# +# *ipfw add 4000 deny tcp from any to me tagged 10,20* +04000 deny tcp from any to me tagged 10,20 +# +---- + +Test this by using man:ncat[1] to set its own source address. +indexterm:[ncat] +To do this, first setup two alias address on the `em0` interface on the *external1* VM: + +[subs=+quotes] +---- +# *ifconfig em0 172.16.200.10/24 alias* +# *ifconfig em0 172.16.225.10/24 alias* +# +# *ifconfig em0* +em0: flags=8843 metric 0 mtu 1500 + options=81209b + ether 02:49:50:46:57:10 + inet 203.0.113.10 netmask 0xffffff00 broadcast 203.0.113.255 + #inet 172.16.200.10 netmask 0xffffff00# broadcast 172.16.200.255 + #inet 172.16.225.10 netmask 0xffffff00# broadcast 172.16.225.255 + media: Ethernet autoselect (1000baseT ) + status: active + nd6 options=29 +---- + + +[[ipfw-rules-tags00]] +.Use of Tags +image::ipfw-rules045.png["Use of Tags. Refer to paragraphs below."] + +Because of the rule tagging in this ruleset, only traffic tagged with value "30" is allowed to pass. + +Tags, combined with lookup tables allow for powerful policy based network access. + +=== Logging + +*ipfw* supports two methods of logging: +indexterm:[rule, log] indexterm:[logging] indexterm:[logging, ipfw0] indexterm:[logging, syslog] indexterm:[ipfw0] + +==== Method 1 – using *ipfw0*, the IPFW pseudointerface + +[subs=+quotes] +---- +# *kldload ipfw* +# *ifconfig ipfw0 create* +---- + +Note that the *ipfw.ko* kernel module must be loaded before creating the *ipfw0* interface. +Also, note that if *ipfw.ko* is unloaded, the interface is destroyed and is no longer available. + +Why use the *ipfw0* interface? + +It is possible to read logs in real time with programs such as man:tcpdump[1], man:wireshark[1], or other network monitoring programs. +This includes viewing the entire packet. + +An example is given further below. + +==== Method 2 – use *syslogd* + +Setting the sysctl variable `net.inet.ip.fw.verbose = 1` will instruct the firewall to log packets to man:syslogd[8] even when the *ipfw0* interface exists. +indexterm:[sysctl, net.inet.ip.fw.verbose] +Syslogd must be configured via [.filename]#/etc/syslog.conf#. +indexterm:[syslog, /etc/syslog.conf] +*ipfw* packets will be logged with a LOG_SECURITY facility. +The logging limit is configurable via `net.inet.ip.fw.verbose_limit`, which is set to 0 (unlimited) by default. + +Why use the *syslogd* interface? + +Of the two methods, it is the only one that processes count actions, and is also the only one that prints rule numbers with the log entry. +indexterm:[log, count actions] + +To test logging, create a rule with the *log* keyword: +indexterm:[logging, example] + +[subs=+quotes] +---- +# *ipfw add 1000 allow #log# udp from 203.0.113.10 to me 5656* +---- + +Counters are also a feature of rules that specify the *log* keyword. +If rules in a ruleset are edited to add the *log* keyword, matches for all rules will be included in the log entries with associated counts. +indexterm:[keyword, log] + +Create a ruleset using the *log* keyword that looks like this: + +[subs=+quotes] +---- +01000 allow log udp from 203.0.113.10 to me 5656 +02000 allow log udp from 203.0.113.10 to me 5657 +03000 allow log udp from 203.0.113.10 to me 5658 +04000 allow log udp from 203.0.113.10 to me 5659 +65535 deny ip from any to any +---- + +==== Using Method 1 + +To use Method 2, first set the required *sysctl* variable: + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.verbose=0* +---- + +Then, capture/view logs with *tcpdump*: +indexterm:[log, Method 1] indexterm:[log, ipfw0] + +[subs=+quotes] +---- +# *tcpdump -i ipfw0 -X -v* +---- + +Experiment with the tcpdump *-v*, *-vv*, and *-vvv* options, which gives increasingly more verbose output. +Consult man:tcpdump[1] for details. + +[TIP] +==== +Be sure to remove the address aliases added to the *em0* interface on the *external1* VM from the previous Section on crossref:ipfw-rules[ipfw-rules-tags, Tags]. +==== + +The example below examines traffic with the *ucont.sh* script on the *external1* VM and the *userv3.sh* script on the *firewall* VM. +indexterm:[ucont.sh] indexterm:[userv3.sh] + +[[ipfw-rules-logging00]] +.UDP Traffic From External1 to Firewall +image::ipfw-rules050.png["UDP Traffic From External1 to Firewall. Refer to paragraphs below."] + +Logged traffic from the above communication appears on the log device ipfw0: + +[subs=+quotes] +---- +# +# *tcpdump -i ipfw0 -X -vvv* +tcpdump: WARNING: ipfw0: That device doesn't support promiscuous mode +(BIOCPROMISC: Invalid argument) +tcpdump: listening on ipfw0, link-type EN10MB (Ethernet), capture size 262144 bytes +20:50:44.259127 IP (tos 0x0, ttl 64, id 61929, offset 0, flags [none], proto UDP (17), length 70) + 203.0.113.10.27337 > 203.0.113.50.5656: [udp sum ok] UDP, length 42 + 0x0000: 4500 0046 f1e9 0000 4011 1c61 ac10 0a0a E..F....@..a.... + 0x0010: ac10 0a32 6ac9 1618 0032 00ff 5544 5020 ...2j....2..UDP. + 0x0020: 7061 636b 6574 2066 726f 6d20 5b31 3732 packet.from.[172 + 0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 .16.10.10],[5656 + 0x0040: 5d2c 5b31 5d0a ],[1]. +20:50:44.581025 IP (tos 0x0, ttl 64, id 61930, offset 0, flags [none], proto UDP (17), length 70) + 203.0.113.10.41914 > 203.0.113.50.5656: [udp sum ok] UDP, length 42 + 0x0000: 4500 0046 f1ea 0000 4011 1c60 ac10 0a0a E..F....@..`.... + 0x0010: ac10 0a32 a3ba 1618 0032 c80c 5544 5020 ...2.....2..UDP. + 0x0020: 7061 636b 6574 2066 726f 6d20 5b31 3732 packet.from.[172 + 0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 .16.10.10],[5656 + 0x0040: 5d2c 5b32 5d0a ],[2]. +20:50:45.960845 IP (tos 0x0, ttl 64, id 61931, offset 0, flags [none], proto UDP (17), length 70) + 203.0.113.10.33126 > 203.0.113.50.5656: [udp sum ok] UDP, length 42 + 0x0000: 4500 0046 f1eb 0000 4011 1c5f ac10 0a0a E..F....@.._.... + 0x0010: ac10 0a32 8166 1618 0032 ea5f 5544 5020 ...2.f...2._UDP. + 0x0020: 7061 636b 6574 2066 726f 6d20 5b31 3732 packet.from.[172 + 0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 .16.10.10],[5656 + 0x0040: 5d2c 5b33 5d0a ],[3]. +^C +---- + +==== Using Method 2 + +To use Method 2, first set the required *sysctl* variable: + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.verbose=1* +---- + +Next, examine [.filename]#/etc/syslog.conf# to see if there is already a facility and level for security listed. +indexterm:[log, Method 2] +In modern versions of FreeBSD it is common to see: + +---- +security.* /var/log/security +---- + +*ipfw* creates logs with the LOG_SECURITY facility, and INFO and DEBUG levels, and sends output to the file [.filename]#/var/log/security# in this case. +indexterm:[log, LOG_SECURITY] +indexterm:[log, .info level] indexterm:[log, .debug level] + +If this entry exists in [.filename]#/etc/syslog.conf#, the system is all set. +Otherwise read through the below and set up an entry for an *ipfw* logfile. + +To log to man:syslogd[8], add the following line to the end of [.filename]#/etc/syslog.conf#: +indexterm:[log, /etc/syslog.conf] + +---- +security.* /var/log/security +---- + +(FreeBSD [.filename]#/etc/syslog.conf# allows tabs or spaces to be used in the file.) + +Create the logfile with + +[subs=+quotes] +---- +# *touch /var/log/security* +---- + +then send a `HANGUP` signal to the `syslogd` daemon: +indexterm:[log, syslogd] + +[subs=+quotes] +---- +# *kill -HUP * +---- + +Re-run the above example and Use *tail -f* to see logs in real time. +indexterm:[log, reading with tail -f] + +Note that *ipfw* only logs _matched rules_ with this method: +indexterm:[log, match] + +[subs=+quotes] +---- +# *tail -f /var/log/security* +Apr 3 14:50:12 firewall newsyslog[401]: logfile first created +Apr 9 21:05:13 firewall kernel: ipfw: #1000# Accept UDP 203.0.113.10:59203 203.0.113.50:5656 in via em0 +Apr 9 21:05:15 firewall kernel: ipfw: #1000# Accept UDP 203.0.113.10:12401 203.0.113.50:5656 in via em0 +Apr 9 21:05:16 firewall kernel: ipfw: #1000# Accept UDP 203.0.113.10:45319 203.0.113.50:5656 in via em0 +^C +---- + +The *log* entry includes the date, time, host, service, and rule number (1000 above) to make it easy to track which rule is being matched. + +*General Notes on logging* + +Consider the following ruleset: + +[subs=+quotes] +---- +# *ipfw list* +00100 check-state :default +01000 allow tcp from 203.0.113.100 to me setup keep-state :default +02000 allow icmp from 203.0.113.100 to me +02100 allow icmp from me to 203.0.113.100 +03000 allow log udp from 203.0.113.10 to me 5656 +04000 allow log logamount 20 udp from 203.0.113.10 to me 5657 +05000 allow log logamount 20 udp from 203.0.113.10 to me 5658 +65535 deny ip from any to any +---- + +When using Method 2 (syslog) on a quiet system, notice that the entries do not appear right away when reading the security log file in real time (for example, `tail -f /var/log/security`). +indexterm:[log, syslog buffering] +This is because *syslogd* will buffer identical lines and output a notification only occasionally as in the below example: + +[subs=+quotes] +---- +Mar 28 22:30:01 firewall kernel: ipfw: 3000 Accept UDP 203.0.113.10:27519 203.0.113.50:5656 in via em0 +Mar 28 22:30:03 firewall syslogd: last message repeated 4 times +Mar 28 22:32:31 firewall syslogd: last message repeated 31 times +---- + +Also, Method 1 (using the *ipfw0* interface) and Method 2 (syslog) are *_mutually exclusive_*. +indexterm:[log, mutually exclusive] +It is not possible to have both active at the same time. +If `net.inet.ip.fw.verbose=0`, the output will be to the *ipfw0* interface; if the value is 1, the log output will be to *syslog*. +indexterm:[sysctl, net.inet.ip.fw.verbose] + +*logamount* values in rules only apply to `Method 2 - syslog`. +indexterm:[log, logamount] indexterm:[keyword, logamount] +They have no effect on limiting the number of packets sent out the *ipfw0* interface. + +In `Method 2 - syslog`, when the log limit is reached, *ipfw* will send a notification similar to the following into the designated security logging file (default: [.filename]#/var/log/security#): + +[subs=+quotes] +---- +Mar 28 23:00:10 firewall kernel: ipfw: 5000 Accept UDP 203.0.113.10:63367 203.0.113.50:5658 in via em0 +Mar 28 23:00:11 firewall kernel: ipfw: 5000 Accept UDP 203.0.113.10:30909 203.0.113.50:5658 in via em0 +#Mar 28 23:00:11 firewall kernel: ipfw: limit 20 reached on entry 5000# +---- + +And, at the same time, it also conveniently sends the same message to [.filename]#/var/log/messages#, the standard FreeBSD logfile: + +[subs=+quotes] +---- +Mar 28 23:00:11 firewall kernel: ipfw: limit 20 reached on entry 5000 +---- + +After that notification is sent, no more syslog entries will be sent from the matching rule until the log counters are reset with: +indexterm:[log, resetlog] + +[subs=+quotes] +---- +# *ipfw resetlog * +---- + +When the *resetlog* command is entered, *ipfw* will send a reset notification to syslog: + +[subs=+quotes] +---- +Mar 28 23:04:51 firewall kernel: ipfw: logging count reset. +---- + +Unfortunately, as of FreeBSD version 14.1, it does not say *_which_* rule the count was reset for. +Presumably, the firewall admin should know which rule since they just entered the command, at least if there is only one admin. +In any case, it is a good idea to keep track of that manually when working with many rules that include the *log* keyword. + +If issuing an *ipfw resetlog* command _without_ specifying a rule number, *_all_* counters in all rules are reset and *ipfw* sends the following notification: +indexterm:[log, resetlog] indexterm:[keyword, resetlog] + +[subs=+quotes] +---- +Mar 28 23:08:52 firewall kernel: ipfw: All logging counts reset. +---- + +Finally, note that the sysctl variable `net.inet.ip.fw.verbose_limit` provides a "default limit" if one is not specified with the *logamount* keyword in the ruleset. +indexterm:[sysctl, net.inet.ip.fw.verbose_limit] + +Consider this scenario: + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.verbose_limit* +net.inet.ip.fw.verbose_limit: 5 #<---- The limit is preset to 5# + +# *ipfw list* +65535 deny ip from any to any +---- + +As new rules are added, *ipfw* will apply any *logamount* value it finds in the body of a rule. +If a rule being entered does not have a *logamount* entry, the value defaults to the current `net.inet.ip.fw.verbose_limit` amount. +indexterm:[log, logamount] + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +00100 check-state :default +# +# *ipfw add 3000 allow log udp from 203.0.113.10 to me 5656* +03000 allow log #logamount 5# udp from 203.0.113.10 to me 5656 +# +# *ipfw add 4000 allow log logamount 20 udp from 203.0.113.10 to me 5657* +04000 allow log #logamount 20# udp from 203.0.113.10 to me 5657 +# +# *ipfw list* +00100 check-state :default +03000 allow log logamount 5 udp from 203.0.113.10 to me 5656 +04000 allow log logamount 20 udp from 203.0.113.10 to me 5657 +65535 deny ip from any to any +---- + +If the sysctl for `net.inet.ip.fw.verbose_limit` is changed *_after_* the rule is entered, it has *_no effect_*: + +[subs=+quotes] +---- +# *sysctl net.inet.ip.fw.verbose_limit=3* +net.inet.ip.fw.verbose_limit: 5 -> 3 +---- + +and later in [.filename]#/var/log/messages# + +[subs=+quotes] +---- +Mar 29 11:07:02 firewall kernel: ipfw: limit 5 reached on entry 3000 + + ... + +Mar 29 11:07:24 firewall kernel: ipfw: limit 20 reached on entry 4000 +---- + +=== Reset + +The *reset* keyword sends an immediate TCP reset on a rule match containing that keyword. +indexterm:[keyword, reset] indexterm:[reset] +This immediately shuts down any TCP connection from the source matching the rule. +Create a new ruleset as follows: + +[subs=+quotes] +---- +# *ipfw list* +00100 check-state :default +01000 allow log tcp from 203.0.113.10 to me 5656 setup keep-state :default +02000 reset log tcp from 203.0.113.10 to me 5657 +03000 reset log udp from 203.0.113.10 to me 5658 +65535 deny ip from any to any +---- + +Test rule 2000 by executing *sh tcon.sh 5657* from the *external1* VM. +Note that the corresponding script, "sh tserv.sh" does not even have to be running. + +The syslog view of a TCP *reset* rule match looks like this: + +[subs=+quotes] +---- +Apr 9 21:44:49 firewall kernel: ipfw: 1000 Accept TCP 203.0.113.50:5656 203.0.113.10:28218 out via em0 +Apr 9 21:44:49 firewall syslogd: last message repeated 1 times +Apr 9 21:44:49 firewall kernel: ipfw: 1000 Accept TCP 203.0.113.10:28218 203.0.113.50:5656 in via em0 +#Apr 9 21:45:01 firewall kernel: ipfw: 2000 Reset TCP 203.0.113.10:12998 203.0.113.50:5657 in via em0# +#Apr 9 21:45:07 firewall kernel: ipfw: 2000 Reset TCP 203.0.113.10:13782 203.0.113.50:5657 in via em0# +---- + +When sysctl `net.inet.ip.fw.verbose=0`, there is no discernible output on *ipfw0* for a *reset* action. +A TCP SYN packet arrives and that is all that is displayed. +To actually witness the *reset*, run man:tcpdump[8] on the specific interface (em0 in this case): +indexterm:[reset, view] + +[subs=+quotes] +---- +# *tcpdump -i em0 -X -vvv* +tcpdump: listening on em0, link-type EN10MB (Ethernet), capture size 262144 bytes +21:53:39.376825 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + 203.0.113.10.32945 > 203.0.113.50.5657: Flags [#S#], cksum 0x68fa (correct), seq 1926269947, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 648984165 ecr 0], length 0 + 0x0000: 4500 003c 0000 4000 4006 ce5f ac10 0a0a E..<..@.@.._.... + 0x0010: ac10 0a32 80b1 1619 72d0 8bfb 0000 0000 ...2....r....... + 0x0020: a002 ffff 68fa 0000 0204 05b4 0103 0306 ....h........... + 0x0030: 0402 080a 26ae b665 0000 0000 ....&..e.... +21:53:39.377143 IP (tos 0x10, ttl 64, id 1965, offset 0, flags [none], proto TCP (6), length 40) + 203.0.113.50.5657 > 203.0.113.10.32945: Flags [#R.#], cksum 0xaddc (correct), seq 0, ack 1926269948, win 0, length 0 + 0x0000: 4510 0028 07ad 0000 4006 06b7 ac10 0a32 E..(....@......2 + 0x0010: ac10 0a0a 1619 80b1 0000 0000 72d0 8bfc ............r... + 0x0020: 5014 0000 addc 0000 P....... +^C +---- + +A UDP rule containing the *reset* keyword just drops the packet. +Nothing is sent back to the source address. +If the *log* keyword is also used on the rule, a log entry is generated for syslog (if enabled): +indexterm:[log, reset] + +[subs=+quotes] +---- +#Apr 9 21:58:49 firewall kernel: ipfw: 3000 Reset UDP 203.0.113.10:56503 203.0.113.50:5658 in via em0# +---- + +=== Tee + +The *tee* rule requires a man:divert[4] socket set up beforehand. +indexterm:[keyword, tee] indexterm:[tee] indexterm:[keyword, divert] +Refer to the crossref:ipfw-rules[ipfw-divert-action, divert] rule covered below for setting up the socket. +Once the socket is set up, the *tee* keyword works like *divert* except that it is not interested in any packet return. +indexterm:[divert] +It is simply copying the packet to the socket. +Processing continues with the next rule. + +In essence, *tee* allows the packet to be sent to userspace for any purpose desired - monitoring, copying, counting - whatever. + +[subs=+quotes] +---- +# *ipfw add 1000 tee 700 ip from any to me* +---- + +=== Unreach + +The *unreach* keyword directs *ipfw* to respond back to the source when packets arrive with a destination port that is not opened by any service. +indexterm:[keyword, unreach] indexterm:[unreach] +*ipfw* sends an ICMP reply with the code set to the keyword parameter. +This works for any IP protocol. + +Because *ipfw* sends an ICMP packet back to the source, the ruleset must allow outbound ICMP. +indexterm:[ICMP] + +Consider the following ruleset: + +[subs=+quotes] +---- +# *ipfw -a list* +00100 0 0 allow icmp from me to any +01000 0 0 unreach 100 log udp from any to me 5656 +02000 0 0 unreach 200 log tcp from any to me 5657 +03000 0 0 unreach 250 log ip from any to me 5658 +---- + +The counters are zero when the *external1* VM sends its packet, a UDP packet destined for port 5656, for which no service is currently set up. + +*ipfw* matches this with rule 1000 and sends an ICMP unreachable notice with code 100 (an arbitrary value, but see the list in man:ipfw[8]). +The offending packet is encapsulated in the data portion of the ICMP reply: + +[subs=+quotes] +---- +# *tcpdump -i bridge0 -X -vvv* +tcpdump: listening on bridge0, link-type EN10MB (Ethernet), capture size 262144 bytes +10:02:37.195380 IP (tos 0x0, ttl 64, id 45085, offset 0, flags [none], proto UDP (17), length 70) + 203.0.113.10.65216 > 203.0.113.50.5656: [udp sum ok] UDP, length 42 + 0x0000: 4500 0046 b01d 0000 4011 524c cb00 710a E..F....@.RL..q. + 0x0010: cb00 7132 fec0 1618 0032 701e 5544 5020 ..q2.....2p.UDP. + 0x0020: 7061 636b 6574 2066 726f 6d20 5b32 3033 packet.from.[203 + 0x0030: 2e30 2e31 3133 2e31 305d 2c5b 3536 3536 .0.113.10],[5656 + 0x0040: 5d2c 5b32 5d0a ],[2]. +10:02:37.196128 IP (tos 0x0, ttl 64, id 29611, offset 0, flags [none], proto ICMP (1), length 98) + #203.0.113.50 > 203.0.113.10: ICMP 203.0.113.50 unreachable - #100, length 78# + IP (tos 0x0, ttl 64, id 45085, offset 0, flags [none], proto UDP (17), length 70) + 203.0.113.10.65216 > 203.0.113.50.5656: [udp sum ok] UDP, length 42 + 0x0000: 4500 0062 73ab 0000 4001 8eb2 cb00 7132 E..bs...@.....q2 + 0x0010: cb00 710a 0364 751d 0000 0000 #4500 0046# #..q..du.....E..F# + 0x0020: #b01d 0000 4011 524c cb00 710a cb00 7132# #....@.RL..q...q2# + 0x0030: #fec0 1618 0032 701e 5544 5020 7061 636b# #.....2p.UDP.pack# + 0x0040: #6574 2066 726f 6d20 5b32 3033 2e30 2e31# #et.from.[203.0.1# + 0x0050: #3133 2e31 305d 2c5b 3536 3536 5d2c 5b32# #13.10],[5656],[2# + 0x0060: #5d0a# #].# + +---- + +The results for a TCP unreachable are almost the same. +The ICMP packet encapsulates the SYN packet in the data portion of the reply. + +Here is a view of an ICMP Reply to unreachable TCP port 5657: +indexterm:[ICMP] indexterm:[ICMP, reply] + +[subs=+quotes] +---- +# *tcpdump -i bridge0 -X -vvv* +tcpdump: listening on bridge0, link-type EN10MB (Ethernet), capture size 262144 bytes +15:24:03.663104 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + 203.0.113.10.58575 > 203.0.113.50.5657: Flags [S], cksum 0x092c (correct), seq 1062429515, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 3566166113 ecr 0], length 0 + 0x0000: 4500 003c 0000 4000 4006 ce5f ac10 0a0a E..<..@.@..-.... + 0x0010: ac10 0a32 e4cf 1619 3f53 634b 0000 0000 ...2....?ScK.... + 0x0020: a002 ffff 092c 0000 0204 05b4 0103 0306 .....,.......... + 0x0030: 0402 080a d48f 6061 0000 0000 ......`a.... +15:24:03.664168 IP (tos 0x0, ttl 64, id 37717, offset 0, flags [none], proto ICMP (1), length 88) + #203.0.113.50 > 203.0.113.10: ICMP # 200 203.0.113.50 unreachable, length 68*# + IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) + 203.0.113.10.58575 > 203.0.113.50.5657: Flags [#S#], cksum 0x092c (correct), seq 1062429515, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 3566166113 ecr 0], length 0 + 0x0000: 4500 0058 9355 0000 4001 7af3 ac10 0a32 E..X.U..@.z....2 + 0x0010: ac10 0a0a 03c8 68c3 0000 0000 #4500 003c# #......h.....E..<# + 0x0020: #0000 4000 4006 ce5f ac10 0a0a ac10 0a32# #..@.@.._.......2# + 0x0030: #e4cf 1619 3f53 634b 0000 0000 a002 ffff# #....?ScK........# + 0x0040: #092c 0000 0204 05b4 0103 0306 0402 080a# #.,..............# + 0x0050: #d48f 6061 0000 0000# #..`a....# +---- + +=== Setdscp + +The *setdscp* action directs *ipfw* to set an IP header option on outbound packets. +indexterm:[keyword, setdscp] indexterm:[setdscp] +The action has no effect on inbound packets. +The header option, formerly known as the "Type of Service" (ToS) option, now defines several classes of differentiated services (DiffServ) per several RFCs - link:https://www.rfc-editor.org/rfc/rfc2474.html[RFC 2474], link:https://www.rfc-editor.org/rfc/rfc3168.html[RFC 3168], and link:https://www.rfc-editor.org/rfc/rfc3260.html[RFC 3260]. +indexterm:[RFC, 2474] indexterm:[RFC, 3260] + +These service classes such as "Network Control", "Telephony", "Multimedia Conferencing", "Broadcast Video", "Low-latency Data", etc. all require their packets to receive special handling in the network. +indexterm:[setdscp, service classes] +This is achieved by inserting "code points" - numerical values in the packet header - that define each class. +indexterm:[setdcsp, code points] + +Firewalls, routers, switches, and other network devices interpret these values and, in theory, service the packets according to their class. +See this Wikipedia article on Differentiated Services: https://en.wikipedia.org/wiki/Differentiated_services. + +In practice, support for service classes vary among network operators. +Check the man page for a list of code points settable by *ipfw*. + +The example below sets the DSCP value to "af31", a codepoint in the "Multimedia Streaming" class. + +[subs=+quotes] +---- +On the *external1* VM, set up a listening service: +# *ncat -u -l 5656* + +On the *firewall* VM create this ruleset: +# *ipfw add 2000 setdscp af31 udp from me to any 5656* +# *ipfw add 3000 allow udp from me to any* +---- + +Note that rule processing for the *setdscp* keyword continues to the next rule. + +Note also that the DSCP value takes up only a partial byte in the IP header, sharing it with two bits of ECN (Explicit Congestion Notification). +indexterm:[ECN] indexterm:[setdscp, ECN] +The binary value for "af31" is 011010nn, where 'nn' are the two bits for ECN. +If no ECN, the value resolves to 0x68 (104 decimal). + +An outbound traffic example, generated by *ncat -u 203.0.113.10 5656* from the *firewall* VM is shown as received by the *external1* VM: +indexterm:[ncat] + +[subs=+quotes] +---- +On the *firewall* VM send out a UDP packet: + +# *echo "Greetings from the firewall" | ncat -u 203.0.113.10 5656* +---- + +To view, run *tcpdump* on the network interface on the *external1* VM: + +[subs=+quotes] +---- +# *tcpdump -i em0 -X -vvv* +tcpdump: listening on em0, link-type EN10MB (Ethernet), capture size 262144 bytes +10:14:22.173252 IP (tos 0x68, ttl 64, id 30816, offset 0, flags [none], proto UDP (17), length 57) + 203.0.113.50.17767 > 203.0.113.10.5656: [udp sum ok] UDP, length 29 + 0x0000: 45##68## 0039 7860 0000 4011 958f ac10 0a32 Eh.9x`..@......2 + 0x0010: ac10 0a0a 4567 1618 0025 0f5b 4772 6565 ....Eg...%.[Gree + 0x0020: 7469 6e67 7320 6672 6f6d 2074 6865 2066 tings.from.the.f + 0x0030: 6972 6577 616c 6c2e 0a irewall.. +---- + +Diffserve codepoints can be set on any IP based protocol or restricted to selected protocols and/or ports through suitable rules. + +=== Skipto + +The *skipto* action directs the firewall engine to pass over any rules less than the *skipto* parameter number. +indexterm:[keyword, skipto] indexterm:[skipto] +If an early rule can match a packet characteristic such as an address, port, TCP or UDP header option or similar, a *skipto* rule can jump to a potentially much later section of the firewall ruleset to handle the packet. + +Consider the following (contrived) ruleset: + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +# *ipfw add 1000 allow tcp from me to any established keep-state* +# *ipfw add 2000 allow tcp from 203.0.113.10 to me 4500 setup keep-state* +# *ipfw add 3000 allow tcp from 203.0.113.10 to me 4502 setup keep-state* +# *ipfw add 4000 allow tcp from 203.0.113.10 to me 4504 setup keep-state* +# *ipfw add 5000 allow tcp from 203.0.113.10 to me 4506 setup keep-state* +# *ipfw add 6000 allow tcp from 203.0.113.10 to me 4508 setup keep-state* +# *ipfw add 7000 allow tcp from 203.0.113.10 to me 4510 setup keep-state* +# *ipfw add 8000 allow tcp from 203.0.113.10 to me 4512 setup keep-state* +# *ipfw add 9000 allow tcp from 203.0.113.10 to me 4512 setup keep-state* +# *ipfw add 10000 allow tcp from 203.0.113.10 to me 5656 setup keep-state* +---- + +With the *external1* VM using the *tcon.sh 5656* TCP connection script, *ipfw* has to traverse the entire firewall ruleset, checking each rule in turn for a match. +indexterm:[tcon.sh] +(When testing this ruleset, ensure that the *firewall* VM is running the appropriate service script such as *tserv3.sh*.) +indexterm:[tserv3.sh] + +By placing a *skipto* action rule after the *check-state* action, *ipfw* jumps directly to the desired rule: + +[subs=+quotes] +---- +# *ipfw add 100 check-state* +# *ipfw add 500 #skipto 10000# tcp from 203.0.113.10 to me 5656* +# *ipfw add 1000 allow tcp from me to any established keep-state* +# *ipfw add 2000 allow tcp from 203.0.113.10 to me 4500 setup keep-state* +# *ipfw add 3000 allow tcp from 203.0.113.10 to me 4502 setup keep-state* +# *ipfw add 4000 allow tcp from 203.0.113.10 to me 4504 setup keep-state* +# *ipfw add 5000 allow tcp from 203.0.113.10 to me 4506 setup keep-state* +# *ipfw add 6000 allow tcp from 203.0.113.10 to me 4508 setup keep-state* +# *ipfw add 7000 allow tcp from 203.0.113.10 to me 4510 setup keep-state* +# *ipfw add 8000 allow tcp from 203.0.113.10 to me 4512 setup keep-state* +# *ipfw add 9000 allow tcp from 203.0.113.10 to me 4512 setup keep-state* +### *ipfw add 10000 allow tcp from 203.0.113.10 to me 5656 setup keep-state*## +---- + +Use the `-a` command line parameter to see if the *skipto* action is working (or use *ipfw show*): +indexterm:[ipfw, show] + +[subs=+quotes] +---- +# *ipfw -a list* +00100 0 0 check-state :default +#00500 1 60 skipto 10000 tcp from 203.0.113.10 to me 5656# +01000 0 0 allow tcp from me to any established keep-state :default +02000 0 0 allow tcp from 203.0.113.10 to me 4500 setup keep-state :default +03000 0 0 allow tcp from 203.0.113.10 to me 4502 setup keep-state :default +04000 0 0 allow tcp from 203.0.113.10 to me 4504 setup keep-state :default +05000 0 0 allow tcp from 203.0.113.10 to me 4506 setup keep-state :default +06000 0 0 allow tcp from 203.0.113.10 to me 4508 setup keep-state :default +07000 0 0 allow tcp from 203.0.113.10 to me 4510 setup keep-state :default +08000 0 0 allow tcp from 203.0.113.10 to me 4512 setup keep-state :default +09000 0 0 allow tcp from 203.0.113.10 to me 4514 setup keep-state :default +#10000 8 474 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default# +65535 0 0 deny ip from any to any +---- + +*General notes on skipto:* +indexterm:[skipto, general notes] + +* The *skipto* action does not allow negative numbers as a parameter. +* A *skipto* to rule 0 or to a value greater than 65534, causes *ipfw* to throw an error. +* It is possible to use the *skipto* action to skip between *sets*. +However, if the *set* containing the *skipto* target is disabled, processing continues with the next rule in *_any_* *set* that is enabled. + +For example, if there are three *sets* - 0, 1, and 2, with a disabled *set* 1 containing the destination of the skipto action, processing will continue with the next rule. +See the below ruleset and counters. +Because *set* 1 is disabled, the next rule in any enabled *set* is rule 2700. +Processing continues at 2700, but the packet was not matched until rule 3000. + + +[subs=+quotes] +---- +# *ipfw -Sa list* +00100 0 0 set 0 check-state :default +00101 1 60 set 0 skipto 2000 tcp from 203.0.113.10 to me +00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +00150 0 0 set 0 allow tcp from me to any established keep-state :default +01000 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +# DISABLED 01200 0 0 set 1 allow tcp from 203.0.113.10 to me 6500 setup keep-state :default +# DISABLED 01800 0 0 set 1 allow tcp from 203.0.113.10 to me 6512 setup keep-state :default +# DISABLED 01900 0 0 set 1 allow tcp from 203.0.113.10 to me 6514 setup keep-state :default +# DISABLED 02000 0 0 set 1 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +#02700 0 0 set 2 allow tcp from 203.0.113.10 to me 7510 setup keep-state :default# +02800 0 0 set 2 allow tcp from 203.0.113.10 to me 7512 setup keep-state :default +02900 0 0 set 2 allow tcp from 203.0.113.10 to me 7514 setup keep-state :default +#03000 8 474 set 2 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default# +65535 0 0 set 31 deny ip from any to any +---- + +* If using *skipto* to a rule number that has multiple rules, the first matching rule at or after that number is executed: + +[subs=+quotes] +---- +# *ipfw -Sa list* +00100 0 0 set 0 check-state :default +00101 1 60 set 0 #skipto 2000# tcp from 203.0.113.10 to me +00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +00150 0 0 set 0 allow tcp from me to any established keep-state :default +01600 0 0 set 1 allow tcp from 203.0.113.10 to me 6508 setup keep-state :default +01700 0 0 set 1 allow tcp from 203.0.113.10 to me 6510 setup keep-state :default +02000 0 0 set 1 allow tcp from 203.0.113.10 to me 6512 setup keep-state :default +02000 0 0 set 1 allow tcp from 203.0.113.10 to me 6514 setup keep-state :default +02000 0 0 set 2 allow tcp from 203.0.113.10 to me 7500 setup keep-state :default +02000 0 0 set 2 allow tcp from 203.0.113.10 to me 7502 setup keep-state :default +02000 0 0 set 2 allow tcp from 203.0.113.10 to me 7504 setup keep-state :default +02500 0 0 set 2 allow tcp from 203.0.113.10 to me 7506 setup keep-state :default +02600 0 0 set 2 allow tcp from 203.0.113.10 to me 7508 setup keep-state :default +02700 0 0 set 2 allow tcp from 203.0.113.10 to me 7510 setup keep-state :default +02800 0 0 set 2 allow tcp from 203.0.113.10 to me 7512 setup keep-state :default +02900 0 0 set 2 allow tcp from 203.0.113.10 to me 7514 setup keep-state :default +#03000 10 567 set 2 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default# +65535 0 0 set 31 deny ip from any to any +---- + +* It is possible to enter a rule with a *skipto* rule number that is lower than the current rule number, attempting to go backward in the ruleset. +However, this has no effect, and processing continues with the next rule: + +[subs=+quotes] +---- +# *ipfw -Sa list* +00100 0 0 set 0 check-state :default +00101 1 60 set 0 #skipto 1000# tcp from 203.0.113.10 to me +00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +00150 0 0 set 0 allow tcp from me to any established keep-state :default +00200 0 0 set 0 allow tcp from 203.0.113.10 to me 4500 setup keep-state :default +00300 0 0 set 0 allow tcp from 203.0.113.10 to me 4502 setup keep-state :default +00400 0 0 set 0 allow tcp from 203.0.113.10 to me 4504 setup keep-state :default +00500 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +00600 0 0 set 0 allow tcp from 203.0.113.10 to me 4508 setup keep-state :default +00700 0 0 set 0 allow tcp from 203.0.113.10 to me 4512 setup keep-state :default +00800 0 0 set 0 allow tcp from 203.0.113.10 to me 4514 setup keep-state :default +01000 1 60 set 0 #skipto 500# tcp from 203.0.113.10 to me +#01100 8 475 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default# +65535 0 0 set 31 deny ip from any to any +---- + +* It is also possible (but not advised) to *skipto* a *skipto* rule: + +[subs=+quotes] +---- +00100 0 0 set 0 check-state :default +00101 1 60 set 0 #skipto 1000# tcp from 203.0.113.10 to me +00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +00150 0 0 set 0 allow tcp from me to any established keep-state :default +00200 0 0 set 0 allow tcp from 203.0.113.10 to me 4500 setup keep-state :default +00300 0 0 set 0 allow tcp from 203.0.113.10 to me 4502 setup keep-state :default +00400 0 0 set 0 allow tcp from 203.0.113.10 to me 4504 setup keep-state :default +00500 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +00600 0 0 set 0 allow tcp from 203.0.113.10 to me 4508 setup keep-state :default +00700 0 0 set 0 allow tcp from 203.0.113.10 to me 4510 setup keep-state :default +00800 0 0 set 0 allow tcp from 203.0.113.10 to me 4512 setup keep-state :default +00900 0 0 set 0 allow tcp from 203.0.113.10 to me 4514 setup keep-state :default +#01000 1 60 set 0 skipto 1500 tcp from 203.0.113.10 to me# +01000 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +#01500 1 60 set 0 skipto 2000 tcp from 203.0.113.10 to me# +01600 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +#02000 1 60 set 0 skipto 2500 tcp from 203.0.113.10 to me# +02100 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +#02500 1 60 set 0 skipto 3000 tcp from 203.0.113.10 to me# +02600 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +#03000 8 475 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default# +65535 0 0 set 31 deny ip from any to any +---- + +See the section on Lists for additional caveats. + +[[ipfw-divert-action]] +=== Divert + +The *divert* mechanism in *ipfw* allows *ipfw* to pull packets into user space for programmatic purposes. +indexterm:[keyword, divert] indexterm:[divert] indexterm:[ipfw, divert] +The *divert* rule snatches the packet and presents it to a man:divert[4] socket, a special socket type that can be created from an external program. +indexterm:[divert, socket] +See the _divert.c_ program at the end of crossref:ipfw-appendix-b[appendix-b, Appendix B] for the sample program used for this book. +indexterm:[divert, source code] +Copy the `divert.c` program onto the *firewall* VM from the host and compile it: + +[subs=+quotes] +---- +Copy divert.c from the host: +# *cd /root/bin* +# *scp user@host:~/ipfw-primer/ipfw/VM_CODE/divert.c .* + +# Compile it: +# *make divert LDFLAGS=-lutil* +---- + +The code should compile cleanly. +If it does not, examine the file closely to ensure it was copied correctly and retry the above command. + +Divert sockets can be used as the basis for many specialized applications such as packet examination, in-flight packet modification, experimental routing techniques, etc. +The program shown here simply reads from the socket and dumps the contents of the packet in hex and ASCII. +It then writes the packet back into the divert socket. + +To work with the *divert* keyword, the man:divert[4] packet diversion mechanism has to be compiled into the kernel or loaded at runtime: +indexterm:[divert, example] indexterm:[module, ipdivert] + +[subs=+quotes] +---- +# *kldload ipfw* +# *kldload ipdivert* +---- + +This loads the *ipfw* firewall kernel module and the *ipdivert* kernel module which provides man:divert[4] functionality. + +[NOTE] +==== +Once loaded, the *ipdivert.ko* module cannot be unloaded. +A firewall reboot is required to remove the *ipdivert.ko* module. +==== + +Once this is done, an application can open a man:divert[4] socket and process packets. + +[subs=+quotes] +---- +# *./divert* +Opening divert on port 700 + +... (see below) +---- + +In another window, run man:netstat[1] to see the divert socket: +indexterm:[divert, view with netstat] + +[subs=+quotes] +---- +# *netstat -an | more* +Active Internet connections (including servers) +Proto Recv-Q Send-Q Local Address Foreign Address (state) +tcp4 0 0 \*.22 *.* LISTEN +tcp6 0 0 \*.22 *.* LISTEN +udp4 0 0 \*.514 *.* +udp6 0 0 \*.514 *.* +#div4 0 0 \*.700 *.*# +Active UNIX domain sockets +Address Type Recv-Q Send-Q Inode Conn Refs Nextref Addr +fffff80003b83000 stream 0 0 fffff80003cac5a0 0 0 0 /var/run/devd.pipe +fffff80003baf800 dgram 0 0 0 fffff80003bafc00 0 fff +... +---- + +To examine the *divert* operation, first create a suitable ruleset: +indexterm:[divert, ruleset] + +[subs=+quotes] +---- +# *ipfw add 700 divert #700# ip from any to any* +# +# *ipfw add 1000 allow udp from 203.0.113.10 to me* +01000 allow udp from 203.0.113.10 to me +# +# *ipfw add 1100 allow udp from me to 203.0.113.10* +01100 allow udp from me to 203.0.113.10 +---- + +The syntax is a bit odd in this case. +The divert keyword takes a numeric argument that functions as the divert object. +indexterm:[divert, object] +This is similar syntax to *pipes*, *queues*, and *NAT* (network address translation) rules which are discussed later. + +A common convention, though not required, is to make the *divert* port the same number as the rule number in the ruleset. +Whatever the rule number, when the packet is diverted and processed, and then returned to *ipfw*, the firewall picks up the packet at the divert rule number, plus one - that is, the next rule. + +[subs=+quotes] +---- +# *ipfw list* +00700 divert 700 ip from any to any +01000 allow udp from 203.0.113.10 to me +01100 allow udp from me to 203.0.113.10 +65535 deny ip from any to any +---- + +Examine the ruleset above. +The packet is diverted to a divert socket, port 700 at the first rule. +When it is returned from the _divert.c_ program, it renters the ruleset at rule 1000. +The ruleset allows UDP packets from and to the *external1* VM. + +To test, set up the *firewall* VM host to run *userv3.sh* and the *external1* VM host to run *ucon.sh 5656*. +This results in the following expected output from the divert program: +indexterm:[divert, execution] + +[subs=+quotes] +---- +# *./divert* +Opening divert on port 700 +203.0.113.10:51417 -> 203.0.113.50:5656 +|0000 45 00 00 46 a9 0c 00 00 40 11 65 3e ac 10 0a 0a |E..F....@.e>....| +|0010 ac 10 0a 32 c8 d9 16 18 00 32 a2 eb 55 44 50 20 |...2.....2..UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 34 5d 0a |],[4]. | +---- + +And the output from *userv3.sh* also shows on the *firewall* console: +indexterm:[userv3.sh] + +[subs=+quotes] +---- +# *sh userv3.sh* +Starting UDP listeners on [5656],[5657],[5658] +UDP communication from [203.0.113.10],[5656],[1] +---- + +Next, shut down the *userv3.sh* services on the *firewall* VM. +The incoming packets find no open port and are rejected by the *firewall* VM host. +However, they still go through the divert socket: + +[subs=+quotes] +---- +# *./divert* +Opening divert on port 700 +203.0.113.10:26058 -> 203.0.113.50:5656 +|0000 45 00 00 47 a9 12 00 00 40 11 65 37 ac 10 0a 0a |E..G....@.e7....| +|0010 ac 10 0a 32 65 ca 16 18 00 33 28 a9 55 44 50 20 |...2e....3(.UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 31 30 5d 0a |],[10]. | +203.0.113.50:771 -> 203.0.113.10:27038 +|0000 45 00 00 63 3a 61 00 00 40 01 65 37 ac 10 0a 32 |E..c:a..@.e7...2| +|0010 ac 10 0a 0a 03 03 69 9e 00 00 00 00 45 00 00 47 |......i.....E..G| +|0020 a9 12 00 00 40 11 65 37 ac 10 0a 0a ac 10 0a 32 |....@.e7.......2| +|0030 65 ca 16 18 00 33 28 a9 55 44 50 20 70 61 63 6b |e....3(.UDP pack| +|0040 65 74 20 66 72 6f 6d 20 5b 31 37 32 2e 31 36 2e |et from [172.16.| +|0050 31 30 2e 31 30 5d 2c 5b 35 36 35 36 5d 2c 5b 31 |10.10],[5656],[1| +|0060 30 5d 0a |0]. | +#divert: sendto: Permission denied# +---- + +The last output line, "Permission denied", is because the kernel, faced with a packet and no port to send it to, instead sends an ICMP port unreachable response back to the sender. +indexterm:[divert, permission denied] +The kernel tries to send the ICMP packet back out the network interface, but there is no *ipfw* rule for it through the firewall - thus "Permission denied". +The packet is dropped. + +To fix, add a rule for ICMP traffic in either direction: + +[subs=+quotes] +---- +# *ipfw list* +00700 divert 700 ip from any to any +#00800 allow icmp from any to any# +01000 allow udp from 203.0.113.10 to me +01100 allow udp from me to 203.0.113.10 +65535 deny ip from any to any +---- + +The *divert* operation now works as expected and the packet re-enters the firewall after rule 700. +The next rule (800) permits ICMP in either direction and the packet is sent back to the source host. +In the listings below, the *ucon.sh* script was run for 5 cycles, and after cycle #3, the firewall *userv3.sh* script was shut down. + +The remaining two cycles result in an ICMP message being returned back to the *external1* VM: + +[subs=+quotes] +---- +# *./divert* +Opening divert on port 700 +203.0.113.10:36083 -> 203.0.113.50:5656 +|0000 45 00 00 46 a9 20 00 00 40 11 65 2a ac 10 0a 0a |E..F. ..@.e*....| +|0010 ac 10 0a 32 8c f3 16 18 00 32 de d4 55 44 50 20 |...2.....2..UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 31 5d 0a |],[1]. | +203.0.113.10:25662 -> 203.0.113.50:5656 +|0000 45 00 00 46 a9 21 00 00 40 11 65 29 ac 10 0a 0a |E..F.!..@.e)....| +|0010 ac 10 0a 32 64 3e 16 18 00 32 07 89 55 44 50 20 |...2d>...2..UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 32 5d 0a |],[2]. | +203.0.113.10:40345 -> 203.0.113.50:5656 +|0000 45 00 00 46 a9 22 00 00 40 11 65 28 ac 10 0a 0a |E..F."..@.e(....| +|0010 ac 10 0a 32 9d 99 16 18 00 32 ce 2c 55 44 50 20 |...2.....2.,UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 33 5d 0a |],[3]. | +203.0.113.10:53482 -> 203.0.113.50:5656 +|0000 45 00 00 46 a9 23 00 00 40 11 65 27 ac 10 0a 0a |E..F.x..@.e'....| +|0010 ac 10 0a 32 d0 ea 16 18 00 32 9a da 55 44 50 20 |...2.....2..UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 34 5d 0a |],[4]. | +#203.0.113.50:771 -> 203.0.113.10:27037 (ICMP packet)# +|0000 45 00 00 62 3a 68 00 00 40 01 65 27 ac 10 0a 32 |E..b:h..@.e'...2| +|0010 ac 10 0a 0a 03 03 69 9d 00 00 00 00 45 00 00 46 |......i.....E..F| +|0020 a9 23 00 00 40 11 65 27 ac 10 0a 0a ac 10 0a 32 |.x..@.e'.......2| +|0030 d0 ea 16 18 00 32 9a da 55 44 50 20 70 61 63 6b |.....2..UDP pack| +|0040 65 74 20 66 72 6f 6d 20 5b 31 37 32 2e 31 36 2e |et from [172.16.| +|0050 31 30 2e 31 30 5d 2c 5b 35 36 35 36 5d 2c 5b 34 |10.10],[5656],[4| +|0060 5d 0a |]. | +203.0.113.10:35359 -> 203.0.113.50:5656 +|0000 45 00 00 46 a9 24 00 00 40 11 65 26 ac 10 0a 0a |E..F.$..@.e&....| +|0010 ac 10 0a 32 8a 1f 16 18 00 32 e1 a4 55 44 50 20 |...2.....2..UDP | +|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172| +|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656| +|0040 5d 2c 5b 35 5d 0a |],[5]. | +#203.0.113.50:771 -> 203.0.113.10:27037 (ICMP packet)# +|0000 45 00 00 62 3a 69 00 00 40 01 65 26 ac 10 0a 32 |E..b:i..@.e&...2| +|0010 ac 10 0a 0a 03 03 69 9d 00 00 00 00 45 00 00 46 |......i.....E..F| +|0020 a9 24 00 00 40 11 65 26 ac 10 0a 0a ac 10 0a 32 |.$..@.e&.......2| +|0030 8a 1f 16 18 00 32 e1 a4 55 44 50 20 70 61 63 6b |.....2..UDP pack| +|0040 65 74 20 66 72 6f 6d 20 5b 31 37 32 2e 31 36 2e |et from [172.16.| +|0050 31 30 2e 31 30 5d 2c 5b 35 36 35 36 5d 2c 5b 35 |10.10],[5656],[5| +|0060 5d 0a |]. | +^C +---- + +Note the two icmp packets logged by rule 800: + +[subs=+quotes] +---- +# *ipfw show* +00700 19 2466 divert 700 ip from any to any +#00800 2 196 allow icmp from any to any# +01000 5 350 allow udp from 203.0.113.10 to me +01100 0 0 allow udp from me to 203.0.113.10 +65535 477 114991 deny ip from any to any +---- + +*General notes on the divert action*: +indexterm:[divert, general notes] + +* The *ipdivert.ko* kernel module must be loaded or compiled into the kernel to create a divert rule, and thus to use man:divert[4] sockets. +* The *ipdivert.ko* kernel module cannot be unloaded. +indexterm:[module, ipdivert] +Restart the VM to remove the *ipdivert.ko* kernel module. +* It is not possible to create a rule with a divert port of 0 or 65535. +The port number must be between 1 and 65534 (inclusive). +* If creating a rule with a divert port on rule 65534, the returning packet will restart firewall rule processing at the default rule, 65535, which cannot be changed. +* A divert rule can be created for any protocol in [.filename]#/etc/protocols#. +* The same divert port can be used for multiple rules. +* After returning from a divert rule, if the next rule is in another set, processing will continue with that rule unless the set is disabled. +If disabled, it will skip to the next rule in any set that is not disabled. + +*General notes on creating the divert socket*: +indexterm:[divert, socket notes] + +* Only root can create a divert socket. +* Opening a divert socket on port 0 or port 65536 results in a random divert port number. +* Opening a divert socket on port 65535 is permitted, but not advised. +* Opening a divert port greater than 65536 or less than 0 results in a positive port number modulo 65536. +* As with other sockets, it is not possible to open two divert sockets on the same port number. +However, it is possible to open a divert socket on a port already in use for any protocols based on IPv4 or IPv6. + + +=== Other Protocols + +Any protocol in [.filename]#/etc/protocols# may be used in a rule. +indexterm:[protocol, other examples] + +[subs=+quotes] +---- +# *ipfw add 1000 allow ospf from any to me* +# *ipfw add 2000 allow chaos from any to me* +etc. +---- + +=== Limit + +*ipfw* can restrict the number of active connections with the *limit* option. +indexterm:[keyword, limit] indexterm:[limit] +This option allows for specifying a parameter in the rule that is regarded as a flow element, that is, one of `src-addr`, `src-port`, `dst-addr`, or `dst-port`. +indexterm:[limit, flow element] +In addition, the *limit* keyword takes a value, N, that is the maximum number of connections desired: + +[subs=+quotes] +---- +# *ipfw add 1000 allow udp from any to me dst-port 5656-5658 limit src-addr 5* +# *ipfw add 1100 count udp from any to me* +---- + +Concurrent connections via TCP, UDP, ICMP, or any protocol can be limited in this way. + +*ipfw* creates a dynamic rule for each connection allowed by the rule. +When the maximum number of connections is reached, additional packets are considered no longer matched and are dropped by the rule after being counted, and the search terminates. + +To test, write the following simple script on the *external1* VM to flood UDP packets at the *firewall* VM running *sh userv3.sh*: +indexterm:[limit, example] indexterm:[userv3.sh] indexterm:[ncat] + +[subs=+quotes] +---- +#!/bin/sh + +export NUM=1 +for i in \`jot -r 500 5656 5658 1` +do + echo "hello [${NUM}] to port [${i}]" | ncat -u 203.0.113.50 ${i} + NUM=`expr $NUM + 1` +done +---- + +On the *firewall* VM, *ipfw* starts creating dynamic rules as soon as the first matching packet is received. +Additional dynamic rules, up to the *limit* number are created. +Each UDP based dynamic rule has a default 10 second lifetime, controlled by the sysctl node `net.inet.ip.fw.dyn_udp_lifetime`. +indexterm:[sysctl, net.inet.ip.fw.dyn_udp_lifetime] +As they expire under the limit value, space for additional connections is created. +The number of open dynamic rules at any point in time can be viewed with the sysctl node `net.inet.ip.fw.dyn_count`. +indexterm:[sysctl, net.inet.ip.fw.dyn_count] + +View the dynamic rules with: +indexterm:[ipfw, -SaD] + +[subs=+quotes] +---- +# *ipfw -SaD list* +00500 0 0 check-state :default +01000 10 531 allow udp from any to me 5656-5658 limit src-addr 5 :default +65535 0 0 deny ip from any to any +## Dynamic rules (4 560): +01000 1 53 (8s) LIMIT udp 203.0.113.10 23755 <-> 203.0.113.50 5657 :default +01000 1 53 (8s) LIMIT udp 203.0.113.10 30144 <-> 203.0.113.50 5656 :default +01000 0 0 (4s) PARENT 3 udp 203.0.113.10 0 <-> 0.0.0.0 0 :default +01000 1 53 (8s) LIMIT udp 203.0.113.10 22722 <-> 203.0.113.50 5658 :default +---- + +[TIP] +==== +Running *cmdwatch -n1 ipfw -SaD list* on the *firewall* VM will show the list of rules grow and shrink in real time. +==== + +indexterm:[cmdwatch] + +It is useful to experiment with the sysctl `net.inet.ip.fw.dyn_udp_lifetime` and see its effect on `net.inet.ip.fw.dyn_count`. +By adjusting the `net.inet.ip.fw.dyn_udp_lifetime` value during a network packet flood (like that above), it is possible to watch how the *ipfw limit* rule blocked traffic through the firewall. + +Here is the result of a sample run. +indexterm:[limit, sample run] +Note the missing connections due to a limit restriction: + +[subs=+quotes] +---- +... +hello [19] to port [5657] +hello [20] to port [5656] +#hello [21] to port [5656]# +#hello [33] to port [5657]# +hello [34] to port [5656] +hello [35] to port [5657] +hello [36] to port [5657] +#hello [37] to port [5657]# +#hello [48] to port [5657]# +#hello [50] to port [5657]# +hello [51] to port [5656] +hello [52] to port [5657] +#hello [53] to port [5656]# +#hello [64] to port [5657]# +... +---- + +=== Call and Return + +The *call* and *return* actions allow *ipfw* to change ruleset processing order by jumping to a rule number elsewhere in the ruleset. +indexterm:[keyword, call] indexterm:[keyword, return] indexterm:[call/return] +If the rules at that location contain a *return* action, processing will jump back to the statement immediately after the original *call* statement. +In practice, this acts like a program function call, or as man:ipfw[8] notes, like an assembly language subroutine. + +Creating a new ruleset with *call* and *return* actions: +indexterm:[call/return, example] + +[subs=+quotes] +---- +# +# *ipfw add 500 check-state* +00500 check-state :default +# +# *ipfw add 1000 call 20000 udp from 203.0.113.10 to me 5656* +01000 call 20000 udp from 203.0.113.10 to me 5656 +# +# *ipfw add 1100 count udp from 203.0.113.10 to me* +01100 count udp from 203.0.113.10 to me +# +# *ipfw add 1200 allow udp from 203.0.113.10 to me 5656* +01200 allow udp from 203.0.113.10 to me 5656 +# +# *ipfw add 20000 count udp from 203.0.113.10 to me* +20000 count udp from 203.0.113.10 to me +# +# *ipfw add 21000 return via any* +21000 return +# +# *ipfw -a list* +00500 0 0 check-state :default +01000 0 0 call 20000 udp from 203.0.113.10 to me 5656 +01100 0 0 count udp from 203.0.113.10 to me +01200 0 0 allow udp from 203.0.113.10 to me 5656 +20000 0 0 count udp from 203.0.113.10 to me +21000 0 0 return +65535 0 0 deny ip from any to any +---- + +As noted in the man page, some extra syntactic sugar on the return statement is required: +indexterm:[call/return, syntax] + +[subs=+quotes] +---- +# *ipfw add 21000 return #via any#* +---- + +In this example several count statements are used to try to trace ruleset processing. + +To test, have the *firewall* VM host startup *userv3.sh*. +indexterm:[userv3.sh] +After the *external1* VM uses *ucon.sh 5656* to send a single udp packet, the count list looks like this: +indexterm:[call/return, example] + +[subs=+quotes] +---- +# *ipfw -a list* +00500 0 0 check-state :default +01000 1 70 call 20000 udp from 203.0.113.10 to me 5656 +01100 1 70 count udp from 203.0.113.10 to me +01200 1 70 allow udp from 203.0.113.10 to me 5656 +20000 1 70 count udp from 203.0.113.10 to me +21000 1 70 return via any +65535 0 0 deny ip from any to any +---- + +The packet was matched at rule 1000 where it encountered a *call* action to jump to rule 20000 where it was then matched. +The next rule was a matched *return* action at rule 21000. +Returning to the rule after the *call* action, it matched a *count* action at 1100, then matched an *allow* action at 1200 where it was sent through to the application layer and was received by *userv3.sh*. + +If the *return* action at rule 21000 is removed and the test is re-run, the counts look much different. +(First, *ipfw zero* and *ipfw zero 65535* to reset all counters.) + +[subs=+quotes] +---- +# *ipfw -a list* +00500 0 0 check-state :default +01000 1 70 call 20000 udp from 203.0.113.10 to me 5656 +01100 0 0 count udp from 203.0.113.10 to me +01200 0 0 allow udp from 203.0.113.10 to me 5656 +20000 1 70 count udp from 203.0.113.10 to me +65535 1 70 deny ip from any to any +---- + +Without a *return* at rule 21000, the only rule left is the default *deny* rule, and there is nothing received by *userv3.sh*. +indexterm:[userv3.sh] + +[WARNING] +==== +Because *ipfw* can jump both forward and backward with the *call* action, it is possible to create an endless loop. +==== + +indexterm:[call/return, endless loop] + +This example creates an endless loop with an incorrect *call* rule: + +[subs=+quotes] +---- +# +# *ipfw -a list* +01000 0 0 count udp from 203.0.113.10 to me +05000 0 0 check-state :default +#06000 0 0 call 1000 udp from 203.0.113.10 to me 5656# +07000 0 0 count udp from 203.0.113.10 to me +65535 0 0 deny ip from any to any +---- + +This example is missing a *return* action. +This creates a loop. +*ipfw* eventually figures out that a loop exists, and breaks out at the next call action with the diagnostic: +indexterm:[call/return, error] + +[subs=+quotes] +---- +# #ipfw: call stack error, go to next rule# +---- + +[TIP] +==== +*ipfw* does its best to get your attention for this error. +The above diagnostic shows up on the console, in any console log, and in the [.filename]#/var/log/messages# file regardless of the state of `sysctl net.inet.ip.fw.verbose`. +==== + +Unfortunately, *ipfw* does not currently note *_where_* the missing *return* action is or which rule it went to next. + +It is possible to pick up a clue by watching the rule counts. +Below is the rule count for this errant ruleset after just one packet was received from the *external1* VM: + + +[subs=+quotes] +---- +# *ipfw -a list* +01000 17 1207 count udp from 203.0.113.10 to me +05000 0 0 check-state :default +#06000 16 1136 call 1000 udp from 203.0.113.10 to me 5656# +07000 1 71 count udp from 203.0.113.10 to me +65535 1 71 deny ip from any to any +---- + +This shows that *ipfw* went around this *call* loop 16 times before throwing an error. + +For TCP connections, call and return operate almost the same. +Below is a ruleset with TCP instead of UDP for the desired protocol and including the required *setup* and *keep-state* keywords: + +[subs=+quotes] +---- +# *ipfw -a list* +00500 0 0 check-state :default +01000 0 0 call 20000 tcp from 203.0.113.10 to me 5656 +01100 0 0 count tcp from 203.0.113.10 to me +02000 0 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +20000 0 0 count tcp from 203.0.113.10 to me +21000 0 0 return +65535 0 0 deny ip from any to any +---- + +After the connection is successfully made from external1, the observed counts are: + +[subs=+quotes] +---- +# *ipfw -a list* +00500 0 0 check-state :default +01000 1 60 call 20000 tcp from 203.0.113.10 to me 5656 +01100 1 60 count tcp from 203.0.113.10 to me +02000 8 479 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +20000 1 60 count tcp from 203.0.113.10 to me +21000 1 60 return +65535 0 0 deny ip from any to any +---- + +The difference in rule counts is due to dynamic rules created by the *setup* and *keep-state* keywords on rule 2000. +Counts can also be shown with the `-d` command line parameter. +indexterm:[ipfw, -d] +The numbers below are from just the initial 3-way handshake: +indexterm:[TCP, 3-way handshake] + +[subs=+quotes] +---- +# *ipfw -ad list* +00500 0 0 check-state :default +01000 1 60 call 20000 tcp from 203.0.113.10 to me 5656 +01100 1 60 count tcp from 203.0.113.10 to me +02000 5 276 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default +20000 1 60 count tcp from 203.0.113.10 to me +21000 1 60 return +65535 0 0 deny ip from any to any +## Dynamic rules (1 152): +02000 5 276 (296s) STATE tcp 203.0.113.10 19179 <-> 203.0.113.50 5656 :default +---- + +The above numbers indicate that the 3-way handshake occurred during the dynamic rule setup. + +*General notes on call and return:* +indexterm:[call/return, general notes] + +* *ipfw* allows a *call* out to an address either before or after the current rule. +* There must be a *return* for every *call*. +* *call* / *return* pairs can be nested up to 16 levels deep. +If *ipfw* sees one more *call* rule, it will throw the "call stack error, go to next rule" error and continue with the next rule. +* Similar to *skip-to*, a *call* to rule 0 or to a value greater than 65534, causes *ipfw* to throw an error. +* Similar also to *sets*, if a *call* is made to a target rule in a set that is disabled, the call will land on the next rule in any non-disabled set and processing continues from there. +* If a *return* is encountered when no *call* has been made, the *return* rule is ignored and processing continues with the next rule. + +=== Using uid and gid in rules + +An interesting capability of *ipfw* is its ability to match packets on Unix *uid* and *gid* values. +indexterm:[keyword, uid] indexterm:[keyword, gid] indexterm:[uid/gid] +Network packets themselves have no inherent ownership, so where does this capability come from? +Answer - it comes from the applications that are the source and destination of those packets. + +The new ruleset below is a simple example to examine this capability. +indexterm:[uid/gid, example] +First, locate or add a user (here 'quarven') if needed. + +Then, note the syntax needed for *uid / gid* matching: + +[subs=+quotes] +---- +# *grep quarven /etc/passwd* +quarven:*:1002:1002:Quarven:/home/quarven:/bin/sh + +Copy userv.sh to user *quarven* home directory +# *cp ~/bin/userv.sh /home/quarven* + +Now use userid 'quarven' in an *ipfw* rule: + +# *ipfw add 700 allow udp from 203.0.113.10 to me #uid quarven#* +00700 allow udp from 203.0.113.10 to me uid quarven +# +# *ipfw show* +00700 0 0 allow udp from 203.0.113.10 to me uid quarven +65535 0 0 deny ip from any to any +---- + +Next, login as user 'quarven' and run the script [.filename]#~/userv.sh 5656#. +Then switch to the *external1* VM and run *echo "hello there" | ncat -u 203.0.113.50 5656*. +The results should appear on the console running the *userv.sh* script. + +The results are shown below. + +[subs=+quotes] +---- +quarven@firewall:~ $ */bin/sh userv.sh 5656* +PORT1 = [5656] +Starting UDP listener on [203.0.113.50],[5656] +hello there +^Cquarven@firewall:~ $ +---- + +This works because the instance of *userv.sh* is run under the *uid* quarven as shown below: +indexterm:[userv.sh] indexterm:[uid/gid, usage] + +[subs=+quotes] +---- +Show the user information for the *userv.sh* instance: + +root@firewall:~ # *ps -o user -xl -U quarven* +USER UID PID PPID C PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND +quarven 1002 4256 83703 0 61 0 13380 2908 pause I+ v0 0:00.03 sh userv.sh 5656 +#quarven 1002 6878 4256 0 61 0 13400 2344 select I+ v0 0:00.02 nc -l -k -u 203.0.113.50 5656# +quarven 1002 83703 83431 0 20 0 13380 3168 wait I v0 0:00.10 -sh (sh) +---- + +*ipfw* has matched an incoming network packet to a program owned by a userid. +If the rule is changed to another userid, even *root*, the match will not succeed and the packet will be picked up by the default rule. +Likewise, if the *userv.sh* script is run under another user, even *root*, the match will not succeed. + +[TIP] +==== +It is sometimes necessary to immediately shut down all IP traffic to or from a certain user. +This capability is can be used for that purpose. +Note however, that the *deny* rule below must come *before any check-state rule* to catch traffic that may be otherwise allowed by a dynamic rule. + +[subs=+quotes] +---- +# #*ipfw add 50 deny ip from any to any uid quarven*# +# *ipfw add 100 check-state* + +Note also the item about ICMP traffic in the "General Notes" below. +---- +==== + +*General Notes on Using **uid** and **gid**:* +indexterm:[uid/gid, general notes] + +* The *gid* keyword works in an identical fashion to *uid* described above. +* If using a name as the *uid* or *gid*, the name must exist in the indicated system file. +* Ranges and lists of *uids* or *gids* are not allowed. +For example, *ipfw* does not allow "... *uid* tom,dick,harry" or "... *uid* 1000-1002". +* Outbound traffic works in a similar way, just reversing the source and destination. +* Denied traffic will generally have an indication of ": sendto: Permission denied" +* ICMP traffic cannot be reliably filtered using *uid/gid*. +indexterm:[uid/gid, ICMP issue] +This is a known limitation. +* As noted in man:ipfw[8], some contexts such as initial incoming SYN packets, may have no *uid/gid* associated with them. +* Programs using *setuid(2)* system calls may not behave as expected, though it may be possible to set the *uid/gid* to the effective id if it can be determined. +* Using *uid/gid* keywords for matching is resource intensive and should be used sparingly if at all. + +[[ipfw-rules-lookup-tables-intro]] +== Lookup Tables + +indexterm:[lookup table] + +Lookup tables are a versatile feature of many firewall systems, including *ipfw*. +A lookup table is a virtual container that holds tuples of elements, one of which is a key that functions as a fast lookup feature. +indexterm:[keyword, lookup] indexterm:[lookup, value] indexterm:[lookup, key] +Using a key provided by a rule, *ipfw* can quickly determine if the element is in the table. +If it is, that portion of the rule is matched the value associated with the key is used according to the rule. + +Lookup tables are a powerful feature of *ipfw* and useful in many situations. + +*ipfw* provides five types of lookup tables: +indexterm:[lookup table, types] + +* *Address tables (addr)* - These tables hold addresses that *ipfw* can rapidly find with an address as a key. +indexterm:[lookup table, addr] +If the address is matched the lookup is considered matched and used by the associated rule. +This table type takes an additional keyword 'valtype' that can be used to specify IPv4 addresses or IPv6 addresses. +* *Interface tables (iface)* - These tables hold interface names. +indexterm:[lookup table, iface] +Each entry is the name of an interface. +Note that wildcards such as `em*` are *not* supported. +* *Number tables (number)* - These tables are used for protocols, ports, uids/gids, or jail ids. +indexterm:[lookup table, number] +Entries are 32 bit unsigned integers. +Ranges (for example, 1234-5678) are *not* supported. +* *Flow tables (flow)* - These tables contain flow type suboptions that are used in looking up existing traffic flows. +indexterm:[lookup table, flow] +* *MAC* - A MAC address type table holds media access control (MAC) addresses as an address with optional mask length. +indexterm:[lookup table, MAC] +The mask length defaults to 48 bits if not otherwise specified. + +=== Creating Lookup Tables + +All tables must be created before they can be referenced by a rule. +Note that the commands to manage tables do not have line numbers - they are independent shell commands that exist outside the ruleset. +indexterm:[lookup table, create] indexterm:[keyword, table] + +[subs=+quotes] +---- +# *ipfw table foo create* +---- + +By default, the *ipfw table create* command creates tables of type *addr*. +Table names share the same namespace and so must be unique even among tables of different types. + +To specify other types, add the type keyword: + +[subs=+quotes] +---- +# *ipfw table bar create type iface* +# +# *ipfw table baz create type flow* +# +# *ipfw table bop create type number* +---- + +[NOTE] +==== +Previously, when creating a table of type number, a bug existed that required an algorithm option such as `number:array`. +This bug was fixed and documented link:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=233072#c1[here]. +==== + +To see all tables, use the *list* subcommand to show the table and any contents. +indexterm:[keyword, table] +Shown below, all four table types are created and one entry is added to each table: + +[subs=+quotes] +---- +# *ipfw table all list* +# +# *ipfw table foo create type addr* +# *ipfw table foo add 192.168.1.100 33* +added: 192.168.1.100/32 33 +# +# *ipfw table bar create type iface* +# *ipfw table bar add em0 33* +added: em0 33 +# +# *ipfw table baz create type number* +# *ipfw table baz add 9999 33* +added: 9999 33 +# +# *ipfw table bop create type flow* +# *ipfw table bop add 203.0.113.10,192.168.1.100 33* +#ignored: 33# +#ipfw: Adding record failed: Invalid argument# +# +# *ipfw table bop destroy* +# +# *ipfw table bop create type flow:src-ip,dst-ip* +# *ipfw table bop add 203.0.113.10,192.168.1.100 33* +added: 203.0.113.10,192.168.1.100 33 +# +# *ipfw table bip create type mac* +# *ipfw table bit add 58:9c:fc:01:02:03 33* +added: 58:9c:fc:01:02:03/48 33 +# +# *ipfw table all list* +--- table(bar), set(0) --- +em0 33 +--- table(baz), set(0) --- +9999 33 +--- table(bip), set(0) --- +58:9c:fc:01:02:03/48 33 +--- table(bop), set(0) --- +203.0.113.10,192.168.1.100 33 +--- table(foo), set(0) --- +192.168.1.100/32 33 +---- + +Note the error on the flow table above. +indexterm:[lookup table, flow] +Flow tables take an explicit flow specification (discussed below) when they are created. +When trying to add an entry to a flow table that does not match the flow specification, *ipfw* throws an error. + +[TIP] +==== +Note that the output of *ipfw table all list* is ordered by table _name_, not table _type_. +This is worth remembering when using many tables of different types. +Also, the command does not actually display the table type. +Use the command *ipfw table info* to display the table type. +==== + +In all the examples above a key and a value were added to each table. +indexterm:[table, value] +The key was added according to the table type (addr, iface, etc.) +The values above, all set to the integer value 33, are just placeholders in the examples. +The _value_ for each key is whatever makes sense for the firewall administrator. + +"Whatever makes sense" depends on how the table will be used. +indexterm:[lookup table, uses] +man:ipfw[8] identifies some 12 different uses for table values - *skipto* rule number to skip to, +*pipe* number, +*fib* number, +*nat* number to jump to, +*dscp* value to match or set, +*tag* number to match or set, +*divert* port number to divert traffic to, +*netgraph* hook number to move packet to, +*limit* maximum number of connections, +*ipf4* ipv4 next hop to forward packets to, +*ipv6* ipv6 next hop to forward packets to, +*mark* value to match or set. + +Some of these keywords have already been studied, and will return to assist with table operations. + +Tables can be removed one at a time with the *destroy* subcommand, provided the table is not used in any rule: +indexterm:[table, destroy] + +[subs=+quotes] +---- +# *ipfw table bar destroy* +---- + +or removed all at once by specifying the special name all: + +[subs=+quotes] +---- +# *ipfw table all destroy* +---- + +[WARNING] +==== +Note that there is *_no confirmation_* with the *ipfw table all destroy* command as there is with the *ipfw flush* command, so make sure that is the intended action. +==== + +[TIP] +==== +A table cannot be destroyed if it is used in a rule. +---- + # *ipfw table all destroy* + ipfw: failed to destroy table(redhosts) in set 0: Device busy +---- +Delete the rule using the table, then delete the table. +==== + +=== Using Tables in Rules + +To begin using tables in rules, it is first necessary to understand the use of the word *tablearg* which is frequently found in man:ipfw[8]. +indexterm:[keyword, tablearg] indexterm:[tablearg] + +[[ipfw-rules-understanding-tablearg]] +==== Understanding the Word *tablearg* + +A *tablearg* is a value that is the result of a table lookup using a key supplied by a field in a packet. +Which field depends on the table type, as discussed above. + +The term *tablearg* is used to show where in the rule the retrieved value will be applied. +indexterm:[tablearg, example] + +[[ipfw-rules-tablearg-keyword]] +.*tablearg* Keyword Used in a Rule +image::ipfw-rules060.png["*tablearg* Keyword Used in a Rule. Refer to paragraphs below."] + +For a rule with a tablearg keyword, *ipfw* + +. Looks up the key in the identified table. +The key is supplied by one or more fields in the packet itself. +. Applies the value associated with that key in the table to replace the word *tablearg*. + +Essentially + +[subs=+quotes] +---- +# *ipfw add 50 skipto tablearg ip from 'table(badhosts)' to any* +---- + +becomes + +[subs=+quotes] +---- +# *ipfw add 50 skipto 65535 ip from 203.0.113.10 to any* +---- + +if the from address in the packet is matched in the table. + +If it is not matched, processing continues with the next rule. + +[NOTE] +==== +From the man:ipfw[8] man page - The *tablearg* argument can be used with the following actions: *nat*, *pipe*, *queue*, *divert*, *tee*, *netgraph*, *ngtee*, *fwd*, *skipto*, *setfib*; wth action parameters: *tag*, *untag*; and with rule options: *limit*, *tagged*. +==== + +*First Example* + +The first example is to use a table with the *skipto* keyword. +indexterm:[table, with skipto] + +Consider a table of addresses of "bad hosts". +If any such host were to try to connect to or through the firewall, they should be denied. +Since there is already a deny rule (the immutable rule at 65535), it is possible to load an address table with keys of hosts, and values of the deny rule, 65535: + +First, on the *firewall* VM, create a table called _badhosts_, and populate it with the addresses of hosts to be denied: + +[subs=+quotes] +---- +Restart *ipfw*: + +# *kldunload ipfw* +# *kldload ipfw* + +Create and populate the table: + +# *ipfw table badhosts create type addr* +# *ipfw table badhosts add 203.0.113.10/32 65535* +added: 203.0.113.10/32 65535 +---- + +Then create a rule that uses the table. +For this use case, put the rule _before_ the *check-state* rule, + +[subs=+quotes] +---- +# *ipfw add 50 skipto tablearg ip from 'table(badhosts)' to any* +00050 skipto tablearg ip from table(badhosts) to any +# +# *ipfw add 100 check-state* +# +# *ipfw add 1000 allow ip from any to any* +---- + +Note the single quotes around the `table(badhosts)` entry to placate the shell: +indexterm:[table, example] + +To test, start up *userv3.sh* on the *firewall* VM: +indexterm:[userv3.sh] + +[subs=+quotes] +---- +# *sh userv3.sh* +Starting UDP listeners on [5656],[5657],[5658] +---- + +And on the *external1* VM (which should have address 203.0.113.10) , start up *ucon.sh*: +indexterm:[ucon.sh] + +[subs=+quotes] +---- +# *sh ucon.sh 5656* +UDP communicationing [203.0.113.50],[5656],[1] +---- + +No communication should be seen on the *firewall* VM. +The *skipto* rule matched the address in the table, and the *tablearg* keyword was replaced with the default deny rule. +This can be verified by reviewing the counters with *ipfw show*. + +However, by removing the entry for `203.0.113.10/32` from the `badhosts` table, the communications succeed and reach the *userv3.sh* services listening on the *firewall* VM: + +[subs=+quotes] +---- +# *ipfw table badhosts delete 203.0.113.10* +deleted: 203.0.113.10/32 0 +---- + +Retrying the *ucon.sh* communications above will succeed. + +It would be tempting to combine the previous two examples into something like: + +[subs=+quotes] +---- +# *ipfw add 1000 allow udp from 'table(badhosts)' to me dst-port 'table(badports)'* +ipfw: invalid destination port table(badports) +---- + +but *ipfw* does not allow the use of more than one table in a rule. + +However, instead of a second *table* keyword, it is possible to use the *lookup* keyword for the port: + +[subs=+quotes] +---- +A contrived example: + +# *ipfw add 25 allow udp from 'table(badhosts)' to me lookup dst-port badports* +00025 allow udp from table(badhosts) to me dst-ip lookup dst-port badports +---- + +While this does work, the better solution is to use the a *flow* table: +indexterm:[table, example] + +Unload and reload the *ipfw* kernel module for the next example, this time for "good hosts". +indexterm:[table, flow table] indexterm:[lookup table, flow] + +[subs=+quotes] +---- +# *ipfw table goodflow create type flow:src-ip,dst-port* +# +# *ipfw table goodflow add 203.0.113.10,5656* +added: 203.0.113.10,5656 0 +# +# *ipfw table goodflow add 203.0.113.10,5657* +added: 203.0.113.10,5657 0 +# +# *ipfw add 500 allow udp from any to me flow 'table(goodflow)'* +00500 allow udp from any to me flow table(goodflow) +---- + +This gives the firewall admin much more granular control of exactly what host and what port to match together. +Startup the *userv3.sh* script on the *firewall* VM and note the results by trying *sh ucon.sh 5656*, *sh ucon.sh 5657*, and *sh ucon.sh 5658* from the *external1* VM. +The first two succeed, while the third does not. + +Using the *valtype* keyword for addr tables permits separate tables for IPv4 and IPv6: +indexterm:[keyword, valtype] + +[subs=+quotes] +---- +# Create the translation tables. +# ipfw table T46 create type addr valtype ipv6 +# ipfw table T64 create type addr valtype ipv4 +---- + +*Second Example* + +The second example concerns using tables with the *limit* keyword. +indexterm:[table, limit example] +Recall that the *limit* keyword limits the number of active connections at one time. + +Reset *ipfw* by unloading and loading the *ipfw.ko* kernel module. + +Now, consider an address table to keep track of addresses and limits like this: + +[subs=+quotes] +---- +# Create a table named "limits". +# *ipfw table limits create type addr valtype limit* +# +# Assign a value of 23 to the address 203.0.113.10 +# *ipfw table limits add 203.0.113.10 23* +added: 203.0.113.10/32 23 +# +# Now add a limit rule for this address +# *ipfw add 1000 allow udp from 'table(limits)' to me limit src-addr tablearg* +01000 allow udp from table(limits) to me limit src-addr tablearg :default +# +# And add a rule to allow the traffic. +# *ipfw add 1100 allow udp from 'table(limits)' to me* +# +---- + +The above rules have created a table named "limits" of tabletype _addr_ and value type _limit_ with one entry, 203.0.113.10 with value 23. +With rule 1000, all packets coming into the firewall will be looked up in the table. +If a packet from address 203.0.113.10 arrives, the lookup will succeed and the value of "23" will be applied as the tablearg to the *limit* option for connections with that address. + +Once this is set up, it is possible to change the limit value without changing the rule. +The value can either be changed by deleting and re-adding the table entry. + +While this looks like a good solution, *there is a bug here*. + +*ipfw* has failed to correctly initialize the value in the table. + +Listing the table shows the problem: + +[subs=+quotes] +---- +# *ipfw table limits list* +203.0.113.10/32 #0# +---- + +This has been logged as link:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=284691[Bug 284691] and will be tracked as this book goes to publication. + +==== More on *flow* tables + +A *flow* table maintains a list of *flows*. +indexterm:[lookup table, flow] indexterm:[table, flow] +A *flow* is a designation given to traffic between two endpoints. +The designation can be any subset of: + +* *src-ip* +* *src-port* +* *proto* +* *dst-ip* +* *dst-port* + +that makes sense in source -> destination order. +indexterm:[table, flow examples] +Examples include: + +[subs=+quotes] +---- +# *ipfw table zoo create type flow:src-ip* # Creates a flow based on soure IP address +# *ipfw table zar create type flow:proto* # Creates a flow based on just a protocol +# *ipfw table zaz create type flow:dst-ip* # Creates a flow based on just the desitination IP +# *ipfw table zop create type flow:dst-port* # Creates a flow based on the destination port +---- + +or with extra specificity: + +[subs=+quotes] +---- +# *ipfw table zip create type flow:src-ip,proto,dst-ip,dst-port* # Flow based on all four +# *ipfw table zim create type flow:src-ip,proto* # Just source IP and protocol +# *ipfw table zam create type flow:src-ip,proto,dst-ip* # Source IP, destination IP and protocol +# *ipfw table zap create type flow:src-ip,dst-ip* # Just IP address endpoints +---- + +Once the table is created for a *flow*, entries can be placed in the table provided they match the table *flow* specification. + +Matching these additions to the tables created above: + +[subs=+quotes] +---- +# *ipfw table zim add 192.168.200.30,tcp* +---- + +would succeed, but + +[subs=+quotes] +---- +# *ipfw table zip add 192.168.30.20,172.20.15.20* +---- + +would fail because the flow specification for table zip is *src-ip,proto,dst-ip,dst-port* and neither the protocol nor the destination port was given. + +A correct flow specification for table zip would be something like: + +[subs=+quotes] +---- +# *ipfw table zip add 192.168.30.20,tcp,172.20.15.20,80* +---- + +*flow* tables allow for precise definition of traffic between a source and a destination. +Once in the table, rules can be applied to commands *allow*, *deny*, *divert*, *queue*, etc. for modifying traffic flow. + +*General notes on all tables:* +indexterm:[lookup table, general notes] + +* Table names can be numeric or alphanumeric and can include only hyphen (-), underscore (_), and period (.) as special characters. +* Maximum table name length is 63 characters. +* Tables names must be unique within a set. +Tables can have the same name across different sets, however any rules for tables in sets other than set 0, must include the set number. +The sysctl variable `net.inet.ip.fw.tables_sets` controls this behavior. +indexterm:[sysctl, net.inet.ip.fw.tables_sets] +* The maximum number of tables across all sets is 65535. +Practically however, the number is controlled by the sysctl variable `net.inet.ip.fw.tables_max`. +indexterm:[sysctl, net.inet.ip.fw.tables_max] +The default is 128. +* If a table is in use in a rule, it cannot be destroyed. +The rule must be removed first, then the table can be destroyed. +However, a table can be flushed (*ipfw table _tablename_ flush*) at anytime. +* All table types survive an *ipfw flush* action, and table contents are not affected. +* Make table names as descriptive as possible to avoid confusion when used in rules. +The names used here (foo, bar, zip, zap, etc.) are just examples. +* As noted in the man page, if two tables are used in a rule, the result of the second (destination) is used. +Therefore avoid using two tables in a rule, or try using the *lookup* keyword instead. + +*Notes on specific table types:* +indexterm:[lookup table, type notes] + +* *Address tables (addr)* +** Address tables (addr) support IPv4 and IPv6 address types, and varying mask lengths appropriate for each address type. +The default mask length for IPv4 is 32 bits (/32) and the default prefix for IPv6 is 128 bits (/128). +** Table lookups will return the most specific entry, so 203.0.113.20/32 is preferred over 203.0.113.0/24. + +* *Interface tables (iface)* +** Interface tables store interface names as alphanumeric text. +The text does not actually have to match a current valid interface. +** Special characters in interface names can include any from the set ++ + [-+_?,.!~@#%^&*()=;:/<>{}|] ++ +Note however, that the shell may recognize some of these characters when adding and during lookup, thus interfering with the table operation, and so _special characters in interface names should be avoided_. +** The maximum key length is 15 characters. +You can create an entry with a longer name and *ipfw* will not throw an error, but the entry will be truncated to 15 characters. +** It is possible to add interface names consisting of Unicode characters, though support for Unicode character sets in user terminals varies. +For example, to add the interface named "meλ" ("em ee lambda") with value 32 to table "myintf" you would type: ++ + # ipfw table myintf add emCtl+Shift+U 03BB 32 ++ +Note however, that it may not be possible to actually create the named interface. +** There is *no support for interface ranges*, for example `em0-4`, even though an interface name *"em0-4"* can be entered. + +* *Number tables (number)* +** Number tables support unsigned 32-bit integer types. +** Entries can be positive or negative. +Negative entries perform unsigned ones complement arithmetic, and positive numbers roll over from 4294967295 to 0. +** Any shell element that evaluates to a number can be used: shell variables that resolve to a number (`$MAILCHECK`, `$PPID`), backtick operations such as `expr 5 + $UID`, `id -u`, `date "+%s"`, and special variables like `$RANDOM` in bash. +** As with other table types, ranges are not supported. + +* *Flow tables (flow)* +** Flow tables describe network traffic based on the desired attributes. +The best matches include as much detail as possible: `src-ip`, `proto`, `dst-ip`, `port`. +Including less than that may make it difficult to add an element in the table: +*** *ipfw table foo create type flow:dst-port* # Table based on just the destination port +*** *ipfw table foo add telnet* # Fails to add! +** *ipfw table bar create type flow:dst-ip,dst-port* +** *ipfw table bar add 203.0.113.10,5656* + +== Stream Control Transport Protocol (SCTP) + +A readable introduction to SCTP is found in Wikipedia - https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol#RFCs and ever more detail is found in the accompanying RFCs. +indexterm:[keyword, sctp] indexterm:[SCTP] + +=== SCTP Versions + +As of FreeBSD 14.1, there are three different versions of SCTP - a "native" version, a "separate portable" version, and a "userland" version. +indexterm:[SCTP, versions] + +* FreeBSD ships with the "native" version of the protocol, described in man:sctp[4]. +(This is actually the reference implementation of SCTP initially developed on FreeBSD 7.) +This version requires loading the kernel module *sctp.ko* before use. +Native SCTP uses the SCTP library on FreeBSD which provides access to the various functions found in . +Developers can use the features described in man:sctp[4] to develop SCTP applications based on the native protocol. + +Then, there are a couple of notable packages regarding SCTP: + +* *libusrsctp “Portable SCTP userland stack”* – This is a non-kernel implementation of the protocol using “usrsctp_*” functions. +It also provides UDP encapsulation as shown in the Wireshark image below: + +* *sctplib “User-space implementation of the SCTP protocol RFC 4960”* – This package is a re-implementation of the native SCTP code that can function as a replacement for the default installed code. +indexterm:[RFC, 4960] +It does not require the *sctp.ko* kernel module. +indexterm:[module, sctp] + +[NOTE] +==== +As noted in the *BUGS* section of man:sctp[4], the *sctp.ko* kernel module cannot be unloaded. +Restart FreeBSD to remove the module from the kernel. +==== + +Interestingly, the reference implementation for SCTP that was developed on FreeBSD 7 and has been archived on GitHub at link:https://github.com/cyberroadie/sctp-examples[https://github.com/cyberroadie/sctp-examples]. +*ipfw* played a role in its development and the vestiges of that development remain in the *ipfw* code base and in the collection of *sysctls* that support it. + +The following section studies the native SCTP protocol usage and the encapsulated usage with *ipfw*. + +=== SCTP Protocol Operation + +The image below shows a Wireshark view of a typical native SCTP association (connection): +indexterm:[SCTP, association] + +[[ipfw-rules-sctp000]] +.Wireshark View of Native SCTP +image::ipfw-sctp000.png["Wireshark view of Native SCTP. Refer to paragraphs below."] + +Notice how there are two different interfaces involved with this transfer - 127.0.0.1, and 192.168.1.78. +In fact, SCTP supports association setup and data exchange with multiple interfaces to a remote node. +The RFC's explain this capability in detail. + +Also in this image, note the basic *_4-way handshake_* - INIT, INIT_ACK, COOKIE_ECHO, and COOKIE_ACK. +Also shown are the HEARTBEAT, DATA, SACK (Stream Acknowledgement) messages, and the shutdown sequence of SHUTDOWN, SHUTDOWN_ACK, and SHUTDOWN_COMPLETE. +indexterm:[SCTP, 4-way handshake] + +Below is a view of `netstat -an` showing the display of a separate SCTP section containing all current associations: +indexterm:[SCTP, view with netstat] + +[subs=+quotes] +---- +% netstat -an +Active Internet connections (including servers) +Proto Recv-Q Send-Q Local Address Foreign Address (state) +tcp4 0 0 \*.22 *.* LISTEN +tcp6 0 0 \*.22 *.* LISTEN +tcp4 0 0 127.0.0.1.631 \*.* LISTEN +tcp6 0 0 ::1.631 \*.* LISTEN +udp4 0 0 127.0.0.1.123 \*.* +udp6 0 0 fe80::1%lo0.123 \*.* +udp6 0 0 ::1.123 \*.* +udp4 0 0 192.168.1.78.123 \*.* +udp6 0 0 2600:1700:3901:4.123 \*.* +udp6 0 0 fe80::3e97:eff:f.123 \*.* +udp4 0 0 \*.123 *.* +udp6 0 0 \*.123 *.* +#Active SCTP associations (including servers)# +Proto Type Local Address Foreign Address (state) +sctp4 1to1 127.0.0.1.5000 127.0.0.1.42227 ESTABLISHED + 192.168.1.78.5000 192.168.1.78.42227 +sctp4 1to1 127.0.0.1.42227 127.0.0.1.5000 ESTABLISHED + 192.168.1.78.42227 192.168.1.78.5000 +sctp4 1to1 127.0.0.1.5000 LISTEN + 192.168.1.78.5000 +Active UNIX domain sockets +Address Type Recv-Q Send-Q Inode Conn Refs Nextref Addr +fffff8015575c000 stream 0 0 0 fffff80155758c00 0 0 +. . . +---- + +Internally, the SCTP data packets look different from TCP and/or UDP packets. +However, like those two, SCTP has a protocol number (hexadecimal 0x84, decimal 132), source address, destination address, and port numbers, so using *ipfw* with SCTP will be fairly straightforward. + +Here's a look at a typical packet: +indexterm:[SCTP, typical packet] + +[[ipfw-rules-sctp010]] +.Internal View of the SCTP INIT Data Packet +image::ipfw-sctp010.png["Internal View of the SCTP INIT Data Packet. Refer to paragraphs below."] + +To study SCTP’s behavior with *ipfw* the client/server echo program, shown above, will be used, along with a separate streaming application similar to the familiar _chargen_ small server. + +Also needed is the *internal* VM. +If this VM has not yet been set up, do so now following the general guidelines of the crossref:ipfw-appendix-a[appendix-a, Qemu Setup] section for details. +Be sure to install all the required packages, including *tsctp*. + +[[ipfw-rules-using-tsctp-tool]] +=== Using the TSCTP Testing Tool on FreeBSD + +A handy testing tool is the FreeBSD package `tsctp`. +indexterm:[SCTP, tsctp test tool] +If this package was not previously installed, install the package on the *external1* and *internal* VMs. +(Configure the VMs to access the Internet to install the package. +Refer to the crossref:ipfw-appendix-a[appendix-a, Qemu Setup] section for details.) + +[subs=+quotes] +---- +# *pkg install tsctp* +---- + +This tool uses the native SCTP protocol version. +To use, first load the *sctp.ko* kernel module on the *external1* and *internal* VMs: +indexterm:[module, sctp] + +[subs=+quotes] +---- +# *kldload sctp.ko* +---- + +Running the program is discussed below. + + +[[ipfw-rules-sctp015]] +.Setting Up to Test Native SCTP +image::ipfw-sctp015.png["Setting Up to Test Native SCTP. Refer to paragraphs below."] + +To get started, on the FreeBSD host machine, initialize the *bridge* and *tap* devices to the architecture shown in the figure above. +indexterm:[bridge] indexterm:[tap] + +[subs=+quotes] +---- +% *cd ~/ipfw-primer/ipfw/HOST_SCRIPTS* +% *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5* + +Then start the required VMs: + +% */bin/sh runvm.sh firewall external1 internal* +---- + +indexterm:[mkbr.sh] indexterm:[runvm.sh] + +Then follow these steps: + +. Apply the addressing shown in the above figure and ensure connectivity with adjacent interfaces, and with the opposite side interfaces (10.10.10.20 from the *external1* VM and 203.0.113.10 from the *internal* VM). ++ +. The default route for the *external1* VM should point to 203.0.113.50, and for the *internal* VM it should point to 10.10.10.50. ++ +. Load the *sctp.ko* kernel module on the *external1* and the *internal* VMs. +This enables communication via native SCTP on these VMs. +indexterm:[SCTP, tsctp example] ++ +[subs=+quotes] +---- +On the *internal* VM, run in server mode: + + # *tsctp -L 127.0.0.1 -L 10.10.10.20 -p 1234* + +and on the *external1* VM, run in client mode: + + # *tsctp -L 203.0.113.10 -p 1234 -n 10 -l 1000 -V 10.10.10.20* + +---- + +Use `tscp --help` to get a list of the options and meanings. + +The `-V` option will print a list of messages being send by the client. + +The client program sends 10 messages (`-n 10`) to the server. +Simple statistics are shown on both the client and the server once the program terminates. + +The above procedure has established SCTP communications across the firewall. +The *firewall* VM does not need to load the *sctp.ko* module. +To the *firewall* VM, this is simply normal IP traffic. + +Restart the client with `-n 0`, for unlimited messages. +While normal SCTP traffic is established from client to server, load *ipfw* on the *firewall* VM. + +Traffic is immediately halted. +Eventually, the client will recognize it has been disconnected. +This may take a couple of minutes. +The disconnection is shown in the image below: + +[[ipfw-rules-sctp020]] +.IPFW Firewall Disrupts SCTP Traffic +image::ipfw-sctp020.png["IPFW Firewall Disrupts SCTP Traffic. Refer to paragraphs below."] + +Creating suitable rules for SCTP traffic is quite similar to other rules performed in previous examples. + +[subs=+quotes] +---- +root@firewall:~ # *ipfw add 100 check-state* +00100 check-state :default +root@firewall:~ # +root@firewall:~ # *ipfw add 1000 allow sctp from 203.0.113.10 to 10.10.10.20* +01000 allow sctp from 203.0.113.10 to 10.10.10.20 +root@firewall:~ # *ipfw add 2000 allow sctp from 10.10.10.20 to 203.0.113.10* +02000 allow sctp from 10.10.10.20 to 203.0.113.10 +root@firewall:~ # +root@firewall:~ # *ipfw zero* +Accounting cleared. +root@firewall:~ # *ipfw zero 65535* +Entry 65535 cleared. +root@firewall:~ # +root@firewall:~ # *ipfw show* +00100 0 0 check-state :default +01000 0 0 allow sctp from 203.0.113.10 to 10.10.10.20 +02000 0 0 allow sctp from 10.10.10.20 to 203.0.113.10 +65535 0 0 deny ip from any to any +root@firewall:~ # +---- + +One would think the "one-rule" version using *setup* and *keep-state* keywords would work, but it does not. +The "two-rule" version must be used. +indexterm:[SCTP, two-rule version] + +Also, keep in mind that SCTP is typically used where there are multiple interfaces per association. +This example has used only one, but the principles are the same. + +=== Downloading and Building *usrsctp* Programs + +To test SCTP encapsulation with UDP, download and build the *usrsctp* kit. +indexterm:[SCTP, usrsctp] +Follow this procedure to download and build the programs for the *usrsctp* kit. +indexterm:[SCTP, building usrsctp] +On the *external1* VM and the *internal* VM, the procedure is the same. + +For this procedure, reconfigure the *external1* and *internal* VMs to access the Internet as described in crossref:ipfw-appendix-a[appendix-a, Appendix A]. +Then perform these steps: + +[subs=+quotes] +---- +# *pkg install git* +# *pkg install cmake* +# *mkdir /root/src* +# *cd /root/src* +# *git clone https://github.com/sctplab/usrsctp.git* +# *mkdir tmp* +# *cd tmp* +# *cmake ../usrsctp* +# *cmake --build .* + +Once finished, the test programs are located in /root/src/tmp/programs. +---- + +Now reconfigure *external1* and *internal* VMs back to the architecture and addressing (including default routes) in crossref:ipfw-rules[ipfw-rules-using-tsctp-tool, Using the TSCTP Testing Tool]. + +=== Encapsulated Echo Server and Client with IPFW + +The figure below shows encapsulated usage of SCTP with the *chargen_server_upcall* program running on the *internal* VM and the *client_upcall* program running on the *external1* VM. +indexterm:[SCTP, UDP encapsulation] +The output is similar to that of the _chargen_ small server program. + +[TIP] +==== +If the client doesn't start right away, hit kbd:[Enter] one time. +==== + + +[[ipfw-rules-sctp030]] +.SCTP Traffic Encapsulated in UDP Datagrams +image::ipfw-sctp030.png["SCTP Traffic Encapsulated in UDP Datagrams. Refer to paragraphs below."] + +All the data exchanged between the two systems was encapsulated in UDP datagrams as shown in the figure below. + +[[ipfw-rules-sctp035]] +.Wireshark View of UDP Encapsulation of SCTP +image::ipfw-sctp035.png["Wireshark View of UDP Encapsulation of SCTP. Refer to paragraphs below."] + +Any *ipfw* rules for this traffic only have to be concerned with UDP, not SCTP. + + diff --git a/documentation/content/en/books/ipfw-primer/ipfw-rules/_index.po b/documentation/content/en/books/ipfw-primer/ipfw-rules/_index.po new file mode 100644 --- /dev/null +++ b/documentation/content/en/books/ipfw-primer/ipfw-rules/_index.po @@ -0,0 +1,6357 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-01-20 12:33-0500\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. type: YAML Front Matter: description +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1 +#, no-wrap +msgid "Creating and Using IPFW Rules" +msgstr "" + +#. type: YAML Front Matter: title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1 +#, no-wrap +msgid "Chapter 3. IPFW Rules" +msgstr "" + +#. type: Title = +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:13 +#, no-wrap +msgid "IPFW Rules" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:54 +msgid "" +"The manual page for man:ipfw[8] lists the entire command syntax including " +"those for general ruleset construction. Basic traffic rules are discussed " +"first and more complex capabilities are discussed in later sections. Each " +"section builds on the previous sections so the reader will be better " +"positioned to understand the advanced material later in the book." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:59 +msgid "" +"Almost all the examples in this section can be run on the architecture used " +"in the previous chapter, specifically that of crossref:ipfw-operation[ipfw-" +"intro-simple-lab, \"Chapter 2, Figure 1\"]. The crossref:ipfw-" +"introduction[ipfw-introduction-quickstart,\"Quick Start\"] section in the " +"Introduction can provide guidance on setting this back up. indexterm:[Quick " +"Start] Ensure IPv4 addressing is set up as shown in crossref:ipfw-" +"operation[ipfw-intro-simple-lab, \"Chapter 2, Figure 1\"]." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:62 +#, no-wrap +msgid "" +"*ipfw* rules take the general format of:\n" +"indexterm:[rule, general format]\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:66 +#, no-wrap +msgid "" +"# *ipfw* command [rule_number] [*set* set_number] [*prob* match_probability] _action_\n" +" [*log* [*logamount* number]] [*altq* queue] [{*tag* | *untag*} number] _body_\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:70 +msgid "" +"Bolded keywords indicate literal option text that is added to a rule. " +"Italicized keywords indicate a block of additional content that is rule " +"dependent." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:73 +msgid "The rule body has its own syntax format: indexterm:[rule, rule body]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:80 +msgid "" +"Here is an example with basic syntax for an entire rule: indexterm:[rule, " +"example syntax]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:82 +#, no-wrap +msgid "Description of *ipfw* Rule Syntax" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:83 +#, no-wrap +msgid "Description of *ipfw* Rule Syntax. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:83 +#, no-wrap +msgid "ipfw-rules-rulecallouts.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:86 +msgid "The FreeBSD *ipfw* shell command" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:87 +msgid "The *ipfw* rule command (add)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:88 +msgid "The optional rule number (1000)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:89 +msgid "An optional set keyword and value (set 2)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:90 +msgid "An optional probability keyword and value (prob 0.5)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:91 +msgid "The rule action keyword (deny)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:92 +msgid "An optional log keyword (log)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:93 +msgid "An optional logamount keyword and value (logamount 50000)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:94 +msgid "An optional altq keyword and value (altq red)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:95 +msgid "An optional tag keyword and value (tag 27)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:96 +msgid "The body of the rule starting with a protocol keyword (tcp)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:97 +msgid "A source direction keyword (from)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:98 +msgid "A source address (any internet address)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:99 +msgid "A destination keyword (to)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:100 +msgid "A destination address (any interface on the local system)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:101 +msgid "A destination port number (8081)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:102 +msgid "" +"A comment. Note that comments are only valid in the match pattern section of " +"a rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:105 +msgid "" +"The example in the above figure would not actually load - there is no man:" +"altq[9] queue named `red` set up yet - but it does show the overall format " +"of how rules are constructed. This example also shows the use of the Unix " +"line continuation convention using a single backslash at the end of the line " +"(with no following spaces) to continue to the next line." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:107 +msgid "" +"The essence of *ipfw* rule processing is found when patterns that are " +"defined in the rule body are matched on incoming or outgoing packets, one at " +"a time and the action keywords are processed in turn." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:110 +msgid "" +"In other words, *ipfw* directs traffic flow by first matching each incoming " +"or outgoing packet against patterns supplied within the body of the rule. " +"The patterns include protocols (tcp, udp, igmp, eigrp, etc.), source and " +"destination addresses and ports, and options that apply to the context of " +"the traffic." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:111 +#, no-wrap +msgid "Practical Ruleset Development" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:115 +msgid "" +"This section concentrates on the basic commands and actions. indexterm:" +"[ruleset, development]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:118 +msgid "The basic command keywords are these: indexterm:[rule, basic keywords]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:124 +#, no-wrap +msgid "" +"*enable/disable* - commands to disable or enable *ipfw* rule processing.\n" +"The kernel module remains loaded - the effect is to suspend or resume rule processing.\n" +"This is important to understand early as these commands function like an 'on/off' switch to firewall operation.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:125 +#, no-wrap +msgid "*add* - adds a rule.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:127 +#, no-wrap +msgid "" +"*delete* - deletes a rule.\n" +"The rule number must be specified - for example, *ipfw delete 1000*.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:129 +#, no-wrap +msgid "" +"*list* - lists the contents of the current ruleset.\n" +"Even if there have been no rules added, the list command should always list out the default rule, by default, `65535 deny ip from any to any`.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:130 +#, no-wrap +msgid "*show* - similar to the *list* command, *show* includes counters for each rule matched.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:133 +#, no-wrap +msgid "" +"*flush* - delete all the rules in the ruleset except for rules in set 31.\n" +"(Sets are described later in this Chapter.)\n" +"Since this is a command with enormous impact, a *_Yes/No_* prompt is issued before continuing.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:136 +msgid "" +"indexterm:[enable/disable] indexterm:[add] indexterm:[delete] indexterm:" +"[list] indexterm:[show] indexterm:[flush]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:138 +msgid "The basic traffic flow action keywords are these:" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:142 +#, no-wrap +msgid "*allow* | *accept* | *pass* | *permit* - direct *ipfw* to allow a packet through this rule should the packet match the rule body.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:144 +#, no-wrap +msgid "" +"*count* - increment a counter applied to a rule.\n" +"No other processing is applied to the packet.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:145 +#, no-wrap +msgid "*deny* | *drop* - do not allow a packet to pass through this rule should the packet match the rule body.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:146 +#, no-wrap +msgid "*check-state* [*:flowname* | *:any*] - check if a dynamic rule already exists.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:147 +#, no-wrap +msgid "*reset* - resets Network Address Translation tables.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:150 +msgid "" +"indexterm:[allow/accept/pass/permit] indexterm:[count] indexterm:[deny/drop] " +"indexterm:[check-state] indexterm:[reset]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:152 +msgid "" +"The man:ipfw[8] man page has the complete list of action keywords, and " +"describes each in detail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:154 +msgid "This text also examines these keywords in the rules section:" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:158 +#, no-wrap +msgid "*prob* - assign a probability (a value between 0 and 1) to the rule action\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:159 +#, no-wrap +msgid "*set* - use a collection of rules\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:160 +#, no-wrap +msgid "*tag* and *untag* - apply an internal tag to a packet affected by the rule\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:161 +#, no-wrap +msgid "*log* and *logamount* - log keywords\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:163 +#, no-wrap +msgid "*reset* - send a TCP reset on connection\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:164 +#, no-wrap +msgid "*tee* - cause packets to flow in multiple ways\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:165 +#, no-wrap +msgid "*unreach* - specify an action if a packet's destination is unreachable\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:166 +#, no-wrap +msgid "*setdscp* - set DiffServe parameters for outbound packets\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:167 +#, no-wrap +msgid "*skipto* - jump around a ruleset\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:168 +#, no-wrap +msgid "*divert* - pull packets into userspace for programmatic purposes\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:169 +#, no-wrap +msgid "*limit* - limit the number of active connections\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:170 +#, no-wrap +msgid "*call* and *return* - another way to jump around a ruleset\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:171 +#, no-wrap +msgid "*lookup tables* and the *lookup* - log keywords\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:174 +msgid "" +"indexterm:[prob] indexterm:[set] indexterm:[tag] indexterm:[log/logamount] " +"indexterm:[reset] indexterm:[tee] indexterm:[unreach] indexterm:[setdscp] " +"indexterm:[skipto] indexterm:[divert] indexterm:[limit] indexterm:[call/" +"return] indexterm:[lookup tables] indexterm:[lookup]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:178 +msgid "" +"Most action keywords, such as `allow` or `deny`, determine traffic flow. It " +"is important to become familiar with these actions as they will be used in " +"almost every rule. In addition, carefully note what *ipfw* does after it " +"matches a packet and applies an action - it either terminates its search, or " +"it goes on to the next rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:182 +msgid "" +"Other action keywords perform an activity that does not have any impact on " +"traffic flow. For example, the *count* action simply updates counters that " +"apply to a rule. It has no effect on traffic flow and *ipfw* continues " +"processing with the next rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:187 +msgid "" +"Recall that *ipfw* is a command line program that uses all the words on the " +"command line as parameters. In developing rules, remember that certain " +"constructs such as braces ({,}), brackets ([,]) and even parentheses " +"themselves are all recognized by the shell and must be escaped with a " +"backslash '\\'. indexterm:[rule, syntax constructs] The man:ipfw[8] man " +"page has additional caveats on rule syntax." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:189 +msgid "" +"Below is the smallest possible ruleset that permits the *external1* VM to " +"make a TCP connection to the service running on the *firewall* VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:194 +msgid "" +"Start up the *external1* VM, and the *firewall* VM. Load the *ipfw.ko* " +"kernel module and start the *tserv.sh* service on the *firewall* VM to " +"listen for incoming connections. indexterm:[tserv.sh] Then create the " +"following ruleset on the firewall VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:201 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"# *ipfw add 1000 allow tcp from any to me 5656 in via em0 setup keep-state*\n" +"01000 allow tcp from any to me 5656 in via em0 setup keep-state :default\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:206 +msgid "" +"Test this ruleset immediately by again running *sh tserv.sh* on the " +"*firewall* VM and *sh tcon.sh 5656* script on the *external1* VM as " +"described in the previous chapter. indexterm:[tserv.sh] indexterm:[tcon.sh] " +"The connection should succeed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:212 +msgid "" +"Rule 100 contains the *check-state* option. It checks to see if a " +"connection is already established and a dynamic rule is in place. indexterm:" +"[rule, dynamic] If so, any additional packets matching the dynamic rule " +"would be passed. \"Dynamic rules\" are discussed shortly." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:218 +msgid "" +"Rule 1000 contains the *add* command. This command inserts the requested " +"rule into the *ipfw* ruleset where it can process packets against the " +"specified actions in the rule body. indexterm:[rule, add] The rule itself " +"contains the *allow* keyword, which permits traffic to pass. indexterm:" +"[rule, allow]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:221 +msgid "" +"The rule also uses the *setup* and *keep-state* options to create a dynamic " +"rule for the connection. indexterm:[rule, setup] indexterm:[rule, keep-" +"state]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:223 +msgid "" +"In a stateful firewall like *ipfw*, once a connection from an external host " +"to an internal host is established, the firewall creates a dynamic rule " +"permitting continued traffic along this path until the connection is reset." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:225 +msgid "" +"Note that without the `check-state` keyword, no check for a dynamic rule is " +"performed and without the `keep-state`, no creation of a dynamic rule is " +"performed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:227 +msgid "Consider this ruleset with just a single rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:232 +#, no-wrap +msgid "# *ipfw add 1000 allow tcp from any to me 5656*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:240 +msgid "" +"This rule looks like it should work, *_but it does not_*. A TCP packet " +"entering *ipfw* has no pre-existing dynamic rule. Further, the rule does " +"not create one. And, because there is no corresponding rule for outbound " +"traffic, no TCP 3-way handshake is ever completed. indexterm:[TCP, 3-way " +"handshake] Note that a SYN packet _is_ received by the firewall, but _not_ " +"by the destination service." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:242 +msgid "By adding the rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:246 +#, no-wrap +msgid "# *ipfw add 2000 allow tcp from me to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:249 +msgid "" +"the TCP 3-way handshake *is* allowed to complete and the data is sent from " +"the *external1* VM host to the *tserv.sh* process running on the *firewall* " +"VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:252 +msgid "" +"While this method works, it uses two rules instead of one. In this case, " +"the better solution is to use the *setup*, *keep-state*, and *check-state* " +"options early in the ruleset as shown in the original example in this " +"section." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:253 +#, no-wrap +msgid "Dynamic Rules" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:258 +msgid "" +"So, what exactly are \"dynamic rules\"? indexterm:[rule, dynamic] The " +"scripts being used close the TCP connection each time, so the dynamic rules " +"are short lived, and cannot be easily examined." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:261 +msgid "" +"To see dynamic rules in action, manually set up an `ncat` listener on the " +"*firewall* VM and send data with an `ncat` sender on the *external1* VM: " +"indexterm:[ncat]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:263 +msgid "On the *firewall* VM, start up the listener service manually:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:267 +#, no-wrap +msgid "# *ncat -l 203.0.113.50 5656*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:270 +msgid "" +"Then, on the *external1* VM, use ncat to connect to the service on the " +"firewall and type a message:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:276 +#, no-wrap +msgid "" +"# *ncat 203.0.113.50 5656*\n" +"*hello there*\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:280 +msgid "" +"The message should appear on the console of the *firewall* VM. If it does " +"not, ensure that the original rule from the previous section is active." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:282 +#, no-wrap +msgid "Manually Creating Traffic to Examine Dynamic Rules" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:283 +#, no-wrap +msgid "Manually Creating Traffic to Examine Dynamic Rules. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:283 +#, no-wrap +msgid "ipfw-rules020.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:287 +msgid "" +"The above figure shows the connection is open between the *external1* and " +"*firewall* VMs. indexterm:[rule, manually create dynamic]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:290 +msgid "" +"While the connection is still open, run the following command on the " +"*firewall* VM serial console: indexterm:[rule, viewing dynamic]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:292 +#, no-wrap +msgid "Viewing Dynamic Rules" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:293 +#, no-wrap +msgid "Viewing Dynamic Rules. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:293 +#, no-wrap +msgid "ipfw-rules025.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:296 +msgid "Output is similar to that in the above figure." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:300 +msgid "" +"The `-d` option displays dynamic rules in addition to regular rules. " +"indexterm:[ipfw, -d] indexterm:[ipfw, -D] The `-D` option displays just " +"dynamic rules." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:302 +#, no-wrap +msgid "Notes on Rule Numbering" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:309 +msgid "" +"Each rule is assigned a rule number, even if one is not specified. " +"indexterm:[rule, numbering] The details for rule number handing are found in " +"the man:ipfw[8] man page. Note that rules are assigned numbers in " +"increments specified by the sysctl `net.inet.ip.fw.autoinc_step`. indexterm:" +"[sysctl, net.inet.ip.fw.autoinc_step]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:314 +#, no-wrap +msgid "" +"# *sysctl net.inet.ip.fw.autoinc_step*\n" +"net.inet.ip.fw.autoinc_step: 100\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:317 +msgid "" +"Restart with a simple check-state rule and note that *ipfw* has assigned a " +"number associated with the increment sysctl shown above:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:321 +#, no-wrap +msgid "Flush the *ipfw* ruleset first.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:325 +#, no-wrap +msgid "" +"# *ipfw -q flush*\n" +"# *ipfw add check-state*\n" +"00000 check-state :default\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:329 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00100 check-state :default\n" +"65535 deny ip from any to any00000 check-state :default\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:336 +#, no-wrap +msgid "" +"*ipfw* has automatically assigned the rule number 100.\n" +"While it can be convenient to have *ipfw* add a rule number automatically, *_always_* assign rule numbers yourself.\n" +"This ensures a deliberate decision was made to put a rule in a specific place within the ruleset.\n" +"With large rulesets this is critical.\n" +"A rule automatically assigned by *ipfw* can be placed where it can have an unexpected effect.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:338 +msgid "Consider this ruleset:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:350 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00300 deny ip from any to 200.200.200.200\n" +"00400 deny ip from any to 200.200.200.201\n" +"00500 deny ip from any to 200.200.200.202\n" +"00600 deny ip from any to 200.200.200.203\n" +"00700 deny ip from any to 200.200.200.204\n" +"00800 deny ip from any to 200.200.200.205\n" +"00800 deny ip from any to 200.200.200.206\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:353 +msgid "" +"Having forgotten to add the check-state rule the firewall admin quickly adds " +"it:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:358 +#, no-wrap +msgid "" +"# *ipfw add check-state*\n" +"00000 check-state :default\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:361 +msgid "resulting in the unintentional placement:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:374 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00300 deny ip from any to 200.200.200.200\n" +"00400 deny ip from any to 200.200.200.200\n" +"00500 deny ip from any to 200.200.200.200\n" +"00600 deny ip from any to 200.200.200.200\n" +"00700 deny ip from any to 200.200.200.200\n" +"00800 deny ip from any to 200.200.200.200\n" +"00800 deny ip from any to 200.200.200.200\n" +"#00900 check-state :default#\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:379 +msgid "" +"Also, *ipfw* allows rules with the same rule number to be added to the " +"ruleset, and it will keep track of the rules in the order they were " +"entered. indexterm:[rule, same number] This is easy to forget when manually " +"entering rules from the command line and using command line editing to " +"change something simple like the last byte of an IP address." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:381 +msgid "" +"It is important to remember that all such rules are affected by commands " +"that operate on one or more lines, such as the *delete* command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:408 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"# *ipfw add #1000# allow tcp from 203.0.113.10 to me 5656 setup keep-state*\n" +"01000 allow tcp from 203.0.113.10 to me 5656 keep-state :default\n" +"# *ipfw add #1000# allow tcp from 203.0.113.20 to me 5656 setup keep-state*\n" +"01000 allow tcp from 203.0.113.20 to me 5656 keep-state :default\n" +"# *ipfw add #1000# allow tcp from 203.0.113.30 to me 5656 setup keep-state*\n" +"01000 allow tcp from 203.0.113.30 to me 5656 keep-state :default\n" +"# *ipfw add #1000# allow tcp from 203.0.113.40 to me 5656 setup keep-state*\n" +"01000 allow tcp from 203.0.113.40 to me 5656 keep-state :default\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"01000 allow tcp from 203.0.113.20 to me 5656 setup keep-state :default\n" +"01000 allow tcp from 203.0.113.30 to me 5656 setup keep-state :default\n" +"01000 allow tcp from 203.0.113.40 to me 5656 setup keep-state :default\n" +"65535 deny ip from any to any\n" +"#\n" +"# *ipfw delete 1000*\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:412 +msgid "" +"The *delete* command can also process both ranges and lists of rules. " +"indexterm:[rule, delete]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:414 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1482 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1703 +msgid "Consider the following ruleset:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:442 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"01100 allow tcp from 203.0.113.11 to me 5656 setup keep-state :default\n" +"01200 allow tcp from 203.0.113.12 to me 5656 setup keep-state :default\n" +"01300 allow tcp from 203.0.113.13 to me 5656 setup keep-state :default\n" +"02000 allow tcp from 203.0.113.20 to me 5656 setup keep-state :default\n" +"02100 allow tcp from 203.0.113.21 to me 5656 setup keep-state :default\n" +"02200 allow tcp from 203.0.113.22 to me 5656 setup keep-state :default\n" +"02300 allow tcp from 203.0.113.23 to me 5656 setup keep-state :default\n" +"03000 allow tcp from 203.0.113.30 to me 5656 setup keep-state :default\n" +"03100 allow tcp from 203.0.113.31 to me 5656 setup keep-state :default\n" +"03200 allow tcp from 203.0.113.32 to me 5656 setup keep-state :default\n" +"03300 allow tcp from 203.0.113.33 to me 5656 setup keep-state :default\n" +"04000 allow tcp from 203.0.113.40 to me 5656 setup keep-state :default\n" +"04100 allow tcp from 203.0.113.41 to me 5656 setup keep-state :default\n" +"04200 allow tcp from 203.0.113.42 to me 5656 setup keep-state :default\n" +"04300 allow tcp from 203.0.113.43 to me 5656 setup keep-state :default\n" +"04400 allow tcp from 203.0.113.44 to me 5656 setup keep-state :default\n" +"04500 allow tcp from 203.0.113.45 to me 5656 setup keep-state :default\n" +"04600 allow tcp from 203.0.113.46 to me 5656 setup keep-state :default\n" +"04700 allow tcp from 203.0.113.47 to me 5656 setup keep-state :default\n" +"04800 allow tcp from 203.0.113.48 to me 5656 setup keep-state :default\n" +"04900 allow tcp from 203.0.113.49 to me 5656 setup keep-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:446 +msgid "" +"A *range* is specified by two number separated by a dash: for example " +"5000-7350; whereas a *list* is a space-separated collection of numbers on " +"the command line. indexterm:[rule, number range] indexterm:[rule, number " +"list]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:448 +msgid "" +"The following command deletes rules from 1000 to 2999 and certain rules " +"between 4000 and 5000:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:465 +#, no-wrap +msgid "" +"# *ipfw delete 1000-2999 4100 4300 4500 4700 4900*\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"03000 allow tcp from 203.0.113.30 to me 5656 keep-state :default\n" +"03100 allow tcp from 203.0.113.31 to me 5656 keep-state :default\n" +"03200 allow tcp from 203.0.113.32 to me 5656 keep-state :default\n" +"03300 allow tcp from 203.0.113.33 to me 5656 keep-state :default\n" +"04000 allow tcp from 203.0.113.40 to me 5656 keep-state :default\n" +"04200 allow tcp from 203.0.113.42 to me 5656 keep-state :default\n" +"04400 allow tcp from 203.0.113.44 to me 5656 keep-state :default\n" +"04600 allow tcp from 203.0.113.46 to me 5656 keep-state :default\n" +"04800 allow tcp from 203.0.113.48 to me 5656 keep-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:469 +msgid "" +"Note that the *delete* command _will_ operate on comma separated values, but " +"the *delete* command will only remove the *_first_* value in a comma " +"separated list, not the entire list. The command does not throw an error, " +"but it does not delete all the lines requested." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:487 +#, no-wrap +msgid "" +"# *ipfw delete 3100,3200,3300*\n" +"# *echo $?*\n" +"0 #<--- No error found with the previous command.#\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"03000 allow tcp from 203.0.113.30 to me 5656 keep-state :default\n" +"#03200 allow tcp from 203.0.113.32 to me 5656 keep-state :default#\n" +"#03300 allow tcp from 203.0.113.33 to me 5656 keep-state :default#\n" +"04000 allow tcp from 203.0.113.40 to me 5656 keep-state :default\n" +"04200 allow tcp from 203.0.113.42 to me 5656 keep-state :default\n" +"04400 allow tcp from 203.0.113.44 to me 5656 keep-state :default\n" +"04600 allow tcp from 203.0.113.46 to me 5656 keep-state :default\n" +"04800 allow tcp from 203.0.113.48 to me 5656 keep-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:491 +msgid "" +"The *show* command is similar to the *list* command but it also includes a " +"packet count and byte count for each rule. indexterm:[rule, show]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:496 +msgid "" +"Stop any existing scripts on the *firewall* VM and run *sh userv3.sh*. " +"indexterm:[userv3.sh] Then create the following ruleset on the *firewall* " +"VM: indexterm:[rule, flush] indexterm:[rule, list]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:519 +#, no-wrap +msgid "" +"# *ipfw -q flush*\n" +"#\n" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"# *ipfw add 1000 allow udp from 203.0.113.10 to me 5656*\n" +"01000 allow udp from 203.0.113.10 to me 5656\n" +"# *ipfw add 2000 allow udp from 203.0.113.10 to me 5657*\n" +"02000 allow udp from 203.0.113.10 to me 5657\n" +"# *ipfw add 3000 allow udp from 203.0.113.10 to me 5658*\n" +"03000 allow udp from 203.0.113.10 to me 5658\n" +"# *ipfw add 4000 allow udp from 203.0.113.10 to me 5659*\n" +"04000 allow udp from 203.0.113.10 to me 5659\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 allow udp from 203.0.113.10 to me 5656\n" +"02000 allow udp from 203.0.113.10 to me 5657\n" +"03000 allow udp from 203.0.113.10 to me 5658\n" +"04000 allow udp from 203.0.113.10 to me 5659\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:523 +msgid "" +"Then, on the *external1* VM, run *sh uconr.sh 5656 1* script to send packets " +"to ports 5656, 5657, and 5658, randomly: indexterm:[uconr.sh]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:551 +#, no-wrap +msgid "" +"# *sh uconr.sh 5656 1*\n" +"PORT1 = [5656]\n" +"SLEEPVAL = [1]\n" +"UDP packet from [203.0.113.10],[5656],[1]\n" +"UDP packet from [203.0.113.10],[5656],[2]\n" +"UDP packet from [203.0.113.10],[5658],[3]\n" +"UDP packet from [203.0.113.10],[5657],[4]\n" +"UDP packet from [203.0.113.10],[5659],[5]\n" +"UDP packet from [203.0.113.10],[5659],[6]\n" +"UDP packet from [203.0.113.10],[5659],[7]\n" +"UDP packet from [203.0.113.10],[5656],[8]\n" +"UDP packet from [203.0.113.10],[5658],[9]\n" +"UDP packet from [203.0.113.10],[5659],[10]\n" +"UDP packet from [203.0.113.10],[5658],[11]\n" +"UDP packet from [203.0.113.10],[5656],[12]\n" +"UDP packet from [203.0.113.10],[5656],[13]\n" +"UDP packet from [203.0.113.10],[5656],[14]\n" +"UDP packet from [203.0.113.10],[5659],[15]\n" +"UDP packet from [203.0.113.10],[5656],[16]\n" +"UDP packet from [203.0.113.10],[5657],[17]\n" +"UDP packet from [203.0.113.10],[5659],[18]\n" +"UDP packet from [203.0.113.10],[5659],[19]\n" +"UDP packet from [203.0.113.10],[5657],[20]\n" +"UDP packet from [203.0.113.10],[5659],[21]\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:555 +msgid "Running the *ipfw show* command outputs: indexterm:[rule, show]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:565 +#, no-wrap +msgid "" +"# *ipfw show*\n" +"00100 #0 0# check-state :default\n" +"01000 #7 494# allow udp from 203.0.113.10 to me 5656\n" +"02000 #3 212# allow udp from 203.0.113.10 to me 5657\n" +"03000 #3 211# allow udp from 203.0.113.10 to me 5658\n" +"04000 #8 565# allow udp from 203.0.113.10 to me 5659\n" +"65535 #11 897# deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:568 +msgid "" +"The output shows the number of packets and the number of bytes processed by " +"each rule, including the default rule which may have processed many more " +"packets." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:571 +msgid "" +"Note that the `-D` command parameter will show counts for dynamic rules " +"similar to the above. indexterm:[ipfw, -D]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:578 +#, no-wrap +msgid "" +"# *ipfw -D show*\n" +"Dynamic rules (2 288):\n" +"04000 #2 100# (1s) STATE tcp 203.0.113.10 31662 <-> 203.0.113.50 5659 :default\n" +"03000 #8 482# (1s) STATE tcp 203.0.113.10 45732 <-> 203.0.113.50 5658 :default\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:583 +msgid "" +"This is a useful tool for debugging. Paired with the *zero* command which " +"can clear counters with precise rule selection, it can show what rules are " +"still processing a rule match. indexterm:[rule, zero]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:587 +msgid "" +"The *zero* command takes a space separated list of rules (similar to the " +"*delete* command) to clear counters. indexterm:[clear counters] However, " +"unlike the *delete* command, ranges (e.g 2000-3000) are not allowed." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:599 +#, no-wrap +msgid "" +"# *ipfw zero 2000 3000*\n" +"#\n" +"# *ipfw show*\n" +"00100 0 0 check-state :default\n" +"01000 7 494 allow udp from 203.0.113.10 to me 5656\n" +"02000 #0 0# allow udp from 203.0.113.10 to me 5657\n" +"03000 #0 0# allow udp from 203.0.113.10 to me 5658\n" +"04000 8 565 allow udp from 203.0.113.10 to me 5659\n" +"65535 11 897 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:602 +msgid "" +"Clearing all rule match counters can be done with *ipfw zero* with no " +"parameters." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:605 +msgid "" +"Clearing the default rule match counter can be done with *ipfw zero 65535*. " +"indexterm:[rule, zero default rule]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:609 +msgid "" +"Counters are also a feature of rules that specify the *log* keyword. " +"indexterm:[log] indexterm:[counters] An example of this is shown below when " +"discussing the *log* and *logamount* keywords." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:610 +#, no-wrap +msgid "Keywords" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:612 +#, no-wrap +msgid "Protocols" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:617 +msgid "" +"Protocols are those defined by link:https://www.iana.org/[IANA - the " +"Internet Assigned Numbers Authority (https://www.iana.org)] and are included " +"in Unix systems in [.filename]#/etc/protocols#. indexterm:[IANA] This file " +"identifies what numbers are assigned to common (and some very obscure) " +"protocols - *ip* (0), *tcp* (6), *udp* (17), *icmp* (1), and many others. " +"indexterm:[protocol, /etc/protocols]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:620 +msgid "" +"Source and destination protocols can be the conventional IP or IPv6 " +"addresses. However, the man:ipfw[8] manual page has this more detailed " +"explanation:" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:624 +msgid "" +"\"The first part (proto from src to dst) is for backward compatibility with " +"earlier versions of FreeBSD. In modern FreeBSD any match pattern (including " +"MAC headers, IP protocols, addresses and ports) can be specified in the " +"options section.\"" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:628 +msgid "" +"The *ipfw* keywords for common protocols include: indexterm:[protocol, " +"keywords]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:630 +#, no-wrap +msgid "*ip4* | *ipv4* Matches IPv4 packets.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:632 +#, no-wrap +msgid "*ip6* | *ipv6* Matches IPv6 packets.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:634 +#, no-wrap +msgid "*ip* | *all* Matches any IP packet.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:642 +msgid "" +"The logical operator \"*or*\" can be use to combine multiple protocols where " +"any one of them applies. indexterm:[operator, or] The \"*{*\" and \"*}*\" " +"braces can be used to group \"*or*\" conditions (known as \"*or-blocks*\"). " +"indexterm:[or-block] Only one level of braces can be used. Braces must be " +"escaped with a backslash '\\' to prevent them from being interpreted " +"directly by the command line shell:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:647 +#, no-wrap +msgid "" +"# *ipfw add 1100 deny \\{ tcp or udp or eigrp or chaos \\} from 1.2.3.4 to 5.6.7.8*\n" +"01100 deny { tcp or udp or eigrp or chaos } from 1.2.3.4 to 5.6.7.8\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:651 +msgid "Consider this ruleset in a shell script: indexterm:[protocol, list]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:652 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:660 +#, no-wrap +msgid "---\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:655 +msgid "#!/bin/sh" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:657 +msgid "" +"ipfw add 5000 deny \\{ icmp or ip or igmp or ggp or ipencap or st2 or tcp or " +"cbt or egp or igp or bbn-rcc or nvp or pup or argus or emcon or xnet or " +"chaos or udp or mux or dcn or hmp or prm or xns-idp or trunk-1 or trunk-2 or " +"leaf-1 or leaf-2 or rdp or irtp or iso-tp4 or netblt or mfe-nsp or merit-inp " +"or dccp or 3pc or idpr or xtp or ddp or idpr-cmtp or tp++ or il or ipv6 or " +"sdrp or ipv6-route or ipv6-frag or idrp or rsvp or gre or dsr or bna or esp " +"or ah or i-nlsp or swipe or narp or mobile or tlsp or skip or ipv6-icmp or " +"ipv6-nonxt or ipv6-opts or cftp or sat-expak or kryptolan or rvd or ippc or " +"sat-mon or visa or ipcv or cpnx or cphb or wsn or pvp or br-sat-mon or sun-" +"nd or wb-mon or wb-expak or iso-ip or vmtp or secure-vmtp or vines or ttp or " +"nsfnet-igp or dgp or tcf or eigrp or ospf or sprite-rpc or larp or mtp or " +"ax.25 or ipip or micp or scc-sp or etherip or encap or gmtp or ifmp or pnni " +"or pim or aris or scps or qnx or a/n or ipcomp or snp or compaq-peer or ipx-" +"in-ip or carp or pgm or l2tp or ddx or iatp or stp or srp or uti or smp or " +"sm or ptp or isis or fire or crtp or crudp or sscopmce or iplt or sps or " +"pipe or sctp or fc or rsvp-e2e-ignore or mobility-header or udplite or mpls-" +"in-ip or manet or hip or shim6 or wesp or rohc or pfsync or divert \\} from " +"any to me" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:659 +msgid "exit" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:663 +msgid "" +"Note that the above file is shown as one very long line and does not use the " +"Unix line continuation convention." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:669 +msgid "" +"This command will deny all traffic using all protocols defined in [." +"filename]#/etc/protocols#. The above command will complete successfully. " +"However, due to a bug in the \"*or-block*\" parser, the rule cannot have the " +"\"*ip*\" protocol first. indexterm:[or-block] Swapping the first two " +"protocols - *icmp* and *ip* - the command throws an error." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:671 +msgid "For example," +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:675 +#, no-wrap +msgid "# *ipfw add 1000 deny \\{ igmp or ip or eigrp \\} from any to me*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:678 +msgid "works Ok but" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:683 +#, no-wrap +msgid "" +"# *ipfw add 1000 deny \\{ ip or igmp or eigrp \\} from any to me*\n" +"ipfw: invalid OR block\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:686 +msgid "fails." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:693 +msgid "" +"The use of the logical \"*and*\" operator in a protocol block is an error. " +"indexterm:[keyword, and] A packet can be in only one protocol at a time. " +"However, the use of the logical \"*not*\" operator *is* permitted in front " +"of a protocol identifier: indexterm:[keyword, not]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:697 +#, no-wrap +msgid "# *ipfw add 1000 deny \\{ icmp or not igmp \\} from any to me*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:700 +msgid "" +"Careful consideration of all logical conditions is essential to correct " +"operation of a ruleset." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:704 +msgid "" +"In later versions of FreeBSD, the use of the protocol \"*or-block*\" is " +"noted as deprecated in man:ipfw[8] but the operation may still complete " +"successfully until the feature is removed completely." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:706 +#, no-wrap +msgid "Addresses" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:710 +msgid "" +"Source and destination addresses can be any of the following: indexterm:" +"[rule, addresses] indexterm:[keyword, any] indexterm:[keyword, me] indexterm:" +"[me6]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:713 +#, no-wrap +msgid "*IPv4* or *IPv6* addresses\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:714 +#, no-wrap +msgid "*any* - matches any IP address.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:715 +#, no-wrap +msgid "*me* - matches any IP address configured on an interface in the system.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:720 +msgid "" +"Note that the interface does not have to have an IP or IPv6 address, *_nor " +"does it have to be up or even exist_* at the time the rule is entered. " +"Thus, be aware that a rule with keyword *me* may affect traffic on " +"interfaces that are configured at a later time. Consider the following " +"system interface list:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:737 +#, no-wrap +msgid "" +"# *ifconfig -a*\n" +"em0: flags=8863 metric 0 mtu 1500\n" +" options=481209b\n" +" ether 02:49:50:46:57:41\n" +" inet 203.0.113.50 netmask 0xffffff00 broadcast 203.0.113.255\n" +" media: Ethernet autoselect (1000baseT )\n" +" status: active\n" +" nd6 options=29\n" +"lo0: flags=8049 metric 0 mtu 16384\n" +" options=680003\n" +" inet6 ::1 prefixlen 128\n" +" inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3\n" +" inet 127.0.0.1 netmask 0xff000000\n" +" groups: lo\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:740 +msgid "" +"The following attempt to add a rule with a non-existent interface succeeds " +"even though there is no `wlan0` interface defined:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:745 +#, no-wrap +msgid "" +"# *ipfw add 1000 deny tcp from 1.2.4.4 to me via wlan0*\n" +"01000 deny tcp from 1.2.4.4 to me via wlan0\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:749 +#, no-wrap +msgid "*me6* - matches any IPv6 address similarly to the above me keyword.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:750 +#, no-wrap +msgid "*table(name[,value])* - matches any IPv4 or IPv6 address for an entry in the named table.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:753 +msgid "indexterm:[table]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:756 +msgid "" +"Tables are discussed below in crossref:ipfw-rules[ipfw-rules-lookup-tables-" +"intro, Lookup Tables]. indexterm:[lookup table]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:759 +msgid "" +"IPv4 and IPv6 addresses follow the usual conventions regarding address and " +"mask or prefix length. Addresses can also be grouped into a list, similar " +"to the capability discussed for protocols above." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:763 +#, no-wrap +msgid "# *ipfw add 2000 allow tcp from \\{ 2.3.4.5/32, 3.4.5.0/24, 10.0.0.0/8 \\} to me*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:765 +#, no-wrap +msgid "# *ipfw add 2000 allow tcp from \\{ 2607:fcc0:0:35::dd/64, 2608:abcd:0:2300::9eac/64 \\} to me*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:770 +msgid "" +"However, IPv4 and IPv6 addresses *_cannot_* be mixed in the same list. Use " +"two different rules instead." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:773 +msgid "" +"For sparse collections of addresses, consider the alternate form allowed by " +"indexterm:[address, sparse addressing]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:776 +#, no-wrap +msgid "*addr-set: addr[/masklen]{list}*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:779 +msgid "such as:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:783 +#, no-wrap +msgid "# *ipfw add 1000 allow tcp from 1.2.3.0/24\\{128,9,35-45,7\\} to me*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:789 +msgid "" +"In this form, lists and increasing ranges are allowed. indexterm:[address, " +"range] indexterm:[address, list] *ipfw* will consolidate overlapping ranges, " +"and will reorder the list in the display to show increasing addresses from " +"left to right. Note that spaces are only allowed after commas between list " +"elements, nowhere else." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:791 +msgid "This example does not work due to incorrect placement of spaces:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:796 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow tcp from 1.2.4.0/24\\{## ##128,9,25-45,7-25## ##\\} to me*\n" +"ipfw: missing ``to''\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:799 +msgid "" +"This example works by correcting where spaces occur on the command line." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:804 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow tcp from 1.2.4.0/24\\{128,9,25-45,7-25\\} to me*\n" +"01000 allow tcp from 1.2.4.0/24{7-45,128} to me\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:807 +msgid "As noted, *ipfw* will simplify, reorder, and display the list:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:813 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"01000 allow tcp from 1.2.4.0/24{7-45,128} to me\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:818 +msgid "" +"Note that ranges *_must_* be defined as increasing. indexterm:[address, " +"range increasing] Also, as noted in man:ipfw[8], there is *no* support for " +"sets of IPv6 addresses." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:819 +#, no-wrap +msgid "Ports" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:825 +msgid "" +"Ports may be specified by number or by service name. indexterm:[keyword, " +"ports] Service names, also under the provenance of link:https://www.iana.org/" +"[IANA], are found in [.filename]#/etc/services# on Unix systems. indexterm:" +"[ports, /etc/services]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:829 +msgid "" +"Ports can be specified as individual items, lists, or ranges. Typically " +"ports are used to determine a destination service and so apply to the " +"destination address (although specifying source ports is also permitted): " +"indexterm:[ports, examples]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:834 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow tcp from 1.2.3.4 to me daytime*\n" +"01000 allow tcp from 1.2.3.4 to me 13\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:837 +#, no-wrap +msgid "" +"# *ipfw add 2000 allow tcp from 2.3.4.5 to me ssh, telnet, smtp*\n" +"02000 allow tcp from 2.3.4.5 to me 22,23,25\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:840 +#, no-wrap +msgid "" +"# *ipfw add 3000 allow tcp from 3.4.5.6 to me auditd-domain*\n" +"03000 allow tcp from 3.4.5.6 to me 48-53\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:844 +#, no-wrap +msgid "" +"# This example uses source and destination ports.\n" +"# *ipfw add 4000 allow tcp from 7.8.9.10 3030 to me ssh*\n" +"04000 allow tcp from 7.8.9.10 3030 to me 22\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:848 +#, no-wrap +msgid "" +"*General Notes on Port Ranges*\n" +"indexterm:[ports, ranges]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:852 +msgid "" +"A range such as that shown above (`auditd-domain`) may accidentally include " +"ports not wanted. In this case, ports `tacacs (49)`, `re-mail-ck (50)`, `la-" +"maint (51)`, and `xns-time (52)` would be included. Therefore, always check " +"actual port numbers when using named ranges for ports." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:855 +msgid "" +"Some service names include the dash character '-' as part of the name, as in " +"the point above. In these cases a _double backslash_, is required, one for " +"the shell and one for *ipfw*:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:860 +#, no-wrap +msgid "" +"# *ipfw add 4000 allow tcp from 4.5.6.7 to me ftp, #ftp\\\\-data#*\n" +"04000 allow tcp from 4.5.6.7 to me 21,20\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:864 +msgid "" +"Some applications require a range of source and destination ports in both " +"directions. This is easy to accomplish with ranges and a `keep-state` rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:873 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state*\n" +"01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default\n" +"#\n" +"# *ipfw list*\n" +"01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:877 +msgid "" +"The syntactic sugar provided by the match keywords `dst-port` and `src-port` " +"are both part of the match section of the rule: indexterm:[dst-port] " +"indexterm:[src-port]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:882 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow tcp from 203.0.113.10 to me src-port 3030 dst-port 1010*\n" +"01000 allow tcp from 203.0.113.10 3030 to me 1010\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:886 +msgid "" +"To test common ports in both directions, manually connect using `ncat`, " +"setting up the source and destination ports as needed: indexterm:[ncat]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:893 +#, no-wrap +msgid "" +"#\n" +"# *ipfw list*\n" +"01000 allow tcp from 203.0.113.10 5200-5205 to me 5656-5658 keep-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:896 +msgid "" +"Note: the transmission and reception lines have been aligned on each side." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:898 +#, no-wrap +msgid "Manually Testing Common Ports in Both Directions" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:899 +#, no-wrap +msgid "Manually Testing Common Ports in Both Directions. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:899 +#, no-wrap +msgid "ipfw-rules030.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:902 +msgid "" +"Note that no connection was achieved when the destination port was out of " +"bounds (5659) and when the source port was out of bounds (5206)." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:903 +#, no-wrap +msgid "Prob" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:909 +msgid "" +"The *prob* keyword is used to assign a chance, that is a probability (a " +"floating point value between 0 and 1), that an incoming packet will be " +"matched. indexterm:[keyword, prob] indexterm:[prob] If the chance is " +"successful, the corresponding rule performs the required action. If the " +"chance is not successful, the rule is not matched and rule processing " +"continues to the next rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:914 +msgid "" +"To test this keyword, use \"*sh ucont.sh 5656 1*\" script on the *external1* " +"VM's side to repeatedly send a UDP packet to the *firewall* VM, who is " +"listening on UDP port 5656. indexterm:[ucont.sh] Using the *prob* keyword, " +"set a probability of .5 (a 50% chance) that the packet will be matched. The " +"action is to let the packet pass to the service, which just prints the " +"contents of the packet." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:917 +msgid "" +"As shown below, there were 24 out of 50 packets received, very close to 50% " +"for such a small sample: indexterm:[userv.sh]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:957 +#, no-wrap +msgid "" +"# *ipfw -q flush*\n" +"#\n" +"# *ipfw add 3000 prob 0.5 allow udp from any to me 5656*\n" +"03000 prob 0.500000 allow udp from any to me 5656\n" +"#\n" +"# *ipfw list*\n" +"03000 prob 0.500000 allow udp from any to me 5656\n" +"65535 deny ip from any to any\n" +"#\n" +"# *sh userv.sh 5656*\n" +"PORT1 = [5656]\n" +"Starting UDP listener on [203.0.113.50],[5656]\n" +"UDP packet from [203.0.113.10],[5656],[5]\n" +"UDP packet from [203.0.113.10],[5656],[6]\n" +"UDP packet from [203.0.113.10],[5656],[7]\n" +"UDP packet from [203.0.113.10],[5656],[10]\n" +"UDP packet from [203.0.113.10],[5656],[11]\n" +"UDP packet from [203.0.113.10],[5656],[13]\n" +"UDP packet from [203.0.113.10],[5656],[14]\n" +"UDP packet from [203.0.113.10],[5656],[16]\n" +"UDP packet from [203.0.113.10],[5656],[19]\n" +"UDP packet from [203.0.113.10],[5656],[20]\n" +"UDP packet from [203.0.113.10],[5656],[22]\n" +"UDP packet from [203.0.113.10],[5656],[28]\n" +"UDP packet from [203.0.113.10],[5656],[29]\n" +"UDP packet from [203.0.113.10],[5656],[32]\n" +"UDP packet from [203.0.113.10],[5656],[33]\n" +"UDP packet from [203.0.113.10],[5656],[34]\n" +"UDP packet from [203.0.113.10],[5656],[35]\n" +"UDP packet from [203.0.113.10],[5656],[37]\n" +"UDP packet from [203.0.113.10],[5656],[38]\n" +"UDP packet from [203.0.113.10],[5656],[39]\n" +"UDP packet from [203.0.113.10],[5656],[41]\n" +"UDP packet from [203.0.113.10],[5656],[43]\n" +"UDP packet from [203.0.113.10],[5656],[45]\n" +"UDP packet from [203.0.113.10],[5656],[49]\n" +"^C#\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:959 +#, no-wrap +msgid "Sets" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:968 +msgid "" +"Firewall rules can be grouped into different *sets* which can be switched " +"atomically. indexterm:[keyword, set] indexterm:[sets] Why use this feature? " +"Consider a datacenter with two sets of identical servers on separate " +"networks. One set must be taken down for maintenance. But first, traffic " +"must be transferred to the other set of servers. Using *sets* is a " +"practical solution for this problem." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:971 +#, no-wrap +msgid "" +"*Sets* are useful, but they do come with some caveats which are described throughout this section.\n" +"indexterm:[sets, caveats]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:976 +msgid "" +"The default *set* is *set* 0. To begin, create rules in *set* 0 and *set* 1 " +"with slight differences between the two. Note that this example also shows " +"the use of the *ipfw* comment feature - allowing comments on a per-rule " +"basis. indexterm:[rule, comments]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:995 +#, no-wrap +msgid "" +"# *ipfw -q flush*\n" +"#\n" +"# *ipfw add 1000 set 0 check-state*\n" +"01000 check-state :default\n" +"#\n" +"# *ipfw add 1100 set 0 allow tcp from any to me 5656 setup keep-state // 5656 only*\n" +"01100 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"#\n" +"# *ipfw add 2000 set 1 check-state*\n" +"02000 check-state :default\n" +"#\n" +"# *ipfw add 2100 set 1 allow tcp from any to me 5657 setup keep-state // 5657 only*\n" +"02100 allow tcp from any to me 5657 setup keep-state :default // 5657 only\n" +"#\n" +"# *ipfw set show*\n" +"enable 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:998 +msgid "" +"The above *ipfw set show* command lists all enabled sets, here showing both " +"0 and 1 as enabled." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1003 +msgid "" +"From the *external1* VM, commence communications using the *tcon.sh* script " +"as shown below. indexterm:[tcon.sh] The first two communications ([1], [2]) " +"are to port 5656, the next two communications are to port 5657 ([3],[4]). " +"The firewall host shows all four communications received:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1005 +#, no-wrap +msgid "Use of Sets" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1006 +#, no-wrap +msgid "Use of Sets. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1006 +#, no-wrap +msgid "ipfw-rules035.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1012 +msgid "" +"Right before communication 5, the firewall host admin disabled *set* 0, (*# " +"ipfw set disable 0*) effectively blocking access to port 5656. indexterm:" +"[set, disable] indexterm:[set, enable] Disabling *set* 0, effectively " +"removes the rules for port 5656 and so the communications [5] and [6] fail. " +"The *external1* VM goes back to port 5657 for communications [7] and [8], " +"which are successful." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1016 +msgid "" +"Notice that when listing the firewall ruleset with just *ipfw list*, only " +"the *sets* that are enabled actually show up. To make sure which *sets* are " +"enabled / disabled, use the `-S` flag on the *ipfw* command as shown below. " +"indexterm:[ipfw, -S]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1043 +#, no-wrap +msgid "" +"# *ipfw set enable 0*\n" +"#\n" +"# *ipfw set show*\n" +"enable 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30\n" +"#\n" +"# *ipfw -S list*\n" +"01000 set 0 check-state :default\n" +"01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"02000 set 1 check-state :default\n" +"02100 set 1 allow tcp from any to me 5657 setup keep-state :default // 5657 only\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw set disable 0*\n" +"#\n" +"# *ipfw set show*\n" +"disable 0 enable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30\n" +"#\n" +"# *ipfw -S list*\n" +"# DISABLED 01000 set 0 check-state :default\n" +"# DISABLED 01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"02000 set 1 check-state :default\n" +"02100 set 1 allow tcp from any to me 5657 setup keep-state :default // 5657 only\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1047 +msgid "" +"To atomically change from one set to the other use the *ipfw set swap* " +"command: indexterm:[set, swap]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1051 +#, no-wrap +msgid "# *ipfw set swap 0 1*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1054 +msgid "" +"What actually happens is that *_the rules in the sets get swapped_*; that " +"is, all the rules in *set 0* get put in *set 1* and all the rules in *set 1* " +"get put in *set 0*." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1073 +#, no-wrap +msgid "" +"#\n" +"# *ipfw -S list*\n" +"# DISABLED 01000 set 0 check-state :default\n" +"# DISABLED 01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"02000 set 1 check-state :default\n" +"02100 set 1 allow tcp from any to me 5657 setup keep-state :default // 5657 only\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw set swap 0 1*\n" +"#\n" +"# *ipfw -S list*\n" +"01000 set 1 check-state :default\n" +"01100 set 1 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"# DISABLED 02000 set 0 check-state :default\n" +"# DISABLED 02100 set 0 allow tcp from any to me 5657 setup keep-state :default // 5657 only\n" +"65535 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1078 +msgid "" +"Note carefully that when swapping *sets* where one of the *sets* is " +"disabled, *the set number is still disabled after the swap*, even though the " +"rules are now different. indexterm:[set, swap disabled] This can lead to " +"unexpected consequences such as the following:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1105 +#, no-wrap +msgid "" +"# *ipfw -S list*\n" +"01000 set 0 check-state :default\n" +"01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"02000 set 1 check-state :default\n" +"02100 set 1 allow tcp from any to me 5660 setup keep-state :default // 5660 only\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw set disable 0*\n" +"#\n" +"# *ipfw -S list*\n" +"# DISABLED 01000 set 0 check-state :default\n" +"# DISABLED 01100 set 0 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"02000 set 1 check-state :default\n" +"02100 set 1 allow tcp from any to me 5660 setup keep-state :default // 5660 only\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw set swap 0 1*\n" +"#\n" +"# *ipfw -S list*\n" +"01000 set 1 check-state :default\n" +"01100 set 1 allow tcp from any to me 5656 setup keep-state :default // 5656 only\n" +"# DISABLED 02000 set 0 check-state :default\n" +"# DISABLED 02100 set 0 allow tcp from any to me 5660 setup keep-state :default // 5660 only\n" +"65535 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1109 +msgid "" +"Here *set 0* is disabled, and then swapped. After the swap, *set 0 is still " +"disabled*, though the rules have changed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1114 +msgid "" +"Note that all sets are initially enabled. When a set is disabled, say *set " +"3*, all other sets are still active, even if no rule references them. Sets " +"are analogous to the pieces on the back row of a chess board. If a knight " +"or a bishop is removed, that one piece is not able to play, but all the " +"others are able to play." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1118 +#, no-wrap +msgid "" +"*set 31* cannot be deleted or changed.\n" +"indexterm:[set, set 31]\n" +"It can however partially participate in a swap.\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1122 +#, no-wrap +msgid "# *ipfw set swap 1 31*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1126 +msgid "" +"This swap will complete successfully (return code 0), but the effect is not " +"the same as the swaps above. The default rule in *set 31* is not swapped, " +"but the set number for the other rules (rules in *set 1*) are set to 31:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1142 +#, no-wrap +msgid "" +"# *ipfw -S list*\n" +"01000 set 1 check-state :default\n" +"01100 set 1 allow tcp from 1.2.3.4 to me 8080\n" +"01200 set 1 allow tcp from 1.2.3.4 to me 8081\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw set swap 1 31*\n" +"#\n" +"# *ipfw -S list*\n" +"01000 set 31 check-state :default\n" +"01100 set 31 allow tcp from 1.2.3.4 to me 8080\n" +"01200 set 31 allow tcp from 1.2.3.4 to me 8081\n" +"65535 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1147 +msgid "" +"As noted in the man:ipfw[8] manual page, rules in *set 31* cannot be " +"flushed. indexterm:[set, set 31] There are now 4 rules in *set 31*:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1158 +#, no-wrap +msgid "" +"# *ipfw -f flush*\n" +"Flushed all rules.\n" +"#\n" +"# *ipfw -S list*\n" +"01000 set 31 check-state :default\n" +"01100 set 31 allow tcp from 1.2.3.4 to me 8080\n" +"01200 set 31 allow tcp from 1.2.3.4 to me 8081\n" +"65535 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1161 +msgid "" +"While *ipfw flush* did not clean out rules in *set* 31, the command *ipfw " +"delete set 31* will clean out all but the default rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1168 +#, no-wrap +msgid "" +"# *ipfw delete set 31*\n" +"#\n" +"# *ipfw -S list*\n" +"65535 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1174 +msgid "" +"Further, note that any *set* that is disabled, remains disabled after a " +"flush. Thus, when disabling a *set* and then flushing the entire ruleset, " +"any rules added back into that *set* number will still be disabled. This " +"includes *set 0*, the default set. indexterm:[set, set 0 default]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1176 +msgid "Consider the following:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1214 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"01000 check-state :default\n" +"01100 allow tcp from any to me 1111\n" +"02000 allow tcp from any to me 2222\n" +"03000 allow tcp from any to me 3333\n" +"65535 deny ip from any to any\n" +"#\n" +"# *ipfw set disable 0*\n" +"#\n" +"# *ipfw -S list*\n" +"# DISABLED 01000 set 0 check-state :default\n" +"# DISABLED 01100 set 0 allow tcp from any to me 1111\n" +"# DISABLED 02000 set 0 allow tcp from any to me 2222\n" +"# DISABLED 03000 set 0 allow tcp from any to me 3333\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw -f flush*\n" +"Flushed all rules.\n" +"#\n" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"# *ipfw add 200 allow tcp from any to me 5555*\n" +"00200 allow tcp from any to me 5555\n" +"# *ipfw add 300 allow tcp from any to me 6666*\n" +"00300 allow tcp from any to me 6666\n" +"# *ipfw add 400 allow tcp from any to me 7777*\n" +"00400 allow tcp from any to me 7777\n" +"#\n" +"# *ipfw -S list*\n" +"# #DISABLED 00100 set 0# check-state :default\n" +"# #DISABLED 00200 set 0# allow tcp from any to me 5555\n" +"# #DISABLED 00300 set 0# allow tcp from any to me 6666\n" +"# #DISABLED 00400 set 0# allow tcp from any to me 7777\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1218 +msgid "" +"Because *set 0* was disabled before the flush, the flush has no effect on " +"the enable/disable state of that *set*. indexterm:[keyword, flush]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1220 +msgid "Note that it is even possible to disable sets that do not yet exist:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1237 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"ipfw2 (+ipv6) initialized, divert loadable, nat loadable, default to deny, logging disabled\n" +"#\n" +"# *ipfw -S list*\n" +"65535 set 31 deny ip from any to any\n" +"#\n" +"# *ipfw set show*\n" +"enable 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30\n" +"#\n" +"# *ipfw set disable 4 5 6 7 8 9*\n" +"#\n" +"# *ipfw set show*\n" +"disable 4 5 6 7 8 9 enable 0 1 2 3 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1240 +msgid "" +"Using *sets* can be very helpful, as long as their properties and " +"limitations are clearly understood." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1241 +#, no-wrap +msgid "Tags" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1245 +#, no-wrap +msgid "" +"*Tags* allow for marking incoming packets in such a way that later rules can be applied based on the *tag*.\n" +"indexterm:[rule, tag] indexterm:[tag]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1249 +msgid "" +"For a simple example, consider tagging incoming packets from different " +"networks. Later rules determine if the tagged packets are allowed or " +"denied: indexterm:[tag, example]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1270 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"#\n" +"# *ipfw add 1000 count tag 10 tcp from 172.16.200.0/24 to me 5656*\n" +"01000 count tag 10 tcp from 172.16.200.0/24 to me 5656\n" +"#\n" +"# *ipfw add 1100 count tag 20 tcp from 172.16.225.0/24 to me 5656*\n" +"01100 count tag 20 tcp from 172.16.225.0/24 to me 5656\n" +"#\n" +"# *ipfw add 1200 count tag 30 tcp from 203.0.113.0/24 to me 5656*\n" +"01200 count tag 30 tcp from 203.0.113.0/24 to me 5656\n" +"#\n" +"# *ipfw add 3000 allow tcp from any to me tagged 30 setup keep-state*\n" +"03000 allow tcp from any to me tagged 30 setup keep-state :default\n" +"#\n" +"# *ipfw add 4000 deny tcp from any to me tagged 10,20*\n" +"04000 deny tcp from any to me tagged 10,20\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1275 +msgid "" +"Test this by using man:ncat[1] to set its own source address. indexterm:" +"[ncat] To do this, first setup two alias address on the `em0` interface on " +"the *external1* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1291 +#, no-wrap +msgid "" +"# *ifconfig em0 172.16.200.10/24 alias*\n" +"# *ifconfig em0 172.16.225.10/24 alias*\n" +"#\n" +"# *ifconfig em0*\n" +"em0: flags=8843 metric 0 mtu 1500\n" +" options=81209b\n" +" ether 02:49:50:46:57:10\n" +" inet 203.0.113.10 netmask 0xffffff00 broadcast 203.0.113.255\n" +" #inet 172.16.200.10 netmask 0xffffff00# broadcast 172.16.200.255\n" +" #inet 172.16.225.10 netmask 0xffffff00# broadcast 172.16.225.255\n" +" media: Ethernet autoselect (1000baseT )\n" +" status: active\n" +" nd6 options=29\n" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1295 +#, no-wrap +msgid "Use of Tags" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1296 +#, no-wrap +msgid "Use of Tags. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1296 +#, no-wrap +msgid "ipfw-rules045.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1299 +msgid "" +"Because of the rule tagging in this ruleset, only traffic tagged with value " +"\"30\" is allowed to pass." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1301 +msgid "" +"Tags, combined with lookup tables allow for powerful policy based network " +"access." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1302 +#, no-wrap +msgid "Logging" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1306 +#, no-wrap +msgid "" +"*ipfw* supports two methods of logging:\n" +"indexterm:[rule, log] indexterm:[logging] indexterm:[logging, ipfw0] indexterm:[logging, syslog] indexterm:[ipfw0]\n" +msgstr "" + +#. type: Title ==== +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1307 +#, no-wrap +msgid "Method 1 – using *ipfw0*, the IPFW pseudointerface" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1313 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"# *ifconfig ipfw0 create*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1317 +msgid "" +"Note that the *ipfw.ko* kernel module must be loaded before creating the " +"*ipfw0* interface. Also, note that if *ipfw.ko* is unloaded, the interface " +"is destroyed and is no longer available." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1319 +msgid "Why use the *ipfw0* interface?" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1321 +msgid "" +"It is possible to read logs in real time with programs such as man:" +"tcpdump[1], man:wireshark[1], or other network monitoring programs." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1323 +msgid "An example is given further below." +msgstr "" + +#. type: Title ==== +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1324 +#, no-wrap +msgid "Method 2 – use *syslogd*" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1332 +msgid "" +"Setting the sysctl variable `net.inet.ip.fw.verbose = 1` will instruct the " +"firewall to log packets to man:syslogd[8] even when the *ipfw0* interface " +"exists. indexterm:[sysctl, net.inet.ip.fw.verbose] Syslogd must be " +"configured via [.filename]#/etc/syslog.conf#. indexterm:[syslog, /etc/" +"syslog.conf] *ipfw* packets will be logged with a LOG_SECURITY facility. " +"The logging limit is configurable via `net.inet.ip.fw.verbose_limit`, which " +"is set to 0 (unlimited) by default." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1334 +msgid "Why use syslog?" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1337 +msgid "" +"Of the two methods, it is the only one that processes count actions, and is " +"also the only one that prints rule numbers with the log entry. indexterm:" +"[log, count actions]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1340 +msgid "" +"To test logging, create a rule with the *log* keyword: indexterm:[logging, " +"example]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1344 +#, no-wrap +msgid "# *ipfw add 1000 allow #log# tcp from any to me 5656 setup keep-state*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1349 +msgid "" +"Counters are also a feature of rules that specify the *log* keyword. If the " +"above rules are edited to add the *log* keyword, matches for all rules will " +"be included in the log entries with associated counts. indexterm:[keyword, " +"log]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1351 +msgid "" +"With the ruleset changes to add the *log* keyword, the ruleset looks like " +"this:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1361 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 allow log tcp from 203.0.113.10 to me 5656 keep-state :default\n" +"02000 allow log tcp from 203.0.113.10 to me 5657 keep-state :default\n" +"03000 allow log tcp from 203.0.113.10 to me 5658 keep-state :default\n" +"04000 allow log tcp from 203.0.113.10 to me 5659 keep-state :default\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Title ==== +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1363 +#, no-wrap +msgid "Using Method 1" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1367 +msgid "" +"Using Method 1, capture/view logs with tcpdump: indexterm:[log, Method 1] " +"indexterm:[log, ipfw0]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1371 +#, no-wrap +msgid "# *tcpdump -i ipfw0 -X*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1374 +msgid "Note: Redirect binary data to a 'savefile' with the `-w file` option." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1376 +msgid "" +"Experiment with the tcpdump *-v*, *-vv*, and *-vvv* options, which gives " +"increasingly more verbose output." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1379 +msgid "" +"The example below examines traffic with the *ucont.sh* on the *external1* VM " +"and the *userv3.sh* script on the *firewall* VM. indexterm:[ucont.sh] " +"indexterm:[userv3.sh]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1381 +#, no-wrap +msgid "UDP Traffic From External1 to Firewall" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1382 +#, no-wrap +msgid "UDP Traffic From External1 to Firewall. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1382 +#, no-wrap +msgid "ipfw-rules050.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1385 +msgid "" +"Logged traffic from the above communication appears on the log device ipfw0:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1415 +#, no-wrap +msgid "" +"#\n" +"# *tcpdump -i ipfw0 -X -vvv*\n" +"tcpdump: WARNING: ipfw0: That device doesn't support promiscuous mode\n" +"(BIOCPROMISC: Invalid argument)\n" +"tcpdump: listening on ipfw0, link-type EN10MB (Ethernet), capture size 262144 bytes\n" +"20:50:44.259127 IP (tos 0x0, ttl 64, id 61929, offset 0, flags [none], proto UDP (17), length 70)\n" +" 203.0.113.10.27337 > 203.0.113.50.5656: [udp sum ok] UDP, length 42\n" +" 0x0000: 4500 0046 f1e9 0000 4011 1c61 ac10 0a0a E..F....@..a....\n" +" 0x0010: ac10 0a32 6ac9 1618 0032 00ff 5544 5020 ...2j....2..UDP.\n" +" 0x0020: 7061 636b 6574 2066 726f 6d20 5b31 3732 packet.from.[172\n" +" 0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 .16.10.10],[5656\n" +" 0x0040: 5d2c 5b31 5d0a ],[1].\n" +"20:50:44.581025 IP (tos 0x0, ttl 64, id 61930, offset 0, flags [none], proto UDP (17), length 70)\n" +" 203.0.113.10.41914 > 203.0.113.50.5656: [udp sum ok] UDP, length 42\n" +" 0x0000: 4500 0046 f1ea 0000 4011 1c60 ac10 0a0a E..F....@..`....\n" +" 0x0010: ac10 0a32 a3ba 1618 0032 c80c 5544 5020 ...2.....2..UDP.\n" +" 0x0020: 7061 636b 6574 2066 726f 6d20 5b31 3732 packet.from.[172\n" +" 0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 .16.10.10],[5656\n" +" 0x0040: 5d2c 5b32 5d0a ],[2].\n" +"20:50:45.960845 IP (tos 0x0, ttl 64, id 61931, offset 0, flags [none], proto UDP (17), length 70)\n" +" 203.0.113.10.33126 > 203.0.113.50.5656: [udp sum ok] UDP, length 42\n" +" 0x0000: 4500 0046 f1eb 0000 4011 1c5f ac10 0a0a E..F....@.._....\n" +" 0x0010: ac10 0a32 8166 1618 0032 ea5f 5544 5020 ...2.f...2._UDP.\n" +" 0x0020: 7061 636b 6574 2066 726f 6d20 5b31 3732 packet.from.[172\n" +" 0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 .16.10.10],[5656\n" +" 0x0040: 5d2c 5b33 5d0a ],[3].\n" +"^C\n" +msgstr "" + +#. type: Title ==== +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1417 +#, no-wrap +msgid "Using Method 2" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1422 +msgid "" +"Using Method 2, first examine [.filename]#/etc/syslog.conf# to see if there " +"is already a facility and level for security listed. indexterm:[log, Method " +"2] In modern versions of FreeBSD it is common to see:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1425 +#, no-wrap +msgid "security.* /var/log/security\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1429 +#, no-wrap +msgid "" +"*ipfw* creates logs with the LOG_SECURITY facility and sends output to the file [.filename]#/var/log/security# in this case.\n" +"indexterm:[log, LOG_SECURITY]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1431 +msgid "" +"If this entry exists on the system, it is all set, otherwise read through " +"the below and set up an entry for an *ipfw* logfile." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1434 +msgid "" +"To log to man:syslogd[8], add the following line to the end of [.filename]#/" +"etc/syslog.conf#: indexterm:[log, /etc/syslog.conf]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1437 +#, no-wrap +msgid "security.info\t\t\t\t/tmp/ipfw.info\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1440 +msgid "(FreeBSD syslog.conf allows tabs or spaces to be used.)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1443 +msgid "Create the logfile with" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1448 +#, no-wrap +msgid "# *touch /tmp/ipfw.info*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1452 +msgid "" +"then send a `HANGUP` signal to the `syslogd` daemon: indexterm:[log, syslogd]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1456 +#, no-wrap +msgid "# *kill -HUP *\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1460 +msgid "" +"Use *tail -f* to see logs in real time. indexterm:[log, reading with tail -" +"f]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1463 +msgid "" +"Note that *ipfw* only logs _matched rules_ with this method. indexterm:" +"[log, match]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1466 +msgid "" +"Note that *ipfw* logs to the syslog .info level and the .debug level. " +"indexterm:[log, .info level] indexterm:[log, .debug level]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1475 +#, no-wrap +msgid "" +"# *tail -f /var/log/security*\n" +"Apr 3 14:50:12 firewall newsyslog[401]: logfile first created\n" +"Apr 9 21:05:13 firewall kernel: ipfw: #1000# Accept UDP 203.0.113.10:59203 203.0.113.50:5656 in via em0\n" +"Apr 9 21:05:15 firewall kernel: ipfw: #1000# Accept UDP 203.0.113.10:12401 203.0.113.50:5656 in via em0\n" +"Apr 9 21:05:16 firewall kernel: ipfw: #1000# Accept UDP 203.0.113.10:45319 203.0.113.50:5656 in via em0\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1478 +msgid "" +"The *log* entry includes the date, time, host, service, and rule number " +"(1000 above) to make it easy to track which rule is being matched." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1480 +#, no-wrap +msgid "*General Notes on logging*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1494 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 allow tcp from 203.0.113.100 to me setup keep-state :default\n" +"02000 allow icmp from 203.0.113.100 to me\n" +"02100 allow icmp from me to 203.0.113.100\n" +"03000 allow log udp from 203.0.113.10 to me 5656\n" +"04000 allow log logamount 20 udp from 203.0.113.10 to me 5657\n" +"05000 allow log logamount 20 udp from 203.0.113.10 to me 5658\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1499 +msgid "" +"When using Method 2 (syslog) on a quiet system, notice that the entries do " +"not appear right away when reading the security log file in real time (for " +"example, `tail -f /var/log/security`). indexterm:[log, syslog buffering] " +"This is because syslog will buffer identical lines and output a notification " +"only occasionally as in the below example:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1505 +#, no-wrap +msgid "" +"Mar 28 22:30:01 firewall kernel: ipfw: 3000 Accept UDP 203.0.113.10:27519 203.0.113.50:5656 in via em0\n" +"Mar 28 22:30:03 firewall syslogd: last message repeated 4 times\n" +"Mar 28 22:32:31 firewall syslogd: last message repeated 31 times\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1512 +msgid "" +"Also, Method 1 (using the *ipfw0* interface) and Method 2 (syslog) are " +"*_mutually exclusive_*. indexterm:[log, mutually exclusive] It is not " +"possible to have both active at the same time. If `net.inet.ip.fw." +"verbose=0`, the output will be to the *ipfw0* interface; if the value is 1, " +"the log output will be to *syslog*. indexterm:[sysctl, net.inet.ip.fw." +"verbose]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1516 +#, no-wrap +msgid "" +"*logamount* values in rules only apply to `Method 2 - syslog`.\n" +"indexterm:[log, logamount] indexterm:[keyword, logamount]\n" +"They have no effect on limiting the number of packets sent out the *ipfw0* interface.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1518 +msgid "" +"In `Method 2 - syslog`, when the log limit is reached, *ipfw* will send a " +"notification similar to the following into the designated security logging " +"file (default: [.filename]#/var/log/security#):" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1524 +#, no-wrap +msgid "" +"Mar 28 23:00:10 firewall kernel: ipfw: 5000 Accept UDP 203.0.113.10:63367 203.0.113.50:5658 in via em0\n" +"Mar 28 23:00:11 firewall kernel: ipfw: 5000 Accept UDP 203.0.113.10:30909 203.0.113.50:5658 in via em0\n" +"#Mar 28 23:00:11 firewall kernel: ipfw: limit 20 reached on entry 5000#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1527 +msgid "" +"And, at the same time, it also conveniently sends the same message to [." +"filename]#/var/log/messages#, the standard FreeBSD logfile:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1531 +#, no-wrap +msgid "Mar 28 23:00:11 firewall kernel: ipfw: limit 20 reached on entry 5000\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1535 +msgid "" +"After that notification is sent, no more syslog entries will be sent from " +"the matching rule until the log counters are reset with: indexterm:[log, " +"resetlog]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1539 +#, no-wrap +msgid "# *ipfw resetlog *\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1542 +msgid "" +"When the *resetlog* command is entered, *ipfw* will send a reset " +"notification to syslog:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1546 +#, no-wrap +msgid "Mar 28 23:04:51 firewall kernel: ipfw: logging count reset.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1551 +msgid "" +"Unfortunately, as of FreeBSD version 14.1, it does not say *_which_* rule " +"the count was reset for. Presumably, the firewall admin should know which " +"rule since they just entered the command, at least if there is only one " +"admin. In any case, it is a good idea to keep track of that manually when " +"working with many rules that include the *log* keyword." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1554 +msgid "" +"If issuing an *ipfw resetlog* command _without_ specifying a rule number, " +"*_all_* counters in all rules are reset and *ipfw* sends the following " +"notification: indexterm:[log, resetlog] indexterm:[keyword, resetlog]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1558 +#, no-wrap +msgid "Mar 28 23:08:52 firewall kernel: ipfw: All logging counts reset.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1562 +msgid "" +"Finally, note that the sysctl variable `net.inet.ip.fw.verbose_limit` " +"provides a \"default limit\" if one is not specified with the *logamount* " +"keyword in the ruleset. indexterm:[sysctl, net.inet.ip.fw.verbose_limit]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1564 +msgid "Consider this scenario:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1569 +#, no-wrap +msgid "" +"# *sysctl net.inet.ip.fw.verbose_limit*\n" +"net.inet.ip.fw.verbose_limit: 5 <---- The limit is preset to 5\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1572 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1577 +msgid "" +"As new rules are added, *ipfw* will apply any *logamount* value it finds in " +"the body of a rule. If a rule being entered does not have a *logamount* " +"entry, the value defaults to the current `net.inet.ip.fw.verbose_limit` " +"amount. indexterm:[log, logamount]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1594 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"00100 check-state :default\n" +"#\n" +"# *ipfw add 3000 allow log udp from 203.0.113.10 to me 5656*\n" +"03000 allow log #logamount 5# udp from 203.0.113.10 to me 5656\n" +"#\n" +"# *ipfw add 4000 allow log logamount 20 udp from 203.0.113.10 to me 5657*\n" +"04000 allow log #logamount 20# udp from 203.0.113.10 to me 5657\n" +"#\n" +"# *ipfw list*\n" +"00100 check-state :default\n" +"03000 allow log logamount 5 udp from 203.0.113.10 to me 5656\n" +"04000 allow log logamount 20 udp from 203.0.113.10 to me 5657\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1597 +msgid "" +"If the sysctl for `net.inet.ip.fw.verbose_limit` is changed *_after_* the " +"rule is entered, it has *_no_* effect:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1602 +#, no-wrap +msgid "" +"# *sysctl net.inet.ip.fw.verbose_limit=3*\n" +"net.inet.ip.fw.verbose_limit: 5 -> 3\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1605 +msgid "and later in [.filename]#/var/log/messages#" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1609 +#, no-wrap +msgid "Mar 29 11:07:02 firewall kernel: ipfw: limit 5 reached on entry 3000\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1611 +#, no-wrap +msgid " ...\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1613 +#, no-wrap +msgid "Mar 29 11:07:24 firewall kernel: ipfw: limit 20 reached on entry 4000\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1615 +#, no-wrap +msgid "Reset" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1620 +msgid "" +"The *reset* keyword sends an immediate TCP reset on a rule match containing " +"that keyword. indexterm:[keyword, reset] indexterm:[reset] This immediately " +"shuts down any TCP connection from the source matching the rule." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1629 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00100 check-state :default\n" +"01000 allow log tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"02000 reset log tcp from 203.0.113.10 to me 5657\n" +"03000 reset log udp from 203.0.113.10 to me 5658\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1632 +msgid "The syslog view of a TCP *reset* rule match looks like this:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1640 +#, no-wrap +msgid "" +"Apr 9 21:44:49 firewall kernel: ipfw: 1000 Accept TCP 203.0.113.50:5656 203.0.113.10:28218 out via em0\n" +"Apr 9 21:44:49 firewall syslogd: last message repeated 1 times\n" +"Apr 9 21:44:49 firewall kernel: ipfw: 1000 Accept TCP 203.0.113.10:28218 203.0.113.50:5656 in via em0\n" +"#Apr 9 21:45:01 firewall kernel: ipfw: 2000 Reset TCP 203.0.113.10:12998 203.0.113.50:5657 in via em0#\n" +"#Apr 9 21:45:07 firewall kernel: ipfw: 2000 Reset TCP 203.0.113.10:13782 203.0.113.50:5657 in via em0#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1646 +msgid "" +"When sysctl `net.inet.ip.fw.verbose=0`, there is no discernible output on " +"*ipfw0* for a *reset* action. A TCP SYN packet arrives and that is all that " +"is displayed. To actually witness the *reset*, run man:tcpdump[8] on the " +"specific interface: indexterm:[reset, view]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1663 +#, no-wrap +msgid "" +"# *tcpdump -i em0 -X -vvv*\n" +"tcpdump: listening on em0, link-type EN10MB (Ethernet), capture size 262144 bytes\n" +"21:53:39.376825 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" 203.0.113.10.32945 > 203.0.113.50.5657: Flags [#S#], cksum 0x68fa (correct), seq 1926269947, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 648984165 ecr 0], length 0\n" +" 0x0000: 4500 003c 0000 4000 4006 ce5f ac10 0a0a E..<..@.@.._....\n" +" 0x0010: ac10 0a32 80b1 1619 72d0 8bfb 0000 0000 ...2....r.......\n" +" 0x0020: a002 ffff 68fa 0000 0204 05b4 0103 0306 ....h...........\n" +" 0x0030: 0402 080a 26ae b665 0000 0000 ....&..e....\n" +"21:53:39.377143 IP (tos 0x10, ttl 64, id 1965, offset 0, flags [none], proto TCP (6), length 40)\n" +" 203.0.113.50.5657 > 203.0.113.10.32945: Flags [#R.#], cksum 0xaddc (correct), seq 0, ack 1926269948, win 0, length 0\n" +" 0x0000: 4510 0028 07ad 0000 4006 06b7 ac10 0a32 E..(....@......2\n" +" 0x0010: ac10 0a0a 1619 80b1 0000 0000 72d0 8bfc ............r...\n" +" 0x0020: 5014 0000 addc 0000 P.......\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1669 +msgid "" +"A UDP rule containing the *reset* keyword just drops the packet. Nothing is " +"sent back to the source address. If the *log* keyword is also used on the " +"rule, a log entry is generated for syslog (if enabled): indexterm:[log, " +"reset]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1673 +#, no-wrap +msgid "#Apr 9 21:58:49 firewall kernel: ipfw: 3000 Reset UDP 203.0.113.10:56503 203.0.113.50:5658 in via em0#\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1675 +#, no-wrap +msgid "Tee" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1684 +msgid "" +"The *tee* rule requires a man:divert[4] socket set up beforehand. indexterm:" +"[keyword, tee] indexterm:[tee] indexterm:[keyword, divert] Refer to the " +"crossref:ipfw-rules[ipfw-divert-action, divert] rule covered below for " +"setting up the socket. Once the socket is set up, the *tee* keyword works " +"like *divert* except that it is not interested in any packet return. " +"indexterm:[divert] It is simply copying the packet to the socket. " +"Processing continues with the next rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1686 +msgid "" +"In essence, *tee* allows the packet to be sent to userspace for any purpose " +"desired - monitoring, copying, counting - whatever." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1690 +#, no-wrap +msgid "# *ipfw add 1000 tee 700 ip from any to me*\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1692 +#, no-wrap +msgid "Unreach" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1698 +msgid "" +"The *unreach* keyword directs *ipfw* to respond back to the source when " +"packets arrive with a destination port that is not opened by any service. " +"indexterm:[keyword, unreach] indexterm:[unreach] *ipfw* sends an ICMP reply " +"with the code set to the keyword parameter. This works for any IP protocol." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1701 +msgid "" +"Because *ipfw* sends an ICMP packet back to the source, the ruleset must " +"allow outbound ICMP. indexterm:[ICMP]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1711 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"00100 0 0 allow icmp from me to any\n" +"01000 0 0 unreach 100 log udp from any to me 5656\n" +"02000 0 0 unreach 200 log tcp from any to me 5657\n" +"03000 0 0 unreach 250 log ip from any to me 5658\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1714 +msgid "" +"The counters are zero when the *external1* VM sends its packet, a UDP packet " +"destined for port 5656, for which no service is currently set up." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1717 +#, no-wrap +msgid "" +"*ipfw* matches this with rule 1000 and sends an ICMP unreachable notice with code 100 (an arbitrary value, but see the list in man:ipfw[8]).\n" +"The offending packet is encapsulated in the data portion of the ICMP reply:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1729 +#, no-wrap +msgid "" +"# *tcpdump -i bridge0 -X -vvv*\n" +"tcpdump: listening on bridge0, link-type EN10MB (Ethernet), capture size 262144 bytes\n" +"14:55:59.666002 IP (tos 0x0, ttl 64, id 25431, offset 0, flags [none], proto UDP (17), length 70)\n" +" 203.0.113.10.36146 > 203.0.113.50.5656: [udp sum ok] UDP, length 42\n" +"\t0x0000: 4500 0046 6357 0000 4011 aaf3 ac10 0a0a E..FcW..@.......\n" +"\t0x0010: ac10 0a32 8d32 1618 0032 de95 5544 5020 ...2.2...2..#UDP.#\n" +"\t0x0020: 6174 7461 636b 2066 726f 6d20 5b31 3732 #communication.from.[172#\n" +"\t0x0030: 2e31 362e 3130 2e31 305d 2c5b 3536 3536 #.16.10.10],[5656#\n" +"\t0x0040: 5d2c 5b31 5d0a #],[1].#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1733 +msgid "" +"The results for a TCP unreachable are almost the same. The ICMP packet " +"encapsulates the SYN packet in the data portion of the reply." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1736 +msgid "" +"Here is a view of an ICMP Reply to unreachable TCP port 5657: indexterm:" +"[ICMP] indexterm:[ICMP, reply]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1757 +#, no-wrap +msgid "" +"# *tcpdump -i bridge0 -X -vvv*\n" +"tcpdump: listening on bridge0, link-type EN10MB (Ethernet), capture size 262144 bytes\n" +"15:24:03.663104 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" 203.0.113.10.58575 > 203.0.113.50.5657: Flags [S], cksum 0x092c (correct), seq 1062429515, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 3566166113 ecr 0], length 0\n" +"\t0x0000: 4500 003c 0000 4000 4006 ce5f ac10 0a0a E..<..@.@..-....\n" +"\t0x0010: ac10 0a32 e4cf 1619 3f53 634b 0000 0000 ...2....?ScK....\n" +"\t0x0020: a002 ffff 092c 0000 0204 05b4 0103 0306 .....,..........\n" +"\t0x0030: 0402 080a d48f 6061 0000 0000 ......`a....\n" +"15:24:03.664168 IP (tos 0x0, ttl 64, id 37717, offset 0, flags [none], proto ICMP (1), length 88)\n" +" 203.0.113.50 > 203.0.113.10: ICMP # 200 203.0.113.50 unreachable, length 68\n" +"\tIP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)\n" +" 203.0.113.10.58575 > 203.0.113.50.5657: Flags [#S#], cksum 0x092c (correct), seq 1062429515, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 3566166113 ecr 0], length 0\n" +"\t0x0000: 4500 0058 9355 0000 4001 7af3 ac10 0a32 E..X.U..@.z....2\n" +"\t0x0010: ac10 0a0a 03c8 68c3 0000 0000 4500 003c ......h.....E..<\n" +"\t0x0020: 0000 4000 4006 ce5f ac10 0a0a ac10 0a32 ..@.@.._.......2\n" +"\t0x0030: e4cf 1619 3f53 634b 0000 0000 a002 ffff ....?ScK........\n" +"\t0x0040: 092c 0000 0204 05b4 0103 0306 0402 080a .,..............\n" +"\t0x0050: d48f 6061 0000 0000 ..`a....\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1759 +#, no-wrap +msgid "Setdscp" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1766 +msgid "" +"The *setdscp* action directs *ipfw* to set an IP header option on outbound " +"packets. indexterm:[keyword, setdscp] indexterm:[setdscp] The action has no " +"effect on inbound packets. The header option, formerly known as the \"Type " +"of Service\" (ToS) option, now defines several classes of differentiated " +"services (DiffServ) per several RFCs - link:https://www.rfc-editor.org/rfc/" +"rfc2474.html[RFC 2474], link:https://www.rfc-editor.org/rfc/rfc3168.html[RFC " +"3168], and link:https://www.rfc-editor.org/rfc/rfc3260.html[RFC 3260]. " +"indexterm:[RFC, 2474] indexterm:[RFC, 3260]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1771 +msgid "" +"These service classes such as \"Network Control\", \"Telephony\", " +"\"Multimedia Conferencing\", \"Broadcast Video\", \"Low-latency Data\", etc. " +"all require their packets to receive special handling in the network. " +"indexterm:[setdscp, service classes] This is achieved by inserting \"code " +"points\" - numerical values in the packet header - that define each class. " +"indexterm:[setdcsp, code points]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1774 +msgid "" +"Firewalls, routers, switches, and other network devices interpret these " +"values and, in theory, service the packets according to their class. See " +"this Wikipedia article on Differentiated Services: https://en.wikipedia.org/" +"wiki/Differentiated_services." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1777 +msgid "" +"In practice, support for service classes vary among network operators. " +"Check the man page for a list of code points settable by *ipfw*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1779 +msgid "" +"The example below sets the DSCP value to \"af31\", a codepoint in the " +"\"Multimedia Streaming\" class." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1783 +#, no-wrap +msgid "# *ipfw add 2000 setdscp af31 udp from me to any 5656*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1786 +msgid "Note that rule processing continues to the next rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1791 +msgid "" +"Note also that the DSCP value takes up only a partial byte in the IP header, " +"sharing it with two bits of ECN (Explicit Congestion Notification). " +"indexterm:[ECN] indexterm:[setdscp, ECN] The binary value for \"af31\" is " +"011010nn, where 'nn' are the two bits for ECN. If no ECN, the value " +"resolves to 0x68 (104 decimal)." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1794 +msgid "" +"An outbound traffic example, generated by *ncat -u 203.0.113.10 5656* from " +"the *firewall* VM is shown as received by the *external1* VM: indexterm:" +"[ncat]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1805 +#, no-wrap +msgid "" +"# *tcpdump -i em0 -X -vvv*\n" +"tcpdump: listening on em0, link-type EN10MB (Ethernet), capture size 262144 bytes\n" +"10:14:22.173252 IP (tos 0x68, ttl 64, id 30816, offset 0, flags [none], proto UDP (17), length 57)\n" +" 203.0.113.50.17767 > 203.0.113.10.5656: [udp sum ok] UDP, length 29\n" +" 0x0000: 45##68## 0039 7860 0000 4011 958f ac10 0a32 Eh.9x`..@......2\n" +" 0x0010: ac10 0a0a 4567 1618 0025 0f5b 4772 6565 ....Eg...%.[Gree\n" +" 0x0020: 7469 6e67 7320 6672 6f6d 2074 6865 2066 tings.from.the.f\n" +" 0x0030: 6972 6577 616c 6c2e 0a irewall..\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1808 +msgid "" +"Diffserve codepoints can be set on any IP based protocol or restricted to " +"selected protocols and/or ports through suitable rules." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1809 +#, no-wrap +msgid "Skipto" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1814 +msgid "" +"The *skipto* action directs the firewall engine to pass over any rules less " +"than the *skipto* parameter number. indexterm:[keyword, skipto] indexterm:" +"[skipto] If an early rule can match a packet characteristic such as an " +"address, port, TCP or UDP header option or similar, a *skipto* rule can jump " +"to a potentially much later section of the firewall ruleset to handle to " +"packet." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1816 +msgid "Consider the following (contrived) ruleset:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1830 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"# *ipfw add 1000 allow tcp from me to any established keep-state*\n" +"# *ipfw add 2000 allow tcp from 203.0.113.10 to me 4500 setup keep-state*\n" +"# *ipfw add 3000 allow tcp from 203.0.113.10 to me 4502 setup keep-state*\n" +"# *ipfw add 4000 allow tcp from 203.0.113.10 to me 4504 setup keep-state*\n" +"# *ipfw add 5000 allow tcp from 203.0.113.10 to me 4506 setup keep-state*\n" +"# *ipfw add 6000 allow tcp from 203.0.113.10 to me 4508 setup keep-state*\n" +"# *ipfw add 7000 allow tcp from 203.0.113.10 to me 4510 setup keep-state*\n" +"# *ipfw add 8000 allow tcp from 203.0.113.10 to me 4512 setup keep-state*\n" +"# *ipfw add 9000 allow tcp from 203.0.113.10 to me 4512 setup keep-state*\n" +"# *ipfw add 10000 allow tcp from 203.0.113.10 to me 5656 setup keep-state*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1836 +msgid "" +"With the *external1* VM using the *tcon.sh 5656* TCP connection script, " +"*ipfw* has to traverse the entire firewall ruleset, checking each rule in " +"turn for a match. indexterm:[tcon.sh] (When testing this ruleset, ensure " +"that the *firewall* VM is running the appropriate service script such as " +"*tserv3.sh*.) indexterm:[tserv3.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1838 +msgid "" +"By placing a *skipto* action rule after the *check-state* action, *ipfw* " +"jumps directly to the desired rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1853 +#, no-wrap +msgid "" +"# *ipfw add 100 check-state*\n" +"# *ipfw add 500 #skipto 10000# tcp from 203.0.113.10 to me 5656*\n" +"# *ipfw add 1000 allow tcp from me to any established keep-state*\n" +"# *ipfw add 2000 allow tcp from 203.0.113.10 to me 4500 setup keep-state*\n" +"# *ipfw add 3000 allow tcp from 203.0.113.10 to me 4502 setup keep-state*\n" +"# *ipfw add 4000 allow tcp from 203.0.113.10 to me 4504 setup keep-state*\n" +"# *ipfw add 5000 allow tcp from 203.0.113.10 to me 4506 setup keep-state*\n" +"# *ipfw add 6000 allow tcp from 203.0.113.10 to me 4508 setup keep-state*\n" +"# *ipfw add 7000 allow tcp from 203.0.113.10 to me 4510 setup keep-state*\n" +"# *ipfw add 8000 allow tcp from 203.0.113.10 to me 4512 setup keep-state*\n" +"# *ipfw add 9000 allow tcp from 203.0.113.10 to me 4512 setup keep-state*\n" +"### *ipfw add 10000 allow tcp from 203.0.113.10 to me 5656 setup keep-state*##\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1857 +msgid "" +"Use the `-a` command line parameter to see if the *skipto* action is working " +"(or use *ipfw show*): indexterm:[ipfw, show]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1874 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"00100 0 0 check-state :default\n" +"#00500 1 60 skipto 10000 tcp from 203.0.113.10 to me 5656#\n" +"01000 0 0 allow tcp from me to any established keep-state :default\n" +"02000 0 0 allow tcp from 203.0.113.10 to me 4500 setup keep-state :default\n" +"03000 0 0 allow tcp from 203.0.113.10 to me 4502 setup keep-state :default\n" +"04000 0 0 allow tcp from 203.0.113.10 to me 4504 setup keep-state :default\n" +"05000 0 0 allow tcp from 203.0.113.10 to me 4506 setup keep-state :default\n" +"06000 0 0 allow tcp from 203.0.113.10 to me 4508 setup keep-state :default\n" +"07000 0 0 allow tcp from 203.0.113.10 to me 4510 setup keep-state :default\n" +"08000 0 0 allow tcp from 203.0.113.10 to me 4512 setup keep-state :default\n" +"09000 0 0 allow tcp from 203.0.113.10 to me 4514 setup keep-state :default\n" +"#10000 8 474 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default#\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1878 +#, no-wrap +msgid "" +"*General notes on skipto:*\n" +"indexterm:[skipto, general notes]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1880 +msgid "" +"The *skipto* action does not allow negative numbers or zero as a parameter." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1884 +#, no-wrap +msgid "" +"*skipto* does allow numbers greater than 65536.\n" +"What happens is the system accepts the input, but the result is the integer remainder of the number modulo 65536.\n" +"So, ensure the value entered is the value displayed by the command output.\n" +"Numbers greater than 65534 should not be used.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1886 +#, no-wrap +msgid "" +"It is possible to use the *skipto* action to skip between *sets*.\n" +"However, if the *set* containing the *skipto* target is disabled, processing continues with the next rule in *_any_* *set* that is enabled.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1889 +msgid "" +"For example, if there are three *sets* - 0, 1, and 2, with a disabled *set* " +"1 containing the destination of the skipto action, processing will continue " +"with the next rule. See the below ruleset and counters:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1907 +#, no-wrap +msgid "" +"# *ipfw -Sa list*\n" +"00100 0 0 set 0 check-state :default\n" +"00101 1 60 set 0 skipto 2000 tcp from 203.0.113.10 to me\n" +"00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"00150 0 0 set 0 allow tcp from me to any established keep-state :default\n" +"01000 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"# DISABLED 01200 0 0 set 1 allow tcp from 203.0.113.10 to me 6500 setup keep-state :default\n" +"# DISABLED 01800 0 0 set 1 allow tcp from 203.0.113.10 to me 6512 setup keep-state :default\n" +"# DISABLED 01900 0 0 set 1 allow tcp from 203.0.113.10 to me 6514 setup keep-state :default\n" +"# DISABLED 02000 0 0 set 1 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"#02700 0 0 set 2 allow tcp from 203.0.113.10 to me 7510 setup keep-state :default#\n" +"02800 0 0 set 2 allow tcp from 203.0.113.10 to me 7512 setup keep-state :default\n" +"02900 0 0 set 2 allow tcp from 203.0.113.10 to me 7514 setup keep-state :default\n" +"03000 8 474 set 2 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"65535 0 0 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1910 +msgid "" +"If using *skipto* to a rule number that has multiple rules, the first " +"matching rule at or after that number is executed:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1932 +#, no-wrap +msgid "" +"# *ipfw -Sa list*\n" +"00100 0 0 set 0 check-state :default\n" +"00101 1 60 set 0 #skipto 2000# tcp from 203.0.113.10 to me\n" +"00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"00150 0 0 set 0 allow tcp from me to any established keep-state :default\n" +"01600 0 0 set 1 allow tcp from 203.0.113.10 to me 6508 setup keep-state :default\n" +"01700 0 0 set 1 allow tcp from 203.0.113.10 to me 6510 setup keep-state :default\n" +"02000 0 0 set 1 allow tcp from 203.0.113.10 to me 6512 setup keep-state :default\n" +"02000 0 0 set 1 allow tcp from 203.0.113.10 to me 6514 setup keep-state :default\n" +"02000 0 0 set 2 allow tcp from 203.0.113.10 to me 7500 setup keep-state :default\n" +"02000 0 0 set 2 allow tcp from 203.0.113.10 to me 7502 setup keep-state :default\n" +"02000 0 0 set 2 allow tcp from 203.0.113.10 to me 7504 setup keep-state :default\n" +"02500 0 0 set 2 allow tcp from 203.0.113.10 to me 7506 setup keep-state :default\n" +"02600 0 0 set 2 allow tcp from 203.0.113.10 to me 7508 setup keep-state :default\n" +"02700 0 0 set 2 allow tcp from 203.0.113.10 to me 7510 setup keep-state :default\n" +"02800 0 0 set 2 allow tcp from 203.0.113.10 to me 7512 setup keep-state :default\n" +"02900 0 0 set 2 allow tcp from 203.0.113.10 to me 7514 setup keep-state :default\n" +"#03000 10 567 set 2 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default#\n" +"65535 0 0 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1936 +msgid "" +"It is possible to enter a rule with a *skipto* rule number that is lower " +"than the current rule number, attempting to go backward in the ruleset. " +"However, this has no effect, and processing continues with the next rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1954 +#, no-wrap +msgid "" +"# *ipfw -Sa list*\n" +"00100 0 0 set 0 check-state :default\n" +"00101 1 60 set 0 #skipto 1000# tcp from 203.0.113.10 to me\n" +"00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"00150 0 0 set 0 allow tcp from me to any established keep-state :default\n" +"00200 0 0 set 0 allow tcp from 203.0.113.10 to me 4500 setup keep-state :default\n" +"00300 0 0 set 0 allow tcp from 203.0.113.10 to me 4502 setup keep-state :default\n" +"00400 0 0 set 0 allow tcp from 203.0.113.10 to me 4504 setup keep-state :default\n" +"00500 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"00600 0 0 set 0 allow tcp from 203.0.113.10 to me 4508 setup keep-state :default\n" +"00700 0 0 set 0 allow tcp from 203.0.113.10 to me 4512 setup keep-state :default\n" +"00800 0 0 set 0 allow tcp from 203.0.113.10 to me 4514 setup keep-state :default\n" +"01000 1 60 set 0 #skipto 500# tcp from 203.0.113.10 to me\n" +"01100 8 475 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"65535 0 0 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1957 +msgid "It is also possible (but not advised) to *skipto* a *skipto* rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1982 +#, no-wrap +msgid "" +"00100 0 0 set 0 check-state :default\n" +"00101 1 60 set 0 #skipto 1000# tcp from 203.0.113.10 to me\n" +"00120 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"00150 0 0 set 0 allow tcp from me to any established keep-state :default\n" +"00200 0 0 set 0 allow tcp from 203.0.113.10 to me 4500 setup keep-state :default\n" +"00300 0 0 set 0 allow tcp from 203.0.113.10 to me 4502 setup keep-state :default\n" +"00400 0 0 set 0 allow tcp from 203.0.113.10 to me 4504 setup keep-state :default\n" +"00500 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"00600 0 0 set 0 allow tcp from 203.0.113.10 to me 4508 setup keep-state :default\n" +"00700 0 0 set 0 allow tcp from 203.0.113.10 to me 4510 setup keep-state :default\n" +"00800 0 0 set 0 allow tcp from 203.0.113.10 to me 4512 setup keep-state :default\n" +"00900 0 0 set 0 allow tcp from 203.0.113.10 to me 4514 setup keep-state :default\n" +"#01000 1 60 set 0 skipto 1500 tcp from 203.0.113.10 to me#\n" +"01000 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"#01500 1 60 set 0 skipto 2000 tcp from 203.0.113.10 to me#\n" +"01600 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"#02000 1 60 set 0 skipto 2500 tcp from 203.0.113.10 to me#\n" +"02100 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"#02500 1 60 set 0 skipto 3000 tcp from 203.0.113.10 to me#\n" +"02600 0 0 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"#03000 8 475 set 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default#\n" +"65535 0 0 set 31 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1985 +msgid "See the section on Lists for additional caveats." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1987 +#, no-wrap +msgid "Divert" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:1996 +msgid "" +"The *divert* mechanism in *ipfw* allows *ipfw* to pull packets into user " +"space for programmatic purposes. indexterm:[keyword, divert] indexterm:" +"[divert] indexterm:[ipfw, divert] The *divert* rule snatches the packet and " +"presents it to a man:divert[4] socket, a special socket type that can be " +"created from an external program. indexterm:[divert, socket] See the " +"_divert.c_ program at the end of crossref:ipfw-appendix-b[appendix-b, " +"Appendix B] for the sample program used for this book. indexterm:[divert, " +"source code] Copy the `divert.c` program onto the *firewall* VM and compile " +"it with this command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2000 +#, no-wrap +msgid "# *make divert LDFLAGS=-lutil*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2004 +msgid "" +"The code should compile cleanly. If it does not, examine the file closely " +"to ensure it was copied correctly and retry the above command." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2008 +msgid "" +"Divert sockets can be used as the basis for many specialized applications " +"such as packet examination, in-flight packet modification, experimental " +"routing techniques, etc. The program shown here simply reads from the " +"socket and dumps the contents of the packet in hex and ASCII. It then " +"writes the packet back into the divert socket." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2011 +msgid "" +"To work with the *divert* keyword, the man:divert[4] packet diversion " +"mechanism has to be compiled into the kernel or loaded at runtime: indexterm:" +"[divert, example] indexterm:[module, ipdivert]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2016 +#, no-wrap +msgid "" +"# *kldload ipfw*\n" +"# *kldload ipdivert*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2019 +msgid "" +"This loads the *ipfw* firewall kernel module and the *ipdivert* kernel " +"module which provides man:divert[4] functionality." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2021 +msgid "" +"Once this is done, an application can open a man:divert[4] socket and " +"process packets." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2026 +#, no-wrap +msgid "" +"# *./divert*\n" +"Opening divert on port 700\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2028 +#, no-wrap +msgid "... (see below)\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2032 +msgid "" +"In another window, run man:netstat[1] to see the divert socket: indexterm:" +"[divert, view with netstat]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2048 +#, no-wrap +msgid "" +"# *netstat -an | more*\n" +"Active Internet connections (including servers)\n" +"Proto Recv-Q Send-Q Local Address Foreign Address (state)\n" +"tcp4 0 0 \\*.22 *.* LISTEN\n" +"tcp6 0 0 \\*.22 *.* LISTEN\n" +"udp4 0 0 \\*.514 *.*\n" +"udp6 0 0 \\*.514 *.*\n" +"#div4 0 0 \\*.700 *.*#\n" +"Active UNIX domain sockets\n" +"Address Type Recv-Q Send-Q Inode Conn Refs Nextref Addr\n" +"fffff80003b83000 stream 0 0 fffff80003cac5a0 0 0 0 /var/run/devd.pipe\n" +"fffff80003baf800 dgram 0 0 0 fffff80003bafc00 0 fff\n" +"...\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2052 +msgid "" +"To examine the *divert* operation, first create a suitable ruleset: " +"indexterm:[divert, ruleset]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2062 +#, no-wrap +msgid "" +"# *ipfw add 700 divert #700# ip from any to any*\n" +"#\n" +"# *ipfw add 1000 allow udp from 203.0.113.10 to me*\n" +"01000 allow udp from 203.0.113.10 to me\n" +"#\n" +"# *ipfw add 1100 allow udp from me to 203.0.113.10*\n" +"01100 allow udp from me to 203.0.113.10\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2068 +msgid "" +"The syntax is a bit odd in this case. The divert keyword takes a number " +"argument that functions as the divert object. indexterm:[divert, object] " +"This is similar syntax to *pipes*, *queues*, and *NAT* (network address " +"translation) rules which are discussed later." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2071 +msgid "" +"A common convention, though not required, is to make the *divert* port the " +"same number as the rule number in the ruleset. Whatever the rule number, " +"when the packet is diverted and processed, and then returned to *ipfw*, the " +"firewall picks up the packet at the divert rule number, plus one - that is, " +"the next rule." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2079 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00700 divert 700 ip from any to any\n" +"01000 allow udp from 203.0.113.10 to me\n" +"01100 allow udp from me to 203.0.113.10\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2085 +msgid "" +"Examine the ruleset above. The packet is diverted to a divert socket, port " +"700 at the first rule. When it is returned from the _divert.c_ program, it " +"renters the ruleset at rule 1000. The ruleset allows UDP packets from and " +"to the *external1* VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2089 +msgid "" +"To test, set up the *firewall* VM host to run *userv3.sh* and the " +"*external1* VM host to run *ucon.sh 5656*. This results in the following " +"expected output from the divert program: indexterm:[divert, execution]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2100 +#, no-wrap +msgid "" +"# *./divert*\n" +"Opening divert on port 700\n" +"203.0.113.10:51417 -> 203.0.113.50:5656\n" +"|0000 45 00 00 46 a9 0c 00 00 40 11 65 3e ac 10 0a 0a |E..F....@.e>....|\n" +"|0010 ac 10 0a 32 c8 d9 16 18 00 32 a2 eb 55 44 50 20 |...2.....2..UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 34 5d 0a |],[4]. |\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2104 +msgid "" +"And the output from *userv3.sh* also shows on the *firewall* console: " +"indexterm:[userv3.sh]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2110 +#, no-wrap +msgid "" +"# *sh userv3.sh*\n" +"Starting UDP listeners on [5656],[5657],[5658]\n" +"UDP communication from [203.0.113.10],[5656],[1]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2115 +msgid "" +"Next, shut down the *userv3.sh* services on the *firewall* VM. The incoming " +"packets find no open port and are rejected by the *firewall* VM host. " +"However, they still go through the divert socket:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2135 +#, no-wrap +msgid "" +"# *./divert*\n" +"Opening divert on port 700\n" +"203.0.113.10:26058 -> 203.0.113.50:5656\n" +"|0000 45 00 00 47 a9 12 00 00 40 11 65 37 ac 10 0a 0a |E..G....@.e7....|\n" +"|0010 ac 10 0a 32 65 ca 16 18 00 33 28 a9 55 44 50 20 |...2e....3(.UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 31 30 5d 0a |],[10]. |\n" +"203.0.113.50:771 -> 203.0.113.10:27038\n" +"|0000 45 00 00 63 3a 61 00 00 40 01 65 37 ac 10 0a 32 |E..c:a..@.e7...2|\n" +"|0010 ac 10 0a 0a 03 03 69 9e 00 00 00 00 45 00 00 47 |......i.....E..G|\n" +"|0020 a9 12 00 00 40 11 65 37 ac 10 0a 0a ac 10 0a 32 |....@.e7.......2|\n" +"|0030 65 ca 16 18 00 33 28 a9 55 44 50 20 70 61 63 6b |e....3(.UDP pack|\n" +"|0040 65 74 20 66 72 6f 6d 20 5b 31 37 32 2e 31 36 2e |et from [172.16.|\n" +"|0050 31 30 2e 31 30 5d 2c 5b 35 36 35 36 5d 2c 5b 31 |10.10],[5656],[1|\n" +"|0060 30 5d 0a |0]. |\n" +"#divert: sendto: Permission denied#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2141 +msgid "" +"The last output line, \"Permission denied\", is because the kernel, faced " +"with a packet and no port to send it to, instead sends an ICMP port " +"unreachable response back to the sender. indexterm:[divert, permission " +"denied] The kernel sends the ICMP packet back out the divert port, but there " +"is no *ipfw* rule for it to re-enter the firewall - thus \"Permission " +"denied\". The packet is dropped." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2143 +msgid "To fix, add a rule for ICMP traffic in either direction:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2152 +#, no-wrap +msgid "" +"# *ipfw list*\n" +"00700 divert 700 ip from any to any\n" +"#00800 allow icmp from any to any#\n" +"01000 allow udp from 203.0.113.10 to me\n" +"01100 allow udp from me to 203.0.113.10\n" +"65535 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2157 +msgid "" +"The *divert* operation now works as expected and the packet re-enters the " +"firewall after rule 700. The next rule (800) permits ICMP in either " +"direction and the packet is sent back to the source host. In the listings " +"below, the *ucon.sh* script was run for 5 cycles, and after cycle #3, the " +"firewall *userv3.sh* script was shut down." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2159 +msgid "" +"The remaining two cycles result in an ICMP message being returned back to " +"the *external1* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2211 +#, no-wrap +msgid "" +"# *./divert*\n" +"Opening divert on port 700\n" +"203.0.113.10:36083 -> 203.0.113.50:5656\n" +"|0000 45 00 00 46 a9 20 00 00 40 11 65 2a ac 10 0a 0a |E..F. ..@.e*....|\n" +"|0010 ac 10 0a 32 8c f3 16 18 00 32 de d4 55 44 50 20 |...2.....2..UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 31 5d 0a |],[1]. |\n" +"203.0.113.10:25662 -> 203.0.113.50:5656\n" +"|0000 45 00 00 46 a9 21 00 00 40 11 65 29 ac 10 0a 0a |E..F.!..@.e)....|\n" +"|0010 ac 10 0a 32 64 3e 16 18 00 32 07 89 55 44 50 20 |...2d>...2..UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 32 5d 0a |],[2]. |\n" +"203.0.113.10:40345 -> 203.0.113.50:5656\n" +"|0000 45 00 00 46 a9 22 00 00 40 11 65 28 ac 10 0a 0a |E..F.\"..@.e(....|\n" +"|0010 ac 10 0a 32 9d 99 16 18 00 32 ce 2c 55 44 50 20 |...2.....2.,UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 33 5d 0a |],[3]. |\n" +"203.0.113.10:53482 -> 203.0.113.50:5656\n" +"|0000 45 00 00 46 a9 23 00 00 40 11 65 27 ac 10 0a 0a |E..F.x..@.e'....|\n" +"|0010 ac 10 0a 32 d0 ea 16 18 00 32 9a da 55 44 50 20 |...2.....2..UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 34 5d 0a |],[4]. |\n" +"#203.0.113.50:771 -> 203.0.113.10:27037 (ICMP packet)#\n" +"|0000 45 00 00 62 3a 68 00 00 40 01 65 27 ac 10 0a 32 |E..b:h..@.e'...2|\n" +"|0010 ac 10 0a 0a 03 03 69 9d 00 00 00 00 45 00 00 46 |......i.....E..F|\n" +"|0020 a9 23 00 00 40 11 65 27 ac 10 0a 0a ac 10 0a 32 |.x..@.e'.......2|\n" +"|0030 d0 ea 16 18 00 32 9a da 55 44 50 20 70 61 63 6b |.....2..UDP pack|\n" +"|0040 65 74 20 66 72 6f 6d 20 5b 31 37 32 2e 31 36 2e |et from [172.16.|\n" +"|0050 31 30 2e 31 30 5d 2c 5b 35 36 35 36 5d 2c 5b 34 |10.10],[5656],[4|\n" +"|0060 5d 0a |]. |\n" +"203.0.113.10:35359 -> 203.0.113.50:5656\n" +"|0000 45 00 00 46 a9 24 00 00 40 11 65 26 ac 10 0a 0a |E..F.$..@.e&....|\n" +"|0010 ac 10 0a 32 8a 1f 16 18 00 32 e1 a4 55 44 50 20 |...2.....2..UDP |\n" +"|0020 70 61 63 6b 65 74 20 66 72 6f 6d 20 5b 31 37 32 |packet from [172|\n" +"|0030 2e 31 36 2e 31 30 2e 31 30 5d 2c 5b 35 36 35 36 |.16.10.10],[5656|\n" +"|0040 5d 2c 5b 35 5d 0a |],[5]. |\n" +"#203.0.113.50:771 -> 203.0.113.10:27037 (ICMP packet)#\n" +"|0000 45 00 00 62 3a 69 00 00 40 01 65 26 ac 10 0a 32 |E..b:i..@.e&...2|\n" +"|0010 ac 10 0a 0a 03 03 69 9d 00 00 00 00 45 00 00 46 |......i.....E..F|\n" +"|0020 a9 24 00 00 40 11 65 26 ac 10 0a 0a ac 10 0a 32 |.$..@.e&.......2|\n" +"|0030 8a 1f 16 18 00 32 e1 a4 55 44 50 20 70 61 63 6b |.....2..UDP pack|\n" +"|0040 65 74 20 66 72 6f 6d 20 5b 31 37 32 2e 31 36 2e |et from [172.16.|\n" +"|0050 31 30 2e 31 30 5d 2c 5b 35 36 35 36 5d 2c 5b 35 |10.10],[5656],[5|\n" +"|0060 5d 0a |]. |\n" +"^C\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2214 +msgid "Note the two icmp packets logged by rule 800:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2223 +#, no-wrap +msgid "" +"# *ipfw show*\n" +"00700 19 2466 divert 700 ip from any to any\n" +"#00800 2 196 allow icmp from any to any#\n" +"01000 5 350 allow udp from 203.0.113.10 to me\n" +"01100 0 0 allow udp from me to 203.0.113.10\n" +"65535 477 114991 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2227 +#, no-wrap +msgid "" +"*General notes on the divert action*:\n" +"indexterm:[divert, general notes]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2229 +msgid "" +"The *ipdivert.ko* kernel module must be loaded or compiled into the kernel " +"to create a divert rule, and thus to use man:divert[4] sockets." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2231 +msgid "" +"The *ipdivert.ko* kernel module cannot be unloaded. indexterm:[module, " +"ipdivert]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2232 +msgid "Restart the VM to remove the *ipdivert.ko* kernel module." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2234 +msgid "" +"It is not possible to create a rule with a divert port of 0 or 65535. The " +"port number must be between 1 and 65534 (inclusive)." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2235 +msgid "" +"If creating a rule with a divert port on rule 65534, the returning packet " +"will restart firewall rule processing at the default rule, 65535, which " +"cannot be changed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2236 +msgid "" +"A divert rule can be created for any protocol in [.filename]#/etc/protocols#." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2237 +msgid "The same divert port can be used for multiple rules." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2239 +msgid "" +"After returning from a divert rule, if the next rule is in another set, " +"processing will continue with that rule unless the set is disabled. If " +"disabled, it will skip to the next rule in any set that is not disabled." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2242 +#, no-wrap +msgid "" +"*General notes on creating the divert socket*:\n" +"indexterm:[divert, socket notes]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2244 +msgid "Only root can create a divert socket." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2245 +msgid "" +"Opening a divert socket on port 0 or port 65536 results in a random divert " +"port number." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2246 +msgid "Opening a divert socket on port 65535 is permitted, but not advised." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2247 +msgid "" +"Opening a divert port greater than 65536 or less than 0 results in a " +"positive port number modulo 65536." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2249 +msgid "" +"As with other sockets, it is not possible to open two divert sockets on the " +"same port number. However, it is possible to open a divert socket on a port " +"already in use for any protocols based on IPv4 or IPv6." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2251 +#, no-wrap +msgid "Other Protocols" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2255 +msgid "" +"Any protocol in [.filename]#/etc/protocols# may be used in a rule. " +"indexterm:[protocol, other examples]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2261 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow ospf from any to me*\n" +"# *ipfw add 2000 allow chaos from any to me*\n" +"etc.\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2263 +#, no-wrap +msgid "Limit" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2270 +#, no-wrap +msgid "" +"*ipfw* can restrict the number of active connections with the *limit* option.\n" +"indexterm:[keyword, limit] indexterm:[limit]\n" +"This option allows for specifying a parameter in the rule that is regarded as a flow element, that is, one of `src-addr`, `src-port`, `dst-addr`, or `dst-port`.\n" +"indexterm:[limit, flow element]\n" +"In addition, the *limit* keyword takes a value, N, that is the maximum number of connections desired:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2275 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow udp from any to me limit src-addr 5*\n" +"# *ipfw add 1100 count udp from any to me*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2278 +msgid "" +"Concurrent connections via TCP, UDP, ICMP, or any protocol can be limited in " +"this way." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2281 +#, no-wrap +msgid "" +"*ipfw* creates a dynamic rule for each connection allowed by the rule.\n" +"When the maximum number of connections is reached, additional packets are considered no longer matched and are dropped by the rule after being counted, and the search terminates.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2284 +msgid "" +"To test, write the following simple script on the *external1* VM to flood " +"UDP packets at the *firewall* VM running *sh userv3.sh*: indexterm:[limit, " +"example] indexterm:[userv3.sh] indexterm:[ncat]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2293 +#, no-wrap +msgid "" +"# *export NUM=1*\n" +"# *for i in \\`jot -r 500 5656 5658 1`*\n" +"> *do*\n" +"> *echo \"hello [$NUM] to port [$i]\" | ncat -u 203.0.113.50 $i*\n" +"> *NUM=`expr $NUM + 1`*\n" +"> *done*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2302 +msgid "" +"On the *firewall* VM, *ipfw* starts creating dynamic rules as soon as the " +"first matching packet is received. Additional dynamic rules, up to the " +"*limit* number are created. Each UDP based dynamic rule has a default 10 " +"second lifetime, controlled by the sysctl node `net.inet.ip.fw." +"dyn_udp_lifetime`. indexterm:[sysctl, net.inet.ip.fw.dyn_udp_lifetime] As " +"they expire under the limit value, space for additional connections is " +"created. The number of open dynamic rules at any point in time can be " +"viewed with the sysctl node `net.inet.ip.fw.dyn_count`. indexterm:[sysctl, " +"net.inet.ip.fw.dyn_count]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2305 +msgid "View the dynamic rules with: indexterm:[ipfw, -SaD]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2317 +#, no-wrap +msgid "" +"# *ipfw -SaD list*\n" +"00500 0 0 check-state :default\n" +"01000 10 531 allow udp from 203.0.113.10 to me limit src-addr 3 :default\n" +"65535 0 0 deny ip from any to any\n" +"## Dynamic rules (4 560):\n" +"01000 1 53 (8s) LIMIT udp 203.0.113.10 23755 <-> 203.0.113.50 5657 :default\n" +"01000 1 53 (8s) LIMIT udp 203.0.113.10 30144 <-> 203.0.113.50 5656 :default\n" +"01000 0 0 (4s) PARENT 3 udp 203.0.113.10 0 <-> 0.0.0.0 0 :default\n" +"01000 1 53 (8s) LIMIT udp 203.0.113.10 22722 <-> 203.0.113.50 5658 :default\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2322 +msgid "" +"Running *cmdwatch -n1 ipfw -SaD list* on the *firewall* VM will show the " +"list of rules grow and shrink in real time." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2325 +msgid "indexterm:[cmdwatch]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2328 +msgid "" +"It is useful to experiment with the sysctl `net.inet.ip.fw.dyn_udp_lifetime` " +"and see its effect on `net.inet.ip.fw.dyn_count`. By adjusting the `net." +"inet.ip.fw.dyn_udp_lifetime` value during a network packet flood (like that " +"above), it is possible to watch how the *ipfw limit* rule blocked traffic " +"through the firewall." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2332 +msgid "" +"Here is the result of a sample run. indexterm:[limit, sample run] Note the " +"missing connections due to a limit restriction:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2351 +#, no-wrap +msgid "" +"...\n" +"hello [19] to port [5657]\n" +"hello [20] to port [5656]\n" +"hello [21] to port [5656]\n" +"hello [33] to port [5657]\n" +"hello [34] to port [5656]\n" +"hello [35] to port [5657]\n" +"hello [36] to port [5657]\n" +"hello [37] to port [5657]\n" +"hello [48] to port [5657]\n" +"hello [50] to port [5657]\n" +"hello [51] to port [5656]\n" +"hello [52] to port [5657]\n" +"hello [53] to port [5656]\n" +"hello [64] to port [5657]\n" +"...\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2353 +#, no-wrap +msgid "Call and Return" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2359 +msgid "" +"The *call* and *return* actions allows *ipfw* to change ruleset processing " +"by jumping to a rule number elsewhere in the ruleset. indexterm:[keyword, " +"call] indexterm:[keyword, return] indexterm:[call/return] If the rules at " +"that location contain a *return* action, processing will jump back to the " +"statement immediately after the original call statement. In practice, this " +"acts like a program function call, or as man:ipfw[8] notes, like an assembly " +"language subroutine." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2362 +msgid "" +"Creating a ruleset with *call* and *return* actions: indexterm:[call/return, " +"example]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2392 +#, no-wrap +msgid "" +"#\n" +"# *ipfw add 500 check-state*\n" +"00500 check-state :default\n" +"#\n" +"# *ipfw add 1000 call 20000 udp from 203.0.113.10 to me 5656*\n" +"01000 call 20000 udp from 203.0.113.10 to me 5656\n" +"#\n" +"# *ipfw add 1100 count udp from 203.0.113.10 to me*\n" +"01100 count udp from 203.0.113.10 to me\n" +"#\n" +"# *ipfw add 1200 allow udp from 172.168.10.10 to me 5656*\n" +"01200 allow udp from 203.0.113.10 to me 5656\n" +"#\n" +"# *ipfw add 20000 count udp from 203.0.113.10 to me*\n" +"20000 count udp from 203.0.113.10 to me\n" +"#\n" +"# *ipfw add 21000 return via any*\n" +"21000 return\n" +"#\n" +"# *ipfw -a list*\n" +"00500 0 0 check-state :default\n" +"01000 0 0 call 20000 udp from 203.0.113.10 to me 5656\n" +"01100 0 0 count udp from 203.0.113.10 to me\n" +"01200 0 0 allow udp from 203.0.113.10 to me 5656\n" +"20000 0 0 count udp from 203.0.113.10 to me\n" +"21000 0 0 return\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2396 +msgid "" +"As noted in the man page, some extra syntactic sugar on the return statement " +"is required: indexterm:[call/return, syntax]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2400 +#, no-wrap +msgid "# *ipfw add 21000 return #via any#*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2403 +msgid "" +"In this example several count statements are used to try to trace ruleset " +"processing." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2408 +msgid "" +"To test, have the *firewall* VM host startup 3 listeners with *userv3.sh*. " +"indexterm:[userv3.sh] After the *external1* VM uses *ucon.sh 5656* to send a " +"udp packet, the count list looks like this: indexterm:[call/return, example]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2419 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"00500 0 0 check-state :default\n" +"01000 1 70 call 20000 udp from 203.0.113.10 to me 5656\n" +"01100 1 70 count udp from 203.0.113.10 to me\n" +"01200 1 70 allow udp from 203.0.113.10 to me 5656\n" +"20000 1 70 count udp from 203.0.113.10 to me\n" +"21000 1 70 return via any\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2424 +msgid "" +"The packet was matched at rule 1000 where it encountered a *call* action to " +"jump to rule 20000 where it was then matched at 20000. The next rule was a " +"matched *return* action at rule 21000. Returning to the rule after the " +"*call* action, it matched a *count* action at 1100, then matched an *allow* " +"action at 1200 where it was sent through to the application layer and was " +"received by *userv3.sh*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2426 +msgid "" +"If the *return* action at rule 21000 is removed, the counts look much " +"different:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2436 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"00500 0 0 check-state :default\n" +"01000 1 70 call 20000 udp from 203.0.113.10 to me 5656\n" +"01100 0 0 count udp from 203.0.113.10 to me\n" +"01200 0 0 allow udp from 203.0.113.10 to me 5656\n" +"20000 1 70 count udp from 203.0.113.10 to me\n" +"65535 1 70 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2440 +msgid "" +"Without a *return* at rule 21000, the only rule left is the default *deny* " +"rule, and there is nothing received by *userv3.sh*. indexterm:[userv3.sh]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2444 +msgid "" +"Because rules can jump both forward and backward with the *call* action, it " +"is possible to create an endless loop." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2447 +msgid "indexterm:[call/return, endless loop]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2449 +msgid "This example creates an endless loop with in incorrect *call* rule:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2459 +#, no-wrap +msgid "" +"#\n" +"# *ipfw -a list*\n" +"01000 0 0 count udp from 203.0.113.10 to me\n" +"05000 0 0 check-state :default\n" +"#06000 0 0 call 1000 udp from 203.0.113.10 to me 5656#\n" +"07000 0 0 count udp from 203.0.113.10 to me\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2465 +msgid "" +"This example is missing a *return* action between rule 1000, the target of " +"the *call* action at rule 6000. This creates a loop. *ipfw* eventually " +"figures out that a loop exists, and breaks out at the next call action with " +"the diagnostic: indexterm:[call/return, error]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2469 +#, no-wrap +msgid "# #ipfw: call stack error, go to next rule#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2472 +msgid "" +"but it does not currently note *_where_* the missing *return* action is or " +"which rule it went to next." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2475 +msgid "" +"It is possible to pick up a clue by watching the rule counts. Below is the " +"rule count for this errant ruleset after just one packet was received from " +"the *external1* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2485 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"01000 17 1207 count udp from 203.0.113.10 to me\n" +"05000 0 0 check-state :default\n" +"#06000 16 1136 call 1000 udp from 203.0.113.10 to me 5656#\n" +"07000 1 71 count udp from 203.0.113.10 to me\n" +"65535 1 71 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2488 +msgid "" +"This shows that *ipfw* went around this *call* loop 16 times before throwing " +"an error." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2491 +msgid "" +"For TCP connections, call and return operate almost the same. Below is a " +"ruleset with TCP instead of UDP for the desired protocol and including the " +"required *setup* and *keep-state* keywords:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2502 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"00500 0 0 check-state :default\n" +"01000 0 0 call 20000 tcp from 203.0.113.10 to me 5656\n" +"01100 0 0 count tcp from 203.0.113.10 to me\n" +"02000 0 0 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"20000 0 0 count tcp from 203.0.113.10 to me\n" +"21000 0 0 return\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2505 +msgid "" +"After the connection is successfully made from external1, the observed " +"counts are:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2516 +#, no-wrap +msgid "" +"# *ipfw -a list*\n" +"00500 0 0 check-state :default\n" +"01000 1 60 call 20000 tcp from 203.0.113.10 to me 5656\n" +"01100 1 60 count tcp from 203.0.113.10 to me\n" +"02000 8 479 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"20000 1 60 count tcp from 203.0.113.10 to me\n" +"21000 1 60 return\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2523 +msgid "" +"The difference in rule counts is due to dynamic rules created by the *setup* " +"and *keep-state* keywords on rule 2000. Counts can also be shown with the `-" +"d` command line parameter. indexterm:[ipfw, -d] The numbers below are from " +"just the initial 3-way handshake: indexterm:[TCP, 3-way handshake]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2536 +#, no-wrap +msgid "" +"# *ipfw -ad list*\n" +"00500 0 0 check-state :default\n" +"01000 1 60 call 20000 tcp from 203.0.113.10 to me 5656\n" +"01100 1 60 count tcp from 203.0.113.10 to me\n" +"02000 5 276 allow tcp from 203.0.113.10 to me 5656 setup keep-state :default\n" +"20000 1 60 count tcp from 203.0.113.10 to me\n" +"21000 1 60 return\n" +"65535 0 0 deny ip from any to any\n" +"## Dynamic rules (1 152):\n" +"02000 5 276 (296s) STATE tcp 203.0.113.10 19179 <-> 203.0.113.50 5656 :default\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2539 +msgid "" +"The above numbers indicate that the 3-way handshake occurred during the " +"dynamic rule setup." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2542 +#, no-wrap +msgid "" +"*General notes on call and return:*\n" +"indexterm:[call/return, general notes]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2544 +#, no-wrap +msgid "*ipfw* allows a *call* out to an address either before or after the current rule.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2545 +#, no-wrap +msgid "There must be a *return* for every *call*.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2547 +#, no-wrap +msgid "" +"*call* / *return* pairs can be nested up to 16 levels deep.\n" +"If *ipfw* sees one more *call* rule, it will throw the \"call stack error, go to next rule\" error and continue with the next rule.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2549 +#, no-wrap +msgid "" +"Similar to *skip-to*, a *call* to rule 0, 65535, or 65536 is an error.\n" +"If there is a *call* to a value greater then 65536, the rule is accepted and the call target rule number is the requested value modulo 65536.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2550 +#, no-wrap +msgid "Similar also to *sets*, if a *call* is made to a target rule in a set that is disabled, the call will land on the next non-disabled rule in any set and processing continues from there.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2551 +#, no-wrap +msgid "If a *return* is encountered when no *call* has been made, the *return* rule is ignored and processing continues with the next rule.\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2552 +#, no-wrap +msgid "Using uid and gid in rules" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2558 +msgid "" +"An interesting capability of *ipfw* is its ability to match packets on Unix " +"*uid* and *gid* values. indexterm:[keyword, uid] indexterm:[keyword, gid] " +"indexterm:[uid/gid] Network packets themselves have no inherent ownership, " +"so where does this capability come from? Answer - it comes from the " +"applications that are the source and destination of those packets." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2562 +msgid "" +"Below is a simple example to examine this capability. indexterm:[uid/gid, " +"example] First, take note of the actual syntax that allows this matching " +"capability." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2566 +#, no-wrap +msgid "Locate or add a user (here 'quarven') if needed:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2569 +#, no-wrap +msgid "" +"# *grep quarven /etc/passwd*\n" +"quarven:*:1002:1002:Quarven:/home/quarven:/bin/sh\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2572 +#, no-wrap +msgid "" +"Copy userv.sh to user *quarven* home directory\n" +"# *cp ~/bin/userv.sh /home/quarven*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2574 +#, no-wrap +msgid "Now use userid 'quarven' in an *ipfw* rule:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2581 +#, no-wrap +msgid "" +"# *ipfw add 700 allow udp from 203.0.113.10 to me #uid quarven#*\n" +"00700 allow udp from 203.0.113.10 to me uid quarven\n" +"#\n" +"# *ipfw show*\n" +"00700 0 0 allow udp from 203.0.113.10 to me uid quarven\n" +"65535 0 0 deny ip from any to any\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2586 +msgid "" +"Next, login as user 'quarven' and run the script [.filename]#/root/bin/userv." +"sh 5656#. Then switch to the *external1* VM and run *echo \"hello there\" | " +"ncat -u 203.0.113.50 5656*. The results should appear on the console " +"running the *userv.sh* script." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2588 +msgid "The results are shown below." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2596 +#, no-wrap +msgid "" +"quarven@firewall:~ $ */bin/sh userv.sh 5656*\n" +"PORT1 = [5656]\n" +"Starting UDP listener on [203.0.113.50],[5656]\n" +"hello there\n" +"^Cquarven@firewall:~ $\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2600 +msgid "" +"This works because the instance of *userv.sh* is run under the *uid* quarven " +"as shown below: indexterm:[userv.sh] indexterm:[uid/gid, usage]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2604 +#, no-wrap +msgid "Show the user information for the *userv.sh* instance:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2610 +#, no-wrap +msgid "" +"root@firewall:~ # ps -o user -xl -U quarven\n" +"USER UID PID PPID C PRI NI VSZ RSS MWCHAN STAT TT TIME COMMAND\n" +"quarven 1002 4256 83703 0 61 0 13380 2908 pause I+ v0 0:00.03 sh userv.sh 5656\n" +"#quarven 1002 6878 4256 0 61 0 13400 2344 select I+ v0 0:00.02 nc -l -k -u 203.0.113.50 5656#\n" +"quarven 1002 83703 83431 0 20 0 13380 3168 wait I v0 0:00.10 -sh (sh)\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2614 +#, no-wrap +msgid "" +"*ipfw* has matched an incoming network packet to a program owned by a userid.\n" +"If the rule is changed to another userid, even *root*, the match will not succeed and the packet will be picked up by the default rule.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2620 +msgid "" +"It is sometimes necessary to immediately shut down all IP traffic to or from " +"a certain user. This capability is ideal for that purpose. Note however, " +"that the *deny* rule below must come *before any check-state rule* to catch " +"traffic that may be otherwise allowed by a dynamic rule." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2625 +#, no-wrap +msgid "" +"# #*ipfw add 50 deny ip from any to any uid quarven*#\n" +"# *ipfw add 100 check-state*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2627 +#, no-wrap +msgid "Note also the item about ICMP traffic in the \"General Notes\" below.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2632 +#, no-wrap +msgid "" +"*General Notes on Using **uid** and **gid**:*\n" +"indexterm:[uid/gid, general notes]\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2634 +msgid "" +"The *gid* keyword works in an identical fashion to *uid* described above." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2635 +msgid "" +"If using a name as the *uid* or *gid*, the name must exist in the indicated " +"system file." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2637 +msgid "" +"Ranges and lists are not allowed. For example, *ipfw* does now allow \"... " +"*uid* tom,dick,harry\" or \"... *uid* 1000-1002\"." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2638 +msgid "" +"Outbound traffic works in a similar way, just reversing the source and " +"destination." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2639 +msgid "" +"Denied traffic will generally have an indication of \": sendto: " +"Permission denied\"" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2642 +msgid "" +"ICMP traffic cannot be reliably filtered using *uid/gid*. indexterm:[uid/" +"gid, ICMP issue] This is a known limitation." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2643 +msgid "" +"As noted in man:ipfw[8] some contexts, such as initial incoming SYN packets " +"may have no *uid/gid* associated with them." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2644 +msgid "" +"Programs using *setuid(2)* system calls may not behave as expected, though " +"it may be possible to set the *uid/gid* to the effective id if it can be " +"determined." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2645 +msgid "" +"Using *uid/gid* keywords for matching is resource intensive and should be " +"used sparingly if at all." +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2647 +#, no-wrap +msgid "Lookup Tables" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2650 +msgid "indexterm:[lookup table]" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2656 +msgid "" +"Lookup tables are a versatile feature of many firewall systems, including " +"*ipfw*. A lookup table is a virtual container that holds tuples of " +"elements, one of which is a key that functions as a fast lookup feature. " +"indexterm:[keyword, lookup] indexterm:[lookup, value] indexterm:[lookup, " +"key] Using a key provided by a rule, *ipfw* can quickly determine if the " +"element is in the table. If it is, that portion of the rule is matched the " +"value associated with the key is used according to the rule." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2658 +msgid "" +"Lookup tables are a powerful feature of *ipfw* and useful in many situations." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2661 +#, no-wrap +msgid "" +"*ipfw* provides five types of lookup tables:\n" +"indexterm:[lookup table, types]\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2666 +#, no-wrap +msgid "" +"*Address tables (addr)* - These tables hold addresses that *ipfw* can rapidly find with an address as a key.\n" +"indexterm:[lookup table, addr]\n" +"If the address is matched the lookup is considered matched and used by the associated rule.\n" +"This table type takes an additional keyword 'valtype' that can be used to specify IPv4 addresses or IPv6 addresses.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2670 +#, no-wrap +msgid "" +"*Interface tables (iface)* - These tables hold interface names.\n" +"indexterm:[lookup table, iface]\n" +"Each entry is the name of an interface.\n" +"Note that wildcards such as `em*` are *not* supported.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2674 +#, no-wrap +msgid "" +"*Number tables (number)* - These tables are used for protocols, ports, uids/gids, or jail ids.\n" +"indexterm:[lookup table, number]\n" +"Entries are 32 bit unsigned integers.\n" +"Ranges (for example,1234-5678) are *not* supported.\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2676 +#, no-wrap +msgid "" +"*Flow tables (flow)* - These tables contain flow type suboptions that are used in looking up existing traffic flows.\n" +"indexterm:[lookup table, flow]\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2679 +#, no-wrap +msgid "" +"*MAC* - A MAC address type table holds media access control (MAC) addresses as an address with optional mask length.\n" +"indexterm:[lookup table, MAC]\n" +"The mask length defaults to 48 bits if not otherwise specified.\n" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2680 +#, no-wrap +msgid "Creating Lookup Tables" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2685 +msgid "" +"All tables must be created before they can be referenced by a rule. Note " +"that the commands to manage tables do not have line numbers - they are " +"independent shell commands that exist outside the ruleset. indexterm:" +"[lookup table, create] indexterm:[keyword, table]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2689 +#, no-wrap +msgid "# *ipfw table foo create*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2693 +msgid "" +"By default, the *ipfw table create* command creates tables of type *addr*. " +"Table names share the same namespace and so must be unique even among tables " +"of different types." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2695 +msgid "To specify other types, add the type keyword:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2703 +#, no-wrap +msgid "" +"# *ipfw table bar create type iface*\n" +"#\n" +"# *ipfw table baz create type flow*\n" +"#\n" +"# *ipfw table bop create type number*\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2709 +msgid "" +"Previously, when creating a table of type number, a bug existed that " +"required an algorithm option such as `number:array`. This bug was fixed and " +"documented link:https://bugs.freebsd.org/bugzilla/show_bug.cgi?" +"id=233072#c1[here]." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2714 +msgid "" +"To see all tables, use the *list* subcommand to show the table and any " +"contents. indexterm:[keyword, table] Shown below, all four table types are " +"created and one entry is added to each table:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2757 +#, no-wrap +msgid "" +"# *ipfw table all list*\n" +"#\n" +"# *ipfw table foo create type addr*\n" +"# *ipfw table foo add 192.168.1.100 33*\n" +"added: 192.168.1.100/32 33\n" +"#\n" +"# *ipfw table bar create type iface*\n" +"# *ipfw table bar add em0 33*\n" +"added: em0 33\n" +"#\n" +"# *ipfw table baz create type number*\n" +"# *ipfw table baz add 9999 33*\n" +"added: 9999 33\n" +"#\n" +"# *ipfw table bop create type flow*\n" +"# *ipfw table bop add 203.0.113.10,192.168.1.100 33*\n" +"#ignored: 33#\n" +"#ipfw: Adding record failed: Invalid argument#\n" +"#\n" +"# *ipfw table bop destroy*\n" +"#\n" +"# *ipfw table bop create type flow:src-ip,dst-ip*\n" +"# *ipfw table bop add 203.0.113.10,192.168.1.100 33*\n" +"added: 203.0.113.10,192.168.1.100 33\n" +"#\n" +"# *ipfw table bip create type mac*\n" +"# *ipfw table bit add 58:9c:fc:01:02:03 33*\n" +"added: 58:9c:fc:01:02:03/48 33\n" +"#\n" +"# *ipfw table all list*\n" +"--- table(bar), set(0) ---\n" +"em0 33\n" +"--- table(baz), set(0) ---\n" +"9999 33\n" +"--- table(bip), set(0) ---\n" +"58:9c:fc:01:02:03/48 33\n" +"--- table(bop), set(0) ---\n" +"203.0.113.10,192.168.1.100 33\n" +"--- table(foo), set(0) ---\n" +"192.168.1.100/32 33\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2763 +msgid "" +"Note the error on the flow table above. indexterm:[lookup table, flow] Flow " +"tables take an explicit flow specification (discussed below) when they are " +"created. When trying to add an entry to a flow table that does not match " +"the flow specification, *ipfw* throws an error." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2768 +msgid "" +"Note that the output list of tables is ordered by table _name_, not table " +"_type_. This is worth remembering when using many tables of different types." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2775 +msgid "" +"In all the examples above a key and a value were added to each table. " +"indexterm:[table, value] The key was added according to the table type " +"(addr, iface, etc.) The values above, all set to the integer value 33, are " +"just placeholders in the examples. The _value_ for each key is whatever " +"makes sense for the firewall administrator." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2790 +msgid "" +"\"Whatever makes sense\" depends on how the table will be used. indexterm:" +"[lookup table, uses] man:ipfw[8] identifies some 12 different uses for table " +"values - *skipto* rule number to skip to, *pipe* number, *fib* number, *nat* " +"number to jump to, *dscp* value to match or set, *tag* number to match or " +"set, *divert* port number to divert traffic to, *netgraph* hook number to " +"move packet to, *limit* maximum number of connections, *ipf4* ipv4 next hop " +"to forward packets to, *ipv6* ipv6 next hop to forward packets to, *mark* " +"value to match or set." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2792 +msgid "" +"Some of these keywords have already been studied, and will return to assist " +"with table operations." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2795 +msgid "" +"Tables can be removed one at a time with the *destroy* subcommand, provided " +"the table is not used in any rule: indexterm:[table, destroy]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2799 +#, no-wrap +msgid "# *ipfw table bar destroy*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2802 +msgid "or removed all at once by specifying the special name all:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2806 +#, no-wrap +msgid "# *ipfw table all destroy*\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2811 +msgid "" +"Note that there is *_no confirmation_* with the *ipfw table all destroy* " +"command as there is with the *ipfw flush* command, so make sure that is the " +"correct command." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2813 +#, no-wrap +msgid "Using Tables in Rules" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2817 +msgid "" +"To begin using tables in rules, it is first necessary to understand the use " +"of the word 'tablearg' which is frequently found in man:ipfw[8]. indexterm:" +"[keyword, tablearg] indexterm:[tablearg]" +msgstr "" + +#. type: Title ==== +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2819 +#, no-wrap +msgid "Understanding the Word *tablearg*" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2823 +msgid "" +"A *tablearg* is a value that is the result of a table lookup using a key " +"supplied by a field in a packet. Which field depends on the table type, as " +"discussed above." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2826 +msgid "" +"The term *tablearg* is used to show where in the rule the retrieved value " +"will be applied. indexterm:[tablearg, example]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2828 +#, no-wrap +msgid "*tablearg* Keyword Used in a Rule" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2829 +#, no-wrap +msgid "*tablearg* Keyword Used in a Rule. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2829 +#, no-wrap +msgid "ipfw-rules060.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2832 +msgid "For a rule with a tablearg keyword, *ipfw*" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2835 +msgid "" +"Looks up the key in the identified table. The key is supplied by one or " +"more fields in the packet itself." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2836 +msgid "" +"Applies the value associated with that key in the table to replace the word " +"*tablearg*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2838 +msgid "Essentially" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2842 +#, no-wrap +msgid "# *ipfw add 50 skipto tablearg ip from 'table(badhosts)' to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2845 +msgid "becomes" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2849 +#, no-wrap +msgid "# *ipfw add 50 skipto 65535 ip from 203.0.113.10 to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2852 +msgid "if the from address in the packet is matched in the table." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2854 +msgid "If it is not matched, processing continues with the next rule." +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2858 +msgid "" +"From the man:ipfw[8] man page - The *tablearg* argument can be used with the " +"following actions: *nat*, *pipe*, *queue*, *divert*, *tee*, *netgraph*, " +"*ngtee*, *fwd*, *skipto*, *setfib*; wth action parameters: *tag*, *untag*; " +"and with rule options: *limit*, *tagged*." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2861 +#, no-wrap +msgid "*First Example*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2864 +msgid "" +"The first example is to use a table with the *skipto* keyword. indexterm:" +"[table, with skipto]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2868 +msgid "" +"Consider a table of addresses of \"bad hosts\". If any such host were to " +"try to connect to or through the firewall, they should be denied. Since " +"there is already a deny rule (the immutable rule at 65535), it is possible " +"to load an address table with keys of hosts, and values of the deny rule, " +"65535:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2870 +msgid "" +"First, on the *firewall* VM, create a table called _badhosts_, and populate " +"it with the addresses of hosts to be denied:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2874 +#, no-wrap +msgid "Restart *ipfw*:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2877 +#, no-wrap +msgid "" +"# *kldunload ipfw*\n" +"# *kldload ipfw*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2879 +#, no-wrap +msgid "Create and populate the table:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2883 +#, no-wrap +msgid "" +"# *ipfw table badhosts create type addr*\n" +"# *ipfw table badhosts add 203.0.113.10/32 65535*\n" +"added: 203.0.113.10/32 65535\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2887 +msgid "" +"Then create a rule that uses the table. For this use case, put the rule " +"_before_ the *check-state* rule," +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2896 +#, no-wrap +msgid "" +"# *ipfw add 50 skipto tablearg ip from 'table(badhosts)' to any*\n" +"00050 skipto tablearg ip from table(badhosts) to any\n" +"#\n" +"# *ipfw add 100 check-state*\n" +"#\n" +"# *ipfw add 1000 allow ip from any to any*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2900 +msgid "" +"Note the single quotes around the `table(badhosts)` entry to placate the " +"shell: indexterm:[table, example]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2903 +msgid "" +"To test, start up *userv3.sh* on the *firewall* VM: indexterm:[userv3.sh]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2908 +#, no-wrap +msgid "" +"# *sh userv3.sh*\n" +"Starting UDP listeners on [5656],[5657],[5658]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2912 +msgid "" +"And on the *external1* VM (which should have address 203.0.113.50) , start " +"up *ucon.sh*: indexterm:[ucon.sh]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2917 +#, no-wrap +msgid "" +"# *sh ucon.sh 5656*\n" +"UDP communicationing [203.0.113.50],[5656],[1]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2920 +msgid "No communication should be seen on the *firewall* VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2922 +msgid "" +"However, by removing the entry for `203.0.113.10/32` from the `badhosts` " +"table, the communications succeed and reach the *userv3.sh* services " +"listening on the *firewall* VM:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2927 +#, no-wrap +msgid "" +"# *ipfw table badhosts delete 203.0.113.10*\n" +"deleted: 203.0.113.10/32 0\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2930 +msgid "Retrying the *ucon.sh* communications above will succeed." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2932 +msgid "" +"It would be tempting to combine the previous two examples into something " +"like:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2937 +#, no-wrap +msgid "" +"# *ipfw add 1000 allow udp from 'table(badhosts)' to me dst-port 'table(badports)'*\n" +"ipfw: invalid destination port table(badports)\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2940 +msgid "but *ipfw* does not allow the use of more than one table in a rule." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2942 +msgid "" +"However, instead of a second *table* keyword, it is possible to use the " +"*lookup* keyword for the port:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2946 +#, no-wrap +msgid "A contrived example:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2949 +#, no-wrap +msgid "" +"# *ipfw add 25 allow udp from 'table(badhosts)' to me lookup dst-port badports*\n" +"00025 allow udp from table(badhosts) to me dst-ip lookup dst-port badports\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2953 +msgid "" +"While this does work, the better solution is to use the a *flow* table: " +"indexterm:[table, example]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2956 +msgid "" +"Unload and reload the *ipfw* kernel module for the next example, this time " +"for \"good hosts\". indexterm:[table, flow table] indexterm:[lookup table, " +"flow]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2969 +#, no-wrap +msgid "" +"# *ipfw table goodflow create type flow:src-ip,dst-port*\n" +"#\n" +"# *ipfw table goodflow add 203.0.113.10,5656*\n" +"added: 203.0.113.10,5656 0\n" +"#\n" +"# *ipfw table goodflow add 203.0.113.10,5657*\n" +"added: 203.0.113.10,5657 0\n" +"#\n" +"# *ipfw add 500 allow udp from any to me flow 'table(goodflow)'*\n" +"00500 allow udp from any to me flow table(goodflow)\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2974 +msgid "" +"This gives the firewall admin much more granular control of exactly what " +"host and what port to match together. Note the results by trying *sh ucon." +"sh 5656*, *sh ucon.sh 5657*, and *sh ucon.sh 5658* from the *external1* VM. " +"The first two succeed, while the third does not." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2977 +msgid "" +"Using the *valtype* keyword for addr tables permits separate tables for IPv4 " +"and IPv6: indexterm:[keyword, valtype]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2983 +#, no-wrap +msgid "" +"# Create the translation tables.\n" +"# ipfw table T46 create type addr valtype ipv6\n" +"# ipfw table T64 create type addr valtype ipv4\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2986 +#, no-wrap +msgid "*Second Example*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2990 +msgid "" +"The second example concerns using tables with the *limit* keyword. " +"indexterm:[table, limit example] Recall that the *limit* keyword limits the " +"number of active connections at one time." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:2992 +msgid "" +"Consider an address table to keep track of addresses and limits like this:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3009 +#, no-wrap +msgid "" +"# Create a table named \"limits\".\n" +"# *ipfw table limits create type addr*\n" +"#\n" +"# Assign a value of 23 to the address 203.0.113.10\n" +"# *ipfw table limits add 203.0.113.10 23*\n" +"added: 203.0.113.10/32 23\n" +"#\n" +"# Now add a limit rule for this address\n" +"# *ipfw add 1000 allow udp from 'table(limits)' to me limit src-addr tablearg*\n" +"01000 allow udp from table(limits) to me limit src-addr tablearg :default\n" +"#\n" +"# And add a rule to allow the traffic.\n" +"# *ipfw add 1100 allow udp from 'table(limits)' to me*\n" +"#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3014 +msgid "" +"The above rules have created a table named \"limits\" with one entry, " +"203.0.113.10 with value 23. With rule 1000, all packets coming into the " +"firewall will be looked up in the table. If a packet from address " +"203.0.113.10 arrives, the lookup will succeed and the value of \"23\" will " +"be applied as the tablearg to the *limit* option for connections with that " +"address." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3017 +msgid "" +"Once this is set up, it is possible to change the limit value without " +"changing the rule. The value can either be changed by deleting and re-" +"adding the table entry, or even better, by creating a new table, " +"_newlimits_, and using the table *swap* command:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3035 +#, no-wrap +msgid "" +"# Create the newlimits table.\n" +"# *ipfw table newlimits create type addr*\n" +"#\n" +"# Assign a value of 50 to the address 203.0.113.10.\n" +"# #*ipfw table newlimits add 203.0.113.10 50*#\n" +"added: 203.0.113.10/32 50\n" +"#\n" +"# Now swap the tables.\n" +"# #*ipfw table limits swap newlimits*#\n" +"#\n" +"# #*ipfw table all list*#\n" +"#--- table(lims), set(0) ---#\n" +"#203.0.113.10/32 50#\n" +"#--- table(newlims), set(0) ---#\n" +"#203.0.113.10/32 23#\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3039 +msgid "" +"With this arrangement, the \"newlimits\" table can be modified independently " +"from the \"limits\" table and the rule is not affected. indexterm:[table, " +"limit example]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3041 +msgid "" +"While this looks like a good solution, *_there is one major flaw here._*" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3046 +msgid "" +"Incoming packets from 203.0.113.10 are processed by rule 1000, which looks " +"like it permits traffic through the firewall, but all it does is perform a " +"table lookup and set a limit value. *And then nothing else happens.* " +"Processing does not continue to rule 1100. This can be verified by using " +"the *ipfw show* command to watch the rule counts." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3049 +msgid "" +"The easiest workaround is to delete rule 1000 after the *swap* is " +"completed. Other more elegant strategies include preparing a \"function\" " +"(using the *call* and *return* keywords) to set a limit value directly." +msgstr "" + +#. type: Title ==== +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3050 +#, no-wrap +msgid "More on *flow* tables" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3056 +msgid "" +"A *flow* table maintains a list of *flows*. indexterm:[lookup table, flow] " +"indexterm:[table, flow] A *flow* is a designation given to traffic between " +"two endpoints. The designation can be any subset of:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3058 +#, no-wrap +msgid "*src-ip*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3059 +#, no-wrap +msgid "*src-port*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3060 +#, no-wrap +msgid "*proto*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3061 +#, no-wrap +msgid "*dst-ip*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3062 +#, no-wrap +msgid "*dst-port*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3066 +msgid "" +"that makes sense in source -> destination order. indexterm:[table, flow " +"examples] Examples include:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3073 +#, no-wrap +msgid "" +"# *ipfw table zoo create type flow:src-ip* # Creates a flow based on soure IP address\n" +"# *ipfw table zar create type flow:proto* # Creates a flow based on just a protocol\n" +"# *ipfw table zaz create type flow:dst-ip* # Creates a flow based on just the desitination IP\n" +"# *ipfw table zop create type flow:dst-port* # Creates a flow based on the destination port\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3076 +msgid "or with extra specificity:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3083 +#, no-wrap +msgid "" +"# *ipfw table zip create type flow:src-ip,proto,dst-ip,dst-port* # Flow based on all four\n" +"# *ipfw table zim create type flow:src-ip,proto* # Just source IP and protocol\n" +"# *ipfw table zam create type flow:src-ip,proto,dst-ip* # Source IP, destination IP and protocol\n" +"# *ipfw table zap create type flow:src-ip,dst-ip* # Just IP address endpoints\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3086 +msgid "" +"Once the table is created for a *flow*, entries can be placed in the table " +"provided they match the table *flow* specification." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3088 +msgid "Matching these additions to the tables created above:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3092 +#, no-wrap +msgid "# *ipfw table zim add 192.168.200.30,tcp*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3095 +msgid "would succeed, but" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3099 +#, no-wrap +msgid "# *ipfw table zip add 192.168.30.20,172.20.15.20*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3102 +msgid "" +"would fail because the flow specification for table zip is *src-ip,proto,dst-" +"ip,dst-port* and neither the protocol nor the destination port was given." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3104 +msgid "A correct flow specification for table zip would be something like:" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3108 +#, no-wrap +msgid "# *ipfw table zip add 192.168.30.20,tcp,172.20.15.20,80*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3112 +#, no-wrap +msgid "" +"*flow* tables allow for precise definition of traffic between a source and a destination.\n" +"Once in the table, rules can be applied to commands *allow*, *deny*, *divert*, *queue*, etc. for modifying traffic flow.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3115 +#, no-wrap +msgid "" +"*General notes on all tables:*\n" +"indexterm:[lookup table, general notes]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3117 +msgid "" +"Table names can be numeric or alphanumeric and can include only hyphen (-), " +"underscore (_), and period (.) as special characters." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3118 +msgid "Maximum table name length is 63 characters." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3122 +msgid "" +"Tables names must be unique within a set. Tables can have the same name " +"across different sets, however any rules for tables in sets other than set " +"0, must include the set number. The sysctl variable `net.inet.ip.fw." +"tables_sets` controls this behavior. indexterm:[sysctl, net.inet.ip.fw." +"tables_sets]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3126 +msgid "" +"The maximum number of tables across all sets is 65535. Practically however, " +"the number is controlled by the sysctl variable `net.inet.ip.fw." +"tables_max`. indexterm:[sysctl, net.inet.ip.fw.tables_max] The default is " +"128." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3129 +msgid "" +"If a table is in use in a rule, it cannot be destroyed. The rule must be " +"removed first, then the table can be destroyed. However, a table can be " +"flushed (*ipfw table _tablename_ flush*) at anytime." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3130 +msgid "" +"All table types survive an *ipfw flush* action, and table contents are not " +"affected." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3132 +msgid "" +"Make table names as descriptive as possible to avoid confusion when used in " +"rules. The names used here (foo, bar, zip, zap, etc.) are just examples." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3134 +msgid "" +"As noted in the man page, if two tables are used in a rule, the result of " +"the second (destination) is used. Therefore avoid using two tables in a " +"rule, or try using the *lookup* keyword instead." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3137 +#, no-wrap +msgid "" +"*Notes on specific table types:*\n" +"indexterm:[lookup table, type notes]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3139 +#, no-wrap +msgid "*Address tables (addr)*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3141 +#, no-wrap +msgid "" +"Address tables (addr) support IPv4 and IPv6 address types, and varying mask lengths appropriate for each address type.\n" +"The default mask length for IPv4 is 32 bits (/32) and the default prefix for IPv6 is 128 bits (/128).\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3142 +#, no-wrap +msgid "Table lookups will return the most specific entry, so 203.0.113.20/32 is preferred over 203.0.113.0/24.\t\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3144 +#, no-wrap +msgid "*Interface tables (iface)*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3146 +#, no-wrap +msgid "" +"Interface tables store interface names as alphanumeric text.\n" +"The text does not actually have to match a current valid interface.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3147 +#, no-wrap +msgid "Special characters in interface names can include any from the set\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3149 +#, no-wrap +msgid "[-+_?,.!~@#%^&*()=;:/,<>{}|]\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3151 +msgid "" +"Note however, that the shell may recognize some of these characters when " +"adding and during lookup, thus interfering with the table operation, and so " +"_special characters in interface names should be avoided_." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3152 +msgid "The maximum key length is 15 characters." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3153 +msgid "" +"There is *no support for interface ranges*, for example `em0-4`, even though " +"an interface name *\"em0-4\"* can be entered." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3155 +#, no-wrap +msgid "*Number tables (number)*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3156 +#, no-wrap +msgid "Number tables support unsigned 32-bit integer types.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3158 +#, no-wrap +msgid "" +"Entries can be positive or negative.\n" +"Negative entries perform unsigned ones complement arithmetic, and positive numbers roll over from 4294967295 to 0.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3159 +#, no-wrap +msgid "Any shell element that evaluates to a number can be used: shell variables that resolve to a number (`$MAILCHECK`, `$PPID`), backtick operations such as `expr 5 + $UID`, `id -u`, `date \"+%s\"`, and special variables like `$RANDOM` in bash.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3160 +#, no-wrap +msgid "As with other table types, ranges are not supported.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3162 +#, no-wrap +msgid "*Flow tables (flow)*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3165 +#, no-wrap +msgid "" +"Flow tables describe network traffic based on the desired attributes.\n" +"The best matches include as much detail as possible: `src-ip`, `proto`, `dst-ip`, `port`.\n" +"Including less than that may make it difficult to add an element in the table:\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3166 +#, no-wrap +msgid "*ipfw table foo create type flow:dst-port* # Table based on just the destination port\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3167 +#, no-wrap +msgid "*ipfw table foo add telnet* # Fails to add!\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3168 +#, no-wrap +msgid "*ipfw table bar create type flow:dst-ip,dst-port*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3169 +#, no-wrap +msgid "*ipfw table bar add 203.0.113.10,5656*\n" +msgstr "" + +#. type: Title == +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3170 +#, no-wrap +msgid "Stream Control Transport Protocol (SCTP)" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3174 +msgid "" +"A readable introduction to SCTP is found in Wikipedia - https://en.wikipedia." +"org/wiki/Stream_Control_Transmission_Protocol#RFCs and ever more detail is " +"found in the accompanying RFCs. indexterm:[keyword, sctp] indexterm:[SCTP]" +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3175 +#, no-wrap +msgid "SCTP Versions" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3179 +msgid "" +"As of FreeBSD 14.1, there are three different versions of SCTP - a " +"\"native\" version, a \"separate portable\" version, and a \"userland\" " +"version. indexterm:[SCTP, versions]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3185 +msgid "" +"FreeBSD ships with the \"native\" version of the protocol, described in man:" +"sctp[4]. (This is actually the reference implementation of SCTP initially " +"developed on FreeBSD 7.) This version requires loading the kernel module " +"*sctp.ko* before use. Native SCTP uses the SCTP library on FreeBSD which " +"provides access to the various functions found in . " +"Developers can use the features described in man:sctp[4] to develop SCTP " +"applications based on the native protocol." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3187 +msgid "Then, there are a couple of notable packages regarding SCTP:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3190 +#, no-wrap +msgid "" +"*libusrsctp “Portable SCTP userland stack”* – This is a non-kernel implementation of the protocol using “usrsctp_*” functions.\n" +"It also provides UDP encapsulation as shown in the Wireshark image below:\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3195 +#, no-wrap +msgid "" +"*sctplib “User-space implementation of the SCTP protocol RFC 4960”* – This package is a re-implementation of the native SCTP code that can function as a replacement for the default installed code.\n" +"indexterm:[RFC, 4960]\n" +"It does not require the *sctp.ko* kernel module.\n" +"indexterm:[module, sctp]\n" +msgstr "" + +#. type: delimited block = 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3200 +msgid "" +"As noted in the *BUGS* section of man:sctp[4], the *sctp.ko* kernel module " +"cannot be unloaded. Restart FreeBSD to remove the module from the kernel." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3204 +msgid "" +"Interestingly, the reference implementation for SCTP that was developed on " +"FreeBSD 7 and has been archived on GitHub at link:https://github.com/" +"cyberroadie/sctp-examples[https://github.com/cyberroadie/sctp-examples]. " +"*ipfw* played a role in its development and the vestiges of that development " +"remain in the *ipfw* code base and in the collection of *sysctls* that " +"support it." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3206 +msgid "" +"The following section studies the native SCTP protocol usage and the " +"encapsulated usage with *ipfw*." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3207 +#, no-wrap +msgid "SCTP Protocol Operation" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3211 +msgid "" +"The image below shows a Wireshark view of a typical native SCTP association " +"(connection): indexterm:[SCTP, association]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3213 +#, no-wrap +msgid "Wireshark View of Native SCTP" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3214 +#, no-wrap +msgid "Wireshark view of Native SCTP. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3214 +#, no-wrap +msgid "ipfw-sctp000.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3219 +msgid "" +"Notice how there are two different interfaces involved with this transfer - " +"127.0.0.1, and 192.168.1.78. In fact, SCTP supports association setup and " +"data exchange with multiple interfaces to a remote node. The RFC's explain " +"this capability in detail." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3223 +msgid "" +"Also in this image, note the basic *_4-way handshake_* - INIT, INIT_ACK, " +"COOKIE_ECHO, and COOKIE_ACK. Also shown are the HEARTBEAT, DATA, SACK " +"(Stream Acknowledgement) messages, and the shutdown sequence of SHUTDOWN, " +"SHUTDOWN_ACK, and SHUTDOWN_COMPLETE. indexterm:[SCTP, 4-way handshake]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3226 +msgid "" +"Below is a view of `netstat -an` showing the display of a separate SCTP " +"section containing all current associations: indexterm:[SCTP, view with " +"netstat]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3256 +#, no-wrap +msgid "" +"% netstat -an\n" +"Active Internet connections (including servers)\n" +"Proto Recv-Q Send-Q Local Address Foreign Address (state)\n" +"tcp4 0 0 \\*.22 *.* LISTEN\n" +"tcp6 0 0 \\*.22 *.* LISTEN\n" +"tcp4 0 0 127.0.0.1.631 \\*.* LISTEN\n" +"tcp6 0 0 ::1.631 \\*.* LISTEN\n" +"udp4 0 0 127.0.0.1.123 \\*.*\n" +"udp6 0 0 fe80::1%lo0.123 \\*.*\n" +"udp6 0 0 ::1.123 \\*.*\n" +"udp4 0 0 192.168.1.78.123 \\*.*\n" +"udp6 0 0 2600:1700:3901:4.123 \\*.*\n" +"udp6 0 0 fe80::3e97:eff:f.123 \\*.*\n" +"udp4 0 0 \\*.123 *.*\n" +"udp6 0 0 \\*.123 *.*\n" +"#Active SCTP associations (including servers)#\n" +"Proto Type Local Address Foreign Address (state)\n" +"sctp4 1to1 127.0.0.1.5000 127.0.0.1.42227 ESTABLISHED\n" +" 192.168.1.78.5000 192.168.1.78.42227\n" +"sctp4 1to1 127.0.0.1.42227 127.0.0.1.5000 ESTABLISHED\n" +" 192.168.1.78.42227 192.168.1.78.5000\n" +"sctp4 1to1 127.0.0.1.5000 LISTEN\n" +" 192.168.1.78.5000\n" +"Active UNIX domain sockets\n" +"Address Type Recv-Q Send-Q Inode Conn Refs Nextref Addr\n" +"fffff8015575c000 stream 0 0 0 fffff80155758c00 0 0\n" +". . .\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3260 +msgid "" +"Internally, the SCTP data packets look different from TCP and/or UDP " +"packets. However, like those two, SCTP has a protocol number, source " +"address, destination address, and port numbers, so using *ipfw* with SCTP " +"will be fairly straightforward." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3263 +msgid "Here's a look at a typical packet: indexterm:[SCTP, typical packet]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3265 +#, no-wrap +msgid "Internal View of the SCTP INIT Data Packet" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3266 +#, no-wrap +msgid "Internal View of the SCTP INIT Data Packet. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3266 +#, no-wrap +msgid "ipfw-sctp010.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3270 +msgid "" +"To study SCTP’s behavior with *ipfw* the client/server echo program, shown " +"above, will be used. A separate streaming application similar to the " +"familiar _chargen_ small server will also be used." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3272 +#, no-wrap +msgid "Using the TSCTP Testing Tool on FreeBSD" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3279 +msgid "" +"A handy testing tool is the FreeBSD package `tsctp`. indexterm:[SCTP, tsctp " +"test tool] Install the package on the *external1* and *internal* VMs. " +"(Configure the VMs to access the Internet to install the package. Refer to " +"the crossref:ipfw-introduction[ipfw-introduction-quickstart, Quick Start] " +"section for details.)" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3283 +#, no-wrap +msgid "# *pkg install tsctp*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3288 +msgid "" +"This tool uses the native SCTP protocol version. To use, first load the " +"*sctp.ko* kernel module: indexterm:[module, sctp]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3292 +#, no-wrap +msgid "# *kldload sctp.ko*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3295 +msgid "Running the program is discussed below." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3298 +msgid "" +"To get started, initialize the bridge and tap devices to the same " +"architecture as \"Simple NAT\", shown in the figure below. indexterm:" +"[bridge] indexterm:[tap]" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3300 +#, no-wrap +msgid "Setting Up to Test Native SCTP" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3301 +#, no-wrap +msgid "Setting Up to Test Native SCTP. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3301 +#, no-wrap +msgid "ipfw-sctp015.png" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3306 +#, no-wrap +msgid "% *sudo /bin/sh mkbr.sh reset bridge0 tap1 tap4 bridge1 tap0 tap5*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3308 +#, no-wrap +msgid "Then start the required VMs:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3310 +#, no-wrap +msgid "% */bin/sh runvm.sh firewall external1 internal*\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3313 +msgid "indexterm:[mkbr.sh] indexterm:[runvm.sh]" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3315 +msgid "Then follow these steps:" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3317 +msgid "" +"Apply the addressing shown in the above figure and ensure connectivity with " +"adjacent interfaces, and with the opposite side interfaces (10.10.10.20 from " +"the *external1* VM and 203.0.113.10 from the *internal* VM)." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3319 +msgid "" +"The default route for the *external1* VM should point to 203.0.113.50, and " +"for the *internal* VM it should point to 10.10.10.50." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3323 +msgid "" +"Load the *sctp.ko* kernel module on the *external1* and the *internal* VMs. " +"This enables communication via native SCTP on these VMs. indexterm:[SCTP, " +"tsctp example]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3327 +#, no-wrap +msgid "On the *internal* VM, run in server mode:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3329 +#, no-wrap +msgid " tsctp -L 127.0.0.1 -L 10.10.10.20 -p 1234\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3331 +#, no-wrap +msgid "and on the *external1* VM, run in client mode:\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3333 +#, no-wrap +msgid " tsctp -L 203.0.113.10 -p 1234 -n 10 -l 1000 192.168.1.128\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3337 +msgid "Use `tscp --help` to get a list of the options and meanings." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3340 +msgid "" +"The client program sends 10 messages (`-n 10`) to the server. Simple " +"statistics are shown once the program terminates." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3344 +msgid "" +"The above procedure has established SCTP communications across the " +"firewall. The *firewall* VM does not need to load the *sctp.ko* module. To " +"the *firewall* VM, this is simply normal IP traffic." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3347 +msgid "" +"Restart the client with `-n 0`, for unlimited messages. While normal SCTP " +"traffic is established from client to server, load *ipfw* on the *firewall* " +"VM." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3352 +msgid "" +"Traffic is immediately halted. Eventually, the client will recognize it has " +"been disconnected. This may take a couple of minutes. The disconnection is " +"shown in the image below:" +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3354 +#, no-wrap +msgid "IPFW Firewall Disrupts SCTP Traffic" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3355 +#, no-wrap +msgid "IPFW Firewall Disrupts SCTP Traffic. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3355 +#, no-wrap +msgid "ipfw-sctp020.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3358 +msgid "" +"Creating suitable rules for SCTP traffic is quite similar to other rules " +"performed in previous examples." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3360 +#, no-wrap +msgid "IPFW Traffic Flow With Two Rules" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3361 +#, no-wrap +msgid "IPFW Traffic Flow With Two Rules. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3361 +#, no-wrap +msgid "ipfw-sctp025.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3366 +msgid "" +"One would think the \"one-rule\" version using *setup* and *keep-state* " +"keywords would work, but it does not. The \"two-rule\" version must be " +"used: indexterm:[SCTP, two-rule version]" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3375 +#, no-wrap +msgid "" +"root@firewall:~ # ipfw show\n" +"00100 0 0 check-state :default\n" +"01000 40 4152 allow sctp from 203.0.113.10 to 10.10.10.20\n" +"02000 48 4424 allow sctp from 10.10.10.20 to 203.0.113.10\n" +"65535 0 0 deny ip from any to any\n" +"root@firewall:~ #\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3379 +msgid "" +"Also, keep in mind that SCTP is typically used where there are multiple " +"interfaces per association. This example has used only one, but the " +"principles are the same." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3380 +#, no-wrap +msgid "Downloading and Building *usrsctp* Programs" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3387 +msgid "" +"To test SCTP encapsulation with UDP, download and build the *usrsctp* kit. " +"indexterm:[SCTP, usrsctp] Follow this procedure to download and build the " +"programs for the *usrsctp* kit. indexterm:[SCTP, building usrsctp] On the " +"*external1* VM and the *internal* VM, the procedure is the same." +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3389 +msgid "" +"For this procedure, reconfigure the *external1* and *internal* VMs to access " +"the Internet as described in crossref:ipfw-introduction[ipfw-introduction-" +"quickstart, Quick Start]." +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3401 +#, no-wrap +msgid "" +"# *pkg install git*\n" +"# *pkg install cmake*\n" +"# *mkdir /root/src*\n" +"# *cd /root/src*\n" +"# *git clone https://github.com/sctplab/usrsctp.git*\n" +"# *mkdir tmp*\n" +"# *cd tmp*\n" +"# *cmake ../usrsctp*\n" +"# *cmake --build .*\n" +msgstr "" + +#. type: delimited block - 4 +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3403 +#, no-wrap +msgid "Once finished, the test programs are located in /root/src/tmp/programs.\n" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3406 +msgid "" +"Now reconfigure *external1* and *internal* VMs to the architecture and " +"addressing in crossref:ipfw-rules[ipfw-rules-using-tsctp-tool, Using the " +"TSCTP Testing Tool]." +msgstr "" + +#. type: Title === +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3407 +#, no-wrap +msgid "Encapsulated Echo Server and Client with IPFW" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3412 +msgid "" +"The figure below shows encapsulated usage of SCTP with the " +"*chargen_server_upcall* program running on the *internal* VM and the " +"*client_upcall* program running on the *external1* VM. indexterm:[SCTP, UDP " +"encapsulation] The output is similar to that of the _chargen_ small server " +"program." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3414 +#, no-wrap +msgid "SCTP Traffic Encapsulated in UDP Datagrams" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3415 +#, no-wrap +msgid "SCTP Traffic Encapsulated in UDP Datagrams. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3415 +#, no-wrap +msgid "ipfw-sctp030.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3418 +msgid "" +"All the data exchanged between the two systems was encapsulated in UDP " +"datagrams as shown in the figure below." +msgstr "" + +#. type: Block title +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3420 +#, no-wrap +msgid "Wireshark View of UDP Encapsulation of SCTP" +msgstr "" + +#. type: Positional ($1) AttributeList argument for macro 'image' +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3421 +#, no-wrap +msgid "Wireshark View of UDP Encapsulation of SCTP. Refer to paragraphs below." +msgstr "" + +#. type: Target for macro image +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3421 +#, no-wrap +msgid "ipfw-sctp035.png" +msgstr "" + +#. type: Plain text +#: documentation/content/en/books/ipfw-primer/ipfw-rules/_index.adoc:3424 +msgid "" +"Any *ipfw* rules for this traffic only have to be concerned with UDP, not " +"SCTP." +msgstr "" diff --git a/documentation/static/images/books/ipfw-primer/ipfw-dummynet055.png b/documentation/static/images/books/ipfw-primer/ipfw-dummynet055.png new file mode 100644 index 0000000000000000000000000000000000000000..de7da239bed03fbd052248a89922b85fc844f323 GIT binary patch literal 39348 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 RLms;!c~?d}P4v0*{|EKjubBV< literal 0 Hc$@BPiwHo{}^z!BC>y#l;bZn+O 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%0AL@9z(ELRdPm@7Y;50Hx6FE0$_C_9n{8 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 -!4AfEiQWA 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%0Dv(PB=drsRzx#?eo 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 literal 0 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 literal 0 Hc$@vmkl-OeaCdiicL?t85FkN=yIXK~_XKx$4estf5831S|;T6GT*iSHU@Xf6+-pe){h1u^m6OTR$$H0g1SE*?SotYib3Q zpiGr&)5TZBEP*vs&8UKc*$6T`ZB(LJdm4dcnwp=l z?_#TG>!Z4viOHnpa*I2=plok%FW=d)yVqBuY#dqziX&bLQjhJYhU+E5D$c1{*5 zf8eXru+-66S@wK-n73**FfuCDY>aLBx-*syhemOHejfbu=g7na1sNHe$NhDc$++c0 zoz36hFSNM-{P}~6i|Z4-n@BeKF%Xl4gNrdrk*)j8;}hk&%&`t&GpP zuqbA=W2B{pfrGo-HHe9ck&}}PX^IOD9*C#ab4JXSPP5e0t8~A+1VM?5i76>7mul3H zO-?d0GRFM5c1m^w`=zI+H##09(i??_guGkaUR`Zl9xhNU^n=HsbHBBJ^~#&q8;X&x z$0{Z^c51-sH8^XY@Ln?Iu_C?EP;^|}@W4P-Rh5FWaxPY7MFkWh?m~_v7D%GFcz<4A zUScBVlDwR}JSPXo`o_k_`g(Fo$_HfR-JP^fU5DL?{HEtE83}|fr>16VX4WsRZeli7 zL`p`snq6F-pO@Fs*_mHhIGjMAOIv#NaCf!V9X35au2-%yH#f)qa4zrR!R201P(a4P z(WKevSW!`7F;{hRaUm%!P3&`heJzp1R9saRok7CQ-P*N)^PDmgkCB0xPF;|!L6D@G zGM)KaD`FoI9V;vAV!fTw!CW;cajad6ykk7lN(rrIlUIvp;6l-aCx5fKuaFE!O?WVFrC zvr|)B^~X{+yIw>_MD+Ib%+%SeT`gihujHrNnfVV_ngj`|xV`;-Y+PKa+9H+mjJmq( zxoR^ZAt9e|%f$v%bo5f~R*%d5SX=@NXxaXDRQW@jl?%6@?z&d2LD z4jY}0w!N9Hmdux19ySM)?k*437HzsialqM6PfsgqYA#PtZSCyNPET)5=fo;2D+zo! zTu!q`1tvy za=Fh94qDuv@0@ooHaclHI$EfzCV&l8()-V^BLuL#Pqv`9DXFQ42M1A&6=Y;&w|9Ua}v z>8*{8(H$#=f7?N&eOp0BhVAwUenWXy*7{1jKNgeu&!8Z7hh2pvCW~!HO3LEnf17j~ zmu9`~256tr(NPd|v)xu`K!7MGbyitfI8sJ>y6l#!fx!kC3mAr+tSs}HvLEPK06M(9 zULF+%2L}fR!g5YJfa<=2f`>*xz-6{f&doJS<8l`Y#U`bs)Rg9UhPlt9iS)|M%(V&h zMz9Q+SXgJFsuXBP@fjq<#JSv$*ZhB70YprfYJcGSA`y>-jZI-aH8BxA9TOIYSlVp0 z+yV|>R#v7`WjuO&vG*o58?5Q*d0TD;8T5RjRIj;zygRyR3Kx%~l0`8vFi_l5B_+*o zaleCQ7?VeLrY^3iko)_RDo$J$1z$j3{_J$49|Hq}SSndWN(uqs-q|qs_}G|&qT(J5 z%rkG?RBsL_3Jd#ta`8NzUtDl|K5A@ny+KAs_6fII?EJm3pdl){b9pfD6AlJHjn!^* zTH6!#<9N1sZHwzgL8^yV%Qu((8CqguVt4lkzvYy))Ko11>!7nHCnmOI$HvCO@VIw( zcTY>oYo9knL_}$D#HHrDsbY0dh6nfB=h7R0<~FwYG1uU9 zHMN5Ld=m=`_v>RFS6VKM$pXc_sp7)i_9SL2kK6MADdwZ4W_GvBeS`j37>y5DSmMy2 zWgg{-K{jz%tiQUrxIB1QTECe7GCU6xMFA4{+*RTukZJ zALFk<5ri>+1@$~oe8nyU7fA!jtac!x7cX7}p;6M&($?E;4UJ`sYierlOv?7hQ6DWf z*82N*Pvpx31d~c;Dc5QDiy>D&P1VxUl2V@j>;t+K0G~Yw62NVx;oxT$(SE-otiB9+{;M@&f>LZvOEq;v^l1~34)!)mE%wzG4i zQG4$Di&xkeN=R(5@VV`pz~ zFDdy>lm3TRX^rcJDLp;?;~TAito+9!q@b`62A|&#{$}hA96A-D4+ zlc2ndi;E8S_Jl-4s3<5PUV_h`1A~Hg;D(Y}+m~U2I>9uQp3qO(&_UcS=t z4jd2~UsP1|yd7`^$cLGk8GV9;rskry$4z!#-cK$?6%`gB1HgU&H~`t*U0;I|`EkXh zq*z#3P?D2_%4$l(Kd)}kd)2mnFrN6i!64s=2mar6k3-Q&pQkpa)8o$8X~AaLbJZap z`tX6arlo5-xyoCre_TowCzD^Sz`PN3uwwY9uSO;^JZ!G23Ns^{|C;|OnobL^c?n^F zMQZ{7O3gJ-JJi4#mY7RPj=y~c87Yv>0NDJ?cWq*V6Y4l71-gk1ljfNGBjnc~+zpgw z5A9vcLUPg{L}d`j^4~u}S2stkr-M(*bkjd+sUjurPv1a{!xJ$}o`MN9sHU^MExDcK zW&Oc%BPjx;q(%A*o-p;ZArQW(li~S{VN{=RdS*KT95@IMxew5MJjO#y9)frauBSQ2 zdiBQMFCfP5&zcbWZJapO!UMBi@rv#6k_YLWGZ2S(&*HGnhWl!}T%-`*Ba4*8Ch+@Gh%IhC25p=`y?oHGybNH$X_A84Sw zyw^}rEzT!iPP;SZdQwtSwzjrlLPJACpLsl`!FD6Cw6xUE&ktaKe*Vt=%~|2|ph$e7 z$H!k;?~OtcEC%Y~^5EJCZXk(S8U+9A*HIN z^LqTQRei5jLypY$4n~-I=5=*F?*bkU$O~pdc0d6XBqc4b4j0ch2iXBu^h6NsTzbDn zyxf}x2yFt6ZewF}dwUB+HoN2gC!Z#dhq>Y5(t-k0Ag}t>xm_ z)Rd#0U4Ksx_p8gErT^zMG0t^hkkNIpxwsNT!n0`P^Sj?7$ zJ^&$ZZf`;2Kx=e$cAA))Uha%<0j7S|AA;J}AVA3^rol9BZUO>+peVb$i3tewPS<;} z5pvzG4g&%L&bEfRUC+1kWHUiaob^+;j_9nfuh%s+7y>h))$9rk0Uo!<`Q@btV37xq zBBh`^?F3cdP(3~8Cq+fOItb*LGRLaP`tY(}$g#qDg^#bN$>q$M5-c7bDl;R)tA8Ug zK0ZDv=~*d(yoG@6$B!3r{SS9XtuXjtZJV4YAcMdgWQ5JvSYRO`9cL$v>BRylYl48F z+S%D%&yBSp`1tss(VFCeU@EJqC@3k(!K;|vM*u%=kNofuftHn#A)%t$)GW=VS3wUIu6u*PBxVz#U(|{sLs^9+;5_)O*Xf8#-cQ zVQuX+qzc{6Kro7073GhJH)Li4Mjo&OAa7`V;Cpb` z9VaFxvZMij0RE&_{ zHi!V95EvCOIpAnqPKU`r5!ct>M3c%NE;XwgZRvG~GTwRW=;%0TWu~Y9VK=1tXb*Wg zy}r4L%m>It|5`v$@IBwQ3=BSSM;A>4nZjYNE-s@V>;RDMu-2W201@wOvRAu=0`PGH z4Im;Nly|{hYf$to+yc>w?O5#@PP(9&80212#cFa(b~ zmAUczRJECMdI$fo^e>X#JGS6}0G)Cbpj|-~GSz4HpD4}7$HzZ7X9G#0L-R4Di4;;L z6Hf_5k3Nd`D$_=MA+T7!zMbWI-P>x)KH@?{*66>QvO!660z%x3=)O zzQrT)T^#`p_VC;~zG=S;wK_Vi`euu^M`pp|0R@-%;!GIZ7ZFDRyEv0Ve5mQ&c10otI(N^0H zF};@~{~VA?v#Z0mZyfmgH>VrEzP`A)xNi}#fi_NMu~`LBc5T<^>g?(Ygrx~M)XvTh zFbiBltkuDFoAsd&%{@ele#4a zy)#|93=|BI)Er>A|Ni~Ey1ELi(~nngk@;LNc7fH5OG;ul9EkULxV2cQqottO2iZ9P z(B9q-K%H13K0G>lA|BEef@Nf3(F_D$wb?W>A24u$Zb9<9fZntI`@5>D3XJt&GHWHi zCRmVU0-eEdD(BMD5)jcK@q7ETl>oj!Vqm!3U)%8Ww*%v#s;)i^3<{`XU|`_ZP>R`d zi#vf8EQAuJ^Wo_C@8+!|KIP<9&ZY{RJi-sNl#t)dKWCyWEsB=9Cj};c0Odp|o-zJm ztYUjji|Pv;-)?+oXb}o17m1j)43J1ZFaJ%iC=H3!hhZ=_*R=nY6u;p5hK2??ZO{PI z9O*S;VEixc%}E2rq@~dvf+5E#GQ-bB$COk53N!{7LT$FY>=3zhd>}QQ6{~jjb-hS? zAe5-j7r5}vdJap0X&*%H4+GUJ;rB<#2z?1jd~FB^fk3O$D|Ej6pYs~d1VA8vyM6w< zrLL4A-|^7?`yd?P+cm=TH8h{#KVJb9{bYlMd{=`0w*npTj9&r&qzv8uBP?V@;GcfN zFa_sec>ixGg=nGC$HB7`A^#584m1bP2i||kJHrq6KhF*Z&-?FZ`2AlF8u(e{`MEFu zJvZvB4ED1`HGcUo9C-Hk|8o{U7x1s->wiI|lcD|3DLy{${`tRlZ*2WPr=SH({NnX* zy)?t9|G%Sn9{mxNe~U|a?aj9e`=6gM96kTf8P1+#h5i>SKaghsIm1U3y64mV`1b<| z)F1s9kncI)|JTU}{x7lW{h#H?qHI1#1(TBpRJ!rI$KD6)>wEdz>&4vDeXp<;_OY3L z%mb#=R)jKi3v&ph80z2oM@$GjPfZ;a8U3dtza6~6*Uu`A>Ct@&F?OI)hd_9s*RzOH z=JzHnuXc?`?*D*}Rr+`0Ot;*cmz0=f6-s`lpJAXNzZChN^N4*|(@-Jzl;E{7Ir=?A z02Sds3YsNLRYDm{^AW8y^fm+bfA(j%{{W?cnr$IDA@~s$|4M z|Cokp7e^p&Q3PY6p>;B+K_HBVg2K=u4aN`(oRP;Js0U){RC8nF znJlMS;J<&qCxCzV&S`&!*6DBous?A4F>!IsJCZLTYS_{>EbGs}G3kwSl9!Oz#0uZym+`8P>#wRA$H!)!kv?Yq*iBqH1GMBix_q6@@h?Y!Tl$BFloS<-e6DYA zcXxIy=Bj!@V7>ate5R(Rjt6s!cdC0+#Zi%wVj?0kvaE`k68=n^8FA@WCNN< z9GqY5X*4=~*4Aae8G)FxZ&8<#8Of2v(sJ|gXaR=Q$4B6m);q}WuxFmV|EbmLG5BoGPt8GETbF%k3WHzof1Y^BlpkCqlLe4mWG63xb`!>OgERHVp= zh|zTZw_0n(>a}c+``44<5QqoKza(c&OeidMDFdef6oe9x2(7miZ{PZ}I~^YH!l0m{ zo=`v4R#rB;oEfUBVmusg^vC7r=bxAVkMz4?Mpvmeodi#Y#!q2$7@MA6Zg3#Cnz#h> z5BwM=gRzVrFzGydUjNbyh`gnx1R4!KXt=l@k5}4(bhfv#SxM1s`R1adlkV@|4MY}DNx-GD=yk!f zMHtY01jEtr?Zy`LuhYTY^F{4%*VbUB-V+Ehbeg?|7}q~DhX=(uUmiZcUtU4MP%7sg zm|>7_T3T8l6Sdtf!Efbk-FU!7 z*Hl&AKU^(SYt#YtEGBLH4jLNhl+d3)Ke9Vg;CBoRJojYN;#(+0+<~t&v6Sje9{0{b z@Pm^Vsg!$By#^YCBl>rwm)r2NZwX7Mo3p{1jOdpxgBKmjk9T8f$|(WbOUe^JcyRdm z`LFh8)eGJXzIvj9sAUk1?!cI+p4(8PN4>#!pn(5PEf0aL{Br6A#*gSBynQ8^ z+jFU_3(5o#RN2=WfbP~GF)=~;E)V9N0BA-=M$Xq-4G#@1)mo+HtpQ@?q(KG~h#ean zYc!NBD=P~F2ZzOEuHxb0At5nPrqeEfgAU6111JwjIw<6dVjG}>^k+Ex4`rye0+;mQdQrh!!A45>K(r9?o zstJgA8JTbZoFL~Q(!xT3GU|l|1>2S8Oi8!Y0C?@}&fdVGDJUpRVCXwK)&R2;92{I) zYDJ)ZbiOlA8hASva?Q%dHdX&a3E1+3IE~!(b^X8$&?KYrG(KM3kzh{bQ99?R(pOr} zU%i0jy#;FW`|+E%Z^t)egMxzaIGmBNuo~U(E@Q}*rIMHq)EfhXgFz}=a&k6-beEKn z-~wH>+7XcE`RD?G0kpH2nAo`i7y(RXOKf)y1qJ)Vh5BsqxSZ_l(S$0VG+w9tn1Yq{zi#x!#8GKx&~u{&F}j@U1LoR<$;7>vW%MlJG0ez#Dj+Lym}V9D|R6DlQYCV&$g>49Dh7lnwf^?ItNEG43C@3^YNRs^e}Ky zz^spj1ffx?fnHvCzM`GdsM8MBFgi06{}f6O3d~?K2GA5>xa;LU=?K6UD@8>`FiqEz z)Pe0Q*7X`c_RE}rNO!xk>>2mGJ78Y2QB%V_itp4dR;}Dj`kY_9qBG&mU6Au>g!>8c zHRRWiV;6MDV+`;+rV}LY?(V?v6X11F1aEF`BA$lO^0p}RN=kD014BarhD684GSSn|*V(Ko6TJAY^sFfF z3qgjqhSS1+{uGgr&}gvVxjEZ6e=a10Nn}`N{x{J3Bj2I#5$>K(BK~=oBg=ppdSqR0IV4&^nc~FAsnc19%L4J$L{_0+EkIB7+Gq zzMQV-z$SM9w6e9c!_xJY!H?-n0A|Qy0h>&GJD%zs_^|t=` zr0YEquiheXxSsdS&bol}fSg%f55I<}y&C|oln}+1O#4FckaxT>w!@GzX4PN)I{sk<6SDJ+jdocPLAPp ziKccl0cU#6^9#$vBfo!t1$5Wwcu-JO6df74s%dCu)~{O*Xm(EzNckS&w8NyqN7m&TtGcaKz>a=OMM@t&(zeV zU@CBM4pvrHR#*9Cqnn>MPJBWxuGB%ptKG>U=B1qUbR8ojCm`>w8hn8a!OsG1JiWTM zCO>>}9s>&t`);SHpkQ~g(dqmoS2_*wEEX=VrK#y$tLM{gn)Bnm3su~Ft~8!j5Fi_G z?{*NsGbK=X?*e{waU&OHX3ERUpY4q2viXOYWs>Xy+`Xp+nI-UPa=j>6c`@+;iqqxS zkdrD&1hhnLOn5jA6Vs#V@jDl|g@pxYJX?EvduV(?LBR_rI7l%va8r0VoH?Dk<;WjC zynTnczPSnFAI%gF14KN6p>AnOg`WkW<)!p`@t)N$Ao}^BJrQa>9$YmwH6P8uYCs=K z;}z!TM?evi2!{a`drsmR1jq?g_xdgSova;{}+tbtTBsnKO2yq@&$b1Hxuu!=)G$dqjXs9GF@2_n= zC|Orm*M13Ao zA3o4KAO8iyWGw#xP%wbE>$JOKq7W+01_4ak;Br#ik`}PeqsB($MY>T@a zDQP}H+UZo%`R5V#MedCx0!vh-1K82}cq=X`8S>|AFgELHVHzjqDVW8Pe{1;i<%>@^ zFdsiIfmQPI@&aISq82Y<_%Es3KvsDUq;Yf8(b?`!@@;v+#H^T2;Uth1;V86n+xv>EQ z55*h?c4=#Cd$_wg(-J>0g$hyLYNR;c^w1`ByWD?PGieVR8XEVLMgfyRB+JkopDtl^bhJqx z8(}L>+k@3%SK-ww=ex^;-#=dU_xF1~JzQA@a(w>m1t#feIn8qeEv{d)$@v86>5KDo zOm2$lVs&O1n1FVF#4|Mjz<>rMTkpT{$)fnT=Pycaxtue=@IiwPf}5IhIdRI{(nR~Y zd-s`?ifWV77wI``z(yaZo@OgkM%Ds%P7+-I@*XK8Gn12(^WfmX+uM6^a1f{#EIhoY z>ytH7`J54P7kdW>&_QnJ+q5>T0u~kr)1}(Nf`TT-#&z}efL0}wm@I%o0U;s6!UFRN z+T;w-k^eia%j|goM5BeL{e6A7T;H4lq@A9g0wip#tNSKD19TkFZ%K3pfxf<-AOVyV z6wlh}biEgNu`p~_+dp1!Lhj3v_&@+VR<)CpldoRAT5fWwwBM0qWvy4OG-PZ!qaK}_ zYVmlueSElk_wLH6GW;E5qDR=a-kyioG|AnB8G_;`(mtj0#TR z!ac&-)issF#rEoOadUGMomz{-`S`1hj0~u=oLppOWo1o`Baq|3B@Ye^T%+4Eo>KlI zPM%m2{RmMb(l3E!e9r?2enVBq3PQMUupRiB!=1o(Mvbrm!oHa51LoZRkg8N-+7%@3(fw;U|`EduuS zUTN#x+?XSiHsRW1QcoR-@<^|4>3(Tav$`q-3}KR8YVg zGnsrU#`I8@5jjXCpvXHnl@%heW{W8$IhY$+;FQ+4>_K5wnE$IZeI$PA5uGFMZhi8t zCZmfWYpe_#p-+>CcEP81x$qbiCI5OWaV}+r>T&tluh3g}l)p-yPKgnt$vbgB;JYuv zbXoSa<%U;}R2hE5g#aZk)F?vNO25%ZPEr4u_gB~O@WTH_aUYZKXJN=8-Ukj}y1%#g z7rFKGRB_5>(~=ju&{oh+L$Tr((fT=WSYZp>5!1*YjP51hSA30*YEBSZ1I)G=tmU%X z+mGnt>w}b0NVPmGS6G={BkyLxx^pC2#~q_2rRnszbmnA^5I3mvp$)B$M_uwzMIR3; zGo5?An>uLIviW}ZV2f>7tTKKt*A>nN8xx|2eSi1X*!LSd)>J}$0eOE3yj>-e<@mLF z{7$}o#Yn?R-LIj_7gAj-_?kqR$)zJKj0?cHYYq)GJ2O+WKYe&2rBtl%g8~` zxCwM;1|8|HA?XueV{2MBjf+Y{Vmij-78||^pGP9%P&3hT``2NnAezhai~L(w20D|d z$mpM#N3@?m@5q}F;S-jYtsAdYW}>Hw(&RbblG&rpm!}A|x85p8M$OSox=n40E8{hl zoOyk+3i8V>_CbPsHQ9XjKyanSZby)Nsj6&-lT{4iW+@tZY3$pC^UicjA7L}mZR-w( z$Ra!BxY+G4Q&0c56_Q*lNp&j@s%@s5k(p&_VPb9+5p|-3;20gtkSDd)tR~mPn*Jb1 z&Eh=W4}1&e=a{qjt&PL5+;NKTWW^HwMeP1}T#uUYF!+obhoeEmew3^(cRTY!j(Npj z&}pXxKP9bCSmSM=2oiHA*YB)0N^dMrq=U}6c#XI`neZ{VZQQ$7@bC28NjE5c3gVn1?i;+T6jX6u) z+JAMr?d?OZ%C|o?uBCnXwA{DQ7FjlF6x*qhnH%d-TcR|V`HF4A#dHkfMmcGvRZHBf zPl0nFcNZ0$RD4*w`G*5E!@SYO-?S-;L0z(*GSE~DR!b-EgbzRYzWMjcl<~XMRQHo+P#BJQN)tb9*?a!Oo{@B!LoGt2E`U z4_6K%vigrbRMl^l7R~M7I?+Ep^1!Uvikk1Pjgm`mp~fC#va6c*!d|#-RXq)BlrDHa zv|O`~SI_BZ#aq@qVPS3B_C8mHiq&PWH>t~>ooS>CEcDmtAC1b^#@Xk?uTQ_Y9QR{6 z=BlD0>1*SmG*|2^^-K}>jMqM@C~O#|f7{?>D$Z?RJ%zEc{3s%DH2HyphzMh4e%y7K zwTA6-GsVbvd6X4WC4(G#{qYuW(^^u%dte&}!)h8yfmA0lPe zj*V6pr^!2(m0C`@8d=XGnpD&uHfma}27q3ivQM=5ljsgN-8_)i&ih_>w{oxHogad}wQu|ke@0HC` z&M-;=T8>eUQRF0rl(?u*c1aK(d|eRA4Y}WND>bXrKy-W9;m7uKP7oKTb^5Zj?6!*^ z*Uva9|Cn>DN|EDJ>;0o4a=+UDCjH0M`N!5kuPX2Q&A*nLnnhJ-OELRWu1I#9qkB$7 z6=RW!WVU=1iBOQi{kFx0+)}QQ?oFryTt|n2oi+uh@3C8Us*|0K^?=Nl`dznli$AQ+ zFU_h6|K-m~u3BGsulWrdUZwgAoJSfa6*J}8#o_u}!Oji-rU7(cw()T!f9C|NfME@c z&CLbg+=$v9QW7rv%YcRo^ObHoKIouc6^zZL_?==fuF1u5rijvVC^pqo779gA4y^QH zPda>RO4d%|Iu3^uTEdFF4co16#Oi(eb?M@l)f;{weI}>GxCj#NsaUTFH02Xfu}TUf zifKn9mcm#VEiDl(e24N^zlemG(P?iZeF@D6N%Tv5_n+V0fBp_twt44=)uz=QEqBt? z`N!m#dXuS--qt6nRVmU=ASWm47G*L>bsK6>CvBB-XD{>xEJSIk4xW@vo;jMEnPr5c zp#6JgZbVl>$*zQ(LPWyTQtB=krIV@V^PyCkE{&kISriDn|T-K z7|WVGAA+l53Ro9LU*IU9X2al{295y^gyW8-o^@B$@-xu+b?eTY?p7!%8#*~F*VyVm zn>*Imx@t+R*>5N+7QamfSICj@Tfj?G6!B8$^9!E-(eT-qC|9j^t%sbR=nbnVM=LQQ z{H=}QED#2vcX3Gx7gQI9LpxZki3Js$jhGkP`q$Y$Jlm(R;=1y9#5qQdbK9Y(R#sV* z*Mh}mSqrWh4u6HHjn>MzYVHGAlH>_GnwkK|ZLbQvLroYc;^PxJ*WkvNvXyMSa_wud zdl?dFTa=ae*haSBw-MQL7TW5eJXTpaI-rx{q3+odt%Ebbq$H-k0cMaS*gQSs$zgH$AQ^%H??oc5vIvpRLb&`00tXIWDNzE4-w- z^pE)qNICygF{cZox|m#B_vqJdb8SwC8^gxCwK&1Ia=6+panqGSvili44hA}CW2;y7 zMW%}TgPR*5o`H(b(q?xfmpA+WW+bIda;D3M8Sez1Lr zV5eQ-+@Vu3K%J~ut{&fs#^#E|N=p2* z^N?ggZdUe0IE#v%I1~>G_4=nSAYff4)qRs{BA=*mBXw!bOzR|5YLNMgLgs@{&A9c( zJ5ws%7)*9cbE#T)nA7y)QbR)6IGY+Lf8xfrQNj;o=8({r#0`=>T^d=g7jZd9k^cF( zJxcYvS45?g)|mztZX^Q;38WA|g&I@SY}85Mq1>do=_cfoCzh86mEwIfcF#ZEJ+x^m z57@`(wYf2MW(mCj;NF&^?AzVJ;DU-fR=u;y3Az|48!$}E&KlOAE>2>v2Oe>Ayc-k9`^8}%v_y1X zsC@j(E~yR{C)W?l?soJ~Wtb7dfr8sr z&X43qRR*Dirc?gD zDI?$Be6v0X27uaN6Jw9$jXh&3-k74)jJ7&+$G9@yWr~Xc_3yxhWqE$Vcmv5+LiVR| zkS*ZZGPiD-7bB@(3~PG^vYr`VVYhy{b!?Q9i$q2pWZZmy%~@9{#0jtRw5t9`AW|XG zHyFVP2=N+~(j57vCZcLA3hpXlQDU{W?yr0n${t#V-)vlzW~Xy@bEdYuOK4h`x02_n zpMBpTc>)8QD09%K6!q58yrxg-@V!=jcUE3!&Fu7)AdD5Zgt1Vp8AbJ302c034N%z( zFt>*xV zFEvOL6<-^%pP8I7GtoUSg?%vFY3z*HFJ$Q>%MD7o3Y9?qo#up0T~Wb?|t?<+A%5h$RI zhmyt;?R?Q%Pae#3i#ThExa_`Z&l@)87i66G(bPt(Q+v)^FSScq?SAtAQk>PLH>>1e zlXnJ$nlRPlhbD&JxvW9y#{&xq%<89O<;keFIY!GpJ;?PJP(vS{br91?HtiGFlXSNu zW~+Zab343|$)SIBRC6M?&6A2;y|dHpstmDU{boD@{;vdO;}aSZGTq?4 zpFM=Yw^`yOnY_Rr?EdqsGJEQl0HZxNIhnb_j9!5)bEhgIZDyIP%E(`S+AdZgw_og8 z)-XFrGRu+sYGS5n4GIB__y(%?joT*AoanFWQaArrYI5U4UumVzIY;Z4htJhg%6RL- z`=VDB)64A3t@*j!QzjcNdmftb?5YfkICr41FW3tGHObXhq z)f8ry)^SyCrRWC@s|&nFeZNEbs1xs=MeM_ZUeHR& zAT=!s@d`D_Jk-Bk&olB`{dbnd-I$+#>ItH{wMVd{A8u0N9E<@wOTV1rcyFuZ$a}K- zrNl}NkyLavxPEL7E8q8`Jf(7DY-qM+@T`-Q8{I5r#`lNWQwyiP=xWn@%|y!&MRU$r zy<9FgD@Q@nZ+*I*_VTzV<}-G7hfeuHLXw}`Ir>_m=2luk!%}T?FD2lLJ4OlNaLRIH z*phGAE)O5*iCXI|RI@dva=2HC7EO{oS~|UcnHX4}XYYHZzkeBw%qv10j3>AF?myd( zeguql(8sm0d#AX#h-9n?vDD#>&Y4;Rvt!+Whi(2-nf| z^Uv={e9!r_em4XJPBMq*ZPuSAF&2%-FH7Tb-0A;}s~34`ZCdJXZ1eZ>!<83W zS~Bav=y-|h)*><=P+cz1MR7D5KWX&ln7^>6GxgJSF#)ihhyd`B8aWLhP9T>uphirm zM-#V9rXc>5;*j~DWRXC6Q_dtz35gmWeS2aO8?5T&NpVbWA||I~%}O%1WyF0yWVfLs zDpmw<_hfRD?|4ggX_%2vgFmP%wQqG~npw-h_5c=G>E~n_c%Z%~Y(pniQ3L#V{^vc+YbeeXB$)q8o3a}qSgHHZF@hesYw>{I?V~Z%9v`-c1{JIG z<;hUT-P+v@WBXL*gB`d4N&rD#;^4iLhwnd-jVbtu$CWV-R`$*8L3>_o@Nc?;y>xt}MCDoN& z_#2rzOx;=0@z>q8U{BaPw|Lxu{bIuD1p<|OV9cLyxKGrqw5v($=}zw_pFOM9PC#2H znd8+?jQ+V>KQ+}U)>xX6SV%phQNeuUSzg-OAatDj_|e?5@$kWtX! z>gfL_n`c)!IC&QtrJVMJ>g49^RQSFn7M@n*K)G|Nidp{Z{it&)gcidtI|Qc6<9hYM zkHF~*;x5UY2+$%O16Ru__n(|ibXD-w-y@9m_lrQesKcL|J3UGr{)q0z3e`V%pvU^F z^M!hRp&vG)?d3N-{gPvE z(*;h?^72;PF;~0p&eYNx{awsvk`>u^(v!3h{ks9qsmh?yvcuRp(?QLr_~+{>Lb~Tp zn7=T78X1tkz!N76(;i}Tz6_}U(RUxAY0IvsOY3TE`|NVm>BxsXs^f0^ry{9dJn zWAnB^n?pd+zmN$^kQPG$HHjcn^P{PJw7~<{lKX0!QHVoyh(ls#oyo(%xq{>HMG)(Q zv4DV_3f_E+Wljc8buM!x<-Ll>`4~3=K@{7^T8v$b(PSG83eNxB3lL*`gYWys7#ie@ zA88&m^naO;akw%ji3`(Iwq0#SHQ5K{g#$B0xX)d6KTV5WEi|YC7LvF|GE<<%$tOe; zJB#v=;|5}obaQg)3}m`7lBf<7wulk%#t1(u{7j1}tR5QU+!39wXyj6^(&@HVPh_ZazhL0C8*{!Q58dwR_oDpf`6C|MV|8GV?m(EB{DNxjk(CzFb=~aH%G+zDq@S;6{ zDrjYXAbRp7gC7xIKu54B*Q|DLL}G=(A!KoRJl>AWSe?zbvok;Cq-e`24$dZqC&Z_6 z8abmgt82>opW)5kqyYqK)l))zUy}HQY(ui6HXocGs#7QrbR5b;yWB+iy|@?e8yEGu zxoyFH(bnh$EUpSOb;<}umo*(31)vv)V%473Jy^aynzXu{STZ$a-p>bJ!XW{b!LfSE zjLbvQ(NuxjYU((+gGHSYg;zm{!QV`I??H>4<^|;wZsdZ8e%O>znr{77=esev^`uhg z=D>U`lgamH=>FL${zM{tu8lX&@yNkFv?cick%Q;ajVdNVY{^ff@^Q=ONyFvh!(Bot zxJ!$s0*K-fr2<(AJNf_EqMHf-;HHDo=v_5Rk{!V;HQ>(g1E^}RXiLqBepO|#;ZvF& z?Fjp+1xDS@2hCd>O1^UfKi>^;p!icl?N;q!uWyXFFtu>BL4rxAdCB2XU>|_RL3Ij zy2;e^pu)O?NO)TtB3uG_)z?++Suq}9=~}5dLZtg`O-m~+E8#+Z=?A1>K zWFmY2S`fO?T$~(c`2)cUoJLUlTS!*fapwEw))R>K*k=IE*Th%+13SX!FN@-DI6GGm zwJcU^I(aOB)`VzECMyMdt|I+FDvr38+ zybt~<`3))gu9iBzeQ!A0p~%Kcv( zDOr$Dy$E-d4wGJ1X;~Y=j@0w3PE>WHa~c$HMLO*Y-DL+vc6W3$9ND*WcqXv|*>$0S zs7L}SuqPcRPUVS9I1ufb&>UDCj57%4t4gERS>{RT{?akQi>`|5YwCIn6ArN8Mlts4@EtCHm!j|55_#A@+!Y9^C2xA?}G^qCOklg7uq zuO{{l@^23w;9hpn;Qv)_-vG4kkfrTL-;8!VDkv5Vbot(B{y}q5n_y!}N$Owx)bT_U zE(E9)%IYb+-j6lw>rD}wID?FWII@e|A^OYiWZbqVY2gN<2O$FW5&LnUe0`O8ik>w7 zAZ8mV0@$TET1&T+9$NI+n4YEivY;)l80@ERx@JL3Vhrj3z!o5{2wz^6~A_wZU zm@@C@(&`f`$u7T$N7DXo*8CpzUVNa1JTIkf%DUciN<=694br&h{qdTy&9hm7E5mIj z**(&^y&78zv|Xj^JP^liac%`dSYC4jXzW!yO8oVc{tWMY>5Q$LfU~+!+@zub6@9T0 z^>joZ`#l|TFcQpXl_v9>>pcBzs;5FUKh|9y&4bxVX3hwzduMd2Co1-u1>??%F@rgB z5jkykx!vBH+0MYFJSiTGlv*-c6dn)xI5JQ-g)6q>blOJ}O;7n%w$` zP-j+CDurdEeN945zzXs;`S#|$+t|S%L(V%Jlr3rPrVxGY7E-QnhdbYIPD+>>2;7S$ z>|+FR)NsPv_@3{4PgH~}Ht#Ggige$d3yP-?Q$We$b8|%6dIR(ytT@_X!{>J0L%5^- z5{l4C{k`+8^m&}%x%2G_B`{O3Y?cCkNilud1xGamvDnp=UQ>T3@L{Q*=Bi?`z6)^U z4U!(h-rP3HrQZG7(#9iiqZY1b{N3T3+EiBS5HNXgCl=H-t!&|KUh#mn2eXI(Ys;M1 ze?Gh)uRD{T$EsF6kBX`;SBb`ZBBP4KZag<%D`(Gq#Rh*;fi%n=>(Frf*WtGPo6Qnc zp_CkDdd>ImD~pszMy=YYZgxvQsWL*dd9zdp0v--DEzVcWSH)yt+G0nIhd$>vr5*BkrKW{_ z?cnyPQn1+toU^tD?tAwGJ<*L&RZe&Yb%`0DaKtq7IH6qOU>gfwI}u|_V_?9K!%Mg+ zrMWy<3&RQn^7Kqd*yS%C;9M=md$7S=RpEy&AwXq>ZtoE$z~jAr1-?K~7Q~0of@Psy zjDuM{2dJ!aFHk6f{$g{Y?bR$W$GCqdV0_d#ITx-%Xc~xfXwG-OB)%osueGwVi<>p#)Mytoc6!P2prX0d-PYMo_bc<$b{M$o*t4q zWi!w@WK3HFA<2uPi27OaAiRghkF*_k(jpc+h-UT$#lk@|{CnaYk73Ps!DgRLUO~9h{YDz)vPD0j$g(H|qL^gp@+ySOmrqwF=gpAE zo}n~XW@O-gR*^~c5_!+-D$DEocBeUe|4wJPi8V3&wOstuFrt2CV*-v7v$Ua6YQmQ| zRTZb>DSxxZ0oA>Mt(DD%zrWa(r5`&UI^qXTy{Y`3x8%;+^+G5&NZb2TjFN}PA|;zGFQDb*bZtv-6+<2M!ed^wP31IXh%>4LBMf-!AxIjr8|= z-UCYR3X`>Wf{*Nwy<4kI3fJd5%seNEbt;m3GTR*omKEsZv8d^Nt(!u-OoOSQFUmMH zIGvR&?A}1Et-neYB~{bm#R1_K3sK zHLy&`M4+CWlp#1j4IW6$kdad=n@K7qc!x-6{Iv4+J}j-7d*7QKcQ0SZ!Wx@Mw!uoH$~<)f7c|3pu3O%xPx`I$QG7%B9wTflo0vhkVp)22w_JXOpi-%8WdeZ^ zzwMgk(+e$GAYJaLD++8c^wjC3BH_?Tz7*;MU)uuX%-RNnY1vf^8s5HCjvw3j&O0No z2#n3kBn`>MoL}x(*ajRWl`d#tlT$F5*U;R3T*Ch)55M3XQ*ZKu{9O)i@HDq*rGtKm zg8_ynl3KYdw{nGn9kC~+19e?=vQ01w6gDN=>p z|L{9P5uM7`1rrUMRsO90b4VZItr=t)ClamuuH+?zZggt3RhXqBJQ<$Qm3)1;`6<{%hJ`L+Fj{2>fxO_dG=d8u%8AmWBYzC&x!Du+8(-*!+sdoZ zC?y7^Qutb4iJigD)Nej1>>)S~#&8=_B%JC<5xs0fBWb~DgzHXrx8&-OTi@VCk{QJR zmhd&JBejlij9(3M|G@mYeA9x)V)N@4T#j|2UjonY)GVBjm6DI})nRmEchp%wRh>*a z7wp$}i&`4BAv9u`kX2a6xt|JDY%6%ydTY;MkQFE9vhoIZ+LA&*Gz2dQrfmv54GVF^ zFI3$1;fd@S_$^H`GXr+}$Kl?nGKr&P`%o+9e&bHq>rK<*PVx_8>_UH<08u-?w7KA* z6hik&Eo(|HVtKLuHQ2$Rbx4Wx8}Z|u6`J{ojR;@-(JI<_&qRgh(h-g!sg=sF{$1s$ zoQ#>1>dJ!M`LyoM#$@<$*@){&p(Ip#xmO^bb_j^a{{hU@XC%>43{=GBZ=D~078Ws3 zn=|QnxA;N6A8NH-Y+=wQpb}3HrgEtUj&`OeSs6%%EqS~0uOqw=JoBqpTWEDTK!2GqCiPshRyzhSD})Tdx4iNn}92sOajf=db2;Ck8yFTkF8ri+W_fT>_e9fC2@pN!i%rIpa1c3u67(pL>bV&w^%NhABejjIV#x#Aa(mjxYH{sjtTp z0LF^DMl@JZ6uR5aBdYh3J5xd5XO>jAY(kl4B-#4F<+kqwzQ58_TgLd8E8bKQrqU)- znlDzpE6R4c{iS6iUw58ZKw(He)>jZa4g&a1oTK5$@96qE#xJd|gdIoYlTi>$z;!~0 z{L(}CK=8FQ1~|R=y&6uG>f^AEn-IFb!dI8NnW8~dMpZ5Qt%{wy$52oyKZ`D#mk=Lo zj<=fd-1^G6jaN2PC<&VV=Qc&l*MW%?)UG3)*5h9JKWJT&sDujo0$7sF%5DirKemP1 zeSFPJqHTmeS;~3kcYnI3O|HUh)x$EuT^Zxs@^W4uGs6ercOR*VhI!u{VjGmtr{COU z(;z{czT-1r1AjaMGF3{2=4_cV&Ve$M=;V^Sv+7XAB1x1sipt$}PriJZSXi?2sDu$0 z=6+>*)TZqod%0sah_B55O45;?)eWZO=lYnil^xB;0lLawM9PPPV?JlUQQ3H@ZeM`@!}7*syoi#foX^Jin@bblhXXYRc%9jg!5XSFPxR{9 z(PBXrI)EZHIem_$iNZeH3cPWdo{`eI$kp_Q5hZCrj<4wx>z`DM@}>+!`W|QVX2ZdP zc&hx^Cxg4Qzugb03FkVNW+seM);l42+2j;D&2S78>2I#z9#j6BZ>{0CmL}^kNv4hx zWmK9JM2;&Ec}fss>HcEAf8QBGpd34~)eG%5@WdM5Rde`zyXp5fhXql9 zo>{PcG|@-R4B63{Dfi8l+`fj(y;jw{-tu;oSFZ~4%%1iPy0jZ9XB)AQ8!zpMl0J2L z>Ml|Yv*Y1nSLt}8H9i8lF^{%4I2yx#^XX(TH}atnex|gPbwi*6mw7F#)4GTyV*l$` z=>D#++{#LFizDx&WFK$!WX*(2XBk-URQt?h!NdnPI6gVm;|FwhHB^`#DmVf ziGOpPOb|{pe@9$?9vsarNQl2T+*(bWyw0GUG73o4vw2{BZAC+m*?05}hNcrgSGSS! z(t=rM7qJCms`H(LlCkbd>IOZ<3=xisCm}L&nx+Hyy||v)^k=>5&MyV~v~F-jGw88I zzdcIKGqN*@$*MUB%b^F&tF1aEE&)@#WlLDeEoBUnRMbw^`ZO?XS&XBPvv^JZ!$g#o zF?YdeFTZ@nTUpG>tMaCNp?_e8!~6~8*w*gy?`-`bYW0+5U+rmE;qcfM#k7&Vst_DC z^Hxo#D}V}VE)jSs61Ht!64Ew5&I%Tm$H5HWB{y^&*a~_DHIwXKsrpzQa*BCC>Sw!Y zvwg;W0+;dcO=-3v6z5J)wsse;LDwUMpsO3JjtsQZ=)jp}mbzL}*0^f%N>{infN7pQRd0 z3?;qCuaN-#y~IYXj*U_-940|kU0+|Qq-@ns{$;G$A?YxJ>eRw8$2RIiGV#oIV}zIP z72Q%Z_x+Km=?TT3<;A)66?Y57)ON{}7is*PU$Gn$X!bvpQGaXF=pUT4co#F1SvvXE z^`t|+w36>b5Mtd&%)LIK2Qy0w{r|cUdz7BR!{{)Xm+pqe9TM=^7n7!{Z3%EqRB zjZ7_5e21YVabln@_-dt`7Vc)Vx>>`4*HL|$)Xh)fBfwV?xXb?`=(Bv^$bb?Uqu$tr z;#*_OBbZy6ZM+LfO9gY{M+phu_oq)s?K13{76DU(PTWDQGUZxQE+=HE-e@9 z+(K4h+VYrmvteO4fK~(b_AM4BCM+~`Pk+DFOj&w*`j0N0NRb}z<5KmsXJ|a50s&qVjNFbv-OBtnTAp zZxnInxoW$<1x>Gr`ex7K^;76I4k`u)Movx+3$~Pykl}DD=j%3=S_?ZH+qzlfhwAy& z4S%l`<;(&swyrt|e^hw*?{ofsjJ6+tJ{n8aH4X0X4%J^!YKHo2;auFPC`|Ho(}ks; zpWDO1!C@m1fBCX`c(^n-$JWtj4Bgo6B2+e=0j!J#PP6)>^Oils_0(QbWMVp#K8(QU z(ed#pZ|}8X?x+3A`>|~C-Q8UflBVXv{mq%c=gOyD!*ZtSz3Eb7V&dgi&$L}mdj|(q z6_uXe-sW#NkvyNAot-IE%0AK3zNg>hPBs}fuQs2hb91}X_I!xhr8~d8Je;lET50$H z{Q0xOkq>OWL5N30JzfR*0enmYE`qi>$X+Z%j z0z!_fzv9I~_aTwBoejrn6;}3EaFzBa6BCoO%|Z1h=aUEmVK#R5Fg$Kc1A~i;J!M*2 zvPzW+MyC|_WP6(+QcG+Oo=;dsgBSgA)R&i+L_|aiM;N@}p`oD!!l45x>~T#p;^INO zIAi@*Qoz3ienWcPP*y+qGZhgTDJCYC$Y6pznI@;CWN2y0<@tDDX*7(6j&3zy6XNf` zwLe>_a1?GzR`Hn&ck0DaD}awoy_be_RvNs#yv`h{_jKgsW><%c4Gj%dagvf!=f8qh za(v~ryU{ILkr_?AM)ITx#qSo2($oL6wecw{Uv2cqRaaNDI~|%E8#|w@c1knr*C?sX zQ740vppq+1OikI^UZylYzn|OlpV>ITblKlL9 zhQpPUweHEuNl{VJ$jC?tL{LyrQgRUFSxsGiJo7uZzhMom6p5+H5o6L9C(BIQ$%JA# zdHI6_lf+9-a&mGuHZ~$6gZUbZs(qt)q}PO7Q`gP?lm(`$I_Zbyec!Dn{D?-iSmUU* znHU(FT+Y7SR#aBn?M)S1SXg*@O=Jz>B#}ZHxAMGv`7$~>8kf_xhKOvf0SqUTQcLie@8X7Vj2DSjBJ7hrz z6sv|N?|_J#?h|TXUmr+`@jVJPHMNV&&09p=uQc(hm4>3?;#Ze+=7iY)+pDH?+Tk5A zm&{f^(RX))Zmcz*bc+LCPmPN|@c0y(RLR|8c;aGW064@&?zfaAJ|Q(VKfld# zh+n~%FJBT85}yCAAGiMHdTRyjo?(%vz~gif@n?zliHT^9eK4=Dc|md*Ean)%el|8X zZ{PZRdA+nB6py0{2n-Yw5HL0~J3BrmAtmMfc8%oTKRY`Mo@rYP;Lq)HALF2nxz>q0 ztXF&MqDxo#_l|$S&P_ETvLrj9vTs=#jn}8wFaL~>%d4s;#KkEqDLMAXQf@P2dwoJc zKma4)d4J-coQ#c#I6RO*FE1}YT8oK=H9A>TT#QboAtL|7Zz6~o%9FyL?bda&H~epy z@9WPNZ=dMx^OHdVDk|tsxwM;I-#`GWVw>n-sx^3=d9>cztB5+laUxjC*w^#il8}%< zAWa?*i4C7QLwi)+4hM~&oaobw+8VTneXdlU&$neyJx4&_zke+%CRR~Zg@TH@v9*=P zYG)`Q@Vep4Z3+$wioTA{pYCpAeEf2&Wvm4l|CIvo+g1Kqx9Q z+pD~PxVu`{6SiUmQ$$5Y_2G-e-;E7LdHF`$4OkZgFqEKOoSdBAzkiR7Pz!kA_SW^B z5`Zu@btx@-vd-s-@GaUKrN&o>{_gl=)-~fBU4lD1Mb??7g8nRSb=ILCB< zJ+(bY)Y8&A-#j~7K?=CJxd{mgStn|AI*N^p!)qqE&0o9v(1X8yatHIOq+Kk+%+9W| zrKJVTm8K@n4;~Q-iPsQpc1H>T#H_5dV`I;Mhq#@nT&lIPx(ZT90TNo;=tpL+ou0Y6VqPCESC0s;b9+1PTjv)yk_4FKNW-`}I6qC$It0AD~RCMH%_R~s4| zA08f9Sy`K#o8Q0g?d^R5`F49A@Isi8qh&>VVaVs=FHAI?o0}Wh>jea`OL1{AwAaks z99U|1SC_}#<-y~_orZ=6wN?|4GTMg^fRF23&I~~}si`Ff2Mi83WCEpw!HU{LmE{ zEz@$A-yJej)W$aFBofy+>-7eXf`Wp?i5#@P`<>%lkbkfuw0Inxzg${RH6jOYX=dj0 z+cGrZ^&FS0uLpkm3G_-*64tGgva+&{4nAw7^TRD8 zH*ek`VzYez^s}H~w?wm%l37g4qFHx4OD)@I$Z>1HUmv1$3OC&m8mpYbaK zKw=OGNG`uN6EkyMY;5H6Vx>`7PR^IxE3o!56?66Z*5Xgwlz#`4n4{gWLVBtTS{CnA z6DJS96F9BGktJ?7o~4i0+9JJn0YO1|V-)Gw@>rxa=i+^#Vn4k#>m^}wKIgrA4HM*h zYb&?cr|mozX=&+GKPDz7At51XFG3=s7mynB*^GjM!1fh;d;4$Sz6sq~3jt-zVcC)D zGQ(Vh00;L9f`X2oNo{6oI#T&QyR@_w6!zT8#^!|8ZZmutv?n$?x-#euOG_#UkCxVB zn=c&bATW2Gy5+dIxS4Jo1V5Ns)b?SIJz|AAYl+>hG+w-T0hn)aP{D6hfoGl+n?tKE z6*l`}7W2TVlGE){L{v1w(-~CB&f5C^cCWN5x_~2lWCr>shw1*DJ7_IZvG{QCz7 zv-NI-O<5wy;kM8Knz^5@2Q)OWAtE9|dD~c9Lm&)HOp(eoG&DRXQ%Ib7&mr?C_X zkt1bgoHj>^liY{#nr`SM6?Z4=1>%R<8`p9#kw*B(3RV^WL3Fw*FEEh*K?|56?$whix4r%w*X!Pe!4h5wzjds z*d+e4F;T>V`x4@8J@V|ox%_GQsx&^iy1I^zj$R!tm*(fw($i;t&TrGErZXUVvpKB0 zwSUh4`xJg*I0hMj*<3+L`wGoR_&HD4-%p<)-$6ZZ@g^1*DJdv4WMyr@IE{?RfRU>< zn_g;hce4-m#{3A+a$hLx>TytrC(nYA*V3{yI4B7i1Lr;!07^&s2WTH4sqFto0N7h< zb~74?2Lp7e+35Iivy~S8D)J+o_lwXk1=69jaT8SyDKPz{7WX$y-kB#|4hM6LASRua z@+6!_d;DgZJT3nGHt7CBGZDpL8?VOxSOG}rl&6Mrz?0^c{oh$@% zRbRJ#uPG4`@%uzr$g5|xUxcUAmwtfL&DmL_*%h_ehz&h)NrlC>*=}nHNLK_fg_r9; zfBxLAe0fs<1^H`TH#8&#`JR_&EZ*-q=EA_t927W~$dj~^P+ViVh>3>w{FaZivjLxa z()s;Kmb0-HeA-ta5MzrGO(EVztLY3U4Hs&1(&N+fHqIgXczji6%9!W(C^6`d#bI~c z2Rz??Q>4XlGIw^acg5veM8~qN%i_vE;t|*Y_nL@;!rat!cXJaB6;)A7%j4#Bumk>GM^Llb?K;X$cI3y$~DaqT*Ykz-V zLQ=9+v(eDV2;d=V1KvwY>n06!rX&r|R9cnosl~uGRxL1-yIIx2{BlpAv1Ox;HiMY8vuhZtIX5A*X*6@}2HwTp1naVhl zxd*o}k&)Z_`|rB(Jb#7oJUn^dCMS4nRssm8rKPQkiF-sLhQ_gGobe=>0%rUt&oVte zIeB4T-ZpRyn3$N`k%@_zfGba7K}BqBZ2@RTuN94UL^U-HIOnMDl1nH@o!%19UMS4G zXC|=7j^K1lKPka||Ncj(E>JZ2RNM#8*GbeHQoA=xTaT6018xKK^Ba?1K$y&D{_gIo z$;#pr6AKd}b8>J1OwQx{wSq}Pz?%iZ3)_HyvzHKMEXu>X=zBK4Xt~_-&>4gdaAZ8U zQfSJ;5Qf?h@rD*sDeduDTU)!&=>-G^24)*iQ&ZE$#l=_+$;@moD=TYv*Yv!2eSIAW zE_U|D_c7@W>1(}>8gcUJ?4>PMd)u6iqt`npH(1#A-CX8^VR1a4fTfKv%goLuA|d%% zLDu4aC&ZObPe%uNK<06DTuW=}ci=eR1&45QOX>DMI0%VOAT-Y|e}12r#f1eb?G}#Y zvKSFQTp!PeL3Y=a=Aqe;E_ir#lO~?$k{a}**?!rrsi^^wL`0Omg8p}Zjqq&ev@)k> z#1XqF#6KuXgij>v#p$X1<6E6_mD9?8;Ap<{K6*nSK%H)T%E-usS60#+kmX6IagmbK z>y^S+nw+AIqjDT|$WOg;{l4u)c5@#b7A9Qj7_Pi$x8Ky%1PnrQa6oR``|ndBYQ6UZFch@?-(jFkeHZUD zQ5~~FMyfPe_>X3%r>B8-=io?IY*YGe8v(k^*!AD$?%o^`AqzU0kB?7Qc64(vNl{Vp z1%#B8)Oel+9eujqZcA5B@9gXhIJL3yac`y~HdfaBygUlkigiGa`1trGB_(KRXh40p z-<-#WrlOa>Iow)qNQEUYu$g;S@^XJA0W)+y)LuTR|E ztw4hoDwlS3bQEbdV?usqWIUtN_V!26QaCuxI_-Xdn*l8aU#z?vt|4-Det9A#!UTa> zAj84H+}z)sP2|hluq?!oD;E?LJijyE!Mu@`)ziT|^J%ajFciXJxRfL$&~R{#t{1yw z+2S|X*APf*YAUe2dsD?hVPQ{a!`!9Xt%oZsKQ?g<)nad9AG^1%kbaU&`($}wnf3`a zEY!(#c6M$P4HG)ov4Wv`2pe23*LO8n>hyZWTdQTnSbGIu4g(|;s5GT|&HhX|0W0eb zFz-N)&$oJVAEdm>=MjHa#KfSm53mFgB7lLnmjQPGMDRzzv9-1~wzA5-&(ZsuxURE9 zuN%~B2j}DG7Z~)s0iBnVpWiz=D$B#eBP6s57A)|2bZ$;fMrLGrd3k<5DJY1Xi%Uyd zI?Uf+SXC7Rr#y&^oLs%m8Xu&$tgH-ZZG$hBFG92o$uV)bJ(APXw3U=<^7Bc_$;~zg z5>zOZ#Kp-;Nb)i=_yh$7`S>#G>YRHciDF}8Yb_V$6cpB1R%jU*2)DTBT0K3V+I@EOiBv+ z`MeDzGLjP#>KBDs5CX@)f5rV2t|yQ6WZ=-; z4>aYOZX*ixRm*iUySux4)1`P1dKq#il5mNFW@}N`SBI!}gA{4|8@_ zJ=ENf)m}+K`JO`v+jG@s&!0VD!?g!=()e^@&%_v_YD_~xB{I#&O z3=Iy>a#zN9n%yMc9Hw_kIT*8*eh}aIDn!fk7+P9_ct~N8q1QFpy8Mh-H89mW- z1{gYb+R>ictabx(uW5*py*i8(7vb&}7M9i+oKEXQx|$Z;x43YvKFjx0T@z8$D%#af zul)TQDut{^exZKQJTgp+vGM$>IR*9Zhg%FtS(}{q=!S0A?rrE_pU;nX zO(^6KW$ElV1_9NM@*Yp@UES>s_02|4A$1L#C0|PgGnwDfjU#uQVB6D5T+6xlG0RFz znueXh<74+fJ?19neWGTIFqbg&mEPX!e~~X`M@*fZ*%wGDps>fCY(}5rXIEZsWAAaV zAZ4Ow%r`n8EoUN|yhttff_O6s?u52M27YRiANon*l;pFpLby}N0m`n&hsu)kdo@{J z^R(Xlc{Vp{4$)ppi>3-aD*gr*`hdD3SO|}-Vt=BY722R|hzRKgr#?M`-g~h#BT{*x zlDregNqFP>dRI%6HL9cS`@o#3P%Q|LkjLVAZ)Qx|&t41@>2r2d&ozUbv-0oEXNfM>E8Epic0H!q4fjdEpb1PUQ=Ac7v!1c zYB=iz1u}w>qu2H`E)~=|h3#8Q zcanU|lan%BWyvu87>5Ju)l=M=39veMLDKLk=)Y+`lpqYORamuPg!OD~hV zLvb>{Y0ghzoUc65Qx#QC>(tX{7FRm43|AClvGE}X4n0Jj)0M~wC3{w`RSgE^>=ufL zMG;1?q=|v)s$q(scq$HTxSTJo9OAeqB>TyETR3WK=dg2v9vY6+u_m-%dzy0_OND?C z+|po=nCeXQ>0op|In&ILl3Cd(azHycQhW6N(>>fqWLM4MG+t0v=d~gRn>MDN4$ZIP z4{3>4PbX^&8rW}@Fsu)_I;FzH`p_x+|)yG zyuMrXL&tTDfzKKp`4d8)x%pm+={8MT$?xr#bl;J&t2D7S|3=>Rl?EKdNHRiIC!bbTi=wt_^v=a~#J?@)(h^3e<1S|LDF&}&>#(2U#^}|@L97%q?a~4Zq+Jh6fS1--xN8IjrTW? zP{U|HO5W~$I8{}H-@;0zSCv{H)oDCgpbmjQARBp$PAn8|)ucRhuiEG2RVm7yYOs?p zy3*xD?eh9XYV8`gzVfB&(%kIbi5;qW$mYi8LXFC>ed2xZ+W=~Al+CB>A&)493{KH+ z3y#>`I`t`(49NqNYn2750vlQ&tv%OI?Oy$6^IV3?5lH&u**)B~!v=SyWMpi}9r_B% zZprq)JHyKZFoj{%tLs~SQqFkNgB2_Lq&fNdF>I(?q%=p6W_!LhaOLj*yRxZbUgY?@ z^EWvCYud*Xv>GnxCs)=_s1I5Pe?AQ6^hP1A^D9k?E_Y1h!ENpK;;EbI=P}xFaKlRX z7joWw`mqoO#mnQWbueTw&P){#>z|We0+ln(^kgK*>+Y~))=0sC(rwkP9sMbknDWSN zGRy--YIAq3EcYD|Je10i%-^*Qss2Kuhgv&KK0XQ~61sw~5`tss|Tw7zdds3Py93Io|L>z&2BOodKRdM6)>SCbT7;!0pW}1L2Y*E7Lyb5~s58e|F z*85b2CY>KtQ1m>8h4gz{!NWuR5XkEn%CE+81=qvld_2iy!;xJd%4HOg_SmGy^%ECZ z@N`~5jLr8ho6de*FVBX}H5{wHxtO9Srp=QX$SyCwGZTGvL-h8oVah|aO_E-E>rG{} zya!=&S|)wT7Bauhzn4P?6X{N7nqQwfAwxbf6;?FEQU7Kxna}E#YjLN}GtJT9BgB7e z*~!VF&py-`_6jnADuCGVu_UeZ?A(3n_RMOI?PR?+uuy#})y>Ypza9j&n>*2p>NuV) z!i)XvIkCJ&f#C_zesVYbn5dF0Kj&4I6&UHbR)>O5j7SKUmNH$r{K>-bS|$mgDE z{>0(>L~od=;`_E&Y2a+|TYT*luAS@0&&)<|z6KELkG)RsJ%x`S|2b=KzviSFVtLed zrMfi9-$PbZOD~7Hh2tfAuVVRX5Jup0Wb|2D04{qY%=_MKdByB6KSLTXO>D{c#l+vC zsz#I&g)9xzX?3B>3`tKdEPY6nVUXqfP6UMypF0?{LG2eG3|mXT;u|yQ9_#-FOc&A@}AR!G=w0cy$~PhxJ~2;dR@iRm?BvRht4eyccrcRO_UV`|}IF)l1QwyMIs z%#SY@)J5K?wor@ec$+-GVQ2G@O`NZ%O}HuW8K0UP{#bBoZnp6vtmn#P1N`>Ok5Iy; zR$Ieu7h#x)mXPxlPM>zC)v()d``ko~1+)r0A}if*IdGS#!gMGT8F;0qI~Fh%-|e#E?A&e`>^s#vO?=6 zEorS^P?TOsO3mFjoS9~Q9>DCafz-+G8e!oDB&F6LUnF(EuV>aa$XWL&H9L&nzY=6$ zGA8-yVnO!>zo)h$Co4HID|t8At3iw7z5A7mdCMkYxuBf_hPsF$QjC(4;xgA?_2$=+ z-NkjU3gOW(!uA4p4~f=e84<40=FhRePWDun7tfzLezUb4{7TMH<(R$co|e!1aPGRF zo}Fp5HF;%h5{utZj%L2KmI_So;#ffZDma-3KaRLh|!ZUQuiG z!cp5jNAC16#@4Gaznt7J*(IOYaB74QSA~a_6Fyvh_$=3_6gvI>+}-*s&41lAV#%Z? zfE=m(XoZp#tL(Otw%%)-0SbkoDFijH6nSlTw~%vrcpF>d7kijfbJ(ys1SE!EY{}G+ z7BUR$*|xl$@Ng;9Trd@BJHX{|&$Dx7jm3&h^XnJN{7FA-bt_;K4L_3dY50oWUr z1z%$5v$H_h<3Q+B*yjhj-Cw_RFr&XkMT|IkEhof#@I7QZlk!BI5ipWjDekQt zk^uP#mK|{$eqpC&EgQYR>MofXRY?4D(mmoZaAvwa*xtBY;CO_(co-6XbsECKlcq4aQh<$sRbZ3iI3z-=GFM21C z{~1pb$X_#2?<=Y^QZWKIR~gyqntpaQW#1RW*tjh>Y?pYjkh~(RG^?zAE^VVMEI$u2 z$MP{0)V5He{CJt0t0^Z^1A;(}Wx^N=Iwc(L9RgEKHogx*em^z*y>os=3Gg8_K4dUN zRI^LKYkLTu$)-7zF$o}*%?LP5I`4{`UftOtn{=p0APLCJ4!FhLkVO9!P5Blsl2H(W z!TY;e}>6gZoi2e`qH1ZH>g;VNHk7~_qbaa_SDGZYHo+` zP|@)Md_;m)N}dd9VTp9*YPF5zoswQc2Bsn+B9MMrxx`Oxt=`TIv_x6nM@L+C*q{pg zenA_p`w%-!3E@S04ZcD?(AfHZg7yMmDzAby@c%vfGzB40{;x+r8GrYn{(A(i`|kh2 zu6j82t}ZSCfq`OTVlN@U-AkpgF~+7n-kcf1L!GU(zlHoB%ND1kr0hN&S4A*zNUx}@ zWMp6v5D@sNLY5=w!sYpJJNf4iuZD&OA79(h(BawEa4;p7{PR5$=+mv0SHPS)J3Et* zlCD^@I5;>^Q&S_O+LewD&n!oK1XeVt!2RH1aXrr~Dx%=#ekxL}TwTjg_#PhYu=fJ> zjm*mD$8bQBiqva?;Sy5G*+ikGsY5>GA4lxwyDkU0uDqg|MBNh)7XRj_xw8 z(Qq))?dlMR>)Z8U60@bH$(=CP#}BFh$77$PfmcAbAJ`v*-C<00=QLF$EeNNh+Ma zfq@Q9d|4R{I0`>MP^O^aY}bEgWIVsydSc>Swb}GYN>5KuGKUNDLt{=3l=mMB?Uv;G z_jGi0=u{dI2q7`Cx~ghGKmZIh^v91M1%!k`XLUkFEG&u(3k!XGUZVvu($MgD+P{P_ zSw4Sc`poQXKnrMvqF=whnwaD#B+NFuUEy*#fB*9p91;S_&(D8;EAab!K0ZD;bSere zDk0{2*Na^rm=9jw-r3pNR|oTPQBmH1zUu1ffkr1IAt9lpY}V^WIMtigQJU@!!vjkZ zt`&k}o*`Y?+UoA?^qqoI6G1=-H5yKp)l`N&->YC{Wrc`{2p-_$r{A1yfj-93tS>1U znw)f4?Fdkza6Daqezp2Qd*U4ylfI#0h7S4j>)5!9)+lCMtxz0t9Jr;0g^l(*a;K(D zOibgs(qX~D3JMCZAz+r%5d)wKO(Eaor?{vnSONwn=BhOd z5m7c6kqBjv`|I-5)YR|azx((+zn3vA9Nb;Byo5wieLcoIby*dPSa0u$l%rneYY-(EQ?G;s1O9a0Y7k~cfl=b4ex;m|vZvkAb zISa2L)>ns`08_NIv|wNY6bqFij+9>=QnIl%3=<8LNMNB_TU%%4zj(8;G3Y%zTRGo#fIw4%vbJaze^&?$jCrP78Dfdsp*=AEXMid=kL^7 zEkht&TwF0RG0|2h$Hx#z=syJWILBB3lSQrBV1IvoGMvVJH2eIq^3NZ(0|il0Q3+=k z@9gO4>F)=flumti_WVh_#YII8jg1!O=C9wpS#EZVi;mVeH-ElOmMg6X{-;1jNQfjK zpI2+Er>kp2dU|?sG36ZoX`3$`Au>!eW`BRbbQ;&e#zywP575jiEj`-b*HBi@&CHZn zQ+vL(2NyT>`uZ9S%jTw`xOo5Jp(O-@h$t;A+zrMNtho+!`}x~F0C!9la}xk|{{Hbc zn=avWyM%|(-0wz4MPZG@-j@E63P2@Snwg)sT5LeIn3@Ba0N5&yLY2=!^97`?z8wGtN(3JU7)3c(tU+5+=LMMV{aMkyvL3WJDv zw7bhUzXUZgISIhh;qLMP%*tY;Q+?E0~%jNk97Wy6+m&<4f+f@<$%-Ye>(!#@7$?C2;s!B8HT0zV5_YO#7Pl~z+cU>R^qTl+T^7A9Y!&NE` z-`!3nGMa&Q1qfGJS?RPtQ|_=g1sX8JDkd)O>EUV_^sTI{?Be3$y5w{HJsxhsA_3%c zy5BMo5g9z*-#~l8*VKZ}y{ccw@HNSNiGY9rk_Dc0PV|H4=g*&Ci#@skTsAnLWW>dx zyK2KCAmHAr#sbm@$|4>$OsU7y0Cj3m<>}{rDY~=(RPBDxUPi$tzS8!qhhAhPr0*># z=;+)or-WXgZfl3bjf5%9PqmPQsA-2rGqdo8qjYKw^c6e0W!UEy+O z2w>L3*C*BI`iR-9j`}lm5t;NkB&F{qNx6LE!va z2cwz7AK`N{GG6kA13U(J$-u;vVKrLV;5RijYgW_ldA%2P)7;;@9mg?N%)rP9WK!6p zrkWZo1R5S*0I6ekR#i;w`7^`;w2Y39+HDO1q9`aX7DUpYF41gjYfDLaTEfG`!~}yW zmBtkUuPV6iy1l=Tf`-;&z4Edlw6&EREy%(W_Yd>?*~H2fRbK~!#e%E`gWeToZcVT% zi{410^|RSNa-|_xxe7 zEZ9`c%vZVHNty~*dkM#BB|;`yHWNrBN2r5?gMiN0Yr!%z^Ya59CAkJ(w5}Ha*Ui9j zr|{dkHWMdzFzZO?*AG4~rgbukROpR{1fGD-1TvM8nVGoNz|b%@E^c~cX0Pj3x~uJi1al$5BbaiAvn`1!#S*uVO>t*@`|jORw-srL2vlarH2T|r0+ zP#7)d7*3Z#e}IfaAhCHR_);*C@4>+Xok8e8+IwCf>j14pN}B)Z_DdYF1~43p3k$&D z(0qi4@)nhp#K|Z*Jv|K$2?6$n6t6C+j&ZQYuA&J9u)mK_k#_6S;^G7F9TT{05APf?!`}yVR8=tm z`F)B^Pf!1vm&^UurzOk0ey38ppfD&OC{Yd)66gcrll@tGFw9kNX>h|zOG^>q;j4h8 zWn={1Oo$x7Y_;?n0^|c|vy`wf#6|D;`1rs;*!p(Fk6D2|fN7OVG(;^azFqDoWM&f7 z+aW}49~@AUkc^Cv6Hwo5#A%Z#%gD@6`PA)#q-mwr}v?l|8qm3 zJx?28WtCMAItdAs`pBcBZ4z@cGqZifZM}%OIW<;RRtJX*L_97)e;XScgMcYO1lz2b zSXe=q?2o4#K~Yi9A3mj{gC8K!wssQCo|9fxQ-cis`o)VEr#ef3Cl|P3AZ0ddT}@3K zAdRS~F@G+R(9!*~WmHr|>ixO26V^*%QM^8V7c4OQDgRPaXQM9$Pz@;I=%`H@=ZKav z_z4b;0!$|mf*orofNMtILfi#d^tyt>!;z}sre{9hij=Dq6&9LlX{8nxlHYQaJZ*mM zDL9mu{TklT@PF>yt3ehN5P+981QW{6-U!6P(R{5HXwZX$0|i`;=6BA<(G3j^(68G- ztM*R%Y89`;;)U$$lJ&n}&jd0*v~RbN z3#+ZDh>VWr_;yX>qJo9sPf!|MWAF)jY;=_Oa|FrWhX<_UVf@Q3zO^{uU+LO+o+G*qXhP4_z97b$k(I!f@*4N!otD= z0{Q?iz_Lq0lK^|ejstrC`1JJgq#Mszc_T3qQwY0b7zPebuYBhG+`iBE`NM_q2$4;e zTb|eQ{{4HarKa+l8eD5cyUhXKB-)-4?Wp!{;&nuU*o1x1QN0O{aGLq{MYBF)f24OK1#1QjC+hCtw6 ziWHR&(m{|x6BTa|Fet@@A|SmOa4>KIxqyKvGu#oSN|_yfnWuS}S!g8W>rc+v zdw*s9J8MHB_`RBMg3XGKUH=P}${WDh{!8Zo%j#zkSD&XWATE&K5QQwhz1@Ay87?R7 z|D~yq^y&+(s_Lkck}nT`r}_$XsNl8h>ph*Eg0b=)M+{`ri;5y<`-?&4Q$39b^U5ck zC4vW8EY{Fa)aR+&$;r0n<}JW30~}D3ywPQG3Lj=Iuu7RAOArO{DWy`?bb1hWoV)my zx7If{F8AL)~Qg?H~husg@iJ1WyF z`SNtJAxN&;ii&g@c__FbBJqCMNzmYUW+*U;l(aM-!t%z&#>VoR{uJhGYB1_3J2{`_ zKbrZpS(Tyjy4u>@`FWL0Ylt;BYjDtUA$wlUt>VM%Y&7UrumIASYb)!kx~rqbk?N4k zP}j~loZ@A{uAUy{JMU#x0D>Q!Ny^E|G1*$zRZ^lbnWN3kJ|71kt*xzb{X;6%OhtFJ zcXUXgP+2A^f_FN!JnL93EmM%idNXO17M2y`QV;6n$p+wK-k9|-Gkp*|h3kp$hFC5q zBf%Qy_|PjWwYXtk`g(d#-Ji$j=ZCc=i*vJ5Qw0Ihg(Ce(Tsqh-?%W)&WxcGdwzd|O zf3(vaE8Yoje|2?%)7aPuq07t4QreXX=69E{99RO26ToXtE;P_Sfk9hN_aDbK#->-C%aa9^$kag@lA0!#d=rvUuwmMgnT_y>wo2nfRIoq zi8M7clb4Y(+z=6FZEaohF3lM1O6lq1wa?R53;VzR2~V~ea{VbOZkr``2mBt;$3a0s z>Jl~E5fGPdZW60yv>&aB0$K-XI@6iE1q1?ypG|THsNifg(CDP}^qQ(FrCQ70;uBE# z3t-d!1sjy3Xyau!c^DP zY_82!f)EBh4UaZBI0#H4jnj#D$ET&G4SZh~78d;5w{4s_b}ZkkTIU6jvyog=;5Y-+ zKcwx*@UVfQA=p4vlq7bUQD{h36-r=|IJTht2?Q==JgAJOsBe}da|lA5ZchW*1!4~D zEOsj+Ki{fjk5r3@6}U8c6l!UCB088z9IFdbHZYKs^-Ya;2XHGfiI!XYByFs$Oa%{d z>((tug}$O=)Gk*?N5{^W?-2xW0&)P*tcg75>ghQK;ccj|e^-IGTXoJ6@S&eGHf{vI z1saE64)qGm2^O9+JA3)!#X1H9SnSS=)>a}d<%))P<2vjEY#l-(DVgXGzJ2TQf-nFY zn{WGe_+C~XS#Pd|H*hf`0thLXL^^u(C@X!swfCW24T%FN*A1KN__%KSYqGeSS3@`% zk{?`!mX=m`di~Aj^E{Luf97+_($W&-w5cg#C~|{azBE5BEh-u`*>ZboY6?7eL&S1n zVPSuP&V|GVoYz9g@!6_js4(Mf{cvJ@1vts^jVdd3w~o`V-QMENm}aa_6`o@ z5Z=0W?OJbNpX^hnH4Y~l4!S6fCp#y4M;%8mzee!|?*;9Y!3Gjd5SDj6dlvj)UT!X! z0kvP972*^Kl>s5CV6osm>_PyZGTlr|l6Vb+3`Pwg{`ZEtXaHCHTo1%7T2X^Lco0BK!jT_K8dIR`i#deQ^qCG#Z6M0Z^Be zOmuc0QCAln=a;3VEVW^G(tM(#q84J70kaKJ)xry%8=KrB4@7D`#~^6xRzZQJp`Vml zMt8TZq9SkJ7!Lo#^vD^8B(C$O8w1a9C!oSy937{or*-x9`?|Woz)OgV4zSr)NBU=P z@0D1pEK8FMJ`4sPlX z2xlkUTW-!6+kO*&l&i0#rj{~8T$wG24k44lyS{$?8l~x3ke{DWQR6>EyVs9nLaopw}1bpu1H;ZdBEGp4!*v==hWZz_Npr@-&}W%jI5{AbxYuP~`mld0O7-kDbeCH1oA$NdhKjVS&VNmX($D z^yyQqg$0PG`1p3vfh=& zOEC7D>C(u^&D9T{u~$cxJ$fWACI)=+fI?AHRK$6D8l4Y}-T1b=Y~n@QDQ-xy3yjrC z^K_RTS9Zf#E_deQ(=0!9=e4VlF7XK_d3JaO1eC|bAjik0$(H)0ONXfvFRP^5Ei0lo zR}X`g#)s;M4{NBQcqcCV$^mrIXkI6%yZcC2SJFURtit1r?CdY|E%U?eWQjE z9WEA}91P(|GLEizc-Ktg8!NB*&sm|h4SV0T9k1GHc3P;nYgbZa{q#>3SKNeSZ{B=Y zsZpqUHIwdd<6wvH`DN7>LDUP%&D&g?2xn4l)u^1Ze9rJeRe`<#NDWcrB(;S5J5JLm zIhSr#A5L_Npuq5KksXhF5YEzvoW;8+w3#3mTob_| zCtFPBqiYt$;LFE7u*D(lil4vzecx6)4~MxzCf7^OPeoZ#o3i*OKyTAH@P->zC2^84 z#<$Z&yj9|C;|NOG}@pI(opIw@s3m{1CRpw|(L-1oyc2VtK4Y0W;gEusY z6U=YfClTZik0#9~LO@A+iJZ!tJM4*F2(pJkzKoF-w{m%_S59s1m?c$@G{{#pNg{~M zBC|NZi>N0fR(hMX1Br?5tUQMx7tdDwyUWV)$KMAcA`-82)`5oFj#T`fnr%&FudS2_5|qt5xaEn>V!%({gV$)w3i{p4ffv@28OT ztxis!C@jK*q4D9-O4!=kQV;{8pQX!}4VZ)UceGU!|nCP8T zl@@>g{ONms)85L8nUQhq%a@&oH}ZL-xw*OT-o2~;s-mK@cp~Ax_Qkl#b8+3kz+i4} zPE1V9@9*yhpZ$XJa_$fr3O-Bak(WW2CpPtkZ5My3Z5s3PmVXW;UAHhLc((mICMG6d zCFQ=dvaOxn_nDcQ>FIb%ennH$pxvb&MDW3ZyOq^14Fa3a&dwc!l7fPQ3eRpm>y@8fVRV%>5RwfqOMF)@xm8hcK5%gVT>NOukoGliYz%&K?B=!nsm zVilB>Z01`7v~N!g4sL!cHH4E4x;UKtGgG(NWM^lmtE;Ph`*2@~Xx9U#F8jKZlT*j4 zorlNa>V{)fM1*9}<@w4`x;J+Ekh;2hq$KsT*x1;TlHZG6QKHhRsi`6^OY$hp#F*ii z0>Alb;q~l8)C*_6e@8_q#!P{PfwqW6?9zv*xTDHdRRD|A?h|;?{apueI3EX%sje& z(BI!5Pc6(x5%>G|Z}x`;1kv5U22-dhD3tHr^YQcZ^72AMKmjSnQ~lc96u0{H3ZAW| zrUuI~D8Lr(`T*7H14{cJ`v_Dx1Q0@5U!47Neu^ZeriKL8|HM=XVx) zgE|tIl7W@A&SO(Ib?VzUGBPr2CnxEE(}QSY*10Ax{DQ*#d{Ge*Z$Cen)cnH2BMBBv z^ib9+>!ITEa(o;dMgq+I{Cuam=H1=hTZzhbPV=ySe|L9Ln&mzfsHMYWo0`NWuFtmx znHn44KtKhXo14FW{TiQEfQp#7u_P9;Cz zN>5Mk!Gi}54xFmzf9mE*NJ$qxy}atu(x%JXE@RB~b#zFh2s+9Rx=e%TTJB3gLCn-X4U2~7#v$W;UtWG4vEbJ+&>K%3 zg-iLs)O7yGj~1_O6QbyYzkdvIyL8KpM4xv6j*;R1((y1L`~*L-JjVPSIVBB*o(VkBF-j|Uecs=mG++PEi{d>@CM zQ85k^3oC?fzRD({s)~PB%JpYItSj$jhh=XZCDc~Lj7F9O3PM|38~3t|5d)Vh{_n~V zHE!3JfKZL7l$4aJs(t8badC0cv7@aYhPt|Bq@>Aj-hA4hJDv}^x`5w78U0%YN?eRf z`uR_v?4T;4cZCH7BiNzd&`~>vht*9?Xg&9nlam*Ji6<&+YiSjgmj0Y;zOG``s z0Ri`zh!AGqtDlfy|N5N9PbVFCzO#t-+mnKt+D)n!WYY*5V|oU8z}%S12uVvzTUab3 zm&jCk_wZ2d-n|f;gOmMLem*`bYHAe3WSOy>n;TjHHp{beoXWW>dW>i9-Z6oG3#GT% zjxr3p3kudeovFR^sCsR??P}$ugPhw0fq2brigzXQM1U&sID42zbv0C;p~J1ItjrNq zB|bhLy0_ey|(8@*WFXq=?P$t2L}h)NkCJdWoMfj85ub{S7c{r^Ykzf%(I%9 znD`xST|>+^dVH9?7i`IgJjcI(O=|2WK+*&S1@CZjf+oLw`SSeYB3eGTq=a+rA&;!T zagJ0+VWd36p+C*s#6t@tU|*zRb-9UY`3f zGc$W9Ar6pz&+w%xY(!CCpJJAci;IhsQ&mk(O;xoy@WOW_LzRUXq50_1_qrI6#|06~ zL}xFr$?U^!P?(HGf6LBo@$Dq?zY@wWwmi|n6(!|xz#f{DJ&{_0_M-C^gKh* z9*p7}2;c0FAB#-^I8Zs5)f0a$RhkD$GK)o>lZIxnDJ07wDqBf z$Q)3j+_GBvoCccT6@`BtAtEC3{{4G13Kni|{P{nIPzq`bU3e%|9ugunlD_Ug`x6le zLqkK6hi0Esc|nO}Wo2P4q@<)^?xB-^{P^Jq`OpMoOE z$jn@KKdmtDl8}_-;NTeh`W1d#T3Wj3z3}=qS-t8Pa1k+aaSIEJ0n3k3QA!>j9(H!c zP@h>@Ci3#(d3kva4L*vBitg?LX{w$sE)9VfVr{S6d=EcOOeAycf{H@RjE{{OHhJF3 z;9OW<9{c`1#(e5Wlh-0aA+JSmhKNh({=)=1Xhxip{Ve1nEC4%QG)j0D)c#1-`Xg5NZZ@k9Q_<1uD@7LkfxOm zqzU?9!!s~AIMWu?*4lar)AXE1bPr@RCx;%yG>7sx_DJf zh}nIF@xO552;TqT#Q%cR{|8R|?}weD|NDlX{>os+8&EI%!%bk*sxTy*20)?Ur3{{F zWFyK-qL4KEAEsUSq<}zFTN5J5R{?>(B#u#P5dQCpm!$vat6|h=EUc|5vm{+FKS%iq zgoci4e)jiIcGE4)?z%9bA8?ITM}@Xy3{R90f@qUdbZ8Rki-U(CZOQkaIyuobdrAbH zzLKGrmzT#iA;mOY^{h@T>p`jrtsF;}hwzh1mh97iGLGRuGi-Efw2h2`QO@021 zi>UBBazqU=v#>xL+uYo|xVX^K*0vRR)7B=f%E`%DU00WqoP1NrVJewJ&y2xeosf#^ ze*S}NlM~a^lr%IY;6wQjKzZmSyo1|xjEo#?ZQs9pM?yz8vb_uo7OG50FC_H3!%X@9 zePA&V)5Z0tPoF-2{+y4GZ*g%Ebz_Mf#hc7fQg2NG>pLQPGAP`$;NF%IN55QgZTT(Ud!eWE2!^^=0#c zXEzW8l$1V~=O-YdHrCdUDLl{qK1BrQ=03KxWJERp@+1W1>FL2bz~~!sFRn;{LUTm$_wSEzyHZsP^7EP7Fb;yq37(Zx{WrvTA7MfC zNPqJNUO~ud&j0+_#lT=XG7|F`3sll4449!6id2zl! zf(VX_!$qk%ibF`mLWNyJ{Qh3^0YXnn2`++wh$!@8hLu9fU&JPDM`{URaKZEvWE8^# zdCug`8trG(9V60Ls(GVX(m}0Y%-3+pn*EN{!ROjB^TMv<$3#cp(XWts_|R>!Gs3$O zf?jpCfIlt}D*NXEoQ#bPJ48E3_JRtyvxJt020j9kRze{H!2}00Go;{alfPD1SAYFF zJlk#qam^aAT>15D(TV-`ZB#_RC10euv9U2j4Oz(XYXWvu3MwkcsfxE16<@l#?&|0q zc1IH*8y<^ZlTU!ti&*uOmq(9R408$YdAvv$!Y+b`hX>Fu>^R&1`7=5K)B7*)zhd{; z*&;sQ>B0w?0yl1i^cfl1o2w8D{>FamR!2E9#^~tkN(G#{Z;TfKTZI@0j((SALPhXA zw;Bi6K|yF_OGR)`I|w0U?%qX1XquSdA=vKR>8Zk6fVAedHQRBu47^QDOg!K0;|A3{ zS#IhyQ>!*!09+-Js~D`7E+i-*U}WOxf`5@K6hUY<^hQwlD#8t$H$-OP zydEYLA~1BN<81xgf&yzRtBAH9QZfunSRf|^Z&nd5M&5@Hg8)w7zc&^X^p1^<&CQv} zu#XjL&0%zmwY7gC)*`*W3tyTi?K9*< zDgR?YBoh@Cd&n6`-5VHq{P=NTU|^`q-@QHG-6e&9fR>jpi4Y6tC;Ol?wY9a-&rC!` z_-YFDtv>QG2vSlg@{&|OtC)-onrQirnS<~w!eE<9VpjEcW9v2}S;?TDuU>r~9IUFT zxe0~W_V~x_ESE{MzNzWXVeyGN5p+iQ&aN`V1A)`CN@F@mf@q-V3~2#x9MpJ zLQDumnrf@-ulxG?Q=n@UxQec>A1f;>l}RD!&d$z0EL2B9K$NX{GRC5n9wXzAk4cB} zE637b6sJg%CCiCy&9pC%TOSObkg zrKQ0g=b|T=NA!n)*&$>I5h2IVW$~E)*(bpj%Kwe0<{n}dfB4XrOV|MOq@d0Z0sn17 zLz)b||A|T%Brschd$%FK@OK3TaN2*zgx9N_|9lsOR%A(R)TE?>Q>3>r zj-)z(5alz;cN%zvgjfhLg2H2yz>r4L_?7P8zptkDbbGFar|{qP7cgRX zF-cBNT&|yTEJ;{bJrfg$F!f-?U6D6-!oYCA^tkTaVJ5)bo^OkaE+{B~p|*Hzl7+}j z)w?jNR@c_TB3+J0Awm{%nwtFne6OLRqJkd$_U#*#aQi%v^Y21pc~#XCcqB*S{rukE z-j~YnE?>nZrKhW`b--#N5b)gi*w_y=HD4qrd$_oSv=BfIvFeo>g>2^kwLIQgge*v2 z-~(oZg@v^~mK7ii39nM0bFCPG0I#8v9?#(DgWdud2G@hQ4PcCh0NEC8BRAq19UZOo z-hHf~pz!3$IwZAa=2x#?Ik(E=(ymQ+T_}YV34uY*>x>tbl?L!2rj#H8tQj_wL_^Z{Wy(_YQ&R?(SC4mbyW1 zL=;z0z+x0rlbgE)#SvDYjTufr16C?2d9gB-4o~_#I(pH^K%xRLoYSP)JLfi)pdE<> zv9QzJ@1H->>)!U+g1-Lx^$VX?0tnmL!=uN>@E{J6o12%%A8>kr^5jbI6BPTx+ei)# zG=xd3|N6=b*i$p$FSw(Qj*f&I2-Rl^r#XpKA~4vi%Zs?UILMK~!ND5yf#HzYpr`}{ z1OQsV_Eu4IA^8ErjE{~scx`6|CjixqWQbOkl*A1{4pcoC%lr7z6>>7f2~A5>;;Zw0 zjfW2(`uLmxZNSSdGRrF|CD2MfQc>C5S?ogH*jQUjmGrB9i9CpmW)NQ|CIoGUX2`=w0L_Eo_S?u1+at6NDv_dwQXqF^!_~?FRx2)9A(Rj5whlfK zE}7ik-u~r_CR8g}=P=GMAR_=^4mLJGvF3m?GM10}oG|apeF>ZE>kv$6M4W?7A4>Zl z^8{V`Lk+VeQBqUKrihw%hWqTVq@|`}67%?=>iIJy4ZsxhAg_yn5~#f9d^@%dv9B+s z7VRoh?YO0#(HYFywNU!o0MxAN895J%crM_P zckbK)D1`y`ZpZ8+(Ses2AR(dWF?93w>(>#8^dV0-H-27T;1$l>x1ngRAq0ekhEsVN zSy&3n%7%fxxA{A*fByVw)a3beqF9GcI`F67IOnS`!iDqg^LU#=%^@J#Y{x&kTf{S>_H@X4E_DjVLtqX!Z=XPC{{K% z#lgLLdlhlJ#Kgqpf0RQn6%`kE_ID9Wpgw!V7u&PpQvegRJyi**R+NK7MM>#8!pzDF zW=^+6e{p*o--0o&%&^XJXn1&da1i;Xg0HVH6cgtyadC0rV91L6{QRt}*AXDHq_niO zbabYMh8(P{b=E^v&5eKm{sjR5I-eXLSIv@0GksX+F#SMFOG{VxFIb4fTr=hAPXxki zdk#+2LraS=Q+<1;Qw`i;Vtl;1s;Y|{b$@>!1f-;-goK0yB0C7k?q}#GNZ^C7?}Uv! z7#tkr#clH5%>{7{3F&|(JNtr=mtLG<4R&k?pcx)kcXM+Cph$gguJ7$#A0FOa{bVdl z(vQV1z{kgj+q8AI*@r(u?(L{;R#p}w`15Dgn>TL?3kzdmMfdju@u{A>h#NI}uYGxo zjtcA)x$Q_04NxCZ*U9!jzej!A24j8>>=YdIJkfOGgI+hLE73aphwLLqqCF z^W&vH66|YE6CjS@(qSDHm6a#!h1uxjo4X={hipA!V9r_X?>K;yjiycTjCcYeH_ z01Y|U;#UXa1+n~X;VU{>Sy?!7c?K5<8_-0@0TzgMIGY8&XBZe50p48gq$n^74i1hK zP6GxmF0P+Req2zcr8zn6`*+GPzeIKV$uSYB+`m898UXnI1X3^kYBVvc(9`elV2a1+I5>WPI`PE1Y~Tiz5rr z$6&mG0)e|r*V2bf8eEwXGODVaQc_Z2n_OI5z46pLX~WR%P`nEh#zsa)W@ZbJ9u=OV zG8O2dqMMWc1jPypntUne(boZAp zUw{`TzkR#S!2vCX)1UG35jQ6c-nR z+b*7v>7lP_RJjaiOJ`?hmX?;nDaBL&@C`Me0%o~;_ip^Z!{YJd9gY`SycNa88+G%6 zVWJ?^P2e|8P3E-VW`$#ZPf2b1bsjz>7M$Db`u5H9XMZA;59F1qii%*gcki`}tE#G! zlau4(RDovUtWXdD>M;LMP0+ePq@j7`@3rkfZ!9g}0pEm$g@H~4qM_{$5V$K|0P;iY zmX?(GUz`eFrm#F(muHx?D|+!q0~pU0iGj_<~D+czAdm^mYfAS_t@&tWl?7AqIgO%or6;Deholk@WiYw=ZAJ z?Cl4AlCn230kCh}h{qx4A|Xc}DJdz-BUZk-`T3-jlvr-BU%f)U4;8?8%jT(bsc4ppJGYCCI65(%t)hDKB0GD*-~jRA%Z(BMiGSFNG4@)9A9SXk$|t9*!O&^CB^E z{Vv4*i(i8&u&&;po)I#_v*zXIe*gacO?o)d}lGK6~~o;Oy_Am>R@Q zi>V6phK2?N0_+V9EsRm=d3AL)xL;{*u3YfMjgVub3=tOwAWQHYXd!6Rm2vvfb@ySL zD*$Vlh$u9BA|j$UZ{GOc$@qZ2$SWiS@F3;90A{;2Gmd~3*3cNq$;kmV0M@Cm7eN`r zJGliOQ#iI8t&A$-_xCq6$UP>aX!#{vdv~#xii#IidV~Z76`p?{d21aU?^>WlTt`R$ zJyVBYhOKFA9I)7VO>1U*Ym1hedgkj_@L-65KUY>*?64$6efBJUd_-wNJ-6p1*~<10 z4w^xy%+1aH{QQiJXlP1K7dpbg$66qzzkhFgae7#R0#Bf>t`7e6=l5?YNHEkOP#j_U z8+S4B=cQzol=?O%K7et++26Qv<4oudu&51$@VimgJnS3)y%zuvoa!_3y1)zNcPc4d zq-11vPo7XxQg-wyKwpEvfr#ts>JE>LT>Yt=_r24Qo10r!h8JXDXb9ZI&dO?IV^asU zFpP70Spi?6yV20l@bMF1D1XO$9vK?q-xPBP&~72C0dcN>327EOl%4&af`ZlVQV**} z)=!#eu`>R*WVGHw^H)~7`1zf^y&JVt_xg^Z=lWM>7{5p#6eG8U1dvE#5{sJe!CK<$ z*Sh5qPSYQmd3ZD*K6C>!MFhihL4t>rhJrXaJOnCTeTJ@%i7p3J0VV--d5`JkyLXm! zv~)D$o^c&!aTL6AhK5KEaH^sMptc!$!+ht?4I9#%lD@A7EHSQM?|O0#s)A<*Y#B5( z`PHkv{e7ftC5)u<-j$P+gR=#B8Ww*R6GJ8CUk{IIZuXavL9B|XanaDwKrR8Iva+-U z^zxqDCs5VaCJF2KGBM%d>KYRlM?&987JYEw4u%IUIyE)b-7P<*7Jh1=q@*O4`P`hs zh#?pBij7Sf(%anJTz@}i_L(!xL2fPsWDMl{KH{FA+uO}#s3Hkye=5k+6CnH}2p0fH zK{x*V`EzV3*IoD%s^aqU($&?KoXdzp%zZ8Ao1p*k4uq=khzJ*{AX!}cdUCCjqh_%7 z-5%%F;hRwVVwr(JeE>=0w~mcOL_{!CafB*^1OMPR0-5BISHW+FNsCj+&&z`0{rxlZ?_&1mo+JaovktSJ?zsJxp@*89nhzdO zwe#tfo7`b#6`sQ1YZJq}DK_qw=n&|Czh-&1!Of2=UMc8VF zq@R#UKcFU*MVe}Db#-{&bHZobQ5{Lxfw%loc^RRXhCzqy?d{L32?%6he6q4Av*7JL zKq%lHpwQ>%=Q|#0cJ}s*kIJmAtu=>H5mT)JO|7j`5pui&0ulkI)eDaS9re^e8C;s{CS3Cvp(qdQC@i-MaqW$aFkAF-L4h|3qibx-C@At*UWF#cB zZ9&=l&djW=T^YytVCaX1*@0r-JAlr=wth5Sm%zA1aPhNB`I@vi8i#ea&+bx0Ss9nn zitUa!NY7NIg`2A@=%NYGy~8wLDlHkAV%{iFiuKSNNaxqioWXt9*Vh3~C0v%e6QnQM z%tCseKgWX%2dNB}{NDZhT*i&sGSo~=Oe>$$h;QB;N|rM3MCbAeiHrLTjSs~I2Rs>) z1atHi6nY@TnwpvpccWd$v$VD*BPY+63J~Mu1n5(i!D868D!vIShfgOpd;LaK|G(?_ zc?AW~ytVG@Uz1oh{`!*_R#&^v*1HH$sp;r=j1{QyxPU9ilHH+_^abxYX!hAh_n)1g zryCvx+_&VR0KJV^2YLZ*8T zxX{RhI|Bs)GS=MO91#K8_FAMl7!=eh*oBs+CWKlrEmWz%!;J|-Mnz}lm7hOhMdXxl zSo0L)A&xKK&yeuhD{s5JU7v{A%^GQg{wz8=O~Qxo@?&$ek*X?CZX8EC6a?}rwI{rC zTU%Rj%*U!KrFbf44i0-WGv|v_kJNg%Rds+aQqp9AK)DG_2@bE{Q|6A2W##1w*~yTB z(uJOWtgIXzAD3`nBT$9FY5{}QH*&yLa7YJUhoZg@wXapGZJq zQ&TC#GNrt>jGDtCmXLDj?vxxsgpQ1iq=>Aktp)7Ax;UDri1cuGSH5=-CfQ}hAIk3K zORzbjHe>iZIit3KVib`-TKrN}S-jlcF{i9>yNHO1)zkdCiKqtLoV0{064Df4tY3K2|iy4KG`Dmj`D z;^yLN^*`Yg@ZAm1zI}&*AvY%ndD&c0P_X{C^WWdoP`dznuuyMcaIKMM8h#WSr`vw$ z2oNJ!2WSufn%whqe>hiZX=zc>29QG+uCiwD-N!6R>%V?QaNl{EojpG_)o;eL=6?Dq znd7WNiUW1mV69EN;^Rlxjq#$y#6;lr2G?KM&Ayk*3DQ6xnTd(Jzo)B0Ls5@kpd!AE zj=n7^IUkX};xw#{+b{WDr1FcM^ru0J^5fn>MQRu;S!|8X2rU=|S!{%~O*m3!`T45~ z3apoVU#eVNUS7UQLn9$6`L^B(`V$cxOU~`< z=SNLJ(LXS72TJSVfiOhBFL%c#AEtbIc)P!fYjHiOn(*^WW|ddT$tVctA3A|$a>oA- zKr-xz+~VR-4S^gQTk~x}P+z5nb*Km_|6>`3MCfqHemW*5T#SriACe(h?(gkE*cY-H zrZF%u2+R*S-jRLu=oGneO(Q!}Lv)wubOfe#d$yqp$_-XuOB#pzb!zJIq-l`LmY%e% zozh%DD4goR;2>0(Pgmp(fM^J-$tfx1Ik)Fq1H_Z>L)(8F9lZxxV@%;Ik?ZctQ2MuT zx-3ZpY5ID4tXy2rmGY%1TA<{^aY8pXH_uK_BO@Zfv(ONb{9gbxe6@0_7{zx@-7_+;{FA?(K@&K-HFBnbz63!3oHRApXO6+bicuZa(OEiqLL3=Aw9S#fQ@ z+qQQ>N={BrplzT$A=^bNmV;{7)z$U&^;J#(21ejXQ^g3=f|h;p0`dVI#I&?!rKLCW z>9ex3fXJL6R2CIM@df{zoI;o!2;<;nKzc&y##&k~|K4$LYVwnl>)c-*fszFjow=?? zr%^;d(n#O=jPi`&>FHf*;|OH$v#33)d>rxNgT0@hcyp=BTTLTlW3R2*X`nBVN2+)s z-ve8OjJvzLtgI{y229P@S4=hB`Pyff~&!?UnQmM4*0DuKo4L7fEfT`FgNMx=?~dR0((AA|Ni^eQz$*&34v&C zX<1%c0#>a85v{7S8O~roJ_dk~3J-7gJ-qK+t5NQW+|kD4Mgr{%SjvmrCG2~lJWnvr z3hq!`QlhP`-Q9L4Py(>9`xzm`2jrWJZY!$uZ#whuqaoixAB4yPK~_hHbS@1Aks<1~ za(QtES`80WzJDKpiQLHH>C-!_IjNwKv9Ym*s%g3ZcAyc^(&DW~J}4T0_wL==nk{%2 z%rGkp%S&Y@@NZxjsBsI6Wia9DY5{MtJEpC(Ol7`$g?>l?r~@VhTnj!qQ|GkW>@h;h13yf9 z`4XbayONUG@85y;+m@UH&W|gB%-lX(Kxl}N+uh#>-lL3=J6VjPGZPz^Mnx?25Fvu) z85ES1Ha9k&Q}Bk$&^t@HY#IE9s0%6v#-DIgT=A{ub6QDkgnqScBFI%pNJoi56&{TU zg1Zh~^U)(Ja&p#oA*_=FyFTQ8k`m4i9|WSxdMH0>KV)E5NBp5RuKF?=|4m%bzmR(u%;fEiDfY z*2g*=_07z3oK5378R zjpTod%Rv6j!3;hwpcMD~U7(h}lSpQYNl8fw47224eAv()aQ$C){IBuJr#dQfcYi*#Yi;F{{}_eE&AiDP_S2cTNFN<f#}8cfnmV)lENI-W##HY7<~l&zN$Xu*L0K zT3-H8T#Qj$)^>S1*xsHqsnB^nJZsRauebM2YARF$F>w;aaEXhZ#V%NRK0ZE`*PP~6 z(-e^{;B*il_Wm7Xg&O6hrKFl#YHIO-C~2xff`TnUSFOPrfZhDopMzs7oy$C19e;=& zS1q11KpX%u!y|)^Fi^+2tf%*6 z;#$gZz9t*A6X;v7bnNO+qrX?}A!xW5cON|X+S$1TDc{>S=$rM($OynNSjSdFbMsEm zlD{4y6xyMYUmFZeNQlgf8J8rC1f^bg#iml9mX9-Pt`1p99%+(?)V&c5Q zLM4`@8@RaYnPSZK3@EE4;v1~M`-uv3t59s!p-@0}0Uv{I{DS^|L2u(7d0@{Gjdq|We;0~%gv zEQ%jXmD(Z@baZs;(ksC`PfBdhZEbC*+Jb_hFtxQ`wY5oSbO687(b5K9o}aL4WWCGJ z?}$j3=S$vwRl1v3NP1&u)c@M`>#Hj(x;i>TY5aXZei&C^V2Vmt_D^F`4Ww$k z+z(Jh{8adjwZ{<3-5%S&J$RF3#}V~dTeq5=+r-=3n~j|vNN($U4GzoYZXX@+Lvm6Q z#9I)+@Mwu^w&(9GK|6W*_;N>W=jP_Xan3hl;^VD&C@lFXPy1$PXU&Es{r&=wLt-}? zkKE-=&J=a)otu-Qr*8*+gaF#wnl+z=S4QX$?TuVy}fQ82e&=&&b z!sl-vic0jRA88yLjC$L(^5BN4#0Uup>~OqT&BFGqKU|gSSV-eJb5lcGEPA`S8h}dk zQ$gND{-?sZYx6UTzLePg=;mh<>usd*L)J|V4QZ*V+W+>HcjQu0Q`>w_B_t+(sHbOR zZ5`=VkKjh3T3}`#{PYPMA3q@>0ZJLp+OW#{Mq48px5?+nm7v=e78VAaWJYMDhzbb# zWU+#l{RG3`_V|+_fO&xf!8*B%-Q>#YNE)$HSiT1j2O}_gNp!o%@kgV_-p_kn`Kdew zd?+7lF8Kj^sNz?amX^SP%9}cqvOGU^xYgexWyo%tlh zz1l1?wcn6XyuZ*9mK}IH(ATFVBLt(Abw!R6bf>fK1-XlijETI~;<@W}EZ#&{oZ4I; zU*FreZ(|4QKKl1|4Li%A&Thh?Y6*~ce}BF6A}RvWRRLYJ zwdI)Q5sjWwge!d_9YT7eT!o2)N*Vy?k)h$y)(;$0x%{cWe`Zh+?Ck6r_jyVG9jGA- zi;ErHQ!byrArNS6%xH*qbEVD6ay>mgIw^k<=|ybZR|rHvzy;t9g^Mnf zCln)%&crMTvy;7FP;DPdO2$V=UA(-avc)_$UX_$MXlW&;rBOO|q9bI8S7an@&%1Gz z(HGVgs;jHRXD)UbI+KuZQv<=DZxCgTY%2UVL?>8KK);gIap7L7eliABdcDa&lJcD! zHiK&Q;`J>BbOa}m9-`%$vjr5x`ue(FnUTRqODyDX!XqN?7}XP;Z^HK!6ck917#Z0H zWt3=n*23k)$z)`@MStsiKqyLOu8y9b+eHb?>6gb0#X+hnDja-#M2|*66#*8X$uj_n z$!!#$7TFVj4mKP;u6#NpU=x##d4%`z%;9KeZVS<>Q4od zBJ)sL6ZvKoC^`9q&dq>As?_CB&dq>CH++2n`cS@_O z-1?s1^z`)1-M~geMMYlMTup^g*hP&Yu^EbKp@4QFlpNhnKjE>n&@mr$B`GSJCeN^V zpO>4vJT5LSBO?P+D6P0B?qAOc;pE+b{dT@|};lC?;>pfzyCnEA&giVBf!g z4^c?{7OP&R#GhBFG>+#4iueDntEI|`&GJZ5HFlu+5Gp)P-J$1ZXnUMUp17JKuKcXo zT1&drmWgN`;23xSqKTrS;*LS=%a;#;VK*i|0Nd>E@9$C?buKR~5Zt`^XLFN-k_qS^XwGPwyDkRqf z{DOi#;?Q3!E1flL1kXlr{);@MDQExfD2t1aj~EI1&qj}~KVT)Q=|XDv?%k7>?HCzJ zaLa%7@+FbT-!qP$sj1X$gb_h5*+B7DwUC(n|SLth^hw1>pc0Kp<>vY&wHN2Gjco2bXbXo=$(f zMx|>#l68}i5QP}n)XXMAhJInQq|~V4r3}4<|8a%W*00=251k<(Ec^Z!w@9$9KD}bk7(D&^ z6J|?YT^+PL!@RAf<;UP)ta>3aCi;1*p04h5I_WIMyiwa~N`C9+z>7yRmAkvUj7rZ* z$jR}susVpR9XxGq-$NrsMq;dL*L?Y+X}*%S{GTmv{QUgKu3$;W_*r97DVdp1pFFw8 zk_0$~+(UO1yZ<|wMHC?e=CRZh3o~eL+o>Yrv7ue=h9|msE==NFk8wV~gVU(d-oq*= z8{n#*Efw$g7ZQ}Tmm9{-n>RDp#|n>5mODB+z%df&q#f<;acf*8sJhu2I4iOB=)x*;hayw*m?_wmiEOWB6rzIy(07p$tVe(6R@5uC9C4zu0_@pK# zqDAF z=VxVQ1(DwAN8>f(!^1-W6$4$}UgXX+maQa$mx+u@it_Rxv1@B<=olDtO!f5E5*Y zqsbQFOzXGcefV%`&5+wk!4g{E&wkO0pwNh8hQym`~m&~T1NE}g1s zJ(6x+sF4jbru*ge_8{Dm z;OTGQJi+`0?Z3hEDap$V2nk&tPMRVR)YR0BjEo=#5L*CXQBdECdu>(M)o~j)zEaF9 zeN=OsnfaR6=wbKN)NvGDV6g8!8osn<E z0241S$bk0UyB15`(U361zI{Lmk!R?jlb~fA&JbN*TdTJmAQH3Z%}ui3lDZ zR`(8YGBzd&3+3Nh1%#r`@9kk=hNOpn}y0oa zodBx0m?edjX1ydV6~> zFE5#ho@~uFsHv&#$p31<0ctU6bZ1XfMP8X|&8jUdT!k`6%Vda-j{Y*kavNmv{?!8` zBV6JL2xc?aFjE}jS>cJQtcPBL*C!?IA0CoA>)1Frs1}Yb&i{?TA%{4;kU0?;xU5%h z0@Z(0(C!roJ5Sp-#Oe=4MFWF_Q2cidUF_{SS}ATv$c4map(3_^G%3*&fKZt>dyj6) z+<>C>^E-R@?wtvBPFdL{c#BF3S4WMy3&;{LZr6n1yhML2=DZvzD+57bu1g2}1WPyb{%M0o#_xjKIXPpfut*oq^?5|Q&Q1GOEj;9vJ zzHGG~&cM1L92gil&Rx1V@7>(k@TJx7c-lWQ;$&y%3-&oK`LIa)oB*byVRo?fBM?Un5Mlt{e>D3L1H23H@Kn^*&DYrL-M^3hd3p?r z@dnz3xKStL8zp^N*^vABAN4t*9VB)SHz%uXMp`{KU)R(Keh!=O`BO-0C!?xql=lq! zl0`KY(I!ok)g;421R@4qZB9EZO(8AacE_-`zrSDgjlew_azg~HNk-VCYh4}`K3k~I zdGZP-%T2Ff)z8oUZzm%!!(Dmr1m|vcsfLRL(3CS!7<2j9doOb9K0$sj9 z-ilt!b2Ynz9nIhK(bkvmz52V7TPUf$;<(Mf?_H|-!~ zlat18qh9{!e5Ir1nPgMem)I$LEI{m?L?KqRUkX2cZHKD3o++EiPu)2#Zg~cpAKLQl zJd$qFM4lm0WXeSTd^np&hC8>aiXV|vUr*shgHNAfBJXWM;V;F_pgxb6g83`ET628w>NUnZ?kvekae5i z(bmEG7{!Zr5yRV``O+|%#Pt4%aBkW6u z$B%PcTQBQ`dtcD?$FkXVgNaljq@<=ceDnw@vMM@~k}W$sJ3uq) zZv@sy^OQ2e)IHqYL9M0T*EH4Cz{gb+Z&NW5zsk*B`Zbv1_2)b2xuvb`aUWd}aDHG@ zg+72N!$Y$mPW_AyaFps8rR| z9PaHAv3wrN5as9Kz>(fW_g_W?Pfh8I=%c8!iTEC{B@N)>;RXKNjvih|MuFQ4N&uSR z@bu}4WHwn`Rn>m6&IcnSBM>)eyvY)SuH+E8w=iw(j4Y`zl}iCW;5PX93A`4)Ya1Jo zYL_0;oa{ohgfO^m6L(7nLJ->joSgPB`^5Iu+S~wNV(p-3&!7K2I=YIxAw!SxdW05* zfFY#$nFN4jD}24k&Cj=*sxVi2PUGV0dOG`5mL3Cx1chK8f)E?UPley&NZhNjOHN3@ zZ#BV2-M#T|-_DOvo5MFuE};7wfa;3z`sl1O6Prq z)#}6XCNGb1L}BY&i2>uwek}@&k(gd$uAxat9Z|THa`_M7&&~!jQzIjqO!buHi5^7xjpPUK9De9n!}SP)8D^i6Q8X+ zFCYDidBiCV-UrolHOSqz5QVxEjX(s~)(X|1kCzx!m6^1Bzxqyy*uy`!V3*nQ-iDp66{(m|I4Nvz-wU-sBv`ob|;RGh9)CD-B3pddB=yBmsiIom;R$iOOE&I?b4O;gcH{c$Ro`m z0m2!9wHj{8EprAhzF05J#-o+cH!x^`UJm)VyLaw-JqC=%pvpQ^)NN%% z`fB#0l}ccslY_ay`t*fgm#5d4r9xV+Gr?CPx zPz`|gD7>4Y(KuwBm{?dY?(XBGqiMoUv?jknFQM*j1>V%vdAYgqw>5&*QsQEysp>v> z@R*0f(b17-HA~Wu0ynb0{uuglmv6o;NE&%-&OXRV568#4I($q_9wDLHnwrw`^3}RR zK|w)WjJx;lVR2pN7Zygf^_cNME-|yVE+{Avvj4^zh`i9Gmd2-`rgn#gB~rbxEA0Ta z-uH0h86o3w%ZI|kqqFTc3kr-Lh5vcgwb!}|`qIMA?o)XNgbm1XZC97nT@}xt20tI4tpHU4{PN?+ zpRFxga`Nk@b8SIE5Xu1Gf03i`;GO}e=jG-Cv*bZ%`R7A>svxps*}i*+UK);0In;t- zMn@xe%m8L`7FSjx@ACop1_QCSwyu9hwL|pp5@|_E35e+N@$vWXk3>a9>qBph{4dvf zzvZi>n57NAzGG3T?|dhKCa{1ntG7SPpNoS^12W-<;^Kv+a!qzm&8m{a;;aW~u zFG>%yefC#IZ3W25$wACIaCDOYdw+_p0&3X0^QM7bU|?%eQBihwc1Ff5pfR-H&S&He zBYbHlCMIA`-YdPmiWp(Cg=2bUM(i7nNiCfxzwjWAEka-izTC+NEzVO)u(Y!BQAB>k zk&n*_kjn4rDkT+_4~>nF;AtwjD51#Ho_%9oYa_kG&AkmykS^?0pvfjcH8eIxjChfj zR+N{wyt2Y_>lPs;Wm;NVv`U#T_7?;<`!rxgSXkK5&=4~dlWv(2R`O$sO(Lwof{!o( zQat}JSB@21nE&st97EHCF@OI28TjS>`}bED+d*buXdERreW6lxbzfIixjlVa3bIjG zCv4>E@#lLDR4zHU2@?TkSy|am(WfS_ZBU{&u(nA_$eW4*jE~xMM2t+gayt1@RWrp% zrReQ#ZFlze?yIUgI6AIq=h72AE59~Mqa0d_yb~lQCMGmHSyxBriJe_c^hKeG`mNNM z809X ziGfLcuWe^$Mz1aF>*qHQA&#Ct=juk7b3j8F_6TOqyLaQ?zI~gR$S)}P_Vw$_H*ctD zY4NrLZ^3Nfj9zkI?~c(mHvTa&(Q~3V#Eu?DMyz##+_eGfwM_M}7ntouV{zcdcXa** zI9rFA+B>YQtEY#X$1Xeq0^O@sq~zrL+WARRWMujmi^egdSYSB+ z(ocPhoS2xAC|Z&qzvOo5YKr*#oj3#-1(Y~4?I$K`X={&zc}dBt5MXwj(SNTBgVt4y zqj+0ZMoUVHye>35>ksh}5e(rKCKkqLW3&4FrugsQzmW;XA0I1AOQ=62nN3w%>~OX06z~Op6zs2e zSr&4bYM+kG(iPY#rzGm)@y{zM`Q09Z#!2>}tc>gS?c$o6A+@ae8}^+ZlU;2 zpwqwWivKq~u?QF>oHjnKgbY6(@{%;pxI&O)HeV?4vQ&j979>#nAXUTxva{8kc4EuqeUSCfnh_w}8 zT0}$yBoEM;oirC|H7f>QWsi%!L2mF@cd^W|4%`3hh3k;3$+^rvL6_Alv}|Wq*9eYq z*YLZTIx;SVx0ND3HDEF*T?^>HRblqy0q2HYzJ2l|t0$%UJs+B0+f4+|-uHNW-=5sA zA|{y;o9V>^0?}N0Oo5f7zSYh1uP<=1ymjVB+B&1~`LjplS+o7ESN0$96sg)xQFZ=u zWp?yU&4`IK*Z=pyERJ?|a)gOAcuHz&e?F)24-XIHVl1DZ>_ZZ;{b;;l4QLE0_ldwG zfJQOY9x;^$7{XBMyCCz!dXatP7XaupYVwupa+1^ zgRA1QGQ3g+6a-@7#JABR6jXwPgrAL8QHfxz(6;wSEXFUCrFSd>F%QA|G)Vl-0b;fw z;JrTOU}Y@?q|k7xVrOSxlL2v!h>YAj@z>7E%zSET`L3ua?Zu1WZ!J>ZJM_i(@*f~? z3^L-1G)F-}A;QYGy~PLx&CShS4FFIAMq@@%Yd29G7l*5@udn|Mg9F;kbi$=8@&*%8 zQEO|UZvYA+n0y*XK!aZPZECA@CPY#R8}8e;H++Owi>j)tfss$DuOvi8eI7qv>W!xc zCx^D6h%~NuHeVgiBqb%ibLYE~9diuz~V6lqcwi5lV=GxLy zrx}mu)@<~rd{2}v9*i)Tg?5zx+y{}%@NUVqK}t$W`}SeYq>0MCdmT+e(-4w&KZr6U z_K%NOmzAl1TYMSOVMakodCy3^e`G`$4k4kk_wVU1-Eg~GP z#RZhFmX?<7p+S)`q`58#D6s0pL_|BuPai*iyrYo=u@(x|hs@)3-_PbgSpR)*31C5? zba<6ohv`uB)DkXwBA3_)@$vD{R=X$XF!#N^y}y4u7zhGaLN?dxmoqj7o_YD<0|(2p z^FZhFE|ZjRgAs_3ovbW!`)r{RpK|jw7!#XEQrF^w*R83kso6#kmGi6<$Rd^coYj%^ zAt2D?BqR$e97LG-_%KzEEA;A`m75@)n^3>p={OYv4<3Vr7w$ z7?)}S?Cb->!|M0$JvrI?1yla?=~Ip3fW7VmLVjUkrFnNCSx`E_{-gn;2G{(LA6*?B zelIN0$MC%V9sw&?T`h3qM!ePF>qV7QkTK+E$@E+Ss>v%UY2@jED`F(nR9EM84)`QI z7}!8%Agp5}O&W-M{`}kcIHVPW%E#AaOYS5Myc=6zvp55}g<-FebyBu2L)6*Y+5#d2 zL*9$~ySKj&vk1e1?$Ua++ux7bdH@NN3_HTMcDXP+kRegIv9a;y&6^MB-oGs@tn=Po z>g?=fr#5^1m`_T|L|1oZb(Pg5D>apkD0*k-HmKl3Mk-=e^($)V6-r8T9ttAC*w|R; z?k|F&9UZa?cL^}z=R?`j(o#~i*-4tOOd0AzlwNww8}vTQS9ao+1!oZ+j9Yeg5y_vs0kn3z6iNv3z0 zo$qH~F$K1P251G!L!nt(GTqKt6rY=!5kF}ss(btPt+})Fiy`Ygc{A*YP`cdFQ7tGg zcaQdo2^}UPL1E$j6MvF;Wlm911Aja;y_hU@4I)=BIE{!hFY8# zQDuMi_bb!UWdk`xM`M8+#O>Tvn*1Iicguy}R^U6(*cW>rsfGc|kMf%DN=xrZiH?5z zW^HfJaf!>6G=Svx{{GZGlk42v<-p>uA~Xk#F(HcO5pr+6$M-fSJ`_5zA`s_A?0;ub zqUB@a1e?D`j|aSz0k|UW3kSMBb>g#iAC=2U3+_b z6%`ejm5Z~Z{r!D9NnfT9IJa)yV%5m%=J^f&up}B25)$&~&!6m|%ZBcVFmRrrpdg<& zA)Sas_T}G94`}i|Wn1U2=t5-LE&13b|JcpMVTR+%t zyUOxTmz9+T#8$-DS9h9-f|((U?Xj+EYHW0Mb7PfmA|xmG+Fu!BHw-n`fBcvs@T9$~ z3wZ}tX=y1G603TKv!^G^!Sf)6Vqjp@*483F zR3uUPV`Bw~$;yf~IeE(G&#Jo#*L8FzAhLoqNazxRg|Dxzy(pw)!_^!XX#!vF?v{rq zg@kTkthq*SX>I*FB?W|6NnRevQ{6zCkMCna0mi?Xu%M`QnwN5~LiNpA=uc$C#b6W_ zZD?)H>M+YGx`u-j+v0ZwLuzblLf+Ci?#%?Wz1$lQbLQ#k3G*`3>{BIwjV~?Z<;&3L z6qQp``u+a&p*yKd6k!z-q_+rM>Nxz7qM*=k^8E8tBh<#a@A*v{yz9C`=-lzEffxvc1ow*&0Y)hM|9rsA-^0Uz zxu+-#1Ht?VL^)@_%$rt5rRS;X>A(P8!GKWhgXk+*2m}R&4G60_j|TmZW}kg<*{oyh z<>lqWg9BV#+^pl*%>HM8>R^BXkjOh~zn`7DX|bt1ynHrH`Dt+Q?!A|Lv-xaS=^wsW zgOjlasA}rzDZOE0Wxd{2vADSS?j4h)q~z15e*n$gzskx6frG=DZ?~Rp5gS#lu^W7} zj2>6m5^|a=(R`67VP|h2biUgM`O{{<`%PFFT0)|Z=I=+1Q0%cB1Nhuov zaJHn8rhac}=tqrxN__l{G}YRgnxT=Az7On;1_*@Ay96x2G_6;&kkR}D0!E?o-Eq4v z|JJqD)YSnmbEQzz(8Os7Wr?^v2D1W&26Bh$4)B!p&YcT9dwP;W^zxySQWQ9hxASn- z_~hhK54ovx!)&QxU71k>(VgM3FJE3{Wd)udteXa&BO>Qyp_p86a~SzaEafWUZrd$3~O zub)42kh|@XAIqeq)HgXH$D6Nr>dd?7L|vGr=p@lztNq&xWQ(G76%6hbmi*usO?xN zDk=(EMQdnw*2rH8&gOY+tOZ{hSiaZxT=K-&)|MkY8VwB%vOIhPdU~!$Mn-mawC&~W z%p)WOjrzKV8+5O|UB<#<8O}Cby)ch;9ZOqRmrK7w=9?1;XxqsOb)s^3XsqU9A6?Mz zKY#9+sIiea&NcgN%{F|j<>%weEiOLYACZog&#kPigu0#>A14sT4Y1nY+Ir2F&2NKu z$*lxpyvlqNtx+%w~tOxKmd?#XTBgmKVYZhdiNiBsLsK` z!RR9$LqnCk(cZqk=qs|_qocn0hgh~fh0)Q`?1l; z$HT>aCeP5b#abVDAr`O5sIPT3oGA{go7tTr?IQQqdHrkt-@kt$LktZK***kH1)<3H z-@E7JR2~*~*WX{lqzz8Iwiep54SaF=_*mq2Mh2b!!-q*w(HrAMzyv@^)s7+K0Z{MH z`<5G;nzm=^68ezD_4aA&(VU+IEq-Z!!r-S*fc^l4U=j0`7Ja`4Q?we!yZZ;?;^QHk zW=ZfTg-%lyvZEfXSTv%p$Pe83`t>Vl(7;P( z4Lf8HB|WwXg+SZ?$b*ZSIYKcnEj=CiIlC7}^C>kE(A%CK9)G4P!&F%w7L8X_@Zfe8 zfA|1763(r-prH22SOKX1;-a}WodWl88h?~LgNK(_Ugy9`2ndRmtLq-v1pu&+!<6QO z2MqS6*z6{?CJ6`xkpyxtz@0l6XY*HOrKL}8Y{&@-Lxf`Qsl;VqL?iARoPGRvypi-1 zdbDpUv84>)%f^m8ux|L$N_giK6`jB!$;rv>pFCMqqE6y|w$~AM{nMvU#Kgp=0f#z% zeoftE*0v*Ak`6+CAS+I77ecavhK4h_xw$ZAwREAUKN^vrYUthO_@gm7J3C=zHCwss z-PY#i#hIX>Af$9KC4f_8G>YH2V_2IZ=~r7_{YswU+V$&sA8sFQ&zA!seE9I8v{ce< zCGNQ9it~1X{^PSdw)GC$LcUN?azYcp)Ah`a?aSJUkqnvB^o+R^3ml`)X=x zI@*^N^MF(mPrm^%-Md#*Sa?1E+WmO!45R+l{SU>(n*Q0)e{iZug7YxNCUi=ztmM7i z<+cgF#T&g&W^nc(5Vs|3F7qcPB_$&xBhZ}asmr$#gRZVF+r_!1rN_JP=otSUMA0C= zx9#i0LPG@v1T@VKK>d%&td;eUhcG|?7(g&2na)l*J3#^MPM*)by(<8U5Xm_7%H%H| zeYC_%=)0S=s`1YJ!I8pS&A7O@FI8BZljT=X&|>1^P#1UQ`apvx3A;bq-l@>F~))u&#%t$hZrAU=vLs1#%X9)2-+bs$PdZ@L~yT{kd&O5 zm}om*iiIW$y4W-we0?W<&m|#2`to>Zv8&tT-4?jV=3-Y=p?W3}b_6({4G#raAD{*& z*@q_NAucHiL6s(7DKa7=;N(|ISXdZ92`Aa$%uKp>0yrk<0rFq3aH;t-QztAW1oZ|_ z0E(@9Zj3+#Khg9a%FR25AuaXdOf# zc3^~!j*nN{P29!^3n`;?`q4N6;S{ESa?)$8Kn*Nkx7vKq@BZ28?<(ZS!>zkFdSfhu zFiKq5`JJ_09+uy`caOrH;1@(pL&NmrKk+ahZGJ~(kd6Zb1I^9f78l>Xy=+L5Qrc+Vpy_C}ROSWxioGiAJ}yn+JHmCuwmHZ~YxE|=#g(EI|^Tpm?W z=MeP-sO~`Ym6W_$Dw$JOW}>g3nv!B;Yb(OX_cA?Q{MW9i$A-3=+6|YRMQ8uH*$d`n za&%NQ;M84KHU#+(r?7n<9)`&kN*X}ka>vcB6!!9Pa}xYw^6OVucs+A-bD)cEKlrVr z``Q->jL$x}h-5IUyr!V0cKTlZWU|Z{is9j3as=YpLIQ)?4%63cQxA_C_*;N%L+QfV zUWO)|AOXN&;7TOi{yPgH#l?2;5P2&|ryLv~0O<;U6a%);eE+_&xtX`h>S9>yuzPUu z>OJRGI){B#_W~}WodYL`jBpRH{R1fIMqYx{DHL;-*IgzbZ*PB~Jg1h!Z&kDG87K&E zD_LDW!~*_*{u18{)c;bWiENdBKWqlUO~PZi2aM^0!fYSxzk=bgcAt~iFcPe z#>O`v#V$=~YiYUcEOe~?zy`FbD3oNW_doe4#~Zd}?p{A4brvVjuxNkrIL2nS#a5G+ zUfoVEPXu!5u6zgiH{h+n%M+WTHdj~IM{R)@2SVwP{_tL9WtrI8vSp7b{hFShR#a4c z^X3f}7MAUgO_+mlO&qI*>N_*$g-2i?+7 z{rxhqh!M6Gatw((IyZ$KreqirVaf_8$+7gxP1KZ?kD(yDuclSvX|ExIZ5FP*VSQ2D z)O2>RKBnQE)=VxR7$}uhMNUe3*qpvUZt&<4muaj2_n@qd3<+Ld7YMJA4#vl|al5#T z>OotF0p&roPEUQSSr{YD%gV|?OKI?;z!}GV!wThk~|oL99^N>O6tP#?(*E+8~_v06)i1o zKtRBIng|x;ovB6I{tBnRe>-q+aDdj?*sQ9gaJ`kIrcUqg@2{;D!U*dyb!?M=aKuFt-jg3ytyNVAV63ddGo}Gc})YQ~~ zwb4rXKf?x82kTGJqfZ(b>!;TQ&i7WmcMq$p0^Ad3!_?Fi2H{VJe&;nk3AVA35e059 zkS!1;ml;Lxzs&^5PhT$_!+PED>;Jne&Sj=;&&?_RKfUODOB&J|OkrZ;;`a848IL}v zF2u}>v!ezhuGk(i*PqW|R$5yxzt`CJOa_A77RK0S$=IEmLdC*t!s>W=3AZX@|G!_L zPRNZ%Zf96nFf%jDS-LpA;xcI#3A*%`%AWuF^|7@zfYZYE_SLZX_QBCnA?UY)!rKX( zd{5-(d^y_|J`fVX9q2QNBW#( zkM6!`-D6$M>XsbBK!8Ro8Qh)nyUa{+IQ216peSW;5bXaeZ+WVz|& zw{KZ|z9a}l7HuwX$Ik5o>&FE2r{L6h(9N?*Hn4Z3;ER>#%#V}}J8#(QVixjgNUjls&@ckcIC@z3$;wE7Gd-zyv&?faX?Zv#pH%bjq3|30XDaA$aV;4w_OG?$Z;6PQ?NCIBk7Qg2I3 zbW`6nRTi8GIf0p77;&O9ldB+r{{5KTnZ$bXj?bSz&&)K{*XuWH+L41<;@-G%4Hc!B@e&2p zI4Lt=SVe9hRqb5x@CP$2T#U{@`RK9mcScTJ6Ut`8p*VOc|vH~80`}bsr zSn{P&{yQGdZ7%%!<#DuSj29IaD9`(4twxiLq^-f@aAV?Ot=r1ZnpV9(0^$9a#BVED zo}s6=*KxMKvaZg{!2uT%1U^1kc&>dNCz;AQiALdAQ)A=KOf#wL#yGn_yYjU0b73+%QZDKv$?rx zV`;fSj)ytt0{$YFc?m8;?8MK;wzl_ca1CW}z4VlTl5*g2<&=XbgegbIt)Di+OG`_R zbIqbwDm=IYF#ZdV10W zks2xBU!Y3r>d)acA+wz9uij&NS;F;ut_3<|x~B&M)5G&+Ssfig35n*aD&hnkd0$^& zF)^{9PcX32NJefmy+}?@PEED7vwM@A%nSl{GaM>vZ_m}s>j>0KLt}(}Q%O|Li5eeYY+Sb_PY?)+UXM2?*G%YL*3#W{%uW zK#H-C{-5mx?7ir~ngfG_%g!RU3WmrZHkTAo{QKtvJ3_A=9v-d{^8JsW&epqhjgBS` zS$Cx(f9BmVU^Fu|HdX~1VQJYtH3ij>D)&}fS67|#HX1x2SeiY}A{1H9Gqq3uL7sO{ z3@KX-E%I-3bFBX>3QH?1h&@m2?4BniSWpy{l?AR2-$eeqcHbU=G@_3%pzeHnvt-Z> z7WnO(E+CZO(H6k2Avw1RSTGMg^0`bN^KJ7s`ySqIEZ>1*Qdd_WskrxVh(SuF~ zO(D#~$qZQTRXGqNe~~4rKSS|9ro)~ZIot(&Ggaj85V&EyD9En_6#pKJ==!gpqxb%s zwsxNA=CB`4Uee{B@I>Os8MpI=1UNNC!6L=t?B+&IL*pN)hKi8T__ukZ#;gMsoJQ4u th~eKE14z@!hz*66F8hQ&5*LlQRqbKLGUP$!7on literal 0 Hc$@wfMzo(-N2Z2~MMIi3PBM{_I-+$5&gCAg- zD=W$&E>QnVZODm&PjH_q={X}1*S?_skJjOsYY87>yWCZk$6mgIi4f(@pz^!|XGGkU zlh*Q>SW9*{Bp-MQ`tRva)Zb8bNS=G`uh4RhpBsR8wcx?VKkD{3s*0; zzTjWQ%4lqC>>&Kq_8OnY$;pY)dkTI|aaG~jGu{~M_j@7ez7 zbVr*S&e!hljEszi`g(K>jPKvSdtH!S7d}Ls3=9mSqIHMQtolCqEcGUpa&h$z z4i0|(`eYzoUM7tIp{}m}d1<%S@MBbz=KcHE5VUvhcrJcR;5M$G-97e}Xv)gUs;Y7u z%GFrt2y1%2ySTm3VPRoWP*8w|`1R`-45X*0r{wt&!%2HZ1;4GWEms^R2?=tLgq*yt zu5NO2a@V6?Gv_`U!fkW9XK9y`l2Y;Q_2#AB^0G2d%}ZEVSm)>G4<9}(D=V|Nw-*!? zgdm&S9ITChG3A-Ae;$>X_|=r>$JErob|5x>VnRaK*RK=f<1hxPUK@JlR(KSAtzBJt znVFb~@aX8wtgN=Vr^XGQFMB7N{3HXLJ9~OKxwx!&t|tjO8rM8c3k(c=^{V|X#cdZC z7cp`1mojEbN^h#F4r-n)kdTtH+0(Q;T^Wa9n=m=opq<`E*X^(W76pv$KnfRxX*jxt#+88mg-H zBZYeKcP`G)WYV7YBnqf7Yu>$Uv$s3|w@J_vLeBjPiIkIny9Mwz>q*1zQU*Z5F1-%^PQP1ZgOz&fu`ndkFD8u z)S>Y3;V_HZ2PvGUvxCXyWow){_Zgq+C&O$wX;QSgA3wI6v$3)Ho*ofK(vn=(DK_pg zFGWX3clc4Wy*2lRO4QBt;)$Kz>FO~1p1X}rUS*}Lq2Z5~msfmzd_sbQ?}&=Fr4Nsc zNcf)W8W>D||Go=pS8USsieS3YhZ4c#xwm|UoXhS<4X>o6-(;0N!aqJf9!dbx1FA`o zpP!YLb!=kdgYYvMRaHEMx{gjIg`cJBL63 z=;h_*RXfh~e*Jm^HwHywZ)aD6)!=(}2VuJNvkR*93c|l*K^mvyEk#CZDx~Spg#`?R zl9JL`lV4Ls#a?qDw&RZ)GfPW;7@Wh+84Ls&w{c-%VZHaU6G93~a$jb6Xo!`a{qXnb z=6Lzzp}zdw-0;ZAi7ICz>H6x6A6bUNC?EL&rkI)RjKRG$MpPyfF`TK(dHzT7d$eACt&X4z3hkJT@mfsPCWoIu! zA$a@v0IZ0Mi{o9rx@8j`gF5~kZc1AB)3UR(yKK$3g&_QW{v71x=R>fF5aF@0Scv%B zkKX}4B_&M)I_&JC&}FG7Nyw}P`R$tuZm|WF`OTX*EgwA^XmFI3#Xv|sd?-LqFT+a0 zrC+fO;|{>YB<2puz2@vgjMb5UX8&!0c_ z4Gac4pzsk0-_vbHzM`q$+BaMA>_4rh=|pV33@Hg!^L zRHuFK-eoVfFkd=#%sq5;8c80W{^{xSll|Y@+uLv!s3XysfUeHYZ;1j|5VLc0&vqA8 z%PirClBZj;1_nt~iWiA<2Lg?TC`nP<>g%IESa{vGvbM(9 zeLX+)-MedP>SN>Mw+L_;N!&W#Q2{j|{C&?(?&@OD)vBjw$vQW3*sA9L8+1% zmBT8kPoF+zXJz>uZKX9doUM(QfBg6nBo=vG6pI=<0)Wlc)%EpN3UmaFXntN^vo9Yc z;7p@W_ri96-^-CF&0!xYE8A&hVg@=a+AZ=V_mmo!3QeMuW45j<( z!|^HT8ifDi;v$q+>N*A!6O-BpF`Fk(=tU2K|L*{3!!5|g;kKp7Gf6SK3i0X~)bUHBrTo<7|I zAUa&1jEj%&T-t>@!)+RBZN>BoZ(G{ca7`9_?lkqu6(vv_ybj+{i{C31L?A5M-`Y4h zOqZAi*42r6KC^IiEY8V65r&@L_}rJ*hh^md5Sf2yJ<=8j29MFx^2;l{#lHujJqZpb zK?~gab5GB*aXT-sKTwCJw{lbx%ppq_7hko{9~~V*lqqgoy@j#?fJUWxh0XWs8Q%~h z$mfi>6Th>4^4DL?%Ev)nZB91?5^Ri>2KHF(dWb11Dh}xMLLkaYN}f79gTPzc=q4Hv zz=TVfEPK@5CwZ~<`#1Y>A;9461eII2ZV3qqxiHevHII#X01(1xI!@P1JN}B}(Brf0 zBv4fBNKdE7nS(nU9v)UzRUK%sF)}i;wPjD~)6vqB6a6!A1KrVa^Y-K3PEd(@y?|f= zfq{^PAo)FM+| zP`b28US3`}3pEJIunt*U9OHTqGh5q&%uEt8GAx9WiVBRN?dZqh@82nTO#K@h&p~F; zApyR>fDY!j4lgLMH8Z1YBf`Z*xBYtz{Za_MkyTX0X?6*hnk()KLW&)iV0Wnx8<84= ziPGp7PX6(6&8x!&q$DJs8F*3(nwn9NFd(q#>FKeqUPs)W=I|C&QBmPCuD3QfAFMV5 zrfjqx0Et82@)Bo?iIEX=UG9iTV91_Y()WEzN^xFZLUeS6`{wlf_cwv~xsz}GH4gXQ zcu_!Iy%+a#TN%vqIah_^003!gYXgqn-`Tn2wl)^W<}5G&vZ?999}T1A*A;#r8CTbR zP!tUf4Vs#oLUvkWy6*&Ca%p%Q;lpjrTlN`}+9>hP)8}Jz6HFOGTT+8Ff9Fbnk^6 zKR{~b<=rB}PsJ${sKmLUe~~q#6SQBSODDX91AL z{7x903x@72)8rl#Wy*`j8w5ne#GD))@hZ%aJNYIEe^7fs+mIc=$rUOdU6D*DCntCA z-0}7G9UG+go{@bo>i(|T^i7qojm^qzb0CwUHjoDi_b2WLll*W-FfxMLMf&o&osfZY zzsL(Zh|z<$n}}ZFQGzG?G~FTMbztY_<|ZxOoTr(St(v6Juo`YJXKl@To)XJtbO-oR z;?`o$Mg^n{7dz_s;_Cv=tL@;g82K8*o~~$aVNq-7prJ7UObK-taP6M5vLt}nRGqt$ z5H8g%R#uPWoky0IjInRS4-O7ODTUIL3Eu!9$DLtRIhS?#)OF1IQN9fgg>mmqk-T_R zzD==QfF^BZbOw3@I4nuf{)V_GKheRP;9w^gm%{vf&-2sTgaiu2=jP_Qt|*pAj~>B^ zotJv$m*)RaBT}KN;!J#-tv0#{u3+|z)700e@9f&zR6Bw&U@Xd>UE%MWIy+1jpMyB1&ZJ~xyuq>T*}ZLM=o zd3kwE%y9kl-S^4KEUJl^2;FLj5u~LiI*QkQ+jj<6w>f9Zh11?Q*-u3pbkBf`T zZKRebMnc8R&YA+HQ&J|u^`@P^Mj};`?+kZ!;ojE!+`*z!<*{u}79s#%mxd;VnB{)> zFEU45!t2+sQ&EXO`bu)`HN*30y;Ad+ph5t^-Qr4~&b5H*27rSC>1b_5AX-{l#Kgq3 zi;Y8*Upg|k`~Yp~>EQvg03ch!@BAj>DHuCkVrCpnbWmylb$ocZ!CKndJICJOt-t4} zWiX77j{~6rkTEE{#kqQwgxGeX&V92#O;*zP^bNlJn2nFOcS%ZmTL?MBKpNAs&WY4vdTlKHvE{G^C}K`)r{d zh>8!YSCS&Xs3?X5%XQ<2h=G9tSp70gODq~N`|eIogWtb@xibvzOv5pS#|)k5YEf~q z&VvUsADIC1L3XgLO`7{;WM#eVTiX0ly9?avEg^a5&W&yrUES-E$;)J*>*9GWu;RKa zD=Ori$KiIMiYCU!goTA^f8m}I$i;`Qt=U0Yleod~u--m0f3SuH3LZl6bK3(fad#}I zEcP}=3qS}sVK_M9;Na+dLK)W7)b!y4HRAK|@ILSounZ|FDR2ksu}MWm1(3q4S6KPO z(t%iMmP(@`C7WmnD6LOG^#iWo6~m~1In`!oXGbQ@9`7!BOQf`!w{>)6Otk-01KBq; zJZ$^q2@WNdiOT7g^6mwO9i{oxrzN?2K2A<$85s+}8MH_x@$-ZANet|3aytkR(`W0| zGqgZkBYvmb*vO~9zQ%NRBe;3Ceit`!>6XkwssNA?$oTl2RaI4ujp<@zW519BSqc*P zd~Ze5+ za8g51W`J4*Ehc_vu3*TQX9F%>5x#ltNnUm~v&$CfM^v=k=o=HZY9Zo6w{NrGx+QJD zJ~xL(w|8(L@oXL$82AOS6vn|9GSFe&-l)X%#qx%qoQlfTohE+*36Cu)V`J(r-Q%Mp z!%r@_GS?|7|G)qN_zm~<;jz6Cs^|jZU;BVa4bibLV zS5$!X#5&_7xeV$pB_&1D^s|4CTFTeXPOw%YA|j8VG(9~5(ItFNv}9#7Dk?}2rVb7t z!ORvFC8wltr^N$EOqD&la_|iNHGs#-1-M12v1-M4Hz`O-FVUSsP}Otbgj-u%);2cM zF{fvTGqO0pS68oJ#ah)tf03G%b!ny=_Yc-r;115%RlKb}2(3IILtR7*!kmpj2LBP%O^$wKZAHF67R0tEgmf{F2Q7*}Z= zpb;u6Dg%A}SfGp0ZyxjW^ST_`&d$3XVKm@8ot&NNkT=Ic;e&Z-}-y#=!_N?a_|>@fU_i6`&Fl!2lS7O#D4fNJutAn+b4;Eu(Y)7r^*Zo zxf0kM9uxCWQ?npHpO24^{?FwBOP~l47kqz@cm{fE8D$&<;(--EA0Hb#dzAV|jSK}e zgp7=g+zbv#Fs#aG5K-sRv9V;{x96PyK(>QP2hPeUe`0G}dTRkZMnz>MZ)sa&+m9bN zr+&SOJp&$vVLIHLVc{U8Xl`x}A>(A@=I;CY)#=%@fx$tUj)wYr1OkMEyqfCZ;9z1> zQUsPcl=JV=;x5LN@87>~dy)cwxv<}O=6-xh&u}l22wn`w;|-*VDac)67kQ1gYHchtqDIHG2BXzk#NGP-@Gy`QyI(N=jqkf|>)dBOc>Xx0oM%3w*WMO>ZNE2&!T*S96JAqJ>aLM#}8$ zpPihs+!(A-Og%J1*xQ6h%IJs&HcLHgP1ooXA~j+NX2!XSwJ?~aoX#Z*nb`WnfhX#c z3@dZgd%rbDlA>;PR`JuO`TIvqvF16mNx1mP@E)t2oSYEqp@D(te-1cr%zo|ePEcXK zGY!TKwn=Uj1U7K-ws@+b@)A1Rr$?G?T>~c7VTGC)M2ba2TcGr z^WDBp&Sm(9s^f%m)rz16^b{b-14lj$dIkpIrJkOiu3&)Yvx9Y@(Mc%hH1#*s$LI(c zy?$W!!9jYrd%C*1FvLbiR0*-=Pz&cAY^h7_x@|HzEcf5PsdfaAA^3gWJXB^(s8fpi zW_ptpK?_tq=qx@_b}9Z@4uh(1gM&mxKlpihrR7uktO>43|7A=d)#Kyim6a7JGfE+c z=#tZ2fCp~l`p>aR;lqL-0H=Es1%5-QtuGf86^UE-(^}rVK|t_y_A^@a8fbaAvm?MX zIVxE>5RSR|`7+;UK)B1v%dbz>q2i~6Po0-~?WS<}+8NGtjMdK1E)Z-#YMx!be0eNi z*Za#{$oOsi8;RWA7kXN(i`NL?+*`BKF6?2r`;tB$^P##(Iyz5J$gg*KrFn~wY9?H;<)fv!MFi$-@c8D z8wJJO-vM@RKU+{-OzeTC=H%ogcs5>58Zl%n!I1RfWx#tkXXgx$%Vtpizn7PF)z$s$ zQzs@T2L@}y!^1&e01W^9`BO_r$HK((*H=BVqfydqwRjHOh zpO^j~>E&qkS@K$1L!d^C8@+Gc>Cbpg4@1ty#f9*PgG$sbRh|bT0Y-0Kdm7j#`Tcvw z(>t$_$W-^~pr9ZI#doc~ND@-gZAWi3gpk7zb#3ifo`Qv^!q#_RTYlm{y3T7Z_uv5$ z+a@sA?#>P?Swe|pxX%KV(wJS zkW_fgQQ(c3NiJVPN8?*!{G-4&m71O|Lrd`XrU;*e1oetNF>`ls?{v+x1wh176Wid* zGmvh;Wzo?j78VvR$To94YO(9T#26SbRK=qrBd<}59WAB!r62RsiBT8V*NaJ_j+wzh zJ|G=h+SJ@!9I6CCdwngfXyh;vxJZubTMTik4 zei!GPjei^<^WyzBay2qQtbv25vKtSWQYUJ$D);g60r|Mpml7tf=CwWF1|VG5SshKH zA7E;4KQ%ZQKt^^68+&wQWas#FYwIaO>d6x}P^VQ@(?IuCCRY$8-p4ziKTEm0yYFE< zKiZlD8o6@i%I(|bCceinw|?U+Ea2kcz);OT6`q@$1BGhYw`^!+^tku^%JOpOFDGDF zpwpQmL9d;kxM3ZCKp4pDm(VDoz|-=l#~gY9X>oENWFtrJYiVi?Y}FKlcyTJ_w3M7eS$ z1OPOh+)|5njS}GxRNdfxJlNKDDHQ9CavWDEwYdJ?9vCRl>LAbV9t8uqR#jIU0BP## zo}T~NMEDEXjuaYHbJ5eAU!0$fg;1UnAp1a1w_bit%kurneJlVF&;b=)jpgN0&8F8WC`!lI zp#0Jwpk>gy2HJUy6noTd5B0nq>qQ;QSgZ9Nf`SFZx&#>>K1F(M!+sI8{f2iW=j zyCy3MWS38Wsx(|PB>wHkz0qq50}~TZ9zT9PZZ<0(jzE0RR{h0D^HhFBD!Q@p)r3Af)D^s^JP;Kq#`s7Kt$5|GYCMR>O41NVnHgM)+Rn5=k-h=|fNG9=~g z3C!*7&yKb&1{ki8bDi#wns^ahHktIu<-bD#x00WqujH@9Z<;cMK>-v7__OTDNTX$B z1k6E1K@rsI?)anTg=N(?*jc|`BQc~;5i_~ zpR59k!7;P2$Vg6}dPgP7C^rdm+I`07wGU+T5%}yGP=;e;x_Wv+*ChPT>mS!LMI$$P z%`p;lGaE2*{zh-Xe2@UWgas3-704F!XjDW*DO7GR1rm!B;cwCLZv98Cri%pKVpdva z=FgRtAe}w}XU-ND3!dv(SXcVPtcM&l%GMXN=!ndfZs)CVRd@8K1t*!J63-NS&UY?SY z(#y*WoOzi+dwP00Bnl=LRux>AoLnkt3jmM2lN!L1m6cWB2XSRpRaa-{?}LMpF)?`8 zu4Old$M-*E{hyO9QarPgCH1~iLTc!Uo1$)S+stcgYLvo> zR-f4;5MaPSY}Xn(fMh1JlU_dpssct!l~nIR*{V?!KY2d{5yo}il!uCy|>bDeu!FoD6Lck8xVE|y@03Yh<;pVz(;DS(nI`zr5tE)@A zZi8`lVS)I@jXS=l9#Gk9D^mcJpsJ|}2|)$Cs2JEPx;s|A-Nm{y>DW|cSW9&G!5tBi zAg-U0ad9+IPo7S9+adJKAoI_e_oUDfCAx*Zy}gQI)ccKtTMmzrf_CPDHkR!=|Cv@2 zZ$UD1yn`o+qd9CaPjoj6FWPV9336)^j{nfO5GIq)LO$uOS2`E zKsh#0wWp`2Pz{}nd|({_FCb}TUrD8#_R{$J`U0K1J$+hITH0Lb60edCslMkXLOHg=3Njum7?rvRp`olJx8*-1$W5006<{7W!5e8SIMT^pQ! zT}GDV<=q`>SBM5_0;*zYNJ~|<2edmeF)?Z~#C53KZLk|J z!zE^JZEFKnS8njVtI<;iuKbnF_w3`Nqo=h$p6@QEDbW4aA|Vt|%P%a{($?nUbD8)K`&^knfBH{kVd^Cpv~4|CBUJlr-$0&;Wet4zJi#A^o_^7wKMoR(~s%4>#7#7 zvw;lg=7WtX(dW;fM3dlxrpOXsA_1dyBzHgqd!$sXUXj2TK`mwRGe|j&h ztkgRF`l^~F2!yB-;CvO?KRHPm+P(ZHI$G<&g9j=qZzCfgpk6rGtqf*?YYs4R2)pa- z?5wXp5y7BXR$dMx+u(J$;ozFj^?Yxc@bwp9qm|KO6G%s7w0J=%1OVut;a3f)NdS%q zlA~>HOt)^W{Ml>*nxgk)eR@jpAE>!>$awg z@Q;flx9U+T4RO;W+k0JF`fOWr`S6B83VujC7v zIz0B4@Y`PvF99Br1=gFRpmKMnYL7q@&clYbpuib6(KIY^s z&Cdsj+sgOSfZ0@1HZ(90rKOcpP*8wUo1Q-3Ug$s|__M*aE6B+y5s0w7Rg2i$+nb-C zPZDx8-?)lYFD+>HqHTl0WM=-_)%Eh#tH|g0tINw!RtK9iGhe^n8+w;pQ=<$23Hf6^ zOytD*Ku2eEc$icbi>|P+P|lXoOD%3uVPaz9{{8##PvD2c{rxkD3zJL!;pR-p$2*xg z%=z5SV|hZA($){5D-kFqM-@P^rA(A;Z{*Y9Zg<`4smh**5|mC4IMGe+OZ&g zz|n0C((Ay^E=ShbnA+3kaAT?tWKOE3#}dAY$qc2C1J28q_V)H4KMb9ncPA$F zUAl*dhFl$KsVv{18u4&(rCmWfK0jC+2Xy4rE5k&fo~$hOCIkP03Piojvh+{H$D?(s)c8Ah zgD|PZ-NxbP`uf@OK*q_5CytqwRd#J{E%LsA_t930?@6A)zTM-;aVaS?V`DgSZdPliEee-iE2yv6)=9a1AA1XBV{&o+2}eVYH|y@>Pt!a@XLdmuLcr+wj$ zv9X%QM(U(P0#91H58__Ti;de0VUlh(vK&@76c??TuoChN;*w(t{u3zd)H}l?BUXF~ zD$K+U+xZ_qg6f9;Ix*!~V$=bH0Sm)#xtEbQ1y8hiV5uyNGRVZ2`PE zIg9%H)m<*h;6x0J0}>8&EOdl{e6h8$Sy^38Pa?%hD=RAt4!-=g>E+8y$dZf$ZG?wB=G?pI&Xps1w{g#>?@vxZzChxtYxoK zl_6L_ehi+O+1c&msDonI4`|QBLpY?(ynI~o-A!p5X0;FBtjcQ*H##F224o(|Y|J$E zS(PWKEY>_*(AU>T%9u$>eRga*dzIe?`2x0-palc_8knb*<>k~9>7R>>*KY9RcqJ(- zKzPB;6cqgKO%^Q;)XY{Xt*UZ!cD8kJP*Cibc}5+^BK`VewmHy{E3VBPsDaMwl6Ou3 z!DY+q+}!r|_E2B&hiGA5-hrtppS7`4YjKkCTJeveP3I>eU*<~2 z*PyO}Im|lh3}s6!I<5&Og=(*wUAc$yMm9EGR^=i$uj%WlYEMQ|CVOT{M+#u3+rQo` zIy*c2($WHAFR+RVf{BHR`BeD5Ub&Txwe`^Ou=H0W5~3oy{^4N|j7AmKgsWIX?iA{` zva72P_g22cb?I@C#qNAdxNUBb+o`Wv=orQHg`w(|6e|hPpSGf+A`~E4Bw7MfTbx`1 zGO_~zCJP!GF^^d=kr3sLjdv=vbV#s?kVC3vyr|a%)hywquD`V*Qq*CugA)=GRsdt` zXUr`u=#UJG@8sebM;;?(=0F&I`}Xbh?99j88#NT4tw7lmK({x^L-wzBR ze(&BrF5~*#oE*h7IU1T2Qg-cBp^b}T5x@k%iPDGfJx~)1Z{Gaznn>1Y9@xun5VVKf zsG#oy2|wP8y5q1oG}P?%V@J%U!O+G*2;7^rhO5^9o<8!OZkheRCQ;P+p53|ghCJhZ zG0D-z)pdVw@5s9mQ~q{v>}Ajee1d{jJl7$O=;J#_m#&bxj6O;=DAcdKT%e27e0prU z@_?2E9jCd-;KC~_E;e@lkYvvvE?QJX#OKredkLS3uCBa{jD@)`uU7%42h-DMi<1Fz zfv{a&Tu_w;u9?&5N1gj-=G`dTpns3A3~xVJ3)4D{Mv^0TBNG!E&N(rspEx&OY%|c^ zyCrD)fIqIeBS-k-gNlh2GRwtVM5)%5#MIPW`AB7L74I@?gv0jL zhd>`&6Uy4!7GMTZ^C@5A1@nl9hbJGl2gCVyLQ;DAV4z(^WhJLcqxY9rcw>ZsTl~)) z0Djii>>M3g_WsG=Et93y)lYsG=UhyB|BP$!zN`_9s~_YLKv8rCfwE=lo=)UE8Ul=UgUbrheldf^=5)iz$cUSp8#Ohxh=|B?YCMM+ZK+sl%kR<8 z->%Y@Qs9S8FCKvFx^4As)~OZ@9i%<+Sq><07&%FB1*h9@T{$vJdQ9Uc3AIr$yUVV50Qy3s+o3|%VZ$vv`0AkI&B)dZ8) z=jZvr0O8_mw0_(JB>;kic31{j0JSE>#bs7eMvC9`0dE}LTeW9~Oyv_RMB?J&8m?_e zM@N;mqw_tQU`C1x3(d{V72aMaynbEjKzX33k>y^B?t1vP%_zZ53GcDKKDE1d^Xlsj zH8pQ@a`t@w?B8W+ZXN}iPfJsC60#183YS3&hnIDI&K2H zR#a4Q7=4PKzco}&2zrBpA}>Fm&2tNQ3^n&aLgMb-yE{8O2!E)$+qZ8sM~T=BW`fMq zD8v)v+kRX8lPtI=TGqJOl)kI5l`n@Ucz7g_3Iav zsN2ibGc;2S~TfNhLam-H|<|Ge|dbcnUYM>IEY8u@ZZ(D*aGM4O2ESKV9i~1pO$fnoLR6O4*YOanY-~@g zt)IHMKuN}&b{@C=boV6nynM&*vXMZuX$7rAUMp-a!l~DG8er9bgX7 z1#tM9gccxcYHQ&Vi?gyWjo*Sl^i53}LE?#v`|K?bq~8h&3Gq8w$$^ZjsuCPfAb(l7 z`P{=JK0cnqxc<6xGipk7W23LNHLK@snZGEuh0B6TK|xXHwtmNDncxH`s5N(CejWw~ z$bsp&jV&!pCM<0}roY_o=dWLnEG<=1B#hRMKntL9<^1#*fSfTvc{xU^RIs(Aq~uLl zm>=lcu~G}raaKKvOmwBWqZqUrn>i08OVl3i<_RleUb++$9Zfc;yL5qv~dU~d6o>_o&c>I_}q7gIg2+ZnmfsQg42`S-u zaBwhy9yfO}I6R9DgomC-{Vz26)3fH^qo#w5;ZYbKV(Q=P?lz--Y;N9vMn-gjji~oM z^ZeNvp_y}E-dzN=GK3uuAAhF&aTv0V34tK}dw>*yx>PzUeL+Ai>c&A&k8W!Yx&g`+ zbS*%AcUMa6w87TO`PK>|?2XcV&I5bk=?YHn_p`7%~mIfk#@O#Aqe zi-o1bl&2lo<>~C_mKK@d@$i@!`B0FpzZMpvl9M^XkY#7TdYkd%$B&80Nx;voZ6=(y z!|S|7NB#Z%4-2%X00&xwh>0xcwqvn}G_uI-R}BE!OP4Mc2GJo= z)64iQ-^8nyELSoxF_Ds!$0a3s?Jo9YXEUp0)nsKciHJO39m-o~NSnf?^H?GTfSn+h zd2^;(qhY*9i+sA!9=hBpDJ0|$o+eeau37ZX9i&X!a)1O|(cJ+>*$O$5-N2H{$_7YE zV`J*F2gID*f<*VIdA8qNBP5zXv@^7~wUzyi>?A@(w!!Og=T|r2kl*R{>%_zxp12{{ z&&B;6^aT<01yn{xMm9D!pww!emx9G(NI04G$~I2oy(4j(qgd2hzI@Sq@SsG8!Gre+ z&fNa*QH^yLCMJp-H_SI<+8iH zJ{*Se%P`0S!fEn7oA~@0u^B^~Cdl}GV8HCjlat@YP4B2g54xgQCA5^$f6g4M*t z#8S=wqb&T`+Z$JATYT9IN5dU~Vms zr%#r*@~-P*Vq%`|baPw#fAM{rppsowv|eRD*{=`=x&{bTM`v`i>B3l9`AP!cGI-=A z8qhdX`5*t+T#vfiS~P^9{RF?q)+``1he>07NlEzHgtX@p{65?O-jyq|XfUE4V$@Yn zFu9Y|Vu^W)(OM>+K6@tee1{Q1DSqZwn@I zJ_(Y`639EU2D|+A>%GjsQzzUC*6%4RUqVOIr}y_Q2Prz|AA~P2EH}Gw=w#U7^eY%{ z16lO&=Cvh&L9oGqW1*p;F>Alam`IA;`Vp7tRPNoAQN*#uNVz&dOcT|pZxh7pxn~Ut zy(lT>b3!uTnhR%7=^KR-8XR$XkZ`0sD$Jjbo!#7CHEiAU zCjb|2{p1Nc0vy|ej?8#G%p1b}>El_-aeN6XQ1{NxyMTzY^xRlw6Q3W;UVR}&tEWhX zvAK_Uwt8l{AIQy|Rv{eoq~3F%EviedfHz*n%Esnaf-^FHw=Lk(6)-*k!C<+IjT`QX zQ+B+gl1+O4_U&7@wXql18odr30IY9b>-hS0wdLiNzhL1oHMlCEG3}3rL5=QfW2M!OGZLPA z%hfZ!20A*5R=Tt#mw{K}Rk9-@G{AWxc|ZZQnWvrck#iYBQQJE>FxR_zh<$*}3<|XuvKA=M%9$!~fxoNz49`{CO;7P~803lxI`T4oEBnh~?DCw^f%-2(%$Vkb`ez)*sxWX++_xbFQ zW{WuBVlx&m1&xgvJtd{L_r9&|Zz!{Yz?5_Wzl$?>T=+SyRwtMbY1XTK)H5{pv59 zP5aewtgX)t()`YCtgSyutGQ9Mc63-I;$8+0RGHKTN|Y(>+0%~5)%{SSm%luTHXVPu z@k0bF@Wof<+{1S|!X2XA1o?*x3kn8dM{4U(DHC&%3GqT zwDei)8$xdhnsv5Dk8S#tKKEzOn#J~Dpuq&aJ#a~D_=7-Py7W@OcH}LMh^aO?%zM+K>6c zUrD1E!BPO;i@R^UPe`EH=h{2jx2;$)R8VN|>I&jf1qgb;gpP=gj$U3}z5KG}zZX%M z`XpVpy!=x+j?1XQbKf5gqhC>`!JREU?=YkdyQa}dUES2&JUu%b3$eAmy%MX4Ay4S* zuesUrdNuU+CHXBMl;)wMql0gEb#gk{?x4{q%gkg1p#(;;v$J!&{4oX*@r!rw-a$~4 zAg%igIwoK4Jx{Z?KDqvPVncrZDyR@zB-k^~Pa<0f2gYTVxJYme>S}7m85tNo3^*wS zy88O4B`|0I^BuDO-MgSijE&Eso(Ni8e~+Nvo6DdUEumHy23r=emaUS>o3BSg9>0Mx; ztd@q+4-|8DvV0> zRqe;1fq{Xvyu2WX9wCPxH7+X;aLim?1t!SG#>R4sibC%SsMk_(va{b75Lh2Ardh=& zXkpj+h)R1I@L;c}no}fv^wreVARJ+m=TeIQJu{#`Fc*o$1pDOU;{$mCSC3=nAhiMbnltz|Fg!$`*0&UIQa5v7DRf?g6NbO9dt2R zj2BX~Yir&sgG^<{LS6@`c~+|NJak-K4j|9PSuf%BETNgI;e=ZWlx9rI5(~~5`%gfu<)s_A!N$c~K zG%rujkA}5Q-?LRA*)-MFmsL-}uv_db;PB~ry&=|Tkt>{a-}te;yNmkaOp~9wI>G(~ zGs$;m4rXHnz;`|Jd z9u0wkb@lTQXVdXw(zkElV%T-eA9CKfNm`Vbx3V?&B}XlVj1-yOk|r|GL_$N|%o8g&VD!Kv{+F3ZVzT)h)YE)y0KqO774 z9Tjy24^KX%*Yl?2?c2M+w~tG80UWxzyRYEj&_-9XkmzH}C61Y2+SIlW3DzJEwjm}X zp3$`|J2qcE`DginQlFTlB#l8OOE6}HAMc7?J!-Tq&z>Btje`LLG?b-@a7H_+%g?`D zyL^L!0`#^0co`EP-vg~DAA$p_)6(WZok0q_ZBC2xZQlFI_aP-^W@H4g91o#eWk(Ux z_UZYqm8a(?u##qh_pmf+x&Kb6-`UwQFV#go{Rs{x@-d=c{hy;Ph%g<@ygNQVE+Qgw za&n?{Ktq#K!cihhe~OGezdps+d33bRU`54<#^#e0ye39BW^f&shVb{*+nj0QCcxndB!Hr<==8s;qoc$4`v}qle4ePVFadKxZZ6Og zq{G{=FvY~54Y#^N$hpVt+*DLlq@<*zrKKI`!Ab(Hut`e#0TYW+Z$duM|1-=a{H0(_ zzYh*dcpvpoPx~IM>2+0dvMH#tW~=I|@Y1;`F(!o(JRFUSh}hoQY1z2d70ahYa7^CA z`Ij8Au&@BoATtsE@7`T=iNi&dR8<*+{haZ;@HstthWPx3kRdWE3T2ougBzx>5pr^J z@$vEAhg0szaau+urb|=alFxUL&8Fd9y>&G;LqkJ$VGuaK84AeqsP0;;d9jI8kUrzBjc z;Qajc3-$7so}Pn)V`q2Q!op%;8|ZyP!R6R?( zA;H1fDhVx1y9EUW~jqWN^7PHNq7vcqy-%P2WrScmj?9bh4;@kP}R7Zf*u9fA#7W z_&Q0KWdgSX4P9N(6v00lai6)mCW|;{XJjzMb-TK_$f%3+`Qwmyx5a;WJeHCbqjcts?1;t;~h%8^IcWdX14ke3`~mSJ+$0 zNH1fegF6PdsK#aci^py4_@bh0_S#x9j)9cJn z6yVmjX)^m?tWLfg1THLRXX>UT$qCN?5LxzWkKT0TW}eek3RfAwn7c`IvF zkch|c{Io5ETo$L=ev<6wO%-6nS2EVZNHqms3D>f+GSKWe2&rCv569~=Nl_9U%n9z- zNOM~^RnO^q&0q7}Xd7Aka-^rH2ZOA{L2=e3L`%wWx(z9Ne)7Ax;p(*@!@n1yGE!}2 z1Z4;a)WGdpUE_7=prrJsy4oG81Dqsx)Ik4f!I38mrl+STK8=K(y*-NNM~h7q6+3|8 z7kiVh&=r3CC@3J{bF#Pcd$c$vIvOcs1_JZmz2LYwa^%ym(YH|D(CqDB5`bfws(BX3 zLm?q?G7ZUkV7dlB*x%ZcTII4N4hY1?$GUV07c=1C-~h_E$f!B@uNo~!osK? zSCf-a(dmJBczEA))RvwK1GJTvmZmecF=HY_177ote-QWb5Tl;ZO-W8x)t)T3>X~<{ zy>{&y+?B$+HzX@(NLt{i zt)TmG3%5`j5=az|()s%S(ujwK6sRY{?hF z=kWY_ZB(?D{CH>Ogd@V=I1;xe<6BvqRps+hTl|cFo1VU{9vr$u1cjhA=*|i0e z0$XhGQKqYNFyFDZvTC>FV^K}yw;SU@e1;LYpCXZ*kZ=qlFO*V<$m)ZqzyZfat~QLu z>uXeOCt2nLx#Z>e3*@Av0{r~KVEHB{P;*NQeLxiFs3yg}fB!x%&i(xKIUIYoK%3j} z2_B`OspHF7PJ`^?VwxK_f`1l4d4B)?Jun~uK8*eFLBgyBv*n1HnR#VpC5&49o|>8o z7$BlwMvdOJg@ty;#?ugkj(1ebBW~txnIAZ4X;JSGK$aL(*#&{lFIeAf{KLh~jd~FV z%5BPrw9>roa;BtG_QQKh78VQ5f!N|=Vt}}ho;(RoV0G)te^_vh>dsJq|LppDgLzx< z*RS_vD%FF#P;L6W8}49&d2rvHepIS^kx;927u3r5!~{qnde?`v^RMXH4Dsp2+}7f& zsstaPGb=Nb(MVf=V@s&7uLtoCLk}`*%~V~zAKZrJqeq$#9s~piMugxapRNpMK^dfP zM&g#!VYQjlZ@!O=jD+-6N#J|gV`WnBf$AKnWOaYYD*N%aSFE39X;f_NtBVJv)+FTv zueXzulEBEh1Li{^!uJS^iV{ER%F4;v1wK&D{rK@3qQ-Oo33#lkyA4%UWC#Lsa?tft zN>rS=x||qvPn{Aj-gc?y+W1tG*l=896!eBn$bq zyzH^_6E$X6u7oTuTJbV4{TIxv7@cv^n6?^3)upc>j~i#Kaq5 zY#>FzE%hb|;WI64dpz#@KzjKls9NiUv4q=?Z{EB)F*#XYUOqfL95E~|0U$XKDg-qR zNbkdd4~xF+*4~QdPhF2+UrCvmvLFXiUmC$U@9*z}>9;l`*Ar|_eemta55v9SYOv-% zew>b#S`f5ARgX={Bn05|BWJS1uJh6h z2$0GgEe|jN>O@bDm%|;38=xLQ4CpY(jS>)$5#viFsI%S_^Vs^^uR_#qOSOS(g;$M-F=RtF*qAIbrt6C z)6y7T_(!|2)1FED^BAtb*?iWoSU^(@)i#C%U{fIVVk$#$9u zFTY&=0h<2G-=j?aJ&(F^xC)<11on*peVt&of69M286I)nWz49F$ z;JYN4)MHhyaay2L%$J~2VIA0I3A9H<7DeD)=JV&EwzgI^f$!09{zGdS|6=Zse^0UmWyiLR`*%4Y zliS9RTW-i6D=#lEzZLI+{yn@svb%|{8E^-xCJ9ndQr^D)w$6Rijoo*K@7cVZ ztLy#?4D5r(cn_S0tFat<>BYsx85s*pONu_&XGS(1vzE|Tg=XyQipX|l{4ken+6<%&IHj0 zmV)R#l^iDvYdcFpD1aY6KE9XNANde64M!5O5^}7Y;s<=66*J;P)l|*R(_g;46xH=} z+XLiQoVpEU5PU1J`G*f58pes9L$Y+CC~uw=Bzz z!I8bptqONcu-dRNyh(@5%F0S74xsj;AjqF#Xsy3Wu+*1QT~(F+!H=Ar-0tE7RMo`O zi=AJ};4XHT`Yedi-$FS;Ai63UKfRC;5qbWzGXmKqm$U-#7SCfAAVmxQq+d-YAIo2uRc7 zV(zexKZ{9@;d_i9z)tubZApW=9U5}kUF=a3jDHK1gql4aQomLCqWXR6bs7^&gg=m@ zfbGc9$w_ujPR2b3mv`a)tm&#hZezTIVO4s=EJ8VyRCD;BDQQ7lCLk?P-2?+mii(O* z69WA%eDB}CMzkk45WX%0T4;%b0kX4gRG3bRz>}i2wUzbOt+|G)shyvcaOO%aIsi3N zTiYTnjj?o!jn^HtZ}aiJx<>VNX&2n@K!GRkz85KJjKd?@tKPg3Ck-IiJ0ln(PQ;Ho zx>HL^P;F&EFL&IZ`P&U-7kqy1lBA$uRaseN_b>3!eclo#_wPF#ZcG7WdT5;0)YPEn z`pV1O&om}`h6)G?e|zG2LXZ|(n>T6;zSYNQ4ANj+!)k$htq7P{g4c2ZZJzZ;&BG@E1inM_0W5Q z5*YuP`xK7k7ypibUHEBgQIWle#}VlFl81y=R#t6)55M!{r6msLe+}2N0XN3#wii~~ zv}nvgIV2Qv^$~3YVp>S zAyyk38*y=Q>M+oo_GSK@oSblW&7AwBqVI;W(om^?G(oGvoHo#Q&SBHQXj7_Ftd+)5?$w7F2P?cxyJTAokvDo*wTKw1CG#^{*gSdoK*q zBO)qF)5vIjaS@F19bc$jDp5BV_JYdFO2Awg6$IiN1L`FqmdIVx z(_I(gJn)S~KMo$CrgeNsOQSn^Qyg0Byaal8367sXQ!(@N^GOyKYy)}pq@+FrGD>+FDypX;Q?VgEaUM8EI~3$3Zv#&q|oztE&hEKDF3qD~qEe^Kok%n_Jx6 z?yjz9=YKXUD=I);v8Uk_XcrOP9wh0;+BYX+{?d_?cHH85Cmw2Pg~yBSxTM8ju&8~w ze&a@dZf?z|PpI}+{Nh!)>a+w~$KJs1kUk*F-oL+Dc1j$)MI+`B-unwFcre6i&9hl6KG9IxnfoR=PC~3S}Ezv%;=C%U@jqd$;il* zV>v*_5s{J3H(-6L&`OQRD?5T*zAW{3A^_^}ZfKF?|K~^{{;OsF9;oR7e~*8u7dVcd zuweRFJ7}4h(EL~1g5i-71##c77jhE39)T3Ai?T?GJJ{E5!i|?yS9g#&mX()37yHoA za0cL6Vu^bEugBw!5e|11gVQ^m96J3_fI=XokHD#qLCpeH@Gg+fP=V` zKYzfm68e3LXCP@i(z;p8n#e*pA~+o%%tHwb42l#I7~~3(3$26z;GTJ@?#*kD0f?4~ zQ0kA-d!^?Z=3ZLu0HkT(|LOwpAZ*5BYn+xpKFvWwZaKr^zt+c-?3(8m7wbHH7-M=y zPjWdVIG7emMMagCmIff<|I6EQ&MLBy4mL6qs4jE%x3oL z75V8z7r>v^j-Jn-*XHN1Lb=n`s`V`oWCR8TG@cz8tQO(YS@I>2l9Hx(y~3w?r$_yU zei28WSAtZLD|qoPvNBXCoBmrnn6svfbJP1iL(2(Y$L_M##$qQjV z2`_e+*}C;Dlokm&qgV5k?sRWa;mA(uAT7d90(m$f@@yU%7Z+DpSeTKK5f`W9i#q=I zgDF}hyLREzXU`~jO#R_UO-)TdA5>ITVPRtf-XDgy_F_jQCax|nzB(5a5>jlco3dB+ zw%hZsZ?oE0vdh?chIOU!{-{#Q$T5YMWQku+R~?b)Q0u5XU}rfQUFSn)zsoR-Yl-Kqb3-^XaI4b6N%Eu$;hBPVfqs^KHps& zDKZ!t8QIv_sCJl2pH4iQI3m%0i0}tZQ|&l&jp|M`kMF~W!+_UJ^&C>+kG{as+G@Ey z-xeeKGKV&lKab@+=Oi0I0l+@WPs*RAM zeFH~uu#>AR)7!9Rc4r2ud1BdR+3#7${f}oSDs4fp0Xa+hor}>{@8%U2s;H^aNcxH) zz?)W8Rt}GjE-fxP{HWpO=dUO)k21F<8o}Bh$t0pds6TutU^AGBY6MR$7SD4oG~>Pd zT}=}2rf^C3N%Lcd|6Wx+2Oegi`EN(M8pDr(r+oJGF35DE6m#CZB$l~9)YI|zI4FC1 zdPGD-;DmkM-Of*+#!LG73VqU=NrQSq&AFtw-412i(t^IOF&J`6Pmz&! z%)Mayo?x%GmJs>0{VfG*35N03?RZMUlU9P0eis{wz47q4IMCQYxRP+2BHl+&m6YBD z1fU}jHdn(aZet;47Z*pSr;VX}N(Htn2bQ!S0!zMl@dE04cK6t_;TLe=6*3OfQr*|r zsO~8#9nHO_!LfbCLkU(3fq*c>D5F|XCrJBA;ZR(Cg{hd!wV=tt91#4RC=EL@mzPw6 z5>!VZ7T(VGHW~sG6Epm|x(^n!YGQP9a&lBuMsabNr-i90sx$ZM>gxH?0zR(VD3oyS zuE2d9DU&41o@7xSkb|HGVhL!dHX)MUf;f0qx$*cuPe32^CqDw8e(&C8zFE48-4_JZ z!cR>nDs0AT8yg#!Uwnm8MMHGvy|@Qpo8efLFX4SeKtNDp*%b*!G5QscuZ9MpzAvx+ zL`7~cYZ)$@1SJqoCrM6T-U3rQxy>XeXJ`11(6?{5{-!Jkvpl4%y)3;2o424Y z#|QxRfC~!)L*Tc-;I|(VDCt@a{lW>Qfc?F_#XO}@TLeTfD01nReE#vnaEK%#y+FOM z49(h^A@Rbqaqj^Z`bqx}R&H*51Sr$c`Uh6u;?X17*IHA#p&@u?78{hw*z@uS)?~^=xb_X++Fhq#IZ6rr}x|dQLXUq zX4l+PfI85vQl$c2PyQhtQMa|_nI=iA@N#estOGfUJLxjsf*&M&K)mH=WwlxIftGxk zjz=TmeX_UW=H_N6_-E%=cRC>>H``h%1Nq-EAikkVXoY&x3(N;#0hlmlR5N;WqKKXF&5=ek7GUJX39qr6srHweZM4tjVe; z5gdjr4&{v-(b3U6ySumxeu5}@ZZpVO=9jfBfVgEK=t9xt*g%96HJ73B4GYyBNv9Kx z@ezqJRythY^1rVSx$OrP^S9e?KydJ7Rn?ySe72S&uY=1ICmcrTH-SzSDsWto<6B9GWEQO7YorzE?6_CFm zeU2yfBo>ck;jl;tU4p`lpKW|udlc1|>DbP{csB;^6!Y&Tm8dmbWexs$IM(gYgPLar zx)$Ywo;*QKQh<_gIRa6OPb2ZIt7{zWoR$`e9$_rE2^TwiQd}Hr@hu1*bVTs~ecymH z2MqqW_dRfCTvQZ8z6PKwI6hHFN5|EoTb^7yHxNS{l&tNWvc;HE^D1;?q2_`ot2a== zU2#6~S-Bc6v;4@^*7o=B-yw&5D97$bkK7t7wE)zJcc4X}u==02GZKF1rwoFg|>hd z|2{YvzQ#o~t)`~7w0o>{eBa233ZZUjczS;3_0t^n#@)igVr}mq$Ei{och8o-wI0h8 zBS9y?+FpH=6RAoY`xRNoEUh1aiMebld91x{eO|6Ypu3R3DlA88E38<2yR8>3SrB)d13C#MHr8{_)7 zCdhEyXtUeP&ipH7-*cZW2KZkBAU3Qakg0jpO;#aMke%H=G{n!%?fC0!3~Ihg7ktln z`Qw)|X6ot$`eUw(-zc!LUmqMCtgYF(y6(dt1_uYhn@HmTn4wnh^uE7)o#q*^6kMIV zQ1y|Wsi`ea|4AA6uagr`(03J$YY+&Krq)Jg)$<_c`x0(r%jg;y6ciODM?|~`<0iQb z1^qT)bF5TWLnDIYeC_YkXHEhfTI900&$DNxpFZ6=sYC5Lk*&Z=qOYraQ_}aQ%os3^ zuI`&&RTY(+cU-L94a(Efn*Yvt(c@r}f4RuDKs+KCGc9vHg@-}{hT+sJH!m;f-8-@v ztk-gJV?Y)CJG2^&e>Uox&QFw`_=2}3T?MVJ&qYy>n*UYNfE3|nO1>z=v8{aXp0|$= z&}`4QZ{WPT<~Jv+`+9opzee8zgB8g`Clzw}?}TwOBQ0xNTU0-Q*;#*1w!Q6bsK=6u zidHgGPY;iq;+_=-MYwnCu}sxiFjFSjU;O*>juKTdPj~=VE~pR_-T!(F`s#r1Unqt) z``b`U=^vQeO-N(G{Fg0rALo`HTwK12?O5omN1c)rV|pe<`m%%>h=8WkA=>*W78QHYLK9q%gV|w zUAmOQ<-s4N2w*U5yJyA0{&_kJ-GAfT4(HgdzU=6=U;yO$Tgw;IxaQr?OVgjC#3hX^YX@j z{J2V2@AT`QgTu$SZ&l*hZ#OhF$XEB>Vq;5Z+6IHc#>Td+jQf0VIU*@3X*t4vvWio$ zEK_YH1QpFe<*c*W+1cHtzL1#C-rj2|#9a}P0Wci>iysFEAAD1nDunPsP6A_{ZUY{I z@KDpBM9vyrC*v|4GqShCY^>T=w{hWvD+W^n4p{fI+NXzuJw2T4>{rgF1_sa&xp22O zHbHOSz88DWhumrprCeNGL@wQ+q*R{v8muNbun%r+Z|{xg#rWf~+z(k%2Mz~k4!q$@ z8B{O2{>8-hb_MvDO4Lp1O_k4|gU!Z2*Zx2XZ*4YRG=k-ZxR#X>QF#L!^*I^n=&+cH zK5!?b>=(43K-$+vN@;7yqQ)*KaD4<78!l!%I)s-D511P`e9un0Iy=WECbYG*5QyIY z*&TnVxA%VZ5dfg5`vyt!0}i84F8iy)7+6=OXkwzH#l*!?k9Vx7p+*c!OwkSqQ{Fb4 zUcY`FfxtwUR#e3Pr2IJ}H&@uQlK>&*=)JPBaSg$9`!=PR$JW`OLo|ehgakyiA;Aigyut5p zZ#GL@A|fI7;K1_n^OWaP%9_LEV3_jB7rLqkJfUmrA-zdm`)XF$NwB7?a1?^PPEXte(K zii5H5DD#f$ibqf10`_%$JfTDY_m7|ig}m>d_39XQ9X57$3Oqdb^z zyMmho#Ns&L8nnC#Aq8eEG;VFGzCf2nm)dj~BMlHVTllADo_Jl~sHUhr|7p$4B zGWS$C{&)%GnI6Z;8$t$eZ}0o>g{6g4(GUP+AOL|RP+M-5If_96oF4B+kg=Ue>dkC? zF&{kTPIpEvXS_i{0cXGbvIX*EX=w@nIuGiNA0HpzvKe`+{T!-OTVn6z_;}FtH>!Wy z#m$i!dzYDgc?F1Ze0&T55Z?0$jFpP2>Yx4JuMMBd;o{+ihJ<{PsH(2EwYE-8Sp1*! zv}1#UaFINB?%Y`Eg3D4@P+-1w3pZI;Uw$AtADnszWOUESO+b;|1*#!@}_6x|4+*sXb++M)FvRh>6R+4juN~A3e${ zD|523u~Affos+{dP8>izs_;J-EEHLL*9XV|70SqCe|IWF<*Tpgo`#|8~<(2Wf;P2uH`~__ zWslYm1gvaq!Qw(K9|)jCpVt0>5)FTupP&CgORH5O22e>@SXfS8{#osh@NfctIa;X7 za@XG@4#W7Z;&i!xw`-6!Lv^4=ZP##9#EJ2S>uo+hs6kpJ>g8N{xonj&Aj+7>oB!E? z?#I}eQarY#WYchgj;OHk*w|QVfv(KVh90jC4w|_!7WxZXdU|>w*WqE(Gv~N~3kVy? z1T|&l48Gm?JFfYdp$1nqW?pPz+l0S6x?sySA^@mv3kh{p9Matn zkPsAfgAp?10=W{|x76L$weJ+rwzNCI>UOecgM0Y`a29fiXdX2+zgE!t-&6BVbaY0) ze|HA;3q^I~j!SMsgZOyuk$Gf-wD+^DGawpppYPw_6cDHcs7EcOe=ic{nX?+H7)Jd} z_$B}qY7egxq}RxY;dbCbkVk-`Xb6jrcgf(z_MMFk4I7UaDX{|Q=H~;n2SLmOa-=nZ zNGd8U%vB7OJGktlq@d6~l&49DT&5$wLqtP^kJtjWrllp<#p*V|)g5roBPiJ0*SA?f z|6l72X6l~@zPhBSsL1c%+0{kI`<2U}TqyJ!;xqmgP|pH9JmC=$6ar6%-csD|ywAbS zJ=)*@`M%@-mrnfOY-Key%MY#e@u|gtYCizUo`5_LIY%+fu&%Z?7NWDW6X)vH=m^vy zt!B`*b#Orachf?Q2*rYk2to-}XXo7psFaz;v$-$WAOZHqUKKhX-sQF7Id_jk`}dP2 z>nUvc=8J%U0FVRR+}va#`(O%lb6MBu9yosX#%5&s4zYOltocJF(Fyw6OcPC=A?~I1 z;h~|(sHltcKbuhdEiE#8z3D=kIXUFyY)}7?F^ZqnhV}2P5*#8%s_5r>{N@4Gls{O6oIQVCb2qt!=@WGHUzXdme#z zbqR3jl6vl6yhiO)w*Wk@7{ug)AyXpcPt-d+GI9+E2NFO7B3oVUcY0KcYz*aQR&_j@ z!EJ^T0J`xzKYqNXq@;x7>6#oLFYNSFsW6FJ#K{tD@UkOyn2xdWhZNM|Xk(KA&_F;S zb?^w)!d5_#0%~bl;Nd?{%$z1M5cPf+zNmf<_g{mj*c;sV*Gssr|Mw0q_#h0`{I|i2 z+#vsnDeCa2ZlD(T%8%T~w#IhzQ7hDoE={CS?TT|GZ$sLO|K07O#8m=l?tn z`9(%0{k1|k2n%FQ|HGILz$c#65dB@l4nCjo>k@L-F;_33Y^m6>M;91iw+_qryG4j5~2RW z3aj$?J;T`XX59Yk{pQ-^X<&vkpWQ`OyD8BaF18o3v9S*ev{mDI(&{k8W6aZkOan^M z5)j-!>q0dvJIo$f`j$XULj%Z#jquo-MO%BPURYZC46a*n)2viC5F6hYK1I+nFvt$k zoPw7&4lU0{-rA3v(4NXU0VWcdXI&=9CbeOztMAnci=ZZR<21})4SH9j$MS$>4T zr3<*++}vC)49HDb6m?{X2?+|mdi}awmqReg=VvEjG-`VZ@a5gVP)*4=wV34!<1MWS zkoW$;-GF^-nO=;HNJy{&GrGF^$$9Di+AIia5S3Fue)L=69rdBw-nsuC;Ve@JG4|7` zmV=C)gQGAnFQ`OQ8s`#vb2yzWmq{ZBoleu)K~h{?Tvb&SjAC3I`Mvk?@yi<<5^ig{ z71Y6NKd49BL5;S}Jsq=iGc}#9bKfjkF#1Rb<^VgXM}d96BcYuH7F z%mwycq4ygGX}fNq4^$CfehJd^{QTU^%*=W5oAl(nC$_d2=;*>Xdkgi-`T6-*S669& zaa|4?Ay{5rO-xMW(yzdA#aOMonoIJ1a?T5 z8(^elU}ThY@j|CCsCE$G<(=F1$ORjaz{SNyMn(pJ-#KFTvom5jvi0PxI;&xYH4Jn@ zQ&Uq|SYN{J$Lg%5XsRx8FE9fm!QfuHLZ+*y2S2~dLr(|pH|%%@7p-S0CoiuHoMcN& z7k67Mr-AR$+-vUSE9g#6PDkDnMwC4K?FYA{h-==xyT;C5&{su8Vxp2bjj(pk;8ynZ{8U!P z7uNA-kRmN@1^54deetG-h8RgMGtkp7_N81rZ`|7@-)*AA(wC9>_p9df9-ixOeH+4n z%yu8jJX;aPmP_ICn4$Wx0-qgj7`bG2EZzkN7@u{yD(9uSpv&LJMgz6+n0fI!*k-2(2L~d~ zi@AAupmY}N}Hb>8Xu=1C2cb=MYY#ZyfL$k?D~Y-q62PI(#R~& zU#RiqhN0iq=(TgA?yp~4J`#d}1k1O!$HhGd=nnb;gbH;S%biFZOmu8)Y!wVF$&U|c z4n0+xe9t^*xehA(mqJLt4-QVFRw2~8tPDDm3fLeJ{)oGB(pt04fs>PybP=NR8XANX zyfr?5+$1F>%dAPnV}Sq4;X$?;MGmf_Zz&oF*G`f>vc=$$@GBvyxv>P+eI`=qWdswtOPHZ2i(PdS}O}!j@G?NJm;4 zZ68mJ+obVZPfzk4SGH`KDbC%rfec0LOPA8b?;}IsZF(UqU-V(gcOGXxL|Rmo17 z59dFm*Soa46qu#_LLG+|v)Ta-2lwI+s-+vj6w$aveM5s+s-P+r8}T9vPMhE@*rMKKQ6Ux< z#T}tYy@x=Z(zFDqmC6MLGqujI`x!3d%l|7;t!-@?G*^IPdwcKm<>>rvlE;!Se0R!w z87dUq!_W|k52Kxn_Y4E7y&l288sxQIqkRGLR^Pw?Oz(3K57QpDMPdvkvGClj69Jyv z7)n09UosAlnP!Wd&Yhk(`}|!WRz5#`1kjtCpC2jz#YB_{>;1&UgmN4gj3Sy(rW3C6-Me%z zvfJAgRO+_C%7GO4ToH>lP;>9u4+hN5O{O^_@Cx#LoI5-U?6ORZkH1by z$qlS^y!W?8P&=b{$8w5M_x1FwgRDX}CnY6;{N32xbhNdtv*@^{QWJFbTmEI4<@I%+ z`Bq$P?AM?@@o6Mb)92OG6-gAT0RSpP9izYJsQq49>FVyj*zTZ-+?BLwzq)o1U@pk^ zU%S}RuT};-qC#JQH(*D*x4$2ubcMq5qnNoG4j_BD^Z}%Rot+(RklNL0jG(KfESNSn zQg?ANu>$NTrCeQSBIpRfLU@8IBkw@(saTH^!m?!{~~#v1jtAOUgT z)A)`B+?O&;Oj!`TH*em+Xv{Z7q(9U7zw6-bAov3V1H8Pv%X;YJHOP2y>_CHzL#S50 zK|x&|VKjh3Q&UsCqcqfELOv%hd!*LbP4OK>X$1sk_Oe6^1=Ka?hK=47w=ESn=8)rC zySt(uTeL{jz=GO}vG5u^ zdqik~R=c>&*10hv#}W3qJ?Z^YhoQz7$Edc>gX-GQeOmGG-Q*V*N_C+qa`UQH{e)8a!POH>Lmq9j5Ck z-gvkgesZyy`h=QxcXT9^Mj-y>KMmhl=ZJCi^u|$+EGsK3JA3ihFWv-|%sHhuxerN4 zFu}@%ym|9^Crm8;@|7#ahPCwB8621YzVAyCv|o)np%M4o1EA_nk)$CfALZ=8WE($P zOmg%+Sz*~Dka5ab_(R<`fk1#aD>iP>cX9v;9CGnOCAKL&ot~Aov%A}Ndmc6KQ>v9k zL0e!J zA(67Vwsw<RJyrXC&<>_zQQ{Ymt7(zv8l#<6@(up+;%>`L$>X)}|XM3uH0JYwn%h zBWGY>umGjxEg{LvOK4PL89KkP@Wql30|TSZK;9%)O@PkhXlo91E0ktI{qKGGPHA za#P%K0a9SE8Y@v|{W}Tae@|3lIK&eEPGv=x8lNLqi7# zRM*L*#6&s!D{_>{JQVwS#qq-gb3vBWN**Fq0}SDv4|5H^Z&Sxpt}HMATw21$#Dr=d z|NdQ5M$q$?DT7_s!|QFWSLDf$mbicMpmRHMy89MBs7n z`}+ENe}6>RLcXpbAU)t86G?FYObEwW1cM?lHYn7=a<-EP|EnY1qKEtCe>%e1|1(9_ z+%ZY6Ckj#9F_{0b;M4DL?Rr;V7A*w6*;W_k96I2*8%*n`BfM2Rl2MG4vORo}^nc12tFnF^9xa z?|sO~6a;7AFkvA6-CeGxL+~;o{i52dVmuw4QBbfzO%>JEDdJwSpRiE~t!Gc{iL?Lt zNA7>^sMlChLLj3Qk4H`(huXCWL2E{ZPiGmYDtz5j#B^DH z{kz~c{_i@d2j8%;4$z4}n)-y52;!8ZCKJ*eoOyAOAE;; z!Hc9;LcS@Y8>{>+>2*z2F4n15mT+8pxv0M1L|meIwwPS8;MwDpWCI6IfWe{cBsaZYF`YFltd$pQk4{ncSW&Wn1M)ejHmz9rmFPEH0i z36i+{Qihl~3fOv3f1Bt!0PcKSh`7W6*}D&s@$mr5>}-#BZt0h2XTNGQAKp9u8qF=I zuHGNXqzpjR=%Ubgy~2eTuScf?xF%dpMN3Po+6n{JVKoNOXJlw7^-|GLg4pw&^2dFs z`MgvSk&&LDj^jSQEl#$dtV+XnG9e{s5wIP3L!D+&uH5ex?kBQGjD92WLi?Zo0r~&* zbqh)JTS4`8Yrfdv``q0-^U1Zlz5Ugfxuc__=$II^Ah!Oc-ee1&>q=kVrw2*t=_M2w z7lWo~Xb{)$yrD~>yuY({9QEK9X=3p>KYo- zis5V&W&-n3`yx<@ZS3!JGBZ=#hEs5OUC$aX&Dap8%Pb@O|7(uJ%b_0DJDT2=g(gkY zQ&SC(Hv_jT2dZaZ{+Ma>`ThI1t)=D9`T59{6nunkgQq~%t!F)n0*#H09`ct}mVIYG zzmR=(6$By(4>Uw(W~Q#59t9<(fu7#JU9qBjK}5elhGU+8*N&~Vb?4WwRn^tR@3fBC z8yXuWgoQzcmX6!mNsU$7l83a-KNY_HxK}O)HIwhsrAsd6E-w7E&p3~Vlu8)%Dy#_u zn`z7Q>GqyBk7Av>zu=LOS-aPvb7QV1F)?vpk98es`e}{S_PNw zhEa=qZq1@0OX}+lA3od%N8Mmzst4uUTALdvbjx4P7;A2B&ir>4ZUJFRVc&R_{UmB@ z>}!pF7t~#LKJ@3CpAIFk{u%Cnc5}0)acZ}@pw)3q)2*h6T(X*ufFPBUxk7h2l9N`SGCzlL%whs>uK46X-51cx0)3<^27%ev0TwbQtd|~{_Wo31^ z0Q>57e~AbDgdWE`Ou>#;R)QW|vwsdZHKUWO0Vk@fu@TmPr_bqVYd?5@vb?hL@ZrOt z-rkXqMvzNgOS@A)ev~xKf&>FC24(~X4Cm@q#&XV7>j(ZhLgo`5|L&hROq+#?kZSTh zTLg@7Thlc$nTd>yjEyA&y$OmEihAeR+r+CM-&0SX)Zr*RW z0})0>%hjPgu+Wm{M-2De{;Snqor8VFaDP8)Xb?K;o>zH~O!t(W zW=ESv_JhfAbaa$7Z^ilB7HBn#B>5Hz2?>bI+n}Q1ml;(QvZ}V9fi-C3-#k4#bNo>w zt^19f+xY1Cc-un^=;Po4F`#yKz=Gk#mZm5eg$Xy=4UUkVP`aE9H+snae|xTo-Tu#cl}#M0xo-CT$540bXCPY zY+ea8{ma-0AUJTk>Uw&$z{9PrnD);Px3}qT_tLs>(piFhKR7rL6ci+8R{5+#FX-^2 z^Ouvz&HL)=1b51w&b0u>&V6}ZS63I6_m*HH;{RR~MJ}l712)ZRiNl@JW43LV|+tuJZ=;Ej@npD9ss?$hT zkd%wdUdziXbVv|A(Gd~gi|AFbx;XKjoSiExDmpoExBkC2!prar4hoW1z#wSB#;1l0 z%$WL^YeA^+C5c3eo;z@B>**em<=R;3n1Y+P01d&y>?8N-Ib@o`JSS=| zJxO1&dv}kJvxhT&DLiKA2Lq#{hK4In z6f(D}N^rH81S%7f2ubh})!+VW%v8QTs-3No(G*axNs})p$z{;AAo;i2NG`v$6Qo?v zbhNdVRr|1Yd6mH3R+&{a4BLbf*|k-6P?96Fp(I7_N;!lE8Xnb6#N52al;{3?;eki^ zfA!tqJR7_ymIBr-r*ZUhJGxUdS}ec(^UCy{(;}#U-GF0P>45v zv#j*8X;2cx0+a3W;7Z-1CY-OU&qyU0q%8-o2xd@b;&V#RKa!`&4*271<%^AsYFx zKzn_riKgL2%f_>|cKiC*SIq1Q&bek67K&Y3?lDm6{8`0q{^a^Q7D{CQo9*aF!gKGj z@$sz8Oeq}HZVdw+j7Kb(x%H3}iWt{EI3#qtT%py=+dA4_K&@{I>nJELrs20HNNfwq zlM)gTK;=Eie=RF&bMv9n($bii7(=eZf7;@W8KIMoKSxM`cg(yS^^QhT!eh%cSd+%x z{m|=h!>HbamzGwFm1ObfPt#aib5Jb|51)XAt?)(1pUy-OJf~=FYa=BmZ}L8Vpr+<{ zvbVBqSRXHF#>a-5PGIBwPp7|BTmb~aK9}l_%QB>Ou44DsuQCCt=jZ2-9z9a>=x%F! z*=!0VoS&DMrpWQ(!w1mjKPqg#gR%iw%Kd9)Aru-K&3mh0gHZyHn!53EANAUqUfA%T zZJFhso*vW`ly^6~dV77r`Yhro4$xxcb(>A4c2us<&+p7O2ZEk)Y&ts_F3`ck!a}_z zF-NVoIs0?C&=H1>xO$xjA^yCD9Y8HQxkFZ)(tP&Oy0qHMAKSwr4mT;Tq8h%&aT)0Y zY8Rb5uMB1pv)l*&0Foo*TWEO40`K*=sC83ty4u=WUteGUPLY5+fM`mVz32!fC8alS z-;zAMMMjyorQ`W`61D#G=f_~};EE;#0??rbO#IGVzs2)H(vXpnS=(K`e3|Xmty^qt ziIRT4PoMI*WrVqN5;FXKp!scPCZ%u5q~mf78soG9oT6 zE+XOuO=WAly-e73Z~Iw4a-4rs?Duxfy@>zWJfE$iT61kFqq0&!NQgY|2^KcC^0hY~ zZ`j(}md#N0k1q11DFNEl z_xa@ZfBx^O2^tOCT#uH1udbqFU;sGyi(4uTYw79TGJ6z?>d>Z3PECE@LF1PTDey5Y z$M52N>@YIu+k)z4L`2++|88y4rll|6R?!uSnv>8SV}kTtS=M;?`0-(qI=xDiEtOhaE z0%chl8FdDtJBn`}W?1rIT;o%I2^I?mE>APZJZDys?KB3py`)Bl!d+$M-zzJ?!I=bN zHiMaKYisY{-}LeE;TOy=DCq9$f;4=#(2jRgn1J)uOW{!>F@lyLVwUuGsCQdnaw@6z zWAb(F|92CbFGIm{9sl6a-y|W{r=De3ZP^MbW@7Wf_nWf+QA0Rv@8G~SxKBjMQ~DzM z@-pWK=fC0AfLKOHM4Cn*l*@-MtZ;@O9(&&7NMw&FWGj1*Y)NI5GP2`|kP+F*Diks!d!-UW*)p>d*?WB-r>@uadcCgq`}h5R zZolvM{NuX0!qa&k$K!Dy=W!g5N12+63L1@W2w@W;&&|t|@61NZT5xfN%qZyD&dU7j ztPn-C!{7F#>1L5;C!#`u2fK zo`_j`KPSyMCYspL(C`K2{@;5b(tp^iDqOj8!X$-QMWnOk9~I>nej^3Q9K@u+gtD-t z!zJE304mbl9Hws&R_FBOFZeHrZUm-f0C9K#bZolY-|iD!r_f^b;XSnG$s-PDX_V z*dMe5F&5aK|2#g;R*wU==dbfrGjaa4k)Jy{m_+QOrwqURX9@O*g@0@_=$~#&Sg~8g zWGtV-!F-+N9|Q&TL((b+kQ zTE%&&jPM?(xVX47|6{KI=s^er!D*}MK>RQ`7{4k9l3D8BjN1MC_Z=MzN=r+DmxF>@ zz^!RHYUwR~bT=W=7TyRXAO%BA9Zp3}9X$Ft=7R2{pS3pOzOk{f&CSi#`oq?a{ey!S z?7PyD74DF*xt5Dog2;I$Z*N|>`1o{nbz4vMuwp=RDaN{#VFzj*oF=UkTRsLYak<~q z)6-z#fD*w~07`|hRTHsbZgf5eGa+lC?m-y-h82REUd(|uwpBz-3?u_w6uZwuLPF+# zd4rS!OV27YPFAYdP)FXz!$F5IoT_SQVPPRKVN#N@xA#R!_b<;bn3$L#W-|~UbEh!? z556248tUuoGb}U@;&{V}VU)Pj@bzmGRGKHT$Rr_@%PD$d8T&5_lp06~^mq-9~$L>r;Uh1~*-@o_v zzD-Z}U!G+b7e@-mG&Wit?(bYYO&VT)yZ<~)B1}@*A&$&=^xHF|y)U=?kAz+}6_{2a zdvYKZEhO1}J~W4rCh!`&{P+;@`}w2IfY=ADz8Z&xRfmS^Q5&O#x2r!oZYgeGd6Qbm z!60(9@iZ>(f|OKvUCz-9AEeKaW3?1~7=R8XC1w46JhFzlmj$97hHd@AtOH=qTVuJv zNmu8+IXZe&m{X3tiJAKP@@k5>vy-DEr&np;?EcC}=3jjUx>{P%v9ZJTe)SkbGYhi6 zkKg0a5(VomW&L$Tf8Q_UIoZFC>laXBhm8t*_>rS0Y96c+5fQ1Ws|zaPdY5QUII`cW zd04@Ur4V__$4HH^PS;GXnBMD|A13#J%1R_`aISgV|I_o=AEO6#uiv<_=5Y}$lFi4+ zjWdV;)d`U4h5bD_PP);uZ1K?xtgNh`o}eF=S9Du)oH=7+WF(NJb~-9#lksbpH`V$? zT~J*><`&VY#T0mbh&CoBCNMyHhK92_QNatqf^Y2 z3x((`ZHEr&$C~z%v+s1C zS5;S6JmdsOvuEu5&mxdIi~pktBu$c&pMgPqU?7fAld77U0s%;qY|XSU6L$a~6cq80 zBLV7YGy@)~Rmml<&1H{^AYVZKFDy6|?-PNNxW_DuwDdUJuKQw(GGKpyAI4nw=qs2$ zz(bC#rvUSeo1V`WN>^5XDB}le8yaq1FTE^}Q}@LXpR6e?>;x#W#y|o?eSH8t_-}z( z_2$mnY>sByb7`O5*ZO&IAD`RW08PJr{R%;vsCFi%hL4}WzproePiHd8N195s%sv~y zTwa!^ss7#MO@NcLrJv4fmvGwXytC^krsjwCWf{ym~M70@kHNnIT_$Z0H zlkZ^yg@uKgWqfPy{!nUa*Dd_;e44rU7KC_}VPseM zTj#rXSHO>epj}&C{gNgF@E_${fM~eb*ix%z{Dp$9lIv~j8yiSpheNx69RJr$6nH35 z7aFSS>A9Pw92LzY@O97hKdV4Ksm8S$4yB6qEcs_MxR)32%{&Hw8Wp9fqZ0${OPx_% zywaW|3|RE5&$Sq-2ssz>^MVfY&%oQKPoFNe>ktwZRXlND&*<%~-VFH=K-!wxTEl!J zZDZp>0K^}*X%T>EdpkR>hPwg5GrG$gzn@XBJ%17tbLGmF5{RRX4aMZAvhOVv^cI=r zJQfB79UUFjEaL>|GAbhG@+`twenkBLst6f-;y)@vzA{?S;yojz20n&P*slHQS=|8# zu_Qm$&dDv_qfduCe0;=5FRlMnnzh-~1JO}bTzuEf4G8>$Ur=HY>2WWRPpW86Sq-_n zckcpWq^72VIeZ3j13`G!E#u3VFGz(MDk>1Z!NI|+t1eV=M^;NUKQbjoWu*Q6S=g@3 z&ee`~zx>Rqh^z1@SEV>$Afgzz#h!wf)+U^ufyaPXK`_kTfrW+ptF`<~8Z5=1I!iNK zANNb@_eOr7zFIuBH?q~1P*`oXS$X66;BZQ6>I3N#ai{Mps;ZY60`az(>U4AU@(K#f z-rcdfefwNUbK_HA?BnbANOgr>2R)!9+`8;#sgTD514d7WQY8WIKY#wrEy`N>PBrbm zo12)ZDBUp|K9}(`S5o>gFt81l)ceGxQ+YmOLPA2DOJkaatm!*fw&`!6Kb75pT;b&4 zK(ENiNqvj7#l+aEaS*jACJ#2jfzl)rqcbB#5(%`Kd9n zaTVXrPvFqTQf2_t$6Y0e*<4xGvmNL3UcMq{E5zeNf-Wg3Sy)^IyGzY)4$~2JT*;CB z__93$3rB>H!#89pKnrvjUD8fiM{oXU6}64F4o?r5!rl;Q>cCNp0;Q}Ec;bjVP&#+#5`@`Y%w@44> z!+YFk&xS@s`0TE~%FUfaI#jl|*Dq{DwE^L;|Ky5 zMvIS^*NB(;v#;h8n50LK(C|?(|2H~MkIJlEksB}lMJY%7VX6LT^gVKMNJzZP$_i|o z9vU13j(nY$7ZMztc})c9_5AtsIy&HV&9Q5!qTQbNo4$u>Hsm{g z>3te%Y7I?Iu6620uEB=>_CqCxB|g?|yF*idvJdaygO9&`>sBO#c%*Y6C;o&X3KjkI z>3hSkTwp&eN^A)|4?vm0VEg{0?dn<&;jb-!;-AqgG(CmmWTRXj<;@kW5TW3{Zhd z+S>!^sawN&RjPBA4^#B&m8ymY$?)XE^f%X+SEsMS;E;sK&+)xi6&p_(EVQTe3?~?C z_aleDUQtrAyF7t|5s;Ef$uHh6L|qZM?&O42hxggNKc7a+#8m6CV!iIUx48)V*Fq9s zMC2*T;)XRFN)`qiqQ=nB(8$OLFw)t12|3HgZ%%}Qf9~q<_dDEw0Pa{(F{rT68Gg*( zp8Lv$XHTDsz$cT0*jQO*q^E;K#XJ6*J@qt;OL0-D*-Uf zXoB${9vCPx$}hJ02xE+m`aUvp{rdG+?;1~934^%=N`^pkaB$E_mBd4-XlS_Izpn?n zFgiN%;sc@AZgX9%_Z9ECxqa#A;9O&7PTStz2Kn-HZVrX&I>H=+Q_AXyhYztezKb65 z*qDz?O&uw+YUbeNWMX7=8m%Ej&CSo7fcl8%Gc7{SzIS01Ktee?^IuU>oOU3mrv44H zI6p7fbdfuP;59dJupd92~e?g&KCUR#+o0W#cw8qhQ~HDN}vQ3eGjZ+#Cu1qB6p54}4$ zM6S|0)>L4)`0A35&ifu6Y`wkRA9?x`JxaiB!Kj27Z@aJ|N%#ivv6$2Mcg|yViHWpA zd*F$|pMW{#r9OEbCo5yeeeLB(&iy-;*R-{}Gc(x)1&hHUhlYp4q=8)p8bD4`etn_3 zva<45f3N1LDO*m?m-+d;W@cvSjFgmN&?zwbB#aUQR!z81(+D0C9}zBQN#eB0`|G@u zMJnQ#gPcQK85<`B1R&GNiUB1C2%jsbuTSL`!q-4-j!xMD658B!LtB}eri6uEK`Ioe zwF9>p6q;WGTmt7B91TZjn0bLieG-g=`d6ONIOf3P(pZT z{NTj1ix0jwH~#?0HzH&OD;ypf8BFFP!T5BXTT&8fNBgIS4T$UP8)*AOKK~;MJ{+D+ za-1$96w21tw*C1f2DwLe{3z|sJzrp}x}@!eEq|9fPaZ9`)g!=rh#4Lsp;Z_l0FKV* zmng}}8x5PQk-|kyO>!_Ia4!!$Jx>r4l3$TS#VqXl1h0TNdG+cQ6&2Owk z((G>U>}>c-giAm`LqqfN{rgAZ;hibsNa+zwFEBvDc{3gk4qIpEr~(C~k6p6;{zktA zutVK_fRfx*QE4Gs6F!{zO#&rwDpjt(kiCO1=5x6+nIFevN$>git@WM^z7pd{5`r8T z;&?y1xM-%YA9N;ZWqgE;ntHU#_4eh6}XdnjHl9VhTy%005hy7kj1 z6%`dggzr_ZC-Y=r`lF+x-@SY1yCGyT^q_H+|{%w0ogXXld zw9KS5x=WX8!BSx{a7}J8 zl8f%YuW4#(IyoVgnHZUv&JHP0b7?#qHw_-)0)Exf(?iPSNGXj9_~dG}+bp9X)Tg#YUYtaYE~g9w0UW>1jQEeNl07i%OT4u`y=3f$!fzUY%bVMHl2}mWSq%JUifk!4L zA_5+_sPVu;K=ull_^rlM4|dmY!mLOX6BY zgdKp+|M1}h@FzA3xU1;0X4=^Lq$Jw{PBLJ?SA1(=atP1-37N*BHs2LnWLs zHTq=!_5@#-%MD$(kdn9pv_$0O)QeTC5 zH8eyT`qsofU^e_w`b+nMY4j2Nt*WXje0+TSVZ>P@9mM-&EiG9*Ws%YhmI6vqr}@sG zhcA$7UG^5TLpvEJ^2^PnGRr)8WS-#<3s@V(W80;z%2q}vHBFlAbTHO2eqn6bKDX$| zhGtzV8N{6+9D2LDXvLivP1*tqgO5&Jt9I*XY;64W=~1gKJ^_Kdn;S(H@WW|jnKWBM zT%0CmNr+`VKFk0cX^_@sf{zrZu|?kM5#cv~`SSa!l$`upD>((lt|txESLD5&v6`CN zix)5I%4kGH(g;0+|CGF$sZT8wcNP3oV6$U(>KqdpQAYe_UESEUw6w6Wu&OFg1qB5| zLmJmT9DE8@p7FORgE!Y+Wn>`7FMs|#E1@ZS?;a?DQn2`8ROgD2lC$*3RcW%Qe)@Ab z`ljv7Z!L{EgE+CXqdt8)ax##HoGhBu&$2eu&^$d??Q+W@qz%yh)3~^|Z{PauEs6{6 zJ$n6`=jP3yxw*N%8`+>Y!@^Ebu*jZUtF5UK2*om&V2q52i1457x|5F07!(wgosIku zAdP8-6IB=9wmndap1QianOW*_9m25oh(AZ5L4v!wZmh4b`))|VmV_;Q zR8>Rs^B0CIoLMpVX1{=IJjX#n&e9elQ#8t<_vaD8c}fr280hMh>gw7fl?t;v)&gcs%h0g1t?k#s zf`h$1t(b$6re-ygN!c4Y?NV&390peGDa z?BLews*sS7j+WM)yLUsw!UD(u_`kHYD9Xt-0dcpq;5ll74A(X==jdH{7|X6c%O0>{Onw*#6pU^e{rSCrQ! z#l-sB+uM73kexq0UTZLRFzAdVIn~u(tudUCVvMrRCyF}v49}g*d+~xpZjY=97yvmh z1%!x=kBf04BSG5%O@oB9vH1Z+nb~AmXbvD_R_m$X;4dpH{D1%#JK6ZS$Aj4bwF7?r@4rQvQ%GSkVTk+m66Y%gE_`t?guL1F&aFL9^u z+mkKfR};>6q)Le&_X2&Fovoy*dX|$@5z?;FGJU-ktOH=|moHy{Dc+wThZ#-aw|Fk; z%9G)vHw#uzg*w*)EclzEqUG)^WtcSk83TU?%rl9**1PLJZT-|$RR@c#0z*QSZ{6Z4 zLE7W=^yoq43*Y$iB0HO&7P;Vy-JP8R^IAz!Q7YqMAo!P86Q-u8k+q%GG;o`>z6bQJ z!~jIZ_cj0$K@0u<{Trf!PS6@RwpH!wRV1Pu9BTZIq+h%J{$2@>bluKQ`oXF##BYxm zWeXQP11~R8OHO_5*#YUzevo7^NFcc>h6)P{$10rD{6p~2LgLR-Qz2mM_kK&MxrVk) z+ugXq#leBdt57yT)H|Sla7r~_Cc&WW?(P!dvr9;L>~F7NFRUps#1)!VBbCRyGUP)@ znAq-T)zn;5R=xo<&P#ocg(V$ep|B7eN%h3SyR!Z)Jwiq`9>tFz6PdT6Rvn)DlV!g6 zT@%De!gbt_p{cR)VV5+UwDcj2@qw!-J9~3)Z(N5RQViPkgzOwXtCZWqHYmpV-n@F1 zXT3c=o4-f)I>g5YhK7*(NLQ|8uKN4?18hPHIE_@j1z$T=4i?|^K{VSaK&1@)`B|ECKl>Xc|`C6aq;nI%Ifd`{F>%>nB=Zc zK<6Qj9N4M%O@%8VVGB%gW|L~{87x$yTK0<we?j9gK1v2nQrU2ka^poYb#ehC&@7e1Wh zC7$(-jqcj<8(l)_Y_I$!JlE&I?NCrs5?+5OO$s*}#ViB%4%ln_D(T};G}%n^(!G3n zYR8(@rs#9JB4T1NX-d#6dtIkVQ|M zC&ov#w6*CjxV)&YmO?cQ5AQA2A03u)u|WXPOoR6G&*&2}Dzoo?M9%KJGfjiFslB6h zlTPcYp2WSGcJR1J7db-0P<~p+r+RPSyg4r>M%__I7KR>QoAC1TLVA+De2Ir*k(I+| zMxL*WN4Ko3%)`s8@LHwI>QrkkNyY)7a@oH1muDA1HQ3@{*D!!Y^jMoAMy1!*9(;Xy z72IF1LT3tSK~Q2qc%9EKtbxn{EsH}yQe?zi5z}m&B?T51f_XsavK%>9llOLUaq)-a3!9pXLW!ZUMpip1AnX7LJJX|cK*{XC9{xsYG2?+@|p-ct?ghhFIIj|GBXnu=2%)!L%E}`wuBgkvC zy3?rCSJ8jf@cZ(wx_vkehSkCUYH)H-j`Z(};#hxG6z?#UVxg70%YHuL_Kh1kfE91v zoTjJWUHPFrzj; z!{cv9f^=}!KOnHOvJzT3t)eb?@?k;@o8GfbIu4}MduKSr;S#>gsQuRFCU`|r5s`Em zRaI3g8XCWwA8*>%In}M(5nu;veSg$89Um8W8SUliiH(C(;V>vSBCVL4J41G&UF(#1 z)9_f4RrB}Cd#uRYb(jOt^_b1G0sYm->7^)KR=&N*bas2Qj+!-CK%MUMQRPIt4B0XkR8Tl zT2pg8iD^2g(M|NcHI^%jsl3pl9;td_WyQ)f8{wv@NqXEvU~Ul-a=ZK|=v1&eZox>O zLJ^U&yu5Re^A|2uR#dqE_z=O(4D%XTS9iEJ+XazM2{ls;js6tzAblpJ}-z!DNbR9|lCIV3L}!u&|7bjNa<%^i{B+)Zsv|!A`$S zO-yDwQa;)WsjI1hPJHj>aqZf7z=fco(0Y>X*jw$1f)F~*!Nim_G! z-n_}Z38`aSIyl>zHdgJ<@7Z0b8yta2oi6hIVy z7tPAb%Jb*XA>L5Hizi@|g@sGOBLvjx1$lUtLNFa3?12x1qz0QnfC3i)cGkngqsS;9 z^hoBl9zj7taOW|xvCWY!;;~(-H6JK20xT>n7cbTn6$yY7dO2WPY8QdQC;(^zmSn3X z1u%_%`-YUGyKrv?JvS*$Rf>A@^i;;=sg5okBO{PsCqd+t*uyYpUW}W&%L-6H*IZYI z^MWjl!Pvya)5BxDCBlPQP9Ck9CS8!38Nf+_kAl?6sja=l%ew&V54`7p?Ylkd&EyD+ zUdKbSHzsevOouNSyQEDjdF-{ewnE~oaC9{`S}hC|V>TfaXwF}IG&7Hvug!v-)&##{ zPmC4V$j#4hsHf+>yAF6!osq#B6Us)!&VTKE#c_X3zzY@#0Tz~VP{GVHzG|wftsNb4 z!2MfWGIz#NDIH(HA%=!dq(*?n6p-RKw|NCa3hw?}wmJ?9z5}zDehcDG#mV3B&fMp? zbCB4%k^bi!()2u9c#}I-_4InO)l*))e7W^|JE-rsA3}CvEQBzozt<7F=ct5LI+EncN;uU{}PmXN)g!19dt` znWeAk>aGFP%$-i?7vyldf3WK+beCOj544&I=&(nR9#vIIhPPbN)HKxBZy6>fBD&~z zSW{c;gP9#!1$aQ}Ayo3lvuJ`N6!=w6TVuek)6>&PS2D{+>tYa5D;*q+WaA&%Fj zV0Q7`1rJ{Y99am4&#X}*wJJ^@zN}5p*y)_O?QM$+*884YRYl+0ax?r56@za$A1;{{8U>tc3Gs^M+Z^rG4lrC}I*5 zAB~7792;FM6wkSH$kN=D_ot>$At50I6mh<*Q-mnl<2mM&kpb2rJnm_4X<207oe2Sz znaNhxmr+!trJ+GGrY5)N5y1&A7XT82!9~deK-|1}_Vwnlb3N;Y&tMobZO-xVl$4g@ z;Nak;Md+O>wcpaqezl@J!y1tA&mnmgtrUq=2}S(;Gn0{Cq}Q+JUYvREXYp zw2nbXW82O#brk03uP-kP2nclb_eVuUaF+UQFIy=qe@qg-p`;9kUo@;;+FY6I&k`6V zf#>GJAb>GIo4%f2+1s~U3xo0l>b9H68LJ;ZZ0zjpZr$=+91_(-_5qxUy$QDT)Ty4) z(MWxzC`DY6ShAWAI@;P#AR|C=goYAIQi7iZ8*tkexiDuxBTiRk=?dx;RVhp8(^KYm z=j$<=uX!+wLgRtrL)dO~L>ceMi97u8{i($>{}lAiXo>iX{!!bv`v2a|r15VtAcKS5 z^nKyr%C_J1XDU|K4DgI7)U8{$u3ftZLsL^zgUc9DsFW+^pHo!S1%3*i?&{T(SMNsk z<2BrP-TC=*(-pY8@87?76@yzxs$J;lG#RACULTs}l$JKv*LU4so+v3PK~_=i0T97Z zNlHor_PPK5PR>|1K5jX>zcV;E=y$NuAH9AqsRo-FCte1HdM4%myEo6Uh7(97gp~Qi z=ov1q(m{u_XI}*bU^ixe%Ixsc*$C&n8qavqgUsSIK)z*TfF?PyT;%CXx4@t|I!0_( z`d^--AJ2*ivCfHY%xjXZUBV9p(tG)m^Ygu+`vfpY5sx1m6q-i}g=J@FTc4nZn?#mw zQR&&)!5wy2RaCq+tg!3urLcWk)Xq|hpcTZf1v&}-@724u>EENZUQ?f*fM@`XIx#W9 ztw}=%X2rn307S=}qrN^Qbi%V|&misH1R;99px$tR)pm1nku&}jj9YhdsIdO<%JnFx zYuBDVeR}GIp{*?kO9Ba5CSq;>{8>j=S3Z2I`^YwFlko1n zd+>A(qmlHYCkkveR8*ot1ze3HWo_^5biaRpif<6?4&Y{pZ7nxU34h=d8Gka3=NIW5 zgQpyy#KlpKQZ~l7W_Gy49Khu6?s|IfJYiR6V`rC96hRA$i~B)RJGc6~5-)dukbn8D zl||2Lu5<}MG%Jh!OxnXm^xWKBqUdb{BO_YOGK`)F9x)~|^2_Y0Gb|S?&H~;xSI16+ z<%A(b&V7)9I|dp7^(f3MqHMi?;^}Ysqm-ToZg`%TN0<$`? z)hFYQBFmNK5+;mRz@Q zzOkb_q@X{>#pFHf=6z@G8PX} z{*ZS@aDkdKHhwZ9MDdwB!YqNQaWT zW-y&~v0-fR%;31YyPt?}Gyw`hYA-G>B5yTF81I0|1Tuu2Q#U7(K zwV4bWOwwjsTU+Y0XZZyM#=Lz&CuySJzI!JD)P3?~ID8ON9!M$0I!70`ut`=00yDg& z26^sEFs}j#2l}vsHFRz(0)HMa!Eko&QRG+ z5IX}4W;!}wF@%($ULipi7Z%W7vCH2-7-oG!swBHDnsBrWx-A$zm82B3e*XyK-9}Xi zeZhNMfC7bs>gns7nVQPCs5e(ouzmlC+{jKqUcPyBbaa1zzmb4XSoj;@$mh?uzQ4O` zpV`*mFD@kHGSi-vcm<6buU@JX77=+SaW@l4wDR68n%^GfpPWojN=oYLx{>C)8(Kw* zk#{ z+_L-K^GerS7#CyevC{h?ikbiH*`Ggu4u1cxCKmtd&6~b&-x$OkjP&$Qjin(D#c3q0 zcJa@u-7qK88Ei@z(*?rqV0S|doHsQ!0STi&nG?hk*y-QDf2*Cj*BZl#lfo+DGW7_2 zpx8^oQO$Dmp)p$%t4N1sk`ZDBYkml z;nN||K*_#2ei2S5?!-7q)aakp-PZ^BytV#Q7d^2x=GS?9tf9ew>3lpt7jpV4Gb>Ab zDSdGj0{6?8FWkh)LMy4vzAUw)G+HWE5<_=td-qLE4Pz~`i#Lqw91G^0;Txn#Eru+j z?AGnutZ#KsU6zpd9}No)t@T(zO1^;1|F%ugjwO*!hb=BHzJ9=S_N=y{;nL5a56R5y zyp84LCU@3mKUtNGPDxeZ-IqLFM;8DPzS6;9C5#Knp>}3%yfM%=d;ZriHZ%RNT|2$TFgr?8!&>vCzW3A6r_iti?bvdxKE%^xTEm5O*BX)6()6T1=C;I|=#p z^5sk0EnC~7K?im94zS>6Rrf>Pw>yc*Uruks2w0v zn5C494@&%#al$`@)9{}l7TYCU>h}7Ey_)AwUeERh1{QNC& zl42=7i$ib4okz7Qf|u4aIREpVB;U8zPoHFkw9lVE511_1%l$mlryQ@gtGoN`5dkrA z#AUI@mKHpuM-3kv8z`!WCt&!WoC@WQ7s1twVV(H{{teDfPjFMGzxI=36qho zZdPvYBc?+bBv3OqzhzTVQx6Rc@S2tr<-L0G;(boK81kwPDK|t-{lTuZztG}nqM1N1 z(w7B<1Q-`Apbomay1L29NuWePJ8Yt=%E}By!z)*=U`*^$C=j=he(=5PZSm^BrJO2w z9A8=GzpBwcK4KtiI7&-lqC8bpR0Q~mW1PJUp98!~Lqh`*bEEUQqJn~DtV$r(Pm=d7 zErf5f-@I{hc8=o*od^NXr`>)nM?DX|b6#G$iYuzxoQeG@rvP5D^hgQ4LK586Nr@ zia#_Y!rqU~w77ivvbuUi1wE$d%^MQaN?{dTqR^u4HAT|~)s4dguM*Mc*bOc`v7Cmd zZAF$x6v!_$1i#YF0oBAokL4bGzB#?aBJ3~^!MAF0DAqy+M^^yB+??!3D*fsI*) z^o=@wsie3V3svL2^Yzmwd&oJUJKMZ`!fDcFYckC036wuf`1R}89Vi|VNjqy3ekSTL z1$S+sug}>)B0Yqy@fuM^`)i#CVWn|#;10>FI?0NHEgQN8goIuf7Ap5oo}@Xyes!nl z#R~-ujq?%`9>6w*7WMcjwPzB@{%CvaaZoYb%0gCUukP>q2L>-ygT>`OZdrkYDoT5B zj< zAigV_nw6FHt)~YQ;q~X;?mZV5M2FGU7`~qEOcPF08@2J<{mIohT!%uzm@h0YI^Mb^ z=L~5L0siglR}=~?aE)oE$6Yr!$U7j-!{rHiB_(`=(OK22pVnqOFEEmz#$i@K6AcXw z`CpU79aBqg#8!1F-4dUW*?d<~TbtTw`S|oD6OiDImgyFvk4)wL5#NKltJ>Z9{1Q^O z6f`IJ0w)8O(DNv1T_2=Q#}jrin?*6tpFf8XOi4}#I=p!FOLGuo2mn2cj{s zac*G&bMZEMcM4bskZ^_%>|YVGf?O&u4H64vEiE`BI=WPeyV$*iCr=6s30VszNlQ!H zX9%%+uM*f=lX>jmpsg-nZiGKtoKtCQYiF07oGd9Ju`pagdhXeUd)Xifva)`BjAGU% zG~xbYUHp5jUeoT1Y}tc;vO5yb1Z_SbTV1egkfV8K*RJX5>8-D?gU!>Lj^)ynyl_E1 zNeHhXgiXq=q5GZhK~+*x(vv4o3JZ}=0mZA*{bUP+r5`_iLKpNjQ$Jb;N=dMP#nQWLP9O*q5)8Gpx|)Jcc9&;Cz(Asacj-uzvC!5Ae@m_- zt;pIC1DWb=n)}H!cIo?>yx