|
@@ -0,0 +1,309 @@
|
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
|
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
|
|
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
|
|
+<!ENTITY mdash "—" >
|
|
|
+]>
|
|
|
+
|
|
|
+<chapter id="classify">
|
|
|
+ <title>Client Classification</title>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <title>Client Classification Overview</title>
|
|
|
+ <para>
|
|
|
+ In certain cases it is useful to differentiate between different
|
|
|
+ types of clients and treat them differently. There are many reasons
|
|
|
+ why one might want to treat clients different some common reasons
|
|
|
+ include:
|
|
|
+ <itemizedlist>
|
|
|
+ <listitem><para>
|
|
|
+ The clients represent different pieces of topology, for example a cable
|
|
|
+ modem vs the clients behind that modem.
|
|
|
+ </para></listitem>
|
|
|
+ <listitem><para>
|
|
|
+ The clients have different behavior, for example a smart phone vs a lapttop
|
|
|
+ vs a desktop.
|
|
|
+ </para></listitem>
|
|
|
+ <listitem><para>
|
|
|
+ The clients require different values for some options, for example a docsis3.0
|
|
|
+ cable modem vs a docsis2.0 cable modem.
|
|
|
+ </para></listitem>
|
|
|
+ </itemizedlist>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ It is envisaged that client classification will be used for changing the
|
|
|
+ behavior of almost any part of the DHCP message processing, including assigning
|
|
|
+ leases from different pools, assigning different options (or different values of
|
|
|
+ the same options) etc. For now, there are only two mechanisms that take
|
|
|
+ advantage of client classification: subnet selection and assigning different
|
|
|
+ options. For cable modems there are specific options for use with the TFTP
|
|
|
+ server address and the boot file field.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The process of doing classification is conducted in three steps. The first step
|
|
|
+ is to assess an incoming packet and assign it to zero or more classes. The
|
|
|
+ second step is to choose a subnet, possibly based on the class information.
|
|
|
+ The third step is to assign options again possibly based on the class
|
|
|
+ information.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Options will be included from all of the assigned classes. In the case two
|
|
|
+ or more classes include an option the value from the first class will be used.
|
|
|
+ Similarly if two or more classes are associated with a subnet the first subnet
|
|
|
+ will be used. In the future the processing order of the various classes may
|
|
|
+ be specified but for now it is being left unspecified and may change in
|
|
|
+ future releases.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ There are two methods of doing classification. The first is automatic and relies
|
|
|
+ on examining the values in the vendor class options. Information from these
|
|
|
+ options is extracted and a class name is constructed from it and added to
|
|
|
+ the class list for the packet. The second allows you to specify an expression
|
|
|
+ that is evaluated for each packet. If the result is true the packet is
|
|
|
+ a member of the class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ The power of the expressions in the classification step is deliberately
|
|
|
+ limited in order to minimize the amount of time required to process each
|
|
|
+ expression. The expression for each class must be executed on each packet,
|
|
|
+ if they are overly complex or time consuming they may impact the performance
|
|
|
+ of the server. If you require complex or time consuming expressions you
|
|
|
+ should write a hook to perform the necessary work.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+
|
|
|
+ <note>
|
|
|
+ <para>
|
|
|
+ Care should be taken with client classification as it is easy for
|
|
|
+ clients that do not meet class criteria to be denied any service altogether.
|
|
|
+ </para>
|
|
|
+ </note>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section id="classification-using-vendor">
|
|
|
+ <title>Using Vendor Class Information In Classification</title>
|
|
|
+ <para>
|
|
|
+ The server checks whether an incoming DHCPv4 packet includes
|
|
|
+ the vendor class identifier option (60) or an incoming DHCPv6 packet
|
|
|
+ includes the vendor class option (16). If it does, the content of that
|
|
|
+ option is prepended with "VENDOR_CLASS_" then it is interpreted
|
|
|
+ as a class. For example, modern cable modems will send this option with
|
|
|
+ value "docsis3.0" and as a result the packet will belong to
|
|
|
+ class "VENDOR_CLASS_docsis3.0".
|
|
|
+ </para>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section id="classification-using-expressions">
|
|
|
+ <title>Using Expressions In Classification</title>
|
|
|
+ <para>
|
|
|
+ The expression portion of classification contains operators and values.
|
|
|
+ Values are currently strings and operators take a string or strings and
|
|
|
+ return another string. When all the operations have completed
|
|
|
+ the result should be a value of "true" or "false".
|
|
|
+ The packet belongs to
|
|
|
+ the class (and the class name is added to the list of classes) if the result
|
|
|
+ is "true". Expressions are written in standard format and can be nested.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Expressions are pre-processed during the parsing of the configuration file
|
|
|
+ and converted to an internal representation. This allows certain types of
|
|
|
+ errors (such as incorrect syntax) to be caught and logged. Other errors
|
|
|
+ (for example mistakes when setting up the values for a substring) won't be
|
|
|
+ caught and may affect the classification. In general if an expression has
|
|
|
+ a problem a log message will be emitted at the debug level and the result
|
|
|
+ will be an empty string.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The expressions are a work in progress and the supported operators and
|
|
|
+ values are limited. The expectation is that additional operators and values
|
|
|
+ will be added over time, however it is expected the basic mechanisms will
|
|
|
+ remain the same.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <table frame="all" id="classification-values-list">
|
|
|
+ <title>List of Classification Values</title>
|
|
|
+ <tgroup cols='3'>
|
|
|
+ <colspec colname='name' />
|
|
|
+ <colspec colname='example' />
|
|
|
+ <colspec colname='description' />
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Name</entry>
|
|
|
+ <entry>Example</entry>
|
|
|
+ <entry>Description</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+<row><entry>String</entry><entry>'example'</entry><entry>A string</entry></row>
|
|
|
+<row><entry>Hex String</entry><entry>'0XABCD'</entry><entry>A hexadecimal string</entry></row>
|
|
|
+<row><entry>Option</entry><entry>option[code]</entry><entry>The value of the option with code "code" from the packet</entry></row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Hex Strings are converted into a string as expected. The starting "0X" or
|
|
|
+ "0x" is removed and if the string is an odd number of characters a
|
|
|
+ "0" is prepended to it.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ Option extracts the value of the given option from the incoming packet. If the
|
|
|
+ packet doesn't contain the option it returns an empty string.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <table frame="all" id="classification-expressions-list">
|
|
|
+ <title>List of Classification Expressions</title>
|
|
|
+ <tgroup cols='3'>
|
|
|
+ <colspec colname='name' />
|
|
|
+ <colspec colname='example' />
|
|
|
+ <colspec colname='description' />
|
|
|
+ <thead>
|
|
|
+ <row>
|
|
|
+ <entry>Name</entry>
|
|
|
+ <entry>Example</entry>
|
|
|
+ <entry>Description</entry>
|
|
|
+ </row>
|
|
|
+ </thead>
|
|
|
+ <tbody>
|
|
|
+<row><entry>Equal</entry> <entry>'foo' == 'bar'</entry><entry>Compare the two values and return "true" or "false"</entry></row>
|
|
|
+<row><entry>Substring</entry><entry>substring('foobar',0,3)</entry><entry>Return the requested substring</entry></row>
|
|
|
+ </tbody>
|
|
|
+ </tgroup>
|
|
|
+ </table>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The substring operator substring(value, start, length) accepts both positive and
|
|
|
+ negative values for the starting position and the length. For start a value of
|
|
|
+ 0 is the first byte in the string while -1 is the last byte. If the starting
|
|
|
+ point is outside of the original string an empty string is returned. Length
|
|
|
+ is the number of bytes to extract. A negative number means to count towards
|
|
|
+ the beginning of the string but doesn't include the byte pointed to by start.
|
|
|
+ The special value "all" means to return all bytes from start to the end of the
|
|
|
+ string. If length is longer than the remaining portion of the string then
|
|
|
+ the entire remaining portion is returned.
|
|
|
+ </para>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section id="classification-configuring">
|
|
|
+ <title>Configuring Classes</title>
|
|
|
+ <para>
|
|
|
+ A class contains three items: a name, a test expression and option data.
|
|
|
+ The name must exist and must be unique amongst all classes. The test
|
|
|
+ expression and option data are optional.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The test expression is a string containing the logical expression used to
|
|
|
+ determine membership in the class. The entire expression is in double
|
|
|
+ quotes.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ The option data is a list which defines any options that should be assigned
|
|
|
+ to members of this class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ <screen>
|
|
|
+"Dhcp4": {
|
|
|
+ "subnet4": [
|
|
|
+ {
|
|
|
+ "subnet": "192.0.2.0/24",
|
|
|
+ "pools": [ { "pool": "192.0.2.10 - 192.0.2.20" } ],
|
|
|
+ "client-class": "Client_foo"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "client-class": [
|
|
|
+<userinput>
|
|
|
+ {
|
|
|
+ "name": "Client_foo",
|
|
|
+ "test": "substring(option[61],0,3) == 'foo'",
|
|
|
+ "option-data": [
|
|
|
+ {
|
|
|
+ "name": "doamin-name-servers",
|
|
|
+ "code": 6,
|
|
|
+ "space": "dhcp4",
|
|
|
+ "csv-format": true,
|
|
|
+ "data": "192.0.2.1, 192.0.2.2"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+</userinput>
|
|
|
+ ...
|
|
|
+}</screen>
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ In this example the class named "Client_foo" is defined. It is comprised
|
|
|
+ of all clients who's client ids (option 61) start with the string "foo".
|
|
|
+ They will be given an address from 192.0.2.10 to 192.0.2.20 and 192.0.2.1
|
|
|
+ and 192.0.2.2 as their domain name servers.
|
|
|
+ </para>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section id="classification-subnets">
|
|
|
+ <title>Configuring Subnets With Class Information</title>
|
|
|
+ <para>
|
|
|
+ In certain cases it beneficial to restrict access to certain subnets
|
|
|
+ only to clients that belong to a given subnet. For details on client
|
|
|
+ classes, see <xref linkend="classification-using-vendor"/> and
|
|
|
+ <xref linkend="classification-using-expressions"/>
|
|
|
+ Let's assume that the server is connected to a network segment that uses
|
|
|
+ the 192.0.2.0/24 prefix. The Administrator of that network has decided
|
|
|
+ that addresses from range 192.0.2.10 to 192.0.2.20 are going to be
|
|
|
+ managed by the DHCP4 server. Only clients belonging to client class
|
|
|
+ example_class are allowed to use this subnet. Such a
|
|
|
+ configuration can be achieved in the following way:
|
|
|
+ <screen>
|
|
|
+"Dhcp4": {
|
|
|
+ "subnet4": [
|
|
|
+ {
|
|
|
+ <userinput>"subnet": "192.0.2.0/24",
|
|
|
+ "pools": [ { "pool": "192.0.2.10 - 192.0.2.20" } ],
|
|
|
+ "client-class": "example_class"</userinput>
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ ...
|
|
|
+}</screen>
|
|
|
+ </para>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <title>Using Classes</title>
|
|
|
+ <para>
|
|
|
+ Currently classes can be used for two functions. They can supply options
|
|
|
+ to the members class and they can choose a subnet for the members of the class.
|
|
|
+ </para>
|
|
|
+
|
|
|
+ <para>
|
|
|
+ When supplying options class options defined as part of the class definition
|
|
|
+ are considred "class globals". They will override any global options that
|
|
|
+ may be defined and in turn will be overridden by any options defined for an
|
|
|
+ individual subnet.
|
|
|
+ </para>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <title>Classes and Hooks</title>
|
|
|
+ <para>
|
|
|
+ You may use a hook to classify your packets. This may be useful if the
|
|
|
+ expression would either be complex or time consuming and be easier or
|
|
|
+ better to write as code. Once the hook has added the proper class name
|
|
|
+ to the packet the rest of the classification system will work as normal
|
|
|
+ in choosing a subnet and selecting options.
|
|
|
+ </para>
|
|
|
+ </section>
|
|
|
+
|
|
|
+</chapter>
|