ฉันอยากจะเริ่มต้นด้วยการบอกว่าฉันรู้ว่ามีหลายร้อยหัวข้อเกี่ยวกับเรื่องนี้ ซึ่งฉันเคยติดตามมาก่อนเพื่อให้สิ่งต่างๆ ดำเนินไปได้ด้วยดี ถึงกระนั้น การกำหนดค่านี้ซึ่งฉันทำงานมาหลายเดือน มันไม่ทำงานในสภาพแวดล้อมอื่น
ข้อกำหนดค่อนข้างตรงไปตรงมา นำผู้ใช้จากไซต์บนพอร์ต 80 ไปยังไซต์เดียวกันบนพอร์ต 443
เรามีไซต์ดังกล่าวโดยมี Apache อยู่ข้างหน้าและมีอินสแตนซ์ Tomcat สำหรับบริการจริงของเรา บริการเหล่านี้โฮสต์บนเครื่องที่แตกต่างกันสองเครื่อง เครื่องหนึ่งเสมือนบน GCP Compute Engine และ Baremetal อื่นๆ ที่เราจะเลิกใช้ในที่สุด
เรามีโดเมน example.com ซึ่งมีดัชนีของบริการต่างๆ ให้บริการแบบคงที่โดย Apache 2.4 เราสามารถเข้าถึงได้ด้วย Http และ Https จากดัชนีนี้ เราเปลี่ยนเส้นทางโดยใช้ proxy_mod ไปยัง app1, app2 และ app3 App2 และ App3 อยู่ในเซิร์ฟเวอร์ Baremetal เราใช้ DNS เพื่อนำผู้ใช้ไปยังโดเมนย่อย app2.example.com/app2 และ app3.example.com/app3 ฉันจะจัดการกับความซ้ำซ้อนในอนาคต เนื่องจากข้อจำกัดบางอย่างและข้อเท็จจริงที่ว่าแอป 2 และแอป 3 ยังไม่ออกสู่สาธารณะ เราจึงเข้าถึงได้ผ่าน Http เท่านั้น
App1 มีใบรับรอง SSL เดียวกันกับเซิร์ฟเวอร์ Apache เนื่องจากโฮสต์อยู่ใน VM เดียวกัน อีกครั้ง เราสามารถเข้าถึงทั้ง example.com และ example.com/app1 ด้วย Http และ Https
ตอนนี้ปัญหา:
ตามที่ระบุไว้ในชื่อเรื่อง ฉันมีปัญหากับข้อผิดพลาด 502s เมื่อใดก็ตามที่ฉันใช้การกำหนดค่าที่ฉันเคยลองใช้มาก่อน และนั่นทำงานในสภาพแวดล้อมอื่น การกำหนดค่าดังกล่าวเป็นดังนี้:
<VirtualHost *:80>
Redirect permanent / https://bar.com/
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#SSL stuff
SSLEngine On
SSLCertificateFile /file.pem
SSLCertificateKeyFile /file.key
SSLVerifyClient none
#Proxies
ProxyRequests Off
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPass /api/ https://localhost:8443/api/
ProxyPassReverse /api/ https://localhost:8443/api/
</VirtualHost>
bar.com เป็นสภาพแวดล้อมการทดสอบของฉัน ฉันใช้การกำหนดค่านี้และปรับแต่งดังต่อไปนี้สำหรับ example.com
<VirtualHost *:80>
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#SSL stuff
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLVerifyClient none
#Proxies
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN on
SSLProxyCheckPeerExpire on
Redirect permanent /app2 http://app2.example.com/app2
Redirect permanent /app3 http://app3.example.com/app3
<Location /app1>
ProxyPass https://localhost:8443/app1
ProxyPassReverse https://localhost:8443/app1
</Location>
</VirtualHost>
แต่สิ่งนี้นำไปสู่ข้อผิดพลาด 502 อีกครั้งฉันเข้าใจว่า vhost บนพอร์ต 80 นั้นใช้ได้ ฉันได้อ่านแม้กระทั่งว่าเป็นวิธีที่แนะนำ (ขณะนี้กำลังมองหาที่ฉันอ่านนี้) ฉันไม่ได้ลองใช้ mod_rewrite เพราะฉันเชื่อว่าข้อผิดพลาดไม่ใช่การกำหนดค่า แต่เป็นการผสมผสานระหว่าง SSL และ Proxy mods กับ GCP
ในด้าน GCP เรามีกฎไฟร์วอลล์พื้นฐาน และเนื่องจากเราสามารถเข้าถึง Https หรือ Http ด้วยการกำหนดค่าพื้นฐาน (นั่นคือ vhost ที่ฉันมีสำหรับ 443 แต่ฟังที่พอร์ต 80 โดยไม่มี vhost ตัวแรก) ฉันตั้งค่าโหลดบาลานเซอร์ แต่ส่วนใหญ่ใช้ประโยชน์จาก CDN ของ Google มีกลุ่มแบ็กเอนด์หนึ่งกลุ่มที่มี VM ซึ่งโฮสต์ Apache และ app1 สำหรับส่วนหน้า ฉันมีกฎสำหรับทั้งพอร์ต 80 และ 443 ซึ่งหมายความว่าฉันมีใบรับรอง SSL อีกใบสำหรับโหลดบาลานเซอร์โดยเฉพาะ ซึ่งจัดการโดย Google ฉันได้ตั้งค่าตัวตรวจสอบความสมบูรณ์สำหรับพอร์ตทั้งสอง ปิดใช้งานและเปิดใช้งานส่วนหน้าเพื่อให้แน่ใจว่าไม่ใช่สิ่งที่เกิดขึ้นกับพอร์ตเอง และจนถึงตอนนี้ดูเหมือนจะไม่เป็นปัญหา
ฉันยังคงคิดเกี่ยวกับระบบนิเวศ GCP ทั้งหมด ดังนั้นการคาดเดาที่ดีที่สุดของฉันคือฉันขาดบางอย่างในส่วนนั้นของสมการ เนื่องจากตัวกำหนดค่า Apache เองดูเหมือนจะใช้ได้สำหรับฉัน
สิ่งที่ฉันยังไม่ได้ลอง:
- ถอดบาลานเซอร์ออก ตั้งค่า VM โดยไม่มี IP แบบคงที่ แล้วลองที่นั่น
- ใช้ใบรับรองเดียวกันในส่วนหน้าและใน VM
- ปิดใช้งานพอร์ต 80 ในส่วนหน้าและตั้งค่า Apache เพื่อฟังพอร์ต 443 (ฉันไม่ต้องการทำเช่นนี้ เนื่องจากเป็นการแฮ็กมากกว่า ตัวกำหนดค่าเองจะทำงานราวกับว่ามันเป็น http)
ทำไมฉันยังไม่ได้ลองสิ่งนี้ อย่างที่คุณอาจเดาได้ การดูการกำหนดค่าในเซิร์ฟเวอร์ที่ใช้งานจริงไม่ใช่ตัวเลือกจริงๆ ฉันไม่สามารถเข้าถึง bar.com ได้ ดังนั้นฉันจึงไม่สามารถลองสิ่งต่างๆ ได้ตามต้องการ และการใช้ WSL แม้จะมีประโยชน์ แต่ก็ยังไม่ได้รับการพิสูจน์ว่าใกล้เคียงกับของจริง (นี่อาจเป็นสิ่งที่อยู่ในเครื่องของฉันด้วย .). เนื่องจากฉันทำงานได้ใกล้เที่ยงคืนเท่านั้น ฉันจึงไม่สามารถลองอะไรได้มากเท่าที่ฉันต้องการ
ไม่มีใครรู้ว่าสิ่งที่อาจทำให้เกิดข้อผิดพลาด 502?
หากคุณได้แนวคิดแต่ต้องการข้อมูลเพิ่มเติม โปรดดำเนินการต่อและถาม ฉันจะให้รายละเอียดมากที่สุดเท่าที่จะทำได้ แต่อย่าลืมว่าฉันยังคงเรียนรู้ว่า IaaS ทำงานอย่างไร
แก้ไข:
หลังจากนั้นไม่นาน ฉันสามารถทำงานนี้ต่อไปได้ ฉันใช้การกำหนดค่าเดียวกันกับรหัสบล็อกที่สองที่ฉันโพสต์ครั้งแรก
ในการตอบกลับ @John Hanley (โปรดทราบว่าฉันเปลี่ยนโดเมนและ IP เป็นค่า 'ทั่วไป'):
โดยใช้ ขด -l -v
ในโดเมน ฉันได้รับสิ่งต่อไปนี้:
* ลอง 1.1.1.1:80...
* ตั้งค่า TCP_NODELAY
* เชื่อมต่อกับ example.com (1.1.1.1) พอร์ต 80 (#0)
> เก็ท / HTTP/1.1
> โฮสต์:example.com
> User-Agent: curl/7.68.0
> ยอมรับ: */*
>
* ทำเครื่องหมายที่บันเดิลว่าไม่รองรับการใช้งานหลายอย่าง
< HTTP/1.1 502 เกตเวย์ไม่ถูกต้อง
< ประเภทเนื้อหา: text/html; ชุดอักขระ = UTF-8
< นโยบายผู้อ้างอิง: ไม่มีผู้อ้างอิง
< ความยาวเนื้อหา: 332
< วันที่: อา. 21 พ.ย. 2564 08:57:31 GMT
<
<html><หัวเรื่อง>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>ข้อผิดพลาดของเซิร์ฟเวอร์ 502</title>
</หัว>
<body text=#000000 bgcolor=#ffffff>
<h1>ข้อผิดพลาด: ข้อผิดพลาดของเซิร์ฟเวอร์</h1>
<h2>เซิร์ฟเวอร์พบข้อผิดพลาดชั่วคราวและไม่สามารถดำเนินการตามคำขอของคุณได้<p>โปรดลองอีกครั้งใน 30 วินาที</h2>
<h2></h2>
</body></html>
* การเชื่อมต่อ #0 ไปยังโฮสต์ example.com ไม่เสียหาย
และ
* ลอง 1.1.1.1:443...
* ตั้งค่า TCP_NODELAY
* เชื่อมต่อกับ example.com (1.1.1.1) พอร์ต 443 (#0)
* ALPN ให้บริการ h2
* ALPN ให้บริการ http/1.1
* ตั้งค่าตำแหน่งการตรวจสอบใบรับรองสำเร็จแล้ว:
* ไฟล์ CA: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (ออก), การจับมือ TLS, สวัสดีลูกค้า (1):
* TLSv1.3 (IN), การจับมือ TLS, สวัสดีเซิร์ฟเวอร์ (2):
* TLSv1.3 (IN), TLS handshake, ส่วนขยายที่เข้ารหัส (8):
* TLSv1.3 (IN), การจับมือ TLS, ใบรับรอง (11):
* TLSv1.3 (IN), TLS handshake, CERT ยืนยัน (15):
* TLSv1.3 (IN), การจับมือ TLS, เสร็จสิ้น (20):
* TLSv1.3 (ออก), TLS เปลี่ยนรหัส, เปลี่ยนข้อมูลจำเพาะของรหัส (1):
* TLSv1.3 (ออก), การจับมือ TLS, เสร็จสิ้น (20):
* การเชื่อมต่อ SSL โดยใช้ TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN เซิร์ฟเวอร์ที่ยอมรับให้ใช้ h2
* ใบรับรองเซิร์ฟเวอร์:
* หัวเรื่อง: CN=example.com
* วันที่เริ่มต้น: 4 ต.ค. 13:25:53 น. 2021 GMT
* วันหมดอายุ: 2 มกราคม 13:25:52 น. 2022 GMT
* subjectAltName: โฮสต์ "example.com" ตรงกับ "example.com" ของใบรับรอง
* ผู้ออก: C=US; O=Google Trust Services LLC; CN=จีทีเอส CA 1D4
* ใบรับรอง SSL ตรวจสอบตกลง
* การใช้ HTTP2 เซิร์ฟเวอร์รองรับการใช้งานหลายอย่าง
* เปลี่ยนสถานะการเชื่อมต่อ (ยืนยัน HTTP/2)
* การคัดลอกข้อมูล HTTP/2 ในสตรีมบัฟเฟอร์ไปยังบัฟเฟอร์การเชื่อมต่อหลังจากอัปเกรด: len=0
* ใช้ Stream ID: 1 (จัดการง่าย 0x55b622463820)
> เก็ท / HTTP/2
> โฮสต์: example.com
> user-agent: curl/7.68.0
> ยอมรับ: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* ID เซสชัน SSL เก่าเก่า กำลังลบออก
* เปลี่ยนสถานะการเชื่อมต่อ (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 502
< ประเภทเนื้อหา: text/html; ชุดอักขระ = UTF-8
< นโยบายผู้อ้างอิง: ไม่มีผู้อ้างอิง
< ความยาวเนื้อหา: 332
< date: อา. 21 พ.ย. 2021 08:57:56 GMT
< alt-svc: ชัดเจน
<
<html><หัวเรื่อง>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>ข้อผิดพลาดของเซิร์ฟเวอร์ 502</title>
</หัว>
<body text=#000000 bgcolor=#ffffff>
<h1>ข้อผิดพลาด: ข้อผิดพลาดของเซิร์ฟเวอร์</h1>
<h2>เซิร์ฟเวอร์พบข้อผิดพลาดชั่วคราวและไม่สามารถดำเนินการตามคำขอของคุณได้<p>โปรดลองอีกครั้งใน 30 วินาที</h2>
<h2></h2>
</body></html>
* การเชื่อมต่อ #0 ไปยังโฮสต์ example.com ไม่เสียหาย
ฉันคิดว่าคำขอ https ที่นี่ล้มเหลวเนื่องจากไม่มีส่วนหัว เนื่องจากฉันสามารถเข้าถึงไซต์ได้บนเบราว์เซอร์ของฉัน
จากนี้ ฉันเห็นว่าคำขอกำลังดำเนินการอย่างถูกต้องโดย LoadBalancer (หรืออย่างน้อยนั่นคือสิ่งที่ฉันเข้าใจ) แต่นั่น ขั้นตอนการเชื่อมต่อเปลี่ยนไป
ข้อความกำลังรบกวนฉันโดยเฉพาะเพราะมันใช้เวลาสองสามวินาทีที่นั่นราวกับกำลังรอการตอบกลับ
จาก apachectl -S
การกำหนดค่า VirtualHost:
*:80 vm-name.region.gcp-project.internal (/etc/apache2/sites-enabled/0080-default.conf:1)
*:443 example.com (/etc/apache2/sites-enabled/0443-secured.conf:6)
รูทเซิร์ฟเวอร์: "/etc/apache2"
รูทเอกสารหลัก: "/var/www/html"
ErrorLog หลัก: "/var/log/apache2/error.log"
Mutex watchdog-callback: using_defaults
Mutex ssl-เย็บเล่ม-รีเฟรช: using_defaults
Mutex การเย็บ ssl: using_defaults
พร็อกซี Mutex: using_defaults
Mutex ssl-cache: using_defaults
ค่าเริ่มต้นของ Mutex: dir="/var/run/apache2/" กลไก=ค่าเริ่มต้น
PidFile: "/var/run/apache2/apache2.pid"
กำหนด: DUMP_VHOSTS
กำหนด: DUMP_RUN_CFG
ผู้ใช้: name="www-data" id=33
กลุ่ม: name="www-data" id=33
อันนี้น่าสนใจ ในขณะที่ Vhost สำหรับพอร์ต 80 อ้างอิงถึงอินสแตนซ์ VM ของ GCP เอง VHost สำหรับพอร์ต 443 จะไม่อ้างอิง ฉันไม่แน่ใจว่าจะเอาอะไรจากสิ่งนี้ ... ฉันพยายามเข้าถึง VM โดยใช้ IP ภายนอกด้วย curl Http แสดงสถานะที่ถูกต้องสำหรับการเปลี่ยนเส้นทางถาวร ในขณะที่ HTTPs แสดงข้อผิดพลาดเนื่องจาก CN และ SAN ไม่ตรงกัน (ซึ่งเหมาะสมเนื่องจากใบรับรองมีไว้สำหรับโดเมน ไม่ใช่สำหรับ IP) ด้วยวิธีนี้ ฉันค่อนข้างมั่นใจว่าการเปลี่ยน VM IP เป็น Static IP ที่เรามีและการปล่อยให้ Apache ทำโหลดบาลานซ์จะตอบสนองความต้องการของฉัน แต่เรากำลังเพิ่ม VM อย่างน้อยหนึ่งตัวในอนาคตอันใกล้ ดังนั้นให้ทำที่ จุดนี้ดูเหมือน...แย่ ฉันยังคงคิดว่า CDN เป็นคุณสมบัติที่ดีและควรใช้มันในที่สุด
เกี่ยวกับโหลดบาลานเซอร์:
สิ่งนี้ค่อนข้างยากที่จะอธิบาย ดังนั้นฉันจะพยายามให้รายละเอียดแต่ตรงไปตรงมาที่สุดเท่าที่จะทำได้ (มีบางอย่างใน GCP CLI ที่จะแสดงการกำหนดค่านี้หรือไม่ ยังไม่ได้ตรวจสอบ CLI):
โหลดบาลานเซอร์เอง:
ส่วนหน้า:
มาตรการ |
ท่าเรือ |
ใบรับรอง |
นโยบาย SSL |
เอชทีทีพี |
80 |
- |
- |
HTTPS |
443 |
ตัวอย่างเช่น.com, GCP จัดการ |
ค่าเริ่มต้น |
แบ็กเอนด์
|โปรโตคอลจุดสิ้นสุด|ชื่อพอร์ต|หมดเวลา|ตรวจสุขภาพ|
|-|-|-|-|
|HTTP|http|30 วินาที| hc-1 (ล้มเหลว)|
|HTTP/2|https|30 วินาที| hc-2 (ผ่าน)|
*แบ็กเอนด์ทั้งสองชี้ไปที่กลุ่มเดียวกัน แต่คนละพอร์ต กลุ่มนี้มี VM เดียวของเรา
กฎโฮสต์/เส้นทาง:
ที่ไม่เสียหายทั้งหมดไปที่แบ็กเอนด์ HTTPขอให้ /* ไปที่แบ็กเอนด์ HTTPS
แม้ว่า hc-1 จะล้มเหลว แต่จริง ๆ แล้วแก้ไขไปที่หน้าหลัก แต่เมื่อฉันพยายามเข้าถึง app1 มันล้มเหลว (ซึ่งสมเหตุสมผลเนื่องจาก VHost นั้นไม่มีการแมปพร็อกซีกับ app1 เพื่อเริ่มต้น) ในทางกลับกัน hc-2 ผ่าน แต่เข้าถึงไซต์เป็น https://example.com
พ่นข้อผิดพลาด 502
สุดท้าย เกี่ยวกับวิธีเปิดใช้งานไซต์ ฉันใช้ a2ensite สำหรับ 0080-default.conf และ 0443-secured.conf
โอ้ และสัปดาห์นี้ไซต์ของเราใช้งานไม่ได้ ฉันคิดว่าเป็นวันอังคาร วันเดียวกับที่ Spotify มีปัญหา ฉันต้องเปิดโหลดบาลานเซอร์ ทำการเปลี่ยนแปลง บันทึก เลิกทำการเปลี่ยนแปลงดังกล่าว และบันทึกอีกครั้งเพื่อให้มันทำงานได้อีกครั้ง แต่ hc-1 ก็ล้มเหลวตั้งแต่นั้นมา
ฉันได้ลองใช้การเรียงสับเปลี่ยนการกำหนดค่าหลายอย่าง เริ่มจากอันที่ฉันรู้ว่าใช้ได้ผล (นั่นคือโหลดบาลานเซอร์เพียงอันเดียวสำหรับ HTTP และหนึ่ง VHost บนพอร์ต 80)