GitHub - PepperDev/totpgate: Lightweight SPA TOTP port knocking daemon · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
PepperDev
totpgate
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
master
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>42 Commits<br>42 Commits
.github/workflows
.github/workflows
man
man
src
src
test
test
.gitignore
.gitignore
AGENTS.md
AGENTS.md
BUG_PREVENTION.md
BUG_PREVENTION.md
DOMAIN.md
DOMAIN.md
LICENSE
LICENSE
Makefile
Makefile
README.md
README.md
TODO.md
TODO.md
View all files
Repository files navigation
totpgate
Single Packet Authorization via TOTP — a lightweight port knocking daemon<br>that listens on UDP for a valid TOTP and, upon matching, temporarily opens a<br>TCP port via direct netlink firewall manipulation.
No external binaries, no shared libraries — just a statically linked<br>binary speaking netlink directly to the kernel.
Why
Traditional port knocking sequences are predictable (fixed port order) and<br>replayable. TOTP-based single-packet authorization replaces the sequence with<br>a time-based one-time password, making each grant unique and replay-proof.
Design
┌──────────┐ UDP/TOTP ┌──────────────┐ netlink ┌──────────┐<br>│ client │ ────────────→ │ totpgated │ ───────────→ │ kernel │<br>│ (CLI) │ │ (daemon) │ │ (nftables)│<br>└──────────┘ └──────────────┘ └──────────┘
Client sends a single UDP packet containing a TOTP value.
Daemon validates the TOTP against the configured shared secret.
On success the daemon inserts a temporary nftables rule that permits the<br>client's IP to reach the target TCP port.
The rule auto-expires after a configurable idle timeout.
Build
Requirements
musl-gcc recommended (falls back to cc; any C99 compiler works)
Linux kernel headers (for linux/netfilter.h, libnl-ish macros)
indent (for code-style checks)
Commands
make # build daemon and client<br>make test # build & run unit tests<br>make style # reformat source to project style<br>make coverage # generate coverage report (requires gcov)<br>make clean # remove build artefacts
Output lands in bin/.
Coverage gate
make coverage
All TODO sections require ≥ 80 % line coverage and zero compiler<br>warnings before the section is considered complete.
Usage
totpgated --port 2222 --target-port 22 --secret "JBSWY3DPEHPK3PXP" --timeout 30<br>totpgated --port 2222 --target-port 22 --secret-file /etc/totpgate.key --foreground<br>totpgated --port 0.0.0.0:2222 --port 192.168.1.1:2223 --interface eth0 --secret "JBSWY3DPEHPK3PXP"<br>totpgate --secret "hex:48656c6c6f" --port 2222 server.example.com
The daemon listens on UDP --port for a valid TOTP. On match the<br>sender's IP is allowed to open a TCP connection to --target-port for --timeout seconds.<br>--port may be given multiple times to listen on different addresses/ports,<br>and --interface restricts firewall rules to a single network interface.
When totpgated starts it flushes any stale rules from a prior session,<br>inserts a permanent ct state established,related accept rule, and installs<br>a silent tcp dport drop for unmatched SYN packets.
See the man pages (totpgated.1, totpgate.1) or --help for full options.
Project map
├── AGENTS.md — agent / AI guidelines<br>├── DOMAIN.md — business rules & entities<br>├── TODO.md — tracked task list<br>├── BUG_PREVENTION.md— recurring-bug checklist<br>├── Makefile<br>├── src/ — source code<br>│ ├── main.c — daemon entrypoint, event loop, CLI parsing<br>│ ├── client.c / h — CLI client tool<br>│ ├── auth.c / .h — auth packet parse / build<br>│ ├── encode.c / h — base32, base64, hex decode<br>│ ├── totp.c / .h — TOTP token validation<br>│ ├── sha1.c / .h — SHA-1 hash<br>│ ├── hmac.c / .h — HMAC-SHA1<br>│ ├── netlink.c / h— nftables rule management via netlink<br>│ ├── udp.c / .h — UDP socket bind / send / recv<br>│ ├── privdrop.c/h— privilege drop & seccomp filter<br>│ ├── ratelimit.c/h— per-IP rate limiting with backoff<br>│ ├── seccomp.c / h— seccomp-BPF syscall filter<br>│ └── util.c / .h — logging helpers<br>├── test/ — unit tests (no third-party test libs)<br>└── bin/ — build artifacts
License
MIT
About
Lightweight...