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

here-document แบบตายตัวคือความเชื่อผิด

ไคลเอนต์ Linux ของ Cisco ติดตั้งโปรแกรมเล็ก ๆ ที่ /opt/cisco/anyconnect/bin/vpn และ Secure Client 5 ยังคงส่งมันมาด้วย เมื่อบริการ vpnagentd ทำงานอยู่ แฟล็ก -s จะอ่านคำตอบจากอินพุตมาตรฐานตามลำดับที่ไคลเอนต์ขอ ลำดับนั้นไม่ตายตัวระหว่างเซิร์ฟเวอร์

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

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

ไคลเอนต์รออะไรอยู่

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

/opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net <<EOF
0
alice
$VPN_PASSWORD
y
EOF

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

ใช้ expect เมื่อลำดับคาดเดาไม่ได้

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

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

expect ยังให้บันทึกที่คุณล็อกได้โดยนำความลับออก ซึ่งมีค่ามากกว่ารหัสออกเมื่อเกตเวย์เปลี่ยนพรอมป์หลังอัปเกรด

ความลับต้องอยู่ที่ใดที่หนึ่ง

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

install -m 600 /dev/null ~/.vpn-secret
umask 077; VPN_PASSWORD=$(cat ~/.vpn-secret) /opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net

ไฟล์โหมด 600 ที่บัญชีเป็นเจ้าของเป็นขั้นต่ำ และมันยังเป็นความลับข้อความธรรมดาบนดิสก์ secret-tool lookup อ่านจากคีย์ริงของ Linux และบน macOS งานเดียวกันทำโดย security find-generic-password -w ที่ใดที่องค์กรรองรับการยืนยันตัวตนด้วยใบรับรองหรือ SAML ให้เลือกสิ่งนั้น เพราะรหัสผ่านที่เก็บไว้บวก MFA ยังไม่สามารถเข้าสู่ระบบได้โดยไม่มีมนุษย์

ยืนยันอุโมงค์ แล้วรับผิดชอบการตัดการเชื่อมต่อ

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

/opt/cisco/anyconnect/bin/vpn state
ip -brief address

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

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

ลำดับงาน: ยืนยัน vpnagentd บันทึกลำดับพรอมป์จริง เลือก here-document หรือ expect เก็บความลับให้พ้น argv และประวัติ ตรวจสอบสถานะและทรัพยากรหนึ่งอย่าง แล้วตัดการเชื่อมต่อในสคริปต์เดียวกัน

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