ops-jrz1/modules/security/ssh-hardening.nix
Dan ab5aebb161 Phase 3: Extract and sanitize Matrix platform modules from ops-base
Extracted modules:
- Matrix homeserver (matrix-continuwuity.nix)
- mautrix bridges (slack, whatsapp, gmessages)
- Security modules (fail2ban, ssh-hardening)
- Development services module
- Matrix secrets module

All modules sanitized to remove personal information:
- Domains: example.com, matrix.example.org
- IPs: 10.0.0.x, 203.0.113.10
- Paths: /home/user, /path/to/ops-base
- Emails: admin@example.com

Configuration:
- Updated flake.nix with sops-nix and nixpkgs-unstable
- Updated hosts/ops-jrz1.nix to import all extracted modules
- Added example files (secrets, minimal config)
- Generated flake.lock

Generated with Claude Code - https://claude.com/claude-code
2025-10-13 14:51:14 -07:00

130 lines
4 KiB
Nix

# SSH hardening configuration for production security
{ config, lib, ... }:
with lib;
{
options.security.ssh-hardening = {
enable = mkEnableOption "SSH security hardening";
level = mkOption {
type = types.enum [ "development" "production" "paranoid" ];
default = "production";
description = "Security level for SSH configuration";
};
allowUsers = mkOption {
type = types.listOf types.str;
default = [ "admin" ];
description = "Users allowed to SSH";
};
maxAuthTries = mkOption {
type = types.int;
default = 3;
description = "Maximum authentication attempts";
};
maxSessions = mkOption {
type = types.int;
default = 10;
description = "Maximum concurrent sessions";
};
};
config = mkIf config.security.ssh-hardening.enable {
services.openssh = {
enable = true;
settings = {
# Authentication settings
PermitRootLogin = if config.security.ssh-hardening.level == "development"
then "prohibit-password"
else "no";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
ChallengeResponseAuthentication = false;
# Security settings
PermitEmptyPasswords = false;
UsePAM = false;
X11Forwarding = false;
AllowAgentForwarding = config.security.ssh-hardening.level == "development";
AllowTcpForwarding = config.security.ssh-hardening.level != "paranoid";
GatewayPorts = "no";
# User restrictions
AllowUsers = config.security.ssh-hardening.allowUsers;
# Protocol settings
Protocol = 2;
LogLevel = if config.security.ssh-hardening.level == "paranoid" then "VERBOSE" else "INFO";
# Timing settings
LoginGraceTime = 30;
ClientAliveInterval = 300;
ClientAliveCountMax = 2;
TCPKeepAlive = false;
# Crypto settings for security
Ciphers = [
"chacha20-poly1305@openssh.com"
"aes256-gcm@openssh.com"
"aes128-gcm@openssh.com"
"aes256-ctr"
"aes192-ctr"
"aes128-ctr"
];
Macs = [
"hmac-sha2-256-etm@openssh.com"
"hmac-sha2-512-etm@openssh.com"
"hmac-sha2-256"
"hmac-sha2-512"
];
KexAlgorithms = [
"curve25519-sha256@libssh.org"
"diffie-hellman-group16-sha512"
"diffie-hellman-group18-sha512"
"diffie-hellman-group14-sha256"
];
};
extraConfig = ''
# Rate limiting
MaxAuthTries ${toString config.security.ssh-hardening.maxAuthTries}
MaxSessions ${toString config.security.ssh-hardening.maxSessions}
MaxStartups 10:30:60
# Banner
${optionalString (config.security.ssh-hardening.level != "development") ''
Banner /etc/ssh/banner
''}
# Additional security
${optionalString (config.security.ssh-hardening.level == "paranoid") ''
StrictModes yes
IgnoreRhosts yes
HostbasedAuthentication no
PermitUserEnvironment no
Compression delayed
''}
'';
};
# Create SSH banner for non-development environments
environment.etc."ssh/banner" = mkIf (config.security.ssh-hardening.level != "development") {
text = ''
################################################################################
# NOTICE #
# #
# This system is for authorized users only. All activity may be monitored #
# and recorded. Unauthorized access is prohibited. #
# #
################################################################################
'';
mode = "0644";
};
};
}