# Network & Security Configuration Complete guide for securing and networking your homelab. ## SSH Security Setup ### Initial Configuration ```bash # Generate SSH key pair ssh-keygen -t ed25519 -C "homelab-key" -f ~/.ssh/homelab_ed25519 # Copy public key to target ssh-copy-id -i ~/.ssh/homelab_ed25519.pub user@target ``` ### SSH Hardening **Status:** ✅ **Complete** - Port changed to 2222 Edit `/etc/ssh/sshd_config`: ``` # Disable root login PermitRootLogin no # Use key-based authentication only PasswordAuthentication no PubkeyAuthentication yes # Change default port (CRITICAL - currently still on 22) Port 2222 # Restrict users AllowUsers hoborg # Security settings Protocol 2 X11Forwarding no AllowTcpForwarding no ClientAliveInterval 300 ClientAliveCountMax 2 MaxAuthTries 3 MaxStartups 2 ``` **Completed:** 1. ✅ Changed SSH port from 22 to 2222 2. ✅ Updated router port forwarding rules 3. ✅ External access via ak-homelab.duckdns.org:2222 working Restart SSH: `sudo systemctl restart sshd` ### Mosh Alternative (Investigation Needed) **Issue:** SSH can be unreliable on WiFi connections with packet loss. **Mosh Benefits:** - Maintains connection during network switches (ethernet ↔ WiFi) - Handles poor WiFi connections better - Local echo for responsive typing - Roaming support (IP changes don't break connection) **Installation:** ```bash # Server side sudo pacman -S mosh # Client side mosh user@server ``` **Requirements:** - UDP ports 60000-61000 open on router - SSH still needed for initial authentication **Status:** ✅ **Local use working** ❌ **External blocked by ISP** **Key Findings:** - **Local mosh**: Works perfectly (`mosh localhost`, `mosh 192.168.0.100`) - **External mosh**: Blocked by ISP UDP port filtering on ports 60000-61000 - **SSH still needed**: Mosh uses SSH for initial authentication, then switches to UDP **ISP UDP Blocking Issue:** - Most ISPs block UDP ports 60000-61000 for "security" - SSH works fine (TCP port 2222) but mosh fails (UDP 60000-61000) - Router port forwarding is correct, but ISP drops UDP packets **Current Recommendation:** - Use mosh for local/internal network connections - Stick with SSH for external connections until VPN is set up - VPN tunnel can bypass ISP UDP blocking ### SSH Client Configuration Create `~/.ssh/config`: ``` Host homelab HostName ak-homelab.duckdns.org User hoborg Port 2222 IdentityFile ~/.ssh/homelab_ed25519 ServerAliveInterval 60 ``` **Usage:** ```bash # Connect via SSH ssh homelab # Connect via Mosh (uses SSH config automatically) mosh homelab ``` ## Dynamic DNS with DuckDNS ### Account Setup 1. Create account at duckdns.org 2. Create subdomain: `ak-homelab.duckdns.org` 3. Get token from dashboard ### Automatic IP Updates Update script at `~/.local/scripts/duckdns.py` (Python implementation) Cron job for automatic updates: ```bash # Update every 5 minutes */5 * * * * /home/hoborg/.local/scripts/duckdns.py >/dev/null 2>&1 ``` ### Current Setup (Router-based) **Status:** ✅ **Migrated from script to router DynDNS** **Changes made:** - ✅ Disabled cron job script (`*/5 * * * *` entry removed) - ✅ Enabled router Dynamic DNS for ak-homelab.duckdns.org - ⏳ **Testing pending** - Cannot force public IP change to verify **Router DynDNS Benefits:** - Immediate updates on IP change (vs 5-minute delay) - Works when server is down - Lower resource usage **Limitations:** - Likely IPv4-only (Sagemcom router limitation) - Less control over update process ### Testing ```bash # Check current IP curl -s https://ipinfo.io/ip # Verify DNS resolution nslookup ak-homelab.duckdns.org # Check IPv6 (likely not updated by router) nslookup -type=AAAA ak-homelab.duckdns.org ``` **Testing will occur naturally when ISP changes public IP address.** ## VPN Setup with WireGuard ### What is WireGuard? WireGuard is a modern, lightweight VPN protocol that creates secure tunnels between devices. It encrypts all network traffic and routes it through a VPN server, making your internet connection private and secure. **Key benefits:** - **Privacy**: Hides your IP address and encrypts traffic - **Security**: Protects against man-in-the-middle attacks on public WiFi - **Access**: Bypass geo-restrictions and enables remote homelab access - **Performance**: Much faster than OpenVPN with lower battery drain - **Simplicity**: Easy to configure compared to other VPN protocols **When you need VPN:** - Accessing homelab remotely over internet - Working from public WiFi frequently - Need to bypass ISP restrictions - Running public-facing services **Costs:** WireGuard itself is free. Self-hosted VPN costs $5-20/month for VPS hosting. **Use cases:** - Access homelab services remotely (SSH, web interfaces, file shares) - Secure connection on public WiFi - Bypass ISP restrictions or geo-blocks **Performance:** Much faster and lighter than OpenVPN, better battery life on mobile devices. ### Server Configuration Install WireGuard: `pacman -S wireguard-tools` Generate keys: ```bash wg genkey | tee server_private.key | wg pubkey > server_public.key ``` Server config `/etc/wireguard/wg0.conf`: ```ini [Interface] PrivateKey = Address = 10.0.0.1/24 ListenPort = 51820 PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] PublicKey = AllowedIPs = 10.0.0.2/32 ``` ### Client Configuration Generate client keys: ```bash wg genkey | tee client_private.key | wg pubkey > client_public.key ``` Client config: ```ini [Interface] PrivateKey = Address = 10.0.0.2/24 DNS = 1.1.1.1 [Peer] PublicKey = Endpoint = ak-homelab.duckdns.org:51820 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 ``` ### Enable VPN ```bash sudo systemctl enable wg-quick@wg0 sudo systemctl start wg-quick@wg0 ``` ## Firewall Configuration ### UFW (Uncomplicated Firewall) **What it does:** Controls what network traffic is allowed in/out of your server. **Key functions:** - **Default deny**: Blocks all incoming connections by default - **Port control**: Open only specific ports you need (SSH, HTTP, etc.) - **Rate limiting**: Prevent brute force attacks - **Application profiles**: Pre-configured rules for common services **Why needed:** Without firewall, all services are exposed to network attacks. ### UFW Setup ```bash # Install and enable UFW pacman -S ufw sudo ufw enable # Default policies sudo ufw default deny incoming sudo ufw default allow outgoing # SSH access sudo ufw allow 2222/tcp # WireGuard sudo ufw allow 51820/udp # HTTP/HTTPS for services sudo ufw allow 80/tcp sudo ufw allow 443/tcp ``` ### Advanced Rules ```bash # Rate limiting for SSH sudo ufw limit 2222/tcp # Allow from specific networks sudo ufw allow from 192.168.1.0/24 to any port 22 # Log denied connections sudo ufw logging on ``` ## Network Security Best Practices ### Port Management - **Change default ports**: SSH (2222), WireGuard (51820) - **Close unused ports**: Regular port scans with nmap - **Port forwarding**: Only forward necessary ports ### Access Control - **VPN-first approach**: Access services through VPN tunnel - **IP whitelisting**: Restrict access to known IPs when possible - **Rate limiting**: Prevent brute force attacks ### Monitoring - **Log analysis**: Monitor `/var/log/auth.log` for SSH attempts - **Network monitoring**: Use netstat/ss to check listening ports - **Intrusion detection**: Use fail2ban for automated blocking ## fail2ban - Intrusion Prevention ### What is fail2ban? **What it does:** Automatically blocks IP addresses that show malicious behavior. **Key functions:** - **Log monitoring**: Watches system logs for suspicious activity - **Pattern detection**: Identifies failed login attempts, scanning, etc. - **Automatic blocking**: Temporarily bans offending IP addresses - **Customizable rules**: Configure what triggers a ban and for how long **Common protections:** - SSH brute force attempts - Web server attacks (404 scanning, etc.) - Email server abuse - Custom application attacks **Example:** After 5 failed SSH login attempts in 10 minutes, ban IP for 1 hour. **Why important:** Reduces server load and prevents automated attacks from succeeding through persistence. ### fail2ban Installation & Setup ```bash # Install fail2ban sudo pacman -S fail2ban # Enable and start service sudo systemctl enable fail2ban sudo systemctl start fail2ban # Create local configuration sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local ``` ### Basic SSH Protection Configuration Edit `/etc/fail2ban/jail.local`: ```ini [sshd] enabled = true port = 2222 filter = sshd logpath = /var/log/auth.log maxretry = 5 bantime = 3600 findtime = 600 ``` **Configuration explained:** - `maxretry = 5`: Ban after 5 failed attempts - `bantime = 3600`: Ban for 1 hour (3600 seconds) - `findtime = 600`: 5 attempts within 10 minutes triggers ban - `port = 2222`: Monitor custom SSH port ### Restart and Monitor ```bash # Restart fail2ban to apply changes sudo systemctl restart fail2ban # Check status sudo fail2ban-client status sudo fail2ban-client status sshd # View banned IPs sudo fail2ban-client get sshd banned ``` ## Router Configuration ### Port Forwarding Forward these ports to your homelab server: - SSH: External port → Internal 2222 - WireGuard: 51820 → 51820 - Web services: 80/443 → 80/443 (if needed) ### Security Settings - **Disable WPS**: Turn off WiFi Protected Setup - **Strong WiFi password**: WPA3 with complex passphrase - **Guest network**: Separate network for guests - **Firmware updates**: Keep router firmware current ## Network Planning ### Dual Network Interface Issue (Critical) **Problem:** Server has both ethernet and WiFi interfaces. When switching between connections, IP address changes from ethernet (192.168.0.22) to different WiFi IP, breaking SSH connections and port forwards. **Limitation:** Most routers don't allow DHCP reservation of same IP for multiple MAC addresses. **Solutions:** **Option 1: Static IP Configuration (Recommended)** Configure both interfaces with same static IP: ```bash # Check interface names ip link show # Configure ethernet interface sudo systemctl edit --full systemd-networkd # Create /etc/systemd/network/20-ethernet.network [Match] Name=enp* [Network] DHCP=no Address=192.168.0.100/24 Gateway=192.168.0.1 DNS=192.168.0.1 # Create /etc/systemd/network/25-wifi.network [Match] Name=wlp* [Network] DHCP=no Address=192.168.0.100/24 Gateway=192.168.0.1 DNS=192.168.0.1 ``` **Option 2: Hostname-based Access** Use local hostname resolution instead of IP: ```bash # Access via hostname (works for both interfaces) ssh hoborg@ak-homelab.local # or configure local DNS/mDNS ``` **Option 3: Bridge Networking** Create bridge combining both interfaces for automatic failover: ```bash # Advanced: Bridge both interfaces ip link add name br0 type bridge ip link set enp3s0 master br0 ip link set wlp2s0 master br0 ``` **Current Setup:** - Router: 192.168.0.1 - Ethernet: 192.168.0.100 (static IP achieved) - WiFi: Static IP needed (same .100) - External: ak-homelab.duckdns.org ✅ - SSH: Port 2222 ✅ ## Network Boot Issues Troubleshooting ### Problem 1: Network not available after reboot until GUI login **Initial diagnosis**: Thought to be NetworkManager sleep behavior. **Actual root cause**: System auto-suspend due to closed laptop lid (`HandleLidSwitch=suspend`). **Symptoms**: - SSH inaccessible after reboot - Network comes up only when laptop lid is opened - System logs show "Suspending..." followed by "Lid opened" **Solution Applied**: 1. **systemd-logind configuration**: Disable lid switch handling for headless server operation 2. **Static IP configuration**: Eliminate DHCP negotiation delays 3. **High connection priority**: Ensure ethernet connects first **Configuration files created**: `/etc/systemd/logind.conf.d/01-server-logind.conf`: ```ini [Login] # Disable all power management triggers for headless server HandleLidSwitch=ignore HandleLidSwitchExternalPower=ignore HandleLidSwitchDocked=ignore # Prevent automatic suspend/hibernate IdleAction=ignore # Keep system running even when no users logged in KillUserProcesses=no ``` **NetworkManager commands**: ```bash nmcli connection modify "Wired connection 2" connection.autoconnect-priority 10 nmcli connection modify "Wired connection 2" ipv4.method manual ipv4.addresses 192.168.0.100/24 ipv4.gateway 192.168.0.1 ipv4.dns "84.2.44.8 84.2.46.8" ``` **Deployment**: ```bash sudo cp config/systemd/01-server-logind.conf /etc/systemd/logind.conf.d/ sudo systemctl restart systemd-logind sudo cp config/networkmanager/01-homelab.conf /etc/NetworkManager/conf.d/ sudo systemctl reload NetworkManager ``` ### Diagnostic Commands **Check system power state**: ```bash systemctl status systemd-logind # Check for suspend/lid events loginctl show-session # Current power management settings ``` **Check network connectivity**: ```bash systemctl status NetworkManager nmcli device status nmcli connection show "Wired connection 2" ip addr show enp4s0 ``` **Monitor boot process**: ```bash journalctl -b -u NetworkManager # Network startup logs journalctl -b -u sshd # SSH service logs journalctl -b -u systemd-logind # Power management events ``` **Result**: ✅ **RESOLVED** - SSH accessible immediately on boot, lid closure no longer suspends system. **Network Interface Identification:** - **enp3s0f0**: First ethernet port (98:fa:9b:f1:06:d5) - **enp4s0**: Second ethernet port (98:fa:9b:f1:06:d4) ← **Use this one** - **wlp1s0**: WiFi interface (0c:dd:24:e6:0f:87) **Issue Solved:** Dual ethernet ports caused MAC address confusion when cable was moved between ports. Stick to enp4s0 consistently. ### IP Address Scheme - **Router**: 192.168.0.1 - **Homelab server**: 192.168.0.100 (target static IP) - **Current ethernet**: 192.168.0.22 (can migrate to .100) - **DHCP range**: 192.168.0.10-99 (excluding static IPs) - **VPN subnet**: 10.0.0.0/24 ### DNS Configuration - **Primary DNS**: Router (192.168.1.1) - **Secondary DNS**: 1.1.1.1, 8.8.8.8 - **Local domain**: homelab.local - **Dynamic DNS**: ak-homelab.duckdns.org ### Service Architecture ``` Internet → Router → Homelab Server ↓ ┌─────────────────────────────┐ │ SSH (2222) │ │ WireGuard VPN (51820) │ │ Web Services (80/443) │ │ Monitoring & Logging │ └─────────────────────────────┘ ``` ## Backup and Recovery ### Configuration Backups - **SSH keys**: Store securely, separate from server - **WireGuard configs**: Document peer configurations - **Firewall rules**: Export UFW rules with `ufw status numbered` ### Network Documentation - **IP mappings**: Document static assignments - **Port forwards**: List all forwarded ports and purposes - **Access credentials**: Secure storage of passwords/keys