-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add Helm chart for VPN connectivity (#2577)
Co-authored-by: 3u13r <[email protected]>
- Loading branch information
Showing
16 changed files
with
480 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Patterns to ignore when building packages. | ||
# This supports shell glob matching, relative path matching, and | ||
# negation (prefixed with !). Only one pattern per line. | ||
.DS_Store | ||
# Common VCS dirs | ||
.git/ | ||
.gitignore | ||
.bzr/ | ||
.bzrignore | ||
.hg/ | ||
.hgignore | ||
.svn/ | ||
# Common backup files | ||
*.swp | ||
*.bak | ||
*.tmp | ||
*.orig | ||
*~ | ||
# Various IDEs | ||
.project | ||
.idea/ | ||
*.tmproj | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
apiVersion: v2 | ||
name: vpn | ||
description: A VPN server for Constellation | ||
|
||
type: application | ||
|
||
version: 0.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Constellation VPN | ||
|
||
This Helm chart deploys a VPN server to your Constellation cluster. | ||
|
||
## Installation | ||
|
||
1. Create and populate the configuration. | ||
|
||
```sh | ||
helm inspect values . >config.yaml | ||
``` | ||
|
||
2. Install the Helm chart. | ||
|
||
```sh | ||
helm install -f config.yaml vpn . | ||
``` | ||
|
||
3. Follow the post-installation instructions displayed by the CLI. | ||
|
||
## Architecture | ||
|
||
The VPN server is deployed as a `StatefulSet` to the cluster. It hosts the VPN frontend component, which is responsible for relaying traffic between the pod and the on-prem network, and the routing components that provide access to Constellation resources. The frontend supports IPSec and Wireguard. | ||
|
||
The VPN frontend is exposed with a public LoadBalancer to be accessible from the on-prem network. Traffic that reaches the VPN server pod is split into two categories: pod IPs and service IPs. | ||
|
||
The pod IP range is NATed with an iptables rule. On-prem worklaods can establish connections to a pod IP, but the Constellation workloads will see the client IP translated to that of the VPN frontend pod. | ||
|
||
The service IP range is handed to a transparent proxy running in the VPN frontend pod, which relays the connection to a backend pod. This is necessary because of the load-balancing mechanism of Cilium, which assumes service IP traffic to originate from the Constellation cluster itself. As for pod IP ranges, Constellation pods will only see the translated client address. | ||
|
||
## Limitations | ||
|
||
* Service IPs need to be proxied by the VPN frontend pod. This is a single point of failure, and it may become a bottleneck. | ||
* IPs are NATed, so the Constellation pods won't see the real on-prem IPs. | ||
* NetworkPolicy can't be applied selectively to the on-prem ranges. | ||
* No connectivity from Constellation to on-prem workloads. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
charon { | ||
filelog { | ||
stderr { | ||
time_format = %b %e %T | ||
ike_name = yes | ||
default = 1 | ||
ike = 2 | ||
flush_line = yes | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/sh | ||
|
||
# The charon binary is not included in the PATH generated by nixery.dev, find it manually. | ||
charon="$(dirname "$(readlink -f "$(command -v charon-systemd)")")/../libexec/ipsec/charon" | ||
|
||
"${charon}" & | ||
|
||
while ! swanctl --stats > /dev/null 2> /dev/null; do | ||
sleep 1 | ||
done | ||
swanctl --load-all | ||
|
||
wait |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#!/bin/sh | ||
|
||
set -eu | ||
|
||
### Pod IPs ### | ||
|
||
# Pod IPs are just NATed. | ||
|
||
iptables -t nat -N VPN_POST || iptables -t nat -F VPN_POST | ||
|
||
for cidr in ${VPN_PEER_CIDRS}; do | ||
iptables -t nat -A VPN_POST -s "${cidr}" -d "${VPN_POD_CIDR}" -j MASQUERADE | ||
done | ||
|
||
iptables -t nat -C POSTROUTING -j VPN_POST || iptables -t nat -A POSTROUTING -j VPN_POST | ||
|
||
### Service IPs ### | ||
|
||
# Service IPs need to be connected to locally to trigger the cgroup connect hook, thus we send them to the transparent proxy. | ||
|
||
# Packets with mark 1 are for tproxy and need to be delivered locally. | ||
# For more information see: https://www.kernel.org/doc/Documentation/networking/tproxy.txt | ||
pref=42 | ||
table=42 | ||
mark=0x1/0x1 | ||
ip rule add pref "${pref}" fwmark "${mark}" lookup "${table}" | ||
ip route replace local 0.0.0.0/0 dev lo table "${table}" | ||
|
||
iptables -t mangle -N VPN_PRE || iptables -t mangle -F VPN_PRE | ||
|
||
for cidr in ${VPN_PEER_CIDRS}; do | ||
for proto in tcp udp; do | ||
iptables -t mangle -A VPN_PRE -p "${proto}" -s "${cidr}" -d "${VPN_SERVICE_CIDR}" \ | ||
-j TPROXY --tproxy-mark "${mark}" --on-port 61001 | ||
done | ||
done | ||
|
||
iptables -t mangle -C PREROUTING -j VPN_PRE || iptables -t mangle -A PREROUTING -j VPN_PRE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/sh | ||
|
||
set -eu | ||
|
||
dev=vpn_wg0 | ||
|
||
ip link add dev "${dev}" type wireguard | ||
wg setconf "${dev}" /etc/wireguard/wg.conf | ||
ip link set dev "${dev}" up | ||
|
||
for cidr in ${VPN_PEER_CIDRS}; do | ||
ip route replace "${cidr}" dev "${dev}" | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
{{- define "..name" -}} | ||
{{- default .Chart.Name .Values.nameOverride | trunc 42 | trimSuffix "-" }} | ||
{{- end }} | ||
|
||
{{- define "..fullname" -}} | ||
{{- $name := default .Chart.Name .Values.nameOverride }} | ||
{{- if contains $name .Release.Name }} | ||
{{- .Release.Name | trunc 42 | trimSuffix "-" }} | ||
{{- else }} | ||
{{- printf "%s-%s" .Release.Name $name | trunc 42 | trimSuffix "-" }} | ||
{{- end }} | ||
{{- end }} | ||
|
||
{{- define "..chart" -}} | ||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 42 | trimSuffix "-" }} | ||
{{- end }} | ||
|
||
{{- define "..labels" -}} | ||
helm.sh/chart: {{ include "..chart" . }} | ||
{{ include "..selectorLabels" . }} | ||
{{- if .Chart.AppVersion }} | ||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} | ||
{{- end }} | ||
app.kubernetes.io/managed-by: {{ .Release.Service }} | ||
{{- end }} | ||
|
||
{{- define "..selectorLabels" -}} | ||
app.kubernetes.io/name: {{ include "..name" . }} | ||
app.kubernetes.io/instance: {{ .Release.Name }} | ||
{{- end }} | ||
|
||
{{- define "..commonEnv" -}} | ||
- name: VPN_PEER_CIDRS | ||
value: {{ join " " .Values.peerCIDRs | quote }} | ||
- name: VPN_POD_CIDR | ||
value: {{ .Values.podCIDR | quote }} | ||
- name: VPN_SERVICE_CIDR | ||
value: {{ .Values.serviceCIDR | quote }} | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: {{ include "..fullname" . }}-tproxy | ||
labels: {{- include "..labels" . | nindent 4 }} | ||
data: | ||
{{ (.Files.Glob "files/tproxy-setup.sh").AsConfig | indent 2 }} | ||
--- | ||
{{- if .Values.wireguard.enabled }} | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: {{ include "..fullname" . }}-wg | ||
labels: {{- include "..labels" . | nindent 4 }} | ||
data: | ||
{{ (.Files.Glob "files/wireguard-setup.sh").AsConfig | indent 2 }} | ||
{{- end }} | ||
--- | ||
{{ if .Values.ipsec.enabled }} | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: {{ include "..fullname" . }}-strongswan | ||
labels: {{- include "..labels" . | nindent 4 }} | ||
data: | ||
{{ (.Files.Glob "files/strongswan/*").AsConfig | indent 2 }} | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{{- if .Values.wireguard.enabled }} | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: {{ include "..fullname" . }}-wg | ||
labels: | ||
{{- include "..labels" . | nindent 4 }} | ||
data: | ||
wg.conf: {{ include "wireguard.conf" . | b64enc }} | ||
{{- end }} | ||
--- | ||
{{ if .Values.ipsec.enabled }} | ||
apiVersion: v1 | ||
kind: Secret | ||
metadata: | ||
name: {{ include "..fullname" . }}-strongswan | ||
labels: | ||
{{- include "..labels" . | nindent 4 }} | ||
data: | ||
swanctl.conf: {{ include "strongswan.swanctl-conf" . | b64enc }} | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: {{ include "..fullname" . }}-lb | ||
labels: | ||
{{- include "..labels" . | nindent 4 }} | ||
spec: | ||
type: LoadBalancer | ||
selector: | ||
{{- include "..selectorLabels" . | nindent 4 }} | ||
component: frontend | ||
externalTrafficPolicy: Local | ||
ports: | ||
{{- if .Values.ipsec.enabled }} | ||
- name: isakmp | ||
protocol: UDP | ||
port: 500 | ||
- name: ipsec-nat-t | ||
protocol: UDP | ||
port: 4500 | ||
{{- end }} | ||
{{- if .Values.wireguard.enabled }} | ||
- name: wg | ||
protocol: UDP | ||
port: {{ .Values.wireguard.port }} | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{{- define "strongswan.swanctl-conf" }} | ||
connections { | ||
net-net { | ||
remote_addrs = {{ .Values.ipsec.peer }} | ||
local { | ||
auth = psk | ||
} | ||
remote { | ||
auth = psk | ||
} | ||
children { | ||
net-net { | ||
local_ts = {{ .Values.podCIDR }},{{ .Values.serviceCIDR }} | ||
remote_ts = {{ join "," .Values.peerCIDRs }} | ||
start_action = trap | ||
} | ||
} | ||
} | ||
} | ||
|
||
secrets { | ||
ike { | ||
secret = {{ quote .Values.ipsec.psk }} | ||
} | ||
} | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
{{ if .Values.ipsec.enabled -}} | ||
apiVersion: apps/v1 | ||
kind: StatefulSet | ||
metadata: | ||
name: {{ include "..fullname" . }}-frontend | ||
labels: {{- include "..labels" . | nindent 4 }} | ||
spec: | ||
selector: | ||
matchLabels: | ||
{{- include "..selectorLabels" . | nindent 6 }} | ||
component: frontend | ||
template: | ||
metadata: | ||
labels: | ||
{{- include "..selectorLabels" . | nindent 8 }} | ||
component: frontend | ||
spec: | ||
hostNetwork: false | ||
initContainers: | ||
- name: tproxy-setup | ||
image: nixery.dev/busybox/iptables | ||
command: ["/bin/sh", "-x", "/entrypoint.sh"] | ||
env: {{- include "..commonEnv" . | nindent 10 }} | ||
securityContext: | ||
capabilities: | ||
add: ["NET_ADMIN"] | ||
volumeMounts: | ||
- name: tproxy-setup | ||
mountPath: "/entrypoint.sh" | ||
subPath: "tproxy-setup.sh" | ||
readOnly: true | ||
containers: | ||
- name: tproxy | ||
# Image source: github.com/burgerdev/go-tproxy | ||
image: ghcr.io/burgerdev/go-tproxy:latest | ||
command: ["/tproxy", "--port=61001", "--nat=true"] | ||
securityContext: | ||
capabilities: | ||
add: ["NET_RAW"] | ||
- name: strongswan | ||
image: "nixery.dev/shell/strongswan" | ||
command: ["/bin/sh", "-x", "/entrypoint.sh"] | ||
securityContext: | ||
capabilities: | ||
add: ["NET_ADMIN"] | ||
volumeMounts: | ||
- name: strongswan | ||
mountPath: "/entrypoint.sh" | ||
subPath: "entrypoint.sh" | ||
readOnly: true | ||
- name: strongswan | ||
mountPath: "/etc/strongswan.d/charon-logging.conf" | ||
subPath: "charon-logging.conf" | ||
readOnly: true | ||
- name: strongswan | ||
mountPath: "/etc/swanctl/swanctl.conf" | ||
subPath: "swanctl.conf" | ||
readOnly: true | ||
volumes: | ||
- name: tproxy-setup | ||
configMap: | ||
name: {{ include "..fullname" . }}-tproxy | ||
- name: strongswan | ||
projected: | ||
sources: | ||
- secret: | ||
name: {{ include "..fullname" . }}-strongswan | ||
items: | ||
- key: swanctl.conf | ||
path: swanctl.conf | ||
- configMap: | ||
name: {{ include "..fullname" . }}-strongswan | ||
items: | ||
- key: entrypoint.sh | ||
path: entrypoint.sh | ||
- key: charon-logging.conf | ||
path: charon-logging.conf | ||
{{- end }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{{- define "wireguard.conf" }} | ||
[Interface] | ||
ListenPort = {{ .Values.wireguard.port }} | ||
PrivateKey = {{ .Values.wireguard.private_key }} | ||
[Peer] | ||
PublicKey = {{ .Values.wireguard.peer_key }} | ||
AllowedIPs = {{ join "," .Values.peerCIDRs }} | ||
{{- if .Values.wireguard.endpoint }} | ||
Endpoint = {{- .Values.wireguard.endpoint }} | ||
{{- end }} | ||
{{- if .Values.wireguard.keepAlive }} | ||
PersistentKeepalive = {{- .Values.wireguard.keepAlive }} | ||
{{- end }} | ||
{{ end }} |
Oops, something went wrong.