]> git.apps.os.sepia.ceph.com Git - ceph-cm-ansible.git/commitdiff
public_facing: Add fail2ban support
authorDavid Galloway <dgallowa@redhat.com>
Fri, 10 Feb 2017 21:08:44 +0000 (16:08 -0500)
committerDavid Galloway <dgallowa@redhat.com>
Wed, 1 Mar 2017 23:39:32 +0000 (18:39 -0500)
Signed-off-by: David Galloway <dgallowa@redhat.com>
roles/public_facing/README.rst
roles/public_facing/defaults/main.yml
roles/public_facing/handlers/main.yml [new file with mode: 0644]
roles/public_facing/tasks/fail2ban.yml [new file with mode: 0644]
roles/public_facing/tasks/main.yml
roles/public_facing/templates/f2b.filter.j2 [new file with mode: 0644]
roles/public_facing/templates/f2b.jail.local.j2 [new file with mode: 0644]
roles/public_facing/templates/f2b.service.j2 [new file with mode: 0644]
roles/public_facing/templates/f2b_ufw.conf.j2 [new file with mode: 0644]

index d1bb6d74b4cbd38bb234314080836a834fe852ec..5f24bd4761fb84cbf9757c09bffc4927de1f1039 100644 (file)
@@ -19,10 +19,36 @@ Variables
 
 Defaults
 --------
-Override these in your ansible inventory ``host_vars`` file.
+Defined in ``roles/public_facing/defaults/main.yml``  Override these in the ansible inventory ``host_vars`` file.
 
 ``use_ufw: false`` specifies whether an Ubuntu host should use UFW_
 
+``f2b_ignoreip: "127.0.0.1"``
+``f2b_bantime: "43200"``
+``f2b_findtime: "900"``
+``f2b_maxretry: 5``
+
+``use_fail2ban: true`` specifies whether a host should use fail2ban_
+
+``f2b_services: {}`` is a dictionary listing services fail2ban should monitor.  See example below::
+
+    f2b_services:
+      sshd:
+        enabled: "true"
+        port: "22"
+        maxretry: 3
+        findtime: "3600" # 1hr
+        filter: "sshd"
+        logpath: "{{ sshd_logpath }}"
+      sshd-ddos:
+        enabled: "true"
+        port: "22"
+        maxretry: 3
+        filter: "sshd-ddos"
+        logpath: "{{ sshd_logpath }}"
+
+    # Note: sshd_logpath gets defined automatically in roles/public_facing/tasks/fail2ban.yml
+
 host_vars
 ---------
 If required, define these in your ansible inventory ``host_vars`` file.
@@ -34,14 +60,26 @@ If required, define these in your ansible inventory ``host_vars`` file.
       - "80"
       - "443"
 
+``f2b_filters: {}`` is a dictionary of additional filters fail2ban should use.  For example, our status portal running Cachet has an additional fail2ban service monitoring repeated login attempts to the admin portal.  See filter example::
+
+    f2b_filters:
+      apache-cachet:
+      failregex: "<HOST> .*GET /auth/login.*$"
+
 Common Tasks
 ++++++++++++
 
+These are tasks that are applicable to all our public-facing hosts.
+
 UFW
 ---
 At the time of this writing, we only have one public-facing host that doesn't run Ubuntu -- the nameserver.  Its firewall is managed in the ``nameserver`` role.
 
-Despite having network port ACLs defined for each host in our cloud provider's interface, enabling a firewall local to the system will allow us to block abusive IPs using fail2ban_.
+Despite having network port ACLs defined for each host in our cloud provider's interface, enabling a firewall local to the system will allow us to block abusive IPs using fail2ban.
+
+fail2ban
+--------
+If ``use_fail2ban`` is set to ``true`` this role will install, configure, and enable fail2ban.
 
 
 .. _UFW: https://wiki.ubuntu.com/UncomplicatedFirewall
index 2f405bd8a13e34d8d1dabd8a1f5b9b516a333a5f..0c7567e20d80c915e04cf6b42244614cc3216160 100644 (file)
@@ -7,3 +7,31 @@ use_ufw: false
 # Default to allow SSH traffic.
 ufw_allowed_ports:
   - "22"
+
+# Use fail2ban by default
+use_fail2ban: true
+
+# Defaults for global fail2ban overrides in /etc/fail2ban/jail.local
+# Override in ansible inventory host_vars, group_vars, or some can be
+# overridden by service files in the f2b_services dict.  See README.
+f2b_ignoreip: "127.0.0.1"
+f2b_bantime: "43200" # 12 hours
+f2b_findtime: "900" # 15 minutes
+f2b_maxretry: 5
+
+# Default fail2ban services to block.  This can be overridden in ansible
+# inventory group_vars or host_vars.
+f2b_services:
+  sshd:
+    enabled: "true"
+    port: "22"
+    maxretry: 3
+    findtime: "3600" # 1hr
+    filter: "sshd"
+    logpath: "{{ sshd_logpath }}"
+  sshd-ddos:
+    enabled: "true"
+    port: "22"
+    maxretry: 3
+    filter: "sshd-ddos"
+    logpath: "{{ sshd_logpath }}"
diff --git a/roles/public_facing/handlers/main.yml b/roles/public_facing/handlers/main.yml
new file mode 100644 (file)
index 0000000..99bcd68
--- /dev/null
@@ -0,0 +1,12 @@
+---
+# Restart fail2ban
+- name: restart fail2ban
+  service:
+    name: fail2ban
+    state: restarted
+
+# Reload fail2ban
+- name: reload fail2ban
+  service:
+    name: fail2ban
+    state: reloaded
diff --git a/roles/public_facing/tasks/fail2ban.yml b/roles/public_facing/tasks/fail2ban.yml
new file mode 100644 (file)
index 0000000..362fe58
--- /dev/null
@@ -0,0 +1,77 @@
+---
+- name: Install or update fail2ban
+  package:
+    name: fail2ban
+    state: latest
+
+- name: Check if firewalld is running
+  shell: firewall-cmd --state
+  register: firewalld_status
+  # Don't fail if command not found
+  failed_when: false
+
+- name: Set f2b_banaction if using firewalld
+  set_fact:
+    f2b_banaction: "firewallcmd-ipset"
+  when: firewalld_status.stdout == "running"
+
+- name: Check if UFW is running
+  shell: ufw status | grep Status | cut -d ' ' -f2
+  register: ufw_status
+  # Don't fail if command not found
+  failed_when: false
+
+- name: Set f2b_banaction if using UFW
+  set_fact:
+    f2b_banaction: "ufw"
+  when: ufw_status.stdout == "active"
+
+- name: Write /etc/fail2ban/action.d/ufw.conf if it's missing
+  template:
+    src: f2b_ufw.conf.j2
+    dest: /etc/fail2ban/action.d/ufw.conf
+  when: use_ufw == true
+
+# Any parameters defined in this file overwrite the package-provided jail.conf
+- name: Write global fail2ban defaults
+  template:
+    src: templates/f2b.jail.local.j2
+    dest: /etc/fail2ban/jail.local
+  notify: restart fail2ban
+
+# sshd_logpath is used in the f2b_services dictionary.  fail2ban doesn't know
+# where ssh logs are for services other than sshd so sshd-ddos, for example
+# needs to be told where to look.  For other services (e.g., nginx), the logpath
+# can be set directly in the dict.
+- name: Set sshd_logpath for CentOS/RHEL
+  set_fact:
+    sshd_logpath: "/var/log/messages"
+  when: ansible_os_family == "RedHat"
+
+- name: Set sshd_logpath for Ubuntu
+  set_fact:
+    sshd_logpath: "/var/log/auth.log"
+  when: ansible_os_family == "Debian"
+
+# This makes sure there are no old or malformed service conf files.
+# We'll rewrite them in the next task.
+- name: Clean up local service conf files
+  shell: rm -f /etc/fail2ban/jail.d/*.local
+
+- name: Write fail2ban service conf files
+  template:
+    src: templates/f2b.service.j2
+    dest: "/etc/fail2ban/jail.d/{{ item.key }}.local"
+  with_dict: "{{ f2b_services }}"
+  notify: reload fail2ban
+
+- name: Clean up local filter conf files
+  shell: rm -f /etc/fail2ban/filter.d/*.local
+
+- name: Write fail2ban filter conf files
+  template:
+    src: templates/f2b.filter.j2
+    dest: "/etc/fail2ban/filter.d/{{ item.key }}.local"
+  with_dict: "{{ f2b_filters }}"
+  when: f2b_filters is defined
+  notify: reload fail2ban
index 274c454f0cdc3b7efd929ec7ccf56cc90e5e8e72..7be38dbb1ffe9f6da65143dd190cd96d8c1c98db 100644 (file)
@@ -8,6 +8,11 @@
   tags:
     - always
 
+- include: fail2ban.yml
+  tags:
+    - always
+  when: use_fail2ban == true
+
 ## Individual host tasks
 
 # local_action in the task after this causes 'ansible_host' to change to 'localhost'
diff --git a/roles/public_facing/templates/f2b.filter.j2 b/roles/public_facing/templates/f2b.filter.j2
new file mode 100644 (file)
index 0000000..4cc8df0
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# {{ ansible_managed }}
+#
+[Definition]
+failregex = {{ item.value.failregex }}
diff --git a/roles/public_facing/templates/f2b.jail.local.j2 b/roles/public_facing/templates/f2b.jail.local.j2
new file mode 100644 (file)
index 0000000..65d840c
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# {{ ansible_managed }}
+#
+
+# These are global overrides of jail.conf
+[DEFAULT]
+ignoreip = {{ f2b_ignoreip }}
+bantime = {{ f2b_bantime }}
+findtime = {{ f2b_findtime }}
+maxretry = {{ f2b_maxretry }}
+{% if f2b_banaction is defined %}
+banaction = {{ f2b_banaction }}
+{% endif %}
diff --git a/roles/public_facing/templates/f2b.service.j2 b/roles/public_facing/templates/f2b.service.j2
new file mode 100644 (file)
index 0000000..9d176d2
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# {{ ansible_managed }}
+#
+[{{ item.key }}]
+enabled = {{ item.value.enabled }}
+{% if item.value.maxretry is defined %}
+maxretry = {{ item.value.maxretry }}
+{% endif %}
+{% if item.value.port is defined %}
+port = {{ item.value.port }}
+{% endif %}
+{% if item.value.findtime is defined %}
+findtime = {{ item.value.findtime }}
+{% endif %}
+{% if item.value.logpath is defined %}
+logpath = {{ item.value.logpath }}
+{% endif %}
+{% if item.value.filter is defined %}
+filter = {{ item.value.filter }}
+{% endif %}
diff --git a/roles/public_facing/templates/f2b_ufw.conf.j2 b/roles/public_facing/templates/f2b_ufw.conf.j2
new file mode 100644 (file)
index 0000000..140a02a
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# {{ ansible_managed }}
+#
+# Fail2Ban action configuration file for ufw
+
+[Definition]
+actionstart = 
+actionstop = 
+actioncheck = 
+actionban = ufw insert 1 deny from <ip> to any port <port>
+actionunban = ufw delete deny from <ip> to any port <port>