This commit is contained in:
Hrankin, Aleksandr (contracted)
2026-02-19 11:34:13 +00:00
commit f243f440c3
191 changed files with 6183 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
---
- name: validate fail2ban config
listen: "validate and restart fail2ban"
become: true
ansible.builtin.command: fail2ban-client -t
register: f2b_validate
changed_when: false
- name: restart fail2ban
listen: "validate and restart fail2ban"
become: true
ansible.builtin.systemd:
name: fail2ban
state: restarted

View File

@@ -0,0 +1,58 @@
---
- name: install fail2ban + deps
ansible.builtin.apt:
name:
- fail2ban
- python3
- python3-systemd
- nftables
state: present
update_cache: true
become: true
- name: enable & start nftables
ansible.builtin.systemd:
name: nftables
enabled: true
state: started
become: true
- name: ensure fail2ban directories exist
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0755"
loop:
- /etc/fail2ban
- /etc/fail2ban/jail.d
- /etc/fail2ban/filter.d
become: true
- name: deploy /etc/fail2ban/fail2ban.local
ansible.builtin.template:
src: fail2ban.local.j2
dest: /etc/fail2ban/fail2ban.local
owner: root
group: root
mode: "0644"
notify: validate and restart fail2ban
become: true
- name: deploy /etc/fail2ban/jail.local
ansible.builtin.template:
src: jail.local.j2
dest: /etc/fail2ban/jail.local
owner: root
group: root
mode: "0644"
notify: validate and restart fail2ban
become: true
- name: ensure fail2ban enabled and started
ansible.builtin.systemd:
name: fail2ban
enabled: true
state: started
become: true

View File

@@ -0,0 +1,6 @@
[Definition]
loglevel = INFO
logtarget = /var/log/fail2ban.log
socket = /run/fail2ban/fail2ban.sock
pidfile = /run/fail2ban/fail2ban.pid
dbpurgeage = 86400

View File

@@ -0,0 +1,18 @@
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1
findtime = 600
maxretry = 5
bantime = 1h
backend = systemd
banaction = nftables[type=multiport]
[sshd]
enabled = true
port = 25105
filter = sshd
maxretry = 5
findtime = 600
bantime = 1h
mode = aggressive

View File

@@ -0,0 +1,12 @@
---
- name: validate nftables config
ansible.builtin.command:
cmd: nft -c -f /etc/nftables.conf
listen: apply nftables
changed_when: false
- name: reload nftables
ansible.builtin.systemd:
name: nftables
state: reloaded
listen: apply nftables

View File

@@ -0,0 +1,22 @@
---
- name: install nftables
ansible.builtin.apt:
name: nftables
state: present
update_cache: true
notify: apply nftables
- name: deploy nftables config
ansible.builtin.template:
src: "{{ nftables_conf_name }}"
dest: /etc/nftables.conf
owner: root
group: root
mode: "0644"
notify: apply nftables
- name: enable and start nftables service
ansible.builtin.systemd:
name: nftables
enabled: true
state: started

View File

@@ -0,0 +1,36 @@
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
policy drop;
iif "lo" accept
ct state established,related accept
# SSH
tcp dport {{ ssh_port }} accept
# ICMP
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# Proxmox Web/API (LAN only)
ip saddr 192.168.0.0/24 tcp dport 8006 accept
# NTP
ip saddr 192.168.0.0/24 udp dport {{ ntp_port }} accept
}
chain forward {
type filter hook forward priority 0;
policy drop;
}
chain output {
type filter hook output priority 0;
policy accept;
}
}

View File

@@ -0,0 +1,32 @@
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
policy drop;
iif "lo" accept
ct state established,related accept
# SSH
tcp dport {{ ssh_port }} accept
# udp dport {{ ntp_port }} accept
# ICMP
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
}
chain forward {
type filter hook forward priority 0;
policy drop;
}
chain output {
type filter hook output priority 0;
policy accept;
}
}

View File

@@ -0,0 +1,25 @@
---
- name: ensure sshd_config.d directory exists
become: true
file:
path: "/etc/ssh/sshd_config.d"
state: directory
owner: root
group: root
mode: "0755"
- name: deploy sshd config file
become: true
template:
src: "00-sshd_config-hardening.conf.j2"
dest: "/etc/ssh/sshd_config.d/00-sshd_config-hardening.conf"
owner: root
group: root
mode: "0644"
validate: "sshd -t -f %s"
- name: restart SSH service
become: true
service:
name: ssh
state: restarted

View File

@@ -0,0 +1,107 @@
# --- MAIN ---
# Change default port 22 → {{ ssh_port }} (reduces noise from scanners)
Port {{ ssh_port }}
# Optionally limit interfaces (default is all)
# ListenAddress 0.0.0.0 # IPv4
# ListenAddress :: # IPv6
# Allow only SSH protocol version 2 (v1 is insecure)
Protocol 2
# --- AUTHENTICATION ---
# Disable root login (only via sudo)
PermitRootLogin prohibit-password
# Disable password login (keys only)
PasswordAuthentication no
# Disable interactive keyboard auth (OTP, TOTP, etc.)
KbdInteractiveAuthentication no
# Disable challenge-response auth (legacy)
ChallengeResponseAuthentication no
# Enable public key authentication (main method)
PubkeyAuthentication yes
# --- ACCESS ---
# Allow only specific user
# AllowUsers adminuser
# Or alternatively allow a group:
# AllowGroups sshusers
# --- FUNCTION RESTRICTIONS ---
# Disallow empty passwords
PermitEmptyPasswords no
# Disallow user environment modification (~/.ssh/environment)
PermitUserEnvironment no
# Disable X11 forwarding (no GUI sessions)
X11Forwarding no
# Disable TCP forwarding (no tunnels)
AllowTcpForwarding yes
# Disable gateway ports (no external binding)
GatewayPorts no
# Disable VPN tunnels via SSH
PermitTunnel no
# Disable SSH agent forwarding
AllowAgentForwarding yes
# --- ANTI-BRUTEFORCE & STABILITY ---
# Login timeout (20 seconds)
LoginGraceTime 20
# Max 3 auth attempts per connection
MaxAuthTries 3
# Limit simultaneous connections
# Allow 10 new, start dropping at 30, max 60 queued
MaxStartups 10:30:60
# --- SESSION ACTIVITY ---
# Ping client every 300s (5 minutes)
ClientAliveInterval 300
# Disconnect if no response twice
ClientAliveCountMax 2
# Disable TCP keepalive
TCPKeepAlive no
# Skip DNS checks for faster login
UseDNS no
# --- SFTP ---
# Use internal SFTP subsystem
Subsystem sftp internal-sftp
# --- CRYPTOGRAPHY (optional) ---
# Modern key exchange algorithms (if supported)
# KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256
# Modern ciphers
# Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr
# Modern MAC algorithms
# MACs umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com

View File

@@ -0,0 +1,15 @@
---
- name: restart unattended-upgrades
ansible.builtin.service:
name: unattended-upgrades
state: restarted
enabled: true
- name: restart apt timers
ansible.builtin.systemd:
name: "{{ item }}"
state: restarted
enabled: true
loop:
- apt-daily.timer
- apt-daily-upgrade.timer

View File

@@ -0,0 +1,17 @@
```bash
## Проверить, что таймеры включены и “тикают”
systemctl status apt-daily.timer apt-daily-upgrade.timer
systemctl list-timers --all | egrep 'apt-daily|apt-daily-upgrade'
## Проверить, что unattended-upgrades реально запускался
systemctl status unattended-upgrades.service
journalctl -u unattended-upgrades --no-pager -n 200
## Проверить логи и фактические действия
ls -l /var/log/unattended-upgrades/
tail -n 200 /var/log/unattended-upgrades/unattended-upgrades.log
tail -n 200 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
## Быстрый “самотест” (прогон в dry-run)
unattended-upgrade --dry-run --debug
```

View File

@@ -0,0 +1,49 @@
---
- name: ensure required packages are present
ansible.builtin.apt:
name:
- unattended-upgrades
- apt-listchanges
- gpg
state: present
update_cache: true
- name: ensure debian-security repo is present
ansible.builtin.apt_repository:
repo: >-
deb http://deb.debian.org/debian-security
{{ ansible_facts.lsb.codename | default(ansible_facts.distribution_release) }}-security
main contrib non-free non-free-firmware
state: present
filename: debian-security
update_cache: true
notify: restart apt timers
- name: deploy /etc/apt/apt.conf.d/50unattended-upgrades
ansible.builtin.template:
src: 50unattended-upgrades.j2
dest: /etc/apt/apt.conf.d/50unattended-upgrades
owner: root
group: root
mode: "0644"
notify: restart unattended-upgrades
- name: deploy /etc/apt/apt.conf.d/20auto-upgrades
ansible.builtin.template:
src: 20auto-upgrades.j2
dest: /etc/apt/apt.conf.d/20auto-upgrades
owner: root
group: root
mode: "0644"
notify:
- restart unattended-upgrades
- restart apt timers
- name: enable & start apt timers
ansible.builtin.systemd:
name: "{{ item }}"
state: started
enabled: true
loop:
- apt-daily.timer
- apt-daily-upgrade.timer

View File

@@ -0,0 +1,4 @@
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";

View File

@@ -0,0 +1,10 @@
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename}-security";
};
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-Time "03:30";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::MinimalSteps "true";