1 คะแนน โดย GN⁺ 2024-09-18 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • ใน Little Snitch 6.1 การเข้ารหัส DNS อาจล้มเหลวได้ในบางสถานการณ์ แต่ภายหลังสรุปได้ว่าไม่ใช่ปัญหาของ macOS โดยรวม และเป็นปัญหาเฉพาะของเวอร์ชันดังกล่าว ซึ่งได้รับการแก้ไขแล้วใน 6.1.1
  • เพื่อให้ทำงานได้ถูกต้อง คำขอ DNS ของ macOS ต้องถูกส่งต่อไปยัง DNS proxy ของ Little Snitch และ proxy จะทำการ query แบบเข้ารหัส
  • ระหว่างการตรวจสอบ พบว่าคำขอบางส่วนจาก legacy API ระดับต่ำ ไม่ไปถึง proxy และส่ง query แบบไม่เข้ารหัสผ่าน UDP 53 ไปยัง nameserver เริ่มต้นของระบบ
  • วิธีทำซ้ำคือเปิดการเข้ารหัส DNS ใน Little Snitch, รัน Wireshark ด้วยตัวกรอง port 53 แล้วเรียก getaddrinfo("dnsproxytest.com") ใน Xcode playground
  • การ query ที่อิงกับ API ระดับสูง เช่นใน Safari และ Chrome ดูเหมือนไม่ได้รับผลกระทบในตอนแรก และ Firefox ดูเหมือนจะได้รับผลกระทบ แต่ขอบเขตสุดท้ายสรุปว่าเป็นปัญหาที่ DNS proxy ของ Little Snitch 6.1

การล้มเหลวของการเข้ารหัส DNS ที่เกิดขึ้นใน Little Snitch 6.1

  • ฟีเจอร์การเข้ารหัส DNS ของ Little Snitch 6 จะ route การ resolve ชื่อโฮสต์ผ่าน Little Snitch เพื่อประมวลผลในรูปแบบ เข้ารหัส
  • เพื่อทำเช่นนั้น Little Snitch จะลงทะเบียน DNS proxy และ macOS ต้องส่งคำขอ DNS ทั้งหมดไปยัง proxy ดังกล่าว
  • พบว่าคำขอ DNS บางส่วน โดยเฉพาะคำขอผ่าน legacy API ระดับต่ำ บางตัว ไม่ถูกรับโดย proxy
  • คำขอเหล่านั้นอาจถูกส่งไปยัง nameserver เริ่มต้นของระบบในรูปแบบไม่เข้ารหัส และสามารถตรวจสอบได้ใน Wireshark ว่าเป็นทราฟฟิก UDP พอร์ต 53
  • ทราฟฟิกการ query ดังกล่าวไม่แสดงใน Little Snitch Network Monitor เนื่องจากการ query ข้าม network filter ไปทั้งหมด

ขั้นตอนการทำซ้ำและความคืบหน้าของการอัปเดต

  • ขั้นตอนการทำซ้ำ

    • เปิดใช้งาน DNS encryption ในการตั้งค่า Little Snitch
    • รัน Wireshark ด้วย capture filter port 53
    • รันการ query dnsproxytest.com ด้วย getaddrinfo ใน Xcode playground
    • การ query dnsproxytest.com อาจปรากฏในรูปแบบไม่เข้ารหัสบน UDP 53
  • ขอบเขตผลกระทบเบื้องต้น

    • การ query DNS ผ่าน API ระดับสูงดูเหมือนจะไม่ได้รับผลกระทบ
    • การท่องเว็บใน Safari และ Chrome ดูเหมือนยังคงได้ประโยชน์จากการ query แบบเข้ารหัส
    • Firefox ดูเหมือนจะได้รับผลกระทบ
  • ประวัติการอัปเดต

    • 2024-09-17 19:10: ยืนยันว่าปัญหานี้อาจมีอยู่ตั้งแต่ macOS 14.5 Sonoma และไม่สามารถทดสอบบนระบบ 14.x ที่เก่ากว่านี้ได้
    • 2024-09-18 12:05: สรุปว่าไม่ใช่ปัญหา DNS proxy ทั่วไปของ macOS แต่เป็นปัญหาที่กระทบเฉพาะ DNS proxy ของ Little Snitch 6.1
    • 2024-09-18 15:52: ปัญหานี้ได้รับการแก้ไขแล้วใน Little Snitch 6.1.1

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

 
GN⁺ 2024-09-18
ความคิดเห็นใน Hacker News
  • รู้สึกแปลกนิดหน่อยที่ getaddrinfo() ถูกมองว่าเป็น “API รุ่นเก่าระดับต่ำ”
    บน macOS สถานการณ์อาจต่างไปมาก แต่บน Linux และน่าจะรวมถึง *BSD มันเป็นวิธีมาตรฐานที่ใช้สำหรับ name resolution
    แอป macOS ส่วนใหญ่น่าจะใช้เฟรมเวิร์กอย่าง Foundation หรือ NetworkKit สำหรับการ query DNS แต่ก็น่าแปลกใจเหมือนกันที่ภายในของเฟรมเวิร์กเหล่านั้นไม่ได้ลงท้ายด้วยการเรียกอย่าง getaddrinfo() เพื่อจัดการงาน
    เพราะ GAI เป็นแบบ blocking จึงน่าจะมี การเรียกแบบ asynchronous ระดับต่ำ อย่างอื่นอยู่

    • ใช่ CFNetwork เป็นโอเพนซอร์ส จึงตรวจสอบ implementation ได้ และเท่าที่จำได้ตอนเคยดู มันใช้ variant อย่าง getaddrinfo_async
      อย่างไรก็ตาม Apple ไม่ต้องการให้ผู้ใช้ปลายทาง resolve IP เองโดยตรงผ่าน getaddrinfo หรือ variant แบบ asynchronous ที่ CF เปิดเผย แล้วค่อย connect() ไปยัง IP นั้น
      โดยรวมแล้วถูกชี้นำให้ เชื่อมต่อด้วย hostname เพื่อให้ Apple จัดการ implementation ของ happy-eyeballs ภายในได้
      เหตุผลที่ Apple ไม่ชอบโมเดล getaddrinfo() ดูได้ที่ https://www.ietf.org/proceedings/72/slides/plenaryw-6.pdf มีโน้ตของผู้นำเสนออยู่ใต้แต่ละสไลด์ด้วย
    • ผมไม่คิดว่า getaddrinfo() ถูกถือว่าเป็น legacy นะ บทความบล็อกนั้นน่าจะเขียนส่วนนี้ผิด
      ส่วนจะเป็น “ระดับต่ำ” หรือไม่ ขึ้นอยู่กับมุมมอง
    • getaddrinfo() ไม่ได้เกี่ยวข้องกับ Linux โดยตรง มันเป็นแค่ ฟังก์ชันของ glibc
      ผู้คนมักเหมารวมว่า glibc คือวิธีมาตรฐานของ user space บน Linux แต่ไม่จำเป็นต้องเป็นอย่างนั้น
      เช่น systemd สร้างกลไก resolved ของตัวเอง และปรากฏว่าดีกว่าฝั่ง glibc มาก
      ผมเองก็กำลังทำซอฟต์แวร์แบบ standalone สำหรับ Linux อยู่ จึงมีโอกาสสูงว่าสักวันหนึ่งจะทำสิ่งคล้าย ๆ กันเอง
    • บน OpenBSD อย่างน้อยฟังก์ชัน DNS แบบดั้งเดิม/มาตรฐานอย่าง getaddrinfo/gethostbyname ทั้งหมดเป็น wrapper ของ OpenBSD libc asr implementation ที่ Eric Faurot เขียน
      https://man.openbsd.org/man3/asr_run.3
      https://github.com/openbsd/src/tree/master/lib/libc/asr
    • ไม่แน่ใจว่ากรณีนี้ใช่แบบนั้นพอดีหรือไม่ แต่แม้จะเป็นฟังก์ชันระบบชื่อเดียวกัน implementation ภายในก็อาจต่างกันมากระหว่าง *Linux/BSD/macOS
      แม้แต่ในกลุ่ม *BSD เองก็มีความแตกต่าง
      ในบางระบบ การเรียกฟังก์ชันหนึ่งอาจถูกใช้มาหลายปีและเป็น “วิธีมาตรฐาน” แต่ในอีกระบบหนึ่งอาจล้าสมัยและไม่ค่อยมีประโยชน์จริง ๆ
  • ปัญหาที่พูดถึงตรงนี้กลายเป็นว่าไม่ใช่ปัญหาของ macOS โดยรวม แต่เกิดเฉพาะกับ Little Snitch 6.1 และมีกำหนดจะแก้ไขด้วยอัปเดต Little Snitch ภายในวันนี้

    • ถ้าอัปเดตชื่อเรื่องให้สะท้อนเรื่องนี้ได้ก็คงดี
  • จากการตรวจสอบเพิ่มเติม บั๊กนี้มีอยู่แล้วอย่างน้อยตั้งแต่ macOS 14.5 Sonoma
    อาจจะมีมาตั้งแต่ก่อนหน้านั้นด้วย แต่ตอนนี้ดูเหมือนจะเข้าถึงระบบ 14.x ที่เก่ากว่าสำหรับทดสอบไม่ได้

    • อยากรู้ว่าเคยทดสอบไหมว่ามันทำงานจริงกับ getaddrinfo หรือเปล่า
      หรือแค่เห็นว่ามันทำงานครั้งหนึ่งใน CFNetwork แล้วจบ จากนั้นภายหลังจึงโพสต์บล็อกว่ามันพัง
    • สถานการณ์ที่นักพัฒนายังต้องเก็บ OS เวอร์ชันเก่าไว้ต่างหากเพื่อทดสอบนั้นยังคงไม่สมเหตุสมผลเลย
      แทบไม่มีเหตุผลทางเทคนิคเลยที่ Apple จะไม่อนุญาตให้ downgrade
    • ถ้าคิดว่ากำลังขายผลิตภัณฑ์อยู่ และ OS ใหม่เพิ่งออกเมื่อวาน นี่ก็ค่อนข้างเหลือเชื่อเหมือนกัน
  • Sequoia ทำให้ความสามารถในการใช้ DNS ของแอปเสียไป และอาจรวมถึงฟังก์ชันที่ใช้ UDP โดยรวมด้วย ถ้าเปิด firewall ของ macOS อยู่และแอปถูกลงทะเบียนว่า “บล็อกการเชื่อมต่อขาเข้า”
    https://waclaw.blog/macos-firewall-blocking-web-browsing-aft...

    • ทำซ้ำไม่ได้ บางคนบอกว่าเกี่ยวข้องกับ ESET: https://www.reddit.com/r/MacOS/comments/1fievr5/updating_mad...
    • ก่อน Sequoia แม้จะใช้ OpenDNS บน VPN ขณะเชื่อมต่อ VPN อยู่ iMessage และแอปอื่น ๆ ก็ยังทำงานต่อได้ แต่หลัง Sequoia ขณะเชื่อมต่อ VPN ข้อความ iMessage และสิ่งอื่น ๆ ไม่ทำงานอีกต่อไป
      พอตัด VPN ทุกอย่างก็ผ่านได้
      สงสัยว่าเรื่องนี้เกี่ยวข้องกันหรือไม่ firewall ของ macOS เปิดอยู่ แต่ไม่ได้บล็อกการเชื่อมต่อขาเข้าทั้งหมด
    • หลังอัปเกรดเป็น Sequoia ผมไม่สามารถท่องเว็บด้วย Safari หรือ Mozilla ได้
      พอเข้าไปที่การตั้งค่า DNS ของการเชื่อมต่อ Wi‑Fi แล้วเพิ่มเซิร์ฟเวอร์ Google DNS คือ 8.8.8.8 และ 8.8.4.4 ก็แก้ได้ และมันแทนที่เซิร์ฟเวอร์ DNS เดิมที่ถูกใส่ไว้โดยอัตโนมัติ
    • พูดตรง ๆ ผมคิดว่าพฤติกรรมแบบนี้โอเค แอปพลิเคชันไม่ควร resolve DNS เองนอกเหนือจากที่ระบุไว้ในการตั้งค่า
      เหตุผลที่แอปทำแบบนี้ก็เพื่อไม่ให้ผู้ใช้บล็อกสิ่งอย่าง telemetry ได้
      นี่เป็นคอมพิวเตอร์ของผม ดังนั้นสิทธิ์ตัดสินใจขั้นสุดท้ายว่าอะไรออกไปข้างนอกควรอยู่ที่ผม
  • ชื่อเรื่องชวนให้คิดว่านี่เป็นสิ่งที่ตั้งใจทำหรือใช้สิทธิพิเศษกับ Apple แต่จริง ๆ แล้วดูเหมือนจะใกล้เคียงกับ บั๊ก ธรรมดามากกว่า
    ถ้าจะบอกว่าได้รายงานเรื่องแบบนี้แล้ว ก็น่าจะใส่ หมายเลข FB และรายละเอียดการรายงานมาด้วย

    • ถ้ามองแบบทนายปีศาจ ก็อาจตั้งใจทำให้เป็นแบบนี้เพื่อเลี่ยงกระแสต่อต้าน แล้วทำให้ดูเหมือนเป็นบั๊กที่ยังไม่ได้แก้ก็ได้
      ถ้าบรรลุเป้าหมาย วิธีการทำงานภายในก็ยืดหยุ่นได้เต็มที่
    • ถ้าตั้งใจทำจริง ก็น่าจะเป็น URL ที่ฮาร์ดโค้ดและเข้ารหัสไว้
      อุปกรณ์บางชนิดเริ่มใช้วิธีแบบนั้นแล้วเพื่อเลี่ยงการบล็อกโฆษณา
  • อาจจะจำผิดก็ได้ แต่รู้สึกเดจาวูว่าทุกครั้งที่ iOS หรือ Mac ออกรุ่นใหม่ มักมีปัญหา DNS ที่ส่งผลกับของอย่าง Little Snitch, Mullvad
    ถ้าเป็นจริง ก็สงสัยมากว่า Apple ทำอะไรอยู่ระหว่างการทดสอบกับนักพัฒนาและเบต้าหลายเดือน

  • ตอนแรกที่กล่าวถึง Little Snitch ทำให้สับสน แต่พออ่านต่อแล้วดูเหมือนจะเป็น บั๊กของ LS ที่เกิดเฉพาะบางกรณี
    ถ้านี่เป็นบล็อกของ LS คำถามเดียวคือทำไมถึงบรรยายเหมือนเป็นบั๊กของ macOS
    ไม่ได้หมายความว่าพวกเขาผิด และนี่เป็นเรื่องในขอบเขตของพวกเขาไม่ใช่ของผม แต่จากเนื้อหาอย่างเดียวดูยังให้เหตุผลได้ไม่ค่อยพอ

    • ถ้า OS อนุญาตให้ ลงทะเบียนพร็อกซี DNS แล้วมีบางการเรียกที่ข้ามพร็อกซีนั้นไป นั่นก็เป็นบั๊กของ OS อย่างชัดเจน
  • เท่าที่จำได้ Apple เคยเลิกให้ third-party developer ใช้ network API บางตัว
    แต่แอปของ Apple เอง เช่น App Store ไม่ได้ถูกจำกัดแบบเดียวกัน
    ดังนั้นเมื่อพยายามกรอง network traffic ผ่านไฟร์วอลล์ของแอปด้วย API ใหม่ ก็ล้มเหลวเพราะ App Store ใช้ legacy API
    อาจเป็นส่วนหนึ่งของบั๊กเก่าที่เคยคิดว่าแก้ไปแล้วก็ได้

    • getaddrinfo() ไม่ใช่ legacy API แต่เป็น API มาตรฐานข้ามแพลตฟอร์ม สำหรับการค้นหา DNS
  • ประกาศแนว “พบบั๊กใน OS รุ่นใหม่! แก้ไข: จริง ๆ แล้วเป็นบั๊กที่มีมานานพอสมควรแล้ว!” นี่สนุกเสมอ

  • ผมใช้ routedns [0] เป็น local stub resolver เพื่อเลือกเองว่าคำขอไหนจะส่งไปที่ใด และใช้วิธีขนส่งแบบไหน
    ยังทำ blocklist, rewrite, cache, load balancing และจัดการ fallback request ได้ด้วย จึงควบคุมได้มาก
    สำหรับคำขอภายในเครื่อง ใช้ stub listener ที่ localhost:53 และคำขอส่วนใหญ่จะถูกส่งต่อไปยัง Cloudflare 1.1.1.1 ผ่าน UDP QUIC พร้อมแคช หรือก็คือ TLS 0-RTT
    เร็วและค่อนข้างปลอดภัย
    [0] https://github.com/folbricht/routedns

 
nearfall 2024-09-18

ขอบคุณสำหรับข้อมูลสำคัญครับ
อย่างน้อยก็ถือว่าโชคดีที่ Safari กับ Chrome ยังพอวางใจได้