docs(security): план UFW, hardening HAProxy и бэкендов, скрипты deploy.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
# UFW на бэкенде: сервисный порт только с HAProxy (+ admin/extra).
|
||||
#
|
||||
# cp backend-ufw.env.example /etc/haproxy/security/backend-ufw.env
|
||||
# ./backend-ufw-from-haproxy.sh --apply
|
||||
set -Eeuo pipefail
|
||||
|
||||
ENV_FILE="${BACKEND_UFW_ENV:-/etc/haproxy/security/backend-ufw.env}"
|
||||
APPLY=0
|
||||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
log() { echo "[*] $*"; }
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--apply) APPLY=1; shift ;;
|
||||
--env-file) ENV_FILE=$2; shift 2 ;;
|
||||
-h | --help)
|
||||
echo "Usage: $0 [--apply] [--env-file PATH]"
|
||||
exit 0
|
||||
;;
|
||||
*) die "unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -f $ENV_FILE ]] || die "missing env: $ENV_FILE"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV_FILE"
|
||||
|
||||
HAPROXY_IP=${HAPROXY_IP:-192.168.160.117}
|
||||
BACKEND_PORT=${BACKEND_PORT:-}
|
||||
ADMIN_ALLOWED=${ADMIN_ALLOWED:-}
|
||||
EXTRA_ALLOWED=${EXTRA_ALLOWED:-}
|
||||
UFW_EXTRA_SERVICES=${UFW_EXTRA_SERVICES:-}
|
||||
UFW_IPV6=${UFW_IPV6:-no}
|
||||
|
||||
[[ -n $BACKEND_PORT ]] || die "BACKEND_PORT required"
|
||||
|
||||
command -v ufw >/dev/null 2>&1 || die "ufw not installed"
|
||||
|
||||
run() {
|
||||
log "$*"
|
||||
[[ $APPLY -eq 1 ]] && "$@"
|
||||
}
|
||||
|
||||
[[ $APPLY -eq 0 ]] && echo "=== DRY-RUN (pass --apply) ==="
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
sed -i "s/^IPV6=.*/IPV6=${UFW_IPV6}/" /etc/default/ufw 2>/dev/null || true
|
||||
fi
|
||||
|
||||
run ufw --force reset
|
||||
run ufw default deny incoming
|
||||
run ufw default allow outgoing
|
||||
|
||||
run ufw allow from "$HAPROXY_IP" to any port "$BACKEND_PORT" proto tcp comment 'haproxy'
|
||||
|
||||
for cidr in $EXTRA_ALLOWED; do
|
||||
[[ -z $cidr ]] && continue
|
||||
run ufw allow from "$cidr" to any port "$BACKEND_PORT" proto tcp comment 'extra'
|
||||
done
|
||||
|
||||
for cidr in $ADMIN_ALLOWED; do
|
||||
[[ -z $cidr ]] && continue
|
||||
run ufw allow from "$cidr" to any port 22 proto tcp comment 'admin ssh'
|
||||
for svc in $UFW_EXTRA_SERVICES; do
|
||||
[[ -z $svc ]] && continue
|
||||
run ufw allow from "$cidr" to any port "$svc" comment 'admin extra'
|
||||
done
|
||||
done
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
ufw --force enable
|
||||
ufw status verbose
|
||||
log "done port=$BACKEND_PORT haproxy=$HAPROXY_IP"
|
||||
else
|
||||
echo "=== end dry-run ==="
|
||||
fi
|
||||
@@ -0,0 +1,14 @@
|
||||
# UFW на бэкенде — пример для Git 192.168.160.129
|
||||
HAPROXY_IP=192.168.160.117
|
||||
BACKEND_PORT=443
|
||||
|
||||
# Admin SSH / мониторинг (пробел), опционально
|
||||
ADMIN_ALLOWED="192.168.160.0/24"
|
||||
|
||||
# Доп. порты с ADMIN_ALLOWED, напр. 2222/tcp для Gitea SSH
|
||||
UFW_EXTRA_SERVICES=""
|
||||
|
||||
# Доп. источники на BACKEND_PORT (напр. MTA для KSMG)
|
||||
EXTRA_ALLOWED=""
|
||||
|
||||
UFW_IPV6=no
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
# UFW для HAProxy: default deny, SSH из SSH_ALLOWED, inbound 25/80/443.
|
||||
# Dry-run по умолчанию; --apply для включения.
|
||||
#
|
||||
# cp haproxy-ufw.env.example /etc/haproxy/security/haproxy-ufw.env
|
||||
# ./haproxy-ufw-apply.sh
|
||||
# ./haproxy-ufw-apply.sh --apply
|
||||
set -Eeuo pipefail
|
||||
|
||||
ENV_FILE="${HAPROXY_UFW_ENV:-/etc/haproxy/security/haproxy-ufw.env}"
|
||||
APPLY=0
|
||||
|
||||
die() { echo "error: $*" >&2; exit 1; }
|
||||
log() { echo "[*] $*"; }
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: haproxy-ufw-apply.sh [--apply] [--env-file PATH]
|
||||
|
||||
--apply выполнить ufw enable/reset (иначе только показ команд)
|
||||
--env-file путь к env (default: /etc/haproxy/security/haproxy-ufw.env)
|
||||
EOF
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--apply) APPLY=1; shift ;;
|
||||
--env-file) ENV_FILE=$2; shift 2 ;;
|
||||
-h | --help) usage; exit 0 ;;
|
||||
*) die "unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -f $ENV_FILE ]] || die "missing env: $ENV_FILE (copy from haproxy-ufw.env.example)"
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$ENV_FILE"
|
||||
|
||||
SSH_ALLOWED=${SSH_ALLOWED:-}
|
||||
INBOUND_TCP=${INBOUND_TCP:-25 80 443}
|
||||
UFW_IPV6=${UFW_IPV6:-no}
|
||||
|
||||
[[ -n $SSH_ALLOWED ]] || die "SSH_ALLOWED is empty — lockout risk"
|
||||
|
||||
command -v ufw >/dev/null 2>&1 || die "ufw not installed (apt install ufw)"
|
||||
|
||||
run() {
|
||||
log "$*"
|
||||
[[ $APPLY -eq 1 ]] && "$@"
|
||||
}
|
||||
|
||||
if [[ $APPLY -eq 0 ]]; then
|
||||
echo "=== DRY-RUN (pass --apply to execute) ==="
|
||||
fi
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
sed -i "s/^IPV6=.*/IPV6=${UFW_IPV6}/" /etc/default/ufw 2>/dev/null || true
|
||||
fi
|
||||
|
||||
run ufw --force reset
|
||||
run ufw default deny incoming
|
||||
run ufw default allow outgoing
|
||||
|
||||
for cidr in $SSH_ALLOWED; do
|
||||
run ufw allow from "$cidr" to any port 22 proto tcp comment 'admin ssh'
|
||||
done
|
||||
|
||||
for port in $INBOUND_TCP; do
|
||||
run ufw allow "$port/tcp" comment "haproxy service $port"
|
||||
done
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
ufw --force enable
|
||||
ufw status verbose
|
||||
log "done"
|
||||
else
|
||||
echo "=== end dry-run ==="
|
||||
fi
|
||||
@@ -0,0 +1,11 @@
|
||||
# UFW для haproxy.kalinamall.ru — пример.
|
||||
# Копия: /etc/haproxy/security/haproxy-ufw.env (не коммитить в GitHub с prod-IP при необходимости)
|
||||
|
||||
# IP/CIDR для SSH (через пробел). Обязательно перед --apply.
|
||||
SSH_ALLOWED="192.168.160.0/24 5.100.81.121"
|
||||
|
||||
# Публичные сервисы HAProxy (пробел)
|
||||
INBOUND_TCP="25 80 443"
|
||||
|
||||
# IPv6: yes | no
|
||||
UFW_IPV6=no
|
||||
Reference in New Issue
Block a user