Ziti-tunnel Docker Image
Run the ziti-tunnel NetFoundry client. ziti-tunnel captures network traffic that is destined for Ziti services and proxes the packet payloads to the associated Ziti service. See the ziti-tunnel README for more details.
This image requires access to a Ziti enrollment token (JWT), and a persistent volume mounted at "/netfoundry" to save the configuration file that is created when the one-time enrollment token is consumed.
Variables
NF_REG_NAME: The name of the identity that ziti-tunnel will assume.
Volumes
/netfoundry: Configuration files that result from enrollment will be stored here. This volume should be persistent unless you don't mind losing the key for your enrollment token.
Files
The enrollment token (jwt) must be mounted into the ziti-tunnel container as a volume.
The token must be in a file named ${NF_REG_NAME}.jwt that must be in one of the
following directories:
/netfoundry: This would be used when running in the Docker engine (or IoT Edge). This could be a bind mount or a docker volume./var/run/secrets/netfoundry.io/enrollment-token: When running in Kubernetes, the enrollment token should be mounted as a secret at this mount point.
Examples
Docker
The ziti-tunnel image can be used in a vanilla Docker environment.
$ mkdir ./ziti_id
$ cp ~/Downloads/ziti_id.jwt ./ziti_id
$ docker run -t --network=host --cap-add=NET_ADMIN \
-v $(pwd)/ziti_id:/netfoundry \
-e NF_REG_NAME=ziti_id \
netfoundry/ziti-tunnel:0.5.7-2546
Notes:
- The container that runs ziti-tunnel will only be able to intercept traffic for other processes within the same container, unless the container uses the "host" network mode.
- The container requires NET_ADMIN capability to create iptables rules.
- The
NF_REG_NAMEenvironment variable must be set to the name of the ziti identity that ziti-tunnel will assume when connecting to the controller. - The "/netfoundry" directory must be mounted on its own volume.
- The one-time enrollment token "/netfoundry/${NF_REG_NAME}.jwt" must exist when the container is started for the first time. This is the JWT that was downloaded from the controller when the Ziti identity was created.
- "/netfoundry/${NF_REG_NAME}.json" is created when the identity is enrolled. The "/netfoundry" volume must be persistent (that is, ${NF_REG_NAME}.json must endure container restarts), since the enrollment token is only valid for one enrollment.
Docker Compose
This example uses Compose to store in a file the Docker build and run parameters for several modes of operation of ziti-tunnel.
Docker Compose Setup
- Install Docker Engine.
docker-composeis a utility you can install with the Python Package Index (PyPi) e.g.pip install --upgrade docker-compose.- Save your Ziti identity enrollment token e.g.
my-ziti-identity-file.jwtin the same directory as the file nameddocker-compose.yml. Your identity will be enrolled the first time you run the container, and the permanent identity file will be saved e.g.my-ziti-identity-file.json. - You may change
ZITI_VERSIONto another release version from our ziti-release repository.
Docker Transparent Proxy for Linux
- Modify "ziti-tproxy" under "services" in the file named
docker-compose.ymlin this Git repo, optionally overriding the default value ofcommandto pass additional parameters toziti-tunnel.
version: "3.3"
services:
ziti-tproxy:
image: netfoundry/ziti-tunnel:tproxy
build:
context: .
args:
ZITI_VERSION: 0.15.3
volumes:
- .:/netfoundry
network_mode: host
cap_add:
- NET_ADMIN
environment:
- NF_REG_NAME
# command: run --resolver udp://127.0.0.123:53
# command: run --resolver none
- Run
NF_REG_NAME=my-ziti-identity-file docker-compose up --build ziti-tproxyin the same directory.
This will cause the container to configure the Linux host to transparently proxy any domain names or IP addresses that match a Ziti service.
Docker Proxy or MacOS or Windows
- Modify "ziti-proxy" under "services" in the file named
docker-compose.ymlin this Git repo. Change the service name(s) and port number(s) to suit your actual services. You must align the mapped ports underportswith the bound ports in thecommand.
version: "3.3"
services:
ziti-proxy:
image: netfoundry/ziti-tunnel:proxy
build:
context: .
args:
ZITI_VERSION: 0.15.3
volumes:
- .:/netfoundry
environment:
- NF_REG_NAME
ports:
- "8888:8888"
- "9999:9999"
command: proxy "my example service":8888 "my other example service":9999
- Run in the same directory:
NF_REG_NAME=my-ziti-identity-file docker-compose up --build ziti-proxy
This will cause the container to listen on the mapped port(s) and proxy any received traffic to the Ziti service that is bound to that port.
Kubernetes
The ziti-tunnel image can be used in Kubernetes either as a sidecar, which would
intercept packets only from other containers in the pod definition or as a dedicated
pod that sets hostNetwork to true.
The following example manifest shows how to run ziti-tunnel as a sidecar:
$ cat app-with-ziti-tunnel-sidecar.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: tunnel-sidecar-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ziti-tunnel-sidecar-demo
spec:
replicas: 1
selector:
matchLabels:
app: ziti-tunnel-sidecar-demo
strategy:
type: Recreate
template:
metadata:
labels:
app: ziti-tunnel-sidecar-demo
spec:
containers:
- image: centos
name: testclient
command: ["sh","-c","while true; set -x; do curl -sSLf ethzero.ziti.ui 2>&1; set +x; sleep 5; done"]
- image: netfoundry/ziti-tunnel:0.5.8-2554
name: ziti-tunnel
env:
- name: NF_REG_NAME
value: tunnel-sidecar
volumeMounts:
- name: tunnel-sidecar-jwt
mountPath: "/var/run/secrets/netfoundry.io/enrollment-token"
readOnly: true
- name: ziti-tunnel-persistent-storage
mountPath: /netfoundry
securityContext:
capabilities:
add:
- NET_ADMIN
dnsPolicy: "None"
dnsConfig:
nameservers:
- 127.0.0.1
- 8.8.8.8
restartPolicy: Always
volumes:
- name: ziti-tunnel-persistent-storage
persistentVolumeClaim:
claimName: tunnel-sidecar-pv-claim
- name: tunnel-sidecar-jwt
secret:
secretName: tunnel-sidecar.jwt
Azure IoT Hub
This image can be used to run a module on an Azure IoT runtime.
# createOption.HostConfig for tun (instead of tproxy): \"Devices\":[{\"PathOnHost\":\"/dev/net/tun\",\"PathInContainer\":\"/dev/net/tun\",\"CgroupPermissions\":\"rwm\"}],
$ cat module.json
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"modules": {
"ziti-tunnel": {
"settings": {
"image": "netfoundry/ziti-tunnel:0.5.8-2554",
"createOptions": "{\"HostConfig\":{\"CapAdd\":[\"NET_ADMIN\"],\"Mounts\":[{\"Type\":\"bind\",\"Source\":\"/opt/netfoundry\",\"Target\":\"/netfoundry\"}],\"NetworkMode\":\"host\"},\"NetworkingConfig\":{\"EndpointsConfig\":{\"host\":{}}}}"
},
"type": "docker",
"version": "1.0",
"status": "running",
"restartPolicy": "always"
}
},
"runtime": {
"settings": {
"minDockerVersion": "v1.25"
},
"type": "docker"
},
"schemaVersion": "1.0",
"systemModules": {
"edgeAgent": {
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": ""
},
"type": "docker"
},
"edgeHub": {
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
},
"type": "docker",
"status": "running",
"restartPolicy": "always"
}
}
}
},
"$edgeHub": {
"properties.desired": {
"routes": {},
"schemaVersion": "1.0",
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
},
"ziti-tunnel": {
"properties.desired": {}
}
}
}