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

การเชื่อมต่อตรวจสอบอะไรจริง ๆ

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

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

สร้างรากบนโฮสต์ที่ไม่เคยได้รับที่อยู่

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

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out root.key
openssl req -x509 -new -key root.key -sha256 -days 7300 \
  -subj "/CN=Example VPN Root CA" -out root.crt \
  -addext "basicConstraints=critical,CA:TRUE" \
  -addext "keyUsage=critical,keyCertSign,cRLSign"

สร้างตัวกลางบนโฮสต์ลงนามและนำเฉพาะคำขอของมันไปยังเครื่องออฟไลน์ รากลงนามคำขอนั้นด้วยความยาวพาธเป็นศูนย์ ดังนั้น CA ระดับกลางจึงลงนามใบรับรองปลายทางได้ แต่สร้าง CA อื่นใต้ตัวเองไม่ได้ ส่วนขยายเดียวนี้กันไม่ให้โฮสต์ลงนามที่ถูกบุกรุกสร้างอำนาจเทียบเท่าราก ใช้ ECDSA เฉพาะเมื่อไคลเอนต์ทุกรายใช้ OpenVPN 2.4 หรือใหม่กว่า มิฉะนั้นให้สร้างกุญแจ RSA และรักษาขั้นตอนเดิม

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out intermediate.key
openssl req -new -key intermediate.key -subj "/CN=Example VPN Intermediate CA" -out intermediate.csr
openssl x509 -req -in intermediate.csr -CA root.crt -CAkey root.key \
  -CAcreateserial -days 3650 -sha256 -extfile intermediate.ext -out intermediate.crt

intermediate.ext มี basicConstraints=critical,CA:TRUE,pathlen:0, keyUsage=critical,keyCertSign,cRLSign และ authorityKeyIdentifier=keyid:always คืนกุญแจรากเข้าตู้เซฟก่อนเชื่อมต่อโฮสต์ลงนามอีกครั้ง ถ้ารากต้องเพิกถอนตัวกลางได้ ให้ลงนามด้วย openssl ca -config root.cnf -extensions intermediate_ca กับ index.txt ระดับรากแทน openssl x509 -req เพื่อให้หมายเลขซีเรียลถูกบันทึก จากนั้นส่งรายการรากที่ได้ไปในโปรไฟล์ไคลเอนต์ ซึ่ง crl-verify แบบไฟล์จะอ่านตอนเริ่มต้น ส่งชุดที่มีใบรับรอง CA ทั้งสองให้ไคลเอนต์ ใบปลายทางเพียงใบเดียวจะตรวจสอบกับรากไม่ได้

ออกใบปลายทางจากตัวกลาง พร้อมฐานข้อมูล

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

mkdir -p /etc/vpn-ca/intermediate/newcerts
touch /etc/vpn-ca/intermediate/index.txt
echo 1000 > /etc/vpn-ca/intermediate/serial
echo 1000 > /etc/vpn-ca/intermediate/crlnumber
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /etc/vpn-ca/intermediate
database = $dir/index.txt
new_certs_dir = $dir/newcerts
serial = $dir/serial
crlnumber = $dir/crlnumber
certificate = $dir/intermediate.crt
private_key = $dir/intermediate.key
default_md = sha256
default_days = 365
default_crl_days = 30
unique_subject = no
policy = policy_any
[ policy_any ]
commonName = supplied
[ server_cert ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = serverAuth
subjectAltName = @server_names
[ client_cert ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = clientAuth
[ server_names ]
DNS.1 = vpn.example.com

บรรทัดการใช้กุญแจสมมติว่าเป็นกุญแจ ECDSA สำหรับ RSA ให้เพิ่ม keyEncipherment ให้ไคลเอนต์แต่ละรายมีชื่อสามัญของตัวเอง เพราะ OpenVPN ระบุการเชื่อมต่อด้วยฟิลด์นั้น และแล็ปท็อปสองเครื่องที่ใช้ CN=vpn-client ร่วมกันแยกไม่ออกในบันทึก ในกฎ client-config-dir หรือในการพุชต่อผู้ใช้ใด ๆ และคุณสูญเสียการระบุตัวตนที่ทำให้การตัดสินใจเพิกถอนป้องกันได้ ออกและตรวจสอบใบปลายทางแบบนี้

openssl req -new -key alice.key -subj "/CN=alice-laptop" -out alice.csr
openssl ca -config intermediate.cnf -extensions client_cert -in alice.csr -out alice.crt -batch
openssl verify -CAfile ca-bundle.crt -untrusted intermediate.crt alice.crt

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

เผยแพร่การเพิกถอนโดยไม่ปลุกราก

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

เพิกถอนและสร้างใหม่ด้วยสองคำสั่งจากฐานข้อมูลเดียวกัน

openssl ca -config intermediate.cnf -revoke /etc/vpn-ca/intermediate/newcerts/1001.pem
openssl ca -config intermediate.cnf -gencrl -out /etc/openvpn/crl.pem

จากนั้นจับตาดูนาฬิกา CRL มีฟิลด์การอัปเดตครั้งถัดไป และเมื่อวันที่นั้นผ่านไป คู่ที่ตรวจสอบจะปฏิเสธรายการแทนที่จะเพิกเฉย การสร้างใหม่รายเดือนด้วย default_crl_days = 30 ยังมีช่องว่าง รายปีไม่มี อายุใบปลายทางที่สั้นลงคือการควบคุมที่เชื่อถือได้กว่า เพราะการเพิกถอนมีผลเฉพาะที่ที่มีการดูรายการ

ทดสอบห่วงโซ่ แล้วเขียนพิธีการลงไป

ทำซ้ำความล้มเหลวสี่อย่างก่อนเชื่อในดีไซน์ ตรวจสอบห่วงโซ่ด้วย openssl verify -CAfile ca-bundle.crt -untrusted intermediate.crt server.crt เชื่อมต่อด้วยใบรับรองไคลเอนต์ที่หมดอายุและยืนยันว่าเซิร์ฟเวอร์ปฏิเสธ เพิกถอนไคลเอนต์ทดสอบ โหลดใหม่ และยืนยันว่ารายการมีผล เลื่อนนาฬิกาของโฮสต์ไปข้างหน้าหนึ่งวัน เพราะนาฬิกาที่ผิดอาจออกและปฏิเสธใบรับรองที่ดูเหมือนใช้ได้ที่อื่น

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

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

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