93 lines
7.3 KiB
Bash
93 lines
7.3 KiB
Bash
#!/bin/bash
|
|
# masoara-apache-haproxy-rpc2.sh (PE rpc2, copiat cu scp si chemat pe nume): retetele `apache` si `haproxy` ale remedierii
|
|
# (cloud-gateway/control-plane/remediere.mjs, GENERATOARE.apache / GENERATOARE.haproxy) masurate pe servere REALE, in containere
|
|
# (httpd:alpine, haproxy:alpine, fiecare cu OpenSSL-ul lui Alpine), publicate NUMAI pe 127.0.0.1 (8447 Apache, 8448 HAProxy; nimic pe
|
|
# porturile gazdei), cu EXACT fragmentele retetei pentru hndl-exposed + tls12-accepted + hsts-missing:
|
|
# apache: SSLOpenSSLConfCmd Groups X25519MLKEM768:X25519 / SSLProtocol -all +TLSv1.3 / Header always set Strict-Transport-Security "max-age=31536000"
|
|
# haproxy: ssl-default-bind-curves X25519MLKEM768:X25519 / ssl-default-bind-options ssl-min-ver TLSv1.3 / http-response set-header Strict-Transport-Security "max-age=31536000"
|
|
# Preconditiile retetei se citesc cum le cere ea (randul de pornire al lui Apache cu OpenSSL/; `haproxy -vv` "Running on OpenSSL"), si
|
|
# comenzile ei de verificare ruleaza in container (`httpd -t` = apachectl configtest; `haproxy -c -f`). Sonde: node 24 de pe rpc2
|
|
# (/root/reteta-sonda.mjs: hibrid singur, clasic singur, hibrid+clasic, TLS 1.2 refuzat), HSTS prin curl -k. Containere si imagini sterse
|
|
# la sfarsit; RPC-ul local cronometrat inainte si dupa. Iesire 0 = 8 din 8 sonde cum trebuie, 1 altfel.
|
|
set -u
|
|
D=/root/reteta-ah; rm -rf "$D"; mkdir -p "$D/certs" "$D/apache" "$D/haproxy"; cd "$D" || exit 2
|
|
N=/opt/node24/bin/node; S=/root/reteta-sonda.mjs
|
|
[ -x "$N" ] || { echo "NEMASURAT: node 24 lipseste la $N"; exit 2; }
|
|
[ -f "$S" ] || { echo "NEMASURAT: sonda lipseste la $S"; exit 2; }
|
|
rpc() { local t0=$(date +%s%N); curl -s -m 5 -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}' http://127.0.0.1:8545 | grep -o '"result":"0x[0-9a-f]*"' | head -1; echo " ($(( ($(date +%s%N) - t0) / 1000000 )) ms)"; }
|
|
echo "== RPC inainte: $(rpc)"
|
|
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout certs/privkey.pem -out certs/fullchain.pem -days 2 -subj '/CN=proba.local' > /dev/null 2>&1 && cat certs/privkey.pem certs/fullchain.pem > certs/proba.pem && chmod 644 certs/*.pem && echo "cert ok (autosemnat, 2 zile)"
|
|
rele=0
|
|
cere() { local nume="$1" ast="$2"; shift 2; out=$("$@" 2>&1); c=$?; if [ "$c" = "$ast" ]; then echo " OK $nume -> cod $c: $(printf '%s' "$out" | cut -c1-170)"; else echo " RAU $nume -> cod $c (asteptat $ast): $(printf '%s' "$out" | cut -c1-170)"; rele=$((rele + 1)); fi; }
|
|
sonde() { local port="$1" nume="$2"
|
|
cere "$nume: hibrid singur (X25519MLKEM768)" 0 $N $S 127.0.0.1 $port X25519MLKEM768
|
|
cere "$nume: clasic singur (X25519, rezerva din reteta)" 0 $N $S 127.0.0.1 $port X25519
|
|
cere "$nume: hibrid + clasic (preferinta)" 0 $N $S 127.0.0.1 $port X25519MLKEM768:X25519
|
|
cere "$nume: client TLS 1.2 (refuz)" 1 $N $S 127.0.0.1 $port X25519 TLSv1.2
|
|
echo " -- $nume: HSTS (curl -k)"; curl -sk -m 10 -D - -o /dev/null https://127.0.0.1:$port/ | grep -iE '^(strict-transport-security|HTTP)' | tr -d '\r' | sed 's/^/ /'; }
|
|
|
|
# ------------------------------------------------------------------ Apache httpd
|
|
echo "== APACHE: imaginea httpd:alpine"; docker pull -q httpd:alpine > /dev/null 2>&1; docker image inspect httpd:alpine --format 'imagine: {{.Id}} {{.Size}} octeti' | cut -c1-90
|
|
docker run --rm httpd:alpine httpd -v 2>&1 | head -2 | sed 's/^/ /'
|
|
# httpd.conf al imaginii + modulele cerute de reteta (ssl, socache, headers) + gazda virtuala cu EXACT fragmentul retetei
|
|
docker run --rm httpd:alpine cat /usr/local/apache2/conf/httpd.conf > apache/httpd.conf 2>/dev/null
|
|
sed -i -e 's/^#LoadModule ssl_module/LoadModule ssl_module/' -e 's/^#LoadModule socache_shmcb_module/LoadModule socache_shmcb_module/' -e 's/^#LoadModule headers_module/LoadModule headers_module/' apache/httpd.conf
|
|
cat >> apache/httpd.conf <<'EOF'
|
|
|
|
# ---- proba retetei AERE (remediere.mjs, profilul apache) ----
|
|
Listen 8447
|
|
<VirtualHost *:8447>
|
|
ServerName proba.local
|
|
DocumentRoot "/usr/local/apache2/htdocs"
|
|
SSLEngine on
|
|
SSLCertificateFile /usr/local/apache2/conf/certs/fullchain.pem
|
|
SSLCertificateKeyFile /usr/local/apache2/conf/certs/privkey.pem
|
|
# EXACT fragmentul retetei:
|
|
SSLOpenSSLConfCmd Groups X25519MLKEM768:X25519
|
|
SSLProtocol -all +TLSv1.3
|
|
Header always set Strict-Transport-Security "max-age=31536000"
|
|
</VirtualHost>
|
|
EOF
|
|
grep -c 'LoadModule ssl_module' apache/httpd.conf | sed 's/^/ LoadModule ssl_module randuri: /'
|
|
docker rm -f apache-reteta > /dev/null 2>&1
|
|
docker run -d --name apache-reteta -p 127.0.0.1:8447:8447 -v "$D/apache/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro" -v "$D/certs:/usr/local/apache2/conf/certs:ro" httpd:alpine > /dev/null; sleep 3
|
|
docker ps --filter name=apache-reteta --format ' container: {{.Status}}'
|
|
echo " -- verificarea retetei: httpd -t (apachectl configtest) in container"; docker exec apache-reteta httpd -t 2>&1 | tail -1 | sed 's/^/ /'
|
|
echo " -- preconditia retetei: randul de pornire cu OpenSSL/ (jurnalul serverului)"; docker logs apache-reteta 2>&1 | grep -i 'openssl/' | tail -1 | cut -c1-160 | sed 's/^/ /'
|
|
sonde 8447 apache
|
|
docker logs apache-reteta 2>&1 | grep -iE 'error|emerg' | grep -v 'AH00558' | head -3 | sed 's/^/ jurnal: /'
|
|
|
|
# ------------------------------------------------------------------ HAProxy
|
|
echo "== HAPROXY: imaginea haproxy:alpine"; docker pull -q haproxy:alpine > /dev/null 2>&1; docker image inspect haproxy:alpine --format 'imagine: {{.Id}} {{.Size}} octeti' | cut -c1-90
|
|
echo " -- preconditia retetei: haproxy -vv | grep -i 'running on openssl'"; docker run --rm haproxy:alpine haproxy -vv 2>&1 | grep -iE 'HAProxy version|running on openssl|built with openssl' | cut -c1-120 | sed 's/^/ /'
|
|
cat > haproxy/haproxy.cfg <<'EOF'
|
|
global
|
|
# EXACT fragmentul retetei (sectiunea global):
|
|
ssl-default-bind-curves X25519MLKEM768:X25519
|
|
ssl-default-bind-options ssl-min-ver TLSv1.3
|
|
|
|
defaults
|
|
mode http
|
|
timeout connect 5s
|
|
timeout client 10s
|
|
timeout server 10s
|
|
|
|
frontend proba
|
|
bind :8448 ssl crt /usr/local/etc/haproxy/certs/proba.pem
|
|
# EXACT fragmentul retetei (frontend-ul HTTPS):
|
|
http-response set-header Strict-Transport-Security "max-age=31536000"
|
|
http-request return status 200 content-type text/plain string "ok\n"
|
|
EOF
|
|
docker rm -f haproxy-reteta > /dev/null 2>&1
|
|
echo " -- verificarea retetei: haproxy -c -f"; docker run --rm -v "$D/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro" -v "$D/certs:/usr/local/etc/haproxy/certs:ro" haproxy:alpine haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg 2>&1 | tail -2 | sed 's/^/ /'
|
|
docker run -d --name haproxy-reteta -p 127.0.0.1:8448:8448 -v "$D/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro" -v "$D/certs:/usr/local/etc/haproxy/certs:ro" haproxy:alpine > /dev/null; sleep 3
|
|
docker ps --filter name=haproxy-reteta --format ' container: {{.Status}}'
|
|
sonde 8448 haproxy
|
|
docker logs haproxy-reteta 2>&1 | grep -iE 'alert|error|emerg' | head -3 | sed 's/^/ jurnal: /'
|
|
|
|
echo "== curatenie"; docker rm -f apache-reteta haproxy-reteta > /dev/null 2>&1; docker rmi httpd:alpine haproxy:alpine > /dev/null 2>&1 && echo " imaginile sterse"
|
|
cd /root && rm -rf "$D"; docker ps -a --format '{{.Names}}' | grep -cE 'apache-reteta|haproxy-reteta' | sed 's/^/ containere ramase: /'
|
|
echo "== RPC dupa: $(rpc)"
|
|
echo "retetele apache + haproxy: $((8 - rele)) din 8 sonde cum trebuie"
|
|
[ "$rele" = 0 ] && exit 0 || exit 1
|