ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

ใช้ Wildcard DNS Record ให้ถูกวิธีและปลอดภัย
Home ใช้ Wildcard DNS Record ให้ถูกวิธีและปลอดภัย

ใช้ Wildcard DNS Record ให้ถูกวิธีและปลอดภัย

Wildcard DNS Record คือระเบียนที่ตอบคำถามสำหรับซับโดเมนใดก็ได้ที่ยังไม่มีระเบียนเฉพาะของตัวเอง เขียนด้วยเครื่องหมายดอกจัน

เหมาะกับระบบที่สร้างซับโดเมนให้ลูกค้าอัตโนมัติ เช่น ระบบ SaaS ที่ให้ลูกค้าแต่ละรายมี ชื่อลูกค้า.example.com ของตัวเอง โดยไม่ต้องเพิ่มระเบียน DNS ทุกครั้ง

สิ่งที่ต้องเตรียม

  • สิทธิ์แก้ไข DNS ของโดเมน
  • เว็บเซิร์ฟเวอร์ที่ตั้งค่ารับทุกซับโดเมนแล้ว
  • ใบรับรอง SSL แบบ Wildcard หากให้บริการผ่าน HTTPS

ขั้นตอนที่ 1: ตั้งระเบียน

*.example.com.  3600  IN  A  203.0.113.10

# หรือชี้ไปยังชื่ออื่น
*.example.com.  3600  IN  CNAME  app.example.com.
dig +short anything.example.com
dig +short random-name-12345.example.com

ทั้งสองควรได้ IP เดียวกัน

ขั้นตอนที่ 2: เข้าใจกฎการมีผลที่คนมักเข้าใจผิด

นี่คือส่วนที่สร้างความสับสนมากที่สุด กฎมีสามข้อ

ข้อ 1 ระเบียนเฉพาะชนะ Wildcard เสมอ

*.example.com.     IN  A  203.0.113.10
api.example.com.   IN  A  203.0.113.20

api.example.com จะได้ 203.0.113.20 ส่วนชื่ออื่นได้ 203.0.113.10

ข้อ 2 Wildcard ครอบคลุมแค่ระดับเดียว

*.example.com ครอบคลุม api.example.com แต่ไม่ครอบคลุม v1.api.example.com

หากต้องการครอบคลุมสองระดับ ต้องเพิ่มอีกระเบียน

*.example.com.      IN  A  203.0.113.10
*.api.example.com.  IN  A  203.0.113.10

ข้อ 3 ชนิดของระเบียนต้องตรงกัน

หากมี *.example.com A และมี mail.example.com MX อยู่ด้วย การถาม mail.example.com ชนิด A จะไม่ได้คำตอบจาก Wildcard เพราะเมื่อมีระเบียนใด ๆ ของชื่อนั้นอยู่แล้ว Wildcard จะไม่ถูกใช้กับชื่อนั้นอีกเลยไม่ว่าชนิดใด

ข้อนี้เป็นสาเหตุที่ระบบพังแบบหาสาเหตุยาก ต้องเพิ่มระเบียน A ให้ชื่อนั้นโดยตรง

mail.example.com.  IN  MX  10 mx.example.com.
mail.example.com.  IN  A   203.0.113.10

ขั้นตอนที่ 3: ตั้งเว็บเซิร์ฟเวอร์ให้รับทุกซับโดเมน

server {
    listen 443 ssl;
    http2 on;
    server_name ~^(?<sub>.+)\.example\.com$;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # ส่งชื่อซับโดเมนให้แอปใช้ระบุลูกค้า
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host       $host;
        proxy_set_header X-Tenant   $sub;
        proxy_set_header X-Real-IP  $remote_addr;
    }
}

ตัวแปร $sub ที่จับจากชื่อโฮสต์ทำให้แอปรู้ว่าคำขอนี้เป็นของลูกค้ารายใด

ขั้นตอนที่ 4: ขอใบรับรอง Wildcard

ต้องยืนยันผ่าน DNS เท่านั้น การยืนยันผ่านไฟล์บนเว็บใช้กับ Wildcard ไม่ได้

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d 'example.com' -d '*.example.com' \
  --agree-tos -m [email protected]

จำไว้ว่า *.example.com ครอบคลุมแค่ระดับเดียวเช่นเดียวกับ DNS หากต้องการสองระดับต้องขอ *.api.example.com เพิ่ม

ขั้นตอนที่ 5: ข้อควรระวังด้านความปลอดภัย

Wildcard ทำให้ทุกชื่อชี้มาที่เซิร์ฟเวอร์คุณ ซึ่งเปิดช่องให้เกิดปัญหาสองอย่าง

การยึดครองซับโดเมน

หากแอปรับทุกชื่อโดยไม่ตรวจสอบ ผู้ไม่หวังดีอาจใช้ ธนาคารปลอม.example.com ทำหน้าหลอกลวงโดยอาศัยความน่าเชื่อถือของโดเมนคุณ

แก้ด้วยการให้แอปตรวจสอบว่าชื่อนั้นมีอยู่จริงในระบบ และปฏิเสธชื่อที่ไม่รู้จัก

server {
    listen 443 ssl;
    server_name ~^(?<sub>.+)\.example\.com$;
    # ...
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header X-Tenant $sub;
        # ให้แอปตอบ 404 เมื่อไม่รู้จักชื่อนี้
    }
}

ปัญหาด้าน SEO

หากทุกชื่อแสดงเนื้อหาเดียวกัน จะกลายเป็นเนื้อหาซ้ำจำนวนมหาศาล ให้ตอบ 404 สำหรับชื่อที่ไม่มีจริง และตั้ง canonical ให้ถูกต้อง

curl -sI https://ชื่อที่ไม่มีจริง.example.com | head -1
# ควรได้ 404

ขั้นตอนที่ 6: เรื่อง Wildcard กับอีเมล

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

# ไม่ควรทำ
*.example.com.  IN  MX  10 mx.example.com.

ระบุ MX เฉพาะชื่อที่ต้องการรับอีเมลจริงเท่านั้น และตั้ง SPF ให้ครอบคลุมซับโดเมนด้วย

*.example.com.  TXT  "v=spf1 -all"

ระเบียนนี้บอกว่าไม่มีเซิร์ฟเวอร์ใดได้รับอนุญาตให้ส่งอีเมลแทนซับโดเมนเหล่านี้ ซึ่งป้องกันการปลอมแปลง

ขั้นตอนที่ 7: ทดสอบให้ครบ

#!/bin/bash
D=example.com
for s in api app shop test random-$(date +%s) v1.api; do
  ip=$(dig +short "$s.$D" | tail -1)
  code=$(curl -s -o /dev/null -w '%{http_code}' "https://$s.$D" --max-time 5)
  printf '%-24s %-16s %s\n' "$s.$D" "${ip:-ไม่มี}" "$code"
done

ตรวจว่าชื่อที่ควรมีตอบ 200 ชื่อที่ไม่ควรมีตอบ 404 และชื่อสองระดับทำงานตามที่คาด

ปัญหาที่พบบ่อย

ซับโดเมนบางชื่อไม่ทำงาน

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

dig example.com ANY +short
dig mail.example.com A +short

ซับโดเมนสองระดับไม่ทำงาน

กฎข้อ 2 Wildcard ครอบคลุมระดับเดียว เพิ่ม *.api.example.com แยกต่างหาก

ใบรับรองไม่ครอบคลุม

เช่นเดียวกับ DNS ใบรับรอง Wildcard ครอบคลุมระดับเดียว ตรวจรายชื่อในใบรับรอง

echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -text | grep DNS:

ผู้ให้บริการ DNS ไม่รองรับ Wildcard

ผู้ให้บริการส่วนใหญ่รองรับ แต่บางรายจำกัดชนิดของระเบียนที่ใช้ได้ ทดสอบด้วยการสร้างแล้วตรวจด้วย dig จริง

ต้องการวางโครงสร้าง DNS สำหรับระบบที่มีลูกค้าหลายราย ติดต่อ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security