📜 ⬆️ ⬇️

Own bash DHCP server

I like to automate the process and write my own bikes to study this or that material. My new goal was a DHCP server that will issue an address in small networks so that you can make initial hardware configuration.

In this article I will tell you a little about the DHCP protocol and some subtleties from bash.



Final result


Let's start from the end, so that it is clear what we are fighting for.
')
Demonstration of work:



Script repository: firemoon777 / bash-dhcp-server

Initial problem


The setup I need is done this way: we connect directly over the twisted pair to the equipment, issue a temporary address via DHCP, configure the already created script. And so ten to twenty times in a row.

Many well-known isc-dhcp-server copes with its duties perfectly, but, alas, it does not notify my script that the address has been issued, so you need to somehow block the execution until the address has been issued.

The solution, like, on the surface: ping until blue in the face, until the equipment responds:

while ! ping -c1 -W1 "$DHCP" | grep -q "time=" do echo "Waiting for $DHCP..." done 

But in this decision, definitely, there is not enough adventurism.

Theoretical part


Getting an address with one DHCP server



The DHCP protocol works over UDP on ports 67 and 68. The server always works only on 67, and the client only on 68. Since the client does not have an address (has the address 0.0.0.0), the DHCP packets are sent in a broadcast manner. Those. The client always sends packets to the address 255.255.255.255:67 from the address 0.0.0.0:68, and the server sends from its address: 67 to the address 255.255.255.255:68.

The client receives the address in four packets ( DORA ):

  1. The client finds out where the DHCP server is here ( D iscover)
  2. The server responds and offers its address ( O ffer)
  3. The client requests the proposed address from a specific server ( R equest)
  4. The server agrees and issues an address ( A ck)

Visually, the scheme can be represented as follows:



Getting an address with multiple DHCP servers



When a client sends Discover, all servers that can hear will send their Offer to the client. But the customer must choose someone one. Client selection is announced in the Request message by option 54 (DHCP server), which contains the IP address of the preferred DHCP server. Although the Request is sent to everyone else on the network, only the DHCP server whose IP is specified in option 54 responds.



DHCP Package Contents


A DHCP packet consists of two parts: a constant, 236 bytes in size, and a variable that carries options (DHCP Option).

A table with all the fields of a DHCP packet from Wikipedia
FieldDescriptionLength (in bytes)
op
Message type For example, the values ​​can be: BOOTREQUEST (0x01, request from client to server) and BOOTREPLY (0x02, response from server to client).
one
htype
Type of hardware address. Valid values ​​for this field are defined in RFC 1700 "Assigned Numbers". For example, for an Ethernet MAC address, this field is 0x01.
one
hlen
The length of the hardware address in bytes. For the Ethernet MAC address — 0x06.
one
hops
The number of intermediate routers (called DHCP relay agents ) that the message went through. The client sets this field to 0x00.
one
xid
A unique 4-byte transaction identifier generated by the client at the beginning of the address acquisition process.
four
secs
The time in seconds since the beginning of the process of obtaining the address. May not be used (in this case it is set to 0x0000).
2
flags
Field for flags - special parameters of the DHCP protocol.
2
ciaddr
The IP address of the client. Filled only if the client already has its own IP address and is able to respond to ARP requests (this is possible if the client performs the address renewal procedure at the end of the lease period).
four
yiaddr
The new client IP address offered by the server.
four
siaddr
IP address of the server. Returned in the DHCP offer (see below).
four
giaddr
The IP address of the relay agent, if one was involved in the delivery of the DHCP message to the server.
four
chaddr
The hardware address (usually the MAC address) of the client.
sixteen
sname
Optional server name as a null-terminated string.
64
file
Optional file name on the server used by diskless workstations for remote boot. Like sname , is represented as a null-terminated string.
128
options
DHCP options field. Various advanced configuration options are listed here. At the beginning of this field, four special bytes are specified with the values ​​99, 130, 83, 99 (“magic numbers”), allowing the server to determine the presence of this field. The field has a variable length, but the DHCP client must be ready to accept a DHCP message of 576 bytes in length (in this message, the options field is 340 bytes long).
variable


List of all DHCP options in RFC 2132

DHCP options are encoded as follows:
roomLengthData

For example, parameter 3 (proposed gateway) with a value of 10.0.0.1:
3fourten00one

In case you need to pass several parameters, the parameter length increases.
For example, in parameter 6 (DNS server), we will transmit two addresses (1.1.1.1 and 8.8.4.4):
6eightoneoneoneoneeighteightfourfour

A sign of the end of the options field is the parameter with the number 255 (0xFF) and a length of 0.

Most often, the client submits parameter 55 (the list of parameters that he wants to receive in response) in DHCP Discover, however, we have the right to give him not everything he asked for.

Practical part


It was originally planned to write a server in some more suitable language for this (C), however, it would be simple and simple. How it is to write a script that will take over the functions of the dhcp-server.

Simplify


Since the server being developed was supposed to be used in networks of two nodes connected by a patch, the following simplifications were adopted:


Listener


First you need to learn how to take packets. This requires a certified sympathetic listener, for example, nc. But not every nc is suitable for these purposes. OpenBSD netcat 1.130 from debian is suitable, but 1.105 with Ubuntu is gone. Run nc to listen to all UDP packets arriving on port 67.

 nc -l 0.0.0.0 -up 67 -w0 

OpenBSD netcat is also needed because of the -w key with a value of 0. After receiving one packet (UDP Broadcast), the traditional nc does not accept more packets, but it does not end either.

Work with raw bytes


In the command interpreter, it is very difficult to work with non-printable characters, for example, with a null character: it simply ignores it. And the DHCP packet contains many bytes 0x00 (for example, the file field). The solution to the problem comes in the form of hex-dump:

  nc -l 0.0.0.0 -up 67 -w0 | stdbuf -o0 od -v -w1 -t x1 -An 

One byte per line, without displaying the address, not missing duplicate bytes. You can also spice up stdbuf -o0 so that the output is not buffered.

Receiving, storing and processing packages


From stdout, the od command is retrieved by the read command and added to the array.

 msg=() for i in {0..235}; do read -r tmp msg[$i]=$tmp done 

Although all values ​​are transmitted in hexadecimal notation, the DHCP Option number and the option length are best displayed on the screen / logs in the usual decimal form. To do this, you can use a brief bash entry:

 $ op=AC $ echo $((16#$op)) 172 

The received packet is edited according to the type of request (Discover or Request) and sent back.

Send reply


However, sending a package is not such an easy task. First you need to convert the bytes from the dump into the raw bytes and send all at once in one packet.

The conversion can be done using the printf utility with the help of escape sequences. And so that nothing is lost, write the bytes immediately to the file.

 #   >/tmp/dhcp.payload #     for i in ${msg[*]}; do printf "\x$i" >> /tmp/dhcp.payload done 

OpenBSD netcat is also used for sending. However, if version 1.105 with Ubuntu is suitable as a listener, then here it is not suitable for broadcasting UDP messages: we get a protocol not available error.

 cat /tmp/dhcp.payload | nc -ub 255.255.255.255 68 -s $SERVER -p 67 -w0 

The -b switch allows sending broadcast messages, and this is the second reason why the server should be started from under the superuser.

What is there with restrictions?


This DHCP server was developed with simplifications like a single client on the network. However, it will work with multiple clients. Just get the fastest address.



Conclusion


Although bash scripts can hardly be called a full-fledged programming language, nevertheless, with the proper desire, you can even solve such tasks as issuing an IP address on a network without using specially designed software. And the solution of specific tasks not only brings joy, but also new knowledge that was discovered at the moment of the solution.

Sources


  1. DHCP - Wikipedia
  2. DHCP and BOOTP Parameters - IANA

Source: https://habr.com/ru/post/435148/


All Articles