diff --git a/host_firewall/defaults/main.yml b/host_firewall/defaults/main.yml index 5ec50df..74b4c3f 100644 --- a/host_firewall/defaults/main.yml +++ b/host_firewall/defaults/main.yml @@ -39,6 +39,11 @@ firewall: lapi: port: null clients: {} + # Hosts outside the ring that upload their journal through Traefik over wt0, and the Traefik container port; as + # with lapi, the flows arrive as client -> pod:port. + journal: + port: null + clients: {} # IPv4 port forwards: name -> {daddr, to, tcp: ports, udp: ports}, ports as in # the maps above. Forwarded traffic passes the forward hook, not input. dnat: {} diff --git a/host_firewall/templates/host.nft.j2 b/host_firewall/templates/host.nft.j2 index 3614e44..d6d31c8 100644 --- a/host_firewall/templates/host.nft.j2 +++ b/host_firewall/templates/host.nft.j2 @@ -32,6 +32,8 @@ set {{ name }} { {% set masquerade = firewall.masquerade | default({}, true) | dict2items | rejectattr('value', 'none') | map(attribute='value') | unique | list %} {% set lapi = cluster.lapi | default({}, true) %} {% set lapi_rule = list(lapi.clients) and lapi.port %} +{% set journal = cluster.journal | default({}, true) %} +{% set journal_rule = list(journal.clients) and journal.port %} {% set scrapers = firewall.scrapers | default({}, true) %} {% set forward_guard = firewall.forward_guard | default({}, true) | dict2items | rejectattr('value', 'none') | list %} {% set blocklists = firewall.spamhaus or firewall.firehol %} @@ -95,6 +97,9 @@ table inet host { {{ addr_set('cluster_v6', 'ipv6_addr', cluster.v6) }} {% if lapi_rule %} {{ addr_set('lapi_clients_v4', 'ipv4_addr', lapi.clients) }} +{% endif %} +{% if journal_rule %} + {{ addr_set('journal_clients_v4', 'ipv4_addr', journal.clients) }} {% endif %} {{ addr_set('scrapers_v4', 'ipv4_addr', scrapers.v4) }} {{ addr_set('scrapers_v6', 'ipv6_addr', scrapers.v6) }} @@ -140,11 +145,16 @@ table inet host { # lose their marks. The same mark lets the LAPI clients (@lapi_clients_v4) reach the pod port of the NodePort service # with their own address: Cilium has translated the NodePort before this point, so NetBird would masquerade the flow # to the cilium_host address and the network policy would see world. + # The journal uploaders (@journal_clients_v4) get the same mark on the Traefik pod port: the NetBird allowlist of + # the ingest route checks their own address. chain pod_identity { type filter hook prerouting priority -140; policy accept; iifname "wt0" ct state new ip saddr @cluster_v4 ip daddr {{ cluster.v4.pods }} meta mark set 0x0001bd20 {% if lapi_rule %} iifname "wt0" ct state new ip saddr @lapi_clients_v4 ip daddr {{ cluster.v4.pods }} tcp dport {{ lapi.port }} meta mark set 0x0001bd20 +{% endif %} +{% if journal_rule %} + iifname "wt0" ct state new ip saddr @journal_clients_v4 ip daddr {{ cluster.v4.pods }} tcp dport {{ journal.port }} meta mark set 0x0001bd20 {% endif %} ct state new ip saddr {{ cluster.v4.pods }} ip daddr {{ cluster.v4.pods }} meta mark 0x0001bd21 meta mark set 0 ct state new ip saddr {{ cluster.v4.pods }} ip daddr {{ cluster.v4.pods }} meta mark 0x0001bd22 meta mark set 0