Apache VirtualHost พร้อม mod-proxy และ SSL


28

ฉันกำลังพยายามตั้งค่าเซิร์ฟเวอร์ที่มีเว็บแอปพลิเคชั่นหลายตัวซึ่งทั้งหมดจะให้บริการผ่าน apache VirtualHost (apache ที่ทำงานบนเซิร์ฟเวอร์เดียวกัน) ข้อ จำกัด หลักของฉันคือแต่ละเว็บแอปพลิเคชันต้องใช้การเข้ารหัส SSL หลังจาก googling ซักพักหนึ่งและดูคำถามอื่น ๆ เกี่ยวกับ stackoverflow ฉันได้เขียนการกำหนดค่าต่อไปนี้สำหรับ VirtualHost:

<VirtualHost 1.2.3.4:443>
    ServerName host.example.org

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    SSLProxyEngine On
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / https://localhost:8443/
    ProxyPassReverse / https://localhost:8443/
</VirtualHost>

แม้ว่าhttps://host.example.org:8443จะสามารถเข้าถึงได้ แต่https://host.example.orgนั้นไม่สามารถทำได้ซึ่งขัดกับวัตถุประสงค์ของการกำหนดค่าโฮสต์เสมือนของฉัน Firefox บ่นว่าแม้ว่าจะเชื่อมต่อกับเซิร์ฟเวอร์สำเร็จ แต่การเชื่อมต่อก็ถูกขัดจังหวะ ฉันยังได้รับคำเตือนต่อไปนี้ใน error ของ apache:

proxy: no HTTP 0.9 request (with no host line) on incoming request and preserve host set forcing hostname to be host.example.org for uri 

บนเว็บแอปพลิเคชัน (เซิร์ฟเวอร์ Tomcat) บันทึกการเข้าถึงแสดงคำขอเข้าถึงที่ไม่ปกติ:

"?O^A^C / HTTP/1.1" 302

ต่อไปนี้เป็นคำขอการเข้าถึงที่ถูกต้องที่ฉันได้รับเมื่อฉันเชื่อมต่อโดยตรงกับhttps://host.example.org:8443 :

"GET / HTTP/1.1" 302

ในที่สุดฉันก็ควรพูดถึงว่าโฮสต์เสมือนทำงานได้อย่างสมบูรณ์แบบเมื่อฉันไม่ใช้ SSL

ฉันจะทำงานนี้ได้อย่างไร

คำตอบ:


34

ในที่สุดฉันก็พบวิธีที่จะทำให้มันใช้งานได้ ก่อนอื่นฉันลองใช้คำแนะนำของ Dave Cheney ดังนั้นฉันจึงติดตั้งใบรับรองอื่นสำหรับเซิร์ฟเวอร์ apache ที่เปลี่ยนเส้นทางไปยัง Tomcat ไม่ใช่พอร์ต SSL (ดังนั้นพร็อกซีก็เปลี่ยนเส้นทางไปที่http: // localhost: 8080 / ) น่าเสียดายที่มันใช้งานไม่ได้เหมือนในเว็บเบราว์เซอร์ https จึงเปลี่ยนเป็น http ทันทีเมื่อเชื่อมต่อ ดังนั้นฉันจึงกลับไปใช้https: // localhost: 8443 /และการสัมผัสขั้นสุดท้ายเพื่อให้มันทำงานได้คือการเพิ่ม SSLProxyEngine อีกครั้ง

นี่คือการกำหนดค่า VirtualHost ที่เป็นผลลัพธ์:

<VirtualHost 1.2.3.4:443>
    ServerName host.domain.org

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    SSLEngine on
    SSLProxyEngine On
    SSLCertificateFile /etc/apache2/ssl/certificate.crt
    SSLCertificateKeyFile /etc/apache2/ssl/certificate.key

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / https://localhost:8443/
    ProxyPassReverse / https://localhost:8443/
</VirtualHost>

1
หลีกเลี่ยงมันเกือบจะผิดเสมอไร้ประโยชน์และแบ่งเกือบตลอดเวลาProxyPreserveHost On ProxyPassReverseในฐานะที่เป็นบันทึกด้านข้างProxyRequests offเป็นค่าเริ่มต้นจึงซ้ำซ้อน
kubanczyk

เมื่อเราใช้ IP ภายนอกแทนlocalhostมันไม่ทำงาน
Chaminda Bandara

4

ลองกำหนดค่านี้

<VirtualHost 1.2.3.4:443>
    ServerName host.domain.org

    SSLEngine On
    # include other ssl options, like cert and key here

    ProxyRequests Off
    ProxyPreserveHost On

    <Location />
        ProxyPass http://localhost:8443/
    </Location>
</VirtualHost>

หากแอปพลิเคชันของคุณต้องการเข้าถึงข้อมูล SSL จากการเชื่อมต่อพร็อกซีคุณควรพิจารณาใช้ mod_proxy_ajp และตัวเชื่อมต่อ tomcat ajp1.3


ฉันจะสร้างใบรับรองด้วยการเข้ารหัสบนเซิร์ฟเวอร์ที่มีแอปพลิเคชันสำหรับ host.domain.org กำลังทำงานอยู่ ถ้าอย่างนั้นฉันต้องนำใบรับรองเดิมมาใช้บนพร็อกซีเซิร์ฟเวอร์อีกครั้งหรือไม่
Giox

2

แต่ถ้าเป้าหมายของคุณคือการใช้งานเว็บแอปพลิเคชั่นที่เปิดใช้งานหลาย SSL บนเซิร์ฟเวอร์เดียวกัน การเพิ่ม apache ไว้ด้านหน้าจะไม่ทำให้เกิดความสมดุลโดยใช้ config ข้างต้นคุณยังต้องใช้ load balancer หรือคุณสามารถใช้โมดูล proxy balancer ของ apache กับสิ่งต่อไปนี้:

ProxyRequests Off

<Proxy balancer://someapplication>
    BalancerMember http://127.0.0.1:18443 keepalive=on max=2 retry=30
    BalancerMember http://127.0.0.1:18444 keepalive=on max=2 retry=30
    BalancerMember http://127.0.0.1:18445 keepalive=on max=2 retry=30
</Proxy>


<VirtualHost 1.2.3.4:443>
    SSLEngine on
    SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile //path/to/key.pem
    SSLVerifyClient optional

    RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
    RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e

<Location />
    SetHandler balancer-manager
    Order allow,deny
    Allow from all
</Location>

ProxyPass / balancer://someapplication:443/
ProxyPassReverse / balancer://someapplication:443/
ProxyPreserveHost on

ขณะนี้ฉันไม่จำเป็นต้องใช้การปรับสมดุลการโหลด แต่อาจเป็นอันตรายในอนาคต ขอบคุณสำหรับความเข้าใจ
JMD

1

สิ่งที่ฉันไม่เข้าใจที่นี่คือเหตุผลที่คุณต้องมีการเชื่อมต่อ SSL จาก Apache ของคุณไปยังแอปพลิเคชันของคุณซึ่งดูเหมือนว่าจะอยู่ในเครื่องเดียวกัน ( http: // localhost: 8443 / )

ฉันเดาวิธีปกติในการตั้งค่าสิ่งต่าง ๆ เช่นนี้คือมี apache ที่ให้การเข้ารหัส SSL แก่ "ลูกค้า" ด้านข้างเช่นอินเทอร์เน็ตและมีการเชื่อมต่อที่ไม่ได้เข้ารหัสกับแอปพลิเคชัน นอกจากนี้ยังช่วยให้คุณมีอิสระมากขึ้นในการดีบักการตอบกลับแอปพลิเคชันของคุณ

อีกสิ่งหนึ่งที่ Dave Cheney กล่าวถึงคือการใช้ตัวเชื่อมต่อ tomcat ดั้งเดิมเพื่อให้มีการทำ load balance และคุณสมบัติอื่น ๆ


ฉันมีสองเหตุผลในการเลือกการตั้งค่าดังกล่าว สิ่งแรกคือเซิร์ฟเวอร์ Tomcat นั้นเปิดใช้งานแล้วใน SSL และฉันคิดว่ามันง่ายที่จะใช้ apache VirtualHost กับมัน อย่างที่สองคือผู้ให้บริการของแอปพลิเคชัน (JIRA) ให้แนวทางบางอย่างสำหรับการรวม apache ( atlassian.com/software/jira/docs/v3.13/apacheintegration.html ) และฉันใช้การกำหนดค่าของฉันโดยเพิ่มการสนับสนุน VirtualHost เดาว่าซับซ้อนกว่าที่ฉันคิดนอกจากทำให้มันทำงานได้ฉันอยากจะเข้าใจว่าปัญหาคืออะไร
JMD

0

คุณต้องการพร็อกซีกับบริการ HTTPS จริง ๆ หรือไม่ คุณอาจต้องการ proxy ไปยังบริการที่ไม่ใช่ ssl ใน localhost เช่น

ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/

การใช้ SSL เป็นสิ่งจำเป็นสำหรับฉัน ฉันยังทดสอบพร็อกซีโดยไม่ใช้ SSL เพื่อตรวจสอบและใช้งานได้ดี การสนับสนุน SSL เป็นปัญหาจริง
JMD

0

ก่อนอื่นฉันจะดูว่าคุณสามารถทำคำขอจาก localhost ถึง localhost: 8443 และดูว่าประสบความสำเร็จ (IE ทำ GET หรือ wget http: // localhost: 8443 )

ฉันไม่แน่ใจว่าทำไม havin ga ของคุณโฮสต์เสมือนกำลังฟังพอร์ต 443 จากนั้น proxying ไปยังโฮสต์ ssl อื่น

เหตุใดแอปพลิเคชันจึงไม่สามารถใช้ 443 โดยกำเนิดได้ หากคุณไม่สามารถเปลี่ยนแปลงได้คุณสามารถใช้ iptables เพื่อเปลี่ยนเส้นทางพอร์ต


เหตุผลคือฉันต้องการติดตั้งเว็บแอปพลิเคชันเพิ่มเติมบนเซิร์ฟเวอร์เดียวกันทั้งหมดโดยใช้ SSL และพวกเขาไม่สามารถฟังพอร์ต 443 ทั้งหมดดังนั้นฉันจึงใช้ VirtualHosts ที่ใช้ IP เพื่อให้ดูเหมือนว่าแต่ละเว็บแอปพลิเคชันโฮสต์อยู่บนเซิร์ฟเวอร์ของตัวเอง ฉันทดสอบคำสั่ง wget ต่อไปนี้และใช้งานได้ดี: wget localhost: 8443 - no-check-certificate
JMD

2
หมายเหตุ - เป็นเรื่องง่าย ๆ ที่จะเพิ่มที่อยู่ IP เพิ่มเติมให้กับเซิร์ฟเวอร์ของคุณและมีแอปพลิเคชั่นมากมายที่รับฟังพอร์ต 443 - ทั้งหมดอยู่ในที่อยู่ IP แยกต่างหาก
Brent

0

ตรวจสอบบันทึกข้อผิดพลาด SSL ของคุณและตรวจสอบให้แน่ใจว่าคุณไม่มีข้อผิดพลาดเกี่ยวกับการไม่สามารถตรวจสอบห่วงโซ่ใบรับรอง CA


หากมีข้อผิดพลาดในการตรวจสอบแน่นอนสิ่งที่จะเป็นทางออก
Javier Méndez
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.