Wstunnel Configuration
InterLink's wstunnel feature enables secure port exposure for pods with containers that have exposed ports. This feature automatically creates websocket tunnel infrastructure outside the virtual node, allowing external access to pod services without requiring VPN connectivity.
Overview
The wstunnel integration provides:
- Automatic Infrastructure Creation: Deployment, Service, and Ingress resources
- Secure Tunneling: WebSocket-based tunneling with random password protection
- Port Forwarding: Automatic forwarding of all exposed container ports
- External Access: Ingress-based external access with customizable DNS
- Resource Management: Automatic cleanup when pods are deleted
Wstunnel is disabled by default and must be explicitly enabled in the configuration.
Configuration
Virtual Kubelet Configuration
Add the wstunnel configuration to your Virtual Kubelet config file:
# VirtualKubeletConfig.yaml
InterlinkURL: "http://interlink-api:3000"
InterlinkPort: "3000"
VerboseLogging: true
ErrorsOnlyLogging: false
# Network configuration
Network:
EnableTunnel: true # Enable wstunnel feature
WildcardDNS: "tunnel.example.com" # DNS domain for ingress
WstunnelTemplatePath: "/etc/templates/custom.yaml" # Optional: custom template path
# Other configuration...
Resources:
CPU: "10"
Memory: "20Gi"
Pods: "100"
Configuration Options
Option | Type | Required | Default | Description |
---|---|---|---|---|
EnableTunnel | bool | No | false | Enable/disable wstunnel feature |
WildcardDNS | string | Yes* | "" | DNS domain for ingress hostnames |
WstunnelTemplatePath | string | No | "" | Path to custom wstunnel template |
*Required when EnableTunnel
is true
How It Works
Automatic Trigger
Wstunnel infrastructure is automatically created when:
Network.EnableTunnel
is set totrue
- Pod has containers with exposed ports
- Pod does NOT have
interlink.eu/pod-vpn
annotation
Resource Creation
For each qualifying pod, interLink creates:
- Deployment: Runs wstunnel server with WireGuard
- Service: Exposes websocket and forwarded ports
- Ingress: Provides external access via DNS
Naming Convention
Resources are named using the pattern: {pod-name}-wstunnel
Example: Pod my-web-app
→ Resources my-web-app-wstunnel
Template System
Default Template
InterLink includes an embedded default template that creates:
# Deployment with wstunnel server
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.Name}}
namespace: {{.Namespace}}
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: {{.Name}}
template:
metadata:
labels:
app.kubernetes.io/component: {{.Name}}
spec:
containers:
- name: wireguard
image: ghcr.io/dciangot/dciangot/wg:v0.2
command: ["bash", "-c"]
args:
- ./wstunnel server --log-lvl DEBUG --dns-resolver-prefer-ipv4 --restrict-http-upgrade-path-prefix {{.RandomPassword}} ws://0.0.0.0:8080
ports:
- containerPort: 8080
name: webhook
protocol: TCP
- containerPort: 51820
name: vpn
protocol: UDP
{{- range .ExposedPorts}}
- containerPort: {{.Port}}
name: {{.Name}}
protocol: {{.Protocol}}
{{- end}}
resources:
requests:
cpu: 100m
memory: 90Mi
nodeSelector:
kubernetes.io/os: linux
---
# Service for port exposure
apiVersion: v1
kind: Service
metadata:
name: {{.Name}}
namespace: {{.Namespace}}
spec:
type: ClusterIP
selector:
app.kubernetes.io/component: {{.Name}}
ports:
- port: 8080
targetPort: 8080
name: ws
{{- range .ExposedPorts}}
- port: {{.Port}}
targetPort: {{.TargetPort}}
name: {{.Name}}
protocol: {{.Protocol}}
{{- end}}
---
# Ingress for external access
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{.Name}}
namespace: {{.Namespace}}
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/server-snippets: |
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: ws-{{.Name}}.{{.WildcardDNS}}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{.Name}}
port:
number: 8080
Template Variables
The template system provides these variables:
Variable | Type | Description | Example |
---|---|---|---|
{{.Name}} | string | Resource name | my-web-app-wstunnel |
{{.Namespace}} | string | Pod namespace | default |
{{.RandomPassword}} | string | Security password | a1b2c3d4e5f6... |
{{.WildcardDNS}} | string | DNS domain | tunnel.example.com |
{{.ExposedPorts}} | []PortMapping | Port mappings | See below |
Port Mapping Structure
type PortMapping struct {
Port int32 // Container port number
TargetPort int32 // Target port (usually same as Port)
Name string // Port name
Protocol string // Protocol (TCP/UDP)
}
Custom Templates
You can provide custom templates by:
-
Creating a custom template file:
# /etc/templates/custom-wstunnel.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.Name}}
namespace: {{.Namespace}}
spec:
# Your custom configuration... -
Configuring the template path:
Network:
EnableTunnel: true
WildcardDNS: "tunnel.example.com"
WstunnelTemplatePath: "/etc/templates/custom-wstunnel.yaml" -
Mounting the template in the Virtual Kubelet deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: virtual-kubelet
spec:
template:
spec:
containers:
- name: virtual-kubelet
volumeMounts:
- name: wstunnel-template
mountPath: /etc/templates/custom-wstunnel.yaml
subPath: custom-wstunnel.yaml
volumes:
- name: wstunnel-template
configMap:
name: wstunnel-template
Pod Configuration
Basic Pod with Exposed Ports
apiVersion: v1
kind: Pod
metadata:
name: web-server
namespace: default
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
restartPolicy: Never
Pod with Custom Timeout
apiVersion: v1
kind: Pod
metadata:
name: web-server
namespace: default
annotations:
interlink.virtual-kubelet.io/wstunnel-timeout: "5m"
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
name: http
restartPolicy: Never
Disabling Wstunnel for Specific Pods
apiVersion: v1
kind: Pod
metadata:
name: web-server
namespace: default
annotations:
interlink.eu/pod-vpn: "true" # Use VPN instead of wstunnel
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
name: http
restartPolicy: Never
DNS Configuration
Wildcard DNS Setup
Configure your DNS provider to point wildcard subdomains to your ingress controller:
*.tunnel.example.com → your-ingress-controller-ip
Generated Hostnames
For each pod, the system generates hostnames using the pattern:
ws-{pod-name}-wstunnel.{WildcardDNS}
Examples:
- Pod
web-server
→ws-web-server-wstunnel.tunnel.example.com
- Pod
api-gateway
→ws-api-gateway-wstunnel.tunnel.example.com
Client Connection Commands
Automatic Command Generation
When wstunnel is enabled, interLink automatically generates a client command annotation for each pod with exposed ports. This annotation contains the complete command needed to connect to the pod's services from a remote location.
Annotation: interlink.eu/wstunnel-client-commands
Example
For a pod with exposed ports, the annotation will contain:
curl -L https://github.com/erebe/wstunnel/releases/latest/download/wstunnel-linux-x64 -o wstunnel && chmod +x wstunnel
./wstunnel client --http-upgrade-path-prefix a1b2c3d4e5f6 -R tcp://[::]:8080:localhost:8080 -R tcp://[::]:9090:localhost:9090 ws://ws-my-pod-wstunnel.tunnel.example.com:80
Command Structure
- Download: Downloads the latest wstunnel client binary
- Connect: Establishes the websocket tunnel with:
--http-upgrade-path-prefix
: Unique random password for authentication-R tcp://[::]:PORT:localhost:PORT
: Port forwarding rules (one per exposed port)ws://ENDPOINT:80
: Websocket endpoint using generated hostname
Retrieving the Command
# Get the complete client command for a pod
kubectl get pod my-pod -o jsonpath='{.metadata.annotations.interlink\.eu/wstunnel-client-commands}'
# Or view all annotations
kubectl describe pod my-pod
Multiple Ports
When a pod exposes multiple ports, all ports are included in a single command with multiple -R
options:
# Pod with ports 8080, 9090, and 3000
./wstunnel client --http-upgrade-path-prefix randompassword \
-R tcp://[::]:8080:localhost:8080 \
-R tcp://[::]:9090:localhost:9090 \
-R tcp://[::]:3000:localhost:3000 \
ws://ws-my-pod-wstunnel.tunnel.example.com:80
Security Considerations
Authentication
- Each wstunnel instance uses a unique random password
- Passwords are generated using cryptographically secure random numbers
- Access is restricted via the
restrict-http-upgrade-path-prefix
parameter
Network Security
- WebSocket connections are established over HTTP/HTTPS
- Consider using TLS termination at the ingress level
- Implement network policies to restrict traffic if needed
Resource Security
- Wstunnel resources are automatically cleaned up when pods are deleted
- Resources are labeled for easy identification and management
- Consider implementing RBAC policies for wstunnel resources
Monitoring and Troubleshooting
Checking Wstunnel Status
# List all wstunnel resources
kubectl get deployment,service,ingress -l interlink.virtual-kubelet.io/type=wstunnel
# Check specific pod's wstunnel resources
kubectl get deployment,service,ingress -l app.kubernetes.io/component=my-pod-wstunnel
# Check wstunnel pod logs
kubectl logs -l app.kubernetes.io/component=my-pod-wstunnel
Common Issues
-
Pod IP not assigned
# Check pod status
kubectl get pod my-pod -o yaml | grep -A 10 status
# Check virtual kubelet logs
kubectl logs -l nodeName=virtual-kubelet -
Wstunnel timeout errors
# Increase timeout annotation
kubectl annotate pod my-pod interlink.virtual-kubelet.io/wstunnel-timeout=10m -
DNS resolution issues
# Test DNS resolution
nslookup ws-my-pod-wstunnel.tunnel.example.com
# Check ingress configuration
kubectl get ingress my-pod-wstunnel -o yaml -
Template errors
# Check virtual kubelet logs for template parsing errors
kubectl logs -l nodeName=virtual-kubelet | grep -i template
Debug Commands
# Get pod with full details
kubectl get pod my-pod -o yaml
# Check wstunnel deployment
kubectl describe deployment my-pod-wstunnel
# Test websocket connection
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: test" -H "Sec-WebSocket-Version: 13" \
http://ws-my-pod-wstunnel.tunnel.example.com/your-random-password
# Check service endpoints
kubectl get endpoints my-pod-wstunnel
Best Practices
Configuration
- Set appropriate
WildcardDNS
that you control - Use custom templates for specific requirements
- Configure reasonable timeout values based on your infrastructure
Security
- Regularly rotate ingress TLS certificates
- Implement network policies to restrict access
- Monitor wstunnel resource usage
Operations
- Monitor DNS resolution and ingress health
- Set up alerts for wstunnel pod failures
- Regular cleanup of orphaned resources
Performance
- Size wstunnel pods appropriately for your traffic
- Use appropriate resource limits in custom templates
- Consider using NodePort or LoadBalancer services for high traffic
Migration Guide
From VPN to Wstunnel
-
Update Virtual Kubelet configuration:
Network:
EnableTunnel: true
WildcardDNS: "tunnel.example.com" -
Remove VPN annotations from pods:
kubectl annotate pod my-pod interlink.eu/pod-vpn-
-
Restart pods to trigger wstunnel creation:
kubectl delete pod my-pod
kubectl apply -f my-pod.yaml
From Wstunnel to VPN
-
Add VPN annotation to pods:
metadata:
annotations:
interlink.eu/pod-vpn: "true" -
Restart pods to use VPN instead of wstunnel
Advanced Configuration
Custom Ingress Controller
# Custom template with different ingress controller
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{.Name}}
namespace: {{.Namespace}}
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
tls:
- hosts:
- ws-{{.Name}}.{{.WildcardDNS}}
secretName: {{.Name}}-tls
rules:
- host: ws-{{.Name}}.{{.WildcardDNS}}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{.Name}}
port:
number: 8080
Resource Limits
# Custom template with resource limits
spec:
template:
spec:
containers:
- name: wireguard
resources:
requests:
cpu: 100m
memory: 90Mi
limits:
cpu: 500m
memory: 256Mi
Multiple Ingress Rules
# Multiple ingress rules for different services
spec:
rules:
- host: ws-{{.Name}}.{{.WildcardDNS}}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{.Name}}
port:
number: 8080
{{- range .ExposedPorts}}
- host: {{.Name}}-{{.Port}}.{{.WildcardDNS}}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{.Name}}
port:
number: {{.Port}}
{{- end}}
Related Documentation
- Pod Annotations Reference - Pod annotation documentation
- Deploy interLink - Basic deployment guide
- API Reference - REST API documentation
- mTLS Deployment - Secure communication setup