Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Python ZTP server which support simple DHCP reponse, TFTP, HTTP file service

Notifications You must be signed in to change notification settings

nchekwa/python-ztp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

54 Commits

Repository files navigation

Zero touch provisioning (ZTP) (include DHCP/TFTP/HTTP)

Python3 script which using YAML file as host config to offer DHCP/IP for device.
System sniff DHCP packets and answer using own build DHCP responses (based on scapy library)
Built-in TFTP/HTTP servers allow host download config/firmware which was pointed in dhcp option.

No more installing Isc/Kea DHCP and configuring DHCP scopes/TFTP/HTTP...

Syntax:

[root@server ztp]# ./ztp.py -h
usage: ztp.py [-h] [-i INTERFACE] [-l LIMIT] [-p PATH] [--port_tftp PORT_TFTP]
 [--port_http PORT_HTTP] [-d PCAP]
optional arguments:
 -h, --help show this help message and exit
 -i INTERFACE, --interface INTERFACE
 Interface to service requests
 -p PATH, --path PATH TFTP folder path. Set `None` to disable TFTP
 --port_tftp PORT_TFTP
 TFTP port
 --port_http PORT_HTTP
 HTTP port
 -d PCAP, --pcap PCAP collect PCAP file name for debug

Memory consumption:

[root@server ztp]# pmap 3068 | grep total
 total 410900K

Example:

Screenshot

Config Yaml file example:

VM0021210000:
 mac: 50:00:21:21:00:00
 hostname: Spine-21
 domain: juniper.lab
 ip: 10.240.40.21
 subnet_mask: 255.255.252.0
 router: 10.240.40.1
 name_server: 8.8.8.8 // (only SINGLE server supported)
 lease_time: 60
 tftp_server_name: 10.240.40.254
 boot-file-name: juniper.config
 tftp_server_address: 10.240.40.254
 vendor_specific: 0:junos.tgz,1:VM0021210000/juniper.sh,3:http

Config needs to be store in tftp folder in single / or multiple yaml files.
Configs are checked/read everytime when new dhcp Discovery pacet would be capture.
This consuming some resorces (utlize disk) but allow you 'in fly' modyfie config without restarting ztp instance.
YAML Config format:
<hostname/name>:
 mac: <mac - allow format with seperators like .:->
 <parameter>: <value>

In some cases new unboxed device report as hostname their serial number so in this situation, if script discovery that hostname inside Discovery message match this <hostname/name> - it will use this config section to send Offer.

DHCP_Discovery

If hostname/name will not be found in config files - it will check in 2nd step - mac match - for DHCP request in all configs.

parameters are related to scapy dhcp layer lib which can be found under this Link -> DHCPOptions
Please note that parameters tftp_server_name (option 66) and tftp_server_address (option 150) are missing in scapy layer lib so it needs to be added manually:

sed -i 's/ 67: StrField/ 66: "tftp_server_name",\n 67: StrField/g' /usr/local/lib/python3.6/site-packages/scapy/layers/dhcp.py
sed -i 's/ 255: "end"/ 150: IPField("tftp_server_address", "0.0.0.0"),\n 255: "end"/g' /usr/local/lib/python3.6/site-packages/scapy/layers/dhcp.py

Scapy issie 2747

Please remember that this docker need to be exposed to net=host as we need to get access to broadcast packages (scapy promisc mode). Use IFACE env on which interface docker should be listening.

Download docker image:

Download from docker.hub

[user@localhost ~]# docker pull nchekwa/python_ztp

Run in interactive mode:

[user@localhost ~]# docker run --name ztp --net=host -e IFACE="eth1" -v /tftp:/opt/ztp/tftp --rm -ti nchekwa/python_ztp

Docker registration:

[user@localhost ~]# docker create \
 --name=ztp \
 --net=host \
 -e IFACE="eth1" \
 -v /tftp:/opt/ztp/tftp \
 --restart unless-stopped \
 nchekwa/python_ztp:latest
[user@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
22cf97689207 nchekwa/python_ztp:latest "/bin/sh -c '\"python..." About a minute ago Created ztp
[user@localhost ~]# docker start ztp
ztp
[user@localhost ~]# docker logs -f --tail 10 ztp
Running. Press CTRL-C to exit.
[facts] DHCP/TFTP interface: eth1
[facts] eth1 IP: 10.240.40.254
[facts] eth1 MAC: 50:00:00:33:00:01
[facts] File folder status: exist
[facts] File Path: /opt/ztp/tftp
[OK] TFTP starting on 10.240.40.254 - port 69
[Warning] HTTP 10.240.40.254:80 port in use
[OK] DHCP starting sniffer eth1 - udp and (port 67 or 68)
eth1|<- [Rcv][Discover][0x61ec0f9e] Host VM0033330000 (50:00:33:33:00:00) asked for an IP
eth1|<- [Rcv][Discover][0x7c78d728] Host VM0033330000 (50:00:33:33:00:00) asked for an IP

Docker Composer:

Install:

curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker-compose version 1.26.2, build eefe0d31

Run:

docker-compose.yaml

---
version: "3"
services:
 python_ztp:
 image: nchekwa/python_ztp
 container_name: ztp
 network_mode: host
 environment:
 - IFACE=eth1
 volumes:
 - /tftp:/opt/ztp/tftp
 restart: unless-stopped
[user@localhost ~]# docker-compose -f docker-compose.yaml up -d
[user@localhost ~]# docker-compose -f docker-compose.yaml down

About

Python ZTP server which support simple DHCP reponse, TFTP, HTTP file service

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

AltStyle によって変換されたページ (->オリジナル) /