9 คะแนน โดย GN⁺ 2026-01-23 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • พบกรณีที่ มีการส่งแพ็กเก็ตนับร้อยชุดเมื่อกดคีย์เพียงครั้งเดียว ในเซสชัน SSH และได้ไล่หาสาเหตุของปัญหานี้
  • ผลการวิเคราะห์ด้วย tcpdump พบว่าแพ็กเก็ตส่วนใหญ่เป็น ข้อความซ้ำขนาด 36 ไบต์ และเกิดขึ้นห่างกันราว 20ms
  • สาเหตุมาจากฟีเจอร์ “keystroke timing obfuscation” ที่ถูกเพิ่มเข้ามาใน SSH เมื่อปี 2023 โดยจะส่ง แพ็กเก็ต ‘chaff’ (SSH2_MSG_PING) จำนวนมากเพื่อซ่อนจังหวะการพิมพ์ของผู้ใช้
  • หากปิดฟีเจอร์นี้ หรือแก้ไม่ให้เซิร์ฟเวอร์โฆษณาส่วนขยาย [email protected] จะทำให้ การใช้ CPU และแบนด์วิดท์ลดลงเหลือน้อยกว่าครึ่ง
  • เป็นกรณีตัวอย่างที่แสดงให้เห็นว่าฟีเจอร์ความปลอดภัยของ SSH อาจกลายเป็นภาระหนักใน แอปพลิเคชันที่ต้องการประสิทธิภาพแบบเรียลไทม์สูง (เช่น เกม)

การค้นพบปัญหา

  • ระหว่างทดสอบ TUI ของเกมประสิทธิภาพสูง ที่รันผ่าน SSH พบว่าการกดคีย์เพียงครั้งเดียวทำให้เกิด แพ็กเก็ต 270 ชุด
    • จากผล tcpdump พบว่า 66% เป็นข้อความขนาด 36 ไบต์, 33% เป็น TCP ACK และที่เหลือเป็นข้อมูลอื่นเพียงเล็กน้อย
    • มีการส่งข้อมูลเฉลี่ย 90 แพ็กเก็ต/วินาที หรือทุก ๆ ประมาณ 11ms
  • ระหว่างการทดสอบ มีการตั้งค่าเซิร์ฟเวอร์ผิดพลาดจนส่งเพียงข้อความ “your screen is too small” เท่านั้น และในตอนนั้น การใช้ CPU และแบนด์วิดท์ลดลงครึ่งหนึ่ง
    • แม้ไม่ควรมีการส่งข้อมูลของเกมแล้ว การใช้ CPU ก็ควรใกล้ 0% แต่ยังคงอยู่ราว 50%
    • ทำให้เกิดข้อสงสัยว่าอาจเป็น โอเวอร์เฮดด้านการสื่อสารของ SSH เอง

กระบวนการสืบสวน

  • ใช้ tcpdump เปรียบเทียบทราฟฟิก SSH ระหว่างสถานะปกติกับสถานะผิดพลาด
    • แม้อยู่ในสถานะผิดพลาดก็ยังพบว่า แพ็กเก็ตขนาด 36 ไบต์ยังคงถูกส่งต่อเนื่องทุก ๆ 20ms
    • ตรวจพบแพตเทิร์นเดียวกันใน SSH client มาตรฐานของ MacOS ด้วย
  • เมื่อนำไฟล์ pcap ไปวิเคราะห์ด้วย Claude Code พบว่า
    • จากแพ็กเก็ตทั้งหมด 413,703 ชุด มี 66% ที่ขนาด 36 ไบต์ และ 34% เป็น ACK ขนาด 0 ไบต์
    • แพ็กเก็ตเหล่านี้ถูกสร้างขึ้นโดยฝั่ง SSH client เป็นหลัก

สาเหตุที่แท้จริง

  • ในล็อกดีบักของ SSH (ssh -vvv) พบข้อความต่อไปนี้
    obfuscate_keystroke_timing: starting: interval ~20ms
    obfuscate_keystroke_timing: stopping: chaff time expired (101 chaff packets sent)
    
    • ค่า ช่วงห่าง 20ms และ แพ็กเก็ต chaff จำนวนหลายสิบถึงกว่าร้อยชุด ตรงกับแพตเทิร์นที่สังเกตได้จริง
  • ต้นเหตุคือ ฟีเจอร์ปกปิดจังหวะการกดคีย์ ที่ถูกเพิ่มเข้ามาใน SSH เมื่อปี 2023
    • ฟีเจอร์นี้ส่ง แพ็กเก็ต ‘chaff’ แบบสุ่ม เพื่อป้องกันไม่ให้รูปแบบความเร็วการพิมพ์ของผู้ใช้รั่วไหล
    • แม้จะมีประโยชน์ด้านความปลอดภัย แต่ในสภาพแวดล้อมที่ latency สำคัญ ก็ทำให้เกิดภาระเกินความจำเป็น

วิธีแก้ไข

  • ฝั่งไคลเอนต์สามารถปิดฟีเจอร์นี้ได้ด้วยตัวเลือก ObscureKeystrokeTiming=no
    • หลังใช้งานแล้ว การใช้ CPU และแบนด์วิดท์ลดลงอย่างมาก ขณะที่การส่งข้อมูลยังทำงานเป็นปกติ
  • สำหรับฝั่งเซิร์ฟเวอร์ มีการแก้โดยนำการโฆษณาส่วนขยาย [email protected] ออกจากไลบรารี SSH ของ Go
    • หลังย้อนคอมมิตที่เกี่ยวข้องแล้วทดสอบ พบว่า
      • การใช้ CPU 29.9% → 11.6% ,
        system call 3.10s → 0.66s,
        การประมวลผลเข้ารหัส 1.6s → 0.11s,
        แบนด์วิดท์ 6.5Mbit/s → 3Mbit/s
    • ประสิทธิภาพดีขึ้น มากกว่า 50%

ประสบการณ์ดีบักด้วย LLM

  • ใช้ Claude Code ช่วยทำงานวิเคราะห์ tcpdump และ tshark แบบอัตโนมัติ ทำให้จำกัดวงหาสาเหตุของปัญหาได้รวดเร็ว
    • สามารถเฝ้าดูขั้นตอนการรันคำสั่งแบบเรียลไทม์และ รักษา mental model ของปัญหาไว้ได้
  • ส่วน ChatGPT เคยตัดสินพฤติกรรมของ SSH ว่า “ปกติ” อย่างผิดพลาด ซึ่งสะท้อนให้เห็น ความแตกต่างระหว่างโมเดล
  • แม้ LLM จะยังไม่สามารถแทนที่กระบวนการแก้ปัญหาได้ทั้งหมด แต่ก็แสดงให้เห็นถึง ประสิทธิภาพสูงในฐานะเครื่องมือวิเคราะห์เสริม
  • เป็นตัวอย่างของการผสาน การให้เหตุผลของมนุษย์กับการวิเคราะห์ของ LLM เพื่อแก้ปัญหาประสิทธิภาพเครือข่ายที่ซับซ้อน

1 ความคิดเห็น

 
GN⁺ 2026-01-23
ความคิดเห็นใน Hacker News
  • รู้สึกน่ากลัวนิดหน่อยที่จะ fork ไลบรารี crypto ของ go
    กำลังคิดอยู่ว่าจะรักษาแพตช์เล็ก ๆ ของตัวเองให้ปลอดภัยได้อย่างไร
    จริง ๆ แล้วคิดว่าฟีเจอร์แบบนี้ควรถูก upstream เป็นออปชันของไลบรารี ssh
    ในสภาพแวดล้อมที่ไม่น่าเชื่อถือ การส่งแพ็กเก็ต chaff (แพ็กเก็ตรบกวน) เป็นค่าเริ่มต้นก็ดี แต่หลายกรณีก็อยากประหยัดแบนด์วิดท์

    • การควบคุมด้วยวิธีที่ไม่ประกาศฟีเจอร์ออกมาเป็นแนวทางที่ เปราะบางเกินไป
      ทางออกที่ถูกต้องคือเพิ่มออปชันให้เซิร์ฟเวอร์ส่งสัญญาณไปยังไคลเอนต์ได้ว่า “ไม่จำเป็น” แล้วให้ไคลเอนต์เลือกรับหรือเตือนได้
    • จริง ๆ แล้วมีพฤติกรรมคล้ายกันนี้อยู่แล้ว
      ใช้กับเฉพาะ TTY session และไคลเอนต์สามารถปิดได้
      เพียงแต่กรณีนี้เป็นสถานการณ์พิเศษที่เซิร์ฟเวอร์รู้ล่วงหน้าว่าการเชื่อมต่อนี้ไม่สำคัญ
      โดยส่วนใหญ่แล้วไคลเอนต์คาดหวังให้การตั้งค่า ObscureKeystrokeTiming ถูกคงไว้
    • ถึงอย่างนั้นก็คิดว่าการเปลี่ยนแปลงนี้มี โอกาสสูงที่จะถูกปฏิเสธ
      ไลบรารี crypto เป็น codebase ที่มีจุดยืนชัดมาก จนถึงขั้นไม่เปิดให้เปลี่ยนลำดับ TLS cipher suite
    • แม้ในสภาพแวดล้อมที่เชื่อถือได้ก็ยังมี ภัยคุกคาม อยู่
      นี่ดูเป็นกรณีใช้งานของ SSH ที่ เฉพาะทางมาก
      ถ้าเปิดให้ใช้กว้างเกินไปก็อาจเกิดสถานการณ์แบบ “ตั้งค่าแล้วลืม” จนทำให้ความปลอดภัยอ่อนลงแทน
    • สมัยก่อนเคยใช้ ZX80 ที่มี RAM 1KB
      เคยสื่อสารผ่านโมเด็ม 1200bps ด้วย และ 56K modem ก็แทบจะเป็นคำโฆษณาเกินจริง
      ราวปี 1994 ตอนทำงานที่วิทยาลัยทหารในอังกฤษได้เจอ WWW ครั้งแรก และตอนนั้นคิดว่า “ก็ไม่ค่อยน่าประทับใจนะ”
      พอมองย้อนกลับไปก็ทึ่งกับ ความเปลี่ยนแปลงของยุคสมัย จริง ๆ
  • เพิ่งเคยได้ยิน ฟีเจอร์ obfuscation นี้ น่าสนใจดี
    เวลาดีบักพฤติกรรมของ ssh การแพตช์ cipher แบบ “None” เพื่อดูเนื้อหาแพ็กเก็ตตรง ๆ ก็เป็นวิธีที่ดี
    ถ้าเป็น เกมบนเทอร์มินัล ที่ความปลอดภัยไม่สำคัญแต่ประสิทธิภาพสำคัญ ก็อาจพิจารณาใช้ telnet ไปเลย

  • ไม่เคยรู้มาก่อนว่า SSH ทำแบบนี้ด้วย
    เข้าใจได้ว่าทำไมถึงเปิดเป็นค่าเริ่มต้น แต่ในสภาพแวดล้อมของผม/ฉันน่าจะเหมาะกับการปิด

    1. แทบไม่มีโอกาสต้องพิมพ์ความลับผ่าน SSH โดยตรง
    2. ไม่มีเหตุผลที่ผู้โจมตีระดับรัฐจะมาดักจับคีย์สโตรกของผม/ฉัน
    3. เป็นการเชื่อมต่อข้ามทวีป จึงสำคัญที่จะ ประหยัดแบนด์วิดท์
      เลยกำลังจะตั้งค่า ObscureKeystrokeTiming=no มีเหตุผลอะไรไหมที่ไม่ควรทำแบบนั้น?
    • ทัศนคติด้านความปลอดภัยแบบมองโลกในแง่ดีเกินไปนั้นอันตราย
      (1) ไม่ใช่ว่าจะบอกได้เสมอว่ามนุษย์กำลังป้อนความลับเมื่อไร และกิจกรรมทั้งหมดอาจถูก วิเคราะห์จากรูปแบบ ได้
      (2) นี่เป็นการโจมตีที่ทำได้แม้ในระดับห้องแล็บมหาวิทยาลัย — ดู งานวิจัย USENIX และ กรณีศึกษา
      (3) ในอินเทอร์เน็ตที่ทราฟฟิกวิดีโอครองสัดส่วนหลัก การยอมลดความปลอดภัยเพื่อประหยัดข้อมูลคีย์สโตรกไม่กี่ไบต์นั้นไม่มีความหมาย
    • ความลับที่พิมพ์บ่อยใน tty SSH connection คือ รหัสผ่าน sudo
      ถ้าผู้โจมตีวิเคราะห์จังหวะการพิมพ์ได้ ก็อาจเดารูปแบบของคำสั่งและรหัสผ่านที่เข้ารหัสไว้ได้
      แน่นอนว่าการถอดรหัสยังยากเพราะ session key เปลี่ยนทุกครั้ง แต่ก็ยังมีความเป็นไปได้
      ผม/ฉันเองก็ copy จาก password manager มาวางสำหรับรหัสผ่านส่วนใหญ่
    • ไม่มีทางมั่นใจได้ว่าข้อความ plaintext ที่รั่วออกมาจะไม่มีประโยชน์ต่อผู้โจมตี
      คนส่วนใหญ่รู้สึกว่าไม่มีปัญหาอะไรแม้จะ ปิดฟีเจอร์ความปลอดภัย ของ SSH แต่ที่จริงอาจแค่โชคดี
      ถ้าต้องการประสิทธิภาพจริง ๆ ใช้ Telnet ไปเลย ถ้าต้องการความปลอดภัยจริง ๆ ใช้ ContainerSSH + OAuth2 จะดีกว่า
  • เมื่อปี 2004 เคยทำวิจัยเรื่อง การวิเคราะห์ความหน่วงระหว่างคีย์สโตรก ของ SSH session เพื่อเดาคำสั่ง
    ดู เอกสารการวิเคราะห์ในตอนนั้น
    แพตช์ปี 2023 ก็เท่ากับมาแก้ปัญหานั้นได้ในที่สุด

    • จำได้ว่าที่งานประชุมแฮ็ก HAL2001 Dug Song กับ Solar Designer เคยนำเสนอการวิเคราะห์ timing ของ SSH
      เอกสารนำเสนอ
      เวลาผ่านไปเร็วจริง ๆ
  • ไม่ค่อยแน่ใจว่า Claude ช่วยในการดีบักจริงแค่ไหน
    ผู้เขียนดูเหมือนจะรู้อยู่แล้วว่าควรไปทางไหน และ Claude ก็เหมือนแค่คอยเห็นด้วย
    เวลาที่ Claude พูดอะไรอย่าง “Holy Cow!” มัน ชวนรำคาญ นิดหน่อย

    • ถึงอย่างนั้น ถ้ามันช่วยจัดระเบียบความคิดได้แบบ Rubber Duck Debugging ก็ถือว่ามีคุณค่า
      เวลาผม/ฉันใช้ Claude ดีบักการทำงานของระบบ ถึงจะไม่ได้คำตอบตรง ๆ แต่ก็ช่วย จัดความเข้าใจและรักษาแรงจูงใจ ได้
      Rubber Duck Debugging บนวิกิ
    • Claude เร็วกว่าผม/ฉันมากในการ ดึงฟิลด์จาก pcap หรือจัดการ awk
    • AI เก่งมากในการ จับบุคลิกจากข้อความ
      จากที่ผู้เขียนชอบปฏิกิริยาแบบ “holy cow” แล้วเอาไปใส่ในบล็อก ก็ดูเหมือน Claude อ่านบรรยากาศได้ดี
    • บางทีการใส่ บุคลิก ให้เครื่องมือพัฒนาอาจไม่ใช่ความคิดที่ดีนัก
  • ถ้าใช้ TCP_CORK ก็ลดจำนวนแพ็กเก็ตได้โดยไม่ต้องเพิ่มความหน่วง
    การปิด TCP_NODELAY ก็เป็นวิธีหนึ่ง แต่ต้องแลกกับ latency ที่เพิ่มขึ้น

    • เพิ่งเคยได้ยิน TCP_CORK น่าสนใจดี
      เมื่อ cork socket แล้ว kernel จะบัฟเฟอร์ข้อมูลไว้จนกว่าจะ uncork หรือถึง MSS แล้วค่อยส่ง
      กล่าวคือเป็นการ รวมแพ็กเก็ตแล้วส่ง
      ข้อมูลอ้างอิง
    • ไม่เคยรู้จัก TCP_CORK มาก่อน แต่ดูมีประโยชน์มาก
      น่าจะยังรับ ping ได้เหมือนเดิม แต่ลดจำนวนครั้งในการส่ง pong ได้
      เคยใช้ TCP_NODELAY แล้ว แต่ latency สูงขึ้น เลยไม่เหมาะกับเกมของผม/ฉัน
      โพสต์ HN ก่อนหน้า
    • แต่ chaff packet ถูกส่งทุก 20ms เลยสงสัยว่า TCP_CORK จะรวมมันได้จริงไหม
      เพื่อจุดประสงค์ด้าน obfuscation แล้ว การ coalescing ความหน่วง น่าจะทำไม่ได้
  • วลี “The smoking gun!” ตลกดี
    ผม/ฉันไม่ใช่เจ้าของภาษาอังกฤษ แต่ Claude ใช้บ่อยจนได้เรียนรู้คำนี้ครั้งแรก
    ตอนนี้มันกำลัง แพร่เหมือนคำฮิต ไปแล้วจริง ๆ

  • รู้สึกเสียดายที่พึ่ง LLM
    เรื่องนี้แค่จับแพ็กเก็ตด้วย Wireshark ก็น่าจะแก้ได้เร็วกว่า
    SSH dissector ก็ค่อนข้างสมบูรณ์แล้ว

    • ผม/ฉันเองก็ไม่ได้ชอบ LLM มาก แต่ถ้าดู SSH packet ใน Wireshark ส่วนใหญ่ก็เห็นแค่ แพ็กเก็ตที่เข้ารหัส เลยไม่ได้ข้อมูลที่มีประโยชน์มาก
      แค่จับหนึ่งคีย์สโตรกด้วย tcpdump ก็ได้แพ็กเก็ตเข้ารหัสเป็นร้อยแล้ว
      สุดท้ายผู้เขียนก็ได้เรียนรู้อะไรน่าสนใจและเอามาแชร์เพราะ LLM แบบนี้ก็มีความหมาย
    • SSH dissector ไม่ได้สมบูรณ์แบบ
      หลังข้อความ NEWKEYS แล้วจะ parse ต่อไม่ได้ และถึงจะแพตช์ให้ใช้การเข้ารหัส none ก็ยังตีความ flow ได้ไม่ครบ
      ยังมีช่องให้ปรับปรุง
    • ท่าทีแบบ “แค่ดู Wireshark ก็พอ” ฟังดูเหมือน gatekeeping
      การใช้เครื่องมือเพื่อเรียนรู้ก็มีคุณค่าเพียงพอ
    • SSH เป็น โปรโตคอลด้านความปลอดภัย ตั้งแต่ชื่อเลย
      การจับแพ็กเก็ตอย่างเดียวจึงยากจะได้ข้อมูลที่มีนัยสำคัญ
    • ผู้เขียนไม่รู้จักตัววิเคราะห์แพ็กเก็ต SSH และเลือกใช้ เครื่องมือทั่วไป (LLM) แทน
      ไม่เห็นว่าทำไมถึงต้องมองว่าน่าเสียดาย
  • ในปี 2023 SSH ได้เพิ่มฟีเจอร์ การทำให้จังหวะคีย์สโตรกสับสน
    เพราะสามารถเดาตัวอักษรจากความเร็วในการพิมพ์ได้ SSH จึงผสม chaff packet เข้าไปเพื่อให้ผู้โจมตีแยกไม่ออก
    แต่เรื่องนี้ดูเหมือนเป็นแนวทางที่ผิด
    ถ้าอยากทำจริง ๆ ก็แค่ส่งทุกคีย์สโตรกที่ ช่วง 50ms ก็พอ

    • ความหน่วง 50ms ดูเหมือนจะ น่าหงุดหงิดมาก ในการใช้งานจริง
    • ไม่ชัดว่าการส่งที่ช่วง 50ms หมายถึงเปลี่ยนจาก 20ms เป็น 50ms หรือหมายถึง ส่งต่อเนื่องด้วยช่วงคงที่
      ตอนนี้การทำงานจริงคือรวมเป็นชุดทุก 20ms และถ้าไม่มีการพิมพ์ต่อสักพักก็หยุดส่ง chaff
  • แก่นของ SSH คือ ความปลอดภัย แต่ถ้าไม่ต้องการความปลอดภัยก็สงสัยว่าจะใช้ SSH ไปทำไม
    อย่างเช่น netcat(nc) ก็มีติดตั้งมาเป็นค่าเริ่มต้นในแทบทุกแพลตฟอร์ม

    • การบอกว่า “ความปลอดภัยมาก่อน” ไม่ได้แปลว่านั่นคือทั้งหมด
      SSH ยังมี ปัจจัยอื่น อย่างประสิทธิภาพและความสะดวกด้วย
      ผู้เขียนแค่บอกว่าไม่ต้องการฟีเจอร์ การทำให้คีย์สโตรกสับสน (privacy) เท่านั้น
      เขา/เธออาจยังต้องการการเข้ารหัสหรือการรับประกันความถูกต้องครบถ้วนอยู่
      กล่าวคือยังคงฟีเจอร์ความปลอดภัยส่วนใหญ่ของ SSH เอาไว้ และปิดเพียงบางส่วน
    • ตอนนี้ Windows ก็มี SSH มาให้แล้ว ดังนั้นคำว่า “ทุกแพลตฟอร์มมี nc” จึง ไม่ถูกต้องนัก