github.com/g0lab/g0efilter
3.1K
Note
Portions of this project were developed with the assistance of AI tools.
Warning
g0efilter is in active development. Its configuration is not stable yet.
g0efilter controls network traffic leaving your containers. It runs beside a workload and applies IP and domain rules without decrypting TLS traffic.
Create a policy directory:
mkdir -p policy
Add policy/policy.yaml:
allowlist:
ips:
- '1.1.1.1'
domains:
- 'github.com'
- '*.alpinelinux.org'
Save this as docker-compose.yaml:
services:
g0efilter:
image: docker.io/g0lab/g0efilter:v0
volumes:
- ./policy/:/app/policy/
cap_drop:
- ALL
cap_add:
- NET_ADMIN
security_opt:
- no-new-privileges
read_only: true
example-container:
image: docker.io/alpine/curl:latest
command: sh -c "sleep infinity"
network_mode: "service:g0efilter"
Start the services:
docker compose up -d
See the examples for complete Compose files and policies. See
the privilege model for how the container
runs unprivileged with only NET_ADMIN. The agent image is built FROM scratch
and programs nftables over netlink, so it has no shell or nft binary.
Attached containers share g0efilter's network namespace. Allowed IPs and CIDRs
pass through directly. Other traffic is handled by FILTER_MODE.
| Mode | Checks domains at | Blocks hardcoded IPs? | Best for |
|---|---|---|---|
https | Connection time, using TLS SNI or the HTTP Host header | Yes | Precise control of web traffic |
dns | DNS lookup time | No | Simple, broad filtering |
dns-strict | DNS lookup and connection time | Yes | Strict domain filtering on any port |
See filter modes for details and limits.
Use dns-strict when a workload connects to allowed domains over protocols or
ports other than HTTP and HTTPS. It allows IPs learned through approved DNS
lookups while blocking direct-IP and alternate-DNS bypasses.
Note
Workloads must not listen on g0efilter's internal HTTP, HTTPS, or DNS ports. The defaults are 65080, 65443, and 65053.
allowlist:
ips:
- '1.1.1.1'
- '192.168.0.0/16'
domains:
- 'github.com'
- '*.alpinelinux.org'
- '/cache-[0-9]+\.example\.com/'
Mount the policy directory, not only the file. This keeps live reload working when an editor replaces the file during save.
Policies can also use a default-allow denylist, learning mode, or audit mode. See policy for patterns and policy modes. See environment variables for configuration.
g0efilter runs as a sidecar that filters the whole pod. Application containers need no extra privileges. A Kustomize component can add the sidecar without changing the workload manifests.
components:
- github.com/g0lab/g0efilter//deploy/kustomize/sidecar?ref=v0.10.2
The component patches Deployment, StatefulSet, DaemonSet, ReplicaSet, Job and CronJob. There is also a Helm library chart for charts you maintain, a Helm post-renderer for third-party charts you cannot edit, and a mutating webhook that injects the sidecar at admission for pods you do not template at all.
To run it cluster-wide, install the control plane and label the namespaces to filter:
helm install g0efilter oci://ghcr.io/g0lab/helm/g0efilter-controller \
--namespace g0efilter-system --create-namespace
kubectl label namespace <namespace> g0efilter.g0lab.com/inject=enabled
Pods also need to match an EgressPolicy; the namespace label alone does not
trigger injection. See the policy example,
and start with enforcement: audit to see what it would deny.
Admission waits for the controller to render the current policy. Where a
ClusterEgressPolicy selects the namespace it also waits for the rendered
baseline revision to match, so new selected pods are rejected until a baseline
change is reconciled. Running pods are never affected.
Certificate Secret access is namespace-scoped and omitted when cert-manager owns the certificate. The controller chart can also restrict webhook ingress to explicit API-server CIDRs; see webhook network isolation.
Three charts are published through a Helm repository at
https://g0lab.github.io/g0efilter and as OCI artifacts under
oci://ghcr.io/g0lab/helm:
| Chart | Type | Use |
|---|---|---|
g0efilter-controller | application | the control plane: controller, webhook and CRDs |
g0efilter-dashboard | application | the dashboard the sidecars ship logs to |
g0efilter | library | sidecar templates for a chart you maintain |
Render-time integrations mount a policy ConfigMap directly. The webhook uses a
controller to render one from each EgressPolicy. Kubernetes Events and
Prometheus metrics are optional.
See Kubernetes for all four integrations, the full
EgressPolicy sidecar options, policy distribution, and the required namespace
label.
The GitHub Action filters traffic from the runner. Add it before the steps you want to protect.
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Filter egress
uses: g0lab/g0efilter@v0
with:
egress-policy: block
allowed-domains: |
*.npmjs.org
nodejs.org
- uses: actions/checkout@v7
The workflow logs its allowlist. The job summary lists blocked, audited and allowed hosts.
See GitHub Actions for inputs, built-in allow rules, the job report, and security limits.
The optional dashboard shows live and stored traffic. Point g0efilter at it with
DASHBOARD_HOST and DASHBOARD_API_KEY. The dashboard can also manage API keys,
fleet policy, and remote unblock requests.
Its Helm chart supports externally managed credentials. List the keys in
secrets.existingSecretKeys so the chart can validate the setup and print the
right recovery notes.
See the examples for a complete setup. See dashboard authentication, persistent logs, and remote unblock for its security requirements.
Images use Cosign keyless signatures.
Signatures are stored in g0lab/signatures:
COSIGN_REPOSITORY=docker.io/g0lab/signatures \
cosign verify g0lab/g0efilter:v0 \
--certificate-identity-regexp=https://github.com/g0lab/g0efilter \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
-o text
Use g0lab/g0efilter-dashboard:v0 to verify the dashboard image.
MIT, see LICENSE.
Content type
Image
Digest
sha256:154e12120…
Size
11.6 MB
Last updated
about 16 hours ago
docker pull g0lab/g0efilter-controller