{"id":19838504,"url":"https://github.com/metal-stack/firewall-controller","last_synced_at":"2025-06-18T03:40:12.724Z","repository":{"id":40367967,"uuid":"258250036","full_name":"metal-stack/firewall-controller","owner":"metal-stack","description":"A kubernetes controller running on bare-metal firewalls, creating nftables rules, configures suricata, collects network metrics","archived":false,"fork":false,"pushed_at":"2025-03-10T14:37:25.000Z","size":831,"stargazers_count":53,"open_issues_count":25,"forks_count":4,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-09T18:16:52.371Z","etag":null,"topics":["firewall-controller","firewall-crd","ids","kubernetes","networkpolicy","nftables","services"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/metal-stack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-23T15:33:55.000Z","updated_at":"2025-03-24T23:43:46.000Z","dependencies_parsed_at":"2023-02-18T09:00:34.493Z","dependency_job_id":"36171c5b-b92c-4183-bc6a-35eafda8a06b","html_url":"https://github.com/metal-stack/firewall-controller","commit_stats":null,"previous_names":[],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metal-stack%2Ffirewall-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metal-stack%2Ffirewall-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metal-stack%2Ffirewall-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metal-stack%2Ffirewall-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/metal-stack","download_url":"https://codeload.github.com/metal-stack/firewall-controller/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248085323,"owners_count":21045139,"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":["firewall-controller","firewall-crd","ids","kubernetes","networkpolicy","nftables","services"],"created_at":"2024-11-12T12:17:59.081Z","updated_at":"2025-04-09T18:16:57.898Z","avatar_url":"https://github.com/metal-stack.png","language":"Go","readme":"# firewall-controller\n\nThis controller is installed on a bare-metal firewall in front of several kubernetes worker nodes and responsible to reconcile a `ClusterwideNetworkPolicy` to nftables rules to control access to and from the kubernetes cluster.\nIt allows also to control the traffic rate going through, to limit network resources for restricted usage scenarios. Nftable and node metrics are exposed with the `nftables-exporter` and `node-exporter`, the ips are visible as service and endpoint from the kubernetes cluster.\n\nAdditionally, an IDS is managed on the firewall to detect known network anomalies. [suricata](https://suricata-ids.org) is used for this purpose. Right now, only basic statistics about the amount of scanned packets is reported. In a future release, access to all alarms will be provided.\n\nThis controller is typically setup through the [firewall-controller-manager](https://github.com/metal-stack/firewall-controller-manager) (FCM), which manages the lifecycle of metal-stack firewalls inside our [Gardener integration](https://docs.metal-stack.io/stable/overview/kubernetes/).\n\n## Architecture\n\nThe firewall-controller is acting on 3 CRDs typically running in your cluster and a provider-managed cluster (in Gardener terms \"shoot\" and \"seed\").:\n\n| CRD                              | API                          | Resides In | Purpose                                                             |\n| -------------------------------- | ---------------------------- | ---------- | ------------------------------------------------------------------- |\n| `ClusterwideNetworkPolicy`       | `metal-stack.io/v1`          | Shoot      | Controls firewall rules and can be provided by the user             |\n| `Firewall` defined by FCM        | `firewall.metal-stack.io/v2` | Seed       | Defines the firewall including rate limits, controller version, ... |\n| `FirewallMonitor` defined by FCM | `firewall.metal-stack.io/v2` | Shoot      | Used as an overview for the user on the status of the firewall      |\n\nNote that `clusterwidenetworkpolicy` resources are namespaced and must reside in the `firewall` namespace, otherwise this controller does not reconcile them.\n\n![Architecture](architecture.drawio.svg)\n\nExample `ClusterwideNetworkPolicy`:\n\n```yaml\napiVersion: metal-stack.io/v1\nkind: ClusterwideNetworkPolicy\nmetadata:\n  namespace: firewall\n  name: clusterwidenetworkpolicy-sample\nspec:\n  egress:\n  - to:\n    - cidr: 1.1.0.0/24\n      except:\n      - 1.1.1.0/16\n    - cidr: 8.8.8.8/32\n    ports:\n    - protocol: UDP\n      port: 53\n    - protocol: TCP\n      port: 53\n    - protocol: TCP\n      port: 8080\n      # Optional, if specified this is the way to specify a port range from port to endPort\n      endPort: 8088\n```\n\n## Automatically Generated Ingress Rules\n\nFor every `Service` of type `LoadBalancer` in the cluster, the corresponding ingress rules will be automatically generated.\n\nIf `loadBalancerSourceRanges` is not specified, incomig traffic to this service will be allowed for any source ip addresses.\n\n### DNS Policies Configuration\n\nThe `ClusterwideNetworkPolicy` resource allows you to define DNS based egress policies as well. They allow you to filter egress traffic based either on DNS name or by matching names to the provided pattern.\n\nTo filter by specific domain name you need to provide `matchName` field:\n\n```yaml\napiVersion: metal-stack.io/v1\nkind: ClusterwideNetworkPolicy\nmetadata:\n  namespace: firewall\n  name: clusterwidenetworkpolicy-fqdn\nspec:\n  egress:\n  - toFQDNs:\n    - matchName: example.com\n    ports:\n    - protocol: UDP\n      port: 80\n    - protocol: TCP\n      port: 80\n```\n\nIf you want to filter FQDNs that are matching certain pattern, you can use `matchPattern` field, which supports `*` wildcard. Following example allows traffic to port 80 of all resources in the `.example` top-level domain:\n\n```yaml\napiVersion: metal-stack.io/v1\nkind: ClusterwideNetworkPolicy\nmetadata:\n  namespace: firewall\n  name: clusterwidenetworkpolicy-fqdn-pattern\nspec:\n  egress:\n  - toFQDNs:\n    - matchPattern: *.example\n    ports:\n    - protocol: UDP\n      port: 80\n    - protocol: TCP\n      port: 80\n```\n\nBy default, DNS info is collected from Google DNS (with address 8.8.8.8:53). The preferred DNS server can be changed through the `Firewall` resource of the FCM, which is governed by the provider.\n\n## Status\n\nOnce the firewall-controller is running, it will report several statistics to the `FirewallMonitor` CRD Status. This can be inspected by running:\n\n```bash\nkubectl get -n firewall fwmon\nNAME                               MACHINE ID                             IMAGE                          SIZE            LAST EVENT    AGE\nshoot--prod--seed-firewall-089f9   f4f8b200-deef-11e9-8000-3cecef22f910   firewall-ubuntu-2.0.20221025   n1-medium-x86   Phoned Home   18m\n```\n\nWhen showing the resource with `-o yaml`, it contains detailed information on traffic counting, package drops and IDS:\n\n```yaml\nStatus:\n  Last Run:  2020-06-17T13:18:58Z\n  Stats:\n    # Network traffic in bytes separated into external and internal in/out/total\n    Devices:\n      External:\n        In:     91696\n        Out:    34600\n        Total:  0\n      Internal:\n        In:     0\n        Out:    0\n        Total:  2678671\n    # IDS Statistics by interface\n    Idsstats:\n      vrf104009:\n        Drop:              1992\n        Invalidchecksums:  0\n        Packets:           4997276\n    # nftable rule statistics by rule name\n    Rules:\n      Accept:\n        BGP unnumbered:\n          Counter:\n            Bytes:    0\n            Packets:  0\n        SSH incoming connections:\n          Counter:\n            Bytes:    936\n            Packets:  16\n        accept established connections:\n          Counter:\n            Bytes:    21211168\n            Packets:  39785\n        accept icmp:\n          Counter:\n            Bytes:    0\n            Packets:  0\n        accept traffic for k8s service kube-system/vpn-shoot:\n          Counter:\n            Bytes:    360\n            Packets:  6\n      Drop:\n        drop invalid packets:\n          Counter:\n            Bytes:    52\n            Packets:  1\n        drop invalid packets from forwarding to prevent malicious activity:\n          Counter:\n            Bytes:    0\n            Packets:  0\n        drop invalid packets to prevent malicious activity:\n          Counter:\n            Bytes:    0\n            Packets:  0\n        drop packets with invalid ct state:\n          Counter:\n            Bytes:    0\n            Packets:  0\n        drop ping floods:\n          Counter:\n            Bytes:    0\n            Packets:  0\n      Other:\n        block bgp forward to machines:\n          Counter:\n            Bytes:    0\n            Packets:  0\n        count and log dropped packets:\n          Counter:\n            Bytes:    2528\n            Packets:  51\n        snat (networkid: internet):\n          Counter:\n            Bytes:    36960\n            Packets:  486\n```\n\n## Prometheus Integration\n\nThere are two exporters running on the firewall to report essential metrics from this machine:\n\n- node-exporter for machine specific metrics like cpu, ram and disk usage, see [node-exporter](https://github.com/prometheus/node_exporter) for details.\n- nftables-exporter for nftables metrics, see [nftables-exporter](https://github.com/Sheridan/nftables_exporter)\n\nBoth exporters are exposed as services:\n\n```bash\nkubectl get svc -n firewall\nNAME                TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE\nnftables-exporter   ClusterIP   None         \u003cnone\u003e        9630/TCP   13h\nnode-exporter       ClusterIP   None         \u003cnone\u003e        9100/TCP   13h\n```\n\nThese services are in front of virtual endpoints:\n\n```bash\nkubectl get ep -n firewall\nNAME                ENDPOINTS         AGE\nnftables-exporter   10.3.164.1:9630   13h\nnode-exporter       10.3.164.1:9100   13h\n```\n\nYou can scrape these services in you prometheus installation to get the metrics.\n\nTo check you can run:\n\n```bash\ncurl nftables-exporter.firewall.svc.cluster.local:9630/metrics\ncurl node-exporter.firewall.svc.cluster.local:9100/metrics\n```\n\n## Firewall Logs\n\nIt is also possible to tail for the dropped packets with the following command (install stern from [stern](https://github.com/stern/stern)):\n\n```bash\nstern -n firewall drop\n```\n\nThe output will look like:\n\n```json\ndroptailer-6d556bd988-4g8gp droptailer 2020-06-17 13:23:27 +0000 UTC {\"ACTION\":\"Drop\",\"DPT\":\"4000\",\"DST\":\"1.2.3.4\",\"ID\":\"54321\",\"IN\":\"vrf104009\",\"LEN\":\"40\",\"MAC\":\"ca:41:f9:80:fa:89:aa:bb:0e:62:8c:a6:08:00\",\"OUT\":\"vlan179\",\"PREC\":\"0x00\",\"PROTO\":\"TCP\",\"RES\":\"0x00\",\"SPT\":\"38464\",\"SRC\":\"2.3.4.5\",\"SYN\":\"\",\"TOS\":\"0x00\",\"TTL\":\"236\",\"URGP\":\"0\",\"WINDOW\":\"65535\",\"timestamp\":\"2020-06-17 13:23:27 +0000 UTC\"}\ndroptailer-6d556bd988-4g8gp droptailer 2020-06-17 13:23:34 +0000 UTC {\"ACTION\":\"Drop\",\"DPT\":\"2362\",\"DST\":\"1.2.3.4\",\"ID\":\"44545\",\"IN\":\"vrf104009\",\"LEN\":\"40\",\"MAC\":\"ca:41:f9:80:fa:89:aa:bb:0e:62:8c:a6:08:00\",\"OUT\":\"\",\"PREC\":\"0x00\",\"PROTO\":\"TCP\",\"RES\":\"0x00\",\"SPT\":\"40194\",\"SRC\":\"2.3.4.5\",\"SYN\":\"\",\"TOS\":\"0x00\",\"TTL\":\"242\",\"URGP\":\"0\",\"WINDOW\":\"1024\",\"timestamp\":\"2020-06-17 13:23:34 +0000 UTC\"}\ndroptailer-6d556bd988-4g8gp droptailer 2020-06-17 13:23:30 +0000 UTC {\"ACTION\":\"Accept\",\"DPT\":\"650\",\"DST\":\"1.2.3.4\",\"ID\":\"12399\",\"IN\":\"vrf104009\",\"LEN\":\"40\",\"MAC\":\"ca:41:f9:80:fa:89:aa:bb:0e:62:8c:a6:08:00\",\"OUT\":\"vlan179\",\"PREC\":\"0x00\",\"PROTO\":\"TCP\",\"RES\":\"0x00\",\"SPT\":\"40194\",\"SRC\":\"2.3.4.5\",\"SYN\":\"\",\"TOS\":\"0x00\",\"TTL\":\"241\",\"URGP\":\"0\",\"WINDOW\":\"1024\",\"timestamp\":\"2020-06-17 13:23:30 +0000 UTC\"}\ndroptailer-6d556bd988-4g8gp droptailer 2020-06-17 13:23:34 +0000 UTC {\"ACTION\":\"Accept\",\"DPT\":\"2362\",\"DST\":\"1.2.3.4\",\"ID\":\"44545\",\"IN\":\"vrf104009\",\"LEN\":\"40\",\"MAC\":\"ca:41:f9:80:fa:89:aa:bb:0e:62:8c:a6:08:00\",\"OUT\":\"\",\"PREC\":\"0x00\",\"PROTO\":\"TCP\",\"RES\":\"0x00\",\"SPT\":\"40194\",\"SRC\":\"2.3.4.5\",\"SYN\":\"\",\"TOS\":\"0x00\",\"TTL\":\"242\",\"URGP\":\"0\",\"WINDOW\":\"1024\",\"timestamp\":\"2020-06-17 13:23:34 +0000 UTC\"}\ndroptailer-6d556bd988-4g8gp droptailer 2020-06-17 13:23:10 +0000 UTC {\"ACTION\":\"Accept\",\"DPT\":\"63351\",\"DST\":\"1.2.3.4\",\"ID\":\"11855\",\"IN\":\"vrf104009\",\"LEN\":\"40\",\"MAC\":\"ca:41:f9:80:fa:89:aa:bb:0e:62:8c:a6:08:00\",\"OUT\":\"vlan179\",\"PREC\":\"0x00\",\"PROTO\":\"TCP\",\"RES\":\"0x00\",\"SPT\":\"54589\",\"SRC\":\"2.3.4.5\",\"SYN\":\"\",\"TOS\":\"0x00\",\"TTL\":\"245\",\"URGP\":\"0\",\"WINDOW\":\"1024\",\"timestamp\":\"2020-06-17 13:23:10 +0000 UTC\"}\ndroptailer-6d556bd988-4g8gp droptailer 2020-06-17 13:23:51 +0000 UTC {\"ACTION\":\"Accept\",\"DPT\":\"8002\",\"DST\":\"1.2.3.4\",\"ID\":\"17539\",\"IN\":\"vrf104009\",\"LEN\":\"40\",\"MAC\":\"ca:41:f9:80:fa:89:aa:bb:0e:62:8c:a6:08:00\",\"OUT\":\"\",\"PREC\":\"0x00\",\"PROTO\":\"TCP\",\"RES\":\"0x00\",\"SPT\":\"47615\",\"SRC\":\"2.3.4.5\",\"SYN\":\"\",\"TOS\":\"0x08\",\"TTL\":\"239\",\"URGP\":\"0\",\"WINDOW\":\"1024\",\"timestamp\":\"2020-06-17 13:23:51 +0000 UTC\"}\n```\n\nYou can forward the droptailer logs to any log aggregation infrastructure you have in place.\n\nIf enabled in the firewall spec, accepted connections can be logged in addition to dropped connections.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetal-stack%2Ffirewall-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmetal-stack%2Ffirewall-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetal-stack%2Ffirewall-controller/lists"}