Initial Commit
This commit is contained in:
30
LICENSE
30
LICENSE
@@ -1,7 +1,4 @@
|
|||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
MIT License
|
||||||
Version 3, 19 November 2007
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Copyright ©
|
Copyright ©
|
||||||
|
|
||||||
@@ -12,15 +9,20 @@ Blog: https://www.cleveradmin.de
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
in the Software without restriction, including without limitation the rights
|
||||||
(at your option) any later version.
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
The above copyright notice and this permission notice shall be included in all
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
copies or substantial portions of the Software.
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
76
README.md
76
README.md
@@ -4,26 +4,86 @@
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h1 align="center">Name des Projekts</h1>
|
<h1 align="center">SSH Login Notifier</h1>
|
||||||
|
|
||||||
<h4 align="center">
|
<h4 align="center">
|
||||||
Kurzbeschreibung des Projekts/Anwendung, um die es geht
|
Benachrichtigungen bei SSH-Logins per E-Mail und/oder ntfy.
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<h6 align="center">
|
<h6 align="center">
|
||||||
<a href="https://www.cleveradmin.de">🏰 Website</a>
|
<a href="https://www.cleveradmin.de">Website</a>
|
||||||
·
|
·
|
||||||
<a href="https://techniverse.net">📰 Community</a>
|
<a href="https://techniverse.net">Community</a>
|
||||||
·
|
·
|
||||||
<a href="https://social.techniverse.net/@donnerwolke">🐘 Mastodon</a>
|
<a href="https://social.techniverse.net/@donnerwolke">Mastodon</a>
|
||||||
·
|
·
|
||||||
<a href="https://matrix.to/#/#support:techniverse.net">💬 Support</a>
|
<a href="https://matrix.to/#/#support:techniverse.net">Support</a>
|
||||||
</h6>
|
</h6>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
## Funktionen
|
||||||
|
|
||||||
CONTENT BEREICH
|
- Benachrichtigung bei jedem SSH-Login
|
||||||
|
- **E-Mail** und/oder **ntfy** als Benachrichtigungskanal (einzeln oder kombiniert)
|
||||||
|
- **Geo-Location** der Quell-IP (Land, Stadt, Provider)
|
||||||
|
- Shell-unabhängig dank **PAM-Integration** (funktioniert mit Bash, Zsh, Fish, etc.)
|
||||||
|
- Einfache Konfiguration über eine zentrale `config.conf`
|
||||||
|
- Installations- und Deinstallationsscript
|
||||||
|
|
||||||
|
## Schnellstart
|
||||||
|
|
||||||
|
### 1. Voraussetzungen prüfen
|
||||||
|
|
||||||
|
Siehe [Voraussetzungen](docs/prerequisites.md) (curl wird automatisch installiert, Mail-Tool muss ggf. manuell eingerichtet werden).
|
||||||
|
|
||||||
|
### 2. Repository klonen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.techniverse.net/scriptos/ssh-login-notifier.git
|
||||||
|
cd ssh-login-notifier
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Konfiguration anpassen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /opt/ssh-login-notifier/config.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Siehe [Konfigurationsreferenz](docs/configuration.md) für alle Optionen.
|
||||||
|
|
||||||
|
### 5. Testen
|
||||||
|
|
||||||
|
Einfach per SSH auf den Server einloggen — die Benachrichtigung sollte sofort eintreffen.
|
||||||
|
|
||||||
|
## Deinstallation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo /opt/ssh-login-notifier/uninstall.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Enthaltene Informationen
|
||||||
|
|
||||||
|
Jede Benachrichtigung enthält:
|
||||||
|
|
||||||
|
| Information | Beispiel |
|
||||||
|
|---|---|
|
||||||
|
| Hostname | `srv-web-01.example.com` |
|
||||||
|
| Datum | `26.04.2026` |
|
||||||
|
| Uhrzeit | `14:32:08` |
|
||||||
|
| Benutzername | `admin` |
|
||||||
|
| Quell-IP | `203.0.113.42` |
|
||||||
|
| Standort | `Berlin, Berlin, Germany (Telekom)` |
|
||||||
|
|
||||||
|
## Dokumentation
|
||||||
|
|
||||||
|
- [Voraussetzungen](docs/prerequisites.md)
|
||||||
|
- [Konfigurationsreferenz](docs/configuration.md)
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -34,4 +94,4 @@ CONTENT BEREICH
|
|||||||
<sub>
|
<sub>
|
||||||
© Patrick Asmus · Techniverse Network · <a href="./LICENSE">Lizenz</a>
|
© Patrick Asmus · Techniverse Network · <a href="./LICENSE">Lizenz</a>
|
||||||
</sub>
|
</sub>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
43
config.conf
Normal file
43
config.conf
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# ============================================================
|
||||||
|
# SSH Login Notifier - Konfiguration
|
||||||
|
# ============================================================
|
||||||
|
# Benachrichtigungsmethode(n)
|
||||||
|
# Erlaubte Werte: email, ntfy, email,ntfy
|
||||||
|
NOTIFICATION_METHODS=ntfy
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# E-Mail Einstellungen
|
||||||
|
# ============================================================
|
||||||
|
# Empfaenger-Adresse
|
||||||
|
EMAIL_RECIPIENT=admin@example.com
|
||||||
|
|
||||||
|
# Absender-Adresse (wird nur von manchen Mail-Tools unterstuetzt)
|
||||||
|
EMAIL_FROM=noreply@example.com
|
||||||
|
|
||||||
|
# Betreff-Prefix (Hostname wird automatisch angehaengt)
|
||||||
|
EMAIL_SUBJECT_PREFIX=SSH Login
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# ntfy Einstellungen
|
||||||
|
# ============================================================
|
||||||
|
# ntfy Server-URL (ohne abschliessendes /)
|
||||||
|
NTFY_SERVER=https://ntfy.example.com
|
||||||
|
|
||||||
|
# ntfy Topic
|
||||||
|
NTFY_TOPIC=ssh-login
|
||||||
|
|
||||||
|
# ntfy Prioritaet (1=min, 2=niedrig, 3=standard, 4=hoch, 5=max)
|
||||||
|
NTFY_PRIORITY=3
|
||||||
|
|
||||||
|
# ntfy Tags (kommasepariert, Emoji-Shortcodes)
|
||||||
|
NTFY_TAGS=warning,computer
|
||||||
|
|
||||||
|
# ntfy Auth-Token (leer lassen fuer Server ohne Authentifizierung)
|
||||||
|
NTFY_AUTH_TOKEN=
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Erweiterte Einstellungen
|
||||||
|
# ============================================================
|
||||||
|
# Geo-Location der Quell-IP abfragen (true/false)
|
||||||
|
# Nutzt die kostenlose API von ip-api.com (kein API-Key noetig)
|
||||||
|
GEO_LOOKUP=true
|
||||||
96
docs/configuration.md
Normal file
96
docs/configuration.md
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# Konfiguration
|
||||||
|
|
||||||
|
Die Konfigurationsdatei befindet sich unter:
|
||||||
|
|
||||||
|
```
|
||||||
|
/opt/ssh-login-notifier/config.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Nach der Installation kann sie jederzeit bearbeitet werden:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /opt/ssh-login-notifier/config.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Änderungen werden **sofort** beim nächsten SSH-Login wirksam — kein Neustart nötig.
|
||||||
|
|
||||||
|
## Benachrichtigungsmethoden
|
||||||
|
|
||||||
|
| Schlüssel | Werte | Beschreibung |
|
||||||
|
|---|---|---|
|
||||||
|
| `NOTIFICATION_METHODS` | `email`, `ntfy`, `email,ntfy` | Kommasepariert für mehrere Methoden |
|
||||||
|
|
||||||
|
## E-Mail Einstellungen
|
||||||
|
|
||||||
|
| Schlüssel | Beschreibung | Beispiel |
|
||||||
|
|---|---|---|
|
||||||
|
| `EMAIL_RECIPIENT` | Empfänger-Adresse | `admin@example.com` |
|
||||||
|
| `EMAIL_FROM` | Absender-Adresse | `noreply@example.com` |
|
||||||
|
| `EMAIL_SUBJECT_PREFIX` | Betreff-Prefix (Hostname wird angehängt) | `SSH Login` |
|
||||||
|
|
||||||
|
> Voraussetzung: Ein funktionierender Mail-Versand auf dem System (siehe [Voraussetzungen](prerequisites.md)).
|
||||||
|
|
||||||
|
## ntfy Einstellungen
|
||||||
|
|
||||||
|
| Schlüssel | Beschreibung | Beispiel |
|
||||||
|
|---|---|---|
|
||||||
|
| `NTFY_SERVER` | Server-URL (ohne `/` am Ende) | `https://ntfy.example.com` |
|
||||||
|
| `NTFY_TOPIC` | Topic-Name | `ssh-login` |
|
||||||
|
| `NTFY_PRIORITY` | Priorität (1–5) | `3` |
|
||||||
|
| `NTFY_TAGS` | Emoji-Tags, kommasepariert | `warning,computer` |
|
||||||
|
| `NTFY_AUTH_TOKEN` | Bearer-Token (leer = keine Auth) | `tk_abc123` |
|
||||||
|
|
||||||
|
### ntfy Prioritäten
|
||||||
|
|
||||||
|
| Wert | Bedeutung |
|
||||||
|
|---|---|
|
||||||
|
| `1` | Minimum |
|
||||||
|
| `2` | Niedrig |
|
||||||
|
| `3` | Standard |
|
||||||
|
| `4` | Hoch |
|
||||||
|
| `5` | Maximum (dringend) |
|
||||||
|
|
||||||
|
## Erweiterte Einstellungen
|
||||||
|
|
||||||
|
| Schlüssel | Werte | Beschreibung |
|
||||||
|
|---|---|---|
|
||||||
|
| `GEO_LOOKUP` | `true` / `false` | IP-Standort über ip-api.com abfragen |
|
||||||
|
|
||||||
|
## Beispielkonfigurationen
|
||||||
|
|
||||||
|
### Nur ntfy (einfachste Variante)
|
||||||
|
|
||||||
|
```conf
|
||||||
|
NOTIFICATION_METHODS=ntfy
|
||||||
|
NTFY_SERVER=https://ntfy.example.com
|
||||||
|
NTFY_TOPIC=ssh-alerts
|
||||||
|
NTFY_PRIORITY=4
|
||||||
|
NTFY_TAGS=warning,skull
|
||||||
|
NTFY_AUTH_TOKEN=tk_dein_token
|
||||||
|
GEO_LOOKUP=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nur E-Mail
|
||||||
|
|
||||||
|
```conf
|
||||||
|
NOTIFICATION_METHODS=email
|
||||||
|
EMAIL_RECIPIENT=admin@example.com
|
||||||
|
EMAIL_FROM=server@example.com
|
||||||
|
EMAIL_SUBJECT_PREFIX=SSH Login
|
||||||
|
GEO_LOOKUP=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Beides kombiniert
|
||||||
|
|
||||||
|
```conf
|
||||||
|
NOTIFICATION_METHODS=email,ntfy
|
||||||
|
EMAIL_RECIPIENT=admin@example.com
|
||||||
|
EMAIL_FROM=server@example.com
|
||||||
|
EMAIL_SUBJECT_PREFIX=SSH Login
|
||||||
|
NTFY_SERVER=https://ntfy.example.com
|
||||||
|
NTFY_TOPIC=ssh-alerts
|
||||||
|
NTFY_PRIORITY=3
|
||||||
|
NTFY_TAGS=warning,computer
|
||||||
|
NTFY_AUTH_TOKEN=
|
||||||
|
GEO_LOOKUP=false
|
||||||
|
```
|
||||||
69
docs/prerequisites.md
Normal file
69
docs/prerequisites.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Voraussetzungen
|
||||||
|
|
||||||
|
## Betriebssystem
|
||||||
|
|
||||||
|
- Debian 11+ (Bullseye oder neuer)
|
||||||
|
- Ubuntu 20.04+
|
||||||
|
- Andere Debian-basierte Distributionen sollten ebenfalls funktionieren
|
||||||
|
|
||||||
|
Architektur: x64 (amd64) und ARM (arm64/armhf) werden unterstützt.
|
||||||
|
|
||||||
|
## Abhängigkeiten
|
||||||
|
|
||||||
|
### Pflicht
|
||||||
|
|
||||||
|
| Paket | Zweck | Prüfung |
|
||||||
|
|---|---|---|
|
||||||
|
| `curl` | ntfy-Benachrichtigungen und Geo-Lookup | `command -v curl` |
|
||||||
|
|
||||||
|
> Das Installationsscript installiert fehlende Pflicht-Abhängigkeiten automatisch.
|
||||||
|
|
||||||
|
### Optional (für E-Mail)
|
||||||
|
|
||||||
|
Mindestens **eines** der folgenden Mail-Tools muss installiert und konfiguriert sein:
|
||||||
|
|
||||||
|
| Tool | Paket | Anmerkung |
|
||||||
|
|---|---|---|
|
||||||
|
| `mail` | `mailutils` oder `bsd-mailx` | Am weitesten verbreitet |
|
||||||
|
| `msmtp` | `msmtp` + `msmtp-mta` | Leichtgewichtig, gut für Relay |
|
||||||
|
| `sendmail` | `postfix` oder `sendmail` | Vollständiger MTA |
|
||||||
|
|
||||||
|
Das Script erkennt automatisch welches Tool verfügbar ist (Reihenfolge: mail → sendmail → msmtp).
|
||||||
|
|
||||||
|
### Optional (für Geo-Location)
|
||||||
|
|
||||||
|
Die Geo-Location nutzt die kostenlose API von [ip-api.com](http://ip-api.com). Dafür ist keine Registrierung oder API-Key nötig.
|
||||||
|
|
||||||
|
**Einschränkungen:**
|
||||||
|
- Maximal 45 Anfragen pro Minute
|
||||||
|
- Nur für nicht-kommerzielle Nutzung
|
||||||
|
- Funktioniert nur mit öffentlichen IPs (lokale IPs wie 192.168.x.x liefern kein Ergebnis)
|
||||||
|
|
||||||
|
Die Geo-Location kann in der `config.conf` deaktiviert werden (`GEO_LOOKUP=false`).
|
||||||
|
|
||||||
|
## Shell-Kompatibilität
|
||||||
|
|
||||||
|
Das Script wird über `/etc/profile.d/` eingebunden und bei jedem interaktiven Login ausgeführt.
|
||||||
|
|
||||||
|
| Shell | Unterstützt | Mechanismus |
|
||||||
|
|---|---|---|
|
||||||
|
| Bash | Ja | `/etc/profile.d/` wird nativ geladen |
|
||||||
|
| Zsh (oh-my-zsh) | Ja | `/etc/zsh/zprofile` sourct `/etc/profile` auf Debian/Ubuntu |
|
||||||
|
| Sh / Dash | Ja | `/etc/profile.d/` wird nativ geladen |
|
||||||
|
| Fish | Nein | Fish sourct `/etc/profile` nicht |
|
||||||
|
|
||||||
|
> **Hinweis:** Nur SSH-Verbindungen lösen eine Benachrichtigung aus. Lokale Logins, `su`, `sudo` und nicht-interaktive Verbindungen (SCP, SFTP, Monitoring-Tools wie PRTG) werden ignoriert.
|
||||||
|
|
||||||
|
## Funktionsweise
|
||||||
|
|
||||||
|
Das Installationsscript legt eine kleine Datei in `/etc/profile.d/` ab:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# /etc/profile.d/ssh-login-notify.sh
|
||||||
|
[ -n "$SSH_CONNECTION" ] && [ -x /opt/ssh-login-notifier/ssh-login-notify.sh ] && . /opt/ssh-login-notifier/ssh-login-notify.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Diese Zeile prüft:
|
||||||
|
1. Ist `$SSH_CONNECTION` gesetzt? (Nur bei SSH-Logins der Fall)
|
||||||
|
2. Ist das Hauptscript vorhanden und ausführbar?
|
||||||
|
3. Wenn ja → Hauptscript im Hintergrund ausführen (Login wird nicht verzögert)
|
||||||
170
install.sh
Normal file
170
install.sh
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SSH Login Notifier - Installationsscript
|
||||||
|
# https://git.techniverse.net/scriptos/ssh-login-notifier
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/ssh-login-notifier"
|
||||||
|
PROFILE_HOOK="/etc/profile.d/ssh-login-notify.sh"
|
||||||
|
ZSH_HOOK_MARKER="# SSH Login Notifier"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
|
# --- Hilfsfunktionen ---
|
||||||
|
|
||||||
|
info() { echo -e "\e[32m[INFO]\e[0m $1"; }
|
||||||
|
warn() { echo -e "\e[33m[WARN]\e[0m $1"; }
|
||||||
|
error() { echo -e "\e[31m[ERROR]\e[0m $1"; exit 1; }
|
||||||
|
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "Dieses Script muss als root ausgefuehrt werden (sudo)."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_os() {
|
||||||
|
if [[ ! -f /etc/os-release ]]; then
|
||||||
|
error "Betriebssystem nicht erkannt. Nur Debian/Ubuntu werden unterstuetzt."
|
||||||
|
fi
|
||||||
|
. /etc/os-release
|
||||||
|
case "$ID" in
|
||||||
|
debian|ubuntu) info "Erkanntes OS: ${PRETTY_NAME}" ;;
|
||||||
|
*) warn "Ungetestetes OS: ${PRETTY_NAME} - Installation wird fortgesetzt." ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
check_arch() {
|
||||||
|
local arch
|
||||||
|
arch="$(uname -m)"
|
||||||
|
case "$arch" in
|
||||||
|
x86_64) info "Architektur: x64 (amd64)" ;;
|
||||||
|
aarch64) info "Architektur: ARM64 (aarch64)" ;;
|
||||||
|
armv7l) info "Architektur: ARMv7 (armhf)" ;;
|
||||||
|
*) warn "Ungetestete Architektur: ${arch}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
check_dependencies() {
|
||||||
|
local missing=()
|
||||||
|
|
||||||
|
if ! command -v curl &>/dev/null; then
|
||||||
|
missing+=("curl")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v mail &>/dev/null && ! command -v sendmail &>/dev/null && ! command -v msmtp &>/dev/null; then
|
||||||
|
warn "Kein Mail-Tool gefunden (mail, sendmail, msmtp)."
|
||||||
|
warn "E-Mail-Benachrichtigungen funktionieren erst nach Installation eines Mail-Tools."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||||
|
info "Installiere fehlende Abhaengigkeiten: ${missing[*]}"
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq "${missing[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Installation ---
|
||||||
|
|
||||||
|
install_files() {
|
||||||
|
info "Erstelle Installationsverzeichnis: ${INSTALL_DIR}"
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
|
||||||
|
info "Kopiere Dateien..."
|
||||||
|
cp "${SCRIPT_DIR}/ssh-login-notify.sh" "${INSTALL_DIR}/ssh-login-notify.sh"
|
||||||
|
cp "${SCRIPT_DIR}/uninstall.sh" "${INSTALL_DIR}/uninstall.sh"
|
||||||
|
|
||||||
|
if [[ -f "${INSTALL_DIR}/config.conf" ]]; then
|
||||||
|
warn "Bestehende config.conf gefunden - wird nicht ueberschrieben."
|
||||||
|
info "Neue Konfiguration als config.conf.new abgelegt."
|
||||||
|
cp "${SCRIPT_DIR}/config.conf" "${INSTALL_DIR}/config.conf.new"
|
||||||
|
else
|
||||||
|
cp "${SCRIPT_DIR}/config.conf" "${INSTALL_DIR}/config.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 755 "${INSTALL_DIR}/ssh-login-notify.sh"
|
||||||
|
chmod 755 "${INSTALL_DIR}/uninstall.sh"
|
||||||
|
chmod 644 "${INSTALL_DIR}/config.conf"
|
||||||
|
chown root:root "${INSTALL_DIR}" -R
|
||||||
|
|
||||||
|
info "Dateien installiert nach ${INSTALL_DIR}"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_profile_hook() {
|
||||||
|
if [[ -f "$PROFILE_HOOK" ]]; then
|
||||||
|
info "Profile-Hook ist bereits vorhanden."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Erstelle Profile-Hook: ${PROFILE_HOOK}"
|
||||||
|
cat > "$PROFILE_HOOK" << 'HOOKEOF'
|
||||||
|
# SSH Login Notifier - wird bei interaktivem Login ausgefuehrt
|
||||||
|
# Installiert von: https://git.techniverse.net/scriptos/ssh-login-notifier
|
||||||
|
[ -n "$SSH_CONNECTION" ] && [ -x /opt/ssh-login-notifier/ssh-login-notify.sh ] && /opt/ssh-login-notifier/ssh-login-notify.sh
|
||||||
|
HOOKEOF
|
||||||
|
|
||||||
|
chmod 644 "$PROFILE_HOOK"
|
||||||
|
info "Profile-Hook aktiviert (Bash, Sh)."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_zsh_hook() {
|
||||||
|
local zshrc="/etc/zsh/zshrc"
|
||||||
|
|
||||||
|
if [[ ! -f "$zshrc" ]]; then
|
||||||
|
info "Keine /etc/zsh/zshrc gefunden - Zsh-Hook wird uebersprungen."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -qF "$ZSH_HOOK_MARKER" "$zshrc" 2>/dev/null; then
|
||||||
|
info "Zsh-Hook ist bereits in ${zshrc} vorhanden."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Fuege Zsh-Hook in ${zshrc} ein..."
|
||||||
|
cat >> "$zshrc" << 'HOOKEOF'
|
||||||
|
|
||||||
|
# SSH Login Notifier
|
||||||
|
# Installiert von: https://git.techniverse.net/scriptos/ssh-login-notifier
|
||||||
|
[ -n "$SSH_CONNECTION" ] && [ -x /opt/ssh-login-notifier/ssh-login-notify.sh ] && /opt/ssh-login-notifier/ssh-login-notify.sh
|
||||||
|
HOOKEOF
|
||||||
|
|
||||||
|
info "Zsh-Hook aktiviert."
|
||||||
|
}
|
||||||
|
|
||||||
|
print_summary() {
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " SSH Login Notifier - Installation"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo " Status: Installiert und aktiv"
|
||||||
|
echo " Version: 1.0.0"
|
||||||
|
echo " Pfad: ${INSTALL_DIR}"
|
||||||
|
echo " Konfig: ${INSTALL_DIR}/config.conf"
|
||||||
|
echo " Hook: ${PROFILE_HOOK}"
|
||||||
|
echo ""
|
||||||
|
echo " Naechste Schritte:"
|
||||||
|
echo " 1. Konfiguration anpassen:"
|
||||||
|
echo " sudo nano ${INSTALL_DIR}/config.conf"
|
||||||
|
echo ""
|
||||||
|
echo " 2. Test durch SSH-Login auf diesen Server"
|
||||||
|
echo ""
|
||||||
|
echo " Deinstallation:"
|
||||||
|
echo " sudo ${INSTALL_DIR}/uninstall.sh"
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Hauptprogramm ---
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "SSH Login Notifier - Installation"
|
||||||
|
echo "================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
check_root
|
||||||
|
check_os
|
||||||
|
check_arch
|
||||||
|
check_dependencies
|
||||||
|
install_files
|
||||||
|
install_profile_hook
|
||||||
|
install_zsh_hook
|
||||||
|
print_summary
|
||||||
143
ssh-login-notify.sh
Normal file
143
ssh-login-notify.sh
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SSH Login Notifier - Hauptscript
|
||||||
|
# Wird ueber /etc/profile.d/ bei interaktivem SSH-Login aufgerufen
|
||||||
|
# https://git.techniverse.net/scriptos/ssh-login-notifier
|
||||||
|
|
||||||
|
# Nur bei SSH-Verbindungen ausfuehren
|
||||||
|
[[ -z "$SSH_CONNECTION" ]] && return 0 2>/dev/null || [[ -z "$SSH_CONNECTION" ]] && exit 0
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/ssh-login-notifier"
|
||||||
|
CONFIG_FILE="${INSTALL_DIR}/config.conf"
|
||||||
|
VERSION="1.0.0"
|
||||||
|
|
||||||
|
# Im Hintergrund ausfuehren, damit der Login nicht verzoegert wird
|
||||||
|
(
|
||||||
|
|
||||||
|
# --- Konfiguration laden ---
|
||||||
|
|
||||||
|
load_config() {
|
||||||
|
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||||
|
logger -t ssh-login-notifier "FEHLER: Konfigurationsdatei nicht gefunden: ${CONFIG_FILE}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
while IFS='=' read -r key value; do
|
||||||
|
key=$(echo "$key" | xargs)
|
||||||
|
value=$(echo "$value" | xargs)
|
||||||
|
[[ -z "$key" || "$key" == \#* ]] && continue
|
||||||
|
declare -g "$key=$value"
|
||||||
|
done < "$CONFIG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Login-Informationen sammeln ---
|
||||||
|
|
||||||
|
collect_login_info() {
|
||||||
|
LOGIN_USER="$USER"
|
||||||
|
LOGIN_HOST="$(hostname -f 2>/dev/null || hostname)"
|
||||||
|
LOGIN_DATE="$(date +%d.%m.%Y)"
|
||||||
|
LOGIN_TIME="$(date +%H:%M:%S)"
|
||||||
|
LOGIN_IP="${SSH_CLIENT%% *}"
|
||||||
|
LOGIN_IP="${LOGIN_IP:-unbekannt}"
|
||||||
|
|
||||||
|
GEO_INFO=""
|
||||||
|
if [[ "$GEO_LOOKUP" == "true" && "$LOGIN_IP" != "unbekannt" ]]; then
|
||||||
|
GEO_JSON=$(curl -s --max-time 5 "http://ip-api.com/json/${LOGIN_IP}?fields=status,country,regionName,city,isp" 2>/dev/null)
|
||||||
|
if echo "$GEO_JSON" | grep -q '"status":"success"'; then
|
||||||
|
GEO_COUNTRY=$(echo "$GEO_JSON" | grep -o '"country":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
GEO_REGION=$(echo "$GEO_JSON" | grep -o '"regionName":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
GEO_CITY=$(echo "$GEO_JSON" | grep -o '"city":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
GEO_ISP=$(echo "$GEO_JSON" | grep -o '"isp":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
GEO_INFO="${GEO_CITY}, ${GEO_REGION}, ${GEO_COUNTRY} (${GEO_ISP})"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- E-Mail senden ---
|
||||||
|
|
||||||
|
send_email() {
|
||||||
|
local subject="${EMAIL_SUBJECT_PREFIX} auf ${LOGIN_HOST}"
|
||||||
|
local body=""
|
||||||
|
body+="SSH-Zugriff erkannt\n"
|
||||||
|
body+="==============================\n\n"
|
||||||
|
body+="Server: ${LOGIN_HOST}\n"
|
||||||
|
body+="Datum: ${LOGIN_DATE}\n"
|
||||||
|
body+="Uhrzeit: ${LOGIN_TIME}\n"
|
||||||
|
body+="Benutzer: ${LOGIN_USER}\n"
|
||||||
|
body+="Quell-IP: ${LOGIN_IP}\n"
|
||||||
|
if [[ -n "$GEO_INFO" ]]; then
|
||||||
|
body+="Standort: ${GEO_INFO}\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v mail &>/dev/null; then
|
||||||
|
echo -e "$body" | mail -s "$subject" "$EMAIL_RECIPIENT"
|
||||||
|
elif command -v sendmail &>/dev/null; then
|
||||||
|
{
|
||||||
|
echo "Subject: ${subject}"
|
||||||
|
echo "From: ${EMAIL_FROM}"
|
||||||
|
echo "To: ${EMAIL_RECIPIENT}"
|
||||||
|
echo "Content-Type: text/plain; charset=UTF-8"
|
||||||
|
echo ""
|
||||||
|
echo -e "$body"
|
||||||
|
} | sendmail "$EMAIL_RECIPIENT"
|
||||||
|
elif command -v msmtp &>/dev/null; then
|
||||||
|
{
|
||||||
|
echo "Subject: ${subject}"
|
||||||
|
echo "From: ${EMAIL_FROM}"
|
||||||
|
echo "To: ${EMAIL_RECIPIENT}"
|
||||||
|
echo "Content-Type: text/plain; charset=UTF-8"
|
||||||
|
echo ""
|
||||||
|
echo -e "$body"
|
||||||
|
} | msmtp "$EMAIL_RECIPIENT"
|
||||||
|
else
|
||||||
|
logger -t ssh-login-notifier "FEHLER: Kein Mail-Tool gefunden (mail, sendmail, msmtp)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- ntfy senden ---
|
||||||
|
|
||||||
|
send_ntfy() {
|
||||||
|
local title="SSH Login registriert"
|
||||||
|
local message=""
|
||||||
|
message+="Es wurde ein SSH Login auf ${LOGIN_HOST} registriert.\n"
|
||||||
|
message+="\n"
|
||||||
|
message+="Datum: ${LOGIN_DATE}\n"
|
||||||
|
message+="Uhrzeit: ${LOGIN_TIME}\n"
|
||||||
|
message+="Benutzer: ${LOGIN_USER}\n"
|
||||||
|
message+="IP-Adresse des Clients: ${LOGIN_IP}"
|
||||||
|
if [[ -n "$GEO_INFO" ]]; then
|
||||||
|
message+="\nStandort: ${GEO_INFO}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -a curl_args=(
|
||||||
|
-s
|
||||||
|
--max-time 10
|
||||||
|
-H "Title: ${title}"
|
||||||
|
-H "Priority: ${NTFY_PRIORITY:-3}"
|
||||||
|
-H "Tags: ${NTFY_TAGS:-warning,computer}"
|
||||||
|
-d "$(echo -e "$message")"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ -n "$NTFY_AUTH_TOKEN" ]]; then
|
||||||
|
curl_args+=(-H "Authorization: Bearer ${NTFY_AUTH_TOKEN}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl "${curl_args[@]}" "${NTFY_SERVER}/${NTFY_TOPIC}" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Hauptprogramm ---
|
||||||
|
|
||||||
|
load_config
|
||||||
|
collect_login_info
|
||||||
|
|
||||||
|
IFS=',' read -ra METHODS <<< "$NOTIFICATION_METHODS"
|
||||||
|
for method in "${METHODS[@]}"; do
|
||||||
|
method=$(echo "$method" | xargs)
|
||||||
|
case "$method" in
|
||||||
|
email) send_email ;;
|
||||||
|
ntfy) send_ntfy ;;
|
||||||
|
*) logger -t ssh-login-notifier "Unbekannte Methode: ${method}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
) &>/dev/null &
|
||||||
|
disown
|
||||||
78
uninstall.sh
Normal file
78
uninstall.sh
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SSH Login Notifier - Deinstallationsscript
|
||||||
|
# https://git.techniverse.net/scriptos/ssh-login-notifier
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/ssh-login-notifier"
|
||||||
|
PROFILE_HOOK="/etc/profile.d/ssh-login-notify.sh"
|
||||||
|
ZSH_HOOK_MARKER="# SSH Login Notifier"
|
||||||
|
|
||||||
|
# --- Hilfsfunktionen ---
|
||||||
|
|
||||||
|
info() { echo -e "\e[32m[INFO]\e[0m $1"; }
|
||||||
|
warn() { echo -e "\e[33m[WARN]\e[0m $1"; }
|
||||||
|
error() { echo -e "\e[31m[ERROR]\e[0m $1"; exit 1; }
|
||||||
|
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error "Dieses Script muss als root ausgefuehrt werden (sudo)."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Deinstallation ---
|
||||||
|
|
||||||
|
remove_profile_hook() {
|
||||||
|
if [[ -f "$PROFILE_HOOK" ]]; then
|
||||||
|
info "Entferne Profile-Hook: ${PROFILE_HOOK}"
|
||||||
|
rm -f "$PROFILE_HOOK"
|
||||||
|
info "Profile-Hook entfernt."
|
||||||
|
else
|
||||||
|
info "Kein Profile-Hook gefunden - nichts zu entfernen."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_zsh_hook() {
|
||||||
|
local zshrc="/etc/zsh/zshrc"
|
||||||
|
if [[ -f "$zshrc" ]] && grep -qF "$ZSH_HOOK_MARKER" "$zshrc" 2>/dev/null; then
|
||||||
|
info "Entferne Zsh-Hook aus ${zshrc}"
|
||||||
|
sed -i "/^${ZSH_HOOK_MARKER}/,+2d" "$zshrc"
|
||||||
|
sed -i '/^$/N;/^\n$/d' "$zshrc"
|
||||||
|
info "Zsh-Hook entfernt."
|
||||||
|
else
|
||||||
|
info "Kein Zsh-Hook gefunden - nichts zu entfernen."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_files() {
|
||||||
|
if [[ -d "$INSTALL_DIR" ]]; then
|
||||||
|
info "Entferne Installationsverzeichnis: ${INSTALL_DIR}"
|
||||||
|
rm -rf "$INSTALL_DIR"
|
||||||
|
info "Dateien entfernt."
|
||||||
|
else
|
||||||
|
info "Installationsverzeichnis nicht gefunden - nichts zu entfernen."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Hauptprogramm ---
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "SSH Login Notifier - Deinstallation"
|
||||||
|
echo "===================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
check_root
|
||||||
|
|
||||||
|
read -p "SSH Login Notifier wirklich deinstallieren? (j/N) " confirm
|
||||||
|
if [[ "$confirm" != "j" && "$confirm" != "J" ]]; then
|
||||||
|
info "Abgebrochen."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
remove_profile_hook
|
||||||
|
remove_zsh_hook
|
||||||
|
remove_files
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
info "SSH Login Notifier wurde vollstaendig deinstalliert."
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user