{"id":16961087,"url":"https://github.com/ricsanfre/ansible-role-firewall","last_synced_at":"2026-04-13T20:32:00.660Z","repository":{"id":111459117,"uuid":"395251054","full_name":"ricsanfre/ansible-role-firewall","owner":"ricsanfre","description":"Ansible role for configuring a firewall based on nftables","archived":false,"fork":false,"pushed_at":"2021-09-24T10:51:29.000Z","size":19,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-03T23:50:00.197Z","etag":null,"topics":["ansible","ansible-role","firewall","nftables"],"latest_commit_sha":null,"homepage":"https://galaxy.ansible.com/ricsanfre/firewall","language":"Jinja","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/ricsanfre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-12T08:36:14.000Z","updated_at":"2023-05-12T17:04:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"8184f6b1-bce9-456e-8ae2-94e4aebde045","html_url":"https://github.com/ricsanfre/ansible-role-firewall","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ricsanfre/ansible-role-firewall","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricsanfre%2Fansible-role-firewall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricsanfre%2Fansible-role-firewall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricsanfre%2Fansible-role-firewall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricsanfre%2Fansible-role-firewall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ricsanfre","download_url":"https://codeload.github.com/ricsanfre/ansible-role-firewall/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ricsanfre%2Fansible-role-firewall/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31770718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T20:17:16.280Z","status":"ssl_error","status_checked_at":"2026-04-13T20:17:08.216Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ansible","ansible-role","firewall","nftables"],"created_at":"2024-10-13T22:50:59.173Z","updated_at":"2026-04-13T20:32:00.591Z","avatar_url":"https://github.com/ricsanfre.png","language":"Jinja","funding_links":[],"categories":[],"sub_categories":[],"readme":"Ansible Role: Firewall\n=========\n\n[![CI](https://github.com/ricsanfre/ansible-role-firewall/actions/workflows/ci.yml/badge.svg)](https://github.com/ricsanfre/ansible-role-firewall/actions/workflows/ci.yml)\n\n\nInstall and configure firewall (nftables based) on Linux.\n\nRequirements\n------------\n\nNone.\n\nRole Variables\n--------------\n\nAvailable variables are listed below along with default values (see `defaults\\main.yaml`)\n\n### Enabling NAT and traffic forwarding\n\n* **firewall_forward_enabled** : Enable or disable traffic forwarding support on a given host. [default : `false`].\n* **firewall_nat_enabled** : Enable or disable NAT support on a given host. [default : `false`].\n\n### Define default open ports\n\n* **in_tcp_port** : IN TCP traffic is allowed on these ports. [default : `{ ssh }`].\n* **in_udp_port** : IN UDP traffic is allowed on these ports. [default : `{ snmp }`].\n* **out_tcp_port** : OUT TCP traffic is allowed on these ports. [default : `{ http, https, ssh }`].\n* **out_udp_port** : OUT UDP traffic is allowed on these ports. [default : `{ domain, bootps , ntp }`].\n\n\n### Rules Dictionaries\n\nFor each chain within ip table (input, output, forward) and nat table (nat-prerouting and nat-postrouting), nft rules are stored in  dictionaries that can be overriding at group and host level.\n\n**Variables and definition sets and global rules**\n\nSet of var and set definitions used by the different rule chains and global chain rules that can be invoke from other chain using the rule `jump global` \n\n|define             |sets            | global chain          |\n|-------------------|----------------|-----------------------|\n|nft_define_default |nft_set_default |nft_global_default     |\n|nft_define_group   |nft_set_group   |nft_global_group_rules |\n|nft_define_host    |nft_set_host    |nft_global_host_rules  |\n\n\n**IP table rules**\n\n|input chain             |output chain             | forward chain            |\n|------------------------|-------------------------|--------------------------|\n|nft_input_default_rules |nft_output_default_rules |nft_forward_default_rules |\n|nft_input_group_rules   |nft_output_group_rules   |nft_forward_group_rules   |\n|nft_input_host_rules    |nft_output_host_rules    |nft_forward_host_rules    |\n\n**Nat table rules**\n\n|prerouting chain                 |postrouting chain                 |\n|---------------------------------|----------------------------------|\n|nft_nat_default_prerouting_rules |nft_nat_default_postrouting_rules |\n|nft_nat_group_prerouting_rules   |nft_nat_group_postrouting_rules   |\n|nft_nat_host_prerouting_rules    |nft_nat_host_postrouting_rules    |\n\nEach type of rules dictionaries will be merged and rules will be applied in the alphabetical order of the keys (the reason to use 000 to 999 as prefix). So :\n  * **nft_*_default_rules** : Define default rules for all nodes. You can define it in `group_vars/all`.\n  * **nft_*_group_rules** : Can add rules and override those defined by **nft_*_default_rules** and **nft_*_rules**. You can define it in `group_vars/group_servers`.\n  * **nft_*_host_rules** : Can add rules and override those define by **nft_*_default_rules**, **nft_*_group_rules** and **nft_*_rules**. You can define it in `host_vars/specific_host`.\n\n\n## Default nftables configuration\n\nBy default the role will generate the following configurations file:\n\n`/etc/nftables.conf`\n\n```\n#!/usr/sbin/nft -f\n# Ansible managed\n\n# clean\nflush ruleset\n\ninclude \"/etc/nftables.d/defines.nft\"\n\ntable inet filter {\n\tchain global {\n\t\t# 000 state management\n\t\tct state established,related accept\n\t\tct state invalid drop\n\t}\n\tinclude \"/etc/nftables.d/sets.nft\"\n\tinclude \"/etc/nftables.d/filter-input.nft\"\n\tinclude \"/etc/nftables.d/filter-output.nft\"\n}\n```\n\n`/etc/nftables.d/defines.nft`\n\n```\n\n  # broadcast and multicast\n  define badcast_addr = { 255.255.255.255, 224.0.0.1, 224.0.0.251 }\n\n  # broadcast and multicast\n  define ip6_badcast_addr = { ff02::16 }\n\n  # in_tcp_accept\n  define in_tcp_accept = { ssh }\n\n  # in_udp_accept\n  define in_udp_accept = { snmp }\n\n  # out_tcp_accept\n  define out_tcp_accept = { http, https, ssh }\n\n  # out_udp_accept\n  define out_udp_accept = { domain, bootps , ntp }\n\n```\n\n`/etc/nftables.d/sets.nft`\n\n```\n  set blackhole {\n        type ipv4_addr;\n        elements = $badcast_addr\n    }\n\n  set in_tcp_accept {\n        type inet_service; flags interval;\n        elements = $in_tcp_accept\n    }\n\n  set in_udp_accept {\n        type inet_service; flags interval;\n        elements = $in_udp_accept\n    }\n\n  set ip6blackhole {\n        type ipv6_addr;\n        elements = $ip6_badcast_addr\n    }\n\n  set out_tcp_accept {\n        type inet_service; flags interval;\n        elements = $out_tcp_accept\n    }\n\n  set out_udp_accept {\n        type inet_service; flags interval;\n        elements = $out_udp_accept\n    }\n\n```\n\n`/etc/nftables.d/filter-input.nft`\n\n```\nchain input {\n        # 000 policy\n        type filter hook input priority 0; policy drop;\n        # 005 global\n        jump global\n        # 010 drop unwanted\n        ip daddr @blackhole counter drop\n        # 011 drop unwanted ipv6\n        ip6 daddr @ip6blackhole counter drop\n        # 015 localhost\n        iif lo accept\n        # 050 icmp\n        meta l4proto {icmp,icmpv6} accept\n        # 200 input udp accepted\n        udp dport @in_udp_accept ct state new accept\n        # 210 input tcp accepted\n        tcp dport @in_tcp_accept ct state new accept\n  }\n\n```\n\n`/etc/nftables.d/filter-output.nft`\n\n```\nchain output {\n        # 000 policy\n        type filter hook output priority 0; policy drop;\n        # 005 global\n        jump global\n        # 015 localhost\n        oif lo accept\n        # 050 icmp\n        ip protocol icmp accept\n        ip6 nexthdr icmpv6 counter accept\n        # 200 output udp accepted\n        udp dport @out_udp_accept ct state new accept\n        # 210 output tcp accepted\n        tcp dport @out_tcp_accept ct state new accept\n        # 250 reset-ssh\n        tcp sport ssh tcp flags { rst, psh | ack } counter accept\n  }\n```\n\n\nAnd the followint ruleset on the host (showed executing `nft list ruleset` command):\n\n```\ntable inet filter {\n        set blackhole {\n                type ipv4_addr\n                elements = { 224.0.0.1, 224.0.0.251,\n                             255.255.255.255 }\n        }\n\n        set in_tcp_accept {\n                type inet_service\n                flags interval\n                elements = { 22 }\n        }\n\n        set in_udp_accept {\n                type inet_service\n                flags interval\n                elements = { 161 }\n        }\n\n        set ip6blackhole {\n                type ipv6_addr\n                elements = { ff02::16 }\n        }\n\n        set out_tcp_accept {\n                type inet_service\n                flags interval\n                elements = { 22, 80, 443 }\n        }\n\n        set out_udp_accept {\n                type inet_service\n                flags interval\n                elements = { 53, 67, 123 }\n        }\n\n        chain global {\n                ct state established,related accept\n                ct state invalid drop\n        }\n\n        chain input {\n                type filter hook input priority filter; policy drop;\n                jump global\n                ip daddr @blackhole counter packets 0 bytes 0 drop\n                ip6 daddr @ip6blackhole counter packets 0 bytes 0 drop\n                iif \"lo\" accept\n                meta l4proto { icmp, ipv6-icmp } accept\n                udp dport @in_udp_accept ct state new accept\n                tcp dport @in_tcp_accept ct state new accept\n        }\n\n        chain output {\n                type filter hook output priority filter; policy drop;\n                jump global\n                oif \"lo\" accept\n                ip protocol icmp accept\n                ip6 nexthdr ipv6-icmp counter packets 0 bytes 0 accept\n                udp dport @out_udp_accept ct state new accept\n                tcp dport @out_tcp_accept ct state new accept\n                tcp sport 22 tcp flags { rst, psh | ack } counter packets 0 bytes 0 accept\n        }\n}\n\n```\n\n\nDependencies\n------------\n\nNone\n\nExample Playbooks\n-----------------\n\n### Apply default rules\n\nInstall and configure a firewall on a host with default rules\n\n```\n- hosts: serverx\n  roles:\n    - ricsanfre.firewall\n```\n\nin `group_vars/all.yml` you could override the default rules for all your hosts:\n\n```yml\nnft_input_default_rules:\n  000 policy:\n    - type filter hook input priority 0; policy drop;\n  005 global:\n    - jump global\n  010 drop unwanted:\n    - ip daddr @blackhole counter drop\n  011 drop unwanted ipv6:\n    - ip6 daddr @ip6blackhole counter drop\n  015 localhost:\n    - iif lo accept\n  050 icmp:\n    - meta l4proto {icmp,icmpv6} accept\n  200 input udp accepted:\n    - udp dport @in_udp_accept ct state new accept\n  210 input tcp accepted:\n    - tcp dport @in_tcp_accept ct state new accept\n```\n\n### Modify default rules at group level\n\nOpenning HTTP incoming traffic for `webservers` group:\n\nIn `group_vars/webservers.yml` this can be done modifying `in_tcp_port` :\n\n```yml\nin_tcp_port: { ssh, http }\n```\n\nOr adding a new specific rule\n\n```yml\nnft_input_group_rule:\n  220 input web accepted:\n    - tcp dport http ct state new accept\n```\n\n### Modify defaults + group rules at host level\n\nOpenning HTTPS incoming traffic for `secureweb` host\nin `host_vars/secureweb.yml` you would want to open https and remove access to http:\n\n```yml\nnft_input_group_rule:\n  220 input web accepted: []\n  230 input secure web accepted:\n    - tcp dport https ct state new accept\n```\n\n### Default rules can be deleted\n\nTo \"delete\" rules, you just assign an empty list to an existing dictionary key:\nExample: remove disable ICMP incoming traffic\n\n```yml\nnft_input_host_rules:\n  050 icmp: []\n```\n\nRemove default rules for allowing all outgoing traffic. in a specific `group_vars/group.yml`\n\n```yml\nnft_output_group_rules:\n  000 policy:\n    - type filter hook output priority 0;\n  005 global:\n    -\n  015 localhost:\n    -\n  050 icmp:\n    -\n  200 output udp accepted:\n    -\n  210 output tcp accepted:\n    -\n  250 reset-ssh:\n    -\n```\n\n`000 policy` default rule is overridden to accept all traffic and the rest of rules are removed.\n\nTo summarize, rules in `nft_X_host_rules` will overwrite rules in `nft_X_group_rules`, and then rules in `nft_X_group_rules` will overwrite rules in `nft_X_default_rules`.\n\n\nLicense\n-------\n\nMIT/BSD\n\nAuthor Information\n------------------\n\nRicardo Sanchez (ricsanfre)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fricsanfre%2Fansible-role-firewall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fricsanfre%2Fansible-role-firewall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fricsanfre%2Fansible-role-firewall/lists"}