Vaultwarden Reverse Proxy

Crumar

Lt. Commander
Registriert
Apr. 2009
Beiträge
1.079
Hi,

ich versuche aktuell vaultwarden einzurichten. Dazu habe ich es mit folgendem Script in Docker laufen:
Bash:
docker run -d \
    --name vaultwarden \
    -v /opt/vw-data/:/data/ \
    -p 127.0.0.01:4480:80 \
    -e DOMAIN="https://bw.xyz.de" \
    -e USE_SYSLOG="true" \
    -e ADMIN_TOKEN="ABC" \
    -e LOG_LEVEL="Info" \
    vaultwarden/server:latest
Mein Apache2 site sieht so aus:
Apache-Konfiguration:
<VirtualHost *:443>
    SSLEngine on
    ServerName bw.xyz.de

    SSLCertificateFile /etc/letsencrypt/live/xyz.de/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/xyz.de/privkey.pem

    ErrorLog ${APACHE_LOG_DIR}/bitwarden-error.log
    CustomLog ${APACHE_LOG_DIR}/bitwarden-access.log combined

    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/?(.*) "ws://127.0.0.1:3012/$1" [P,L]
    ProxyPass / http://127.0.0.1:4480/ Keepalive=On

    ProxyPreserveHost On
    ProxyRequests Off
    RequestHeader set X-Real-IP %{REMOTE_ADDR}s
</VirtualHost>

Wenn ich jetzt die Docker run abänder, dass dort '-p 4480:80' steht, ändert docker entsprechend meine iptables Firewall und ich kann mittels IP:4480 auf bitwarden drauf. In beiden Fällen funktioniert aber der reverse proxy nicht.
Ich habe an beiden Scripten viel versucht, bspw. ROCKET_TLS Variable auf verschiedene Arten zu leeren, damit vaultwarden kein TLS benutzt. Scheint aber ja eh nicht der Fall zu sein, da ich so ohne HTTPs drauf komme.
Bei Apache2 habe ich erst selbst eine Kombination aus anderen Reverse Proxy sites bzw. den LetsEncrypt SSL Options versucht. Danach das proxy example von vaultwarden, wobei ich da bei den Log Dirs die Slashes am Anfang entfernen musste und eben nur Certificate und CertificateKeyFile nutze.

Leider kriege ich immer einen 502 Timeout:
1641637784000.png
Code:
[Sat Jan 08 11:28:49.930401 2022] [proxy_http:error] [pid 22650] (104)Connection reset by peer: [client xyz] AH01102: error reading status line from remote server 127.0.0.1:4480
[Sat Jan 08 11:28:49.930512 2022] [proxy:error] [pid 22650] [client xyz] AH00898: Error reading from remote server returned by /
[Sat Jan 08 11:29:21.418120 2022] [proxy_http:error] [pid 22650] (104)Connection reset by peer: [client xyz] AH01102: error reading status line from remote server 127.0.0.1:4480, referer: https://bw.xyz.de/
[Sat Jan 08 11:29:52.906032 2022] [proxy_http:error] [pid 22651] (104)Connection reset by peer: [client xyz] AH01102: error reading status line from remote server 127.0.0.1:4480, referer: https://bw.xyz.de/
[Sat Jan 08 11:29:52.906091 2022] [proxy:error] [pid 22651] [client xyz] AH00898: Error reading from remote server returned by /favicon.ico, referer: https://bw.xyz.de/

Die Logs von Vaultwarden (docker logs vaultwarden) zeigen leider nur meine Versuche direkt über den Port an. Von den Reverse Proxy Versuchen ist nichts zu sehen.

Hat jemand noch einen Rat?

Vaultwarden selbst gibt bei Reverse Proxys relativ wenig Support.
 
Eigentlich gibt es da nicht viel zu beachten. Bei mir läuft vaultwarden direkt, also nicht via docker, auf port 8000. Die nginx config ist simpel:
Code:
  location / {
    proxy_pass http://localhost:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
  location /notifications/hub {
    proxy_pass http://localhost:3012;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }

  location /notifications/hub/negotiate {
    proxy_pass http://localhost:8000;
  }
  location /admin {
    return 503;
  }

Location /admin ist ein spezialfall und muss zu admin Zwecken aktiviert werden. Im normalbetrieb bleibt es jedoch aus.
Deiner Fehlermeldung nach bekommt der apache nichts verwertbares. Was gibt curl -v http://127.0.0.1:4480 auf dem Host direkt zurück?
Deine Rewrite Rule zum Websocket sieht mir falsch aus. Da fehlt IMHO das /notifications/hub. Zudem wird laut docker run der Port 3012 gar nicht exposed. Ist aber nicht das Problem hier

Edit: Hab im Dockerfile geschaut, 3012 wird exposed, das passt also
 
Zuletzt bearbeitet von einem Moderator:
Das mit den websockets hatte ich geändert nach einem github issue. Vorher war das notifications/hub drin wie im example aus dem repo.

1641641050226.png
 
Dein Problem ist also nicht der Apache bzw. dessen Config, sondern dass du via http://127.0.0.1:4480 nichts zurück bekommst. Weiß nicht, wie fit du darin bist, aber ich würde jetzt mit tcpdump weiter machen.. Sieht für mich so aus als kämen die ACKS nicht an. IPtables Problem vlt?

Du sagtest ja, dass es via externer ip geht. Mach doch mal zur Probe: curl -v http://extip:4480 auf dem host.
 
Das geht tatsächlich auch nicht, selber Fehler.
Browser geht.
1641641951285.png

Muss mal eben weg, schaue gleich wieder rein

Edit:
Also vaultwarden ist auf einem vServer.
Hab nen raspberry zuhause, bei dem kommt beim curl mit IP addresse sofort die Antwort, ohne Verzögerung.
(Warum vergesse ich immer curl? Ich versuch dauernd nur telnet)
 
telnet ist ja auch ok, dann aber ein GET / HTTP/1.1 \r\n Host:bla dahinter, sonst ist es nicht aussagekräftig.
Die iptables Regeln sehen eigentlich gut aus, insbesondere für localhost. Eigentlich sollte es so sein wie bei deinem Pi zuhause.
 
Tja, wo kann ich dann noch suchen?
1641644872508.png

nmap sieht jetzt auch nicht besonders aus, links vom host selbst, einmal local einmal public ip, rechts vom raspberry
Kann es sein, dass docker die Antwort zurück an localhost nicht routen kann?

Also tcpdump im docker Container geht ja nicht, hab das lang nicht mehr gemacht

Edit 1:
@foo_1337

kannst du damit was anfangen?
1641680283365.png

Edit 2:

Also wenn ich mit tcpdump auf dem docker0 interface monitore, dann sehe ich traffic wenns von extern kommt. von intern kommt nichts an

Edit 3:
Also es liegt an iptables. nachdem ich alle rules gelöscht und docker + container neugestartet hab gings. Danach mein firewall script und ebenfalls docker + container neustart -> wieder nicht
 
Zuletzt bearbeitet:
push

jemand noch eine Idee?

Danach funktioniert localhost nicht:
Bash:
/scripts/firewall.sh
systemctl restart docker
docker start vaultwarden

Danach funktioniert localhost:
Bash:
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
systemctl restart docker
docker start vaultwarden

Bash:
#!/bin/bash
IPT="/sbin/iptables"
IPT6="/sbin/ip6tables"
PUBIF="eth0"

$IPT -F
$IPT -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT6 -F
$IPT6 -X
$IPT6 -t mangle -F
$IPT6 -t mangle -X

$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
$IPT6 -A INPUT -i lo -j ACCEPT
$IPT6 -A OUTPUT -o lo -j ACCEPT

$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
$IPT6 -P INPUT DROP
$IPT6 -P OUTPUT DROP
$IPT6 -P FORWARD DROP

$IPT -A INPUT -i $PUBIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT6 -A INPUT -i $PUBIF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT6 -A OUTPUT -o $PUBIF -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

$IPT -A INPUT -i $PUBIF -p icmp -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p icmp -j ACCEPT
$IPT6 -A INPUT -i $PUBIF -p ipv6-icmp -j ACCEPT
$IPT6 -A OUTPUT -o $PUBIF -p ipv6-icmp -j ACCEPT

function b {
    $IPT -A INPUT -i $PUBIF -p $1 --destination-port $2 -j ACCEPT
    $IPT6 -A INPUT -i $PUBIF -p $1 --destination-port $2 -j ACCEPT
}

function u {
    b udp $1
}

function t {
    b tcp $1
}

t 22222       #SSH
t 80          #HTTP
t 443         #HTTPS
t 53          #DNS
u 53          #DNS
t 27015       #CSGO
u 27015       #CSGO

$IPT -A INPUT -i $PUBIF -j LOG
$IPT -A INPUT -i $PUBIF -j DROP
 
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
$IPT6 -P INPUT DROP
$IPT6 -P OUTPUT DROP
$IPT6 -P FORWARD DROP

^logge hier mal bitte alles mit, ggf gibt es dann mehr Details. Vlt kann ein Mod ja den Titel auf iptables ändern bzw. hinzufügen, damit es mehr/andere User anspricht. Bin leider nicht wirklich iptables erfahren.
 
Ich wusste jetzt nicht wie genau, habe also am Ende meiner firewall.sh folgendes hinzugefuegt:
$IPT -A INPUT -j LOG --log-prefix "Input Log:"
$IPT -A OUTPUT -j LOG --log-prefix "Output Log:"
$IPT -A FORWARD -j LOG --log-prefix "Forward Log:"

Dann, direkt nach dem Curl aufruf (wobei er da noch haengt)
1641752802354.png

Was mich wundert, ich finde nirgendso etwas zu 4480. Weder in iptables noch im log, nur docker interface 80

Gerade nochmal getestet mit den Defaults pro Chain:

INPUTOUTPUTFORWARDFunktioniert?
ACCEPTACCEPTACCEPTJa
ACCEPTACCEPTDROPJa
ACCEPTDROPDROPNein
DROPACCEPTDROPNein

An Forward liegt es also nicht, aber sowohl In als auch Out scheinen nicht zu reichen.

Es geht wenn ich folgendes manuell ausfuehre:
iptables -A INPUT -i docker0 -p tcp -j ACCEPT
iptables -A OUTPUT -o docker0 -p tcp -j ACCEPT

Es geht dann auch korrekt ueber den Reverse Proxy, wenn ich den Container nur an 127.0.0.1 publishe, aber nicht mehr aus dem Internet.
Jetzt ist die Frage wie ich das permanent einrichte und ob ich dadurch mehr offen hab, als ich sollte.
 
Zuletzt bearbeitet:
Zurück
Oben