IPMan is a Kubernetes operator that simplifies the management of IPSec connections, enabling secure communication between your Kubernetes workloads and the outside world. It automates the setup and configuration of IPSec VPN tunnels using StrongSwan, making it easy to expose pods to external networks securely.
# Add the repository
helm repo add ipman https://dialohq.github.io/ipman
# Install the chart
helm install ipman ipman/ipman -n ipman-system --create-namespace
IPMan requires a secret for IPSec authentication:
kubectl create secret generic ipsec-secret -n default --from-literal=example=yourpresharedkey
Create an IPSecConnection Custom Resource (CR) to establish a VPN connection:
apiVersion: ipman.dialo.ai/v1
kind: IPSecConnection
metadata:
name: example-connection
namespace: ipman-system
spec:
name: "example"
remoteAddr: "192.168.1.2"
localAddr: "192.168.1.1"
localId: "192.168.1.1"
remoteId: "192.168.1.2"
secretRef:
name: "ipsec-secret"
namespace: default
key: "example"
children:
example-child:
name: "example-child"
extra:
esp_proposals: aes256-sha256-ecp256
start_action: start
dpd_action: restart
local_ips:
- "10.0.2.0/24"
remote_ips:
- "10.0.1.0/24"
xfrm_ip: "10.0.2.1/24"
vxlan_ip: "10.0.2.2/24"
if_id: 102
ip_pools:
primary:
- "10.0.2.3/24"
- "10.0.2.4/24"
nodeName: "your-node-name"
To route workload traffic through the VPN tunnel, add specific annotations to your Pods or Deployments. These annotations tell IPMan to allocate IPs from the configured pools and set up the necessary routing.
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-app
spec:
template:
metadata:
annotations:
ipman.dialo.ai/childName: "example-child" # Must match the child name in IPSecConnection
ipman.dialo.ai/ipmanName: "example-connection" # Must match the IPSecConnection name
ipman.dialo.ai/poolName: "primary" # IP pool to use (defined in IPSecConnection)
spec:
# Your pod spec here
The operator will automatically:
Field | Description |
---|---|
name |
Name for the IPSec connection |
remoteAddr |
Remote VPN endpoint address |
localAddr |
Local VPN endpoint address |
localId |
Local identification |
remoteId |
Remote identification |
secretRef |
Reference to Kubernetes secret containing pre-shared key |
children |
Map of child connections (for multiple tunnels) |
nodeName |
Kubernetes node to establish connection from |
Field | Description |
---|---|
name |
Name for the child connection |
local_ips |
List of local networks/IPs for the tunnel |
remote_ips |
List of remote networks/IPs for the tunnel |
xfrm_ip |
IP for the xfrm interface |
vxlan_ip |
IP for the vxlan interface |
if_id |
Interface ID |
ip_pools |
Named IP pools available for allocation |
extra |
Additional StrongSwan configuration options |
If you encounter issues with your IPSec connections:
kubectl get ipsecconnection -n ipman-system
kubectl describe ipsecconnection example-connection -n ipman-system
kubectl logs -n ipman-system -l app=ipman-controller
IPMan now supports monitoring via Prometheus. To enable monitoring:
global.monitoring.enabled
to true
in your Helm valuesglobal.monitoring.release
to the name you’ve given your Prometheus operator
(e.g., if installed via helm install kps prometheus-community/kube-prometheus-stack
,
set it to “kps”)See helm/values.yaml
for more configuration options.
IPMan ensures secure connectivity between remote sites and workload pods by injecting secondary interfaces tied to the local encryption domain’s network. Inbound traffic arrives at the host’s network interface, is forwarded through a dedicated XFRM interface, and routed within an isolated VXLAN segment for enhanced security and segmentation. Charon, the IKE daemon from StrongSwan, operates on user-specified nodes, with instance counts driven by the IPsec configuration. Each child connection runs in a dedicated pod, equipped with its own XFRM interface and VXLAN segment. This design enables flexible workload deployment across the cluster, abstracting the underlying physical infrastructure for seamless scalability. Only ports 500 (IKE) and 4500 (NAT-traversal/IPsec) are exposed for secure communication. Charon and the restctl service, which manage the Charon socket and XFRM interface configuration, operate within the host network namespace, exposing only sockets mounted in the host filesystem. Control sockets, accessible via proxies, facilitate cluster-wide management without requiring additional open ports.
Special thanks to LarsTi for his ipsec_exporter repository, which we’ve adapted for our use case.
This project is licensed under the MIT License.