main.yml 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. ---
  2. - name: Ensure nftables.d directory exists
  3. ansible.builtin.file:
  4. path: "{{ geo_nft_table_dir }}"
  5. state: directory
  6. owner: root
  7. group: root
  8. mode: '0755'
  9. - name: Create temp directory for zone files
  10. ansible.builtin.tempfile:
  11. state: directory
  12. suffix: geo_zones
  13. register: geo_temp_dir
  14. # --- Source: live download ---
  15. - name: Test connectivity to ipdeny.com (fast pre-check)
  16. ansible.builtin.uri:
  17. url: "{{ geo_ipdeny_base_url }}/us-aggregated.zone"
  18. method: HEAD
  19. timeout: 8
  20. register: geo_connectivity_check
  21. ignore_errors: yes
  22. when: geo_zone_files_dir | length == 0
  23. - name: Fail fast if ipdeny.com is unreachable and no local cache configured
  24. ansible.builtin.fail:
  25. msg: >-
  26. Cannot reach ipdeny.com (connection timed out or refused) and
  27. geo_zone_files_dir is not set. Pre-download zone files on a machine
  28. with internet access using scripts/download-geo-zones.sh, copy them
  29. to this host, then set geo_zone_files_dir in inventory or with -e.
  30. when:
  31. - geo_zone_files_dir | length == 0
  32. - geo_connectivity_check is failed
  33. - name: Download zone files for blocked countries
  34. ansible.builtin.get_url:
  35. url: "{{ geo_ipdeny_base_url }}/{{ item.code | lower }}-aggregated.zone"
  36. dest: "{{ geo_temp_dir.path }}/{{ item.code | lower }}.zone"
  37. timeout: 30
  38. loop: "{{ geo_countries | selectattr('blocked', 'equalto', true) | list }}"
  39. loop_control:
  40. label: "{{ item.code }}"
  41. ignore_errors: yes
  42. when:
  43. - geo_zone_files_dir | length == 0
  44. - geo_connectivity_check is succeeded
  45. # --- Source: local pre-downloaded cache ---
  46. - name: Copy zone files from local cache directory
  47. ansible.builtin.copy:
  48. src: "{{ geo_zone_files_dir }}/{{ item.code | lower }}.zone"
  49. dest: "{{ geo_temp_dir.path }}/{{ item.code | lower }}.zone"
  50. remote_src: yes
  51. loop: "{{ geo_countries | selectattr('blocked', 'equalto', true) | list }}"
  52. loop_control:
  53. label: "{{ item.code }}"
  54. ignore_errors: yes
  55. when: geo_zone_files_dir | length > 0
  56. # --- Assemble and deploy ---
  57. - name: Assemble all CIDRs from downloaded zone files
  58. ansible.builtin.shell: >
  59. cat {{ geo_temp_dir.path }}/*.zone 2>/dev/null |
  60. grep -v '^#' | grep -v '^$' | sort -u
  61. register: geo_cidrs_raw
  62. changed_when: false
  63. - name: Set geo_blocked_cidrs fact
  64. ansible.builtin.set_fact:
  65. geo_blocked_cidrs: "{{ geo_cidrs_raw.stdout_lines }}"
  66. - name: Deploy geo-block nftables ruleset
  67. ansible.builtin.template:
  68. src: geo-block.nft.j2
  69. dest: "{{ geo_nft_file }}"
  70. owner: root
  71. group: root
  72. mode: '0644'
  73. backup: yes
  74. notify: reload nftables
  75. - name: Ensure nftables.conf includes geo-block.nft
  76. ansible.builtin.lineinfile:
  77. path: /etc/sysconfig/nftables.conf
  78. line: 'include "{{ geo_nft_file }}"'
  79. state: present
  80. backup: yes
  81. - name: Enable and start nftables service
  82. ansible.builtin.service:
  83. name: nftables
  84. state: started
  85. enabled: yes
  86. - name: Clean up temp directory
  87. ansible.builtin.file:
  88. path: "{{ geo_temp_dir.path }}"
  89. state: absent