Architecture
Deep dive into kftray's internal component structure, proxy server, and security model.
This page covers kftray's internal component structure for contributors, advanced users, and anyone troubleshooting complex setups.
Component structure
| Component | Role |
|---|---|
kftray-commons | Shared types, configuration models, and utilities used across all components |
kftray-portforward | Core port-forwarding logic, Kubernetes API client, TCP/UDP protocol handling |
kftray-tauri | Desktop interface built with Tauri, system tray integration, GUI state management |
kftui | Terminal interface built with Ratatui, keyboard navigation, TUI rendering |
kftray-helper | Privilege escalation helper for low-port binding and hostfile modification |
kftray-server | UDP-to-TCP proxy server deployed in Kubernetes for UDP forwarding |
kftray-http-logs | HTTP request/response parser and logger for traffic inspection |
All components share the same SQLite database for configuration storage, enabling seamless switching between desktop and terminal interfaces.
Shared state
kftray stores all configuration in a SQLite database at ~/.kftray/kftray.db:
-- Simplified schema
CREATE TABLE configs (
id INTEGER PRIMARY KEY,
alias TEXT NOT NULL,
context TEXT NOT NULL,
namespace TEXT NOT NULL,
service TEXT,
pod TEXT,
local_port INTEGER NOT NULL,
remote_port INTEGER NOT NULL,
protocol TEXT DEFAULT 'tcp',
-- ... additional fields
);Both interfaces read and write to this database concurrently. SQLite's locking mechanism prevents corruption, but active port forwards are tracked in-memory by the process that started them. This is why you cannot stop a forward from a different interface than the one that started it.
TCP forwarding architecture
Direct TCP forwarding uses the Kubernetes API's port-forward subprotocol:
This path is identical to kubectl port-forward and has comparable performance. The kftray-portforward component maintains a persistent WebSocket connection to the Kubernetes API server and multiplexes multiple TCP connections over it.
See port forwarding configuration for usage examples.
UDP forwarding architecture
UDP forwarding requires protocol conversion because Kubernetes port-forward only supports TCP:
The kftray-server proxy runs as a deployment in the target namespace. kftray automatically deploys it when you create a UDP forward and removes it when no UDP forwards remain active.
This architecture adds latency compared to native UDP (typically 5-20ms) due to the TCP conversion overhead. See proxy forwarding for configuration details.
Proxy server deployment
When you create a UDP forward, kftray:
Checks if kftray-server deployment exists in the target namespace.
If not, creates deployment with minimal resource requests (10m CPU, 32Mi memory).
Waits for pod to become ready (typically 2-5 seconds).
Establishes TCP port-forward to the proxy pod.
Begins UDP-to-TCP conversion.
The proxy server lifecycle:
- Auto-deployment: created on first UDP forward in a namespace
- Shared: multiple UDP forwards reuse the same proxy pod
- Cleanup: deployment deleted when last UDP forward stops
Proxy persistence
If kftray crashes or is killed forcefully, the proxy deployment may remain in the cluster. It consumes minimal resources but can be manually deleted with kubectl delete deployment kftray-server -n <namespace>.
HTTP logging implementation
HTTP logging uses a streaming parser to extract requests and responses from TCP traffic:
TCP stream → HTTP parser → Request/Response objects → JSON log filesThe kftray-http-logs component:
Intercepts TCP traffic between local app and Kubernetes API.
Parses HTTP/1.1 requests and responses in real-time.
Generates trace IDs to correlate requests with responses.
Writes structured JSON logs to ~/.kftray/http_logs/.
Log format:
{
"timestamp": "2026-02-09T10:30:45.123Z",
"trace_id": "abc123",
"direction": "request",
"method": "GET",
"path": "/api/users",
"headers": {"Host": "api.example.com"},
"body": null
}HTTP logging adds 1-5ms latency per request due to parsing overhead. Disable it for performance-critical forwards.
Helper component
The kftray-helper binary handles operations requiring elevated privileges:
- Low-port binding: ports below 1024 on macOS/Linux require root
- Hostfile modification:
/etc/hostsupdates for custom domain mapping
When you bind to a port below 1024, kftray:
Prompts for administrator password (macOS/Linux) or UAC elevation (Windows).
Launches kftray-helper with elevated privileges.
Helper binds to the privileged port.
Helper forwards traffic to kftray running as your user.
Helper drops privileges after binding.
This privilege separation ensures kftray itself never runs as root, reducing security risk.
Security model
Credential management
kftray uses the same kubeconfig files as kubectl:
- Default location:
~/.kube/config - Custom location:
KUBECONFIGenvironment variable - Multiple files: colon-separated paths in
KUBECONFIG
Credentials are never stored in kftray's database. All authentication happens through the Kubernetes client library, which reads kubeconfig files at runtime.
For cloud providers (GKE, EKS, AKS), kftray invokes the same credential helpers as kubectl:
- GKE:
gcloudCLI - EKS:
awsCLI withaws-iam-authenticator - AKS:
azCLI
See CLI reference for environment variable configuration.
Network security
By default, kftray binds to 127.0.0.1, making forwards accessible only from the local machine:
{
"local_address": "127.0.0.1",
"local_port": 8080
}Binding to 0.0.0.0 exposes the forward to your entire network:
{
"local_address": "0.0.0.0",
"local_port": 8080
}Network exposure
Binding to 0.0.0.0 allows anyone on your network to access the forwarded service. Use this only when necessary and document the reason in your configuration.
Follow security best practices when configuring credential storage and network access.
Privilege separation
kftray follows the principle of least privilege:
- Main process: runs as your user, no elevated privileges
- Helper process: runs with elevated privileges only when needed, drops privileges after binding
- Proxy server: runs in Kubernetes with minimal RBAC permissions
The helper binary is signed and verified on macOS to prevent tampering.