feat: enhance Ansible playbook with security and timezone configurations

- Add fail2ban installation and configuration for SSH, Nginx, and Docker
- Implement kernel security parameter adjustments to mitigate DDoS and spoofing attacks
- Set timezone to Europe/Moscow
- Update SSH configuration to use port 15722 and close the default port 22
- Enhance UFW rules to allow new SSH port and restrict access to essential services
- Include checks for fail2ban status and debug output for verification
This commit is contained in:
2025-09-16 16:41:54 +03:00
parent a1586e78b3
commit 8673cb4f55

View File

@@ -52,8 +52,14 @@
- traceroute
- ncdu
- prometheus-node-exporter
- fail2ban
- tzdata
state: present
- name: Установить часовой пояс Europe/Moscow
timezone:
name: Europe/Moscow
- name: Проверить существование swap-файла
stat:
path: /swapfile
@@ -99,6 +105,77 @@
state: present
create: yes
# --- НАСТРОЙКА БЕЗОПАСНОСТИ ЯДРА ---
- name: Настроить параметры безопасности ядра
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
state: present
reload: yes
loop:
# Защита от DDoS
- { name: "net.ipv4.tcp_syn_retries", value: "2" }
- { name: "net.ipv4.tcp_synack_retries", value: "2" }
- { name: "net.ipv4.tcp_max_syn_backlog", value: "2048" }
- { name: "net.ipv4.tcp_fin_timeout", value: "15" }
- { name: "net.ipv4.tcp_keepalive_time", value: "1200" }
- { name: "net.ipv4.tcp_keepalive_intvl", value: "15" }
- { name: "net.ipv4.tcp_keepalive_probes", value: "5" }
- { name: "net.core.netdev_max_backlog", value: "1000" }
- { name: "net.core.somaxconn", value: "65535" }
# Защита от IP спуфинга
- { name: "net.ipv4.conf.all.accept_source_route", value: "0" }
- { name: "net.ipv4.conf.default.accept_source_route", value: "0" }
- { name: "net.ipv6.conf.all.accept_source_route", value: "0" }
- { name: "net.ipv6.conf.default.accept_source_route", value: "0" }
# Защита от фрагментации
- { name: "net.ipv4.conf.all.log_martians", value: "1" }
- { name: "net.ipv4.conf.default.log_martians", value: "1" }
- { name: "net.ipv4.icmp_echo_ignore_broadcasts", value: "1" }
- { name: "net.ipv4.icmp_ignore_bogus_error_responses", value: "1" }
- { name: "net.ipv4.tcp_syncookies", value: "1" }
- { name: "net.ipv4.conf.all.rp_filter", value: "1" }
- { name: "net.ipv4.conf.default.rp_filter", value: "1" }
# Для Docker
- { name: "kernel.pid_max", value: "65536" }
- { name: "kernel.threads-max", value: "4096" }
- { name: "vm.max_map_count", value: "262144" }
- name: Сохранить параметры безопасности в /etc/sysctl.conf
lineinfile:
path: /etc/sysctl.conf
regexp: "^{{ item.name }}\\s*="
line: "{{ item.name }} = {{ item.value }}"
state: present
loop:
# Защита от DDoS
- { name: "net.ipv4.tcp_syn_retries", value: "2" }
- { name: "net.ipv4.tcp_synack_retries", value: "2" }
- { name: "net.ipv4.tcp_max_syn_backlog", value: "2048" }
- { name: "net.ipv4.tcp_fin_timeout", value: "15" }
- { name: "net.ipv4.tcp_keepalive_time", value: "1200" }
- { name: "net.ipv4.tcp_keepalive_intvl", value: "15" }
- { name: "net.ipv4.tcp_keepalive_probes", value: "5" }
- { name: "net.core.netdev_max_backlog", value: "1000" }
- { name: "net.core.somaxconn", value: "65535" }
# Защита от IP спуфинга
- { name: "net.ipv4.conf.all.accept_source_route", value: "0" }
- { name: "net.ipv4.conf.default.accept_source_route", value: "0" }
- { name: "net.ipv6.conf.all.accept_source_route", value: "0" }
- { name: "net.ipv6.conf.default.accept_source_route", value: "0" }
# Защита от фрагментации
- { name: "net.ipv4.conf.all.log_martians", value: "1" }
- { name: "net.ipv4.conf.default.log_martians", value: "1" }
- { name: "net.ipv4.icmp_echo_ignore_broadcasts", value: "1" }
- { name: "net.ipv4.icmp_ignore_bogus_error_responses", value: "1" }
- { name: "net.ipv4.tcp_syncookies", value: "1" }
- { name: "net.ipv4.conf.all.rp_filter", value: "1" }
- { name: "net.ipv4.conf.default.rp_filter", value: "1" }
# Для Docker
- { name: "kernel.pid_max", value: "65536" }
- { name: "kernel.threads-max", value: "4096" }
- { name: "vm.max_map_count", value: "262144" }
- name: Проверить статус swap
command: swapon --show
register: swap_status
@@ -151,6 +228,12 @@
port: "22"
proto: tcp
- name: Разрешить новый SSH порт (15722) перед включением UFW
ufw:
rule: allow
port: "15722"
proto: tcp
- name: Настроить политику UFW по умолчанию
ufw:
policy: deny
@@ -171,6 +254,8 @@
- "9090" # Prometheus
- "3000" # Grafana
- "9100" # Node Exporter
- "80" # HTTP
- "443" # HTTPS
- name: Проверить существование пользователя deploy
getent:
@@ -216,11 +301,16 @@
line: "{{ item.line }}"
backup: yes
loop:
- { regexp: "Port", line: "Port 15722" }
- { regexp: "PermitRootLogin", line: "PermitRootLogin no" }
- { regexp: "PasswordAuthentication", line: "PasswordAuthentication no" }
- { regexp: "PubkeyAuthentication", line: "PubkeyAuthentication yes" }
- { regexp: "AllowUsers", line: "AllowUsers {{ deploy_user }}" }
notify: reload ssh
- name: Переподключиться по новому SSH порту
meta: reset_connection
- name: Удалить /home/prod, если требуется (чистое развертывание)
file:
path: "{{ project_root }}"
@@ -483,6 +573,79 @@
become_user: "{{ deploy_user }}"
tags: ["start_bots"]
# --- НАСТРОЙКА FAIL2BAN ---
- name: Создать конфигурацию Fail2ban для SSH
copy:
content: |
[sshd]
enabled = true
port = 15722
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
dest: /etc/fail2ban/jail.d/sshd.local
owner: root
group: root
mode: '0644'
- name: Создать конфигурацию Fail2ban для Nginx
copy:
content: |
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
findtime = 600
[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
findtime = 600
dest: /etc/fail2ban/jail.d/nginx.local
owner: root
group: root
mode: '0644'
- name: Создать конфигурацию Fail2ban для Docker
copy:
content: |
[docker]
enabled = true
port = 2375,2376
filter = docker
logpath = /var/log/syslog
maxretry = 3
bantime = 3600
findtime = 600
dest: /etc/fail2ban/jail.d/docker.local
owner: root
group: root
mode: '0644'
- name: Включить и запустить Fail2ban
systemd:
name: fail2ban
enabled: yes
state: started
- name: Проверить статус Fail2ban
command: fail2ban-client status
register: fail2ban_status
changed_when: false
- name: Показать статус Fail2ban
debug:
var: fail2ban_status.stdout_lines
# --- НОВОЕ: Проверка портов ---
- name: Пауза на 30 секунд — дать контейнерам запуститься
pause:
@@ -532,24 +695,16 @@
retries: 5
delay: 10
- name: Проверить, что дашборд Node Exporter загружен в Grafana
uri:
url: "http://{{ ansible_host }}:3000/api/search?query=Node%20Exporter%20Full"
method: GET
user: "{{ grafana_admin_user | default('admin') }}"
password: "{{ grafana_admin_password | default('admin') }}"
status_code: 200
register: dashboard_check
retries: 3
delay: 5
- name: Показать информацию о найденных дашбордах
debug:
var: dashboard_check.json
- name: Закрыть старый SSH порт 22 в UFW (финальный шаг)
ufw:
rule: deny
port: "22"
proto: tcp
- name: Проверка запуска ботов завершена — всё работает 🟢
debug:
msg: "Все сервисы запущены и слушают нужные порты."
msg: "Все сервисы запущены и слушают нужные порты. SSH настроен на порт 15722, Fail2ban активен, параметры безопасности ядра применены. Порт 22 закрыт для безопасности."
# handlers для перезагрузки сервисов
handlers: