ไคลเอนต์ VPN ต้องอาศัยความช่วยเหลือที่มีสิทธิ์พิเศษในการกำหนดค่าเครือข่ายใหม่ และข้อเท็จจริงนั้นถูกนำไปใช้กว้างเกินไปกับทุกสิ่งรอบตัว สคริปต์ที่เมานต์แชร์ไฟล์ไม่จำเป็นต้องใช้ root เพราะแชร์นั้นเป็นของเซสชันของผู้ใช้ที่ลงชื่อเข้าใช้และของข้อมูลรับรองของผู้ใช้คนนั้น การย้ายการเมานต์ออกจากเส้นทางที่มีสิทธิ์พิเศษทำให้ไม่ต้องมีกฎ sudo ไม่ต้องมี hook ของ root และไม่ต้องแก้ไขแอปที่มาพร้อมระบบ สิ่งที่เหลืออยู่คือแอปเพล็ตเล็ก ๆ ที่เปิดค้างไว้ เฝ้าดูโปรไฟล์หนึ่งโปรไฟล์ และลองเพียงครั้งเดียว

ทำไมเรื่องนี้จึงอยู่ในเซสชันของผู้ใช้

วอลุ่มที่เมานต์แล้วเป็นคุณสมบัติของเซสชันที่เมานต์มัน เซสชันของผู้ใช้อื่นมองไม่เห็น และการเมานต์ที่เป็นของ root ก็ทำงานต่างจากการเมานต์ที่ Finder สร้าง การเก็บการเมานต์ไว้ในเซสชันของผู้ใช้จึงรักษาความหมายนั้นไว้

ตัวช่วยที่มีสิทธิ์พิเศษมีไว้สำหรับส่วนที่จำเป็นจริง ๆ ได้แก่ การสร้างอินเทอร์เฟซ tunnel การเปลี่ยนเส้นทาง และการอัปเดตตัวแปลงชื่อ การเมานต์แชร์ SMB ไม่ใช่หนึ่งในนั้น การปฏิบัติต่อมันราวกับว่าใช่จะบังคับให้ต้องเลือกระหว่าง sudo ที่ไม่ต้องใช้รหัสผ่านกับสคริปต์ root ที่ทำงานตอนไม่มีใครอยู่ ทั้งสองอย่างเป็นความเสี่ยงที่ใหญ่เกินกว่าปัญหาจะสมเหตุสมผล และแนวทางแบบเซสชันของผู้ใช้ก็เลี่ยงทางเลือกนั้นไปเลย

hook การเชื่อมต่อของ Tunnelblick เองใช้แทนกันไม่ได้ในที่นี้ เพราะทำงานนอกเซสชันเดสก์ท็อปและลำดับเทียบกับสคริปต์ของไคลเอนต์ไม่ได้ถูกกำหนดไว้ การสอบถามสถานะจากแอปเพล็ตของผู้ใช้เป็นกลไกที่เล็กกว่าด้วยสมมติฐานที่น้อยกว่า

พิสูจน์ด้วยมือก่อนว่าแชร์ใช้งานได้

ระบบอัตโนมัติไม่สามารถจัดหาเส้นทาง สิทธิ์ หรือบัญชีที่ไม่มีอยู่ได้ ก่อนเขียนสคริปต์ใด ๆ ให้เชื่อมต่อ VPN ด้วยมือและเปิดแชร์ใน Finder ถ้าขั้นตอนนั้นล้มเหลว สคริปต์จะล้มเหลวในแบบที่สับสนกว่า

จดค่าสามอย่างที่สคริปต์จะใช้ ได้แก่ ชื่อโปรไฟล์ตามที่ Tunnelblick แสดงทุกตัวอักษร URL ของแชร์ และชื่อวอลุ่มที่ Finder แสดงหลังการเมานต์ ชื่อวอลุ่มสำคัญเพราะการตรวจสอบการเมานต์ที่มีอยู่ใช้ชื่อนี้ และการตรวจสอบด้วยชื่อเพียงอย่างเดียวเป็นเพียงการป้องกันเพื่อความสะดวก ไม่ใช่หลักฐานยืนยันตัวตนของเซิร์ฟเวอร์ ให้ใช้ชื่อที่ไม่ซ้ำบนเครื่อง จากนั้นยืนยันว่าเซิร์ฟเวอร์ตอบสนองจริงหรือไม่

smbutil view //files.corp.example
osascript -e 'tell application "Tunnelblick" to get state of first configuration whose name is "Office"'
mount | grep -i smbfs

คำสั่งแรกพิสูจน์ว่าเซิร์ฟเวอร์ตอบสนอง คำสั่งที่สองพิสูจน์ว่าชื่อโปรไฟล์แปลงได้ และคำสั่งที่สามแสดงว่าการเมานต์ที่สำเร็จหน้าตาเป็นอย่างไร บันทึกทั้งสามอย่างก่อนจะทำอะไรให้เป็นอัตโนมัติ

อ่านสถานะโปรไฟล์จาก Tunnelblick

Tunnelblick เปิดเผยการกำหนดค่าและสถานะผ่าน AppleScript และนั่นคือ hook เดียวที่การออกแบบนี้ต้องใช้ สถานะที่สำคัญคือสตริงที่รายงานสำหรับโปรไฟล์นั้น ไม่ใช่การมีอยู่ของแอป

การสอบถามมีผลที่ควรกล่าวถึง การเชื่อมต่อใหม่ที่สั้นกว่าช่วงเวลาอาจผ่านไปโดยไม่ถูกสังเกต และแอปเพล็ตจะไม่เห็นการเปลี่ยนสถานะเลย ซึ่งยอมรับได้สำหรับการเฝ้าระวังการเมานต์ แต่ยอมรับไม่ได้สำหรับสิ่งใดที่ต้องตอบสนองต่อทุกเหตุการณ์ หากต้องการความเที่ยงตรงระดับเหตุการณ์ นี่คือกลไกที่ผิด ไม่ใช่กลไกที่ต้องใช้ตัวจับเวลาสั้นลง ควรเลือกช่วงเวลาโดยคำนึงถึงข้อแลกเปลี่ยนนั้น

property attempted : false

on idle
    set profileName to "Office"
    set shareURL to "smb://files.corp.example/OfficeTeam"
    set volName to "OfficeTeam"
    tell application "Tunnelblick" to set vpnState to state of first configuration whose name is profileName
    if vpnState is not "CONNECTED" then
        set attempted to false
        return 20
    end if
    tell application "Finder" to set mounted to (exists disk volName)
    if (not mounted) and (not attempted) then
        set attempted to true
        try
            mount volume shareURL
        end try
    end if
    return 20
end idle

ส่งออกเป็นแอปพลิเคชันพร้อมตัวเลือกให้เปิดค้างไว้ แล้วเปิดใช้งานในเซสชันที่ลงชื่อเข้าใช้แทนการใช้ sudo

เมานต์ครั้งเดียว แล้วหยุดพยายาม

แฟล็ก ‘พยายามแล้ว’ คือสิ่งที่กันไม่ให้เรื่องนี้กลายเป็นลูปเดาข้อมูลรับรอง เมื่อแอปเพล็ตพยายามแล้ว มันจะรอให้สถานะการเชื่อมต่อเปลี่ยนก่อนจะลองอีกครั้ง

พฤติกรรมนั้นตั้งใจไว้ แชร์ที่ปฏิเสธการเมานต์มักปฏิเสธด้วยเหตุที่การลองใหม่แก้ไม่ได้ และการลองซ้ำ ๆ จะเปลี่ยนการถามครั้งเดียวให้เป็นสายของการถาม แฟล็กจะถูกรีเซ็ตเมื่อโปรไฟล์ออกจากสถานะเชื่อมต่อ ดังนั้นการเชื่อมต่อใหม่จริงจะสร้างความพยายามใหม่พอดีหนึ่งครั้ง การออกและเปิดแอปเพล็ตใหม่ก็รีเซ็ตเช่นกัน และนั่นคือการบังคับด้วยมือ ทั้งสองเส้นทางไม่ปกปิดความล้มเหลว ทั้งคู่ปล่อยให้มองเห็นได้ใน Finder

สคริปต์ไม่ได้เก็บรหัสผ่านใด ๆ และควรเป็นเช่นนั้น ให้การเมานต์เป็นฝ่ายถาม และให้พวงกุญแจทำสิ่งที่องค์กรรองรับ การฝังข้อมูลรับรองลงใน URL จะเปลี่ยนสคริปต์เพื่อความสะดวกให้กลายเป็นความลับที่ต้องหมุนเวียน

สิ่งที่ตัวช่วยทำไม่ได้

มีขีดจำกัดสามข้อที่ควรเขียนไว้ข้างแอปเพล็ต มันไม่สามารถถอดวอลุ่มที่กำลังใช้งานอยู่ออกหลังเครือข่ายล้มเหลว ไม่สามารถรับประกันว่า DNS และเซิร์ฟเวอร์พร้อมเมื่อสถานะบอกว่าเชื่อมต่อแล้ว และไม่ได้ตอบสนองต่อการเชื่อมต่อใหม่ทุกครั้ง

ขีดจำกัดแรกสำคัญที่สุดในทางปฏิบัติ แชร์ที่เซิร์ฟเวอร์หายไปจะทิ้งวอลุ่มที่ดูเหมือนเมานต์อยู่และค้างเมื่อเข้าถึง วิธีแก้อย่างสุภาพคือทำงานกับไฟล์ให้เสร็จแล้วถอดออกก่อนตัดการเชื่อมต่อตามแผน ข้อที่สองอธิบายความล้มเหลวของการลองครั้งแรกส่วนใหญ่ คือ tunnel ขึ้นแล้วแต่ตัวแปลงชื่อยังตามไม่ทัน จึงควรรอแล้วเมานต์ด้วยมือหนึ่งครั้งเพื่อยืนยัน ข้อที่สามคือข้อแลกเปลี่ยนของการสอบถามที่กล่าวมาก่อน ไม่ใช่บั๊กที่ต้องแพตช์

สำหรับเครื่องที่ไม่มีคนดูแลหรือฟลีตที่ถูกจัดการ การออกแบบนี้ผิดรูป ควรใช้นโยบายการเมานต์ที่ผู้ดูแลระบบเป็นเจ้าของ แทนการขยายแอปเพล็ตเดสก์ท็อปให้เป็นบริการที่มีสิทธิ์พิเศษ

บทความที่เกี่ยวข้อง