ข้อสงสัยว่า macOS Sequoia 15 ข้ามการเข้ารหัส DNS แต่จริง ๆ แล้วเป็นปัญหาของ Little Snitch 6.1
(obdev.at)- ใน 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 ความคิดเห็น
ความคิดเห็นใน Hacker News
รู้สึกแปลกนิดหน่อยที่ getaddrinfo() ถูกมองว่าเป็น “API รุ่นเก่าระดับต่ำ”
บน macOS สถานการณ์อาจต่างไปมาก แต่บน Linux และน่าจะรวมถึง *BSD มันเป็นวิธีมาตรฐานที่ใช้สำหรับ name resolution
แอป macOS ส่วนใหญ่น่าจะใช้เฟรมเวิร์กอย่าง Foundation หรือ NetworkKit สำหรับการ query DNS แต่ก็น่าแปลกใจเหมือนกันที่ภายในของเฟรมเวิร์กเหล่านั้นไม่ได้ลงท้ายด้วยการเรียกอย่าง getaddrinfo() เพื่อจัดการงาน
เพราะ GAI เป็นแบบ blocking จึงน่าจะมี การเรียกแบบ asynchronous ระดับต่ำ อย่างอื่นอยู่
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 มีโน้ตของผู้นำเสนออยู่ใต้แต่ละสไลด์ด้วย
ส่วนจะเป็น “ระดับต่ำ” หรือไม่ ขึ้นอยู่กับมุมมอง
ผู้คนมักเหมารวมว่า glibc คือวิธีมาตรฐานของ user space บน Linux แต่ไม่จำเป็นต้องเป็นอย่างนั้น
เช่น systemd สร้างกลไก resolved ของตัวเอง และปรากฏว่าดีกว่าฝั่ง glibc มาก
ผมเองก็กำลังทำซอฟต์แวร์แบบ standalone สำหรับ Linux อยู่ จึงมีโอกาสสูงว่าสักวันหนึ่งจะทำสิ่งคล้าย ๆ กันเอง
https://man.openbsd.org/man3/asr_run.3
https://github.com/openbsd/src/tree/master/lib/libc/asr
แม้แต่ในกลุ่ม *BSD เองก็มีความแตกต่าง
ในบางระบบ การเรียกฟังก์ชันหนึ่งอาจถูกใช้มาหลายปีและเป็น “วิธีมาตรฐาน” แต่ในอีกระบบหนึ่งอาจล้าสมัยและไม่ค่อยมีประโยชน์จริง ๆ
ปัญหาที่พูดถึงตรงนี้กลายเป็นว่าไม่ใช่ปัญหาของ macOS โดยรวม แต่เกิดเฉพาะกับ Little Snitch 6.1 และมีกำหนดจะแก้ไขด้วยอัปเดต Little Snitch ภายในวันนี้
จากการตรวจสอบเพิ่มเติม บั๊กนี้มีอยู่แล้วอย่างน้อยตั้งแต่ macOS 14.5 Sonoma
อาจจะมีมาตั้งแต่ก่อนหน้านั้นด้วย แต่ตอนนี้ดูเหมือนจะเข้าถึงระบบ 14.x ที่เก่ากว่าสำหรับทดสอบไม่ได้
หรือแค่เห็นว่ามันทำงานครั้งหนึ่งใน CFNetwork แล้วจบ จากนั้นภายหลังจึงโพสต์บล็อกว่ามันพัง
แทบไม่มีเหตุผลทางเทคนิคเลยที่ Apple จะไม่อนุญาตให้ downgrade
Sequoia ทำให้ความสามารถในการใช้ DNS ของแอปเสียไป และอาจรวมถึงฟังก์ชันที่ใช้ UDP โดยรวมด้วย ถ้าเปิด firewall ของ macOS อยู่และแอปถูกลงทะเบียนว่า “บล็อกการเชื่อมต่อขาเข้า”
https://waclaw.blog/macos-firewall-blocking-web-browsing-aft...
พอตัด VPN ทุกอย่างก็ผ่านได้
สงสัยว่าเรื่องนี้เกี่ยวข้องกันหรือไม่ firewall ของ macOS เปิดอยู่ แต่ไม่ได้บล็อกการเชื่อมต่อขาเข้าทั้งหมด
พอเข้าไปที่การตั้งค่า DNS ของการเชื่อมต่อ Wi‑Fi แล้วเพิ่มเซิร์ฟเวอร์ Google DNS คือ 8.8.8.8 และ 8.8.4.4 ก็แก้ได้ และมันแทนที่เซิร์ฟเวอร์ DNS เดิมที่ถูกใส่ไว้โดยอัตโนมัติ
เหตุผลที่แอปทำแบบนี้ก็เพื่อไม่ให้ผู้ใช้บล็อกสิ่งอย่าง telemetry ได้
นี่เป็นคอมพิวเตอร์ของผม ดังนั้นสิทธิ์ตัดสินใจขั้นสุดท้ายว่าอะไรออกไปข้างนอกควรอยู่ที่ผม
ชื่อเรื่องชวนให้คิดว่านี่เป็นสิ่งที่ตั้งใจทำหรือใช้สิทธิพิเศษกับ Apple แต่จริง ๆ แล้วดูเหมือนจะใกล้เคียงกับ บั๊ก ธรรมดามากกว่า
ถ้าจะบอกว่าได้รายงานเรื่องแบบนี้แล้ว ก็น่าจะใส่ หมายเลข FB และรายละเอียดการรายงานมาด้วย
ถ้าบรรลุเป้าหมาย วิธีการทำงานภายในก็ยืดหยุ่นได้เต็มที่
อุปกรณ์บางชนิดเริ่มใช้วิธีแบบนั้นแล้วเพื่อเลี่ยงการบล็อกโฆษณา
อาจจะจำผิดก็ได้ แต่รู้สึกเดจาวูว่าทุกครั้งที่ iOS หรือ Mac ออกรุ่นใหม่ มักมีปัญหา DNS ที่ส่งผลกับของอย่าง Little Snitch, Mullvad
ถ้าเป็นจริง ก็สงสัยมากว่า Apple ทำอะไรอยู่ระหว่างการทดสอบกับนักพัฒนาและเบต้าหลายเดือน
ตอนแรกที่กล่าวถึง Little Snitch ทำให้สับสน แต่พออ่านต่อแล้วดูเหมือนจะเป็น บั๊กของ LS ที่เกิดเฉพาะบางกรณี
ถ้านี่เป็นบล็อกของ LS คำถามเดียวคือทำไมถึงบรรยายเหมือนเป็นบั๊กของ macOS
ไม่ได้หมายความว่าพวกเขาผิด และนี่เป็นเรื่องในขอบเขตของพวกเขาไม่ใช่ของผม แต่จากเนื้อหาอย่างเดียวดูยังให้เหตุผลได้ไม่ค่อยพอ
เท่าที่จำได้ Apple เคยเลิกให้ third-party developer ใช้ network API บางตัว
แต่แอปของ Apple เอง เช่น App Store ไม่ได้ถูกจำกัดแบบเดียวกัน
ดังนั้นเมื่อพยายามกรอง network traffic ผ่านไฟร์วอลล์ของแอปด้วย API ใหม่ ก็ล้มเหลวเพราะ App Store ใช้ legacy API
อาจเป็นส่วนหนึ่งของบั๊กเก่าที่เคยคิดว่าแก้ไปแล้วก็ได้
ประกาศแนว “พบบั๊กใน 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
ขอบคุณสำหรับข้อมูลสำคัญครับ
อย่างน้อยก็ถือว่าโชคดีที่ Safari กับ Chrome ยังพอวางใจได้