diff --git a/ansible/host_vars/casey.yml b/ansible/host_vars/casey.yml index 5416696..e1b093a 100644 --- a/ansible/host_vars/casey.yml +++ b/ansible/host_vars/casey.yml @@ -1 +1,2 @@ nebula_is_lighthouse: true +ssh_extra_allowed_users: f2b@{{ nebula.cidr }} f2b@{{ pve_hosts.internal_cidr }} diff --git a/ansible/host_vars/pve-docker.yml b/ansible/host_vars/pve-docker.yml index a6dbb2c..6ffa9ce 100644 --- a/ansible/host_vars/pve-docker.yml +++ b/ansible/host_vars/pve-docker.yml @@ -3,3 +3,5 @@ private_ip: "{{ pve_hosts.pve_docker.ip }}" traefik_provider_jellyfin: true traefik_provider_homeassistant: true traefik_provider_grafana: true + +with_fail2ban: true diff --git a/ansible/main.yml b/ansible/main.yml index 44070c4..8c719ba 100644 --- a/ansible/main.yml +++ b/ansible/main.yml @@ -8,6 +8,7 @@ roles: - gateway - nebula + - fail2ban_ssh - hosts: - pve diff --git a/ansible/roles/base/defaults/main.yml b/ansible/roles/base/defaults/main.yml new file mode 100644 index 0000000..ea6f5f3 --- /dev/null +++ b/ansible/roles/base/defaults/main.yml @@ -0,0 +1 @@ +ssh_extra_allowed_users: "" diff --git a/ansible/roles/base/files/sshd_config b/ansible/roles/base/files/sshd_config index cede24c..4a69245 100644 --- a/ansible/roles/base/files/sshd_config +++ b/ansible/roles/base/files/sshd_config @@ -2,7 +2,7 @@ # Change to a high/odd port if this server is exposed to the internet directly Port {{ ssh_port }} -AllowUsers {% if ansible_hostname in pve_hosts %}{{ user }}@{{ pve_hosts.internal_cidr }}{% endif %} {% if ansible_hostname in nebula.clients %}{{ user }}@{{ nebula.cidr }}{% endif %} +AllowUsers {% if ansible_hostname in pve_hosts %}{{ user }}@{{ pve_hosts.internal_cidr }}{% endif %} {% if ansible_hostname in nebula.clients %}{{ user }}@{{ nebula.cidr }}{% endif %} {{ ssh_extra_allowed_users }} # Bind to all interfaces (change to specific interface if needed) ListenAddress 0.0.0.0 diff --git a/ansible/roles/fail2ban_ssh/defaults/main.yml b/ansible/roles/fail2ban_ssh/defaults/main.yml new file mode 100644 index 0000000..48ce2a0 --- /dev/null +++ b/ansible/roles/fail2ban_ssh/defaults/main.yml @@ -0,0 +1 @@ +f2b_user: f2b diff --git a/ansible/roles/fail2ban_ssh/files/f2b-entrypoint.sh b/ansible/roles/fail2ban_ssh/files/f2b-entrypoint.sh new file mode 100644 index 0000000..ccfe93c --- /dev/null +++ b/ansible/roles/fail2ban_ssh/files/f2b-entrypoint.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +# Remove `-c` argument +shift + +sudo fail2ban-client $@ diff --git a/ansible/roles/fail2ban_ssh/tasks/main.yml b/ansible/roles/fail2ban_ssh/tasks/main.yml new file mode 100644 index 0000000..5da9cc7 --- /dev/null +++ b/ansible/roles/fail2ban_ssh/tasks/main.yml @@ -0,0 +1,27 @@ +- name: Make user + user: + name: "{{ f2b_user }}" + comment: "{{ name }}" + shell: /home/{{ f2b_user }}/f2b-entrypoint.sh + system: false + become: true + +- name: Give user sudo access to client + lineinfile: + path: /etc/sudoers + line: "{{ f2b_user }} ALL=(ALL) NOPASSWD: /usr/bin/fail2ban-client" + become: true + +- name: Allow custom shell + lineinfile: + path: /etc/shells + line: /home/{{ f2b_user }}/f2b-entrypoint.sh + become: true + +- name: Create entrypoint + template: + src: files/f2b-entrypoint.sh + dest: /home/{{ f2b_user }}/f2b-entrypoint.sh + mode: 0755 + become: true + register: sshd_config diff --git a/ansible/roles/traefik/defaults/main.yml b/ansible/roles/traefik/defaults/main.yml index b13e5c2..87d632c 100644 --- a/ansible/roles/traefik/defaults/main.yml +++ b/ansible/roles/traefik/defaults/main.yml @@ -3,3 +3,4 @@ traefik_provider_homeassistant: false traefik_provider_grafana: false with_traefik_pages: false +with_fail2ban: false diff --git a/ansible/roles/traefik/files/docker-compose.yml b/ansible/roles/traefik/files/docker-compose.yml index 631eb34..1080608 100644 --- a/ansible/roles/traefik/files/docker-compose.yml +++ b/ansible/roles/traefik/files/docker-compose.yml @@ -8,5 +8,6 @@ services: - CF_DNS_API_TOKEN={{ cloudflare_api_token }} volumes: - /var/run/docker.sock:/var/run/docker.sock:ro + - /tmp/traefik-logs:/var/log/traefik - ./traefik:/etc/traefik restart: unless-stopped diff --git a/ansible/roles/traefik/files/fail2ban/traefik-filter.conf b/ansible/roles/traefik/files/fail2ban/traefik-filter.conf new file mode 100644 index 0000000..4f670ca --- /dev/null +++ b/ansible/roles/traefik/files/fail2ban/traefik-filter.conf @@ -0,0 +1,4 @@ +[Definition] +failregex = ^ \- \S+ \[\] \"(GET|POST|HEAD) .+\" .+$ +ignoreregex = +mode = normal diff --git a/ansible/roles/traefik/files/fail2ban/traefik-jail.conf b/ansible/roles/traefik/files/fail2ban/traefik-jail.conf new file mode 100644 index 0000000..ab6137e --- /dev/null +++ b/ansible/roles/traefik/files/fail2ban/traefik-jail.conf @@ -0,0 +1,9 @@ +[traefik] +enabled = true +bantime = 6000 +findtime = 600 +maxretry = 5 +filter = traefik +logpath = /tmp/traefik-logs/access.log +port = http,https +ignoreip = {{ wireguard.cidr }},{{ nebula.cidr }},{{ pve_hosts.internal_cidr }} diff --git a/ansible/roles/traefik/files/logrotate.conf b/ansible/roles/traefik/files/logrotate.conf new file mode 100644 index 0000000..4b98916 --- /dev/null +++ b/ansible/roles/traefik/files/logrotate.conf @@ -0,0 +1,8 @@ +/tmp/traefik-logs/access.log { + daily + rotate 7 + missingok + compress + nodateext + notifempty +} diff --git a/ansible/roles/traefik/files/traefik.yml b/ansible/roles/traefik/files/traefik.yml index 1b5e824..7a79df3 100644 --- a/ansible/roles/traefik/files/traefik.yml +++ b/ansible/roles/traefik/files/traefik.yml @@ -77,3 +77,9 @@ tls: pilot: dashboard: false + +accessLog: + filePath: "/var/log/traefik/access.log" + filters: + statusCodes: + - "400-600" diff --git a/ansible/roles/traefik/handlers/main.yml b/ansible/roles/traefik/handlers/main.yml index 699f0fd..39e4f13 100644 --- a/ansible/roles/traefik/handlers/main.yml +++ b/ansible/roles/traefik/handlers/main.yml @@ -2,3 +2,9 @@ shell: chdir: /opt/traefik cmd: "{{ docker_update_command }}" + +- name: restart fail2ban + service: + name: fail2ban + state: restarted + become: true diff --git a/ansible/roles/traefik/tasks/fail2ban.yml b/ansible/roles/traefik/tasks/fail2ban.yml new file mode 100644 index 0000000..a767fa5 --- /dev/null +++ b/ansible/roles/traefik/tasks/fail2ban.yml @@ -0,0 +1,15 @@ +- name: Create jail + template: + src: files/fail2ban/traefik-jail.conf + dest: /etc/fail2ban/jail.d/traefik.conf + mode: 0644 + become: true + notify: restart fail2ban + +- name: Create filter + template: + src: files/fail2ban/traefik-filter.conf + dest: /etc/fail2ban/filter.d/traefik.conf + mode: 0644 + become: true + notify: restart fail2ban diff --git a/ansible/roles/traefik/tasks/main.yml b/ansible/roles/traefik/tasks/main.yml index b22ab76..64b4074 100644 --- a/ansible/roles/traefik/tasks/main.yml +++ b/ansible/roles/traefik/tasks/main.yml @@ -77,3 +77,14 @@ notify: restart traefik when: traefik_provider_grafana become: true + +- name: logrotate config + template: + src: files/logrotate.conf + dest: /etc/logrotate.d/traefik + mode: "0600" + become: true + +- name: fail2ban + include: fail2ban.yml + when: with_fail2ban