% ============================================
% STEP 02: FIREWALL MIT UFW
% ============================================

\section{Firewall mit UFW einrichten}
\label{sec:step02}

In diesem Schritt konfigurieren wir die Firewall des Servers mit \textbf{UFW} (Uncomplicated Firewall). UFW ist eine benutzerfreundliche Schnittstelle für \texttt{iptables}, die seit Ubuntu 8.04 standardmäßig installiert ist.

\subsection{Was ist eine Firewall und warum brauchen wir sie?}

Eine Firewall ist wie ein \textbf{Türsteher vor einem Club}: Sie entscheidet, welche Datenpakete (Gäste) hereinkommen und welche draußen bleiben. Ohne Firewall steht der Server "nackt" im Internet und jeder kann an jede Tür (Port) klopfen.

\textbf{Das Prinzip der minimalen Angriffsfläche:}
\begin{itemize}
    \item Jeder offene Port ist eine potenzielle \textbf{Eintrittspforte} für Angreifer
    \item Je weniger Ports offen sind, desto weniger Möglichkeiten gibt es für einen Angriff
    \item Standard-Dienste haben oft \textbf{bekannte Sicherheitslücken} – selbst wenn wir sie nicht aktiv nutzen
\end{itemize}

\subsection{Die 65.535 Ports: Ein kurzer Überblick}

Ein Server hat 65.535 TCP-Ports und 65.535 UDP-Ports. Jeder Netzwerkdienst lauscht auf einem bestimmten Port. Hier sind die bekanntesten:

\begin{table}[h]
\centering
\caption{Bekannte Ports und ihre Dienste}
\begin{tabular}{@{}cll@{}}
\toprule
\textbf{Port} & \textbf{Dienst} & \textbf{Risiko/Bemerkung} \\
\midrule
21   & FTP           & Uralt, Passwörter im Klartext -- niemals offen lassen \\
22   & SSH           & Unser Verwaltungszugang -- MUSS offen sein \\
23   & Telnet        & Wie SSH, aber unverschlüsselt -- Todesurteil für Server \\
25   & SMTP          & Mail-Versand -- Angreifer könnten Spam verschicken \\
53   & DNS           & Namensauflösung -- Ziel für DDoS-Angriffe \\
80   & HTTP          & Standard-Webport -- für unsere Fitness-App \\
110  & POP3          & E-Mail-Abruf -- veraltet, unsicher \\
143  & IMAP          & E-Mail-Abruf -- veraltet \\
443  & HTTPS         & Verschlüsselter Webport -- PFLICHT für PWAs! \\
3306 & MySQL         & Datenbank -- beliebtes Bruteforce-Ziel \\
5432 & PostgreSQL    & Datenbank -- ebenso populär bei Angreifern \\
6379 & Redis         & Oft ohne Passwort vorkonfiguriert -- sehr gefährlich \\
8080 & HTTP-Alt      & Häufig für Entwicklertools mit schwacher Absicherung \\
27017& MongoDB       & Bekannt für katastrophale Standardkonfigurationen \\
\bottomrule
\end{tabular}
\end{table}

\textbf{Merksatz:} Alles, was du nicht explizit brauchst, wird blockiert. Das ist keine Paranoia, sondern Best Practice im Server-Management.

\subsection{Die drei Ports, die wir öffnen}

Wir öffnen nur drei Ports – das absolute Minimum für einen Webserver:

\begin{table}[h]
\centering
\caption{Geöffnete Ports und ihre Begründung}
\begin{tabular}{@{}clp{5cm}@{}}
\toprule
\textbf{Port} & \textbf{Dienst} & \textbf{Warum offen?} \\
\midrule
22   & SSH           & Unser \textbf{einziger Verwaltungszugang}. Ohne Port 22 könnten wir den Server nicht mehr fernsteuern -- wir wären ausgesperrt. \\
80   & HTTP          & \textbf{Standard-Webport} für alle Browser. Wenn jemand deine Domain aufruft, landet er zuerst hier. Leitet später automatisch auf HTTPS (Port 443) um. \\
443  & HTTPS         & \textbf{Verschlüsselte Webseiten}. Seit 2018 Pflicht für moderne Web-Apps! Ohne HTTPS verweigern Browser Funktionen wie PWA-Installation, Kamera-Zugriff oder Standort. \\
\bottomrule
\end{tabular}
\end{table}

\subsection{Warum HTTPS für PWAs Pflicht ist}

Eine Progressive Web App (PWA) \textbf{kann ohne HTTPS nicht installiert werden}. Das ist eine Sicherheitsanforderung von Google und Apple:

\begin{itemize}
    \item Der \textbf{Service Worker} (das Herzstück einer PWA) benötigt zwingend HTTPS
    \item Nur so kann der Browser garantieren, dass die App nicht manipuliert wurde
    \item HTTP-Verbindungen können von Angreifern verändert werden (Man-in-the-Middle)
\end{itemize}

\textbf{Praxis-Beispiel:} Wenn du \texttt{http://deine-domain.de} aufrufst und dort die PWA installieren willst, verweigert Chrome die Installation. Erst mit \texttt{https://deine-domain.de} und einem gültigen SSL-Zertifikat funktioniert es.

\subsection{Durchführung}

\subsubsection{Standardrichtlinien setzen}

Zuerst definieren wir die grundlegenden Regeln: Alles Eingehende wird blockiert, alles Ausgehende erlaubt.

\textbf{Auf dem Server:}

\begin{lstlisting}[language=Bash, caption={Firewall-Standardregeln definieren}]
ufw default deny incoming
ufw default allow outgoing
\end{lstlisting}

\textbf{Erklärung der Befehle:}
\begin{itemize}
    \item \texttt{ufw} -- das Firewall-Programm (Uncomplicated Firewall)
    \item \texttt{default} -- setzt die Standardregel für alle Ports, die nicht explizit konfiguriert sind
    \item \texttt{deny incoming} -- alle eingehenden Verbindungen werden \textbf{abgelehnt} (geblockt)
    \item \texttt{allow outgoing} -- alle ausgehenden Verbindungen sind \textbf{erlaubt} (Server kann selbst ins Internet)
\end{itemize}

\textbf{Warum outgoing erlauben?} Der Server muss Updates herunterladen können (\texttt{apt update}), auf externe APIs zugreifen und im Internet kommunizieren. Das sind alles ausgehende Verbindungen -- die der Server selbst initiiert.

\subsubsection{Benötigte Ports öffnen}

Jetzt geben wir gezielt die drei Ports frei, die von außen erreichbar sein sollen.

\begin{lstlisting}[language=Bash, caption={Ports 22, 80, 443 für TCP freigeben}]
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
\end{lstlisting}

\textbf{Erklärung der Befehle:}
\begin{itemize}
    \item \texttt{allow} -- dieser Port wird geöffnet
    \item \texttt{22/tcp} -- Port 22, nur TCP-Protokoll (nicht UDP)
    \item \texttt{80/tcp} -- Port 80 (HTTP), nur TCP
    \item \texttt{443/tcp} -- Port 443 (HTTPS), nur TCP
\end{itemize}

\textbf{Warum nur TCP?} SSH, HTTP und HTTPS verwenden ausschließlich das TCP-Protokoll. UDP wird von diesen Diensten nicht benötigt. Würden wir nur \texttt{ufw allow 80} (ohne \texttt{/tcp}) schreiben, wäre auch UDP offen -- unnötige Angriffsfläche.

\subsubsection{Firewall aktivieren}

Die Firewall wurde bisher nur konfiguriert, ist aber noch nicht aktiv. Erst mit dem Enable-Befehl greifen die Regeln.

\begin{lstlisting}[language=Bash, caption={Firewall aktivieren}]
ufw --force enable
\end{lstlisting}

\textbf{Erklärung:}
\begin{itemize}
    \item \texttt{enable} -- schaltet die Firewall ein
    \item \texttt{--force} -- überspringt die Sicherheitsabfrage ("Bist du sicher?") und führt den Befehl direkt aus
\end{itemize}

\textbf{Achtung:} Wenn du Port 22 vergessen hättest, wärst du jetzt vom Server ausgesperrt! Die Firewall würde deine aktuelle SSH-Verbindung zwar nicht sofort trennen, aber ein erneuter Login wäre unmöglich. Deshalb prüfen wir im nächsten Schritt die Konfiguration.

\subsubsection{Konfiguration überprüfen}

\begin{lstlisting}[language=Bash, caption={Firewall-Status mit Details anzeigen}]
ufw status verbose
\end{lstlisting}

\textbf{Erklärung:}
\begin{itemize}
    \item \texttt{status} -- zeigt an, ob die Firewall aktiv ist und welche Regeln gelten
    \item \texttt{verbose} -- erweiterte Ausgabe mit zusätzlichen Details wie Logging-Einstellungen und Standardrichtlinien
\end{itemize}

Die erwartete Ausgabe:

\begin{lstlisting}[language=Bash, caption={Erwartete Firewall-Ausgabe (gekürzt)}]
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)
\end{lstlisting}

\textbf{Wichtige Details der Ausgabe:}
\begin{itemize}
    \item \texttt{Status: active} -- die Firewall läuft und blockt unerwünschten Traffic
    \item \texttt{Default: deny (incoming)} -- alle nicht explizit erlaubten eingehenden Verbindungen werden geblockt
    \item \texttt{Anywhere} -- diese Ports sind von \textbf{jeder} IP-Adresse aus erreichbar (für Webseiten notwendig)
    \item \texttt{(v6)} -- die Regeln gelten identisch für IPv6, sodass auch moderne Netzwerke geschützt sind
\end{itemize}

\subsection{Zusammenfassung}

Nach diesem Schritt ist die Firewall aktiv und schützt den Server:

\begin{itemize}
    \item \textbf{65.532 Ports sind dicht} -- nur 3 sind offen
    \item \textbf{SSH} (22) bleibt als einziger Verwaltungszugang offen
    \item \textbf{HTTP/HTTPS} (80/443) sind für die spätere Web-App vorbereitet
    \item \textbf{IPv4 und IPv6} werden beide geschützt
    \item Die Firewall startet automatisch bei jedem Server-Neustart
\end{itemize}

\textbf{Praxis-Tipp:} Mit dem Befehl \texttt{ufw status numbered} kannst du jederzeit alle Regeln mit Nummern anzeigen. Eine einzelne Regel löschst du dann mit \texttt{ufw delete [Nummer]}.