Initial commit: Simple DHCP Server mit Tkinter-GUI und Start-Skripten

This commit is contained in:
Marcel Peterkau
2025-09-11 09:58:51 +02:00
commit 992835bdc1
10 changed files with 292 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
venv/
__pycache__/
*.pyc
*.pyo
*.pyd
.env
.DS_Store

55
README.md Normal file
View File

@@ -0,0 +1,55 @@
# Python DHCP Tkinter Application
This project is a simple DHCP server application built using Python and Tkinter. It provides a graphical user interface (GUI) for managing DHCP leases and clients.
## Project Structure
```
python-dhcp-tk-app
├── src
│ ├── main.py # Entry point of the application
│ ├── dhcp_server.py # Contains the DHCPServer class
│ ├── gui.py # Defines the GUI layout
│ ├── utils.py # Utility functions for networking tasks
│ └── types
│ └── __init__.py # Custom types and data structures
├── requirements.txt # Project dependencies
└── README.md # Project documentation
```
## Requirements
To run this project, you need to install the following dependencies:
- tkinter
- (any additional libraries required for DHCP functionality)
You can install the required packages using pip:
```
pip install -r requirements.txt
```
## Usage
1. Run the application by executing the `main.py` file:
```
python src/main.py
```
2. The GUI will display a dropdown menu with available network interfaces. Select the desired interface.
3. Enter the desired IP address and subnet mask in the provided fields.
4. Use the "Start" button to start the DHCP server. The application will begin managing DHCP leases and display active clients in the list.
5. To stop the DHCP server, click the "Stop" button.
## Contributing
Feel free to contribute to this project by submitting issues or pull requests. Your feedback and contributions are welcome!
## License
This project is licensed under the MIT License. See the LICENSE file for more details.

2
requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
tkinter
scapy

35
src/dhcp_server.py Normal file
View File

@@ -0,0 +1,35 @@
class DHCPServer:
def __init__(self):
self.leases = {}
self.active_clients = []
def start(self, interface, ip_range, subnet):
# Start the DHCP server on the specified interface
pass
def stop(self):
# Stop the DHCP server
pass
def handle_request(self, request):
# Handle incoming DHCP requests
pass
def add_lease(self, client_ip, client_mac):
# Add a new lease for a client
self.leases[client_mac] = client_ip
self.active_clients.append(client_mac)
def remove_lease(self, client_mac):
# Remove a lease for a client
if client_mac in self.leases:
del self.leases[client_mac]
self.active_clients.remove(client_mac)
def get_active_clients(self):
# Return a list of active clients
return self.active_clients
def get_leases(self):
# Return the current leases
return self.leases

68
src/gui.py Normal file
View File

@@ -0,0 +1,68 @@
from tkinter import Tk, Label, Button, Entry, StringVar, OptionMenu, Listbox, END
import psutil
from dhcp_server import DHCPServer
class DHCPApp:
def __init__(self, master):
self.master = master
master.title("DHCP Server")
self.interface_label = Label(master, text="Select Network Interface:")
self.interface_label.pack()
self.interface_var = StringVar(master)
self.interfaces = self.get_network_interfaces()
self.interface_menu = OptionMenu(master, self.interface_var, *self.interfaces)
self.interface_menu.pack()
self.ip_label = Label(master, text="IP Address:")
self.ip_label.pack()
self.ip_entry = Entry(master)
self.ip_entry.pack()
self.subnet_label = Label(master, text="Subnet Mask:")
self.subnet_label.pack()
self.subnet_entry = Entry(master)
self.subnet_entry.pack()
self.start_button = Button(master, text="Start DHCP Server", command=self.start_dhcp_server)
self.start_button.pack()
self.stop_button = Button(master, text="Stop DHCP Server", command=self.stop_dhcp_server)
self.stop_button.pack()
self.clients_label = Label(master, text="Active Clients:")
self.clients_label.pack()
self.clients_listbox = Listbox(master)
self.clients_listbox.pack()
self.dhcp_server = None
def get_network_interfaces(self):
return psutil.net_if_addrs().keys()
def start_dhcp_server(self):
ip = self.ip_entry.get()
subnet = self.subnet_entry.get()
interface = self.interface_var.get()
self.dhcp_server = DHCPServer(interface, ip, subnet)
self.dhcp_server.start()
self.update_clients_list()
def stop_dhcp_server(self):
if self.dhcp_server:
self.dhcp_server.stop()
self.dhcp_server = None
self.clients_listbox.delete(0, END)
def update_clients_list(self):
if self.dhcp_server:
self.clients_listbox.delete(0, END)
for client in self.dhcp_server.get_active_clients():
self.clients_listbox.insert(END, client)
if __name__ == "__main__":
root = Tk()
app = DHCPApp(root)
root.mainloop()

69
src/main.py Normal file
View File

@@ -0,0 +1,69 @@
import tkinter as tk
from tkinter import ttk
from dhcp_server import DHCPServer
import utils
class DHCPApp:
def __init__(self, root):
self.root = root
self.root.title("Simple DHCP Server")
self.server = None
self.interface_label = tk.Label(root, text="Select Network Interface:")
self.interface_label.grid(row=0, column=0, padx=10, pady=10)
self.interface_var = tk.StringVar()
self.interface_dropdown = ttk.Combobox(root, textvariable=self.interface_var)
self.interface_dropdown['values'] = utils.get_network_interfaces()
self.interface_dropdown.grid(row=0, column=1, padx=10, pady=10)
self.ip_label = tk.Label(root, text="DHCP IP Range Start:")
self.ip_label.grid(row=1, column=0, padx=10, pady=10)
self.ip_entry = tk.Entry(root)
self.ip_entry.grid(row=1, column=1, padx=10, pady=10)
self.subnet_label = tk.Label(root, text="Subnet Mask:")
self.subnet_label.grid(row=2, column=0, padx=10, pady=10)
self.subnet_entry = tk.Entry(root)
self.subnet_entry.grid(row=2, column=1, padx=10, pady=10)
self.start_button = tk.Button(root, text="Start DHCP Server", command=self.start_server)
self.start_button.grid(row=3, column=0, padx=10, pady=10)
self.stop_button = tk.Button(root, text="Stop DHCP Server", command=self.stop_server)
self.stop_button.grid(row=3, column=1, padx=10, pady=10)
self.clients_label = tk.Label(root, text="Active Clients:")
self.clients_label.grid(row=4, column=0, padx=10, pady=10)
self.clients_listbox = tk.Listbox(root, width=50)
self.clients_listbox.grid(row=5, column=0, columnspan=2, padx=10, pady=10)
def start_server(self):
if not self.server:
ip_range = self.ip_entry.get()
subnet = self.subnet_entry.get()
interface = self.interface_var.get()
self.server = DHCPServer(interface, ip_range, subnet)
self.server.start()
self.update_clients()
def stop_server(self):
if self.server:
self.server.stop()
self.server = None
self.clients_listbox.delete(0, tk.END)
def update_clients(self):
if self.server:
self.clients_listbox.delete(0, tk.END)
for client in self.server.get_active_clients():
self.clients_listbox.insert(tk.END, client)
if __name__ == "__main__":
root = tk.Tk()
app = DHCPApp(root)
root.mainloop()

8
src/types/__init__.py Normal file
View File

@@ -0,0 +1,8 @@
class ClientLease:
def __init__(self, ip_address, mac_address, lease_time):
self.ip_address = ip_address
self.mac_address = mac_address
self.lease_time = lease_time
def __repr__(self):
return f"ClientLease(ip_address={self.ip_address}, mac_address={self.mac_address}, lease_time={self.lease_time})"

29
src/utils.py Normal file
View File

@@ -0,0 +1,29 @@
def get_available_interfaces():
import netifaces
return netifaces.interfaces()
def format_ip_address(ip):
try:
parts = ip.split('.')
if len(parts) != 4:
raise ValueError("Invalid IP address format")
return '.'.join(str(int(part)) for part in parts)
except ValueError as e:
raise ValueError(f"Error formatting IP address: {e}")
def validate_subnet_mask(mask):
valid_masks = [
'255.255.255.255', '255.255.255.254', '255.255.255.252',
'255.255.255.248', '255.255.255.240', '255.255.255.224',
'255.255.255.192', '255.255.255.128', '255.255.255.0',
'255.255.254.0', '255.255.252.0', '255.255.248.0',
'255.255.240.0', '255.255.224.0', '255.255.192.0',
'255.255.128.0', '255.255.0.0', '255.254.0.0',
'255.252.0.0', '255.248.0.0', '255.240.0.0',
'255.224.0.0', '255.192.0.0', '255.128.0.0',
'255.0.0.0', '254.0.0.0', '252.0.0.0',
'248.0.0.0', '240.0.0.0', '224.0.0.0',
'192.0.0.0', '128.0.0.0', '0.0.0.0'
]
if mask not in valid_masks:
raise ValueError("Invalid subnet mask")

11
start.bat Normal file
View File

@@ -0,0 +1,11 @@
@echo off
if not exist venv (
python -m venv venv
)
call venv\Scripts\activate
pip install --upgrade pip
pip install -r requirements.txt
tasklist /FI "IMAGENAME eq python.exe" | find /I "main.py" >nul
if errorlevel 1 (
python src\main.py
)

8
start.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
if [ ! -d "venv" ]; then
python3 -m venv venv
fi
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
pgrep -f "python src/main.py" > /dev/null || python src/main.py