{"id":19268590,"url":"https://github.com/moolen/skouter","last_synced_at":"2025-04-21T20:31:54.972Z","repository":{"id":65500763,"uuid":"584116091","full_name":"moolen/skouter","owner":"moolen","description":"🛡️ cloud-native eBPF node egress firewall","archived":false,"fork":false,"pushed_at":"2023-02-19T21:30:14.000Z","size":1009,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-14T19:12:58.779Z","etag":null,"topics":["dns","ebpf","kubernetes"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moolen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2023-01-01T12:44:20.000Z","updated_at":"2024-01-31T16:39:42.000Z","dependencies_parsed_at":"2023-02-14T15:00:37.833Z","dependency_job_id":null,"html_url":"https://github.com/moolen/skouter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moolen%2Fskouter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moolen%2Fskouter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moolen%2Fskouter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moolen%2Fskouter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moolen","download_url":"https://codeload.github.com/moolen/skouter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223876356,"owners_count":17218389,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dns","ebpf","kubernetes"],"created_at":"2024-11-09T20:16:46.035Z","updated_at":"2024-11-09T20:16:46.769Z","avatar_url":"https://github.com/moolen.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skouter\n\ncloud-native egress proxy.\n\n---\n\n## Overview\n\n![overview](overview.png)\n\n## Rationale\n\nThis is a counter-draft to the traditional centralized egress firewall approach.\n\nRequirements:\n\n- provide a **DNS-based firewall** to allow/deny egress traffic\n- **no change of existing applications needed**: an app must not rely on `HTTP_PROXY` env variables or iptables traffic redirection\n- **no central infrastructure** for egress filtering: No single point of failure. Eliminate complexity introduced by HA architecture like leader election, state replication, snapshots for DR, VRRP.\n- is capable of filtering **host** egress traffic\n- supports audit mode that allows to discover traffic patterns before blocking them\n\nIt runs on the tc egress hook. Essentially, all traffic from the host that goes through that interface is subject to egress policies.\nIt parses the DNS response packets from the trusted DNS server and allows/blocks traffic egressing from the system.\n\nThere are other implemenatation approaches for egress filtering:\n\n- L7: HTTP Proxy\n- L7|L4: HTTP(S) CONNECT\n- L5+: TLS SNI\n- L3|L4: IP CIDRs + ports\n- K8s Operator like https://github.com/giantswarm/dns-network-policy-operator\n\n### Limitations and edge cases\n\n* DNS over TCP is not supported, currently\n* IPv6 is not yet supported\n* may interfere with other eBPF-based tools (e.g. cilium)\n* depending on the CNI implementation, pods may also be subject to the same egress policies as the host (overlay networking)\n\n## Further improvements\n\n- [ ] ~~implement DNS parsing in eBPF (beware, there be dragons!)~~ This is completely nuts\n- [x] validate kube-dns source/dest IP for DNS lookups\n- [x] track source port/id of DNS query and match it with response (make spoofing harder)\n- [ ] support DNS over TCP\n- [x] support CNAME records\n- [x] packet-level metrics\n- [x] regex hostnames\n- [ ] support IPv6\n- [x] block host traffic\n- [x] support plain IPs\n- [x] support IP cidr ranges\n- [x] audit mode (allow egress by default but log/store traffic patterns)\n- [x] clean up deleted IPs\n- [x] drop initial DNS answer and respond from userspace\n- [x] ~~lift limitation of 256 adresses per node~~\n- [ ] consider pivoting into making this a central egress infrastructure by ip forwarding ip packets while still supporting kubernetes integration\n\n## Example\n\nGiven this egress config:\n\n```yaml\napiVersion: egress.skouter/v1alpha1\nkind: Egress\nmetadata:\n  name: example\nspec:\n  # use nodeSelector to set up\n  # host firewall\n  nodeSelector: {}\n  rules:\n    - domains:\n      - example.com\n      - httpbin.org\n    - ips:\n      - 1.2.3.4\n      - 5.7.3.1\n    - cidrs:\n      - 127.0.0.1/8\n      - 10.0.10.0/24\n    - regex:\n      - .*\\.wikipedia\\.org # de|en|...\n```\n\nOn the host system, try make HTTP calls to verify the behaviour:\n\n```shell\n% wget -O - example.com\nConnecting to example.com (93.184.216.34:80)\nwriting to stdout\n\u003c!doctype html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003ctitle\u003eExample Domain\u003c/title\u003e\n[...]\n\n% wget -O - github.com --timeout 5\nConnecting to github.com (140.82.121.3:80)\nwget: download timed out\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoolen%2Fskouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoolen%2Fskouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoolen%2Fskouter/lists"}