Rocky www: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| (26 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 55: | Zeile 55: | ||
= VirtualHost konfigurieren = | = VirtualHost konfigurieren = | ||
| − | ;Die mitgelieferte ssl.conf | + | ;Die mitgelieferte ssl.conf wird ersetzt mit dem notwendigsten |
| − | * rm /etc/httpd/conf.d/ | + | * echo Listen 443 https > /etc/httpd/conf.d/ssl.conf |
| + | ;Die Welcome Seite wir vaborisiert | ||
| + | * rm /etc/httpd/conf.d/welcome.conf | ||
| + | ;Wir legen unsere Seite an | ||
* vi /etc/httpd/conf.d/www.conf | * vi /etc/httpd/conf.d/www.conf | ||
<pre> | <pre> | ||
| − | + | ||
| − | |||
# HTTPS VirtualHost | # HTTPS VirtualHost | ||
<VirtualHost *:443> | <VirtualHost *:443> | ||
ServerName www.it2XX.int | ServerName www.it2XX.int | ||
| − | DocumentRoot /var/ | + | DocumentRoot /var/repo |
| − | |||
SSLEngine on | SSLEngine on | ||
SSLCertificateFile /etc/ssl/own.crt | SSLCertificateFile /etc/ssl/own.crt | ||
SSLCertificateKeyFile /etc/ssl/own.key | SSLCertificateKeyFile /etc/ssl/own.key | ||
| − | <Directory /var/ | + | <Directory /var/repo> |
Options +Indexes | Options +Indexes | ||
AllowOverride None | AllowOverride None | ||
| Zeile 90: | Zeile 91: | ||
= Beispielseite = | = Beispielseite = | ||
;Eine einfache PHP-Seite die den Hostnamen und die aktuelle Zeit anzeigt. /var/www/html ist die Standard-DocumentRoot von httpd – existiert bereits, kein eigenes Verzeichnis und kein eigener SELinux-Kontext nötig | ;Eine einfache PHP-Seite die den Hostnamen und die aktuelle Zeit anzeigt. /var/www/html ist die Standard-DocumentRoot von httpd – existiert bereits, kein eigenes Verzeichnis und kein eigener SELinux-Kontext nötig | ||
| − | * vi /var/ | + | * vi /var/repo/index.php |
<pre> | <pre> | ||
<!DOCTYPE html> | <!DOCTYPE html> | ||
| Zeile 117: | Zeile 118: | ||
Syntax OK | Syntax OK | ||
| − | = Dienst starten = | + | = Dienst Testweise starten = |
| − | |||
* systemctl restart httpd | * systemctl restart httpd | ||
| + | |||
| + | = SELinux = | ||
| + | ;SELinux läuft auf Rocky standardmäßig im enforcing-Modus. /var/www/html ist bereits korrekt mit httpd_sys_content_t gelabelt – nur die Zertifikate unter /etc/ssl brauchen einen eigenen Kontext | ||
| + | |||
| + | == Fehleranalyse == | ||
| + | ;Falls der Zugriff trotzdem fehlschlägt – SELinux-Blockaden anzeigen | ||
| + | * ausearch -m avc -ts recent | ||
| + | |||
| + | == Kontext setzen == | ||
| + | *semanage fcontext -a -t httpd_sys_content_t "/etc/ssl/own\.(crt|key)" | ||
| + | *restorecon -Rv /etc/ssl/ | ||
| + | |||
| + | ;Kontext prüfen | ||
| + | * ls -Z /etc/ssl/own.crt /etc/ssl/own.key | ||
= Firewall = | = Firewall = | ||
| Zeile 126: | Zeile 140: | ||
* firewall-cmd --permanent --zone=public --add-service=https | * firewall-cmd --permanent --zone=public --add-service=https | ||
* firewall-cmd --reload | * firewall-cmd --reload | ||
| + | = Test = | ||
| + | ;Im Browser aufrufen | ||
| + | *https://www.it2XX.int | ||
| + | Wir bekommen ein Forbidden | ||
| + | |||
| + | You don't have the permission to access this resource | ||
| + | |||
| + | = Wieder zu Ausearch= | ||
| + | *ausearch -m avc -ts recent | ||
| + | <pre> | ||
| + | time->Tue Jul 7 23:59:32 2026 | ||
| + | type=PROCTITLE msg=audit(1783461572.080:196): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44 | ||
| + | type=SYSCALL msg=audit(1783461572.080:196): arch=c000003e syscall=262 success=no exit=-13 a0=ffffff9c a1=7fb4c400bd08 a2=7fb4d1de37c0 a3=100 items=0 ppid=3347 pid=3350 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null) | ||
| + | type=AVC msg=audit(1783461572.080:196): avc: denied { getattr } for pid=3350 comm="httpd" path="/var/repo/index.html" dev="dm-0" ino=67781042 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0 | ||
| + | </pre> | ||
| + | *semanage fcontext -a -t httpd_sys_content_t "/var/repo(/.*)?" | ||
| + | *restorecon -Rv /var/repo | ||
| + | ;Erklärung der Regex "/var/repo(/.*)?" | ||
| + | {| class="wikitable" | ||
| + | ! Teil !! Bedeutung | ||
| + | |- | ||
| + | | <code>/var/repo</code> || literaler, fester Text – muss genau so vorkommen | ||
| + | |- | ||
| + | | <code>( )</code> || Gruppierung – fasst den eingeschlossenen Ausdruck zusammen | ||
| + | |- | ||
| + | | <code>/</code> || literales Zeichen – ein fester Slash | ||
| + | |- | ||
| + | | <code>.</code> || beliebiges einzelnes Zeichen (Wildcard) | ||
| + | |- | ||
| + | | <code>*</code> || 0 bis unendlich Wiederholungen des davorstehenden Elements (hier: <code>.</code>) | ||
| + | |- | ||
| + | | <code>.*</code> || zusammen: beliebig viele beliebige Zeichen (auch keins) | ||
| + | |- | ||
| + | | <code>(/.*)</code> || Gruppe: ein <code>/</code> gefolgt von beliebig vielem Inhalt | ||
| + | |- | ||
| + | | <code>?</code> || macht die davorstehende Gruppe optional (0 oder 1 mal) | ||
| + | |- | ||
| + | | <code>(/.*)?</code> || die ganze Gruppe "/ + beliebiger Inhalt" ist optional | ||
| + | |} | ||
| + | |||
| + | '''Matched:''' | ||
| + | * <code>/var/repo</code> | ||
| + | * <code>/var/repo/</code> | ||
| + | * <code>/var/repo/index.html</code> | ||
| + | * <code>/var/repo/sub/dir/datei.txt</code> (beliebige Tiefe) | ||
| + | |||
| + | '''Matched nicht:''' | ||
| + | * <code>/var/repository</code> | ||
| + | * <code>/var/repo2</code> | ||
| + | |||
| + | = Test = | ||
| + | ;Im Browser aufrufen | ||
| + | *https://www.it2XX.int | ||
| + | ;Jetzt klappt es | ||
= Logs = | = Logs = | ||
| Zeile 131: | Zeile 199: | ||
* tail -f /var/log/httpd/www.it2XX.int_error.log | * tail -f /var/log/httpd/www.it2XX.int_error.log | ||
* tail -f /var/log/httpd/www.it2XX.int_access.log | * tail -f /var/log/httpd/www.it2XX.int_access.log | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
;Zertifikat prüfen | ;Zertifikat prüfen | ||
* openssl s_client -connect www.it2XX.int:443 -showcerts | * openssl s_client -connect www.it2XX.int:443 -showcerts | ||
Aktuelle Version vom 8. Juli 2026, 16:17 Uhr
Installation
DATEN
| Parameter | Wert | Erläuterung |
|---|---|---|
| VM Name | www | Name der VM |
| Disk | 20GB | Vorgabe übernehmen |
| CPU | 4 Cores | Kerne |
| Ram | 4 GB | Speicher |
| Netzwerk (NIC) | DMZ | Interface-Zuweisung in VirtualBox |
| Admin | root | Passwort: radler |
| User | kit | Passwort: kit |
| IP | 10.88.2XX.11/24 | Statische IP |
| CIDR | 24 | Classless Inter-Domain Routing Präfixlänge |
| GW | 10.88.2XX.1 | GATEWAY |
| NS | 10.88.2XX.21 | Resolver |
| FQDN | www.it2XX.int | Fully Qualified Domain Name |
| DOM | it2XX.int | Domain Name |
Hostname
- hostnamectl set-hostname FQDN
Netzwerk
- nmcli con mod enp0s3 ipv4.addresses IP/CIDR
- nmcli con mod enp0s3 ipv4.gateway GW
- nmcli con mod enp0s3 ipv4.dns NS
- nmcli con mod enp0s3 ipv4.method manual
- nmcli con mod enp0s3 ipv4.dns-search DOM
- nmcli con mod enp0s3 connection.autoconnect yes
- nmcli con up enp0s3
Hintergrund
- Die Verbindungen findet ihr hier
- DIR: /etc/NetworkManager/system-connections/
- In unserem Fall
- cat /etc/NetworkManager/system-connections/enp0s3.nmconnection
[connection] id=enp0s3 uuid=40ff96e5-0c0d-31de-9bf0-f75da265425b type=ethernet autoconnect-priority=-999 interface-name=enp0s3 timestamp=1784278716 [ethernet] [ipv4] address1=192.168.3.127/24 dns=192.168.20.1; dns-search=it.int; gateway=192.168.3.254 method=manual [ipv6] addr-gen-mode=eui64 method=auto [proxy]
Apache Webserver auf Rocky Linux
Der Webserver läuft in der DMZ und stellt Webinhalte über HTTP und HTTPS bereit. HTTP-Anfragen werden automatisch auf HTTPS umgeleitet. Das Zertifikat kommt von web.samogo.de und liegt unter /etc/ssl/.
Installation
- dnf install -y httpd mod_ssl
Zertifikat holen
- get-cert.sh
PHP installieren
- PHP wird über das dnf-Modul installiert – so lässt sich später auch eine andere Version aktivieren
- dnf install -y php php-fpm php-mysqlnd php-json php-mbstring
- PHP-FPM starten – httpd übergibt PHP-Anfragen an diesen Prozess
- systemctl enable --now php-fpm
ℹ️ Hinweis:
- mod_php
- Läuft als Apache-Modul direkt im httpd-Prozess – jeder Apache-Worker hat einen eigenen PHP-Interpreter im Speicher, was bei prefork/MPM viel RAM frisst und PHP fest an Apache bindet.
- PHP-FPM
- Läuft als eigenständiger Prozess-Pool außerhalb von httpd, der über FastCGI (Unix-Socket oder TCP) angesprochen wird – dadurch kann Apache mit dem schlankeren event/worker-MPM laufen, PHP-Prozesse lassen sich unabhängig skalieren/neustarten, und derselbe FPM-Pool ist auch von nginx oder mehreren vhosts mit unterschiedlichen PHP-Versionen nutzbar.
VirtualHost konfigurieren
- Die mitgelieferte ssl.conf wird ersetzt mit dem notwendigsten
- echo Listen 443 https > /etc/httpd/conf.d/ssl.conf
- Die Welcome Seite wir vaborisiert
- rm /etc/httpd/conf.d/welcome.conf
- Wir legen unsere Seite an
- vi /etc/httpd/conf.d/www.conf
# HTTPS VirtualHost
<VirtualHost *:443>
ServerName www.it2XX.int
DocumentRoot /var/repo
SSLEngine on
SSLCertificateFile /etc/ssl/own.crt
SSLCertificateKeyFile /etc/ssl/own.key
<Directory /var/repo>
Options +Indexes
AllowOverride None
Require all granted
</Directory>
# PHP über FPM
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>
ErrorLog /var/log/httpd/www.it2XX.int_error.log
CustomLog /var/log/httpd/www.it2XX.int_access.log combined
</VirtualHost>
Beispielseite
- Eine einfache PHP-Seite die den Hostnamen und die aktuelle Zeit anzeigt. /var/www/html ist die Standard-DocumentRoot von httpd – existiert bereits, kein eigenes Verzeichnis und kein eigener SELinux-Kontext nötig
- vi /var/repo/index.php
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Willkommen auf <?= gethostname() ?></title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 4em auto; }
h1 { color: #c0392b; }
p { color: #333; }
</style>
</head>
<body>
<h1>Willkommen auf <?= gethostname() ?></h1>
<p>Server: <strong><?= $_SERVER['SERVER_NAME'] ?></strong></p>
<p>Zeit: <strong><?= date('d.m.Y H:i:s') ?></strong></p>
<p>PHP: <strong><?= phpversion() ?></strong></p>
</body>
</html>
Konfiguration prüfen
- Syntaxfehler erkennen bevor httpd neu gestartet wird
- apachectl configtest
Syntax OK
Dienst Testweise starten
- systemctl restart httpd
SELinux
- SELinux läuft auf Rocky standardmäßig im enforcing-Modus. /var/www/html ist bereits korrekt mit httpd_sys_content_t gelabelt – nur die Zertifikate unter /etc/ssl brauchen einen eigenen Kontext
Fehleranalyse
- Falls der Zugriff trotzdem fehlschlägt – SELinux-Blockaden anzeigen
- ausearch -m avc -ts recent
Kontext setzen
- semanage fcontext -a -t httpd_sys_content_t "/etc/ssl/own\.(crt|key)"
- restorecon -Rv /etc/ssl/
- Kontext prüfen
- ls -Z /etc/ssl/own.crt /etc/ssl/own.key
Firewall
- HTTP und HTTPS auf dem www-Server freigeben
- firewall-cmd --permanent --zone=public --add-service=http
- firewall-cmd --permanent --zone=public --add-service=https
- firewall-cmd --reload
Test
- Im Browser aufrufen
Wir bekommen ein Forbidden
You don't have the permission to access this resource
Wieder zu Ausearch
- ausearch -m avc -ts recent
time->Tue Jul 7 23:59:32 2026
type=PROCTITLE msg=audit(1783461572.080:196): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44
type=SYSCALL msg=audit(1783461572.080:196): arch=c000003e syscall=262 success=no exit=-13 a0=ffffff9c a1=7fb4c400bd08 a2=7fb4d1de37c0 a3=100 items=0 ppid=3347 pid=3350 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
type=AVC msg=audit(1783461572.080:196): avc: denied { getattr } for pid=3350 comm="httpd" path="/var/repo/index.html" dev="dm-0" ino=67781042 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0
- semanage fcontext -a -t httpd_sys_content_t "/var/repo(/.*)?"
- restorecon -Rv /var/repo
- Erklärung der Regex "/var/repo(/.*)?"
| Teil | Bedeutung |
|---|---|
/var/repo |
literaler, fester Text – muss genau so vorkommen |
( ) |
Gruppierung – fasst den eingeschlossenen Ausdruck zusammen |
/ |
literales Zeichen – ein fester Slash |
. |
beliebiges einzelnes Zeichen (Wildcard) |
* |
0 bis unendlich Wiederholungen des davorstehenden Elements (hier: .)
|
.* |
zusammen: beliebig viele beliebige Zeichen (auch keins) |
(/.*) |
Gruppe: ein / gefolgt von beliebig vielem Inhalt
|
? |
macht die davorstehende Gruppe optional (0 oder 1 mal) |
(/.*)? |
die ganze Gruppe "/ + beliebiger Inhalt" ist optional |
Matched:
/var/repo/var/repo//var/repo/index.html/var/repo/sub/dir/datei.txt(beliebige Tiefe)
Matched nicht:
/var/repository/var/repo2
Test
- Im Browser aufrufen
- Jetzt klappt es
Logs
- journalctl -fu httpd
- tail -f /var/log/httpd/www.it2XX.int_error.log
- tail -f /var/log/httpd/www.it2XX.int_access.log
- Zertifikat prüfen
- openssl s_client -connect www.it2XX.int:443 -showcerts