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

สิ่งที่ ServerName ตัดสินใจจริง

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

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

RequireAll คือคอนเทนเนอร์ที่ทำให้การตรวจสอบทั้งสองเป็นข้อบังคับ

Apache 2.4 ห่อคำสั่ง Require ของส่วนเดียวไว้ใน RequireAny โดยนัย ดังนั้นคำสั่งเปล่าสองคำสั่งหมายความว่าอันใดอันหนึ่งก็เพียงพอ เพิ่มคอนเทนเนอร์แล้วความหมายจะกลับกัน:

<Location /svn/repo>
    AuthType Basic
    AuthName "Subversion"
    AuthBasicProvider file
    AuthUserFile /etc/apache2/svn.htpasswd
    <RequireAll>
        Require ip 10.8.0.0/24
        Require valid-user
    </RequireAll>
</Location>

RequireAll ต้องการทั้งสองเงื่อนไข: ที่อยู่ต้นทางภายในช่วงอุโมงค์และผู้ใช้ที่คลังเก็บยอมรับ นั่นคือสิ่งที่ควรหมายถึงเฉพาะ-VPN สำหรับ URL ของ Subversion เอกสารอ้างอิง mod_authz_core อธิบายกฎของคอนเทนเนอร์ เก็บบล็อกไว้ใน Location ที่มีอยู่ของคลังเก็บ และปล่อยคำสั่ง DAV ที่ทำงานอยู่แล้วไว้ตามเดิม เพราะส่วนนี้ไม่ได้แทนที่ AuthType หรือไฟล์รหัสผ่านหรือการอนุญาตระดับเส้นทาง

การทดสอบต้นทางมาจาก mod_authz_host ดังนั้นตรวจสอบว่าโหลดแล้วก่อนแก้ไขปัญหาอื่น: apachectl -M | grep authz_host

ที่อยู่ที่ Apache ประเมินคือที่อยู่ของซ็อกเก็ต

Require ip เปรียบเทียบกับที่อยู่ที่ Apache บันทึกไว้สำหรับการเชื่อมต่อ ซึ่งไม่ใช่ที่อยู่ที่ไคลเอนต์คิดว่าตนมีเสมอ

เมื่อ VPN กำหนดเส้นทางที่อยู่โดยไม่มีการแปล Apache จะเห็นที่อยู่ของอุโมงค์และ 10.8.0.0/24 ตรงกัน เมื่อเกตเวย์แปลที่อยู่ Apache จะเห็นเกตเวย์และกฎจะไม่ตรงกับสิ่งใดอย่างเงียบ ๆ สิ่งเดียวกันเกิดขึ้นหลังตัวบาลานซ์โหลดที่สิ้นสุด TLS หน้าโฮสต์ สำหรับกรณีนั้นมี mod_remoteip RemoteIPHeader X-Forwarded-For พร้อมกับ RemoteIPTrustedProxy สำหรับตัวบาลานซ์จะแทนที่ที่อยู่ที่บันทึกไว้ และเฉพาะแล้วช่วงจึงมีสิ่งที่เปรียบเทียบ

การไว้วางใจส่วนหัวการส่งต่อตามอำเภอใจนั้นแย่กว่าการไม่มีกฎเลย ไคลเอนต์ใดก็ส่ง X-Forwarded-For ที่มี 10.8.0.9 และผ่านการตรวจสอบช่วงที่ไม่เคยยึดกับฮอปที่เชื่อถือได้

จัดชั้นตัวรับฟังและนโยบายของคลังเก็บ

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

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

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

พิสูจน์การปฏิเสธทั้งสองก่อนบอกว่าเสร็จ

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

คำสั่งเดียวต่อกรณีก็เพียงพอ: curl -sI -u user:pass https://svn.example.com/svn/repo/ แล้วอ่านบรรทัดสถานะ ทำกรณีที่ทำงานได้ซ้ำผ่านไคลเอนต์จริงด้วย เพราะ svn info ฝึกวิธี DAV ที่คอมมิตและการอัปเดตจะใช้

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

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