นาฬิกาไม่ตรงกันและความล้มเหลวผ่านพร็อกซี: การวินิจฉัย TLS, โทเค็น และลายเซ็น
บทความ
- พื้นฐาน: ทำไมเวลาจึงเป็นส่วนหนึ่งของโปรโตคอล ไม่ใช่แค่ตัวเลขบนหน้าจอ
- เจาะลึก: เวลาสำคัญตรงไหนบ้าง
- ข้อผิดพลาดปรากฏอย่างไรในไคลเอนต์ต่าง ๆ
- ทำไมนาฬิกาถึงเพี้ยน: กายวิภาคของการคลาดเคลื่อน
- วินิจฉัยในหนึ่งนาที: วินิจฉัยอย่างรวดเร็ว
- ตั้งค่าการซิงค์: ให้มันทำงานได้จริง
- คอนเทนเนอร์และนาฬิกา: อะไรสืบทอด อะไรไม่
- ข้อผิดพลาดทั่วไป: อะไรที่ไม่ควรทำ
- เครื่องมือและแหล่งข้อมูล
- กรณีศึกษาและผลลัพธ์
- คำถามที่พบบ่อย: คำตอบเชิงลึกสำหรับคำถามที่พบบ่อย
ลองจินตนาการดู: เมื่อวานตัวดึงข้อมูลของคุณผ่านพร็อกซีทำงานได้อย่างสมบูรณ์แบบ บันทึกสะอาดหมดจด เมตริกเขียวทั้งหมด เช้านี้คุณเปิดแดชบอร์ดแล้วเจอกำแพงข้อผิดพลาด: certificate is not yet valid, token expired, signature does not match ความคิดแรกของวิศวกรนั้นคาดเดาได้: พร็อกซีพัง ผู้ให้บริการทำอะไรบางอย่าง ต้องเปลี่ยนพูล คุณใช้เวลาหลายชั่วโมงวินิจฉัยเครือข่าย เปลี่ยนปลายทาง เขียนหาฝ่ายสนับสนุน แต่ต้นเหตุกลับนั่งอยู่ตรงหน้าจมูกมาตลอดและเดินไม่ตรงเวลา นั่นคือเวลาของระบบ
นาฬิกาไม่ตรงกันเป็นหนึ่งในสาเหตุความล้มเหลวที่ถูกมองข้ามมากที่สุดในโครงสร้างพื้นฐานที่ทำงานผ่านพร็อกซี มันร้ายกาจตรงที่ปลอมตัวเป็นปัญหาเครือข่ายและใบรับรอง คุณเห็นคำว่า certificate ในข้อผิดพลาดแล้วก็รีบไปจัดการกับ TLS ทั้งที่ใบรับรองยังสดใหม่และถูกต้อง เพียงแค่เครื่องของคุณคิดว่าตอนนี้เป็นวันอื่น
ในคู่มือนี้เราจะเจาะลึกหัวข้อนี้ตั้งแต่ต้นจนจบ คุณจะได้รู้ว่าเวลาถูกฝังอยู่ในจุดใดของวิทยาการเข้ารหัสและโปรโตคอล ข้อผิดพลาดเฉพาะหน้าตาเป็นอย่างไรใน curl, Python และ Node ทำไมนาฬิกาถึงเพี้ยนในเครื่องเสมือนและคอนเทนเนอร์ วิธีวินิจฉัยภายในหนึ่งนาที และวิธีตั้งค่าการซิงค์ให้ทำงานได้จริง ไม่ใช่แค่ติดตั้งไว้เฉย ๆ บทความนี้เขียนโดยวิศวกรของ Proxeon จากกรณีศึกษาจริง ขอย้ำชัดเจน: เราไม่ได้พูดถึงการออกใบรับรองหรือโครงสร้างของมัน แต่พูดถึงเวลาในฐานะสาเหตุของความล้มเหลวเท่านั้น
พื้นฐาน: ทำไมเวลาจึงเป็นส่วนหนึ่งของโปรโตคอล ไม่ใช่แค่ตัวเลขบนหน้าจอ
เริ่มจากรากฐาน คนส่วนใหญ่มองว่าเวลาของระบบเป็นเพียงอนุสัญญาของมนุษย์: สะดวกที่จะรู้ว่าตอนนี้เป็น 14:30 แต่ในโลกของโปรโตคอลเครือข่าย เวลาเป็นผู้เล่นที่แข็งขันในการตรวจสอบความปลอดภัย มันถูกฝังอยู่ในตรรกะการตรวจสอบหลายระดับพร้อมกัน
เมื่อสองโหนดสร้างการเชื่อมต่อที่ปลอดภัยหรือแลกเปลี่ยนข้อความที่ลงลายเซ็น พวกมันต้องการวิธีแยกแยะข้อมูลสดออกจากข้อมูลเก่า หากไม่มีความคิดเรื่องเวลา ก็เป็นไปไม่ได้ที่จะตอบคำถามง่าย ๆ: ใบรับรองนี้หมดอายุหรือยัง? โทเค็นนี้หมดอายุหรือยัง? ผู้โจมตีกำลังเล่นซ้ำคำขอเก่าที่ดักจับมาหรือเปล่า? ด้วยเหตุนี้การประทับเวลาและหน้าต่างความถูกต้องจึงถูกฝังเข้าไปในโปรโตคอล
เวลาของระบบคืออะไรและมาจากไหน
ในระบบปฏิบัติการใด ๆ มีสองแนวคิดที่เชื่อมโยงกัน แนวคิดแรกคือ นาฬิกาฮาร์ดแวร์ (RTC, real-time clock) ชิปที่มีแบตเตอรี่เลี้ยงของตัวเอง เดินต่อไปแม้คอมพิวเตอร์ปิดอยู่ แนวคิดที่สองคือ นาฬิกาของระบบ ที่เคอร์เนล OS เก็บไว้ในหน่วยความจำ เริ่มจากค่า RTC ตอนบูตและปรับไปเรื่อย ๆ ระหว่างทำงาน
ปัญหาคือ ออสซิลเลเตอร์ควอตซ์ ในฮาร์ดแวร์ใด ๆ ไม่สมบูรณ์แบบ มันเดินเร็วหรือช้าไม่กี่เสี้ยววินาทีต่อวัน เรียกว่า การคลาดเคลื่อนของนาฬิกา (clock drift) ภายในหนึ่งสัปดาห์โดยไม่แก้ไข จะสะสมเป็นวินาทีที่สังเกตเห็นได้ และในสภาพแวดล้อมเสมือนบางประเภทอาจถึงระดับนาที เพื่อต่อสู้กับการคลาดเคลื่อน จึงคิดค้นโปรโตคอลการซิงค์เวลาผ่านเครือข่าย เดมอนการซิงค์จะถามเซิร์ฟเวอร์อ้างอิงเป็นระยะเพื่อเวลาที่แม่นยำและค่อย ๆ ปรับนาฬิกาท้องถิ่น
UTC, เขตเวลา และทำไมมันสำคัญสำหรับพร็อกซี
ข้อมูลเชิงลึกสำคัญสำหรับมือใหม่: การเข้ารหัสเครือข่ายที่จริงจังทั้งหมดทำงานใน UTC - เวลาสากลเชิงพิกัด โดยไม่ผูกกับเขตเวลา ใบรับรอง JWT ลายเซ็นคำขอ ทั้งหมดดำเนินการกับช่วงเวลาใน UTC เขตเวลาเป็นเพียงเครื่องสำอางสำหรับแสดงผลให้มนุษย์
นั่นหมายความว่าถ้าคุณตั้งเขตเวลาผิด แต่เวลาสัมบูรณ์ (ใน UTC) ถูกต้อง การเข้ารหัสจะไม่ได้รับผลกระทบ แต่ถ้าเวลาสัมบูรณ์เองผิด ทุกอย่างจะพัง ความสับสนที่พบบ่อย: วิศวกรเห็นเวลาโลคอลแปลก ๆ ในบันทึก เข้าไปแก้เขตเวลา แต่ต้นเหตุอยู่ที่อื่น จำการแบ่งนี้ไว้: เขตเวลามีผลต่อการแสดงผล เวลาสัมบูรณ์ใน UTC มีผลต่อการตรวจสอบ
พร็อกซีเข้ามาเกี่ยวข้องอย่างไร
เมื่อคุณทำงานผ่านพร็อกซี คุณมีโหนดเพิ่มเติมในเส้นทางคำขอ แต่สิ่งสำคัญที่ต้องเข้าใจคือ: พร็อกซีในสถานการณ์ส่วนใหญ่ไม่ได้เปลี่ยนหรือแทนที่เวลาในการตรวจสอบการเข้ารหัสของคุณ การจับมือ TLS กับเซิร์ฟเวอร์ปลายทาง การตรวจสอบอายุใบรับรอง การตรวจสอบโทเค็น ทั้งหมดเกิดขึ้นฝั่งคุณหรือฝั่งเซิร์ฟเวอร์ปลายทาง พร็อกซีเพียงส่งต่อไบต์
จึงเกิดความขัดแย้ง: การทำงานผ่านพร็อกซีไม่ได้สร้างปัญหาเวลา แต่ทำให้อาการสับสนมากขึ้น วิศวกรเห็นห่วงโซ่ไคลเอนต์ - พร็อกซี - เซิร์ฟเวอร์ และสงสัยตรงกลางโดยธรรมชาติ แต่ความผิดอยู่ที่เครื่องท้องถิ่นที่มีนาฬิกาเดินผิด เราเรียกสิ่งนี้ว่า เอฟเฟกต์ความสงสัยที่ถูกเลื่อน: ยิ่งห่วงโซ่ยาวเท่าไหร่ เราก็ยิ่งโทษตรงกลาง มากกว่าปลายทั้งสองข้าง
เจาะลึก: เวลาสำคัญตรงไหนบ้าง
ตอนนี้เรามาดูจุดเฉพาะที่เวลาไม่ถูกต้องกลายเป็นความล้มเหลว มีสี่จุด แต่ละจุดสมควรได้รับความสนใจแยกกัน
การตรวจสอบอายุใบรับรองใน TLS
ใบรับรอง TLS ทุกใบมีสองฟิลด์: notBefore (ใช้ไม่ได้ก่อนหน้านี้) และ notAfter (ใช้ไม่ได้หลังจากนี้) นี่คือขอบเขตของหน้าต่างความถูกต้อง เมื่อไคลเอนต์ของคุณสร้างการเชื่อมต่อที่ปลอดภัย มันได้รับใบรับรองของเซิร์ฟเวอร์และตรวจสอบว่า เวลาปัจจุบัน อยู่ในหน้าต่างนี้หรือไม่
และนี่คือจุดสำคัญ: เวลาปัจจุบันหมายถึงเวลาบนเครื่องของคุณ ถ้านาฬิกาของคุณช้าและแสดงวันที่ก่อน notBefore ไคลเอนต์จะตัดสินว่าใบรับรองยังไม่เริ่มมีผล ข้อผิดพลาดแบบ certificate is not yet valid ถ้านาฬิกาเดินหน้าไปเกิน notAfter ใบรับรองก็หมดอายุสำหรับคุณ แม้สำหรับโลกทั้งใบมันยังสดใหม่ ข้อผิดพลาด certificate has expired
ใบรับรองอายุสั้นนั้นร้ายกาจเป็นพิเศษ แนวปฏิบัติสมัยใหม่กำลังมุ่งไปสู่ใบรับรองที่มีอายุ 90 วันหรือน้อยกว่า และภายในปี 2026 อุตสาหกรรมกำลังหารือเรื่องการลดอายุลงเหลือ 45 วันหรือน้อยกว่า ยิ่งหน้าต่างความถูกต้องสั้นลง กำไรความปลอดภัยต่อนาฬิกาที่เพี้ยนก็ยิ่งน้อยลง แต่ก่อนการไม่ตรงกันเป็นชั่วโมงแทบจะไม่สังเกตเห็นเมื่อเทียบกับใบรับรองอายุหนึ่งปี ตอนนี้หน้าต่างแคบหมายความว่าแม้การเลื่อนเพียงไม่กี่ชั่วโมงที่ขอบเขตการต่ออายุก็สามารถล้มการเชื่อมต่อได้
JWT: ฟิลด์ exp, nbf และ iat
JSON Web Token เป็นรูปแบบโทเค็นการอนุญาตที่ได้รับความนิยม ภายในมีฟิลด์เวลาที่ตรวจสอบทุกครั้งที่ใช้โทเค็น:
- exp (expiration time) - ช่วงเวลาที่โทเค็นถือว่าหมดอายุ
- nbf (not before) - ช่วงเวลาที่โทเค็นยังไม่ใช้งานได้
- iat (issued at) - เมื่อโทเค็นถูกออก
ทั้งสามเป็น Unix timestamp ในหน่วยวินาทีนับจาก epoch นั่นคือเวลาสัมบูรณ์ใน UTC เมื่อเซิร์ฟเวอร์ได้รับโทเค็น มันเปรียบเทียบฟิลด์เหล่านี้กับนาฬิกาของตัวเอง เมื่อไคลเอนต์ของคุณตัดสินใจว่าต้องรีเฟรชโทเค็นหรือไม่ มันดูที่ exp เทียบกับนาฬิกาของตัวเอง
สถานการณ์ความล้มเหลวนั้นงดงามในความร้ายกาจ สมมติว่านาฬิกาของไคลเอนต์คุณเดินหน้าไปสิบนาที เซิร์ฟเวอร์ออกโทเค็นอายุห้านาที ไคลเอนต์ของคุณมองนาฬิกาที่เดินเร็วและคิดทันทีว่าโทเค็นสดใหม่นั้นหมดอายุแล้ว และอาจไม่ส่งมัน หรือเริ่มลูปการรีเฟรชไม่รู้จบ สถานการณ์ตรงกันข้าม: ถ้า nbf ผิดเทียบกับนาฬิกาของคุณ คุณจะเจอ token used before issued หรือ token not yet valid
ลายเซ็นคำขอที่มีการประทับเวลา
API หลายแห่งต้องการให้ทุกคำขอถูกลงลายเซ็น และการประทับเวลาถูกรวมเข้าในลายเซ็น ตัวอย่างคลาสสิกคือรูปแบบลายเซ็น HMAC ที่ไคลเอนต์สร้างสตริงจากเมธอด เส้นทาง เนื้อหา และ timestamp ปัจจุบัน แล้วลงลายเซ็นด้วยคีย์ลับ เซิร์ฟเวอร์ทำการคำนวณซ้ำและเปรียบเทียบลายเซ็น
ที่นี่เวลามีบทบาทสองอย่าง อย่างแรก timestamp รวมอยู่ในสตริงที่ลงลายเซ็น ดังนั้นเซิร์ฟเวอร์ต้องใช้ timestamp เดียวกับที่ไคลเอนต์ส่งมา - มันดึงจากเฮดเดอร์ อย่างที่สอง เซิร์ฟเวอร์ตรวจสอบว่า timestamp นี้ไม่ห่างจากเวลาของตัวเองมากเกินไป โดยปกติอนุญาตหน้าต่างไม่กี่นาที - ป้องกันการเล่นซ้ำคำขอเก่า
ถ้านาฬิกาของไคลเอนต์ออกนอกหน้าต่างนี้ เซิร์ฟเวอร์จะปฏิเสธคำขอว่าเก่าเกินไปหรือมาจากอนาคต ข้อผิดพลาดแบบ request timestamp too skewed, signature expired หรือ signature does not match แบบทั่วไป และเพราะเวลาเองนี่แหละที่คุณมักเห็นข้อผิดพลาดลายเซ็น ไม่ใช่ข้อผิดพลาดเวลา - เซิร์ฟเวอร์ไม่ค่อยบอกตรง ๆ ว่าปัญหาอยู่ที่นาฬิกา
รหัสใช้ครั้งเดียวและรหัสผ่านชั่วคราว
หมวดหมู่แยกต่างหากคือรหัสใช้ครั้งเดียวตามเวลา (TOTP) ที่ใช้ในการยืนยันตัวตนสองขั้นตอนเมื่อเข้าถึงแผงควบคุมและคอนโซล API รหัสนี้คำนวณจากความลับที่ใช้ร่วมกันและเวลาปัจจุบัน แบ่งเป็นช่วงปกติ 30 วินาที ทั้งสองฝ่ายคำนวณรหัสอย่างอิสระและเปรียบเทียบ
ถ้านาฬิกาของไคลเอนต์เพี้ยนเกินหนึ่งถึงสองช่วง รหัสจะไม่ตรงกันอีกต่อไป คุณป้อนรหัสที่เพิ่งสร้างใหม่ แต่ระบบบอกว่าไม่ถูกต้อง คนในสถานการณ์นี้มักโทษแอปสร้างรหัสหรือตื่นตระหนกเรื่องการถูกแฮก ทั้งที่แค่ดูนาฬิกาก็พอ ค่าเผื่อตรงนี้แคบมาก - ไม่กี่สิบวินาที ดังนั้น TOTP จึงทำงานเป็นตัวชี้วัดการไม่ตรงกันได้อย่างยอดเยี่ยม
ข้อผิดพลาดปรากฏอย่างไรในไคลเอนต์ต่าง ๆ
ทฤษฎีก็คือทฤษฎี แต่วิศวกรอยู่กับเทอร์มินัลและอ่านข้อความข้อผิดพลาด มาดูว่าการไม่ตรงกันของนาฬิกาปรากฏในเครื่องมือยอดนิยมอย่างไร สิ่งนี้จะช่วยให้คุณจดจำอาการได้ทันที
curl
เมื่อทำงานกับ TLS ผ่าน curl นาฬิกาที่เพี้ยนให้ข้อความเฉพาะเจาะจง ถ้าเวลาช้าและใบรับรองยังไม่เริ่มมีผลตามนาฬิกาของคุณ:
curl: (60) SSL certificate problem: certificate is not yet validถ้าเวลาเดินหน้าไปและใบรับรองหมดอายุตามมาตรฐานของคุณแล้ว:
curl: (60) SSL certificate problem: certificate has expiredรายละเอียดที่มีประโยชน์: รหัสข้อผิดพลาด 60 เกี่ยวข้องกับปัญหาการตรวจสอบใบรับรอง วิศวกรที่ไม่มีประสบการณ์เห็นคำว่า certificate แล้วไปตรวจสอบใบรับรองด้วยคำสั่งดูข้อมูล ยืนยันว่าวันที่ความถูกต้องเป็นไปด้วยดี แล้วก็งง คำตอบคือวันที่ของใบรับรองถูกเปรียบเทียบกับเวลาท้องถิ่นของคุณ ตรวจสอบตัวอย่างผ่านพร็อกซี:
curl -x http://user:pass@gateway.proxeon.net:8080 -v https://api.example.com/statusถ้าในเอาต์พุต -v คุณเห็นบรรทัดเกี่ยวกับการตรวจสอบวันที่ของใบรับรองและตามด้วยข้อผิดพลาดความถูกต้อง สิ่งแรกที่ควรทำคือเทียบ date -u กับค่าอ้างอิง ไม่ใช่สงสัยเกตเวย์
Python (requests และ httpx)
ใน Python บนสแต็ก TLS มาตรฐาน นาฬิกาที่เพี้ยนทำให้เกิดข้อยกเว้นตอนจับมือ:
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.example.com', port=443): Max retries exceeded (Caused by SSLError(SSLCertVerificationError("certificate verify failed: certificate is not yet valid")))สังเกตส่วนท้ายของข้อความ: certificate is not yet valid นี่คืออาการเวลาแบบเดียวกัน เมื่อทำงานกับ JWT ภาพจะต่างออกไป - ไม่มีข้อผิดพลาด TLS แต่ไลบรารีตรวจสอบโทเค็นจะโยนข้อยกเว้นเฉพาะ:
jwt.exceptions.ImmatureSignatureError: The token is not yet valid (nbf)หรือ
jwt.exceptions.ExpiredSignatureError: Signature has expiredตรงนี้คำว่า signature ทำให้สับสน - ดูเหมือนปัญหาอยู่ที่ลายเซ็นการเข้ารหัส อันที่จริง expired ชี้ไปที่ฟิลด์ exp และนาฬิกาของคุณโดยตรง การตรวจสอบเวลาอย่างรวดเร็วจากในโค้ด:
import time, datetime; print(datetime.datetime.utcnow(), int(time.time()))เปรียบเทียบ Unix timestamp ที่ได้กับค่าอ้างอิง - ส่วนต่างเกินสองสามวินาทีก็น่าสงสัยแล้ว
Node.js
ใน Node ข้อผิดพลาด TLS มาพร้อมรหัส สำหรับการไม่ตรงกันของนาฬิกา รหัสที่เป็นเอกลักษณ์คือ:
Error: certificate is not yet valid\ncode: 'CERT_NOT_YET_VALID'และ
Error: certificate has expired\ncode: 'CERT_HAS_EXPIRED'รหัส CERT_NOT_YET_VALID และ CERT_HAS_EXPIRED เป็นตัวชี้ตรง ถ้าคุณเห็นตัวแรกกับใบรับรองที่ยังดีอยู่ นาฬิกาของคุณช้า ถ้าเห็นตัวที่สองกับใบรับรองที่สดใหม่ชัดเจน นาฬิกาของคุณเร็ว เมื่อทำงานกับไลบรารี JWT ใน Node คุณจะได้ข้อผิดพลาดชื่อ TokenExpiredError และ NotBeforeError การตรวจสอบอย่างรวดเร็ว:
node -e "console.log(new Date().toISOString(), Math.floor(Date.now()/1000))"ตารางสรุปอาการ
รวบรวมรูปแบบเป็นแผนที่ในใจเดียว:
- certificate is not yet valid / CERT_NOT_YET_VALID - นาฬิกาช้า
- certificate has expired / CERT_HAS_EXPIRED กับใบรับรองที่สดใหม่ - นาฬิกาเร็ว
- token not yet valid / nbf / ImmatureSignature - นาฬิกาช้าเมื่อเทียบกับเซิร์ฟเวอร์ที่ออก
- token expired / ExpiredSignature ทันทีหลังจากได้รับโทเค็น - นาฬิกาเร็ว
- signature does not match / timestamp too skewed - นาฬิกาออกนอกหน้าต่างเผื่อของเซิร์ฟเวอร์
- รหัส TOTP ผิดตลอด - นาฬิกาเพี้ยนไปหลายสิบวินาทีขึ้นไป
ทำไมนาฬิกาถึงเพี้ยน: กายวิภาคของการคลาดเคลื่อน
การเข้าใจสาเหตุคือครึ่งหนึ่งของการแก้ปัญหา มาดูว่าทำไมในโครงสร้างพื้นฐานสมัยใหม่ นาฬิกาถึงเพี้ยนบ่อยกว่าที่คิด โดยเฉพาะกับเซิร์ฟเวอร์และโหนดทำงานที่คุณส่งทราฟฟิกพร็อกซีผ่าน
เครื่องเสมือนและการแช่แข็ง
เครื่องเสมือนไม่มีการเข้าถึงควอตซ์ทางกายภาพโดยตรง ความคิดเรื่องเวลาของมันเป็นนามธรรมที่ไฮเปอร์ไวเซอร์ดูแล โดยปกติทุกอย่างดี ตราบใดที่ VM ทำงานต่อเนื่อง แต่พอไฮเปอร์ไวเซอร์หยุดเครื่องชั่วคราว ก็เริ่มมีเรื่องประหลาด
สถานการณ์คลาสสิกคือ การแช่แข็งและสแนปช็อต ไฮเปอร์ไวเซอร์หยุด VM ชั่วคราว เช่น เพื่อการย้ายหรือสำรองข้อมูล ภายในเกสต์ เวลาดูเหมือนหยุดนิ่ง เมื่อเครื่องถูกปลุก เวลาของระบบจะช้าไปเท่ากับระยะเวลาที่หยุด ถ้าเป็นหนึ่งนาที คุณได้การเลื่อนหนึ่งนาทีทันทีในพริบตา สำหรับโทเค็นอายุสั้นและหน้าต่างลายเซ็นแคบ นี่เป็นเรื่องร้ายแรง
แย่ยิ่งกว่าคือการกู้คืนจากส แนปช็อตเก่า เครื่องตื่นขึ้นด้วยเวลาที่บันทึกไว้ตอนสแนปช็อต - อาจเป็นชั่วโมงหรือวันในอดีต TLS จะเริ่มปฏิเสธใบรับรองทันทีว่าไม่ถูกต้อง แพลตฟอร์มคลาวด์หลายแห่งมีเกสต์เอเจนต์ที่ปรับเวลาให้หลังปลุก แต่ไม่ได้มีและทำงานเสมอไป
คอนเทนเนอร์
กับคอนเทนเนอร์ เรื่องราวละเอียดอ่อนกว่า คอนเทนเนอร์ไม่มีนาฬิกาของระบบเป็นของตัวเอง - มันใช้เคอร์เนลของโฮสต์และเวลาของโฮสต์ นี่เป็นข่าวดี: ถ้าโฮสต์ซิงค์อยู่ คอนเทนเนอร์จะเห็นเวลาที่ถูกต้องโดยอัตโนมัติ
ข่าวร้ายอยู่ในรายละเอียด อย่างแรก ปกติคุณไม่สามารถเปลี่ยนเวลาระบบภายในคอนเทนเนอร์ได้ - มันไม่มีสิทธิ์ที่เกี่ยวข้อง และนั่นก็ถูกต้อง อย่างที่สอง ซึ่งสำคัญคือ ภายในคอนเทนเนอร์มักไม่มีเดมอนซิงค์ และนั่นปกติ - โฮสต์ควรเป็นผู้ซิงค์ ปัญหาเกิดขึ้นเมื่อโฮสต์เองไม่ซิงค์ และคุณไม่สังเกตเพราะเคยชินว่าแล็ปท็อปนักพัฒนาทุกอย่างซิงค์ในตัวอยู่แล้ว
ไม่มีเดมอนซิงค์
สาเหตุที่โง่ที่สุดและพบบ่อยที่สุด บนอิมเมจเซิร์ฟเวอร์แบบมินิมอล เดมอนซิงค์เวลาอาจไม่ได้ติดตั้งหรือไม่ถูกเรียกใช้ เครื่องบูต ดึงเวลาจาก RTC แล้วดำเนินชีวิตบนควอตซ์ที่คลาดเคลื่อนโดยไม่แก้ไข วันแล้ววันเล่า ความเบี่ยงเบนสะสม
อิมเมจที่สร้างด้วยมือหรือโคลนมานั้นอันตรายเป็นพิเศษ วิศวกรตั้งค่าทุกอย่างบนเครื่องอ้างอิง ทำอิมเมจ แจกจ่ายไปยังร้อยโหนด - แต่เดมอนซิงค์ไม่ได้เปิดใช้งาน ร้อยโหนดเริ่มค่อย ๆ แยกออกจากกันไปคนละทาง ตราบใดที่ความเบี่ยงเบนยังเล็ก ทุกอย่างก็ทำงานได้ ผ่านไปหนึ่งสัปดาห์ ควอตซ์ที่เร็วที่สุดก็เกินหน้าต่างเผื่อ คุณจะได้ความล้มเหลวแบบลอย ๆ ที่ทำซ้ำไม่ได้บนบางส่วนของฝูง
การแก้ไขด้วยมือและ RTC ที่ค้าง
บางครั้งมนุษย์ทำเวลาพัง มีคนตั้งวันที่ด้วยมือเพื่อทดสอบและลืมคืนค่า มีคนปิดการซิงค์เพราะมันรบกวนการทดลองหนึ่ง ปัญหาแยกต่างหากคือแบตเตอรี่ RTC หมดบนเซิร์ฟเวอร์กาย: หลังรีสตาร์ทนาฬิกาจะรีเซ็ตไปอดีตอันไกล และจนกว่าจะซิงค์ครั้งแรก TLS ก็ไม่ทำงานเลย
การควบคุมเวลาสองทาง
กรณีที่ละเอียดอ่อนที่คนมักลืม บางครั้งมีสองกลไกต่อสู้กันเพื่อเวลา: เกสต์เอเจนต์ของไฮเปอร์ไวเซอร์และเดมอนซิงค์ภายใน OS พวกมันดึงนาฬิกาไปคนละทาง และคุณได้เวลาที่แกว่งไปแกว่งมา ปรากฏเป็นความล้มเหลวเป็นระยะที่จับไม่ได้ กฎง่าย ๆ: กลไกเดียวเท่านั้นที่ควรรับผิดชอบเวลา
วินิจฉัยในหนึ่งนาที: วินิจฉัยอย่างรวดเร็ว
มาต่อที่ภาคปฏิบัติ เป้าหมายของคุณคือเข้าใจในหกสิบวินาทีว่าเวลาเป็นความผิดหรือไม่ นี่คือกรอบทีละขั้นตอนที่เราใช้ที่ Proxeon ในการสืบสวนเหตุการณ์
ขั้นแรก: ดูเวลาของคุณใน UTC
อย่างแรก ดูว่านาฬิกาของคุณคิดอย่างไร ใน UTC โดยเฉพาะ เพื่อหลีกเลี่ยงความสับสนกับเขตเวลา:
date -uจดค่าไว้ ตอนนี้เปรียบเทียบกับค่าอ้างอิง
ขั้นที่สอง: เปรียบเทียบกับแหล่งภายนอก
วิธีที่น่าเชื่อถือที่สุดคือถามเวลาจากเซิร์ฟเวอร์เวลาเครือข่ายและดูการเบี่ยงเบน ถ้าติดตั้ง chrony:
chronyc trackingในเอาต์พุต มองหาบรรทัด System time - มันแสดงการเบี่ยงเบนของนาฬิการะบบเทียบกับค่าอ้างอิง ค่าเช่น 0.000030 seconds คืออุดมคติ ถ้าใช้ systemd-timesyncd:
timedatectl show-timesync --all | grep -i offsetอีกวิธีที่รวดเร็วคือการสอบถามเซิร์ฟเวอร์เวลาแบบครั้งเดียวโดยไม่เปลี่ยนนาฬิกา:
chronyd -Q 'server pool.ntp.org iburst'มันจะพิมพ์ค่าแก้ไขที่คาดไว้ ถ้าค่าสัมบูรณ์ของมันใหญ่ - นั่นคือคำตอบของคุณ
ขั้นที่สาม: ตรวจสอบผ่านเฮดเดอร์ Date ของ HTTP
ข้อมูลเชิงลึกที่ช่วยประหยัดเวลามหาศาล เว็บเซิร์ฟเวอร์เกือบทั้งหมดส่งเฮดเดอร์ Date กลับมาในคำตอบพร้อมเวลาปัจจุบันใน UTC เปรียบเทียบกับนาฬิกาของคุณโดยตรงผ่านพร็อกซีของคุณ:
curl -sI -x http://user:pass@gateway.proxeon.net:8080 https://example.com | grep -i ^dateเทียบกับ date -u ถ้าต่างกันไม่กี่วินาที - ทุกอย่างเรียบร้อย ถ้าต่างกันเป็นนาที - นั่นคือสาเหตุของคุณ จุดเด่นของวิธีนี้คือไม่ต้องมีเดมอนติดตั้ง และทำงานได้แม้ในคอนเทนเนอร์เปล่า ๆ ที่มีแค่ curl
ส่วนต่างเท่าไรถึงถือว่าปกติ
แนวปฏิบัติที่ได้จากประสบการณ์:
- ไม่เกิน 1 วินาที - ยอดเยี่ยม ไม่ต้องทำอะไร ระบบที่ซิงค์ดีจะรักษาระดับเสี้ยววินาที
- 1-5 วินาที - ยอมรับได้สำหรับ TLS และ JWT ส่วนใหญ่ แต่เป็นโซนที่ต้องจับตา ลายเซ็นคำขอและ TOTP ยังไหว แต่กำไรกำลังลดลง
- 5-30 วินาที - เตือนภัย TOTP เริ่มเพี้ยน หน้าต่างลายเซ็นแคบตกอยู่ในอันตราย การซิงค์ไม่ทำงานอย่างที่ควร
- มากกว่า 30 วินาที - วิกฤต ลายเซ็น โทเค็นอายุสั้น ล้มเหลว และถ้าเบี่ยงเบนมาก TLS ก็ด้วย แก้ไขทันที
- นาทีและชั่วโมง - หายนะ ปกติเป็นผลจากการแช่แข็ง สแนปช็อต หรือแบตเตอรี่ RTC ตาย
กฎทอง: ถ้าการเบี่ยงเบนเกินห้าวินาที ต้องถือว่าเวลาเป็นผู้ต้องสงสัยอันดับแรกในความล้มเหลว TLS โทเค็น และลายเซ็นทั้งหมด
ตั้งค่าการซิงค์: ให้มันทำงานได้จริง
การวินิจฉัยอย่างเดียวยังไม่พอ - ต้องรักษาและป้องกันการเกิดซ้ำ มาดูเครื่องมือหลักสองตัวใน Linux และที่สำคัญที่สุด วิธีตรวจสอบว่าการซิงค์ทำงานอยู่จริง ไม่ใช่แค่ติดตั้งไว้ นี่คือความแตกต่างสำคัญที่คนมักมองข้าม
systemd-timesyncd: ตัวเลือกง่าย
สำหรับเครื่องไคลเอนต์ส่วนใหญ่และโหนดเบา ไคลเอนต์ที่ติดมากับ systemd ก็เพียงพอ มันซิงค์เวลาผ่านโปรโตคอลเวลาอย่างง่าย การเปิดใช้งาน:
timedatectl set-ntp trueตรวจสอบว่าการซิงค์เกิดขึ้นจริง:
timedatectl statusมองหาสองบรรทัด System clock synchronized: yes หมายถึงระบบคิดว่าตัวเองซิงค์แล้ว NTP service: active หมายถึงเดมอนทำงาน ทั้งสองต้องเป็นบวก ถ้า synchronized: no แต่ active - เดมอนรันอยู่แต่ยังเชื่อมต่อเซิร์ฟเวอร์ไม่ได้หรือเซิร์ฟเวอร์เข้าถึงไม่ได้
รายละเอียดของเซิร์ฟเวอร์เฉพาะ:
timedatectl show-timesync --allที่นี่เห็นว่าเชื่อมต่อกับเซิร์ฟเวอร์ใดและได้การเบี่ยงเบนเท่าไร คำสั่งนี้เองที่แยกการซิงค์ที่ทำงานจริงออกจากการตกแต่ง
chrony: ตัวเลือกจริงจัง
สำหรับเซิร์ฟเวอร์ที่ความเสถียรสำคัญ โดยเฉพาะ VM ที่เสี่ยงต่อการแช่แข็ง chrony เป็นที่นิยมกว่า มันรับมือกับเวลาที่กระโดดได้ฉลาดกว่าและลู่เข้าหลังจากการหยุดได้เร็วกว่า ติดตั้งผ่านตัวจัดการแพ็กเกจ แล้วเริ่มบริการ ตรวจสอบการทำงาน - คำสั่งหลัก:
chronyc trackingวิเคราะห์บรรทัดสำคัญในเอาต์พุต:
- Reference ID - ผูกกับแหล่งใด ถ้าเป็น 00000000 หรือบรรทัดที่บอกว่าไม่ได้เลือกแหล่ง แสดงว่าไม่มีการซิงค์
- Stratum - ระดับความห่างจากนาฬิกาอ้างอิง ปกติเห็นตัวเลขน้อย ๆ
- System time - การเบี่ยงเบนปัจจุบันของนาฬิการะบบ นี่คือตัวชี้วัดหลักของคุณ
- Last offset และ RMS offset - ค่าแก้ไขล่าสุดและเฉลี่ย แสดงความเสถียร
รายการแหล่งและสถานะ:
chronyc sources -vสัญลักษณ์ดาวทางซ้ายของเซิร์ฟเวอร์หมายถึงเซิร์ฟเวอร์นั้นถูกเลือกเป็นแหล่งที่ใช้งานอยู่ ถ้าไม่มีแหล่งใดมีเครื่องหมายถูกเลือก แสดงว่าเดมอนติดตั้งแล้วแต่ไม่ได้ซิงค์ - กับดักที่พบบ่อย
วิธีแยกการซิงค์ที่ติดตั้งออกจากการซิงค์ที่ทำงาน
นี่คือข้อมูลเชิงลึกที่คุ้มค่ากับการอ่านส่วนนี้ การติดตั้งแพ็กเกจและแม้แต่การที่บริการรันอยู่ ไม่ได้รับประกันการซิงค์ บริการอาจวนอยู่และไม่มีสิทธิ์เข้าถึงเซิร์ฟเวอร์เวลา เช่น ไฟร์วอลล์ตัดแพ็กเก็ตขาออกที่พอร์ตที่ต้องการ หรือในเครือข่ายปิดไม่มีเซิร์ฟเวอร์เวลาภายใน
การตรวจสอบจริงประกอบด้วยสามคำถาม ข้อแรก: มีแหล่งที่เลือกอยู่หรือไม่? ดูเครื่องหมายใน sources หรือ Reference ID ใน tracking ข้อสอง: การเบี่ยงเบนปัจจุบันเท่าไร? System time ควรอยู่ในระดับเสี้ยววินาที ข้อสาม: มันอัปเดตหรือไม่? รันการตรวจสอบสองครั้งห่างกันและดูว่าตัวเลขยังมีชีวิต ไม่ได้ค้าง ถ้าทั้งสามตอบบวก - การซิงค์ทำงานจริง
การมอนิเตอร์การเบี่ยงเบนเป็นเมตริก
แนวทางระดับมืออาชีพคือไม่รอให้เกิดเหตุการณ์ แต่ติดตามการเบี่ยงเบนอย่างต่อเนื่อง ส่งค่า System time เข้าสู่ระบบมอนิเตอร์ของคุณเป็นเมตริกปกติ ตั้งการเตือนเมื่อเกิน เช่น สองวินาที และสัญญาณเตือนเมื่อห้าวินาที แล้วคุณจะรู้ปัญหาก่อนที่ลายเซ็นและโทเค็นจะพัง ต้นทุนการมอนิเตอร์แบบนี้แทบเป็นศูนย์ แต่ผลตอบแทนมหาศาล: การป้องกันเหตุการณ์ตอนกลางคืนหนึ่งครั้งก็คุ้มค่าทั้งหมดแล้ว
คอนเทนเนอร์และนาฬิกา: อะไรสืบทอด อะไรไม่
การคอนเทนเนอร์ไรเซชันสมควรได้รับการวิเคราะห์เชิงลึกแยก เพราะที่นี่วิศวกรมีความเข้าใจผิดมากที่สุด มาแยกให้ชัดว่าคอนเทนเนอร์ได้รับอะไรจากโฮสต์และอะไรไม่
สิ่งที่สืบทอด: ตัวเวลาเอง
ข้อเท็จจริงสำคัญ: คอนเทนเนอร์ใช้เคอร์เนลของโฮสต์ร่วม ดังนั้นจึงใช้เวลาของระบบร่วมด้วย ภายในคอนเทนเนอร์ date -u จะแสดงเวลาสัมบูรณ์เดียวกันกับโฮสต์ คอนเทนเนอร์ไม่มีตัวนับเวลาแยก นี่เป็นพื้นฐาน คำสรุปหลัก: เพื่อให้คอนเทนเนอร์เห็นเวลาที่ถูกต้อง ต้องซิงค์ที่โฮสต์ ไม่ใช่พยายามตั้งค่าซิงค์ภายในคอนเทนเนอร์
สิ่งที่ไม่สืบทอด: เขตเวลา
แต่การแสดงเวลานั้นต่างเรื่อง เขตเวลาถูกกำหนดโดยการตั้งค่าภายในคอนเทนเนอร์ ปกติเป็นไฟล์โซนและตัวแปรสภาพแวดล้อม อิมเมจพื้นฐานมักมาพร้อม UTC และนั่นเป็นแนวปฏิบัติที่ดีสำหรับเซิร์ฟเวอร์ ถ้าภายในคอนเทนเนอร์เวลาโลคอลดูต่างจากโฮสต์ - นั่นเกือบทุกครั้งคือความต่างของเขตเวลา ไม่ใช่เวลาจริง ตรวจสอบค่าสัมบูรณ์ใน UTC ก่อนตื่นตระหนก
ทำไมไม่ควรเรียกใช้เดมอนเวลาในคอนเทนเนอร์
ข้อผิดพลาดที่พบบ่อยของมือใหม่คือยัดเดมอนซิงค์เข้าไปในคอนเทนเนอร์ นี่ผิดด้วยสองเหตุผล อย่างแรก การเปลี่ยนเวลาระบบเป็นการดำเนินการที่มีสิทธิพิเศษ ส่งผลต่อทั้งเคอร์เนลและดังนั้นต่อทุกคอนเทนเนอร์บนโฮสต์และตัวโฮสต์เอง ตามค่าเริ่มต้นคอนเทนเนอร์ถูกห้าม และก็ดีแล้ว การให้สิทธิ์นี้เพื่อการซิงค์เท่ากับเปิดช่องโหว่และสร้างความขัดแย้ง
อย่างที่สอง มันไม่จำเป็น: เวลามาจากโฮสต์อยู่แล้ว สถาปัตยกรรมที่ถูกต้องคือโฮสต์ที่ซิงค์แล้วหนึ่งตัว คอนเทนเนอร์มากมายที่เห็นเวลาถูกต้องโดยอัตโนมัติ ถ้าคุณมีออร์เคสเตรเตอร์ที่มีหลายโหนด ต้องให้การซิงค์ในแต่ละโหนดโฮสต์ ไม่ใช่ในแต่ละพอด
กับดักของแล็ปท็อปนักพัฒนา
เตือนแยกต่างหากเกี่ยวกับสถานการณ์ที่ร้ายกาจ บนแล็ปท็อปนักพัฒนาทุกอย่างทำงาน: คอนเทนเนอร์เห็นเวลาถูกต้อง เพราะ OS ของเวิร์กสเตชันซิงค์มาในตัว วิศวกรสร้างอิมเมจ ทุกอย่างเขียว อิมเมจไปยังเซิร์ฟเวอร์ที่โฮสต์ไม่ซิงค์ - และที่นั่นความล้มเหลวเริ่ม บทเรียน: ทดสอบพฤติกรรมเมื่อเวลาผิด ไม่ใช่แค่เมื่อสมบูรณ์แบบ จงตั้งใจเลื่อนเวลาในสภาพแวดล้อมทดสอบและดูว่าแอปตอบสนองอย่างไร
ตรวจสอบเวลาในคอนเทนเนอร์ที่ทำงาน
คำสั่งรวดเร็วเพื่อแอบดูในคอนเทนเนอร์ที่รันอยู่และเทียบเวลาสัมบูรณ์:
docker exec -it my_container date -uถ้ามันตรงกับ date -u บนโฮสต์ - ทุกอย่างเรียบร้อย หาปัญหาที่อื่น ถ้าคอนเทนเนอร์แสดงเวลาสัมบูรณ์ต่างออกไป นั่นคือสัญญาณของการตั้งค่าที่ไม่มาตรฐานและอาจเป็นอันตราย ซึ่งควรทบทวนทันที
ข้อผิดพลาดทั่วไป: อะไรที่ไม่ควรทำ
ประสบการณ์จากการสืบสวนเหตุการณ์รวมตัวเป็นรายการกับดักที่คนเหยียบซ้ำแล้วซ้ำเล่า มาดูกันเพื่อให้คุณหลีกเลี่ยง
ข้อผิดพลาดแรก: โทษพร็อกซีโดยสัญชาตญาณ
เราเริ่มด้วยสิ่งนี้และจะย้ำอีก คำว่า certificate หรือ signature ในข้อผิดพลาดเมื่อทำงานผ่านพร็อกซีสร้างความสงสัยต่อเครือข่ายและเกตเวย์โดยอัตโนมัติ อย่าหลง การกระทำแรกกับข้อผิดพลาดเหล่านี้คือเทียบเวลา ไม่ใช่เปลี่ยนปลายทาง ใช้เวลาสิบวินาทีและตัดสาเหตุที่ซ่อนอยู่ที่พบบ่อยที่สุดออกไป
ข้อผิดพลาดที่สอง: แก้เขตเวลาแทนเวลา
วิศวกรเห็นเวลาโลคอลแปลก ๆ ในบันทึกและเปลี่ยนเขตเวลา อาการในบันทึกเปลี่ยน แต่การเข้ารหัสก็ยังพังเหมือนเดิม เพราะเวลาสัมบูรณ์จริงใน UTC ยังเพี้ยนอยู่ วินิจฉัยผ่าน date -u และเปรียบเทียบกับค่าอ้างอิงเสมอ ไม่ใช่ผ่านการแสดงผลโลคอล
ข้อผิดพลาดที่สาม: คิดว่าการติดตั้งซิงค์คือการแก้ปัญหา
ติดตั้งแพ็กเกจ เห็นว่าบริการรัน ปิดงาน ผ่านไปหนึ่งสัปดาห์ความล้มเหลวกลับมา เพราะบริการไม่มีการเข้าถึงเซิร์ฟเวอร์เวลา การติดตั้งไม่เท่ากับการซิงค์ ตรวจสอบการเบี่ยงเบนจริงและ наличиแหล่งที่เลือกอยู่เสมอ
ข้อผิดพลาดที่สี่: แก้ไขนาฬิกาแบบกระชากกลางคัน
การกระโดดเวลาระบบด้วยคำสั่งตั้งค่าตรง ๆ อาจทำให้โปรเซสที่ทำงานอยู่ซึ่งพึ่งพาความเป็นโมโนโทนของเวลาพัง: timeout หมด เซสชันขาด ตัวจัดตารางทำงานผิดพลาด สิ่งที่ถูกต้องคือปล่อยให้เดมอนซิงค์ค่อย ๆ ปรับนาฬิกา การแก้ไขแบบกระชากยอมรับได้เฉพาะเมื่อมีการเลื่อนครั้งใหญ่มาก และต้องทำอย่างมีสติ
ข้อผิดพลาดที่ห้า: มองข้ามการแช่แข็งของ VM
ทีมไม่คำนึงว่าการย้าย สแนปช็อต และการหยุดชั่วคราวสร้างการเลื่อนในพริบตา สำหรับสภาพแวดล้อมเช่นนี้ ต้องมีเดมอนที่ทนทานต่อการกระโดด และการมอนิเตอร์การเบี่ยงเบนหลังการบำรุงรักษา ถ้าความล้มเหลวของคุณสัมพันธ์กับเวลาของการสำรองข้อมูลหรือการย้าย - นั่นคือคำตอบ
ข้อผิดพลาดที่หก: การควบคุมเวลาสองทาง
เกสต์เอเจนต์ของไฮเปอร์ไวเซอร์และเดมอนภายในทำงานพร้อมกัน นาฬิกากระตุก ความล้มเหลวมาเป็นระยะและทำซ้ำไม่ได้ เลือกกลไกเดียวและปิดอีกอัน สิ่งนี้รักษาบั๊กลอย ๆ ที่ทำให้เหนื่อยที่สุด
ข้อผิดพลาดที่เจ็ด: หน้าต่างแคบเกินไปโดยไม่มีกำไร
ถ้าคุณพัฒนา API ที่มีลายเซ็นคำขอ อย่าตั้งหน้าต่างเผื่อสามสิบวินาทีโดยไม่มีเหตุผลหนัก กำไรที่สมเหตุสมผลไม่กี่นาทีลดความไวต่อการไม่ตรงกันเล็กน้อยของไคลเอนต์ได้อย่างมาก โดยไม่เสียการป้องกันการเล่นซ้ำ สมดุลระหว่างความเข้มงวดและความเสถียรเป็นการตัดสินใจเชิงวิศวกรรม ไม่ใช่หลักคำสอน
เครื่องมือและแหล่งข้อมูล
รวบรวมคลังแสงที่ควรมีติดตัว เครื่องมือทั้งหมดเป็นมาตรฐานและถูกกฎหมาย สำหรับการดำเนินงานเชิงวิศวกรรมปกติ
บรรทัดคำสั่ง
- date -u - ดูเวลาสัมบูรณ์ทันที คำสั่งแรกเมื่อสงสัยอะไร
- timedatectl - สถานะการซิงค์และเขตเวลาในระบบที่มี systemd
- chronyc tracking และ chronyc sources - การวินิจฉัยเชิงลึกของ chrony: การเบี่ยงเบน แหล่งข้อมูล ความเสถียร
- curl -sI ... | grep -i date - เทียบเวลาผ่านเฮดเดอร์ Date ของ HTTP ทำงานได้แม้ที่ไม่มีเดมอน เหมาะสุดกับคอนเทนเนอร์เปล่าและการตรวจสอบผ่านเกตเวย์
การตรวจสอบเฉพาะภาษา
- ใน Python: บรรทัดเดียวที่แสดง utcnow และ timestamp เพื่อเทียบจากสภาพแวดล้อมที่แอปรันอยู่
- ใน Node: บรรทัดเดียวที่แสดง toISOString และ Date.now เพื่อดูเวลาผ่านสายตาของรันไทม์ของคุณเอง
- ถอดรหัส JWT โดยไม่ตรวจสอบลายเซ็น เพื่อดูฟิลด์ exp, nbf, iat ด้วยตาตัวเองและเทียบกับเวลาปัจจุบัน สิ่งนี้ขจัดความคาดเดา: คุณเห็นตรง ๆ ว่าโทเค็นหมดอายุตามนาฬิกาของคุณหรือไม่
สิ่งที่ควรมอนิเตอร์ตลอดเวลา
- การเบี่ยงเบนของนาฬิการะบบ เป็นเมตริกตัวเลขที่มีเกณฑ์เตือนและสัญญาณเตือน
- สถานะการมีแหล่งเวลาที่เลือก - ตัวชี้วัดบูลีนของสุขภาพการซิงค์
- ความถี่ของข้อผิดพลาด TLS และโทเค็น แยกตามโหนด - การพุ่งขึ้นบนโหนดเฉพาะมักชี้ไปที่นาฬิกาที่เพี้ยนของโหนดนั้น
โครงสร้างพื้นฐาน Proxeon
เมื่อทำงานผ่านเกตเวย์ Proxeon เราแนะนำให้ฝังการตรวจสอบเวลาในสคริปต์เริ่มต้นของโหนดทำงาน บรรทัดเดียวที่เทียบเฮดเดอร์ Date ผ่านเกตเวย์ตอนเริ่มต้น - และคุณจะจับการไม่ตรงกันได้ก่อนคำขอแรก สิ่งนี้ราคาถูกและลดสัดส่วนการติดต่อฝ่ายสนับสนุนที่ต้นเหตุอยู่ที่นาฬิกาฝั่งไคลเอนต์ ไม่ใช่พร็อกซีลงอย่างมาก
กรณีศึกษาและผลลัพธ์
ทฤษฎีมีชีวิตในเรื่องจริง มาดูกรณีศึกษาทั่วไปจากประสบการณ์ - ตัวเลขปัดเศษ รายละเอียดไม่ระบุตัวตน แต่รูปแบบเป็นจริงทั้งหมด
กรณีแรก: ความล่มสลายของตัวดึงข้อมูลตอนกลางคืนหลังการสำรองข้อมูล
ทีมเก็บข้อมูลผ่านพร็อกซีตลอด 24 ชั่วโมง ทุกคืนประมาณสามโมง กำแพงข้อผิดพลาด certificate is not yet valid เริ่มขึ้น พอเช้าทุกอย่างหายไปเอง วิศวกรโทษพูลพร็อกซีอยู่สองสัปดาห์ เปลี่ยนปลายทาง เขียนคำร้อง คำตอบมาเมื่อมีคนสังเกตความสัมพันธ์: ความล้มเหลวเริ่มตรงเวลาสำรองข้อมูล VM ตอนกลางคืน précis
ไฮเปอร์ไวเซอร์แช่แข็ง VM หนึ่งนาทีครึ่งถึงสองนาทีเพื่อสแนปช็อตที่สอดคล้อง หลังปลุก นาฬิกาช้าไปตามนาทีเหล่านั้น และเกสต์เอเจนต์ปรับไม่ทันที ในหน้าต่างระหว่างปลุกกับการแก้ไข TLS ปฏิเสธใบรับรองสดใหม่ว่าไม่ถูกต้อง - เพราะตามนาฬิกาที่ช้า พวกมันเริ่มมีผลในอนาคต วิธีแก้คือเปลี่ยนไปใช้ chrony ที่ลู่เข้าเร็วหลังการกระโดดและมอนิเตอร์การเบี่ยงเบนทันทีหลังการสำรองข้อมูล ความล้มเหลวตอนกลางคืนหายไปทั้งหมด เวลาวินิจฉัยปัญหาคล้ายกันในอนาคตลดจากหลายวันเหลือไม่กี่นาที
กรณีที่สอง: ร้อยโหนดที่แยกออกจากกัน
องค์กรแจกจ่ายฝูงร้อยโหนดทำงานจากอิมเมจเดียว สัปดาห์แรกทุกอย่างทำงาน จากนั้นความล้มเหลวลอย ๆ ของลายเซ็นคำขอเริ่มขึ้นบนโหนดสุ่ม - request timestamp too skewed ทำซ้ำไม่ได้: รีสตาร์ทงาน มันอาจผ่านบนโหนดอื่น
สาเหตุ - ในอิมเมจไม่ได้เปิดใช้งานการซิงค์เวลา ร้อยโหนดคลาดเคลื่อนตามควอตซ์ของตัวเอง ตัวที่เร็วที่สุดผ่านไปหนึ่งสัปดาห์เกินหน้าต่างเผื่อในลายเซ็น การตรวจสอบ chronyc tracking ทั่วทั้งฝูงแสดงการเบี่ยงเบนตั้งแต่เสี้ยววินาทีถึงสิบห้าวินาที หลังเปิดใช้งานและตรวจสอบการทำงานจริงของการซิงค์บนทุกโหนด บวกการเพิ่มเมตริกการเบี่ยงเบนในมอนิเตอร์ ความล้มเหลวหยุด ข้อสรุปของทีม: ในการแจกจ่ายจำนวนมาก ให้ตรวจสอบการซิงค์จริง ไม่ใช่แค่การติดตั้ง
กรณีที่สาม: นักพัฒนาที่ไม่มีใครเข้าใจ
วิศวกรคนหนึ่งบ่นว่าที่เครื่องตัวเอง การยืนยันตัวตนด้วย TOTP เข้าแผงควบคุมไม่ผ่าน แม้คนอื่นจะทำงานได้ ป้อนรหัสถูก แต่ระบบปฏิเสธ สงสัยว่าเป็นปัญหาบัญชีของเขา
ปรากฏว่าเขาสัปดาห์ก่อนเลื่อนเวลาระบบบนเวิร์กสเตชันด้วยมือเพื่อทดสอบแอปอื่นและลืมคืนค่า และปิดการซิงค์ไปด้วย นาฬิกาเบี่ยงไปเกือบหนึ่งนาที TOTP ที่มีหน้าต่างสามสิบวินาทีจึงไม่ตรงอีกต่อไป การเปิดการซิงค์อัตโนมัติแก้ทันที บทเรียน: ค่าเผื่อแคบของ TOTP เป็นตัวจับการไม่ตรงกันในตัว ถ้ารหัสไม่ตรงกัน สิ่งแรกที่ควรดูคือนาฬิกา
กรณีที่สี่: คอนเทนเนอร์กับเขตเวลาผิด
ในบันทึกของแอปในคอนเทนเนอร์ เวลาเดินเบี่ยงไปสามชั่วโมงจากโฮสต์ วิศวกรคิดว่านาฬิกาคอนเทนเนอร์เพี้ยน และใช้เวลาหนึ่งวันพยายามตั้งค่าซิงค์ภายใน เกือบให้สิทธิ์พิเศษเกินจำเป็นกับคอนเทนเนอร์
การตรวจ date -u ทั้งภายในและภายนอกแสดงเวลาสัมบูรณ์เดียวกัน ความเบี่ยงอยู่แค่การแสดงผล: อิมเมจพื้นฐานมีเขตเวลาหนึ่ง โฮสต์อีกหนึ่ง การเข้ารหัสทำงานไม่มีที่ติเพราะใน UTC ทุกอย่างตรงกัน ไม่มีปัญหาจริงเลย - มีแค่ความสับสนด้านความงามในบันทึก บทเรียนราคาหนึ่งวัน: แยกเวลาสัมบูรณ์ออกจากการแสดงผลเสมอ
คำถามที่พบบ่อย: คำตอบเชิงลึกสำหรับคำถามที่พบบ่อย
พร็อกซีเองสามารถทำให้นาฬิกาผมเพี้ยนหรือแทนที่มันใน TLS ได้หรือไม่?
ในสถานการณ์ปกติของการทำงานผ่านเกตเวย์ - ไม่ พร็อกซีส่งต่อไบต์ระหว่างคุณกับเซิร์ฟเวอร์ปลายทาง การตรวจสอบอายุใบรับรอง ฟิลด์ exp และ nbf หน้าต่างลายเซ็น เกิดขึ้นฝั่งคุณหรือฝั่งเซิร์ฟเวอร์ปลายทาง โดยอ้างอิงนาฬิกาของพวกเขาเอง ดังนั้นเมื่อมีข้อผิดพลาดที่ดูเหมือนเวลา สิ่งแรกที่ต้องสงสัยคือนาฬิกาท้องถิ่นของโหนดทำงาน ไม่ใช่เกตเวย์ พร็อกซีเพียงยืดห่วงโซ่และเลื่อนความสงสัยไปที่ตรงกลางทางจิตวิทยา
เวลาต้องแม่นยำแค่ไหนถึงจะทำงานได้?
สำหรับ TLS กำไรโดยปกติมาก - หน้าต่างความถูกต้องของใบรับรองวัดเป็นวัน และแม้การเบี่ยงไม่กี่นาทีก็มักผ่านไปไม่สังเกต ยกเว้นช่วงที่ขอบเขตการต่ออายุ สำหรับ JWT ทุกอย่างขึ้นกับอายุโทเค็น: กับโทเค็นสั้น แม้วินาทีก็มีบทบาท สำหรับลายเซ็นคำขอ หน้าต่างทั่วไปคือนาที แต่ควรเก็บการเบี่ยงให้อยู่ในระดับวินาที TOTP ต้องการมากที่สุด - หลายสิบวินาที คำแนะนำสากล: เก็บการเบี่ยงให้อยู่ในวินาทีเดียว แล้วคุณจะปลอดภัยจากกลไกทั้งหมดพร้อมกัน
ทำไมใบรับรองแสดงวันที่ถูกต้อง แต่ไคลเอนต์บอกว่ายังไม่ถูกต้อง?
เพราะไคลเอนต์เปรียบเทียบวันที่ของใบรับรองไม่ใช่กับความจริงสัมบูรณ์ แต่กับนาฬิกาท้องถิ่นของคุณ ถ้านาฬิกาของคุณช้าและแสดงช่วงเวลาก่อน notBefore สำหรับไคลเอนต์ใบรับรองยังไม่มาถึง วันที่ในใบรับรองเองสมบูรณ์แบบ คำตอบอยู่ที่การเทียบ date -u ของคุณกับค่าอ้างอิงเสมอ นี่คือสาเหตุความงงที่พบบ่อยที่สุดของวิศวกร
ต้องติดตั้งเดมอนซิงค์ในคอนเทนเนอร์หรือไม่?
ไม่ คอนเทนเนอร์ใช้เวลาของเคอร์เนลโฮสต์ ดังนั้นต้องซิงค์โฮสต์ การติดตั้งเดมอนในคอนเทนเนอร์ไม่มีประโยชน์และต้องการสิทธิ์พิเศษอันตรายในการเปลี่ยนเวลาระบบ ที่ส่งผลต่อทั้งโฮสต์ โมเดลที่ถูกต้องคือโฮสต์ที่ซิงค์แล้วและคอนเทนเนอร์มากมายที่เห็นเวลาถูกต้องโดยอัตโนมัติ ในออร์เคสเตรเตอร์ การซิงค์เกิดขึ้นในแต่ละโหนดโฮสต์
จะแยกปัญหากับเวลาออกจากปัญหาพร็อกซีหรือเครือข่ายจริงได้อย่างไร?
เริ่มด้วยการตรวจสอบเวลา - ใช้เวลาสิบวินาที เทียบ date -u กับค่าอ้างอิงและกับเฮดเดอร์ Date ของ HTTP ผ่านเกตเวย์ของคุณ ถ้าการเบี่ยงน้อยแต่ข้อผิดพลาด TLS และโทเค็นยังอยู่ - จากนั้นค่อยไปที่การวินิจฉัยเครือข่าย ถ้าการเบี่ยงมาก - คุณพบสาเหตุแล้ว อาการเอกลักษณ์ของปัญหาเวลาคือข้อผิดพลาดมีคำว่า not yet valid, expired, skewed, signature กับใบรับรองที่ยังดีและโทเค็นที่สดใหม่
ควรทำอะไรทันทีหลังปลุกหรือย้าย VM?
ตรวจสอบว่าเดมอนซิงค์ปรับนาฬิกาเร็วหรือไม่ สำหรับสภาพแวดล้อมที่มีการแช่แข็ง chrony เป็นที่นิยมกว่า ซึ่งรับมือกับการกระโดดได้ดี ตรวจสอบ chronyc tracking และดูว่า System time กลับมาในระดับเสี้ยววินาที แนวปฏิบัติที่ดีคือบังคับเริ่มการตรวจสอบการเบี่ยงหลังการบำรุงรักษาและไม่ส่งคำขอที่ลงลายเซ็นสำคัญจนกว่านาฬิกาจะลู่เข้า
เขตเวลาผิดมีผลต่อการทำงานของ TLS และโทเค็นหรือไม่?
ไม่ หากเวลาสัมบูรณ์ใน UTC ถูกต้อง การเข้ารหัสทั้งหมดดำเนินการกับ UTC และเขตเวลาเป็นเพียงการแสดงผลสำหรับมนุษย์ เขตเวลาผิดจะทำให้คุณสับสนในบันทึก แต่ไม่ล้ม TLS, JWT หรือลายเซ็น ด้วยเหตุนี้จึงต้องวินิจฉัยผ่าน UTC ไม่ใช่เวลาโลคอล ความสับสนระหว่างเขตเวลากับเวลาสัมบูรณ์เป็นกับดักคลาสสิก
จะฝังการตรวจสอบเวลาในเวิร์กโฟลว์ผ่านพร็อกซีได้อย่างไร?
เพิ่มบรรทัดเดียวในสคริปต์เริ่มต้นของโหนด: ขอเฮดเดอร์ Date ผ่านเกตเวย์ Proxeon ของคุณและเทียบกับ date -u ท้องถิ่น ถ้าต่างกันเกินเกณฑ์ หยุดการเริ่มต้นและส่งสัญญาณเตือน บวกกับการส่งการเบี่ยงของนาฬิการะบบเข้าในมอนิเตอร์เป็นเมตริกถาวรที่มีเกณฑ์ สองมาตรการนี้จับเหตุการณ์เวลาเกือบทั้งหมดก่อนที่มันจะกลายเป็นความล้มเหลว TLS และโทเค็น