Просмотр исходного кода

nftables: First shot at generating forwarding rules.

  This commit introduces the first bits for forwarding rules for IPv4 + IPv6.
  The policy for the forward chain will be derived as follows:
   * By default the forwarding policy is drop.
   * If »forward_default_policy« in the »firewall« pillar, this value is used
   * If »forward_accept_roles« is set in the »firewall« pillar and at least one
     role of the current node is in this list, the forward policy will be accept.

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
Maximilian Wilhelm 2 лет назад
Родитель
Сommit
a6db6d7f8f
2 измененных файлов с 69 добавлено и 3 удалено
  1. 37 0
      _modules/ffho_netfilter.py
  2. 32 3
      nftables/nftables.conf.tmpl

+ 37 - 0
_modules/ffho_netfilter.py

@@ -85,3 +85,40 @@ def generate_service_rules (services, acls, af):
 		rules.append (rule)
 
 	return rules
+
+
+def generate_forward_policy (policy, roles, config_context):
+	fp = {
+		# Get default policy for packets to be forwarded
+		'policy' : 'drop',
+		'policy_reason' : 'default',
+		'rules': {
+			4 : [],
+			6 : [],
+		},
+	}
+
+	if 'forward_default_policy' in policy:
+		fp['policy'] = policy['forward_default_policy']
+		fp['policy_reason'] = 'forward_default_policy'
+
+	# Does any local role warrants for forwarding packets?
+	accept_roles = [role for role in policy.get ('forward_accept_roles', []) if role in roles]
+	if accept_roles:
+		fp['policy'] = 'accept'
+		fp['policy_reason'] = "roles: " + ",".join (accept_roles)
+
+	try:
+		cust_rules = config_context['filter']['forward']
+		for af in [ 4, 6 ]:
+			if af not in cust_rules:
+				continue
+
+			if type (cust_rules[af]) != list:
+				raise ValueError ("nftables:filter:forward:%d in config context expected to be a list!" % af)
+
+				fp['rules'][af] = cust_rules[af]
+	except KeyError:
+		pass
+
+	return fp

+ 32 - 3
nftables/nftables.conf.tmpl

@@ -2,14 +2,21 @@
 #
 # /etc/nftables.conf - FFHO packet filter configuration
 #
-{%- set roles = salt['pillar.get']('nodes:' ~ grains['id'] ~ ':roles', []) %}
+{%- set node_config = salt['pillar.get']('nodes:' ~ grains['id']) %}
+{%- set nf_cc = node_config.get ('nftables', {}) %}
+{%- set roles = node_config.get ('roles', []) %}
+{%- set services = node_config.get ('services', []) %}
+
+{%- set fw_policy = salt['pillar.get']('firewall:policy', {}) %}
 {%- set acls = salt['pillar.get']('firewall:acls') %}
 {%- set admin_access = salt['pillar.get']('firewall:admin_access') %}
 {%- set ssh = salt['pillar.get']("firewall:ssh") %}
-{%- set services = salt['pillar.get']('nodes:' ~ grains['id'] ~ ':services', []) %}
+
 {%- set icinga2_queriers = salt['pillar.get']('monitoring:icinga2:queriers', []) %}
 {%- set nms_list = salt['pillar.get']('globals:snmp:nms_list', []) %}
 
+{%- set forward = salt['ffho_netfilter.generate_forward_policy'](fw_policy, roles, nf_cc) %}
+
 flush ruleset
 
 table ip filter {
@@ -37,11 +44,22 @@ table ip filter {
 {%- endif %}
 		ct state related,established counter accept
 		counter jump services
-		limit rate 1/second burst 3 packets counter log prefix "netfilter: "
+		limit rate 1/second burst 3 packets counter log prefix "nf input: "
 		limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
 		counter drop
 	}
 
+	chain forward {
+		type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
+{%- for rule in forward['rules'].get ('4', []) %}
+		{{ rule }}
+{%- endfor %}
+{%- if forward['policy'] == 'drop' %}
+		limit rate 1/second burst 3 packets counter log prefix "nf forward: "
+		limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
+{%- endif %}
+	}
+
 	chain icmp_chain {
 		icmp type { echo-request, destination-unreachable, time-exceeded } counter accept
 	}
@@ -124,6 +142,17 @@ table ip6 filter {
 		counter drop
 	}
 
+	chain forward {
+		type filter hook forward priority 0; policy {{ forward['policy'] }}; # {{ forward['policy_reason'] }}
+{%- for rule in forward['rules'].get ('6', []) %}
+		{{ rule }}
+{%- endfor %}
+{%- if forward['policy'] == 'drop' %}
+		limit rate 1/second burst 3 packets counter log prefix "nf forward: "
+		limit rate 1/second burst 3 packets counter reject with icmp type admin-prohibited
+{%- endif %}
+	}
+
 	chain icmp_chain {
 		icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply } counter accept
 		icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert } ip6 hoplimit 255 counter accept