สคริปต์ที่เริ่ม OpenVPN แล้วไม่เคยเชื่อมต่อมักไม่ใช่ปัญหาเครือข่าย: ไคลเอนต์กำลังรอพรอมป์โดยไม่มีเทอร์มินัลให้วาด OpenVPN มีวิธีที่รองรับอยู่สองวิธีในการตอบพรอมป์นั้นโดยไม่ต้องมีคน คือไฟล์ข้อมูลรับรองหลัง auth-user-pass กับซ็อกเก็ตการจัดการ และสองวิธีนี้ใช้แทนกันไม่ได้ ไฟล์มีต้นทุนหนึ่งไดเรกทีฟและตอบพรอมป์หนึ่งครั้ง ซ็อกเก็ตตอบทุกพรอมป์และให้ทุกสิ่งที่เปิดพอร์ต loopback ได้ช่องควบคุมที่ไม่มีการพิสูจน์ตัวตน ว่าจะใช้อันไหนกับการติดตั้งของคุณขึ้นอยู่กับว่าพรอมป์ใดกำลังบล็อกอยู่จริง และคุณสามารถปล่อยความลับใดให้อยู่นิ่งได้

ตั้งชื่อพรอมป์ก่อนเลือกกลไก

พรอมป์สี่แบบดูเหมือนกันบนเทอร์มินัล คู่บัญชีมาจากการตั้งค่า PAM หรือ auth-user-pass-verify ของเซิร์ฟเวอร์ และ auth-user-pass เป็นตัวตอบ วลีรหัสของกุญแจส่วนตัวเป็นของไฟล์กุญแจและอ่านผ่าน --askpass หรือพิมพ์ด้วยมือ แพ็กเกจ PKCS#12 ขอรหัสของตัวเอง การพิสูจน์ตัวตนพร็อกซีใช้ไฟล์ auth ที่ --http-proxy รับ ไม่ใช่ข้อมูลรับรองบัญชี

เมื่อ OpenVPN ทำงานเป็นลูกของ systemd, PHP หรือ Node จะไม่มีเทอร์มินัล ดังนั้นแต่ละอย่างจึงบล็อกอย่างเงียบ ๆ โปรเซสยังนั่งอยู่ โลจหยุดหลังบรรทัดรหัส และยูนิตสุดท้ายก็หมดเวลา ความเงียบนั้นคือเหตุผลที่ผู้คนเพิ่มลูปพยายามซ้ำหรือ sleep แทนที่จะดูว่าพรอมป์ใดค้างอยู่ มีเพียงซ็อกเก็ตการจัดการเท่านั้นที่ตอบทั้งสี่ได้ ไฟล์ข้อมูลรับรองตอบอันแรกและไม่ตอบอย่างอื่น

auth-user-pass: ไฟล์เดียว พรอมป์เดียว

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

สองรายละเอียดเปลี่ยนไฟล์ที่ถูกต้องให้กลายเป็นพรอมป์ เอดิเตอร์ที่บันทึก CRLF จะทิ้งการคืนแคร่ที่ติดอยู่กับรหัสผ่าน เซิร์ฟเวอร์จึงปฏิเสธรหัสผ่านที่ดูเหมือนถูกต้องในไฟล์ ตรวจด้วย cat -A หรือ od -c ไม่ใช่ด้วยตา และ auth-user-pass ที่ไม่มีอาร์กิวเมนต์ในโปรไฟล์หมายถึง «ถามผู้ใช้» ตามการออกแบบ ซึ่งไดเรกทีฟที่สองบนบรรทัดคำสั่งอาจแทนที่ไม่ได้ เพราะโปรไฟล์ถูกแยกวิเคราะห์ตรงที่มันอยู่

ลำดับของออปชันเป็นกับดักที่สาม และขึ้นอยู่กับเวอร์ชัน OpenVPN 2.4 บางบิลด์ไม่สนใจ --auth-user-pass เมื่อมันอยู่ก่อน --config ดังนั้นออปชันสองตัวเดียวกันในลำดับอื่นจึงเชื่อมต่อได้ วางไดเรกทีฟไว้ในโปรไฟล์ หรือหลัง --config บนบรรทัดคำสั่ง และ grep โปรไฟล์หาทุกการปรากฏก่อนแก้อื่นใด

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

ซ็อกเก็ตการจัดการ: ทุกพรอมป์ พื้นผิวมากขึ้น

เริ่มไคลเอนต์ด้วยตัวรับฟังและประกาศชัดเจนว่าพรอมป์จะถูกรายงานบนนั้น โดยใช้ไดเรกทีฟที่เอกสารไว้ในคู่มือ OpenVPN 2.6:

management 127.0.0.1 3030
management-query-passwords

จาก bash ให้ถือการเชื่อมต่อบนตัวอธิบายไฟล์สำรองและตอบตามชื่อพรอมป์ไม่ใช่ตามตำแหน่ง เพราะการเชื่อมต่อใหม่อาจถามในลำดับอื่น:

exec 3<>/dev/tcp/127.0.0.1/3030
while read -r -u 3 line; do
  case "$line" in
    *"Need 'Auth' username/password"*)
      echo 'username "Auth" alice' >&3
      echo 'password "Auth" secret' >&3 ;;
    *"Need 'Private Key' password"*)
      echo 'password "Private Key" secret' >&3 ;;
  esac
done

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

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

อันไหนเหมาะกับการติดตั้ง

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

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

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

openvpn --config client.ovpn --auth-user-pass <(printf "%s
%s
" "$USER" "$PASS")

มันพังใต้ /bin/sh ในยูนิตที่ข้ามเชลล์ และในอิมเมจที่ไม่มี bash หรือ /dev/fd เก็บมันไว้สำหรับการทดสอบแบบโต้ตอบ อย่าใช้เป็นสัญญาที่บริการพึ่งพา

ปกป้องความลับ แล้วตรวจสอบจากโลจ

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

การรันที่ถูกต้องแสดงลำดับพรอมป์เสร็จสิ้นและเซสชันไปถึง «Initialization Sequence Completed» หากไคลเอนต์หยุดที่พรอมป์เดิม การจับคู่ล้มเหลว พิมพ์บรรทัดที่แน่นอนที่ซ็อกเก็ตส่งมา ตรวจเครื่องหมายคำพูดและชื่อพรอมป์ และแก้รูปแบบแทนการเพิ่ม sleep อุโมงค์ที่รายงานความสำเร็จและไม่ได้บรรทุกอะไรคือปัญหาเส้นทางหรือ push ไม่ใช่ข้อมูลรับรอง

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

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