# Linux - SSH

# SSH Authentifizierung

<article id="bkmrk-debian-ssh%3A-passwort"># Debian SSH: Passwort für normale User, SSH-Key für root

Diese Anleitung zeigt, wie du OpenSSH so konfigurierst, dass sich **normale Benutzer mit Passwort** anmelden können, während sich **root ausschließlich mit SSH-Schlüssel** (Zertifikat/Key) anmelden darf.

## Voraussetzungen

- Debian/Ubuntu mit `openssh-server`
- Zugriff als root (oder per `sudo`)
- Ein funktionierender SSH-Key für root (z. B. Ed25519)

## 1) SSH-Key für root vorbereiten

1. Auf deinem Admin-Client (nicht auf dem Server) einen Key erzeugen (falls noch nicht vorhanden): ```
    ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519
    ```
    
    ```
    ssh-keygen -t ed25519 -a 256 -f ~/.ssh/id_ed25519 -C "jj@little-snitch"
    
    ```
2. Öffentlichen Schlüssel auf den Server in die root-Authorized Keys kopieren: ```
    ssh-copy-id -i ~/.ssh/id_ed25519.pub root@server.example.com
    ```
    
    Alternativ manuell:
    
    ```
    cat ~/.ssh/id_ed25519.pub | ssh root@server.example.com 'mkdir -p /root/.ssh && chmod 700 /root/.ssh && cat >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys'
    ```

## 2) Bestehende SSH-Konfiguration sichern

```
cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%F-%H%M%S)
```

## 3) Kerneinstellungen

Die zentrale Idee:

- `PermitRootLogin prohibit-password` → verbietet root-Passwortlogin, erlaubt aber Schlüssel.
- `PasswordAuthentication yes` → Passwortlogin global erlaubt (wird in Match-Blöcken eingeschränkt).
- `Match User root` → für root *nur* SSH-Key.
- `Match User <username>` → optional: für bestimmte User Verhalten festlegen.

## 4) Beispiel: vollständige `/etc/ssh/sshd_config`

Folgende Konfiguration entspricht deinem Beispiel und erzwingt für `root` Key-Login, lässt für `master771` sowohl Passwort als auch Key zu. Andere Benutzer folgen den globalen Einstellungen (Passwort erlaubt, Key erlaubt):

```
root@mqtt:~# cat /etc/ssh/sshd_config

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/bin:/usr/bin:/bin:/usr/games

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Include /etc/ssh/sshd_config.d/*.conf

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes
PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to "no" here!
#PasswordAuthentication yes
PasswordAuthentication yes
#PermitEmptyPasswords no

# Change to "yes" to enable keyboard-interactive authentication.  Depending on
# the system's configuration, this may involve passwords, challenge-response,
# one-time passwords or some combination of these and other methods.
# Beware issues with some PAM modules and threads.
KbdInteractiveAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin prohibit-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Allow client to pass locale and color environment variables
AcceptEnv LANG LC_* COLORTERM NO_COLOR

# override default of no subsystems
Subsystem       sftp    /usr/lib/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

Match User root
    PasswordAuthentication no
    PubkeyAuthentication yes

Match User master771
    PasswordAuthentication yes
    PubkeyAuthentication yes

```

## 5) Syntax prüfen und SSH neu laden

1. Syntaxcheck: ```
    sshd -t
    ```
    
    Wenn keine Ausgabe erfolgt, ist die Syntax OK.
2. Dienst neu laden (ohne laufende Sessions zu kappen): ```
    systemctl reload ssh
    ```
    
    Falls `reload` nicht verfügbar, dann:
    
    ```
    systemctl restart ssh
    ```

## 6) Sicher testen (zweite Session!)

1. **Neue Terminal-Session** öffnen, bestehende Sitzung nicht schließen.
2. Test root per Key: ```
    ssh -i ~/.ssh/id_ed25519 root@server.example.com
    ```
3. Test root per Passwort (soll scheitern): ```
    ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no root@server.example.com
    ```
4. Test normaler Benutzer per Passwort (soll funktionieren): ```
    ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no master771@server.example.com
    ```

## Optionen &amp; Varianten

- **Nur Passwort für bestimmte Benutzer erzwingen:**```
    Match User alice,bob
        PasswordAuthentication yes
        PubkeyAuthentication no
    ```
- **Key-Login global erlauben, aber root-Passwort strikt verbieten:** Bereits abgedeckt durch `PermitRootLogin prohibit-password` und den `Match User root`-Block.
- **Brute-Force eindämmen:** `fail2ban` verwenden und `MaxAuthTries` senken (z. B. `MaxAuthTries 3`).

## Rollback

Falls etwas schiefgeht, via Konsole (z. B. VM-Konsole) die Sicherung zurückspielen:

```
mv /etc/ssh/sshd_config.backup.YYYY-MM-DD-HHMMSS /etc/ssh/sshd_config
systemctl restart ssh
```

## Hinweise zur Sicherheit

- Lege für alle Benutzer starke Passwörter fest oder nutze ggf. 2FA (z. B. `google-authenticator`) zusätzlich.
- Bevorzuge Ed25519-Schlüssel. RSA nur mit ausreichend großer Länge (min. 3072 Bit).
- Überlege, den SSH-Port zu ändern und/oder Port-Knocking bzw. VPN vorzuschalten.
- Halte `openssh-server` aktuell (`apt update && apt upgrade`).

---

*Stand: aktualisiere diese Seite, wenn sich deine Policy ändert oder neue Benutzer hinzukommen.*

</article>

# SSH - only key

<article id="bkmrk-ziel%3A-auf-dem%C2%A0client">Ziel: Auf dem **Client** ein Ed25519-Schlüsselpaar mit Passphrase erzeugen und in `~/.ssh/config` hinterlegen. Auf dem **Server** Logins für `root` und `jj` auf Public-Key-Authentifizierung beschränken.

## Platzhalter

- `SERVER_IP`: IP oder FQDN des Zielservers
- `$Dieser_Client`: Kommentar (z. B. Hostname des Clients)
- `little-ghost`: frei wählbarer Schlüsselnamens-Ordner

---

## 1) Client: SSH-Key mit Passphrase erzeugen

### Befehl (kopierbar)

```
ssh-keygen \
  -t ed25519 \
  -a 1024 \
  -o \
  -Z aes256-ctr \
  -C "$Dieser_Client" \
  -f "/root/.ssh/$org/$device_name/id_ed25519"
```

### Beispielausgabe

```
Generating public/private ed25519 key pair.
Enter passphrase for "/root/.ssh/JSc/little-ghost/id_ed25519" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/JSc/little-ghost/id_ed25519
Your public key has been saved in /root/.ssh/JSc/little-ghost/id_ed25519.pub
The key fingerprint is:
SHA256:**************************** little-ghost
The key's randomart image is:
+--[ED25519 256]--+
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
|*****************|
+----[SHA256]-----+
```

### Optional: Rechte setzen

```
chmod 700 /root/.ssh /root/.ssh/JSc /root/.ssh/JSc/little-ghost
chmod 600 /root/.ssh/JSc/little-ghost/id_ed25519
chmod 644 /root/.ssh/JSc/little-ghost/id_ed25519.pub
```

#### Beispielausgabe

```
# (keine Ausgabe bei Erfolg)
# Kontrolle:
ls -ld /root/.ssh /root/.ssh/JSc /root/.ssh/JSc/little-ghost
ls -l /root/.ssh/JSc/little-ghost/
```

---

## 2) Client: SSH-Konfiguration für Zielhost

In `/root/.ssh/config` eintragen/ergänzen:

### Dateiinhalt (kopierbar)

```
Host SERVER_IP
  HostName SERVER_IP
  IdentitiesOnly yes
  IdentityFile /root/.ssh/JSc/little-ghost/id_ed25519
  ForwardAgent no
  ForwardX11 no
  StrictHostKeyChecking ask
  UserKnownHostsFile /root/.ssh/known_hosts
```

### Beispielausgabe

```
# Kontrolle:
cat /root/.ssh/config
```

---

## 3) Client: Public Key anzeigen/kopieren

### Befehl (kopierbar)

```
cat /root/.ssh/JSc/little-ghost/id_ed25519.pub
```

### Beispielausgabe

```
ssh-ed25519 AAAAAAAAAABBBBBBBBBB/CCCCCCCCCC little-ghost
```

Diesen Einzeiler auf dem **Server** in die Datei `~<user>/.ssh/authorized_keys` einfügen (eine Zeile pro Key, keine Umbrüche).

---

## 4) Server: `root` nur per Public Key

Datei `/etc/ssh/sshd_config.d/10-root-only-key.conf` anlegen/ändern.

### Dateiinhalt (kopierbar)

```
# Root: nur noch Public-Key, keine Passwörter/Keyboard-Interactive
Match User root
    PubkeyAuthentication yes
    PasswordAuthentication no
    KbdInteractiveAuthentication no
    AuthenticationMethods publickey
    PermitRootLogin prohibit-password
```

### Beispielausgabe

```
# Kontrolle:
cat /etc/ssh/sshd_config.d/10-root-only-key.conf
```

---

## 5) Server: `jj` nur per Public Key

Datei `/etc/ssh/sshd_config.d/20-jj-only-key.conf` anlegen/ändern.

### Dateiinhalt (kopierbar)

```
# jj: nur noch Public-Key, keine Passwort-/Keyboard-Interactive-Logins
Match User jj
    PubkeyAuthentication yes
    PasswordAuthentication no
    KbdInteractiveAuthentication no
    AuthenticationMethods publickey
```

### Beispielausgabe

```
# Kontrolle:
cat /etc/ssh/sshd_config.d/20-jj-only-key.conf
```

---

## 6) Server: Syntax prüfen &amp; Dienst neu laden

### Befehl (kopierbar)

```
sshd -t
sleep 30
systemctl reload ssh   # Debian-Standarddienstname
```

### Beispielausgabe

```
# Bei korrekter Konfiguration keine Ausgabe.
# Fehler würden hier mit Zeile/Datei gemeldet werden.
```

---

## 7) Client: Login zum Server testen

### Befehl (kopierbar)

```
ssh SERVER_IP
```

### Beispielausgabe

```
The authenticity of host 'SERVER_IP (SERVER_IP)' can't be established.
ED25519 key fingerprint is SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'SERVER_IP' (ED25519) to the list of known hosts.
Enter passphrase for key '/root/.ssh/JSc/little-ghost/id_ed25519':
Last login: Wed Sep 24 12:34:56 2025 from 203.0.113.42
root@server:~#
```

---

## Hinweise

- **Dateirechte:** Verzeichnisse `700`, Private Key `600`, Public Key `644`.
- **Known Hosts:** Datei heißt `known_hosts` (nicht `known_hos`).
- **Debug bei Problemen:** `ssh -v SERVER_IP` zeigt, welchen Key der Client nutzt.

Stand: 25.09.2025

</article>

# SSHFS - Storage

## 🔐 SSHFS-Mount Anleitung für Linux + Nextcloud

*Beispiele nutzen Fantasie-Namen und RFC-5737-Dummy-IP (192.0.2.0/24):*  
Client: `orion-client` • Server: `atlas-storage` • Server-IP: `192.0.2.55`  
Zielpfad auf dem Server: `/srv/projects/ai/labs/local-sdxl-cpu`

---

### 0. Voraussetzungen (Server)

```
# Gruppe für SSHFS-Nutzer anlegen (falls noch nicht vorhanden)
groupadd sshfsusers

# Verzeichnis für hinterlegte Public Keys anlegen und absichern
mkdir -p /etc/sshfs_keys
chown root:root /etc/sshfs_keys
chmod 0755 /etc/sshfs_keys

```

---

### 1. SSH-Schlüssel erstellen (Client)

```
# moderner Schlüssel (ed25519)
ssh-keygen -t ed25519 -a 2048 -o -Z aes256-ctr -f ~/.ssh/orion_to_atlas -C "sshfs orion-client → atlas-storage"

```

---

### 2. Öffentlichen Schlüssel auf den Server übertragen

```
scp ~/.ssh/orion_to_atlas.pub root@192.0.2.55:/etc/sshfs_keys/sshfs_orion.pub
# auf dem Server:
chown root:root /etc/sshfs_keys/sshfs_orion.pub
chmod 0644 /etc/sshfs_keys/sshfs_orion.pub

```

---

### 3. SSHFS-Benutzer auf dem Server anlegen

```
# Benutzer ohne Home (kein Risiko durch dotfiles), in Gruppe sshfsusers
useradd -M -g sshfsusers -s /usr/sbin/nologin sshfs_orion

# Ziel-Verzeichnisstruktur (nur Beispielpfad)
mkdir -p /srv/projects/ai/labs/local-sdxl-cpu

# Eigentümer/Gruppe setzen, setgid auf dem Zielordner
chown -R root:sshfsusers /srv/projects
chmod 2750 /srv/projects/ai/labs/local-sdxl-cpu

```

**Wichtig (Traversal nur für die Gruppe):** Damit der Benutzer `sshfs_orion` den Zielordner erreicht, müssen alle Elternordner das x-Recht für die Gruppe haben, ohne Leserechte (kein Listing). Das hält den Pfad geschlossen und erlaubt nur Durchgang.

```
# Elternordner: Gruppe setzen + nur Durchgang (710)
chgrp sshfsusers /srv
chmod 710       /srv

chgrp sshfsusers /srv/projects
chmod 710        /srv/projects

chgrp sshfsusers /srv/projects/ai
chmod 710        /srv/projects/ai

chgrp sshfsusers /srv/projects/ai/labs
chmod 710        /srv/projects/ai/labs

# Zielordner: nur Besitzer+Gruppe, setgid damit neue Dateien in der Gruppe bleiben
chgrp sshfsusers /srv/projects/ai/labs/local-sdxl-cpu
chmod 2770       /srv/projects/ai/labs/local-sdxl-cpu

```

---

### 4. SSH-Konfiguration auf dem Server

Datei `/etc/ssh/sshd_config` bearbeiten und am Ende hinzufügen:

```
Match User sshfs_orion
    AuthorizedKeysFile /etc/sshfs_keys/%u.pub
    PubkeyAuthentication yes
    KbdInteractiveAuthentication no
    PasswordAuthentication no
    AllowTcpForwarding no
    X11Forwarding no
    PermitTTY no
    PermitTunnel no
    ForceCommand internal-sftp

```

```
# Syntax prüfen und Dienst neu laden
sshd -t
systemctl reload ssh

```

---

### 5. FUSE erlauben (Client &amp; ggf. Server)

Datei `/etc/fuse.conf` öffnen und sicherstellen, dass die Zeile ohne Kommentar vorhanden ist:

```
user_allow_other

```

---

### 6. Bequemer Host-Alias auf dem Client (empfohlen)

Datei `~/.ssh/config` (Client) ergänzen:

```
Host atlas
    HostName 192.0.2.55
    User sshfs_orion
    IdentityFile ~/.ssh/orion_to_atlas
    IdentitiesOnly yes
    ServerAliveInterval 15
    ServerAliveCountMax 3
    StrictHostKeyChecking yes

```

---

### 7. SSHFS-Mount auf dem Client

```
# lokaler Mountpunkt
mkdir -p /mnt/atlas_labs

# Mount (streng: others=0 → umask=007)
sshfs -o IdentityFile=~/.ssh/orion_to_atlas \
      -o reconnect \
      -o ServerAliveInterval=15 \
      -o ServerAliveCountMax=3 \
      -o allow_other \
      -o default_permissions \
      -o uid=1000 \
      -o gid=1000 \
      -o umask=007 \
      -o idmap=user \
      atlas:/srv/projects/ai/labs/local-sdxl-cpu /mnt/atlas_labs

```

**Hinweise:**

- `umask=007` ergibt effektiv 770/660 auf dem Mount (keine Rechte für others). *(`umask=002` würde 775/664 zulassen.)*
- `default_permissions` sorgt dafür, dass Kernel-Rechte lokal erzwungen werden.

---

### 8. Optional: Dauerbetrieb per `/etc/fstab` (Client)

```
sshfs#sshfs_orion@192.0.2.55:/srv/projects/ai/labs/local-sdxl-cpu  /mnt/atlas_labs  fuse.sshfs  \
IdentityFile=/root/.ssh/orion_to_atlas,allow_other,default_permissions,uid=1000,gid=1000,umask=007, \
reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,idmap=user,_netdev  0  0

```

---

### 🎁 Bonus: Nutzung mit Nextcloud

Mount für `www-data` (uid/gid 33):

```
mkdir -p /mnt/nextcloud_data
sshfs -o IdentityFile=/root/.ssh/nextcloud_key \
      -o reconnect -o ServerAliveInterval=15 -o ServerAliveCountMax=3 \
      -o allow_other -o default_permissions \
      -o uid=33 -o gid=33 -o umask=007 -o idmap=user \
      nextcloud_svc@192.0.2.55:/srv/nextcloud/export /mnt/nextcloud_data

```

- In Nextcloud: Admin → **Externer Speicher** → Pfad `/mnt/nextcloud_data` einbinden.

---

### 9. Troubleshooting (kurz &amp; sicher)

- **Passwort-Prompt statt Key:** Rechte prüfen: `/etc/sshfs_keys` = 0755, Dateien = 0644, Owner = root:root. Dann `sshd -T -C user=sshfs_orion` auf dem Server und auf `authorizedkeysfile` achten.
- **Zugriff verweigert trotz korrektem Key:** Elternordner-Traversal mit `namei -l /srv/projects/ai/labs/local-sdxl-cpu` prüfen. Jeder Ordner braucht `g+x` bei Gruppe `sshfsusers`.
- **Host verwechselt:** Host-Alias in `~/.ssh/config` nutzen, nicht rohe IPs tippen.