Simplified BOOTP/DHCP/PXE/TFTP server
Project description
Overview
PyBootd is a daemon supporting a subset of the BOOTP, DHCP, PXE and TFTP protocols, with some handy extensions.
One of its main goals is to provide a simple solution to boot up any PXE-enabled personal computer, with no other tool required but a standard Python installation.
Pybootd can be used for any network boot up, or to install an OS without any physical support such as a USB key or a CD/DVD.
Requirements
Python
Permissions
DHCP protocol requires the daemon to listen on port 67.
TFTP protocol requires the daemon to listen on port 69.
As these ports are within the server’s range (<1024), the superuser privileges are required on Unix hosts (Linux, Mac OS X, …) to start up these daemons.
Status
This project is in beta development stage.
Supported features
Access control:
None (any remote host can be served)
MAC address ACL
UUID based ACL - requires PXE protocol
HTTP forwarding - authorization is delegated to a remote server using simple HTTP GET requests
Local or remote file serving:
For example, it is possible to boot up a full Debian system directly from the Internet, without storing any file on the pybootd host machine
Network notification of client requests through UDP messages
File name translation
Files requested from TFTP clients can be filtered and transformed into local filenames using filters
It is possible to use pybootd with only one of the services, either TFTP or DHCP
FAQ
Common errors
- pybootd.pxed.BootpError: Unable to detect network configuration
This error is often triggered when the pool_start address is not part of a valid network. Double check the network configuration and fix up the [bootp] section so that it matches the actual network.
Configuration
pybootd has a few option switches. The server offers two services: bootp (which supports Dhcp and PXE extensions) and tftp. It is possible to disable either services.
- Usage: pybootd.py [options]
PXE boot up server, a tiny BOOTP/DHCP/TFTP server
- Options:
- -h, --help
show this help message and exit
- -c CONFIG, --config=CONFIG
configuration file
- -p, --pxe
enable BOOTP/DHCP/PXE server only
- -t, --tftp
enable TFTP server only
pybootd daemon uses a configuration file, in .ini format, for all other options.
Some options accept a boolean value. The following values are recognized:
true values: on, true, enable, enabled, yes, high, ok, 1
false values: off, false, disable, disabled, no, low, ko, 0
The BOOTP daemon associates each MAC address to an assigned IP address. As long as the BOOTP daemon is running, the same IP address is always assigned to the same client. The address never gets back to the pool, i.e. it cannot be re-assigned to another machine even when the lease expires.
This is especially useful for a full network-based installation, where each client requests at least an IP address twice:
when BIOS kicks off, its PXE ROM code requests an IP address, then requests an executable to run,
when the executable runs, it usually boots up an OS (Linux, …), which in turn requests an IP address to resume the installation.
[logger] section
- type
The type of logger, if any. stderr, file, syslog or none.
- level
The level of logger verbosity. critical, error, info or debug.
- file
The path to the output log file, if type is set to file.
[bootp] section
- access
Type of access control list. If this option is not defined, all BOOTP requests are served, as long as the defined pool is not exhausted. It can be one among the following options:
mac: incoming BOOTP requests are filtered out based on the MAC address of the requester.
uuid: incoming PXE requests are filtered out based on the UUID of the request. UUIDs are not emitted from simple BOOTP or DHCP clients, so this option is only meaningful for PXE-enabled clients.
http: incoming requests are forwarded to another host, through simple HTTP GET requests. The MAC address and the UUID if it exists, are sent to the HTTP server which replies to grant or deny access to the requester.
A section named after the selected option should exist to define the access list.
- address
Specifies the network to listen to requesters for receiving incoming BOOTP requests. On most hosts, the only valid address is 0.0.0.0. Some hosts accept subnetworks (such as 192.168.1.0). It is recommended not to define this option, and use an ACL to reject clients. Hosts will multiple network interfaces, it might not be possible to listen to single network. Implementing such as feature would require to use RAW sockets, which falls out of scope for this simple server.
- allow_simple_dhcp
The default behaviour is to expect PXE requests. In order to serve simple BOOTP or DHCP requests, this option should be enabled. This option accepts a boolean value.
- boot_file
Boot filename to send back to the BOOTP client, which usually requests such a file over TFTP to boot up after it has been assigned a network address.
- domain
Domain part of the client FQDN, that is the network’s domain name.
- dns
IP address of the DNS server. The server only accepts a single address.
- lease_time
Validity in seconds of a DHCP lease. Please note that the BOOTP daemon does not manage lease expiration; this value has therefore little meaning.
- pool_start
First address to allocate for a BOOT client.
- pool_count
The maximum number of clients that can be served.
- notify
When defined, the IP address and port (using a column separator: a.b.c.d:p) to which a UDP notification message should be sent whenever a client requests an IP address to the BOOTP daemon.
- port
Alternative port for incoming BOOTP requests.
- timeout
Timeout in seconds for a response from a remote authentication host to be received, when ACL is enabled and set to use the HTTP protocol. If no answer is received from the remote host, the BOOTP daemon ignores the incoming BOOTP/DHCP request.
- servername
Name of the BOOTP server.
[mac] section
The [mac] section contains one entry for each MAC address to allow or block. The value for each entry is a boolean, i.e.:
AA-BB-CC-DD-EE-FF = enable
[uuid] section
The [uuid] section contains one entry for each UUID to allow or block. The value for each entry is a boolean, i.e.:
xxxxxxxx-aaaa-bbbb-cccc-yyyyyyyyyyyy = enable
[http] section
- location
The URL prefix to contact the remote server for boot permission.
- pxe
The path to append to the URL prefix when the requester emits PXE information. A regular PC with PXE capability emits a PXE boot request when the BIOS kicks off. The remote HTTP server may therefore identify a BIOS boot sequence upon receiving this kind of request from the pybootd daemon.
- dhcp
The path to append to the URL prefix when the requester emits simple DHCP information. A regular OS emits a simple DHCP request at start up. The remote HTTP server may therefore identify an OS boot sequence upon receiving this kind of request from the pybootd daemon.
The pxe/dhcp option pair enables the remote HTTP server to identify the boot phase: either a BIOS initialization or an OS boot sequence. When such differentiation is useless, both options may refer to the same path.
[tftp] section
- address
Address to listen to incoming TFTP requests. When the BOOTP daemon is enabled this option is better omitted, as the address is automatically received from the BOOTP daemon.
- blocksize
Size of each exchanged data block. It is recommended to leave the default value, as some clients may not accept other values.
- port
Alternative port for incoming TFTP request.
- timeout
Timeout in seconds for an acknowledgment from the TFTP client to be received. If the timeout expires the TFTP server retransmits the last packet. It can be expressed as a real value.
- root
Base directory for the TFTP service. This path is automatically prepended to the pathname issued from the TFTP client. It can either be:
a relative path to the daemon directory, when the root option starts with ./,
an absolute path, when the root option starts with /,
a URL prefix, to access remote files.
[filters] section
The filters section allows on-the-fly pathnames transformation. When a TFTP client requests some specific filenames, the tftp server can translate them to other ones.
This option is useful to serve the very same configuration file (‘’e.g.’’ pxelinux.cfg) whatever the remote client, thus speeding up the boot process. This option also enables to access files that are not stored within the currently configured path (see the root option).
Each option of the filters section represents a file pattern to match. It accepts standard wildcard characters: * and ?. The option’s value defines the translated path.
The value part can contain variables. Variables are written with enclosing braces, such as {varname}.
For now, the only supported variable is filename, which is replaced with the actual requested filename.
The value part can also contain a special marker, that tells the tftp daemon to read the replacement pattern from a file. This special marker should be written with enclosing brackets, such as [file].
Examples
The following filter:
pxelinux.cfg/* = pybootd/etc/pxe.cfg
tells the tftp server that all client requests matching the pxelinux.cfg/* pattern should be served the pybootd/etc/pxe.cfg file instead. This prevents the client to perform the usual time-costing fallback requests using UUID, MAC, and suffix addresses before eventually falling back to the simple pxelinux.cfg file.
The following filter:
startup = [dir/{filename}.cfg]
tells the tftp server that when the startup file is requested, it should read out the actual filename from the dir/startup.cfg file.
HTTP-based authentication
This option enabled the delegation of the BOOTP authorization to a remote web server. As pybootd emits standard HTTP GET requests and expects standard HTTP reply codes, any web server may be used to manage authorizations.
This web server receives HTTP GET requests with URLs formatted as follows:
http://server/path?mac=AA-BB-CC-DD-EE-FF&uuid=xxxxxxxx-aaaa-bbbb-cccc-yyyyyyyyyyyy
where:
http://server matches the location option,
/path matches the pxe or dhcp options of the [http] section.
The web server should reply either with:
200 Ok result if the requester is to be assigned an IP address, or
401 Unauthorized result if it is to be ignored.
The pybootd package contains a minimalist HTTP server that demonstrates this feature. It can be found within the tests/ subdirectory. See the config.ini file for this test daemon. The test daemon expects the pxe path to be set to /boot and the dhcp path to /linux.
Sample configurations
Installing a Debian 6.0 machine from the official archive
As the tftp daemon is able to retrieve remote files using the HTTP protocol, there is no need to manually download any file from a Debian mirror. The daemon will forward all file requests to the mirror on behalf of the client being installed.
The pybootd.ini would contain:
[logger] ; show requests on the standard error output of the daemon type = stderr ; show informative and error messages only (disable verbose mode) level = info [bootp] ; do not force a full PXE boot-up cycle to accept the client allow_simple_dhcp = enable ; First BOOTP/DHCP address to generate pool_start = 192.168.1.100 ; Google DNS dns = 8.8.8.8 ; boot-up executable the client should request through TFTP boot_file = pxelinux.0 [tftp] ; URL to install a Debian 6.0 Intel/AMD 64-bit network installation root = http://http.us.debian.org/debian/dists/squeeze/main/installer-amd64/current/images/netboot [filters] ; serve a simple configuration file to the linux PXE helper pxelinux.cfg/* = pybootd/etc/pxe.cfg
The pool_start parameter should be a valid address on the host’s networks, and the root URL may be changed to use alternative mirror and path.
Please note that to complete the network installation, the client should be able to access the remote resources on its own - as with a network ISO image installation. There are two ways to achieve this:
either enable IP forwarding on the pybootd host (see forward.sh script within the pybootd package), or
be sure to connect the network cable of the client to a LAN that has direct access to the Internet, once the first installation stage is complete.