เคยสังเกตว่าเว็บไซต์บางแห่งแสดงไอคอนกุญแจสีแดงหรือแสดงคำเตือน "NET::ERR_CERT_INVALID" ทั้งที่เจ้าของเว็บยืนยันว่าได้ติดตั้ง SSL Certificate เรียบร้อยแล้ว สาเหตุที่พบบ่อยที่สุดคือปัญหา Incomplete Certificate Chain — นั่นคือการที่ Server ส่งใบรับรองให้ Browser ไม่ครบชุด บทความนี้จะอธิบายอย่างละเอียดว่า SSL Certificate Chain คืออะไร ทำงานอย่างไร และวิธีแก้ไขบน Web Server ทุกประเภท
SSL Certificate Chain คืออะไร
SSL Certificate Chain (หรือ Chain of Trust) คือลำดับชั้นของใบรับรองดิจิทัลที่เชื่อมกันเป็นสายตั้งแต่ใบรับรองของเว็บไซต์คุณ (Server Certificate) ไปจนถึงใบรับรองที่ Browser หรือ Operating System เชื่อถือโดยตรงที่เรียกว่า Root Certificate Authority (Root CA)
โครงสร้างมาตรฐานประกอบด้วย 3 ระดับ:
- Root CA — ใบรับรองระดับสูงสุด ถูกฝังไว้ใน Trust Store ของ OS/Browser ตั้งแต่โรงงาน (เช่น DigiCert, Comodo, GlobalSign, Let's Encrypt ISRG) เจ้าของ Root CA จะไม่ออกใบรับรองให้เว็บไซต์โดยตรง
- Intermediate CA — ใบรับรองระดับกลาง ได้รับการรับรองจาก Root CA และเป็นผู้ออก Server Certificate ให้เว็บไซต์ หากมีหลาย Intermediate ก็จะเรียงเป็นชั้นๆ ลงมา
- Server Certificate — ใบรับรองของเว็บไซต์คุณ ระบุ Domain Name, Public Key และ Validity Period
เมื่อ Browser เชื่อมต่อกับเว็บของคุณผ่าน HTTPS มันจะทำ Chain Validation โดยตรวจสอบว่า Server Certificate ออกโดย Intermediate ที่ถูกต้อง และ Intermediate นั้นถูกรับรองจาก Root CA ที่ Trust Store มีอยู่ ถ้าสายโซ่นี้ขาดหรือไม่ครบชุด Browser จะแสดงคำเตือน
ทำไม Root CA ไม่ออก Certificate โดยตรง
นี่เป็นคำถามที่หลายคนสงสัย เหตุผลหลักคือ การลดความเสี่ยงในระดับสูงสุด Root CA มี Private Key ที่มีมูลค่าสูงมาก ถ้า Root CA Private Key ถูกขโมย ใบรับรองที่ออกโดย CA นั้นทั้งหมดในโลกจะต้องถูก Revoke และอุปกรณ์ทุกชิ้นต้องอัปเดต Trust Store ทันที ซึ่งเป็นหายนะระดับอินเทอร์เน็ต
วิธีป้องกันคือ Root CA จะเก็บ Private Key ไว้ใน Hardware Security Module (HSM) ในห้องที่ปิดสนิทและไม่เชื่อมต่ออินเทอร์เน็ต (Air-gapped) จากนั้นออก Intermediate CA Certificate ให้ Intermediate CA เป็นผู้ออก Certificate ให้ลูกค้าแทน ถ้า Intermediate ถูก Compromise ก็ Revoke เฉพาะ Intermediate นั้นและออก Intermediate ใหม่ได้ทันที โดย Root CA ยังปลอดภัย
ข้อดีเพิ่มเติมของการใช้ Intermediate:
- แต่ละ Intermediate สามารถออก Certificate ให้ลูกค้าประเภทต่างๆ (DV, OV, EV) ได้โดยมี Policy เฉพาะ
- ลด Revocation Scope เมื่อเกิดปัญหา
- รองรับ Certificate Lifecycle Management ที่ยืดหยุ่นกว่า
- Root CA สามารถ Cross-Sign กับ Root อื่นเพื่อเพิ่ม Compatibility ได้
Incomplete Chain คืออะไร และเกิดขึ้นได้อย่างไร
Incomplete Chain (หรือ Broken Chain) เกิดขึ้นเมื่อ Web Server ส่งเฉพาะ Server Certificate เพียงใบเดียว ไปให้ Browser โดยไม่แนบ Intermediate Certificate ที่จำเป็นมาด้วย
สาเหตุที่พบบ่อย:
- ติดตั้ง Certificate ผิดไฟล์ — ใส่เฉพาะ
certificate.crtโดยไม่ได้ใส่ca_bundle.crtหรือintermediate.crt - ใช้ Self-signed Certificate — ออก Certificate เองโดยไม่ผ่าน CA จึงไม่มี Chain ที่ Browser เชื่อถือ
- ย้าย Hosting หรือ Migrate Server — ก็อปเฉพาะ
server.keyกับserver.crtโดยลืม CA Bundle - Automation Script ผิดพลาด — เช่น Let's Encrypt ที่ตั้งค่า Renew Hook ผิดทำให้ Chain ไม่ถูก Update
- Certificate Provider ส่งไฟล์มาไม่ครบ — บางผู้ให้บริการส่งมาแค่
.crtไม่มี CA Bundle มาด้วย
ผลกระทบที่เกิดขึ้น:
- Browser Desktop บางตัว (Chrome/Firefox) อาจยังแสดงกุญแจสีเขียวได้ชั่วคราว เพราะ Cache Intermediate ไว้จากเว็บอื่น
- Browser บน Mobile / Device ใหม่ที่ยังไม่เคย Cache จะแสดงคำเตือน Security
- API Client, cURL, Python Requests จะ Error เช่น
SSL: CERTIFICATE_VERIFY_FAILED - Google Search Console อาจรายงาน HTTPS Issue
- Monitoring Tool เช่น UptimeRobot, Pingdom จะแจ้ง SSL Error
วิธีตรวจสอบ Certificate Chain ด้วย OpenSSL
เครื่องมือที่ดีที่สุดในการตรวจ Chain คือ openssl ที่มีติดมากับ Linux/macOS ทุกเครื่อง:
ตรวจ Chain ที่ Server ส่งมา
openssl s_client -connect yourdomain.com:443 -showcerts
ผลลัพธ์ที่ดีจะเห็นหลาย -----BEGIN CERTIFICATE----- บล็อก (ปกติ 2-3 ใบ) ถ้าเห็นเพียงใบเดียว แสดงว่า Chain ไม่ครบ
ตรวจ Chain Depth ด้วย verbose
openssl s_client -connect yourdomain.com:443 -showcerts 2>&1 | grep -E "depth|verify"
ตัวอย่าง Output ที่ถูกต้อง (Chain ครบ):
depth=2 C = US, O = DigiCert Inc, CN = DigiCert Global Root CA verify return:1 depth=1 C = US, O = DigiCert Inc, CN = RapidSSL TLS RSA CA G1 verify return:1 depth=0 CN = yourdomain.com verify return:1
ตรวจสอบรายละเอียดของ Certificate
openssl x509 -in /path/to/certificate.crt -text -noout | grep -E "Issuer|Subject|Not After"
ตรวจสอบว่า Key ตรงกับ Certificate
# ผลลัพธ์ (md5) ต้องตรงกัน openssl x509 -noout -modulus -in certificate.crt | openssl md5 openssl rsa -noout -modulus -in private.key | openssl md5
| สถานะ Chain | สัญญาณที่พบ | ผลกระทบ | วิธีแก้ |
|---|---|---|---|
| Chain ครบถ้วน | depth=2 verify OK ครบทุกระดับ | กุญแจสีเขียว ทุก Client ผ่าน | ไม่จำเป็น |
| Incomplete Chain | depth=0 เท่านั้น, ขาด Intermediate | Mobile/API Error, คำเตือน Browser | เพิ่ม CA Bundle |
| Wrong Order | Chain มีครบแต่เรียงผิดลำดับ | บาง Client Error แบบสุ่ม | เรียง Server→Intermediate→Root |
| Expired Intermediate | verify error: certificate has expired | Error ทุก Client | อัปเดต CA Bundle |
วิธีแก้ Incomplete Chain บน Apache
Apache รองรับการกำหนด Chain ได้หลายวิธี วิธีที่แนะนำคือการสร้างไฟล์ fullchain.pem ที่รวม Certificate ทุกใบไว้ด้วยกัน:
วิธีที่ 1 — สร้าง fullchain.pem แล้วใช้ SSLCertificateFile เดียว
# รวม Server Certificate + Intermediate ไว้ในไฟล์เดียว (ลำดับสำคัญ)
cat certificate.crt intermediate.crt > /etc/ssl/certs/yourdomain.fullchain.pem
# ใน VirtualHost block
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/yourdomain.fullchain.pem
SSLCertificateKeyFile /etc/ssl/private/yourdomain.key
</VirtualHost>
วิธีที่ 2 — ใช้ SSLCertificateChainFile (Apache เก่า < 2.4.8)
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/ssl/certs/certificate.crt
SSLCertificateKeyFile /etc/ssl/private/private.key
SSLCertificateChainFile /etc/ssl/certs/ca_bundle.crt
</VirtualHost>
หลังแก้ไขให้ test config ก่อน reload เสมอ:
apachectl configtest # ต้องได้ "Syntax OK" systemctl reload apache2
วิธีแก้ Incomplete Chain บน Nginx
Nginx ใช้ไฟล์เดียวที่รวม Certificate ทุกใบ โดยไม่มี directive แยก Chain ออกมา ลำดับต้องเป็น Server Certificate ก่อน แล้วตามด้วย Intermediate:
# สร้าง fullchain.pem
cat yourdomain.crt intermediate.crt > /etc/nginx/ssl/yourdomain.fullchain.pem
# ใน server block
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/yourdomain.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
}
ทดสอบและ reload:
nginx -t # ต้องได้ "syntax is ok" และ "test is successful" systemctl reload nginx
วิธีแก้บน DirectAdmin Hosting (cPanel สไตล์)
สำหรับผู้ใช้ Shared Hosting ที่ใช้ DirectAdmin (เช่น บน AsiaGB Hosting) การจัดการ SSL ทำผ่าน Control Panel โดยไม่ต้องแตะ Command Line:
- เข้า DirectAdmin → SSL Certificates
- คลิก Paste a pre-generated certificate and key
- ในช่อง Certificate วาง Server Certificate (
-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----) - ในช่อง Private Key วาง Private Key
- เปิดใช้ Use a CA Cert แล้ววาง Intermediate / CA Bundle ในช่องที่ปรากฏ
- คลิก Save
หากผู้ให้บริการ SSL ส่งไฟล์ ca_bundle.crt มาให้ ให้ Copy เนื้อหาทั้งหมดไปวางในช่อง CA Cert ได้เลย ถ้าได้รับมาเป็น .zip ให้แตกไฟล์ก่อนและหา file ที่ชื่อ *ca-bundle*, *intermediate* หรือ *chain*
Let's Encrypt กับปัญหา Chain
Let's Encrypt ใช้ Certbot ในการออก Certificate โดย Certbot จะสร้างไฟล์หลายตัวใน /etc/letsencrypt/live/yourdomain/:
cert.pem— Server Certificate เพียงใบเดียวchain.pem— Intermediate Certificatefullchain.pem— รวม cert.pem + chain.pem (แนะนำให้ใช้นี่เสมอ)privkey.pem— Private Key
ข้อผิดพลาดที่พบบ่อยสุด คือการที่ Admin ใส่ cert.pem แทน fullchain.pem ใน SSL Config ทำให้ Intermediate ขาดหายไป
# ถูก — ใช้ fullchain.pem เสมอ ssl_certificate /etc/letsencrypt/live/yourdomain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain/privkey.pem; # ผิด — cert.pem ขาด Intermediate ssl_certificate /etc/letsencrypt/live/yourdomain/cert.pem;
ตรวจสอบว่า Auto-Renew ทำงานถูกต้อง:
certbot renew --dry-run
เคล็ดลับสำคัญ: หลังแก้ไข Certificate Chain บน Server แล้ว ควรทดสอบด้วย SSL Server Test ที่ ssl-checker.html หรือ openssl s_client -connect yourdomain.com:443 -showcerts 2>&1 | grep -c "BEGIN CERT" ตัวเลขที่ได้ควรเป็น 2 หรือ 3 (มากกว่า 1 แสดงว่า Intermediate ส่งมาด้วยแล้ว) อย่าทดสอบจาก Browser เครื่องที่เพิ่งใช้เว็บไซต์นั้นมาก่อน เพราะ Browser อาจ Cache Intermediate ไว้และแสดง Valid ทั้งที่จริงยังไม่ครบ
Certificate Chain กับ Performance: OCSP Stapling
เมื่อ Browser ตรวจสอบ Chain มันยังต้อง Revocation Check ด้วย ว่า Certificate ใดใบหนึ่งถูก Revoke ไปแล้วหรือไม่ โดยปกติ Browser จะส่ง Request ไปที่ OCSP Responder ของ CA ซึ่งเพิ่ม Latency ในการเชื่อมต่อครั้งแรก
OCSP Stapling คือการที่ Server ทำการ Query OCSP Responder ล่วงหน้าและ "แนบ" (Staple) คำตอบนั้นมาพร้อมกับ TLS Handshake Browser ไม่ต้องส่ง Request แยกออกไปเอง ทำให้การเชื่อมต่อเร็วขึ้นและ Privacy ดีขึ้น
# เปิด OCSP Stapling บน Nginx ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s;
# เปิด OCSP Stapling บน Apache SSLUseStapling On SSLStaplingCache shmcb:/tmp/stapling_cache(128000)
Chain ที่ครบถ้วนเป็นเงื่อนไขเบื้องต้นก่อนจะเปิด OCSP Stapling ได้ เพราะ Server ต้องการ Intermediate เพื่อรู้ว่าจะ Query OCSP Responder ที่ URL ใด
คำถามที่พบบ่อย (FAQ)
SSL Certificate Chain คืออะไร และทำไมต้องมี Intermediate CA
SSL Certificate Chain คือลำดับชั้นของใบรับรองที่เชื่อมจาก Server Certificate ผ่าน Intermediate CA หนึ่งตัวหรือมากกว่า ไปถึง Root CA ที่ Browser เชื่อถือ เหตุที่ต้องมี Intermediate CA เพราะ Root CA จะไม่ออกใบรับรองให้เว็บไซต์โดยตรง เพื่อป้องกันความเสี่ยงกรณี Root CA ถูก Compromise Intermediate CA ทำหน้าที่เป็นตัวกลางและ Browser จะตรวจสอบ Chain จนพบ Root CA ที่ Trust Store มีอยู่
Incomplete Chain คืออะไร และวิธีตรวจสอบ
Incomplete Chain คือการที่ Server ส่งเฉพาะ Server Certificate เปล่าๆ โดยไม่แนบ Intermediate Certificate มาด้วย ทำให้ Browser บางตัว (โดยเฉพาะบน Mobile) ไม่สามารถ Verify ได้ วิธีตรวจสอบคือรัน openssl s_client -connect yourdomain.com:443 -showcerts แล้วดูว่า Chain มีกี่ระดับ หรือใช้ SSL Server Test ที่ให้ผล Chain Status ทันที
วิธีแก้ Incomplete Chain บน Apache Nginx และ LiteSpeed แตกต่างกันอย่างไร
บน Apache ใช้ directive SSLCertificateChainFile ชี้ไปยังไฟล์ Intermediate หรือรวม Intermediate ต่อท้าย fullchain.pem แล้วใช้ SSLCertificateFile ชี้ไปที่ fullchain.pem บน Nginx ใช้ไฟล์เดียวที่รวม Server Cert + Intermediate ไว้ด้วยกัน กำหนดใน ssl_certificate บน LiteSpeed ตั้งค่าผ่าน Web Admin Console ใน SSL Certificate section โดยวางไฟล์ CA Bundle ในช่อง CA Certificate
Let's Encrypt มีปัญหา Chain หรือไม่ และ Cross-Signed Certificate คืออะไร
Let's Encrypt ออก Chain 2 แบบคือ Short Chain ผ่าน ISRG Root X1 (รองรับ Android 7.1+ ขึ้นไป) และ Long Chain ผ่าน DST Root CA X3 Cross-Signed ซึ่งรองรับ Android เก่ากว่าได้ หลังจาก DST Root CA X3 Expire ในปี 2021 เครื่อง Android เก่ามาก (ต่ำกว่า 7.1) จะไม่รองรับ Let's Encrypt อีก สำหรับเว็บที่ต้องการ Compatibility สูงสุด ควรใช้ SSL จาก Commercial CA เช่น GeoTrust หรือ DigiCert ที่มี Root ฝังใน Trust Store อุปกรณ์หลากหลาย
SSL Certificate ทุกประเภทที่ AsiaGB
DV OV EV Wildcard SSL เริ่มต้น 1,000 บาท/ปี พร้อม Installation Support
ดู SSL Certificate