PHPKnock is a web frontend for the port-knocking client fwknop. It lets you send a Single Packet Authorization (SPA) or port-knocking request to a remote server directly from a browser, without needing fwknop installed locally.
Why a web frontend? It lets you trigger port-knocking from any device with a browser. Typical use cases:
- Install it on an intranet server so staff can open ports on other servers in your network.
- Install it in your extranet so support staff can send SPA requests from home without installing fwknop on their own machines.
For background reading, see Wikipedia on port knocking and Single Packet Authorization.
- Single Packet Authorization via fwknop — no fwknop installation required on the client device
- Flexible destination configuration — free-text input, a fixed server set in config, or a named dropdown list
- Multi-host knocking — knock multiple servers in one submit (semicolon-separated or dropdown multi-select)
- CSRF protection — synchronizer token validated on every form submission
- Per-IP rate limiting — configurable attempt limit and time window to prevent abuse
- Destination validation — user-supplied hosts are validated as a proper IP address or RFC 1123 hostname before being passed to fwknop
- Audit log — every knock attempt (timestamp, source IP, destination, success/fail) is recorded to
log/audit.logby default - HMAC authentication — optional HMAC key support for Rijndael mode with configurable digest algorithm
- GPG encryption mode — asymmetric encryption via GPG keys as an alternative to Rijndael
- Encryption key handling — key is written to a temp file (
chmod 0600) and passed to fwknop via-G; never appears on the command line - Docker / FrankenPHP support — zero-config container deployment; all settings via environment variables
- No build tools or Composer required for production — plain PHP, no framework
- PHP >= 8.1 (with
proc_openenabled) - fwknop client 2.x
- A web server (Apache, Nginx, etc.) or Docker
- Composer (for autoloading, traditional install only)
Pull the latest image from GitHub Container Registry:
docker pull ghcr.io/teqneers/phpknock:latest
docker run -p 80:80 -e PHPKNOCK_SERVER_PORT=62201 ghcr.io/teqneers/phpknockNo config file is required. All settings are controlled via environment variables set in docker/compose.yaml.
-
Edit
docker/compose.yamland set the environment variables for your setup (see table below). -
Start the container from the
docker/directory:cd docker docker compose up -d
| Variable | Default | Description |
|---|---|---|
PHPKNOCK_SERVER_PORT |
62201 |
UDP port fwknopd listens on |
PHPKNOCK_ACCESS_PORT_LIST |
tcp/22 |
Ports to request access to (e.g. tcp/22,udp/53) |
PHPKNOCK_USE_HTTPS_ONLY |
false |
Redirect HTTP → HTTPS |
PHPKNOCK_ENCRYPTION_KEY |
(none) | Fixed encryption key; omit to let the user enter it in the browser |
PHPKNOCK_DESTINATION |
(none) | Fixed destination IP/hostname, a semicolon-separated list for multiple hosts, or a JSON object ({"10.0.0.1":"prod","10.0.0.2":"dev"}) for a dropdown; omit to show a free-text input |
PHPKNOCK_ERRORS_VERBOSE |
false |
Show fwknop command and raw output in the browser |
PHPKNOCK_ERRORS_LOG |
/web/log/error.log |
Path to error log file |
PHPKNOCK_AUDIT_LOG |
/web/log/audit.log |
Path to audit log file; set to empty string to disable |
PHPKNOCK_RATE_LIMIT |
10 |
Max knock attempts per IP per window (0 = disabled) |
PHPKNOCK_RATE_WINDOW |
60 |
Rate limit window in seconds |
PHPKNOCK_ENCRYPTION_MODE |
rijndael |
rijndael (AES symmetric) or gpg (GPG asymmetric) |
PHPKNOCK_HMAC_ENABLED |
false |
Enable HMAC authentication (Rijndael mode only) |
PHPKNOCK_HMAC_KEY |
(none) | Fixed HMAC key; omit to let the user enter it in the browser |
PHPKNOCK_HMAC_DIGEST_TYPE |
sha256 |
HMAC digest algorithm: md5, sha1, sha256, sha384, sha512 |
PHPKNOCK_GPG_RECIPIENT_KEY |
(none) | Server's GPG key ID (required for GPG mode) |
PHPKNOCK_GPG_SIGNER_KEY |
(none) | Client's GPG key ID (required for GPG mode) |
PHPKNOCK_GPG_HOME_DIR |
(none) | GPG keyring path; omit to use system default |
-
Clone or download PHPKnock somewhere outside your document root, for example
/opt/phpknock. -
Point your web server at the
app/public/subdirectory. Example Apache alias:Alias /phpknock /opt/phpknock/app/public
See Apache mod_alias for details.
-
Install dependencies:
cd app composer install -
Copy and configure the config file:
cp app/local_config.php.dist app/local_config.php vi app/local_config.php
-
Make the
tmp/andlog/directories writable by the web server user:chown www-data:www-data tmp log chmod 770 tmp log
-
Open
https://your-domain.com/phpknock/in a browser.
The project uses Docker Bake to orchestrate image builds. The bake file is at docker/docker-bake.hcl. Run all commands from the docker/ directory.
Dev image (no app code baked in — use with volume mounts for live editing):
docker buildx bake devProduction image (app code and Composer dependencies baked in):
docker buildx bakeTo override the image tag:
docker buildx bake --set 'default.tags=ghcr.io/teqneers/phpknock:0.3.0'cd app
composer install
./vendor/bin/phpunit
./vendor/bin/phpstan analyseBug reports and pull requests are welcome via the GitHub issue tracker.
Copyright (C) 2012-2026 by TEQneers GmbH & Co. KG
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

