https://github.com/thiswillbeyourgithub/knockd_rotator
Enhances knockd security with automatically rotating port knocking sequences to prevent replay attacks.
https://github.com/thiswillbeyourgithub/knockd_rotator
Last synced: 7 months ago
JSON representation
Enhances knockd security with automatically rotating port knocking sequences to prevent replay attacks.
- Host: GitHub
- URL: https://github.com/thiswillbeyourgithub/knockd_rotator
- Owner: thiswillbeyourgithub
- License: gpl-3.0
- Created: 2025-04-12T17:36:58.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-04-28T14:41:53.000Z (10 months ago)
- Last Synced: 2025-06-09T07:56:09.058Z (9 months ago)
- Language: Python
- Homepage:
- Size: 98.6 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Knockd Rotator
A security-enhanced port knocking system with rotating knock sequences.
## Overview
This project provides tools to enhance the security of [knockd](https://github.com/jvinet/knock) port knocking by automatically rotating knock sequences based on time periods. This prevents replay attacks and significantly improves the security of your port knocking setup.
The rotating sequence is deterministically generated based on:
- The timestamp at the beginning of the current time period (UNIX seconds floored to a multiple of the period length)
- A unique service name
- A pre-shared secret
This means that legitimate clients and servers will independently generate the same sequence for each time period, while attackers cannot predict future sequences without knowing the secret.
## How It Works
Both the server and client independently generate the same knock sequence for a given time period:
1. The client uses `knockd_rotator_client.py` to generate the current sequence and performs the knocks
2. The server runs `knockd_rotator_server.py` periodically (via systemd timer) to:
- Update `/etc/knockd.conf` with the current sequences
- Restart the knockd service to apply changes
- Sometimes schedule an anticipated run to ensure timely updates at period boundaries
The shared sequence generation algorithm ensures both sides produce identical sequences without any communication between them.
## Components
### knockd_rotator_client.py (v1.0.1)
A lightweight client-side tool that both generates and executes knock sequences:
- Runs on minimal environments like [Termux](https://termux.dev/) on Android
- Requires only Python 3 standard library
- Supports abbreviated commands (e.g. "gene" for "generate", "knock" for "knock")
- Supports two modes:
- **Generate mode**: Creates the sequence string for a service
- Usage: `./knockd_rotator_client.py generate [--offset ]`
- **Knock mode**: Performs the actual port knocking against a target host
- Usage: `./knockd_rotator_client.py knock [--offset ]`
- Automatically appends "_ROTATOR" to service names if not already present
- Supports time period offsets to generate past or future sequences
- Note: A Zsh reimplementation of the client is available in `knockd_rotator_client.zsh`. It has not been as thoroughly tested as the Python script but should function similarly.
### knockd_rotator_server.py (v1.0.1)
A server-side tool that:
- Scans `/etc/knockd.conf` for sections ending with `_ROTATOR`
- Updates those sections with freshly generated sequences
- Restarts the knockd service after updating
- Verifies that the service is running correctly after restart
- Intelligently schedules an additional run to handle period transitions
- Supports dry-run mode for testing
- Usage: `./knockd_rotator_server.py [--dry-run] [--config /path/to/knockd.conf]`
## Configuration
The system is configured through environment variables:
- `KNOCKD_ROTATOR_LENGTH`: Number of ports in the knock sequence (default: 10)
- `KNOCKD_ROTATOR_SECRET`: The shared secret used to generate sequences (required, minimum 10 characters). You can generate a strong secret using: `openssl rand -hex 64`
- `KNOCKD_ROTATOR_PROTO_MODULO`: Controls TCP/UDP protocol selection:
- When `KNOCKD_ROTATOR_PROTO_MODULO = 0` (default): All knocks use TCP protocol
- When `KNOCKD_ROTATOR_PROTO_MODULO > 0`: For each port of the sequence, the port modulo `KNOCKD_ROTATOR_PROTO_MODULO` determines protocol (even = TCP, odd = UDP)
- `KNOCKD_ROTATOR_PERIOD_MODULO`: Controls how frequently the sequence changes, in seconds (default: 21600, which is 6 hours)
- `KNOCKD_ROTATOR_SERVER_INTERVAL`: How often the server script is expected to run, in seconds (default: 3600, which is 1 hour). This is used to know if we should fork the process to anticipate the next period.
- `KNOCKD_ROTATOR_PORTS`: List of ports or port ranges to use for knock sequences (default: "2000-65536")
- Format: Comma-separated list of either single ports or ranges (e.g., "2000-3000,4000,5000-6000")
- Both ends of ranges are included
- At least 2 ports must be specified, with no duplicates.
Port numbers are generated in the range 2000-65536 by default to avoid requiring elevated privileges. You can adjust this with the `KNOCKD_ROTATOR_PORTS` environment variable if needed (for example, if certain port ranges are blocked by firewalls or require special permissions). Using 3 or fewer ports will significantly reduce security and generate a warning.
## Example knockd.conf Section
```
[ssh_ROTATOR]
sequence = 12345:tcp,23456:tcp,34567:tcp,45678:tcp,56789:tcp,65432:tcp
seq_timeout = 15
tcpflags = syn
start_command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 30
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
```
## Setup
1. Install knockd on your server
2. Configure your knockd.conf with sections ending in `_ROTATOR`
3. Set up the systemd service and timer:
- Copy `knockd_rotator.service` and `knockd_rotator.timer` to `/etc/systemd/system/`
- Enable and start the timer: `systemctl enable --now knockd_rotator.timer`
4. Distribute the client script to your devices:
- Copy `knockd_rotator_client.py` to your client devices
- Set the same environment variables on clients as on the server
## Advanced Features
- **Period Boundary Handling**: The server automatically schedules an additional run at period transitions to ensure timely sequence updates
- **Service Verification**: Confirms knockd is running properly after configuration changes
- **Multiple Services**: Support for multiple different rotator services in one config file
- **Time Period Offsets**: Generate past or future sequences with the `--offset` parameter. This is useful to generate sequences that were valid at passed times if you know that the server side script failed to run for some reason.
## Notes
- I am *obviously* not a security expert.
- This works fine using `ufw` in my tests.
- I don't advise using a very frequent rotation unless you don't use knockd's `start_command` and `stop_command` because if it happens between the two you might end up in a compromised state.
- The code is minimal on purpose so that you just have to copy the `knockd_rotator_client.py` file around and the env variables.
- User @rdmitry0911 made [a pull request](https://github.com/jvinet/knock/pull/76) to include a somewhat similar feature directly in knockd. Their implementation is based on OTP whereas this project uses pure Python for the sequence generation.
- Knockd already includes a feature to have knock sequences taken from a text file and used only once at a time. However, I wanted to be able to perform knocks from multiple clients without issues, so I created this solution which deterministically generates the same sequence across all clients for a given time period.
- Why not use HMACs or other counter-based approaches? This time-based key setup allows clients and servers to operate without having to sync counters between them. All clients are equal, and the setup is as simple as possible while still providing robust security.
- You might also be interested in my other project [fowlrot.sh](https://github.com/thiswillbeyourgithub/fowlrot.sh), which applies a similar rotating secret concept to fail2ban jails.
- If you are looking for a dedicated Android client, support for this rotator logic has been requested in the [knockonports app issue tracker](https://github.com/impalex/knockonports/issues/26).
- You can run the test suite to verify everything is working correctly: `python -m pytest test_knockd_rotator_client.py -v`
This project was developed with the assistance of [aider.chat](https://github.com/Aider-AI/aider/issues).