124 lines
4.4 KiB
Markdown
124 lines
4.4 KiB
Markdown
# HAProxy: UFW и hardening
|
||
|
||
Хост: **haproxy.kalinamall.ru**, **192.168.160.117**, Ubuntu 24.04, HAProxy 2.8.x.
|
||
|
||
## Порты на хосте
|
||
|
||
| Порт | Служба | С интернета (MikroTik) | UFW (текущий план) |
|
||
|------|--------|------------------------|---------------------|
|
||
| 22 | sshd | нет DNAT | только `SSH_ALLOWED` |
|
||
| 25 | fe_smtp → KSMG | **нет** (25 → `.57`) | **закрыт** |
|
||
| 80 | fe_http_zabbix | да | все |
|
||
| 443 | fe_https_sni | да | все |
|
||
| 8404 | stats (закомментирован) | нет | только `SSH_ALLOWED` |
|
||
|
||
## UFW — правила
|
||
|
||
Скрипт: [haproxy-ufw-apply.sh](../../scripts/security/haproxy-ufw-apply.sh).
|
||
|
||
```
|
||
default incoming: deny
|
||
default outgoing: allow
|
||
|
||
22/tcp from 5.100.81.121, 192.168.128.0/17
|
||
8404/tcp from 5.100.81.121, 192.168.128.0/17 # если включите fe_stats
|
||
80/tcp from anywhere
|
||
443/tcp from anywhere
|
||
```
|
||
|
||
`192.168.128.0/17` покрывает офисную/VPN-подсеть (в т.ч. `192.168.160.0/24`).
|
||
|
||
Ответный трафик с бэкендов (`.42`, `.129` → высокие порты на `.117`):
|
||
|
||
```
|
||
ufw allow from 192.168.160.0/24 comment 'LAN backends return'
|
||
```
|
||
|
||
(в [haproxy-ufw-apply.sh](../../scripts/security/haproxy-ufw-apply.sh) — `LAN_BACKENDS_CIDR`).
|
||
|
||
### Env
|
||
|
||
`/etc/haproxy/security/haproxy-ufw.env` (из [haproxy-ufw.env.example](../../scripts/security/haproxy-ufw.env.example)):
|
||
|
||
```bash
|
||
SSH_ALLOWED="5.100.81.121 192.168.128.0/17"
|
||
INBOUND_TCP="80 443"
|
||
STATS_TCP="8404"
|
||
UFW_IPV6=no
|
||
```
|
||
|
||
### Внедрение
|
||
|
||
```bash
|
||
sudo mkdir -p /etc/haproxy/security
|
||
sudo cp ~/reverse-proxy/scripts/security/haproxy-ufw.env.example /etc/haproxy/security/haproxy-ufw.env
|
||
sudo bash ~/reverse-proxy/scripts/security/haproxy-ufw-apply.sh
|
||
# вторая SSH-сессия:
|
||
sudo bash ~/reverse-proxy/scripts/security/haproxy-ufw-apply.sh --apply
|
||
sudo ufw status numbered
|
||
```
|
||
|
||
**Откат:** `sudo ufw disable` (временно).
|
||
|
||
### Проверка
|
||
|
||
- SSH с `5.100.81.121` или из `192.168.128.0/17` — OK.
|
||
- SSH с другого IP — timeout/refused.
|
||
- `curl -I http://zabbix.kalinamall.ru` / HTTPS на allowlist-сервис — OK.
|
||
- `ss -tlnp | grep :25` — слушает HAProxy, но UFW + MikroTik не пускают с периметра.
|
||
|
||
## fe_smtp (:25)
|
||
|
||
Inbound-почта с интернета идёт на **KSMG `.57`**, не на HAProxy. `fe_smtp` в `haproxy.cfg` можно оставить для LAN или **отключить**, если не используется — UFW его не открывает.
|
||
|
||
## stats (:8404)
|
||
|
||
В `haproxy.cfg` закомментирован. Если включите — UFW уже ограничит доступ списком `SSH_ALLOWED`; обязательно `stats auth` и не `0.0.0.0` без нужды.
|
||
|
||
## Рекомендуется дополнительно (не блокирует UFW)
|
||
|
||
| Мера | Зачем |
|
||
|------|--------|
|
||
| SSH: ключи, `PermitRootLogin no`, `PasswordAuthentication no` | до/вместе с UFW |
|
||
| fail2ban на sshd | подстраховка SSH |
|
||
| fail2ban на HAProxy JSON | бан сканеров / reject SNI / Zabbix 403 |
|
||
| `unattended-upgrades` | патчи |
|
||
| Не открывать лишние listen | `ss -tlnp` |
|
||
|
||
Опционально позже: sysctl syncookies, rate-limit на frontend, allowlist для Exchange/sac-api.
|
||
|
||
## fail2ban (HAProxy JSON)
|
||
|
||
Скрипт: [fail2ban-install.sh](../../scripts/security/fail2ban-install.sh), конфиги в `scripts/security/fail2ban/`.
|
||
|
||
| Jail | Что ловит |
|
||
|------|-----------|
|
||
| `haproxy-reject` | JSON: `"be":"fe_https_sni","srv":"<NOSRV>"` — сканеры, чужой SNI, allowlist reject |
|
||
| `haproxy-zabbix-403` | httplog: `fe_http_zabbix` + `403` |
|
||
|
||
```bash
|
||
sudo apt install -y fail2ban
|
||
sudo bash ~/reverse-proxy/scripts/security/fail2ban-install.sh
|
||
sudo fail2ban-client status haproxy-reject
|
||
```
|
||
|
||
Порог: **15** reject за **10 мин** → бан **24 ч** через UFW. `ignoreip`: LAN, VPN, admin.
|
||
|
||
**sshd:** `jail.d/sshd.local` — `banaction = ufw`, те же `ignoreip` (не банить admin/VPN/LAN).
|
||
|
||
После `systemctl restart fail2ban` подождите 1–2 с перед `fail2ban-client status` (сокет).
|
||
|
||
### SSH (пример)
|
||
|
||
`/etc/ssh/sshd_config.d/99-hardening.conf`:
|
||
|
||
```
|
||
PermitRootLogin no
|
||
PasswordAuthentication no
|
||
PubkeyAuthentication yes
|
||
MaxAuthTries 3
|
||
AllowUsers papatramp
|
||
```
|
||
|
||
`sshd -t && systemctl reload sshd`
|