Initial commit: DHCP whitelist service for direct link connections
Features: - Docker-based DHCP server with MAC address whitelisting - Binds to specific ethernet interface only - NO DNS/gateway advertised (direct link only, not a router) - Configurable network parameters (subnet, DHCP range, lease times) - Systemd service integration for Arch/Manjaro - Test environment with isolated network (172.20.0.0/24) - Auto-configuration script to detect network settings - Complete Makefile with management targets Security: - Only responds to whitelisted MAC addresses - deny unknown-clients configuration - Runs in Docker container for isolation Configuration: - Copy .example files to create your config - interface.conf: Network interface to bind to - whitelist.conf: Allowed MAC addresses - network.conf: Network parameters (optional)
This commit is contained in:
commit
141ac1c9dd
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
|
docker-compose.override.yml
|
||||||
|
*.log
|
||||||
|
*.pid
|
||||||
|
/data/
|
||||||
|
/tmp/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# User configuration files (keep examples only)
|
||||||
|
config/interface.conf
|
||||||
|
config/whitelist.conf
|
||||||
|
config/network.conf
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
FROM alpine:3.19
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
dhcp \
|
||||||
|
bash \
|
||||||
|
iproute2
|
||||||
|
|
||||||
|
RUN mkdir -p /var/lib/dhcp /etc/dhcp /run/dhcp
|
||||||
|
|
||||||
|
COPY dhcp/entrypoint.sh /entrypoint.sh
|
||||||
|
COPY dhcp/dhcpd.conf.template /etc/dhcp/dhcpd.conf.template
|
||||||
|
|
||||||
|
RUN chmod +x /entrypoint.sh && \
|
||||||
|
touch /var/lib/dhcp/dhcpd.leases
|
||||||
|
|
||||||
|
EXPOSE 67/udp
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
78
Makefile
Normal file
78
Makefile
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
.PHONY: up down install service_up service_down test autoconfig clean help
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
help:
|
||||||
|
@echo "Available targets:"
|
||||||
|
@echo " up - Start DHCP server in userland mode"
|
||||||
|
@echo " down - Stop DHCP server"
|
||||||
|
@echo " install - Install as systemd service (requires sudo)"
|
||||||
|
@echo " service_up - Enable and start systemd service"
|
||||||
|
@echo " service_down - Disable and stop systemd service"
|
||||||
|
@echo " test - Run test environment with virtual network (172.20.0.0/24)"
|
||||||
|
@echo " test-clean - Clean up test environment"
|
||||||
|
@echo " autoconfig - Auto-generate configuration from current network"
|
||||||
|
@echo " clean - Remove all containers and generated files"
|
||||||
|
|
||||||
|
# Start DHCP server in userland mode
|
||||||
|
up:
|
||||||
|
@echo "Building DHCP server image..."
|
||||||
|
@docker-compose build
|
||||||
|
@echo "Starting DHCP server..."
|
||||||
|
@docker-compose up -d
|
||||||
|
@echo "DHCP server started. Check logs with: docker-compose logs -f"
|
||||||
|
|
||||||
|
# Stop DHCP server
|
||||||
|
down:
|
||||||
|
@echo "Stopping DHCP server..."
|
||||||
|
@docker-compose down
|
||||||
|
@echo "DHCP server stopped."
|
||||||
|
|
||||||
|
# Install as systemd service (requires sudo)
|
||||||
|
install:
|
||||||
|
@echo "Installing systemd service..."
|
||||||
|
@bash scripts/install-service.sh
|
||||||
|
@echo "Service installed. Use 'make service_up' to start."
|
||||||
|
|
||||||
|
# Enable and start systemd service
|
||||||
|
service_up:
|
||||||
|
@echo "Enabling and starting systemd service..."
|
||||||
|
@systemctl --user enable dhcp-whitelist.service 2>/dev/null || sudo systemctl enable dhcp-whitelist.service
|
||||||
|
@systemctl --user start dhcp-whitelist.service 2>/dev/null || sudo systemctl start dhcp-whitelist.service
|
||||||
|
@echo "Service started. Check status with: systemctl status dhcp-whitelist"
|
||||||
|
|
||||||
|
# Disable and stop systemd service
|
||||||
|
service_down:
|
||||||
|
@echo "Stopping and disabling systemd service..."
|
||||||
|
@systemctl --user stop dhcp-whitelist.service 2>/dev/null || sudo systemctl stop dhcp-whitelist.service
|
||||||
|
@systemctl --user disable dhcp-whitelist.service 2>/dev/null || sudo systemctl disable dhcp-whitelist.service
|
||||||
|
@echo "Service stopped."
|
||||||
|
|
||||||
|
# Run test environment
|
||||||
|
test:
|
||||||
|
@echo "Building test environment..."
|
||||||
|
@docker-compose -f docker-compose.test.yml build
|
||||||
|
@echo "Running tests..."
|
||||||
|
@docker-compose -f docker-compose.test.yml up --abort-on-container-exit
|
||||||
|
@$(MAKE) test-clean
|
||||||
|
@echo "Tests completed."
|
||||||
|
|
||||||
|
# Clean up test environment (always runs, even on test failure)
|
||||||
|
test-clean:
|
||||||
|
@echo "Cleaning up test environment..."
|
||||||
|
@docker-compose -f docker-compose.test.yml down -v --remove-orphans 2>/dev/null || true
|
||||||
|
@docker network rm service-dhcp-direct-link-only_test-net 2>/dev/null || true
|
||||||
|
@echo "Test cleanup complete."
|
||||||
|
|
||||||
|
# Auto-generate configuration
|
||||||
|
autoconfig:
|
||||||
|
@echo "Auto-generating configuration..."
|
||||||
|
@bash scripts/autoconfig.sh
|
||||||
|
@echo "Configuration generated. Review config/ directory before starting."
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
clean:
|
||||||
|
@echo "Cleaning up..."
|
||||||
|
@docker-compose down 2>/dev/null || true
|
||||||
|
@$(MAKE) test-clean
|
||||||
|
@rm -f config/*.tmp
|
||||||
|
@echo "Cleanup complete."
|
136
README.md
Normal file
136
README.md
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# DHCP Direct Link Only Service
|
||||||
|
|
||||||
|
A Docker-based DHCP server that only serves IP addresses to whitelisted MAC addresses on a specific ethernet interface. Designed for secure, controlled network environments where only authorized devices should receive DHCP leases.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **MAC Address Whitelisting**: Only responds to DHCP requests from pre-authorized MAC addresses
|
||||||
|
- **Interface Binding**: Binds to a specific ethernet interface only
|
||||||
|
- **Docker-Based**: Runs in an isolated container environment
|
||||||
|
- **Systemd Integration**: Can be installed as a system service on Arch/Manjaro
|
||||||
|
- **Auto-Configuration**: Automatically detects network settings and connected devices
|
||||||
|
- **Testing Environment**: Includes isolated test environment with virtual networks
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
- Docker Compose
|
||||||
|
- Make
|
||||||
|
- systemd (for service installation)
|
||||||
|
- sudo (for service installation)
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. Auto-configure for current network:
|
||||||
|
```bash
|
||||||
|
make autoconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Start the DHCP server:
|
||||||
|
```bash
|
||||||
|
make up
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Stop the server:
|
||||||
|
```bash
|
||||||
|
make down
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Manual Configuration
|
||||||
|
|
||||||
|
Edit the following files in the `config/` directory:
|
||||||
|
|
||||||
|
- `interface.conf`: Specify the ethernet interface to bind to
|
||||||
|
- `whitelist.conf`: List MAC addresses (one per line) that should be served
|
||||||
|
|
||||||
|
### Auto Configuration
|
||||||
|
|
||||||
|
Run `make autoconfig` to automatically:
|
||||||
|
- Detect your ethernet interface
|
||||||
|
- Find connected devices on the network
|
||||||
|
- Generate configuration files
|
||||||
|
|
||||||
|
## Make Targets
|
||||||
|
|
||||||
|
| Target | Description | Requires sudo |
|
||||||
|
|--------|-------------|---------------|
|
||||||
|
| `up` | Start DHCP server in userland mode | No |
|
||||||
|
| `down` | Stop DHCP server | No |
|
||||||
|
| `install` | Install as systemd service | Yes |
|
||||||
|
| `service_up` | Enable and start systemd service | No |
|
||||||
|
| `service_down` | Disable and stop systemd service | No |
|
||||||
|
| `test` | Run isolated test environment | No |
|
||||||
|
| `autoconfig` | Auto-generate configuration | No |
|
||||||
|
| `clean` | Remove generated files | No |
|
||||||
|
|
||||||
|
## Installation as System Service
|
||||||
|
|
||||||
|
To install and run as a systemd service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install the service (requires sudo)
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
make service_up
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
systemctl status dhcp-whitelist
|
||||||
|
|
||||||
|
# Stop the service
|
||||||
|
make service_down
|
||||||
|
```
|
||||||
|
|
||||||
|
The service configuration will be stored in `/etc/dhcp-whitelist/` and will persist across system reboots.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run the test environment with virtual networks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates an isolated Docker network with:
|
||||||
|
- A DHCP server with test whitelist
|
||||||
|
- Test clients with different MAC addresses
|
||||||
|
- Validation of whitelist enforcement
|
||||||
|
|
||||||
|
## Network Configuration
|
||||||
|
|
||||||
|
Default DHCP settings:
|
||||||
|
- Subnet: 192.168.75.0/24
|
||||||
|
- Range: 192.168.75.10 - 192.168.75.100
|
||||||
|
- Gateway: 192.168.75.1
|
||||||
|
- DNS: 8.8.8.8, 8.8.4.4
|
||||||
|
- Lease time: 12 hours
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### DHCP server not responding
|
||||||
|
- Check that the interface in `config/interface.conf` is correct
|
||||||
|
- Verify the MAC address is in `config/whitelist.conf`
|
||||||
|
- Check Docker logs: `docker-compose logs dhcp-server`
|
||||||
|
|
||||||
|
### Permission denied errors
|
||||||
|
- Service installation requires sudo: `sudo make install`
|
||||||
|
- Ensure Docker daemon is running
|
||||||
|
- Check that your user is in the docker group
|
||||||
|
|
||||||
|
### Service won't start
|
||||||
|
- Check systemd logs: `journalctl -u dhcp-whitelist -f`
|
||||||
|
- Verify Docker and docker-compose are installed
|
||||||
|
- Check configuration files in `/etc/dhcp-whitelist/`
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- This server uses MAC address filtering as the primary security mechanism
|
||||||
|
- MAC addresses can be spoofed; use additional security measures in production
|
||||||
|
- The server runs with host networking to access the physical interface
|
||||||
|
- Consider firewall rules to restrict DHCP traffic further
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
57
claude.md
Normal file
57
claude.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# DHCP Direct Link Only Service - Development Notes
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
This project creates a DHCP server that only responds to whitelisted MAC addresses on a specific ethernet interface. It's designed for direct link connections where only authorized devices should receive IP addresses, without any routing or DNS services.
|
||||||
|
|
||||||
|
## Configuration Features
|
||||||
|
- Binds to specific ethernet interface (configurable)
|
||||||
|
- MAC address whitelisting (configurable)
|
||||||
|
- NO DNS servers advertised (direct link only)
|
||||||
|
- NO gateway/router advertised (not a NAT setup)
|
||||||
|
- Configurable network parameters (subnet, range, lease times)
|
||||||
|
|
||||||
|
## Architecture Decisions
|
||||||
|
|
||||||
|
### Why Docker?
|
||||||
|
- Isolation from host system
|
||||||
|
- Easy deployment and management
|
||||||
|
- Consistent environment across different systems
|
||||||
|
- Simple cleanup and removal
|
||||||
|
|
||||||
|
### Why ISC DHCP Server?
|
||||||
|
- Mature, stable DHCP implementation
|
||||||
|
- Extensive configuration options
|
||||||
|
- Good documentation
|
||||||
|
- Supports MAC address filtering natively
|
||||||
|
|
||||||
|
### Network Mode: Host
|
||||||
|
The container uses host network mode because:
|
||||||
|
- DHCP requires direct access to the physical network interface
|
||||||
|
- DHCP uses raw sockets that don't work well with Docker's bridge networking
|
||||||
|
- We need to bind to a specific physical interface
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Whitelist Implementation
|
||||||
|
The whitelist is implemented using ISC DHCP's host declarations with a deny unknown-clients directive. This ensures only explicitly defined MAC addresses receive leases.
|
||||||
|
|
||||||
|
### Configuration Management
|
||||||
|
- Local configs in `config/` for development
|
||||||
|
- System configs in `/etc/dhcp-whitelist/` for production service
|
||||||
|
- Auto-config script detects network settings automatically
|
||||||
|
|
||||||
|
### Testing Strategy
|
||||||
|
- Isolated Docker network for testing
|
||||||
|
- Separate test client containers
|
||||||
|
- Tests both allowed and denied MAC scenarios
|
||||||
|
|
||||||
|
## Known Limitations
|
||||||
|
1. MAC addresses can be spoofed - this is not a security solution by itself
|
||||||
|
2. Requires host network mode which reduces container isolation
|
||||||
|
3. Only one instance can run per interface
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
- Web UI for managing whitelist
|
||||||
|
- Logging and monitoring
|
||||||
|
- Multiple interface support
|
||||||
|
- Integration with network authentication systems
|
3
config/interface.conf.example
Normal file
3
config/interface.conf.example
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Example: Ethernet interface name
|
||||||
|
# Find your interface with: ip link show
|
||||||
|
eth0
|
24
config/network.conf.example
Normal file
24
config/network.conf.example
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Network configuration for DHCP server
|
||||||
|
# These values override automatic detection
|
||||||
|
|
||||||
|
# Network subnet (leave empty for auto-detection from interface)
|
||||||
|
# Example: SUBNET=192.168.1.0
|
||||||
|
SUBNET=
|
||||||
|
|
||||||
|
# Netmask in dotted notation (leave empty for auto-detection)
|
||||||
|
# Example: NETMASK=255.255.255.0
|
||||||
|
NETMASK=
|
||||||
|
|
||||||
|
# DHCP range start offset from network base (default: 10)
|
||||||
|
# For example, if network is 192.168.1.0, start will be 192.168.1.10
|
||||||
|
RANGE_START_OFFSET=10
|
||||||
|
|
||||||
|
# DHCP range end offset from network base (default: 100)
|
||||||
|
# For example, if network is 192.168.1.0, end will be 192.168.1.100
|
||||||
|
RANGE_END_OFFSET=100
|
||||||
|
|
||||||
|
# Lease time in seconds (default: 43200 = 12 hours)
|
||||||
|
LEASE_TIME=43200
|
||||||
|
|
||||||
|
# Max lease time in seconds (default: 86400 = 24 hours)
|
||||||
|
MAX_LEASE_TIME=86400
|
5
config/whitelist.conf.example
Normal file
5
config/whitelist.conf.example
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# MAC addresses to whitelist (one per line)
|
||||||
|
# Format: aa:bb:cc:dd:ee:ff
|
||||||
|
# Example:
|
||||||
|
# 00:11:22:33:44:55
|
||||||
|
# aa:bb:cc:dd:ee:ff
|
18
dhcp/dhcpd.conf.template
Normal file
18
dhcp/dhcpd.conf.template
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
authoritative;
|
||||||
|
default-lease-time __LEASE_TIME__;
|
||||||
|
max-lease-time __MAX_LEASE_TIME__;
|
||||||
|
|
||||||
|
# Deny all clients by default
|
||||||
|
deny unknown-clients;
|
||||||
|
|
||||||
|
# Network configuration - Direct link only, no routing
|
||||||
|
subnet __SUBNET__ netmask __NETMASK__ {
|
||||||
|
range __RANGE_START__ __RANGE_END__;
|
||||||
|
# No gateway - this is a direct link only
|
||||||
|
# No DNS - clients should use their own DNS from other interfaces
|
||||||
|
option subnet-mask __NETMASK__;
|
||||||
|
option broadcast-address __BROADCAST__;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Whitelisted MAC addresses
|
||||||
|
__HOST_ENTRIES__
|
176
dhcp/entrypoint.sh
Executable file
176
dhcp/entrypoint.sh
Executable file
@ -0,0 +1,176 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
INTERFACE_FILE="/config/interface.conf"
|
||||||
|
WHITELIST_FILE="/config/whitelist.conf"
|
||||||
|
NETWORK_FILE="/config/network.conf"
|
||||||
|
DHCPD_CONF="/etc/dhcp/dhcpd.conf"
|
||||||
|
|
||||||
|
if [ ! -f "$INTERFACE_FILE" ]; then
|
||||||
|
echo "Error: Interface configuration file not found: $INTERFACE_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$WHITELIST_FILE" ]; then
|
||||||
|
echo "Error: Whitelist configuration file not found: $WHITELIST_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
INTERFACE=$(cat "$INTERFACE_FILE" | tr -d '\n\r ')
|
||||||
|
echo "Using interface: $INTERFACE"
|
||||||
|
|
||||||
|
# Wait for interface to be available
|
||||||
|
for i in {1..30}; do
|
||||||
|
if ip link show "$INTERFACE" &>/dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo "Waiting for interface $INTERFACE..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! ip link show "$INTERFACE" &>/dev/null; then
|
||||||
|
echo "Error: Interface $INTERFACE not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Load network configuration if available
|
||||||
|
if [ -f "$NETWORK_FILE" ]; then
|
||||||
|
echo "Loading network configuration from $NETWORK_FILE"
|
||||||
|
source "$NETWORK_FILE"
|
||||||
|
else
|
||||||
|
echo "No network configuration file found, using defaults"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set defaults for unset variables
|
||||||
|
RANGE_START_OFFSET=${RANGE_START_OFFSET:-10}
|
||||||
|
RANGE_END_OFFSET=${RANGE_END_OFFSET:-100}
|
||||||
|
LEASE_TIME=${LEASE_TIME:-43200}
|
||||||
|
MAX_LEASE_TIME=${MAX_LEASE_TIME:-86400}
|
||||||
|
|
||||||
|
# Get interface IP and network info
|
||||||
|
INTERFACE_IP=$(ip -4 addr show "$INTERFACE" | grep "inet " | awk '{print $2}' | cut -d'/' -f1)
|
||||||
|
INTERFACE_CIDR=$(ip -4 addr show "$INTERFACE" | grep "inet " | awk '{print $2}' | cut -d'/' -f2)
|
||||||
|
|
||||||
|
# Check if subnet is manually configured
|
||||||
|
if [ -n "$SUBNET" ] && [ -n "$NETMASK" ]; then
|
||||||
|
echo "Using manual network configuration: $SUBNET/$NETMASK"
|
||||||
|
INTERFACE_NETWORK="$SUBNET"
|
||||||
|
# Calculate broadcast from subnet and netmask
|
||||||
|
if [ "$NETMASK" = "255.255.255.0" ]; then
|
||||||
|
BROADCAST="${SUBNET%.*}.255"
|
||||||
|
elif [ "$NETMASK" = "255.255.0.0" ]; then
|
||||||
|
BROADCAST="${SUBNET%.*.*}.255.255"
|
||||||
|
elif [ "$NETMASK" = "255.0.0.0" ]; then
|
||||||
|
BROADCAST="${SUBNET%.*.*.*}.255.255.255"
|
||||||
|
else
|
||||||
|
BROADCAST="${SUBNET%.*}.255"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Auto-detecting network configuration from interface"
|
||||||
|
# For test environment, handle Docker's internal network properly
|
||||||
|
if [ "$INTERFACE" = "eth0" ] && [ -n "$INTERFACE_IP" ]; then
|
||||||
|
# Extract network base from the actual IP
|
||||||
|
INTERFACE_NETWORK=$(echo "$INTERFACE_IP" | sed 's/\.[0-9]*$/\.0/')
|
||||||
|
else
|
||||||
|
# Fallback for physical interfaces
|
||||||
|
INTERFACE_NETWORK=$(ip -4 addr show "$INTERFACE" | grep "inet " | awk '{print $2}' | cut -d'/' -f1 | sed 's/\.[0-9]*$/\.0/')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert CIDR to netmask and calculate broadcast
|
||||||
|
case $INTERFACE_CIDR in
|
||||||
|
24)
|
||||||
|
NETMASK="255.255.255.0"
|
||||||
|
BROADCAST="${INTERFACE_NETWORK%.*}.255"
|
||||||
|
;;
|
||||||
|
16)
|
||||||
|
NETMASK="255.255.0.0"
|
||||||
|
BROADCAST="${INTERFACE_NETWORK%.*.*}.255.255"
|
||||||
|
;;
|
||||||
|
8)
|
||||||
|
NETMASK="255.0.0.0"
|
||||||
|
BROADCAST="${INTERFACE_NETWORK%.*.*.*}.255.255.255"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
NETMASK="255.255.255.0"
|
||||||
|
BROADCAST="${INTERFACE_NETWORK%.*}.255"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Interface IP: $INTERFACE_IP"
|
||||||
|
echo "Network: $INTERFACE_NETWORK/$NETMASK"
|
||||||
|
echo "DHCP Range: ${INTERFACE_NETWORK%.*}.$RANGE_START_OFFSET - ${INTERFACE_NETWORK%.*}.$RANGE_END_OFFSET"
|
||||||
|
echo "Lease Time: $LEASE_TIME seconds"
|
||||||
|
|
||||||
|
# Generate dhcpd.conf from template
|
||||||
|
cp /etc/dhcp/dhcpd.conf.template "$DHCPD_CONF"
|
||||||
|
|
||||||
|
# Generate host entries for whitelisted MACs
|
||||||
|
HOST_ENTRIES=""
|
||||||
|
HOST_NUM=1
|
||||||
|
echo "Reading whitelist from $WHITELIST_FILE"
|
||||||
|
|
||||||
|
# Check if file exists and is readable
|
||||||
|
if [ ! -f "$WHITELIST_FILE" ]; then
|
||||||
|
echo "ERROR: Whitelist file does not exist!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -r "$WHITELIST_FILE" ]; then
|
||||||
|
echo "ERROR: Whitelist file is not readable!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "File size: $(stat -c%s "$WHITELIST_FILE") bytes"
|
||||||
|
echo "File contents (hex dump):"
|
||||||
|
hexdump -C "$WHITELIST_FILE" | head -5
|
||||||
|
echo "File contents (raw):"
|
||||||
|
cat "$WHITELIST_FILE"
|
||||||
|
echo ""
|
||||||
|
echo "--- Processing MACs ---"
|
||||||
|
|
||||||
|
# Read file line by line without subshell
|
||||||
|
while IFS= read -r MAC || [ -n "$MAC" ]; do
|
||||||
|
# Remove any whitespace, carriage returns, and convert to lowercase
|
||||||
|
ORIG_MAC="$MAC"
|
||||||
|
MAC=$(echo "$MAC" | tr -d '\r\n\t ' | tr '[:upper:]' '[:lower:]')
|
||||||
|
echo "Processing: original='$ORIG_MAC' cleaned='$MAC'"
|
||||||
|
|
||||||
|
if [ -n "$MAC" ]; then
|
||||||
|
# Generate IP based on host number (starting from .10)
|
||||||
|
LAST_OCTET=$((10 + HOST_NUM - 1))
|
||||||
|
HOST_IP="${INTERFACE_NETWORK%.*}.$LAST_OCTET"
|
||||||
|
NEW_ENTRY="
|
||||||
|
host client$HOST_NUM {
|
||||||
|
hardware ethernet $MAC;
|
||||||
|
fixed-address $HOST_IP;
|
||||||
|
}"
|
||||||
|
HOST_ENTRIES="${HOST_ENTRIES}${NEW_ENTRY}"
|
||||||
|
echo "Added whitelist entry: $MAC -> $HOST_IP"
|
||||||
|
HOST_NUM=$((HOST_NUM + 1))
|
||||||
|
fi
|
||||||
|
done < "$WHITELIST_FILE"
|
||||||
|
|
||||||
|
if [ -z "$HOST_ENTRIES" ]; then
|
||||||
|
echo "Warning: No MAC addresses found in whitelist!"
|
||||||
|
else
|
||||||
|
echo "Total whitelisted MACs: $((HOST_NUM - 1))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Replace placeholders in config
|
||||||
|
sed -i "s#__SUBNET__#$INTERFACE_NETWORK#g" "$DHCPD_CONF"
|
||||||
|
sed -i "s#__NETMASK__#$NETMASK#g" "$DHCPD_CONF"
|
||||||
|
sed -i "s#__RANGE_START__#${INTERFACE_NETWORK%.*}.$RANGE_START_OFFSET#g" "$DHCPD_CONF"
|
||||||
|
sed -i "s#__RANGE_END__#${INTERFACE_NETWORK%.*}.$RANGE_END_OFFSET#g" "$DHCPD_CONF"
|
||||||
|
sed -i "s#__BROADCAST__#$BROADCAST#g" "$DHCPD_CONF"
|
||||||
|
sed -i "s#__LEASE_TIME__#$LEASE_TIME#g" "$DHCPD_CONF"
|
||||||
|
sed -i "s#__MAX_LEASE_TIME__#$MAX_LEASE_TIME#g" "$DHCPD_CONF"
|
||||||
|
# Use a different approach for multiline HOST_ENTRIES
|
||||||
|
awk -v entries="$HOST_ENTRIES" '{gsub(/__HOST_ENTRIES__/, entries); print}' "$DHCPD_CONF" > "$DHCPD_CONF.tmp" && mv "$DHCPD_CONF.tmp" "$DHCPD_CONF"
|
||||||
|
|
||||||
|
echo "Starting DHCP server on interface $INTERFACE..."
|
||||||
|
echo "Configuration:"
|
||||||
|
cat "$DHCPD_CONF"
|
||||||
|
|
||||||
|
# Start DHCP server
|
||||||
|
exec dhcpd -4 -f -d -cf "$DHCPD_CONF" "$INTERFACE"
|
45
docker-compose.test.yml
Normal file
45
docker-compose.test.yml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
test-net:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.20.0.0/24
|
||||||
|
gateway: 172.20.0.1
|
||||||
|
|
||||||
|
services:
|
||||||
|
test-dhcp-server:
|
||||||
|
build: .
|
||||||
|
image: dhcp-whitelist:test
|
||||||
|
container_name: test-dhcp-server
|
||||||
|
networks:
|
||||||
|
test-net:
|
||||||
|
ipv4_address: 172.20.0.2
|
||||||
|
volumes:
|
||||||
|
- ./test/test-config:/config:ro
|
||||||
|
environment:
|
||||||
|
- TZ=UTC
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- NET_RAW
|
||||||
|
|
||||||
|
test-client-allowed:
|
||||||
|
build: ./test/test-client
|
||||||
|
container_name: test-client-allowed
|
||||||
|
networks:
|
||||||
|
test-net:
|
||||||
|
mac_address: "02:42:ac:11:00:02"
|
||||||
|
depends_on:
|
||||||
|
- test-dhcp-server
|
||||||
|
command: ["/bin/sh", "-c", "sleep 5 && udhcpc -i eth0 -n -q && ip addr show eth0"]
|
||||||
|
|
||||||
|
test-client-denied:
|
||||||
|
build: ./test/test-client
|
||||||
|
container_name: test-client-denied
|
||||||
|
networks:
|
||||||
|
test-net:
|
||||||
|
mac_address: "02:42:ac:11:00:99"
|
||||||
|
depends_on:
|
||||||
|
- test-dhcp-server
|
||||||
|
command: ["/bin/sh", "-c", "sleep 5 && timeout 10 udhcpc -i eth0 -n -q || echo 'DHCP request denied as expected'"]
|
17
docker-compose.yml
Normal file
17
docker-compose.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
dhcp-server:
|
||||||
|
build: .
|
||||||
|
image: dhcp-whitelist:latest
|
||||||
|
container_name: dhcp-whitelist-server
|
||||||
|
network_mode: host
|
||||||
|
privileged: true
|
||||||
|
volumes:
|
||||||
|
- ./config:/config:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- TZ=UTC
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- NET_RAW
|
155
scripts/autoconfig.sh
Executable file
155
scripts/autoconfig.sh
Executable file
@ -0,0 +1,155 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CONFIG_DIR="./config"
|
||||||
|
INTERFACE_CONF="${CONFIG_DIR}/interface.conf"
|
||||||
|
WHITELIST_CONF="${CONFIG_DIR}/whitelist.conf"
|
||||||
|
NETWORK_CONF="${CONFIG_DIR}/network.conf"
|
||||||
|
|
||||||
|
echo "=== DHCP Whitelist Auto-Configuration ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Create config directory if it doesn't exist
|
||||||
|
mkdir -p "${CONFIG_DIR}"
|
||||||
|
|
||||||
|
# Find ethernet interfaces (excluding loopback and virtual interfaces)
|
||||||
|
echo "Detecting ethernet interfaces..."
|
||||||
|
INTERFACES=$(ip link show | grep -E "^[0-9]+: en" | awk -F': ' '{print $2}' | head -1)
|
||||||
|
|
||||||
|
if [ -z "$INTERFACES" ]; then
|
||||||
|
echo "Error: No ethernet interface found"
|
||||||
|
echo "Please configure manually by editing ${INTERFACE_CONF}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found ethernet interface: $INTERFACES"
|
||||||
|
|
||||||
|
# Get the interface with an IP in 192.168.x.x range (common for local networks)
|
||||||
|
SELECTED_INTERFACE=""
|
||||||
|
for IFACE in $INTERFACES; do
|
||||||
|
IP_INFO=$(ip -4 addr show "$IFACE" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' || true)
|
||||||
|
if [ -n "$IP_INFO" ]; then
|
||||||
|
echo " Interface $IFACE has IP: $IP_INFO"
|
||||||
|
if [[ "$IP_INFO" =~ ^192\.168\. ]] || [[ "$IP_INFO" =~ ^10\. ]] || [[ "$IP_INFO" =~ ^172\. ]]; then
|
||||||
|
SELECTED_INTERFACE="$IFACE"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$SELECTED_INTERFACE" ]; then
|
||||||
|
# Fall back to first interface with any IP
|
||||||
|
for IFACE in $INTERFACES; do
|
||||||
|
if ip -4 addr show "$IFACE" 2>/dev/null | grep -q "inet "; then
|
||||||
|
SELECTED_INTERFACE="$IFACE"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SELECTED_INTERFACE" ]; then
|
||||||
|
echo "Error: No ethernet interface with IP address found"
|
||||||
|
echo "Using first available interface: $INTERFACES"
|
||||||
|
SELECTED_INTERFACE="$INTERFACES"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Selected interface: $SELECTED_INTERFACE"
|
||||||
|
echo "$SELECTED_INTERFACE" > "${INTERFACE_CONF}"
|
||||||
|
|
||||||
|
# Find MAC addresses of devices on the network
|
||||||
|
echo
|
||||||
|
echo "Scanning for devices on the network..."
|
||||||
|
|
||||||
|
# Get the network range
|
||||||
|
NETWORK_INFO=$(ip -4 addr show "$SELECTED_INTERFACE" | grep -oP '(?<=inet\s)\d+(\.\d+){3}/\d+' | head -1)
|
||||||
|
if [ -z "$NETWORK_INFO" ]; then
|
||||||
|
echo "Warning: Could not determine network range for $SELECTED_INTERFACE"
|
||||||
|
echo "Creating empty whitelist file. Please add MAC addresses manually."
|
||||||
|
touch "${WHITELIST_CONF}"
|
||||||
|
else
|
||||||
|
NETWORK=$(echo "$NETWORK_INFO" | cut -d'/' -f1 | sed 's/\.[0-9]*$/\.0/')
|
||||||
|
NETMASK=$(echo "$NETWORK_INFO" | cut -d'/' -f2)
|
||||||
|
|
||||||
|
echo "Network: ${NETWORK}/${NETMASK}"
|
||||||
|
|
||||||
|
# Try to ping the network to populate ARP table (just a few addresses)
|
||||||
|
echo "Discovering devices (this may take a moment)..."
|
||||||
|
BASE_NET=$(echo "$NETWORK" | sed 's/\.0$//')
|
||||||
|
for i in {1..10}; do
|
||||||
|
ping -c 1 -W 1 "${BASE_NET}.${i}" >/dev/null 2>&1 &
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
|
||||||
|
# Get MAC addresses from ARP table
|
||||||
|
echo
|
||||||
|
echo "Found devices:"
|
||||||
|
MACS=$(ip neigh show dev "$SELECTED_INTERFACE" | grep -E "lladdr" | awk '{print $5}' | sort -u)
|
||||||
|
|
||||||
|
if [ -z "$MACS" ]; then
|
||||||
|
echo " No devices found in ARP table"
|
||||||
|
echo " Creating empty whitelist. Please add MAC addresses manually."
|
||||||
|
touch "${WHITELIST_CONF}"
|
||||||
|
else
|
||||||
|
echo "$MACS" | while read -r MAC; do
|
||||||
|
IP=$(ip neigh show dev "$SELECTED_INTERFACE" | grep "$MAC" | awk '{print $1}')
|
||||||
|
echo " $MAC (IP: $IP)"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Writing MAC addresses to whitelist..."
|
||||||
|
echo "$MACS" > "${WHITELIST_CONF}"
|
||||||
|
echo "Added $(echo "$MACS" | wc -l) MAC address(es) to whitelist"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Configuration Summary ==="
|
||||||
|
echo "Interface: $(cat "${INTERFACE_CONF}")"
|
||||||
|
echo "Whitelist entries:"
|
||||||
|
if [ -f "${WHITELIST_CONF}" ] && [ -s "${WHITELIST_CONF}" ]; then
|
||||||
|
cat "${WHITELIST_CONF}" | sed 's/^/ /'
|
||||||
|
else
|
||||||
|
echo " (empty - please add MAC addresses manually)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
# Create or update network.conf with defaults (can be customized)
|
||||||
|
if [ ! -f "${NETWORK_CONF}" ]; then
|
||||||
|
echo
|
||||||
|
echo "Creating default network configuration..."
|
||||||
|
cat > "${NETWORK_CONF}" << EOF
|
||||||
|
# Network configuration for DHCP server
|
||||||
|
# These values override automatic detection
|
||||||
|
|
||||||
|
# Network subnet (leave empty for auto-detection from interface)
|
||||||
|
SUBNET=
|
||||||
|
|
||||||
|
# Netmask in dotted notation (leave empty for auto-detection)
|
||||||
|
NETMASK=
|
||||||
|
|
||||||
|
# DHCP range start offset from network base (default: 10)
|
||||||
|
RANGE_START_OFFSET=10
|
||||||
|
|
||||||
|
# DHCP range end offset from network base (default: 100)
|
||||||
|
RANGE_END_OFFSET=100
|
||||||
|
|
||||||
|
# Lease time in seconds (default: 43200 = 12 hours)
|
||||||
|
LEASE_TIME=43200
|
||||||
|
|
||||||
|
# Max lease time in seconds (default: 86400 = 24 hours)
|
||||||
|
MAX_LEASE_TIME=86400
|
||||||
|
EOF
|
||||||
|
echo "Network configuration created with defaults"
|
||||||
|
else
|
||||||
|
echo "Network configuration already exists, keeping current settings"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Configuration files created:"
|
||||||
|
echo " ${INTERFACE_CONF}"
|
||||||
|
echo " ${WHITELIST_CONF}"
|
||||||
|
echo " ${NETWORK_CONF}"
|
||||||
|
echo
|
||||||
|
echo "You can now start the DHCP server with: make up"
|
||||||
|
echo "Or install as a service with: sudo make install"
|
134
scripts/install-service.sh
Executable file
134
scripts/install-service.sh
Executable file
@ -0,0 +1,134 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "This script must be run with sudo"
|
||||||
|
echo "Usage: sudo make install"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVICE_NAME="dhcp-whitelist"
|
||||||
|
SERVICE_FILE="systemd/${SERVICE_NAME}.service"
|
||||||
|
SYSTEMD_DIR="/etc/systemd/system"
|
||||||
|
CONFIG_DIR="/etc/dhcp-whitelist"
|
||||||
|
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
echo "=== Installing DHCP Whitelist Service ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if Docker is installed
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo "Error: Docker is not installed"
|
||||||
|
echo "Please install Docker first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if docker-compose is installed
|
||||||
|
if ! command -v docker-compose &> /dev/null; then
|
||||||
|
echo "Error: docker-compose is not installed"
|
||||||
|
echo "Please install docker-compose first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create config directory
|
||||||
|
echo "Creating configuration directory: ${CONFIG_DIR}"
|
||||||
|
mkdir -p "${CONFIG_DIR}"
|
||||||
|
|
||||||
|
# Copy configuration files
|
||||||
|
echo "Copying configuration files..."
|
||||||
|
if [ -f "${PROJECT_DIR}/config/interface.conf" ]; then
|
||||||
|
cp "${PROJECT_DIR}/config/interface.conf" "${CONFIG_DIR}/"
|
||||||
|
echo " Copied interface.conf"
|
||||||
|
else
|
||||||
|
echo "Warning: config/interface.conf not found"
|
||||||
|
echo " Creating default interface.conf"
|
||||||
|
echo "enp0s13f0u3" > "${CONFIG_DIR}/interface.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${PROJECT_DIR}/config/whitelist.conf" ]; then
|
||||||
|
cp "${PROJECT_DIR}/config/whitelist.conf" "${CONFIG_DIR}/"
|
||||||
|
echo " Copied whitelist.conf"
|
||||||
|
else
|
||||||
|
echo "Warning: config/whitelist.conf not found"
|
||||||
|
echo " Creating empty whitelist.conf"
|
||||||
|
touch "${CONFIG_DIR}/whitelist.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set proper permissions
|
||||||
|
chmod 644 "${CONFIG_DIR}"/*.conf
|
||||||
|
echo "Configuration files installed to: ${CONFIG_DIR}"
|
||||||
|
|
||||||
|
# Create service file from template
|
||||||
|
echo
|
||||||
|
echo "Creating systemd service file..."
|
||||||
|
cat > "${SYSTEMD_DIR}/${SERVICE_NAME}.service" << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=DHCP Whitelist Service
|
||||||
|
After=network.target docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
WorkingDirectory=${PROJECT_DIR}
|
||||||
|
Environment="CONFIG_DIR=${CONFIG_DIR}"
|
||||||
|
|
||||||
|
# Pre-start: Build the image
|
||||||
|
ExecStartPre=/usr/bin/docker-compose build
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
ExecStart=/usr/bin/docker-compose up
|
||||||
|
|
||||||
|
# Stop the service
|
||||||
|
ExecStop=/usr/bin/docker-compose down
|
||||||
|
|
||||||
|
# Reload config by restarting containers
|
||||||
|
ExecReload=/usr/bin/docker-compose restart
|
||||||
|
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Service file created: ${SYSTEMD_DIR}/${SERVICE_NAME}.service"
|
||||||
|
|
||||||
|
# Create docker-compose override for service mode
|
||||||
|
echo
|
||||||
|
echo "Creating docker-compose override for service mode..."
|
||||||
|
cat > "${PROJECT_DIR}/docker-compose.override.yml" << EOF
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
dhcp-server:
|
||||||
|
volumes:
|
||||||
|
- ${CONFIG_DIR}:/config:ro
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
echo
|
||||||
|
echo "Reloading systemd daemon..."
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Installation Complete ==="
|
||||||
|
echo
|
||||||
|
echo "Configuration files location: ${CONFIG_DIR}"
|
||||||
|
echo " - ${CONFIG_DIR}/interface.conf"
|
||||||
|
echo " - ${CONFIG_DIR}/whitelist.conf"
|
||||||
|
echo
|
||||||
|
echo "Service management commands:"
|
||||||
|
echo " Start service: systemctl start ${SERVICE_NAME}"
|
||||||
|
echo " Stop service: systemctl stop ${SERVICE_NAME}"
|
||||||
|
echo " Enable on boot: systemctl enable ${SERVICE_NAME}"
|
||||||
|
echo " Check status: systemctl status ${SERVICE_NAME}"
|
||||||
|
echo " View logs: journalctl -u ${SERVICE_NAME} -f"
|
||||||
|
echo
|
||||||
|
echo "Or use make targets:"
|
||||||
|
echo " make service_up - Enable and start service"
|
||||||
|
echo " make service_down - Stop and disable service"
|
||||||
|
echo
|
||||||
|
echo "To start the service now, run: make service_up"
|
29
systemd/dhcp-whitelist.service
Normal file
29
systemd/dhcp-whitelist.service
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=DHCP Whitelist Service
|
||||||
|
After=network.target docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
WorkingDirectory=/opt/dhcp-whitelist
|
||||||
|
Environment="CONFIG_DIR=/etc/dhcp-whitelist"
|
||||||
|
|
||||||
|
# Pre-start: Build the image
|
||||||
|
ExecStartPre=/usr/bin/docker-compose build
|
||||||
|
|
||||||
|
# Start the service
|
||||||
|
ExecStart=/usr/bin/docker-compose up
|
||||||
|
|
||||||
|
# Stop the service
|
||||||
|
ExecStop=/usr/bin/docker-compose down
|
||||||
|
|
||||||
|
# Reload config by restarting containers
|
||||||
|
ExecReload=/usr/bin/docker-compose restart
|
||||||
|
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
7
test/test-client/Dockerfile
Normal file
7
test/test-client/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM alpine:3.19
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
iproute2 \
|
||||||
|
iputils
|
||||||
|
|
||||||
|
CMD ["/bin/sh"]
|
1
test/test-config/interface.conf
Normal file
1
test/test-config/interface.conf
Normal file
@ -0,0 +1 @@
|
|||||||
|
eth0
|
20
test/test-config/network.conf
Normal file
20
test/test-config/network.conf
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Network configuration for TEST DHCP server
|
||||||
|
# Uses 172.20.0.0/24 to avoid conflicts with common networks
|
||||||
|
|
||||||
|
# Network subnet (overrides auto-detection)
|
||||||
|
SUBNET=172.20.0.0
|
||||||
|
|
||||||
|
# Netmask in dotted notation
|
||||||
|
NETMASK=255.255.255.0
|
||||||
|
|
||||||
|
# DHCP range start offset from network base
|
||||||
|
RANGE_START_OFFSET=10
|
||||||
|
|
||||||
|
# DHCP range end offset from network base
|
||||||
|
RANGE_END_OFFSET=100
|
||||||
|
|
||||||
|
# Lease time in seconds (shorter for testing)
|
||||||
|
LEASE_TIME=300
|
||||||
|
|
||||||
|
# Max lease time in seconds
|
||||||
|
MAX_LEASE_TIME=600
|
1
test/test-config/whitelist.conf
Normal file
1
test/test-config/whitelist.conf
Normal file
@ -0,0 +1 @@
|
|||||||
|
02:42:ac:11:00:02
|
Loading…
x
Reference in New Issue
Block a user