-
Notifications
You must be signed in to change notification settings - Fork 2
nftables formula #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
nftables formula #61
Changes from all commits
80e10ac
85dd5cb
bfb3e8d
96573f3
045bb85
43e488a
1eee500
93886ae
3240740
605572e
e121717
730c448
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| {%- from 'nftables/map.jinja' import dir, nft, nft_chains, nft_variables, nft_sets, nft_maps, nft_vmaps -%} | ||
| {{ pillar.get('managed_by_salt_formula', '# Managed by the nftables formula') }} | ||
|
|
||
| {#- -#} | ||
| {{ nft_variables(config.get('variables', {})) }} | ||
|
|
||
| {#- -#} | ||
| {{ nft_sets(config.get('sets', {})) }} | ||
|
|
||
| {#- -#} | ||
| {%- if config.get('mode', 'active') == 'passive' %} | ||
| {%- if 'chains' in config %} | ||
| {{ nft_chains(config['chains']) }} | ||
| {%- endif %} | ||
| {%- if 'maps' in config %} | ||
| {{ nft_maps(config['maps']) }} | ||
| {%- endif -%} | ||
| {%- if 'vmaps' in config %} | ||
| {{ nft_vmaps(config['vmaps']) }} | ||
| {%- endif %} | ||
| {%- endif %} | ||
|
|
||
| {#- -#} | ||
| {%- for table, table_config in config.get('tables', {}).items() %} | ||
| table {{ table }}{{ ' ' ~ table_config['type'] if 'type' in table_config else '' }} { | ||
| {%- if 'include' in table_config %} | ||
| {%- if table_config['include'] is string %} | ||
| {%- set table_includes = [table_config['include']] %} | ||
| {%- elif table_config['include'] is iterable and table_config['include'] is not mapping %} | ||
| {%- set table_includes = table_config['include'] %} | ||
| {%- else %} | ||
| {%- do salt.log.error('nftables: illegal value for include in table ' ~ table) %} | ||
| {%- endif %} | ||
| {%- for table_include in table_includes %} | ||
| {%- if table_include in nft and nft[table_include].get('mode') == 'passive' %} | ||
| {%- set lowinclude = dir ~ '/passive/' ~ table_include ~ '.conf' -%} | ||
| {%- else %} | ||
| {%- set lowinclude = table_include -%} | ||
| {%- endif %} | ||
| include "{{ lowinclude }}" | ||
| {%- endfor %} | ||
| {%- endif -%} | ||
| {{ nft_chains(table_config.get('chains', {})) | indent(2) }} | ||
| } | ||
| {%- endfor %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| {%- from 'nftables/map.jinja' import nft, dir %} | ||
|
|
||
| #nftables_packages: | ||
| # pkg.installed: | ||
| # - pkgs: | ||
| # - nftables-service | ||
|
|
||
| nftables_directory: | ||
| file.directory: | ||
| - names: | ||
| - {{ dir }}/active | ||
| - {{ dir }}/passive | ||
| - makedirs: true | ||
|
|
||
| nftables_config_base: | ||
| file.managed: | ||
| - name: /etc/nftables.conf | ||
| - contents: | | ||
| #!/usr/sbin/nft -f | ||
| include "{{ dir }}/active/*.conf" | ||
|
|
||
| {%- for category, config in nft.items() %} | ||
|
|
||
| nftables_config_{{ category }}: | ||
| file.managed: | ||
| - name: | ||
| {%- set file = category ~ '.conf' -%} | ||
| {%- if 'priority' in config -%} | ||
| {%- set file = config['priority'] ~ '_' ~ file -%} | ||
| {%- endif -%} | ||
| {{ ' ' ~ dir }}/{{ config.get('mode', 'active') }}/{{ file }} | ||
| - template: jinja | ||
| - source: salt://{{ slspath }}/files/nftables.j2 | ||
| - context: | ||
| config: {{ config }} | ||
| {%- endfor %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| {%- macro nft_sets(sets) -%} | ||
| {%- for set, set_config in sets.items() %} | ||
| set {{ set }} = | ||
| {%- if 'type' in set_config %} | ||
| type {{ set_config['type'] }} | ||
| {%- endif %} | ||
| {{ nft_flags(set_config.get('flags', none)) }} | ||
| {%- if set_config.get('auto-merge', False) %} | ||
| auto-merge | ||
| {%- endif %} | ||
| {%- if set_config.get('counter', False) %} | ||
| counter | ||
| {%- endif %} | ||
| {%- if 'policy' in set_config %} | ||
| policy {{ set_config['policy'] }} | ||
| {%- endif %} | ||
| {%- if 'timeout' in set_config %} | ||
| timeout {{ set_config['timeout'] }} | ||
| {%- endif %} | ||
| elements = { | ||
| {%- for element in set_config.get('elements', []) %} | ||
| {{ element }}, | ||
| {%- endfor %} | ||
| } | ||
| {%- endfor %} | ||
| {%- endmacro -%} | ||
|
|
||
| {%- macro nft_variables(variables) -%} | ||
| {%- for variable, contents in variables.items() %} | ||
| define {{ variable }} ={{ ' ' }} | ||
| {%- if contents is string -%} | ||
| {{ contents }} | ||
| {%- elif contents is iterable and contents is not mapping -%} | ||
| { | ||
| {%- for value in contents %} | ||
| {{ value }}, | ||
| {%- endfor %} | ||
| } | ||
| {%- endif -%} | ||
| {%- endfor -%} | ||
| {%- endmacro -%} | ||
|
|
||
| {%- macro nft_chains(chains) -%} | ||
| {%- for chain, chain_config in chains.items() %} | ||
| chain {{ chain }} { | ||
| {%- if 'type' in chain_config %} | ||
| type {{ chain_config['type'] }} | ||
| {%- if 'hook' in chain_config -%} | ||
| {{ ' hook ' ~ chain_config['hook'] }} | ||
| {%- endif -%} | ||
| {%- if 'priority' in chain_config -%} | ||
| {{ ' priority ' ~ chain_config['priority'] }} | ||
| {%- endif -%} | ||
| {%- endif %} | ||
| {%- if 'policy' in chain_config %} | ||
| policy {{ chain_config['policy'] }} | ||
| {%- endif %} | ||
| {%- if 'jump' in chain_config %} | ||
| {%- if chain_config['jump'] is string %} | ||
| {%- set chain_jumps = [chain_config['jump']] %} | ||
| {%- elif chain_config['jump'] is iterable and chain_config['jump'] is not mapping %} | ||
| {%- set chain_jumps = chain_config['jump'] %} | ||
| {%- else %} | ||
| {%- do salt.log.error('nftables: illegal value for jump in chain ' ~ chain) %} | ||
| {%- endif %} | ||
| {%- for chain_jump in chain_jumps %} | ||
| jump {{ chain_jump }} | ||
| {%- endfor %} | ||
| {%- endif %} | ||
| {%- if 'maps' in chain_config %} | ||
| {{ nft_maps(chain_config['maps']) | indent(2) }} | ||
| {%- endif -%} | ||
| {%- if 'vmaps' in chain_config %} | ||
| {{ nft_vmaps(chain_config['vmaps']) | indent(2) }} | ||
| {%- endif %} | ||
| {%- for entry in chain_config.get('rules', []) %} | ||
| {{ entry }} | ||
| {%- endfor %} | ||
| {%- if chain_config.get('counter', False) %} | ||
| counter | ||
| {%- endif %} | ||
| {%- if 'log' in chain_config %} | ||
| {%- set log_config = chain_config['log'] %} | ||
| log{{ ' prefix "' ~ log_config['prefix'] ~ '"' if 'prefix' in log_config else '' }}{{ nft_flags(log_config.get('flags', none), ' ') }} | ||
| {%- endif %} | ||
| } | ||
| {%- endfor -%} | ||
| {%- endmacro -%} | ||
|
|
||
| {%- macro nft_flags(flags, prefix='') -%} | ||
| {%- if flags is not none -%} | ||
| {%- if flags is string or ( flags is iterable and flags is not mapping ) -%} | ||
| {{ prefix }}flags {{ flags if flags is string else ' '.join(flags) }} | ||
| {%- else -%} | ||
| {%- do salt.log.error('nftables: illegal flags') -%} | ||
| {%- endif -%} | ||
| {%- endif %} | ||
| {%- endmacro -%} | ||
|
|
||
| {%- macro _nft_maps(maps, type) -%} | ||
| {%- for map, map_config in maps.items() %} | ||
| {{ map }} {{ type }} { | ||
| {%- for map_from, map_to in map_config.items() %} | ||
| {{ map_from }} : {{ map_to }} | ||
| {%- endfor %} | ||
| } | ||
| {%- endfor %} | ||
| {%- endmacro -%} | ||
|
|
||
| {%- macro nft_maps(maps) -%} | ||
| {{ _nft_maps(maps, 'map') }} | ||
| {%- endmacro -%} | ||
|
|
||
| {%- macro nft_vmaps(vmaps) -%} | ||
| {{ _nft_maps(vmaps, 'vmap') }} | ||
| {%- endmacro -%} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| {%- set mypillar = salt['pillar.get']('nftables', {}) -%} | ||
| {%- set nft = mypillar.get('config', {}) -%} | ||
| {%- set dir = '/etc/nftables.conf.d/salt' -%} | ||
| {%- from 'nftables/macros.jinja' import nft_chains, nft_variables, nft_sets, nft_maps, nft_vmaps -%} | ||
| {%- set nft_chains = nft_chains -%} | ||
| {%- set nft_sets = nft_sets -%} | ||
| {%- set nft_variables = nft_variables -%} | ||
| {%- set nft_maps = nft_maps -%} | ||
| {%- set nft_vmaps = nft_vmaps -%} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| nftables: | ||
| config: | ||
| testchain: | ||
| # passive configurations will not be included in the top nftables.conf and can be referenced in lower "includes" | ||
| mode: passive | ||
| chains: | ||
| forward: | ||
| type: filter | ||
| rules: | ||
| - ct state established, related accept | ||
| sets: | ||
| mode: passive | ||
| sets: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there needs to be a layer for inet/ip/ip6 here.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate, do you mean some abstraction which will generate sets for the different families? Currently I just build
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how do you decide if a set should go into which is might be needed if you want to use sets in nat rules . those can not live in
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That depends on where you include the file you define the set in. In the example pillar, a configuration file Edit: Maybe I should make it more clear that the key names underneath |
||
| myv6net: | ||
| type: ipv6_addr | ||
| flags: interval | ||
| auto-merge: true | ||
| elements: | ||
| - 127.0.0.1/128 | ||
| - $mylan | ||
| variables: | ||
| priority: 01 | ||
| variables: | ||
| vpn_ranges: | ||
| - 192.168.0.0/24 | ||
| - 192.168.1.0/24 | ||
| myhost: 192.168.0.1/32 | ||
| tables: | ||
| priority: 02 | ||
| tables: | ||
| nat: | ||
| # if the include matches the name of a passive configuration, it will be expanded to its path | ||
| # multiple includes can be passed using a list | ||
| include: sets | ||
| inet: | ||
| type: filter | ||
| chains: | ||
| input: | ||
| type: filter | ||
| hook: input | ||
| priority: 0 | ||
| policy: drop | ||
| counter: true | ||
| log: | ||
| prefix: Denied Inbound | ||
| flags: all | ||
| maps: | ||
| dport: | ||
| 80: 127.0.0.1 | ||
| vmaps: | ||
| iif: | ||
| eth0: jump testchain | ||
| rules: | ||
| - iif external jump input_external | ||
| - ct state established, related accept | ||
| - ct state invalid accept | ||
Uh oh!
There was an error while loading. Please reload this page.