mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-04-17 05:53:15 +02:00
Fix ssh dev-container to use the official hooks from linuxserver.io
This commit is contained in:
@@ -59,79 +59,25 @@ services:
|
|||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
- NET_RAW
|
- NET_RAW
|
||||||
- SYS_ADMIN
|
|
||||||
network_mode: bridge
|
network_mode: bridge
|
||||||
ports:
|
ports:
|
||||||
- "2222:22" # SSH port mapping
|
- "2222:22"
|
||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Zurich
|
- TZ=Europe/Zurich
|
||||||
- VERBOSITY=-vv
|
- VERBOSITY=-vv
|
||||||
- PUID=0 # Run as root for SSH setup
|
- PUID=0
|
||||||
- PGID=0
|
- PGID=0
|
||||||
|
# Install needed packages at startup (non-persistent, but simplest)
|
||||||
|
- DOCKER_MODS=linuxserver/mods:universal-package-install
|
||||||
|
- INSTALL_PACKAGES=openssh-server|sudo|acl|bash
|
||||||
volumes:
|
volumes:
|
||||||
- ./fail2ban-config-ssh:/config:z
|
- ./fail2ban-config-ssh:/config:z
|
||||||
- /var/log:/var/log:ro
|
- /var/log:/var/log:ro
|
||||||
- /var/log/httpd:/remotelogs/apache2:ro
|
- /var/log/httpd:/remotelogs/apache2:ro
|
||||||
# Mount persistent SSH keys - shared between containers
|
# Mount persistent SSH keys - shared between containers
|
||||||
- ./ssh-keys:/mnt/ssh-keys:z
|
- ./ssh-keys:/mnt/ssh-keys:z
|
||||||
# We use entrypoint override to run SSH setup before the container's init
|
|
||||||
entrypoint: /bin/sh
|
|
||||||
command: >
|
|
||||||
-c "
|
|
||||||
apk update && apk add --no-cache openssh-server openssh-keygen sudo acl;
|
|
||||||
ssh-keygen -A;
|
|
||||||
useradd -m -s /bin/bash testuser 2>/dev/null || true;
|
|
||||||
passwd -d testuser 2>/dev/null || usermod -U testuser 2>/dev/null || true;
|
|
||||||
chage -E -1 testuser 2>/dev/null || true;
|
|
||||||
mkdir -p /home/testuser/.ssh;
|
|
||||||
if [ ! -f /mnt/ssh-keys/id_rsa ]; then
|
|
||||||
echo 'Generating new SSH key pair...';
|
|
||||||
ssh-keygen -t rsa -b 4096 -m PEM -f /mnt/ssh-keys/id_rsa -N '';
|
|
||||||
chmod 600 /mnt/ssh-keys/id_rsa;
|
|
||||||
chmod 644 /mnt/ssh-keys/id_rsa.pub;
|
|
||||||
echo 'SSH key pair generated in persistent volume';
|
|
||||||
else
|
|
||||||
echo 'Using existing SSH key pair from persistent volume';
|
|
||||||
fi;
|
|
||||||
cp /mnt/ssh-keys/id_rsa /home/testuser/.ssh/id_rsa;
|
|
||||||
cp /mnt/ssh-keys/id_rsa.pub /home/testuser/.ssh/id_rsa.pub;
|
|
||||||
cat /mnt/ssh-keys/id_rsa.pub > /home/testuser/.ssh/authorized_keys;
|
|
||||||
chmod 700 /home/testuser/.ssh;
|
|
||||||
chmod 600 /home/testuser/.ssh/id_rsa;
|
|
||||||
chmod 644 /home/testuser/.ssh/id_rsa.pub;
|
|
||||||
chmod 600 /home/testuser/.ssh/authorized_keys;
|
|
||||||
chown -R testuser:testuser /home/testuser/.ssh;
|
|
||||||
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config;
|
|
||||||
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config;
|
|
||||||
echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config;
|
|
||||||
echo 'LogLevel VERBOSE' >> /etc/ssh/sshd_config;
|
|
||||||
echo 'AuthorizedKeysFile .ssh/authorized_keys' >> /etc/ssh/sshd_config;
|
|
||||||
echo 'SyslogFacility AUTH' >> /etc/ssh/sshd_config;
|
|
||||||
mkdir -p /etc/sudoers.d;
|
|
||||||
echo 'testuser ALL=(ALL) NOPASSWD: /usr/bin/fail2ban-client *' > /etc/sudoers.d/fail2ban-ui;
|
|
||||||
echo 'testuser ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart fail2ban' >> /etc/sudoers.d/fail2ban-ui;
|
|
||||||
echo 'testuser ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload fail2ban' >> /etc/sudoers.d/fail2ban-ui;
|
|
||||||
chmod 440 /etc/sudoers.d/fail2ban-ui;
|
|
||||||
mkdir -p /etc/fail2ban/jail.d /etc/fail2ban/filter.d /etc/fail2ban/action.d;
|
|
||||||
setfacl -Rm u:testuser:rwX /etc/fail2ban 2>/dev/null || true;
|
|
||||||
setfacl -dRm u:testuser:rwX /etc/fail2ban 2>/dev/null || true;
|
|
||||||
[ -d /etc/fail2ban/action.d ] && setfacl -m u:testuser:rwX /etc/fail2ban/action.d 2>/dev/null || true;
|
|
||||||
[ -d /etc/fail2ban/filter.d ] && setfacl -m u:testuser:rwX /etc/fail2ban/filter.d 2>/dev/null || true;
|
|
||||||
[ -d /etc/fail2ban/jail.d ] && setfacl -m u:testuser:rwX /etc/fail2ban/jail.d 2>/dev/null || true;
|
|
||||||
[ -d /config/fail2ban/action.d ] && setfacl -m u:testuser:rwX /config/fail2ban/action.d 2>/dev/null || true;
|
|
||||||
[ -d /config/fail2ban/filter.d ] && setfacl -m u:testuser:rwX /config/fail2ban/filter.d 2>/dev/null || true;
|
|
||||||
[ -d /config/fail2ban/jail.d ] && setfacl -m u:testuser:rwX /config/fail2ban/jail.d 2>/dev/null || true;
|
|
||||||
echo '========================================';
|
|
||||||
echo 'SSH Test Container Ready';
|
|
||||||
echo '========================================';
|
|
||||||
echo 'Host: 127.0.0.1';
|
|
||||||
echo 'Port: 2222';
|
|
||||||
echo 'User: testuser';
|
|
||||||
echo 'Key: /config/.ssh/id_rsa (in fail2ban-ui container)';
|
|
||||||
echo 'Test command: podman exec -it DEV_fail2ban-ui ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -i /config/.ssh/id_rsa -p 2222 testuser@127.0.0.1';
|
|
||||||
echo '========================================';
|
|
||||||
/usr/sbin/sshd -D -e &
|
|
||||||
exec /init
|
|
||||||
"
|
|
||||||
|
|
||||||
|
# New: custom init + service hooks (read-only is recommended)
|
||||||
|
- ./fail2ban-ssh-custom-cont-init.d:/custom-cont-init.d:ro,z
|
||||||
|
- ./fail2ban-ssh-custom-services.d:/custom-services.d:ro,z
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
68
development/ssh_and_local/fail2ban-ssh-custom-cont-init.d/99-ssh-acl
Executable file
68
development/ssh_and_local/fail2ban-ssh-custom-cont-init.d/99-ssh-acl
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "[custom-init] ssh + acl setup starting"
|
||||||
|
|
||||||
|
# ---- user management (Alpine-friendly, idempotent) ----
|
||||||
|
if ! id -u testuser >/dev/null 2>&1; then
|
||||||
|
# Alpine has adduser by default
|
||||||
|
adduser -D -s /bin/bash testuser
|
||||||
|
# UNLOCK the account for SSH publickey auth (BusyBox adduser -D sets '!' in /etc/shadow)
|
||||||
|
# Convert "testuser:!:" (locked) -> "testuser::" (no password, unlocked)
|
||||||
|
sed -i -e 's/^testuser:!:/testuser::/' -e 's/^testuser:\*:/testuser::/' /etc/shadow || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- SSH host keys ----
|
||||||
|
ssh-keygen -A
|
||||||
|
|
||||||
|
# ---- persistent client keypair in /mnt/ssh-keys ----
|
||||||
|
mkdir -p /mnt/ssh-keys
|
||||||
|
if [ ! -f /mnt/ssh-keys/id_rsa ]; then
|
||||||
|
echo "[custom-init] generating new SSH key pair in /mnt/ssh-keys"
|
||||||
|
ssh-keygen -t rsa -b 4096 -m PEM -f /mnt/ssh-keys/id_rsa -N ''
|
||||||
|
chmod 600 /mnt/ssh-keys/id_rsa
|
||||||
|
chmod 644 /mnt/ssh-keys/id_rsa.pub
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- authorize key for testuser ----
|
||||||
|
install -d -m 700 -o testuser -g testuser /home/testuser/.ssh
|
||||||
|
cat /mnt/ssh-keys/id_rsa.pub > /home/testuser/.ssh/authorized_keys
|
||||||
|
chown testuser:testuser /home/testuser/.ssh/authorized_keys
|
||||||
|
chmod 600 /home/testuser/.ssh/authorized_keys
|
||||||
|
|
||||||
|
# ---- sshd_config (idempotent; avoid duplicate lines every restart) ----
|
||||||
|
SSHD_CFG=/etc/ssh/sshd_config
|
||||||
|
|
||||||
|
grep -qE '^PermitRootLogin\s+' "$SSHD_CFG" || echo 'PermitRootLogin no' >> "$SSHD_CFG"
|
||||||
|
grep -qE '^PasswordAuthentication\s+' "$SSHD_CFG" || echo 'PasswordAuthentication no' >> "$SSHD_CFG"
|
||||||
|
grep -qE '^KbdInteractiveAuthentication\s+' "$SSHD_CFG" || echo 'KbdInteractiveAuthentication no' >> "$SSHD_CFG"
|
||||||
|
grep -qE '^PermitEmptyPasswords\s+' "$SSHD_CFG" || echo 'PermitEmptyPasswords no' >> "$SSHD_CFG"
|
||||||
|
grep -qE '^PubkeyAuthentication\s+' "$SSHD_CFG" || echo 'PubkeyAuthentication yes' >> "$SSHD_CFG"
|
||||||
|
grep -qE '^LogLevel\s+' "$SSHD_CFG" || echo 'LogLevel VERBOSE' >> "$SSHD_CFG"
|
||||||
|
grep -qE '^AuthorizedKeysFile\s+' "$SSHD_CFG" || echo 'AuthorizedKeysFile .ssh/authorized_keys' >> "$SSHD_CFG"
|
||||||
|
|
||||||
|
# ---- sudoers: use fail2ban-client (systemctl isn't present in LSIO containers) ----
|
||||||
|
# (LSIO support guidance is to control fail2ban via fail2ban-client, not systemctl/service) :contentReference[oaicite:5]{index=5}
|
||||||
|
install -d -m 0750 /etc/sudoers.d
|
||||||
|
cat > /etc/sudoers.d/fail2ban-ui <<'EOF'
|
||||||
|
testuser ALL=(ALL) NOPASSWD: /usr/bin/fail2ban-client *
|
||||||
|
EOF
|
||||||
|
chmod 0440 /etc/sudoers.d/fail2ban-ui
|
||||||
|
|
||||||
|
# ---- ACLs: run AFTER LSIO has created /config/fail2ban on first boot ----
|
||||||
|
# The container creates /config content on first run. :contentReference[oaicite:6]{index=6}
|
||||||
|
mkdir -p /config/fail2ban/{action.d,filter.d,jail.d}
|
||||||
|
|
||||||
|
# Apply both access ACL and default ACL (so new files/dirs inherit)
|
||||||
|
for d in /config/fail2ban /config/fail2ban/action.d /config/fail2ban/filter.d /config/fail2ban/jail.d; do
|
||||||
|
setfacl -m u:testuser:rwX,m::rwX "$d"
|
||||||
|
setfacl -d -m u:testuser:rwX,m::rwX "$d"
|
||||||
|
done
|
||||||
|
|
||||||
|
# /etc/fail2ban is a symlink to /config/fail2ban in this image; setfacl follows symlinks by default.
|
||||||
|
if [ -e /etc/fail2ban ]; then
|
||||||
|
setfacl -m u:testuser:rwX,m::rwX /etc/fail2ban || true
|
||||||
|
setfacl -d -m u:testuser:rwX,m::rwX /etc/fail2ban || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[custom-init] ssh + acl setup complete"
|
||||||
2
development/ssh_and_local/fail2ban-ssh-custom-services.d/sshd
Executable file
2
development/ssh_and_local/fail2ban-ssh-custom-services.d/sshd
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
exec /usr/sbin/sshd -D -e
|
||||||
Reference in New Issue
Block a user