Apache reverse proxy

Fórumok

Sziasztok!

 

Szükségem volna reverse proxy használatára. A proxy IIS szervereknek továbbítaná a kéréseket.

Az Apache konfigurációja eddig:

<VirtualHost *:80>
    ServerName www.xyz.hu
    ServerAlias xyz.hu www.xyz.hu
    Redirect "/" "https://www.xyz.hu/"
</VirtualHost>

<VirtualHost *:443>
    SSLEngine On

    SSLProxyEngine On
    SSLCertificateFile /etc/ssl/certs/www.xyz.hu.pem
    ServerName www.xyz.hu
    ServerAlias xyz.hu www.xyz.hu
    ProxyPass / https://192.168.111.100:443/
    ProxyPassReverse / https://192.168.111.100:443/
</VirtualHost>

A logfájlban a következő hibák vannak:

 pass request body failed to 192.168.111.100:443 (192.168.111.100)

 Error during SSL Handshake with remote server returned by /favicon.ico

Az IIS-en lévő pfx tanúsítványt konvertáltam a következőképpen:

.\openssl pkcs12 -in .\www.xyz.hu.pfx -out www.xyz.hu.pem -nodes 

Ez van a fenti útvonalon.

Hozzászólások

Biztos, hogy nem akarod terminálni az SSL-t Apache oldalon? Mert így most az SSL-t az IIS-n terminálod.

Nézz utána a ProxyPass és ProxyPassReverse paramétereknek. Mert a fenti felállás így nem jó.

Továbbá hiányzik a korrekt SSL kezeléshez még pár paraméter korrekt beállítása (SSLCertificateKeyFile, SSLCertificateChainFile)

Az a rinetd (vagy SSH-tunnel, stb.), ami nem foglalkozik tanúsítvánnyal; a http-proxy a végpontja az SSL/TLS kapcsolatnak (bár lehet, hogy ő maga is SSL/TLS kapcsolatot nyit az igazi szerverhez).
Akkor használhatja ugyanazt a cert-et, ha az mondjuk a *.gazlampa.hu nevre szól, és a proxy.gazlampa.hu továbbít a www.gazlampa.hu-ra. (És persze így a privátkulcson is boldogan megosztoznak.)

Nem értem a kérdésed: Mi miért lenne jobb? Az SSL terminálás az Apache-on?

Nekem az tűnik egyszerűbbnek, ha a reverse proxyn nem kellene foglalkoznom tanúsítvánnyal. Megoldható ez?

Ohh, itt kicsi fogalomzavart érzek. Egy reverse proxy az L6/L7 szinten működik.
Ha olyan kell, ami csak továbbítja a forgalmat, akkor neked L3/L4 szinten működő megoldás kell. Például: NAT, IP forwarding, routing. Az meg nem Apache, csak egy sima tűzfalszabály.

Ha nem titok, akkor mi az alapprobléma, amit meg kellene oldanod?

Mi miért lenne jobb? Az SSL terminálás az Apache-on?

Kihagyni az Apache-on az ssl konfigurálását. Igen, mintha az úgy működne, mint az ip szintű csomagtovábbítás. :)

Azt értem, hogy nekem nem (csak) port forwarding kell (az is, mivel egy ip-nk van, amit a router használ, a reverse proxynak is csak lokális címe van, oda továbbítani kell a http, https-re jövő csomagokat), hanem magasabb szinten kell kezelnem a problémát, ami a következő.

Van több domainünk, amelyek eddig mind saját külön ip-t használtak. A domaineket persze nem egy szerver szolgálja ki. Ez nagy hirtelen megváltozott egy időre, egy ip-nk van addig, amíg a Kifü át nem helyezi a szolgáltatását az új helyünkre. Hogy miért a hirtelenség, azt most hagyjuk, nem releváns.

Ha van egyszerűbb megoldás a reverse proxynál, nyitott vagyok arra is, meg arra is, hogy megértem, hogy hogyan valósíthatom meg a vázolt feladatot reverse proxy (akár Apache, akár Nginx) használatával.

Ne Apache-ba gondolkozzál hanem inkább HAPROXY-ban (Én ilyet használok), mert azzal simán meg tudod ezt csinálni (1 fix publikus IP, több domain különböző belső IP címeken és a HAPROXY végzi az irányítást a domain-nek alapján a belső IP címekre.)

SSL terminálás: ahhoz, hogy megfelelően működjőnk ez az egész, a programnak (HAPROXY) látnia kell a forgalomnak a tartalmát, mert ez alapján tudja eldönteni, hogy a bejövő kérés melyik belső weboldalra vonatkozik illetve hova kell irányítani a kérést. Ezért kell az, hogy a weboldalhoz tartozó tanúsítványt (priv+publikus kulcs) a HAPROXY-nak elérhetővé kell tenni.
Ha nincs tanúsítvány akkor nem tudja kibontani a HTTPS forgalmat és döntést hozni arról, hogy hova dobja át a kérést.
(weboldal tanúsítvány: az a tanúsítvány amin ahhoz szükséges, amin biztosítja a HTTPS megfelelő működését a külső ügyfél részére. Ez sok esetben különbözhet attól, ami a belső gépen szerepel mint tanúsítvány.)

Ne Apache-ba gondolkozzál hanem inkább HAPROXY-ban (Én ilyet használok), mert azzal simán meg tudod ezt csinálni (1 fix publikus IP, több domain különböző belső IP címeken és a HAPROXY végzi az irányítást a domain-nek alapján a belső IP címekre.)

Ezt most úgy írod, mintha Apache esetén ez lehetetlen lenne...

+ egy SSL-t termináló reverseproxy azért is kell, hogy legalább a ma már standardnak mondható OWASP TOP10 ellenőrzést/blokkolást meg tudja csinálni a forgalomban, ne törjék szanaszét 2 perc alatt a mögötte lévő dolgot.

Teljesen mindegy, de valamit tegyél elé. Direktbe a net-re nem "illik" kitenni semmilyen szolgáltatást már évek óta.

Egy rövid leírás hogy kb miért is kell és mire jó....

https://www.cloudflare.com/learning/cdn/glossary/reverse-proxy/

A tanúsítvány részét nem látom át rendesen. Nekem az tűnik egyszerűbbnek, ha a reverse proxyn nem kellene foglalkoznom tanúsítvánnyal. Megoldható ez?

Nem oldható meg. Ha Apache(SSL -> proxy) -> IIS(SSL -> weboldal) a működés, akkor két helyen is kell a tanúsítvánnyal foglalkoznod.

Ha nem akarod csak az Apache oldalán az SSL-t feloldani (rendesen beállítva, nem így), akkor kellene egy ProxyPreserveHost, mert az IIS nem fogja tudni, hogy milyen domain-t kellene kiszolgálnia, illetve nézz rá az Apache-ot futtató gépen például curl-el, hogy az IIS jól válaszol, ha igen, akkor szopj tovább a proxy beállításokkal, mert ha nem válaszol jól, akkor nem tudod megjavítani.

Szerkesztve: 2023. 07. 16., v – 20:59

Egyszer írtam valamit reverse-proxy ügyben, nem biztos, hogy még értem, de hátha elfér:


Az Apache httpd-t reverse-proxyként is használhatjuk, ez a konkrét
helyzettől függően igényel egyszerűbb vagy bonyolulabb beállításokat
a httpd.conf fájlban. (A nálunk eddig felmerült esetekben az alábbiak
használata elégségesnek bizonyult, a httpd dokumentációi még sokkal
több beállítási lehetőséget írnak le.)

Szükséges httpd modulok:
    egyszerűbb eset:
      LoadModule proxy_module         libexec64/apache2/mod_proxy.so
      LoadModule proxy_http_module    libexec64/apache2/mod_proxy_http.so

    ha HTML-átírásra is szükség van:
      LoadModule proxy_html_module    libexec64/apache2/mod_proxy_html.so
      LoadModule xml2enc_module       libexec64/apache2/mod_xml2enc.so

* A proxyzás legegyszerűbb esete: path-név(prefix) alapján továbbítunk,
  nincs módosítás:

    ProxyPass "/localpath/" "https://10.20.30.40/remotepath/"

  Ha https-sel továbbítunk, használjuk ezt a beállítást is:

    SSLProxyEngine on

* Összetettebb esetekben használjunk Location utasítást, amivel
  csoportosítjuk az összetartozó beállításokat

    
        ProxyPass        "https://10.20.30.40/remotepath/"
        ProxyPassReverse "https://10.20.30.40/remotepath/"
        ProxyPassReverse "/remotepath/"
        ProxyPassReverseCookiePath "/remotepath" "/localpath"
    

    az egyes utasítások jelentősége:

    ProxyPass: maga az átirányítás (itt csak a "hova" cimet kell megadni,
        a "honnan" rész a 'Location'-ban van megadva)

    ProxyPassReverse: a szerver-ről kliensre menő HTTP-válaszokban (Location,
        Content-Location, URI mezők) is végezzen értelemszerű átírást.
        A kísérletek szerint több is kellhet; a fenti példában
        egy teljes URL és egy path-prefix szerepel.

    ProxyPassReverseCookiePath: írjuk át a 'Set-Cookie' HTTP-mezőkben
        a 'Path' értékét

    ProxyPassReverseCookieDomain: írjuk át a 'Set-Cookie' HTTP-mezőkben
        a 'Domain' értékét (erre az opcióra eddig nem volt szükségünk)

* Még bonyolultabb az az eset, amikor a HTML-tartalom átírására is szükség van,
  vagyis a benne lévő path-neveket is meg kell változtatni. Ilyenkor a
  'mod_proxy_html' modult is hasznalni kell (lasd fentebb a LoadModule utasítást,
  és lentebb a fordítás).

     A modul használatához különféle ProxyHTMLLinks és ProxyHTMLEvents
     utasításokra van szükség, ezeket készen megtaláljuk egy gyári fájlban,
     ennek használata:

         Include "etc/apache2/extra/proxy-html.conf"

     A proxyzáshoz használt utasítások:

       
         ProxyPass         "http://10.129.11.42:8080/remotepath/"
         ProxyPassReverse  "http://10.129.11.42:8080/remotepath/"
         ProxyPassReverseCookiePath   "/remotepath"  "/localpath"
         ProxyHTMLEnable On
         ProxyHTMLExtended On
         ProxyHTMLDocType ""
         ProxyHTMLURLMap "/remotepath/" "/localpath/"
       

    Az egyes utasítások jelentősége:

         ProxyHTMLEnable: HTML-átírás engedélyezése

         ProxyHTMLExtended: JavaScript-ben (és CSS-ben) is végezzen átírást

         ProxyHTMLDocType: az átírás nem őrzi meg a DOCTYPE eredeti értékét,
            hanem az ebben az utasításban megadottat teszi a HTML elejére

         ProxyHTMLURLMap: a tulajdonképpeni átírást írja elő, több ilyet is
            használhatunk

  httpd-2.4 fordítása mod_proxy_html használatához:
    configure-nál használjuk ezeket az opciókat (is):
    --enable-proxy-html --enable-xml2enc
    utána a szokott módon végezzük el a 'make all'
    és 'make install' futtatását.

  Megjegyzések:
  * fordítási hiba esetén töröljük a forrást, és
    kezdjük 'tiszta lappal'; a 'make distclean' nem elég.
  * a modul függősége a 'libxml2' nevű komponens (is)

* Kifinomult JavaScriptes technológiák (vö: The HTML Hell Page)
  esetén ez sem elég, de még mindig használhatunk VirtualHost-ot,
  de ehhez további IP-cím vagy hostnév kell. Példa (fiktív adatokkal):

    
      SSLEngine On
      SSLCertificateFile    /usr/local/etc/ssl_keys/default.cert.pem
      SSLCertificateKeyFile /usr/local/etc/ssl_keys/default.key.pem
      ServerName special.proxy.server.hu
      
        ProxyPass         "http://10.129.11.223:10080/"
        ProxyPassReverse  "http://10.129.11.223:10080/"
      
    

   Itt a 'ServerName' a fontos rész, a klienst úgy kell beállítani
   (vö 'hosts'-file), hogy ezt az hostnevet a proxy-szerver IP-címére
   fordítsa át. Úgyszintén fontos, hogy az SSL-certificate lefedje az
   új nevet is (pl. Subject Alternative Name (SAN): *.proxy.server.hu).

   Fontos, hogy _ne_ az első VirtualHost legyen ez (ugyanis az első
   VirtualHost a 'default', tehát ha a kérésben beérkező 'Host' mező
   tartalma semelyik VirtualHost-beli 'SeverName'-mel nem egyezik meg,
   akkor az első  VirtualHost kapja meg a kérést).

Források:
  https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
  https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
  https://httpd.apache.org/docs/2.4/mod/mod_proxy_html.html
  https://httpd.apache.org/docs/2.4/vhosts/

Szerintem ha bizonytalan vagy még az Apache2 konfig írásában és kevés az idő, próbálkozz inkább nginx-szel. Kevésbé "meredek" a tanulási görbéje és egy elfogadható konfigot akár percek alatt össze is tudsz kattintgatni hozzá: https://www.digitalocean.com/community/tools/nginx#?

"If I had six hours to chop down a tree, I'd spend the first four hours sharpening the axe."

"If I had six hours to chop down a tree, I'd spend the first four hours sharpening the axe."

Köszönöm, közben sikerült is megoldanom vele. Még tesztelem, de úgy néz ki, jó lesz. Nem tudom, mennyire lett volna bonyolult Apache-csal összehozni, azért az a konfig sem egyszerű, amit ezen a felületen össze lehet kattintgatni. De legalább van ilyen és működik. :)

Elakadtam. Miért akar reverse proxy helyi mappájából dolgozni? Azt látom, hogy a root paraméter határozza meg, honnan akar dolgozni, de miért akar onnan, miért nem a proxy_pass-ban megadott címre továbbít minden kérést? Alap html oldalt hoz be csak a böngésző. Azt miért hozza be?

Bocs a késői válaszért. Szerintem csak vedd ki a pipát a Routing tab "root enable" lehetőségből. Ez törölni fogja a konfigból a "root                    /var/www/xyz.hu/public;" sort.
 

"If I had six hours to chop down a tree, I'd spend the first four hours sharpening the axe."

Azt, hogy "De miért kapja meg az egyszerű html oldalt, a többit miért nem" kristálygömb, de legalább konkrét  URL és logrészlet nélkül nehéz megmondani. Tippre nem akad bele a "servername" résznél megadott konfigdarabba. De nincs kristálygömböm.

Ugyanakkor felhívnám a figyelmedet arra, hogy ez, amit most csinálsz, és nem értesz, és nem működik, az pontosan azt hivatott csinálni, amit már az elején leszögeztél hogy nem akarsz.

Ellenben amit javasoltam, az azt.

Megoldva, működik sniproxyval az oldalaink elérése. Banális volt a hiba: nem volt engedélyezve a /etc/default/sniproxyban. A systemctl restart nem jelzett hibát, amíg futott az nginx, addig az válaszolt, miután leállítottam, akkor derült ki, hogy az sniproxy nem is fut...

Szerkesztve: 2023. 07. 18., k – 18:12

Kezdetnek nem volna rossz a *.pfx fájlból kiollózni(*) az EE-cert-et, és megnézni, hogy mire szól (CN, SAN). Ha mondjuk CN=csokigyar.hu, SAN=csokigyar.hu, *.csokigyar.hu, akkor az ip-címen alapuló elérés nemigen fog működni. (De néha maga a szerver is elvárja, hogy a nevén szólítsák (nem pedig IP-n), lásd Host, VirtualHost, SNI).

(*) vagy Firefox, 'openssl s_client -showcerts', stb.

Bármivel proxyzod is a kéréseket, ha szét kell váglogatni FQDN-enként a site-okat, akkor nem úszod meg az ssl config-ot az apache-on/nginx-en/squid-en/varnish-on(hitch-en), stb.

Mivel úgytűnik annyira nem vagy még profi ezeknek a konfigolásában, azt javasolnám:

1. használd az nginx-et, az sokkal elterjedtebb proxynak mint az apache2, jól is dokumentált.

2. állíts be egy site-ot az nginx-en, ssl-el, helyi kiszolgálóként, proxyzás nélkül, ha már jól működik és szépen bejön https://-el az oldal, akkor

3. az IIS-nek mondd meg, hogy szolgáljon ki http://-en is, ne csak https:// -en.

4. állítsd be a proxyt, http-n keresztül.

Az ssl-es backend szerverrel csak a nyűg van, ráadásul manapság nem túl gyakori, a http-s backend példájára ezer leirást találsz a neten...

Docker -> swag

Ezmod.

Every single person is a fool, insane, a failure, or a bad person to at least ten people.