บทความสี่หน้าในชุดนี้ลงเอยที่ข้อสรุปเดียวกันโดยไม่ได้นัดกัน
arp เส้นทางเชื่อไม่ได้ ต้องเข้ารหัสจากต้นทางถึงปลายทาง
dhcp DHCP ไม่มีการยืนยันตัวตนใด ๆ ทั้งสิ้น ไม่มีลายเซ็น ไม่มีรหัส
stp STP ไม่มีการยืนยันตัวตนใด ๆ ทั้งสิ้น ไม่มีลายเซ็น ไม่มีรหัส
tcp-udp ถ้าเลขเริ่มต้นเดาได้ ใครก็ตามที่เดาได้จะแทรกข้อมูลเข้าไปได้
ชั้นล่างเชื่อไม่ได้สักชั้น และทางออกที่ทุกหน้าชี้ไปคือเข้ารหัสตั้งแต่ต้นทางถึง ปลายทาง หน้านี้คือสิ่งนั้น
แต่ต้องเริ่มด้วยการแก้ความเข้าใจผิดที่ใหญ่ที่สุดก่อน HTTPS ไม่ได้แปลว่า ปลอดภัย มันแปลว่าอย่างหนึ่งที่เจาะจงมาก และการรู้ว่าอย่างไหน คือทั้งหมดของเรื่อง
ถ้ายังไม่เคยดู เริ่มตรงนี้
เว็บที่คุณกำลังอ่านอยู่นี้เปิดดูได้ทั้งการจับมือ
$ echo | openssl s_client -connect netkubelab.com:443 \
-servername netkubelab.com
Protocol : TLSv1.3
Cipher : AEAD-CHACHA20-POLY1305-SHA256
Verify return code: 0 (ok)
สามบรรทัดนี้คือสามคำตอบคนละเรื่องกัน เวอร์ชันที่ตกลงได้ · วิธีเข้ารหัสที่เลือก · และผลการตรวจใบรับรอง ซึ่งจะได้อธิบายทีละอัน
บรรทัดสุดท้ายคือบรรทัดที่คนอ่านผ่านบ่อยที่สุด และเป็นบรรทัดที่แบกทั้งเรื่องไว้
สัญญาสามข้อ และสิ่งที่ไม่ได้สัญญา
RFC 8446 ซึ่งเป็นมาตรฐานของ TLS 1.3 ระบุคุณสมบัติที่ให้ไว้สามข้อ ตรงไปตรงมา
"Authentication: The server side of the channel is always authenticated; the client side is optionally authenticated"
"Confidentiality: Data sent over the channel after establishment is only visible to the endpoints"
"Integrity: Data sent over the channel after establishment cannot be modified by attackers without detection"
อ่านให้ดีจะเห็นว่าทั้งสามข้อพูดถึงช่องทาง ไม่มีข้อไหนพูดถึงคนที่อยู่ปลายช่อง
ยืนยันตัวตนแปลว่าอะไรกันแน่ — แปลว่าเครื่องที่คุณกำลังคุยด้วยถือกุญแจส่วนตัว ที่คู่กับชื่อในใบรับรอง เท่านั้น ไม่ได้แปลว่าเจ้าของชื่อนั้นเป็นคนดี ไม่ได้แปลว่า เขาจะดูแลข้อมูลของคุณ และไม่ได้แปลว่าเว็บนั้นไม่ใช่เว็บหลอกลวง
เว็บหลอกลวงขอใบรับรองได้ปกติ และได้ง่ายมากด้วย เพราะสิ่งที่ต้องพิสูจน์คือคุมโดเมน นั้นอยู่จริง ไม่ใช่ว่าเป็นคนน่าเชื่อถือ แม่กุญแจในเบราว์เซอร์จึงบอกว่าคุณคุยกับ เจ้าของชื่อนี้จริง ไม่ได้บอกว่าชื่อนี้ควรเชื่อ
จับมือ
TLS 1.2 ต้องคุยกันสองรอบไปกลับก่อนส่งข้อมูลจริงได้ ซึ่งบวกกับการจับมือสามทางของ TCP ที่ต้องทำก่อนอีกหนึ่งรอบ กลายเป็นสามรอบก่อนได้ไบต์แรก
TLS 1.3 ตัดไปหนึ่งรอบ
วิธีที่ใช้ตรงไปตรงมามาก ให้ลูกข่ายเดาไปเลยว่าเซิร์ฟเวอร์น่าจะใช้กลุ่มกุญแจไหน แล้วส่งส่วนของตัวเองไปพร้อม ClientHello เลย ไม่ต้องรอถามก่อนว่ารองรับอะไรบ้าง
เดาถูกก็จบในรอบเดียว เดาผิดค่อยเสียเพิ่มอีกรอบ ซึ่งเกิดน้อยมากเพราะกลุ่มที่ใช้ กันจริงมีไม่กี่กลุ่ม
และของที่ถูกตัดทิ้งสำคัญพอ ๆ กับของที่เพิ่ม RFC ระบุว่า "Static RSA and Diffie-Hellman cipher suites have been removed" ซึ่งจะกลับมา เป็นหัวข้อตอนพูดถึง forward secrecy
อีกอย่างที่เปลี่ยนคือ "All handshake messages after the ServerHello are now encrypted" ข้อความจับมือทุกใบหลังจากนั้นถูกเข้ารหัสหมด รวมถึงใบรับรองด้วย ซึ่งใน TLS 1.2 ยังส่งแบบโล่ง
ประโยคนี้มีผลตามมาที่จะได้เห็นในหัวข้อ SNI — สิ่งที่อยู่ก่อน ServerHello ยังโล่งอยู่
ALPN — HTTP/2 ถูกเลือกตั้งแต่ตอนจับมือ
บทความ HTTP บอกว่า HTTP/2 กับ HTTP/1.1 ต้องตกลงกันก่อนใช้ การตกลงนั้นเกิดขึ้นข้างในการจับมือ TLS นี่เอง ทดสอบได้
request ['h2', 'http/1.1'] -> h2
request ['http/1.1'] -> http/1.1
ลูกข่ายบอกรายการที่พูดได้ไปตอนจับมือ เซิร์ฟเวอร์เลือกมาหนึ่งอัน จบไปพร้อมกับ การตั้งช่องทาง ไม่ต้องเสียรอบเพิ่มเพื่อถามว่าพูด HTTP เวอร์ชันไหนได้บ้าง
โซ่ใบรับรอง
เว็บนี้ส่งใบรับรองมาสามใบ ดูได้ตรง ๆ
subject=CN=netkubelab.com
issuer= C=US, O=Google Trust Services, CN=WE1
subject=C=US, O=Google Trust Services, CN=WE1
issuer= C=US, O=Google Trust Services LLC, CN=GTS Root R4
subject=C=US, O=Google Trust Services LLC, CN=GTS Root R4
issuer= C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
สังเกตว่า issuer ของใบบน เท่ากับ subject ของใบล่างเสมอ RFC 5280 เรียกการต่อ แบบนี้ว่า name chaining และอธิบายว่าทำโดย "matching the issuer distinguished name in one certificate with the subject name in a CA certificate"
ทำไมต้องสามใบ
ใบปลายคือใบเดียวที่ถือกุญแจส่วนตัวที่ใช้จริงในการจับมือ ส่วนอีกสองใบมีไว้พาไป ถึงรากที่เครื่องเชื่ออยู่แล้ว
เหตุผลที่ต้องมีใบกลางคั่นคือ รากมีค่าเกินกว่าจะเอามาใช้งานทุกวัน กุญแจส่วนตัว ของรากถูกเก็บออฟไลน์ในที่ที่เข้าถึงยากมาก ถ้าเอามาเซ็นใบให้ทุกเว็บโดยตรง ก็ต้อง เอาออกมาใช้ตลอดเวลา
ใบกลางจึงทำหน้าที่แทน และถ้าใบกลางหลุด ก็เพิกถอนใบกลางใบเดียวโดยที่รากยังอยู่
และมีรายละเอียดที่น่าสนใจในใบที่สาม GTS Root R4 ที่ดูเหมือนราก ตัวมันเอง ก็ถูกเซ็นโดย GlobalSign Root CA อีกที นี่คือการเซ็นไขว้ ทำไว้เพื่อให้เครื่องเก่า ที่ยังไม่รู้จักรากใหม่ ไล่ต่อขึ้นไปหารากเก่าที่รู้จักได้
สิ่งที่ต้องเข้าใจคือรากที่เชื่อจริง ๆ ไม่ได้มากับโซ่ มันอยู่ในเครื่องคุณอยู่ ก่อนแล้ว โซ่ที่ส่งมามีหน้าที่พาไปถึงมันเท่านั้น
การตรวจชื่อ คือจุดที่ความปลอดภัยอยู่จริง
โซ่ที่ถูกต้องพิสูจน์ได้แค่ว่า ใบนี้ออกโดย CA ที่เครื่องเชื่อ เท่านั้น
มันไม่ได้พิสูจน์เลยว่าเป็นใบของเว็บที่คุณตั้งใจจะไป ถ้าหยุดแค่ตรงนี้ ผู้โจมตีที่มี ใบรับรองถูกต้องของโดเมนตัวเอง จะเอามาใช้แทนเว็บไหนก็ได้
ขั้นที่ปิดช่องนั้นคือการเทียบชื่อ RFC 6125 ให้กฎไว้ว่าลูกข่ายต้อง "check each of its reference identifiers against the presented identifiers for the purpose of finding a match" คือเทียบชื่อที่ผู้ใช้ตั้งใจจะไป กับชื่อที่อยู่ ในใบ
ใบของเว็บนี้มีชื่ออยู่สองที่
Subject CN netkubelab.com
SAN DNS netkubelab.com
และมีแค่ช่องล่างที่ใช้ได้ RFC 6125 ระบุว่าลูกข่าย "MUST NOT seek a match for a reference identifier of CN-ID if the presented identifiers include a DNS-ID" มี SAN เมื่อไร ให้ลืม CN ไปเลย
เหตุผลคือ CN เป็นช่องข้อความทั่วไปที่ออกแบบมาสำหรับชื่อคน ไม่ได้ออกแบบมาสำหรับ ชื่อโดเมน และมีได้ค่าเดียว ส่วน SAN เป็นช่องที่ทำมาเพื่อการนี้โดยเฉพาะ และใส่ได้ หลายชื่อ
ใบของเว็บนี้มีชื่อเดียวใน SAN ซึ่งแปลว่า www.netkubelab.com ต้องเป็นใบคนละใบ และมันเป็นอย่างนั้นจริง ซึ่งพาไปหัวข้อถัดไป
รากของความเชื่อใจอยู่ที่ไหน
คำถามที่ควรถามคือแล้วเครื่องรู้ได้อย่างไรว่าจะเชื่อรากไหน คำตอบคือมีรายชื่อติดมา กับระบบปฏิบัติการอยู่แล้ว และนับได้
$ security find-certificate -a \
/System/Library/Keychains/SystemRootCertificates.keychain \
| grep -c labl
160
หนึ่งร้อยหกสิบองค์กร ที่เครื่องนี้เชื่อไว้ล่วงหน้าโดยที่เจ้าของเครื่องไม่เคย เลือกเอง
และข้อเท็จจริงที่ต้องยอมรับคือ รากตัวใดตัวหนึ่งใน 160 นั้น ออกใบให้ชื่อ netkubelab.com ได้ทั้งหมด ไม่ต้องขออนุญาตเจ้าของโดเมน ไม่ต้องบอกใคร และ เบราว์เซอร์จะเชื่อใบนั้นเหมือนใบจริงทุกประการ
นี่คือรูปแบบความเชื่อใจที่แท้จริงของ TLS ไม่ใช่ความเชื่อใจต่อเว็บที่เข้า แต่เป็น ความเชื่อใจต่อรายชื่อในเครื่อง และความแข็งแรงของทั้งระบบเท่ากับความแข็งแรงของ สมาชิกที่อ่อนแอที่สุดในรายชื่อนั้น
Certificate Transparency — ทางแก้ที่ไม่ได้ลดจำนวนราก
ทางแก้ที่เลือกใช้ไม่ใช่การตัดรากออก แต่คือ ทำให้ใบทุกใบที่ออกมาถูกมองเห็นได้
RFC 9162 อธิบายเป้าหมายไว้ว่า "Certificate Transparency aims to mitigate the problem of misissued certificates by providing append-only logs of issued certificates"
และประโยคที่สำคัญที่สุดคือประโยคที่บอกว่ามันไม่ได้ทำอะไร — "The logs do not themselves prevent misissuance, but they ensure that interested parties (particularly those named in certificates) can detect such misissuance"
ป้องกันไม่ได้ แต่ซ่อนไม่ได้ ใครออกใบให้ชื่อของคุณ ใบนั้นต้องไปโผล่ในบันทึก สาธารณะ ไม่งั้นเบราว์เซอร์ไม่ยอมรับ คุณจึงเฝ้าดูเองได้ว่ามีใครออกใบให้โดเมนของคุณ โดยที่คุณไม่ได้ขอ
บันทึกนั้นเป็นแบบเพิ่มได้อย่างเดียว ลบไม่ได้ ใช้ Merkle Tree ซึ่ง RFC ระบุว่าทำให้ "efficiently prove that any particular instance of the log is a superset of any particular previous instance" คือพิสูจน์ได้ว่าไม่มีใครย้อนไปลบของเก่าออก
SNI — ชื่อที่ยังโล่งอยู่
RFC 6066 อธิบายปัญหาที่ SNI แก้ไว้ว่า "TLS does not provide a mechanism for a client to tell a server the name of the server it is contacting" ในตอนที่ "servers host multiple 'virtual' servers at a single underlying network address"
เซิร์ฟเวอร์ตัวเดียวถือเว็บหลายเว็บ พอมีคนต่อเข้ามา มันต้องส่งใบรับรองก่อน แต่จะรู้ได้อย่างไรว่าจะส่งใบของเว็บไหน ในเมื่อยังไม่ได้คุยกัน
ทางแก้คือให้ลูกข่ายบอกชื่อไปตั้งแต่ ClientHello และทดสอบได้ตรง ๆ ด้วยการยิงเข้า เลขที่อยู่เดียวกัน แล้วเปลี่ยนแค่ชื่อที่ส่งไป
same IP 104.21.35.137
servername netkubelab.com -> cert CN=netkubelab.com
servername www.netkubelab.com -> cert CN=www.netkubelab.com
ปลายทางเดียวกันทุกอย่าง ต่างกันแค่ฟิลด์เดียว แล้วได้ใบรับรองคนละใบ
และตรงนี้คือช่องว่างที่ยังเปิดอยู่ ฟิลด์นั้นอยู่ใน ClientHello ซึ่งมาก่อน ServerHello ส่วน RFC 8446 บอกว่าที่ถูกเข้ารหัสคือข้อความหลังจาก ServerHello
รวมสองข้อแล้วได้ข้อสรุปว่า ชื่อเว็บที่คุณกำลังจะไปเดินทางแบบโล่ง ใครที่เห็น ทราฟฟิกอ่านได้หมดว่าคุณไปเว็บอะไร แม้จะอ่านเนื้อหาไม่ได้สักไบต์
นี่ไม่ใช่ความผิดพลาด มันเป็นผลที่หลีกไม่พ้นของลำดับ ต้องบอกชื่อก่อนถึงจะได้ใบ ต้องได้ใบก่อนถึงจะตั้งการเข้ารหัสได้ ทางแก้ที่กำลังทำกันคือหาวิธีเข้ารหัสฟิลด์นี้ ด้วยกุญแจที่ได้มาคนละทาง ซึ่งยังไม่แพร่หลาย
forward secrecy
สมมติมีคนเก็บทราฟฟิกที่เข้ารหัสแล้วของคุณไว้ทั้งหมดตั้งแต่วันนี้ อ่านไม่ออกสักไบต์ แล้วผ่านไปหลายปี เขาได้กุญแจส่วนตัวของเซิร์ฟเวอร์มา
แบบเก่าเขาถอดรหัสของที่เก็บไว้ได้ทั้งหมด ย้อนหลังทุกเซสชัน เพราะกุญแจของแต่ละ เซสชันถูกส่งไปโดยเข้ารหัสด้วยกุญแจสาธารณะในใบรับรอง มีกุญแจส่วนตัวก็แกะออกได้หมด
TLS 1.3 ทำไม่ได้ เพราะกุญแจของเซสชันไม่ได้มาจากกุญแจในใบรับรองเลย มันถูกสร้าง ขึ้นใหม่ทุกครั้งจากเลขสุ่มที่ทั้งสองฝั่งช่วยกันคิด แล้วทิ้งไปเมื่อจบเซสชัน
กุญแจส่วนตัวในใบรับรองมีหน้าที่เดียวคือ พิสูจน์ว่าเป็นเจ้าของชื่อจริง ไม่ได้ มีส่วนในการสร้างกุญแจที่ใช้เข้ารหัสข้อมูล
และ RFC 8446 ไม่ได้แค่แนะนำ แต่ถอดทางเลือกเก่าออกทั้งหมด — "all public-key based key exchange mechanisms now provide forward secrecy" เลือกทำแบบเก่าไม่ได้อีกแล้ว
การเพิกถอน — ส่วนที่ยังไม่เรียบร้อย
ถ้ากุญแจส่วนตัวของใบไหนหลุด ต้องมีวิธีบอกโลกว่าใบนั้นใช้ไม่ได้แล้ว และนี่คือส่วน ที่ระบบทำได้ไม่ดีมาตลอด
วิธีดั้งเดิมคือให้ CA ประกาศรายการใบที่ถูกเพิกถอน แล้วให้ลูกข่ายไปโหลดมาตรวจ ปัญหาคือรายการยาวมาก และถ้าโหลดไม่ได้ ลูกข่ายส่วนใหญ่เลือกที่จะปล่อยผ่าน เพราะทางเลือกอีกทางคือทำให้เว็บเปิดไม่ได้ทั้งอินเทอร์เน็ตเวลาเซิร์ฟเวอร์ตรวจล่ม
ผลคือกลไกที่มีไว้กันของหลุด กลับเป็นกลไกที่ถูกข้ามบ่อยที่สุด
ทางออกที่ใช้กันจริงในวันนี้ไม่ใช่การซ่อมการเพิกถอน แต่คือ ทำให้ใบอายุสั้นจน ไม่ต้องเพิกถอน ใบของเว็บนี้เป็นตัวอย่าง
notBefore 2026-08-29
notAfter 2026-11-27
lifetime 90 days
เก้าสิบวัน แปลว่าถ้ากุญแจหลุดวันนี้ ความเสียหายมีเพดานอยู่ที่เก้าสิบวัน โดยไม่ต้อง พึ่งกลไกใดเลย
และนี่คือเหตุผลที่การต่ออายุใบต้องเป็นงานอัตโนมัติ ใบที่อายุสั้นและต่ออายุด้วย มือคือใบที่จะหมดอายุตอนตีสามของวันหยุด
สิ่งที่ TLS ไม่ได้ปกป้อง
รวมทุกอย่างที่ผ่านมาแล้วแยกให้ชัดว่าอะไรถูกปิดและอะไรไม่
ถูกปิด — เส้นทางใน URL ส่วนหัว HTTP ทั้งหมด คุกกี้ โทเคน เนื้อหาที่ส่งและรับ และรหัสสถานะที่ตอบกลับมา ทั้งหมดนี้อยู่หลังการเข้ารหัส
ยังมองเห็น — เลขที่อยู่ปลายทาง ชื่อเว็บใน SNI ขนาดของแต่ละแพ็กเก็ต จังหวะเวลา จำนวนการเชื่อมต่อ ระยะเวลา และคำถาม DNS ถ้าไม่ได้ใช้ DoH
คอลัมน์ขวาพอสำหรับบอกได้เยอะกว่าที่คนคิด ว่าคุณเข้าเว็บอะไร ตอนไหน นานแค่ไหน และดูหน้าใหญ่หรือหน้าเล็ก ซึ่งบางกรณีเดาได้ถึงระดับว่าเป็นหน้าไหน จากขนาดอย่างเดียว
TLS ปิดเนื้อหา ไม่ได้ปิดว่าคุณคุยกับใคร สองอย่างนี้คนละเรื่องกัน และการสับสน ระหว่างสองอย่างนี้คือที่มาของความมั่นใจเกินจริงจำนวนมาก
เมื่อมันโกหก
"มีแม่กุญแจแปลว่าเว็บนี้ปลอดภัย" แม่กุญแจบอกว่าคุณคุยกับเจ้าของชื่อนี้จริง และไม่มีใครแก้ระหว่างทางได้ ไม่ได้บอกอะไรเลยว่าเจ้าของชื่อนี้เป็นใคร ตั้งใจอะไร หรือทำอะไรกับข้อมูลของคุณต่อ
"ใบรับรองแพงกว่าปลอดภัยกว่า" การเข้ารหัสเหมือนกันทุกประการ ต่างกันที่กระบวนการ ตรวจก่อนออกใบว่าเข้มแค่ไหน ซึ่งเป็นเรื่องของการยืนยันว่าองค์กรมีตัวตนจริง ไม่ได้ทำให้ช่องทางแข็งแรงขึ้นแม้แต่นิดเดียว
"HTTPS แล้วไม่ต้องกังวลเรื่องความเป็นส่วนตัว" ชื่อเว็บยังเดินทางแบบโล่งใน SNI และคำถาม DNS ก็เช่นกันถ้าไม่ได้ใช้ DoH คนที่เห็นทราฟฟิกยังรู้ว่าคุณไปที่ไหนบ้าง
"ใบหมดอายุแล้วยังใช้ต่อได้ ก็แค่กดข้าม" การกดข้ามคือการยกเลิกการตรวจชื่อทั้ง ขั้นตอน ซึ่งเป็นขั้นตอนเดียวที่ทำให้ TLS มีความหมาย เหลือแค่การเข้ารหัสกับใครก็ไม่รู้
"เข้ารหัสแล้วปลอดภัยจากทุกอย่าง" ปลอดภัยจากคนกลางเท่านั้น ปลายทั้งสองข้างยังเป็น จุดอ่อนเหมือนเดิม เครื่องที่ติดมัลแวร์อ่านข้อมูลได้ก่อนเข้ารหัสและหลังถอดรหัสอยู่ดี
ตัวอย่างจริงจากงานจริง
กรณีที่ 1 — เว็บใช้ได้ปกติ แล้วอยู่ ๆ ทุกคนเปิดไม่ได้พร้อมกัน
ไม่ได้แก้อะไรเลย แต่เช้าวันหนึ่งทุกเบราว์เซอร์ขึ้นเตือนพร้อมกันหมด
อ่านอย่างไร อาการพร้อมกันทุกเครื่องโดยไม่มีใครแก้อะไร คือลายเซ็นของเวลา ไม่ใช่ของการตั้งค่า ดูวันหมดอายุก่อนอย่างอื่น
$ echo | openssl s_client -connect example.com:443 \
-servername example.com 2>/dev/null \
| openssl x509 -noout -dates
notBefore=Aug 29 01:40:33 2026 GMT
notAfter=Nov 27 02:40:27 2026 GMT
ถ้า notAfter ผ่านไปแล้ว นั่นคือคำตอบทั้งหมด และมักแปลว่าการต่ออายุอัตโนมัติหยุด ทำงานมาสักพักแล้วโดยไม่มีใครสังเกต
สิ่งที่ยังไม่ได้พิสูจน์ เรารู้ว่าใบหมดอายุ แต่ยังไม่รู้ว่าทำไมการต่ออายุถึงไม่ ทำงาน ให้ดูล็อกของตัวต่ออายุย้อนหลังไปถึงครั้งสุดท้ายที่สำเร็จ
กรณีที่ 2 — เปิดด้วยชื่อหนึ่งได้ อีกชื่อหนึ่งไม่ได้
www.example.com เปิดได้ แต่ example.com ขึ้นเตือนว่าใบไม่ตรงกับชื่อ
อ่านอย่างไร ดูว่าในใบมีชื่ออะไรอยู่บ้าง
$ echo | openssl s_client -connect example.com:443 \
-servername example.com 2>/dev/null \
| openssl x509 -noout -text | grep -A1 'Subject Alternative Name'
X509v3 Subject Alternative Name:
DNS:www.example.com
ใน SAN มีแค่ www.example.com ส่วนชื่อที่ผู้ใช้พิมพ์คือ example.com ซึ่งไม่ตรง เบราว์เซอร์จึงปฏิเสธตามที่ RFC 6125 กำหนด
สังเกตว่าถ้าไปดูช่อง CN แล้วเห็นชื่อที่ตรง ก็ยังไม่ช่วย เพราะเมื่อมี SAN อยู่ ลูกข่ายต้องไม่มองช่อง CN เลย
สิ่งที่ยังไม่ได้พิสูจน์ เรารู้ว่าใบไม่ครอบคลุมชื่อนั้น แต่ยังไม่รู้ว่าตั้งใจ หรือลืม ให้ดูว่าระบบออกใบถูกตั้งให้ขอชื่อไหนไว้บ้าง
กรณีที่ 3 — เบราว์เซอร์เปิดได้ แต่โปรแกรมอื่นเปิดไม่ได้
หน้าเว็บเปิดปกติทุกเบราว์เซอร์ แต่สคริปต์ที่เรียก API ตัวเดียวกันล้มเหลวเรื่องใบรับรอง
อ่านอย่างไร นับจำนวนใบที่เซิร์ฟเวอร์ส่งมา
$ echo | openssl s_client -showcerts -connect example.com:443 \
-servername example.com 2>/dev/null \
| grep -c 'BEGIN CERTIFICATE'
1
ส่งมาใบเดียว แปลว่าไม่ได้ส่งใบกลาง ลูกข่ายจึงต่อโซ่ขึ้นไปหารากไม่ได้
เบราว์เซอร์รอดเพราะมันไปโหลดใบกลางมาเองได้ หรือเคยเจอมาก่อนแล้วจำไว้ ส่วนไลบรารี ส่วนใหญ่ไม่ทำแบบนั้น อาการที่เบราว์เซอร์ผ่านแต่โปรแกรมอื่นไม่ผ่าน จึงเกือบจะ เป็นข้อนี้เสมอ
ทางแก้อยู่ที่เซิร์ฟเวอร์ ให้ตั้งค่าส่งโซ่ให้ครบ ไม่ใช่ไปแก้ที่ลูกข่าย
สิ่งที่ยังไม่ได้พิสูจน์ ใบเดียวยืนยันว่าโซ่ไม่ครบ แต่ยังไม่รู้ว่าไฟล์ที่ตั้งไว้ ผิดตั้งแต่แรก หรือเพิ่งถูกเขียนทับตอนต่ออายุครั้งล่าสุด
กรณีที่ 4 — เครื่องเดียวเปิดไม่ได้ทุกเว็บ
เครื่องหนึ่งขึ้นเตือนเรื่องใบรับรองกับทุกเว็บที่เข้า ส่วนเครื่องอื่นในห้องปกติหมด
อ่านอย่างไร ถ้าเป็นทุกเว็บพร้อมกัน ปัญหาไม่ได้อยู่ที่เว็บ ให้ดูสองอย่างที่ เครื่องนั้นถือไว้ฝ่ายเดียว คือนาฬิกากับรายชื่อราก
$ date
Mon Aug 31 00:40:00 +07 2026
ถ้านาฬิกาเพี้ยนไปมาก ใบทุกใบจะดูเหมือนยังไม่เริ่มใช้ หรือหมดอายุไปแล้ว เพราะ การตรวจเทียบกับ notBefore และ notAfter ใช้เวลาของเครื่องเป็นเกณฑ์
นี่คือจุดที่ TLS พึ่งพาสิ่งที่ไม่มีบทความไหนในชุดนี้พูดถึง — เวลาที่ตรงกัน และเป็นเหตุผลที่เครื่องที่ถอดถ่านนาฬิกาไปนาน ๆ มักเปิดเว็บไม่ได้เลยหลังเปิดเครื่อง จนกว่าจะซิงก์เวลาเสร็จ
สิ่งที่ยังไม่ได้พิสูจน์ นาฬิกาถูกไม่ได้แปลว่าไม่ใช่สาเหตุอื่น ถ้าเวลาตรงแล้วยัง เป็นอยู่ ให้สงสัยว่ามีอะไรถูกติดตั้งเพิ่มในรายชื่อรากของเครื่องนั้น
อ้างอิง
มาตรฐานหลัก
- RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3 E. Rescorla, สิงหาคม 2018 Standards Track แทนที่ RFC 5077 5246 และ 6961 ที่มาของคุณสมบัติสามข้อ การจับมือรอบเดียว การเข้ารหัสข้อความหลัง ServerHello และการถอดชุดรหัสลับที่ไม่มี forward secrecy ออก
- RFC 5280 — Internet X.509 Public Key Infrastructure Certificate Profile Cooper และคณะ พฤษภาคม 2008 นิยามของโซ่ใบรับรอง การต่อชื่อ และการตรวจเส้นทาง
- RFC 6125 — Representation and Verification of Domain-Based Application Service Identity Saint-Andre และ Hodges, มีนาคม 2011 กฎการเทียบชื่อ และข้อบังคับว่าเมื่อมี SAN แล้วห้ามมอง CN
ส่วนขยายและกลไกรอบข้าง
- RFC 6066 — TLS Extensions: Extension Definitions D. Eastlake 3rd, มกราคม 2011 ที่มาของ SNI และปัญหาเว็บหลายเว็บบนเลขที่อยู่เดียว
- RFC 9162 — Certificate Transparency Version 2.0 Laurie, Messeri และ Stradling, ธันวาคม 2021 แทนที่ RFC 6962 และประโยคที่ระบุว่า บันทึกไม่ได้ป้องกันการออกใบผิด แต่ทำให้ตรวจพบได้
ของจริงบนเครื่อง
openssl s_client -connect netkubelab.com:443 -servername netkubelab.comแสดงเวอร์ชัน ชุดรหัสลับ ผลการตรวจ และโซ่ใบรับรองสามใบทั้งหมด- ยิงเข้าเลขที่อยู่เดียวกันแล้วเปลี่ยนแค่
-servernameได้ใบรับรองคนละใบ ซึ่งพิสูจน์ว่า SNI เป็นตัวเลือกใบ security find-certificate -aบนรายชื่อรากของ macOS นับได้ 160 รากopenssl x509 -noout -datesบนใบของเว็บนี้ ได้อายุ 90 วันพอดี
อ่านต่อในชุดนี้
- HTTP — ชั้นที่วิ่งอยู่ข้างใน และ ALPN ที่เลือกเวอร์ชันของมัน ตั้งแต่ตอนจับมือ
- TCP กับ UDP — การจับมือที่ต้องเสร็จก่อนการจับมือของหน้านี้
- ARP — บทความที่ปิดท้ายด้วยการบอกให้มาทำสิ่งที่หน้านี้อธิบาย
- DNS — คำถามที่ยังเดินทางแบบโล่งอยู่ ถ้าไม่ได้ใช้ DoH