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

ตัดสินใจเป็นรายชื่อ ไม่ใช่รายเกตเวย์

การทดสอบง่ายมาก: ที่อยู่นี้เปลี่ยนหรือไม่เมื่อไคลเอนต์เชื่อมต่อใหม่ ถ้าใช่ ชื่อต้องถูกสร้างจากเซสชัน VPN ถ้าไม่ใช่ มันอยู่ในรายการแบบคงที่ที่คุณอ่านและตรวจสอบได้

Name kindSource of truthWhere it lives
Connected clientThe address OpenVPN just assignedGenerated hosts file, rewritten per session
Service behind the tunnelA fixed address you choseStatic address= drop-in
Anything with a certificate nameThe certificate, not the poolEither, but the name must match the certificate

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

เส้นทางไดนามิก: learn-address และพูล

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

client-config-dir /etc/openvpn/ccd
ifconfig-pool-persist /etc/openvpn/ip-pool 60
script-security 2
learn-address /etc/openvpn/learn-address.sh

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

#!/bin/sh
HOSTS=/etc/openvpn/hosts.lan
case "$1" in
  add|update) echo "$2 $3" >> "$HOSTS" ;;
  delete)     sed -i "/^$2 /d" "$HOSTS" ;;
esac
kill -HUP $(cat /var/run/dnsmasq.pid)

บนอุปกรณ์ tun อาร์กิวเมนต์ที่สองคือที่อยู่ tunnel ของไคลเอนต์ บรรทัดนั้นจึงใช้ได้โดยตรง บนอุปกรณ์ tap OpenVPN จะส่งที่อยู่ MAC ของไคลเอนต์แทน เพราะเซกเมนต์ tap สามารถบรรทุกโปรโตคอลอื่นที่ไม่ใช่ IPv4 ได้ และตอนนั้นคุณต้องค้นที่อยู่ในไฟล์พูลด้วยชื่อสามัญก่อนเขียนอะไรลงไป

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

เส้นทางคงที่: address= และการขยายโดเมน

ชี้ dnsmasq ไปที่ไฟล์ที่สร้างขึ้นแทนไฟล์ hosts ของระบบ และให้โดเมนเพื่อให้ชื่อสั้นขยายเป็นชื่อที่ระบุเต็ม:

domain=corp.example
no-hosts
addn-hosts=/etc/openvpn/hosts.lan
listen-address=127.0.0.1,10.8.0.1
bind-interfaces

เมื่อตั้ง domain แล้ว บรรทัดอย่าง 10.8.0.6 alice จะตอบทั้ง alice และ alice.corp.example จำกัด listen-address ไว้ที่เกตเวย์อุโมงค์และ loopback เพราะตัวแปลงชื่อที่เผลอประกาศบนอินเทอร์เฟซ LAN คือบริการที่คุณไม่ได้ตั้งใจให้

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

address=/files.corp.example/10.8.0.20
address=/db.corp.example/10.9.0.5

ส่งมอบตัวแปลงชื่อ หรือจะไม่มีอะไรเกิดขึ้น

ตัวแปลงชื่อที่ไม่มีใครถามไม่เปลี่ยนอะไร เซิร์ฟเวอร์ต้องประกาศมัน:

push "dhcp-option DNS 10.8.0.1"
push "dhcp-option DOMAIN corp.example"

ไคลเอนต์ Windows ใช้ทั้งสองตัวเลือกเอง ไคลเอนต์ Linux ส่วนใหญ่ไม่ใช้: พวกมันต้องมี การผสานตัวแปลงชื่อที่รองรับ เช่นฮุก update-resolv-conf ของดิสทริบิวชัน หรือการจัดการ DNS ของ NetworkManager หรือโดเมนค้นหาและเนมเซิร์ฟเวอร์ที่ตั้งด้วยมือ ตรวจสอบตัวแปลงชื่อจริงของไคลเอนต์แทนการสันนิษฐานว่า push ถูกปฏิบัติตาม เพราะ push ที่ถูกละเลยดูเหมือนเซิร์ฟเวอร์ที่ไม่ตอบ

ตรวจสอบสามชั้น

ถามเซิร์ฟเวอร์โดยตรงก่อน แล้วจึงถามไคลเอนต์ แล้วจึงถามแอปพลิเคชัน:

dig +short @10.8.0.1 alice.corp.example
getent hosts files.corp.example

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

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

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