瀏覽代碼

fix: use SSH drop-in config and correct handler service name

Replace the full sshd_config template with a drop-in at
sshd_config.d/99-hardening.conf to avoid overwriting Ubuntu defaults.
Change handler from restart sshd to reload ssh (correct service name
on Ubuntu/Debian, avoids dropping active connections).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
kotoyuuko 3 周之前
父節點
當前提交
a9a72248cc

+ 2 - 0
openspec/changes/archive/2026-04-22-ssh-hardening-incremental/.openspec.yaml

@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-04-22

+ 35 - 0
openspec/changes/archive/2026-04-22-ssh-hardening-incremental/design.md

@@ -0,0 +1,35 @@
+## Context
+
+Ubuntu 22.04+ ships with `/etc/ssh/sshd_config` that includes `Include /etc/ssh/sshd_config.d/*.conf` at the top. Files in `sshd_config.d/` override settings from the main config because they're processed first and later directives take precedence. The base role currently replaces the entire main config with a minimal template.
+
+## Goals / Non-Goals
+
+**Goals:**
+- Only override the 6 specific settings that need hardening
+- Preserve Ubuntu's default sshd_config including Include directives
+- Apply changes without dropping active SSH connections
+
+**Non-Goals:**
+- No changes to which hardening settings are enforced
+- No changes to UFW or fail2ban
+
+## Decisions
+
+Use a drop-in config file at `/etc/ssh/sshd_config.d/99-hardening.conf` containing only the settings we want to override:
+
+```
+Port {{ ssh_port }}
+PermitRootLogin prohibit-password
+PubkeyAuthentication yes
+PasswordAuthentication no
+KbdInteractiveAuthentication no
+X11Forwarding no
+```
+
+Ubuntu's default config already has `Include /etc/ssh/sshd_config.d/*.conf`, so our drop-in takes effect without touching the main config.
+
+Also fix the handler: `restart sshd` → `reload ssh`. Correct service name, and reload doesn't terminate existing connections.
+
+## Risks / Trade-offs
+
+- [Older Ubuntu versions may not support sshd_config.d] → This project targets Ubuntu/Debian servers; all supported versions (22.04+) include the drop-in mechanism.

+ 25 - 0
openspec/changes/archive/2026-04-22-ssh-hardening-incremental/proposal.md

@@ -0,0 +1,25 @@
+## Why
+
+The base role completely replaces `/etc/ssh/sshd_config` with a custom template, which overwrites Ubuntu's default configuration including `Include` directives and other distro-specific settings. This can cause sshd to enter a broken state after the handler fires — password auth, root login, and other defaults are silently removed, and sshd may not recover properly from the restart.
+
+## What Changes
+
+- Replace the full `sshd_config.j2` template with a drop-in config file at `/etc/ssh/sshd_config.d/99-hardening.conf` that only overrides the specific settings we need to change
+- Remove the old `sshd_config.j2` template file
+- Change the sshd handler from `restart sshd` to `reload ssh` to avoid dropping active connections
+
+## Capabilities
+
+### New Capabilities
+<!-- none -->
+
+### Modified Capabilities
+<!-- none -->
+
+## Impact
+
+- `roles/base/tasks/main.yml`: change from template to copy/drop-in task
+- `roles/base/templates/sshd_config.j2`: deleted
+- `roles/base/templates/sshd-hardening.conf.j2`: new file
+- `roles/base/handlers/main.yml`: handler service name and state corrected
+- No changes to which settings are enforced — same hardening, delivered incrementally

+ 3 - 0
openspec/changes/archive/2026-04-22-ssh-hardening-incremental/specs/NOTE.md

@@ -0,0 +1,3 @@
+## Note
+
+No capability changes. Same hardening settings, different delivery mechanism.

+ 9 - 0
openspec/changes/archive/2026-04-22-ssh-hardening-incremental/tasks.md

@@ -0,0 +1,9 @@
+## 1. Replace full sshd_config with drop-in
+
+- [x] 1.1 Create new `sshd-hardening.conf.j2` template with only the 6 hardened settings
+- [x] 1.2 Replace the template task in `roles/base/tasks/main.yml` to deploy drop-in at `/etc/ssh/sshd_config.d/99-hardening.conf`
+- [x] 1.3 Delete old `roles/base/templates/sshd_config.j2`
+
+## 2. Fix sshd handler
+
+- [x] 2.1 Change handler from `restart sshd` to `reload ssh` in `roles/base/handlers/main.yml`

+ 2 - 2
roles/base/handlers/main.yml

@@ -1,8 +1,8 @@
 ---
 - name: restart sshd
   ansible.builtin.systemd:
-    name: sshd
-    state: restarted
+    name: ssh
+    state: reloaded
 
 - name: restart fail2ban
   ansible.builtin.systemd:

+ 4 - 4
roles/base/tasks/main.yml

@@ -9,14 +9,14 @@
     name: "{{ base_packages }}"
     state: present
 
-- name: Harden SSH configuration
+- name: Deploy SSH hardening drop-in
   ansible.builtin.template:
-    src: sshd_config.j2
-    dest: /etc/ssh/sshd_config
+    src: sshd-hardening.conf.j2
+    dest: /etc/ssh/sshd_config.d/99-hardening.conf
     owner: root
     group: root
     mode: "0644"
-    validate: "sshd -t -f %s"
+    validate: "sshd -t -f /etc/ssh/sshd_config"
   notify: restart sshd
 
 - name: Allow SSH through UFW

+ 6 - 0
roles/base/templates/sshd-hardening.conf.j2

@@ -0,0 +1,6 @@
+Port {{ ssh_port }}
+PermitRootLogin prohibit-password
+PubkeyAuthentication yes
+PasswordAuthentication no
+KbdInteractiveAuthentication no
+X11Forwarding no

+ 0 - 14
roles/base/templates/sshd_config.j2

@@ -1,14 +0,0 @@
-Port {{ ssh_port }}
-Protocol 2
-
-PermitRootLogin prohibit-password
-PubkeyAuthentication yes
-PasswordAuthentication no
-ChallengeResponseAuthentication no
-UsePAM yes
-
-X11Forwarding no
-PrintMotd no
-AcceptEnv LANG LC_*
-
-Subsystem sftp /usr/lib/openssh/sftp-server