libknock/libknock
GitHub: libknock/libknock
Stars: 2 | Forks: 0
# libknock
[](LICENSE)
[](LICENSE)
[](https://pkg.go.dev/github.com/libknock/libknock)
Source-available under BSL-1.1. Production use is allowed, but offering libknock or derivative works as a hosted or managed service is restricted before it converts to Apache-2.0 on 2030-05-15. See [LICENSE](LICENSE) and [license notes](docs/license.md).
Embeddable TCP pre-application authentication SDK for Go applications.
It authenticates a compact binary frame after a TCP connection is established and before the application protocol starts. After authentication succeeds, the caller receives a normal `net.Conn` and continues with its own protocol stack: plain TCP, TLS, HTTP, gRPC, custom RPC, agent connections, game protocols, database-like protocols, or any protocol built on top of `net.Conn`.
## Dependency model
libknock uses Go modules as the primary dependency path. The standard source archive is for normal Go module users. The companion `with-vendor` archive includes `vendor/`, `vendor/modules.txt`, `go.work`, and `go.work.sum` for offline review, reproducible local audit, LLM-assisted integration, and restricted CI. Use `go test -mod=vendor ./...` and `go vet -mod=vendor ./...` from the workspace root when validating the vendored archive. Keep `go.work` enabled; do not use `GOWORK=off` with workspace vendor mode.
For coding-agent and LLM-assisted work, start with [`llms.txt`](llms.txt), [`docs/llms.md`](docs/llms.md), and [`docs/agents/AGENTS.md`](docs/agents/AGENTS.md). These files describe the supported integration entry points, forbidden shortcuts, vendored-workspace expectations, and task-specific recipes.
## What it provides
- Authenticated `net.Listener` wrappers for server-side TCP services.
- Authenticated `net.Dialer` wrappers for clients.
- Standalone `ServerAuth` and `ClientAuth` functions for custom connection pipelines.
- Core root-package SDK entry points for TCP authentication.
- Optional knock, firewall, gate, and relay packages for advanced admission paths.
- Replay protection, timestamp validation, peer metadata, event hooks, and policy hooks.
- Optional Prometheus adapter in a separate module.
## Install
go get github.com/libknock/libknock
## Minimal server
package main
import (
"log"
"net"
"time"
libknock "github.com/libknock/libknock"
)
func main() {
secret := []byte("0123456789abcdef0123456789abcdef")
ln, err := net.Listen("tcp", ":9000")
if err != nil {
log.Fatal(err)
}
ln, err = libknock.NewListener(ln, libknock.ServerConfig{
ServerPort: 9000,
Secrets: libknock.NewStaticSecretResolver(map[string][]byte{
"client-001": secret,
}),
ReplayCache: libknock.NewMemoryReplayCache(5 * time.Minute),
})
if err != nil {
log.Fatal(err)
}
for {
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
go handleConn(conn)
}
}
`NewListener` returns startup validation errors directly and creates a listener-owned replay cache when one is not provided. `WrapListener` remains available as a convenience `net.Listener` wrapper; configuration errors surface from `Accept`. If you call the low-level `ServerAuth` function directly, provide a shared `ReplayCache` yourself.
## Minimal client
package main
import (
"context"
"net"
"time"
libknock "github.com/libknock/libknock"
)
func dial(ctx context.Context) (net.Conn, error) {
secret := []byte("0123456789abcdef0123456789abcdef")
d := libknock.Dialer{
Base: &net.Dialer{Timeout: 5 * time.Second},
Config: libknock.ClientConfig{
ClientID: "client-001",
Secret: secret,
ServerPort: 9000,
AuthTimeout: 3 * time.Second,
},
}
return d.DialContext(ctx, "tcp", "127.0.0.1:9000")
}
## Root package and advanced packages
The root package intentionally stays small. It exposes the common SDK path: `NewListener`, `WrapListener`, `WrapListenerE`, `ServerAuth`, `ClientAuth`, `Dialer`, `ServerConfig`, `ClientConfig`, `PeerInfo`, `NewServer`, `NewMemoryReplayCache`, and `NewStaticSecretResolver`.
Advanced admission features live in subpackages. Use `auth` for protocol selectors and advanced auth hooks, `gate` for listener composition modes, `relay` for proxy-style gateways, `firewall` for platform backends, `knock` for knock senders/listeners, and `observability` for gateway events.
import (
libknock "github.com/libknock/libknock"
"github.com/libknock/libknock/gate"
)
ln, err := gate.Listen(ctx, gate.Config{
Mode: gate.AuthOnly,
Auth: libknock.ServerConfig{
ServerPort: 9000,
Secrets: libknock.NewStaticSecretResolver(map[string][]byte{"client-001": secret}),
},
})
## TCP authentication protocols
`libknock` supports two TCP pre-application authentication protocols:
| Protocol | Name | Summary |
| --- | --- | --- |
| v1 | `tcp-auth-frame-v1` | Fixed binary frame with AEAD-sealed authentication metadata. |
| v2 | `tcp-auth-envelope-v2` | Sealed envelope with route hint support and fixed-size bucket padding. |
Both protocols provide client secret validation, timestamp window validation, replay protection, optional knock session binding, peer metadata, event hooks, and optional server proof.
Clients select a protocol with `ClientConfig.Protocol`. Servers select a preferred protocol with `ServerConfig.Protocol` and accepted protocols with `ServerConfig.AcceptProtocols`. The default TCP authentication protocol is `tcp-auth-envelope-v2`.
## UDP knock frame
UDP knock uses a binary datagram frame with an AEAD-sealed payload. The same UDP frame family is used by:
- `udp`
- `udp-seq`
- `udp-passive`
- `udp-passive-seq`
The frame carries authenticated metadata such as client identity hash, method, timestamp, protected port, optional session ID, sequence fields, and extensions.
## Capability status
| Capability | Status |
| --- | --- |
| Authenticated listener | stable |
| Dialer | stable |
| TCP auth frame v1 | stable |
| TCP auth envelope v2 | release candidate |
| UDP knock / UDP sequence | release candidate |
| Knock-auth-only gate | release candidate |
| Firewall-backed gates | platform-specific / not fully validated |
| UDP passive knock | experimental / not fully validated |
| TCP SYN knock | experimental / not fully validated |
| Windows packet capture integrations | experimental / not fully validated |
| macOS passive capture integrations | experimental / not fully validated |
## Gate modes
| Mode | Description |
| --- | --- |
| `auth-only` | TCP connections must pass libknock TCP authentication before the application accepts them. |
| `knock-auth-only` | TCP stays open at the transport layer, but clients must knock first and then pass TCP authentication before the application accepts them. No firewall rules are changed. |
| `knock-firewall-auth` | A successful knock opens a short firewall window, then TCP authentication must pass. |
| `knock-firewall-only` | A successful knock opens a short firewall window and the application receives the matching TCP connection. |
`knock-auth-only` is not a port-hiding mode: SYN scans can still report the TCP port as open, but unauthenticated clients cannot reach the application protocol. It does not require root or `CAP_NET_ADMIN`, is useful in containers, restricted VPS instances, Windows/macOS deployments, and adds a short-lived knock session requirement on top of `auth-only`. It does not replace `knock-firewall-auth` when firewall-backed port gating is required.
`knock-firewall-auth` and `knock-firewall-only` require a real firewall backend. `auth-only` and `knock-auth-only` can use `firewall.Noop{}`.
Repeated valid knocks renew the firewall allow window from the latest accepted knock; stale timers from earlier knocks do not revoke the renewed lease.
## Relay gateway
`relay.Gateway` is an optional TCP forwarding component. It listens on one address, performs libknock authentication and optional knock/firewall handling, then connects to an upstream TCP service.
gw := relay.Gateway{
Listen: ":9000",
Upstream: "127.0.0.1:19000",
Auth: serverAuthConfig,
Firewall: firewall.Noop{},
}
err := gw.Run(ctx)
Use relay when the protected upstream is a separate TCP service rather than an application that embeds `libknock` directly.
## Documentation
- Coding agents: [docs/agents/AGENTS.md](docs/agents/AGENTS.md), [integration guide](docs/agents/integration-guide.md), [anti-patterns](docs/agents/anti-patterns.md), [recipes](docs/agents/recipes/)
- Examples: [examples/README.md](examples/README.md)
- [Documentation index](docs/README.md)
- [Getting started](docs/getting-started.md)
- [Use cases](docs/use-cases.md)
- [API reference](docs/api.md)
- [API surface and compatibility](docs/api-surface.md)
- [Compatibility policy](COMPATIBILITY.md)
- [Protocols](docs/protocols.md)
- [Gate and relay](docs/gate-and-relay.md)
- [Knock methods](docs/knock-methods.md)
- [Firewall backends](docs/firewall.md)
- [Observability](docs/observability.md)
- [Production deployment](docs/production.md)
- [Troubleshooting](docs/troubleshooting.md)
- [Known limitations](docs/known-limitations.md)
- [Validation matrix](docs/validation-matrix.md)
- [Performance notes](docs/performance.md)
- [Roadmap](docs/roadmap.md)
- [Release notes](docs/release-notes.md)
- [Release checklist](docs/release-checklist.md)
- [Development guide](docs/development.md)
## Firewall note
## Repository layout
protocol/ binary protocol codecs and cryptographic helpers
auth/ server/client authentication, replay cache, secret resolvers
netx/ listener, dialer, buffered connection behavior
knock/ knock senders and listeners
firewall/ firewall backend interfaces and implementations
gate/ SDK listener composition modes
relay/ optional TCP relay gateway
policy/ limiter and ban policy adapters
observability/ event interfaces and metrics adapters
cmd/knock-proxy command entrypoint
examples/ integration examples
## Test
scripts/check.sh
For a shorter edit loop:
go test ./...
go vet ./...
go test -race ./auth ./firewall ./knock ./netx ./policy ./protocol ./relay
Prometheus and gRPC integration checks are separate modules:
go -C observability/prometheus test ./...
go -C test/integration/grpc test ./...
## Compatibility command
`cmd/knock-proxy` is a compatibility caller for simple client/server proxy deployments. It is not the full historical knock-proxy product and does not host every optional integration. Embedding applications should prefer the SDK packages directly when they need custom lifecycle, metrics, policy, or application-protocol handling.
标签:EVTX分析