Table of content
We will use dnsmasq
to provide basic networking
(DNS forwarding, DHCP configuration, PXE booting) to a dedicated network
behind a NAT.
In this example the gateway to the network is done through the interface
vmnet0
which is configured as 192.168.100.1/24
.
- Website: https://thekelleys.org.uk/dnsmasq/doc.html
- Follow-up: iPXE, NAT
- Related: DHCP, DNS
As our system is already running a local DNS resolver
(local_unbound
) we need to ensure that
dnsmasq
doesn’t steal its requests by listening on the
wildcard address (0.0.0.0
or ::
), so we explicitly bind to the
desired interfaces.
dnsmasq
listen on the loopback interface even
if not requested in interface
directive so it needs to be
explicitly removed using except-interface
During the setup phase in can be useful to log information about the DNS queries handled or the DHCP messages exchanged.
DNS
Here we are using the default behaviour of dnsmasq
which is to:
- read
/etc/resolv.conf
to identify name servers to use for resolving queries - read
/etc/hosts
to make locally defined host available for name resolution
To try to avoid forwarding name resolution up to the DNS root servers,
only the requests having a domain part (ie: names with a dot in it)
will be forwarded.
Other restrictions are possibles such as bogus-priv
,
which forbid private addresses reverse lookups (like: 192.168.x.y
)
but they will not be enabled as in our configuration we are on a private
network if it’s not your case you should consider enabling it.
We enable DNSSEC validation to ensure authenticity of name resolution.
But as lot of domains don’t sign their zones we don’t want to have
name resolution for these domains rejected, so extra check will be
performed to distinguish unsigned domain from forgery
(dnssec-check-unsigned
).
DHCP
Usually you should never run dnsmasq
on your
main interface (even worst if dhcp-authoritative
is set),
failing to do this will summon a really angry sysadmin, as you will serve
bogus answer on its network.
As the purpose of dnsmasq
is to act as a DNS + DHCP +
TFTP server, the corresponding options (router
(3), dns-server
(6), and next server
) in DHCP answers will be filled automatically
to announce the IP address on which dnsmasq
is listening,
so you shouldn’t need to specify them.
Nevertheless if required it is possible to overwrite defaults
(replacing 192.168.100.1
by the desired address)
using:
1 2 3 |
|
It is possible to have conditional configuration for numerous
directives (dhcp-option
, dhcp-host
, dhcp-boot
, … ) by using
tag:
my-tag
, documentation for each directive must be
read to know the exact placement of the tag keyword.
Address allocation
We define our DHCP server as authoritative (we are the only DHCP server on our network), and the range of IP addresses that can be dynamically allocated (with it default lease time).
Diskless booting
We will create various tag for conditional branching, they will be mainly based on the vendor class, the client architecture, and the MAC address (which prefix identify the card manufacturer).
The number1 defined in the client architecture option allows to identify
the computer architecture (i386
, x86_64
, arm32
, arm64
, …),
it’s interface (BIOS, UEFI, …), and the type of client (default or http).
The following table give a summary of it:
Id | Architecture | Interface | Client | Deprecated |
---|---|---|---|---|
0 | i386 | BIOS | ||
1 | NEC/PC98 | ✓ | ||
2 | Itanium | |||
3 | DEC Alpha | ✓ | ||
4 | Arc x86 | ✓ | ||
5 | Intel Lean Client | ✓ | ||
6 | x86_64 | UEFI | ||
7 | x86_64 | UEFI | ||
8 | Xscale | EFI | ✓ | |
9 | EBC | UEFI | ||
10 | ARM 32-bit | UEFI | ||
11 | ARM 64-bit | UEFI | ||
12 | PowerPC | Open Firmware | ||
13 | PowerPC | ePAPR | ||
14 | PowerPC | OPAL v3 | ||
15 | x86_64 | UEFI | http | |
16 | i386 | UEFI | http | |
17 | EBC | UEFI | http | |
18 | ARM 32-bit | UEFI | http | |
19 | ARM 64-bit | UEFI | http | |
20 | i386 | BIOS | http | |
21 | ARM 32-bit | uboot | ||
22 | ARM 64-bit | uboot | ||
23 | ARM 32-bit | uboot | http | |
24 | ARM 64-bit | uboot | http | |
25 | RISC-V 32-bit | UEFI | ||
26 | RISC-V 32-bit | UEFI | http | |
27 | RISC-V 64-bit | UEFI | ||
28 | RISC-V 64-bit | UEFI | http | |
29 | RISC-V 128-bit | UEFI | ||
30 | RISC-V 128-bit | UEFI | http | |
31 | s390 Basic | |||
32 | s390 Extended | |||
33 | MIPS 32-bit | UEFI | ||
34 | MIPS 64-bit | UEFI | ||
35 | Sunway 32-bit | UEFI | ||
36 | Sunway 64-bit | UEFI |
Base on this table, we define several tags corresponding to (this can of course be reduced to the list you really need):
-
the type of interface
-
the CPU architecture
-
the type of client
We also define tags based on:
-
The MAC address. It allows for example to identify vm-bhyve allocated VM, as the start of the MAC address correspond to the manufacturer, here: FreeBSD.
-
The type of client currently running. It allows to break bootloop when chain loading another PXE client, otherwise if you can’t identify the running client you risk to always request the same file.
Force HTTPClient
option in response, if it was set in the request:
Load the preferred client (here: iPXE) to manage the boot process:
Now that we are running the desired client, we need to choose how to boot (the examples below are snippets that need to be customize and prefixed with additional tags):
-
Use an iPXE script to decide what actions need to be performed.
-
Boot from an iSCSI target (using an iPXE SAN target URI).
-
Use the FreeBSD loader (without loading iPXE)
TFTP
The TFTP protocol can be used if you need to retrieve files during the
boot process (kernel, bootloader, configuration, …), and
dnsmasq
already embed such a server.
TFTP is not the most secure protocol or the one with the best transfer rate. Recent PXE/UEFI implementation allow the use of HTTP or HTTPS instead.
-
The list of assigned architecture is available at: https://www.ietf.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml#processor-architecture ↩