SSL/TLS Security

สร้าง Wildcard Certificate ด้วย Let's Encrypt + Certbot

คู่มือฉบับสมบูรณ์สำหรับสร้างใบรับรอง SSL Wildcard พร้อม Bash Script อัตโนมัติ

Let's Encrypt
Cloudflare DNS
Bash Script

วิธีการทำงาน (How It Works)

LET'S ENCRYPT Certificate Authority 🔐 DNS Challenge CLOUDFLARE DNS Provider TXT Record _acme-challenge CERTBOT Automation Bash Script SERVER Ubuntu/Debian Wildcard *.example.com ขั้นตอนการทำงาน (Workflow) 1 ขอ Certificate 2 สร้าง TXT 3 ตรวจสอบ DNS 4 ออก Certificate 5 ติดตั้ง SSL

Wildcard Certificate คืออะไร?

Wildcard Certificate คือใบรับรอง SSL ที่ครอบคลุมโดเมนย่อยทั้งหมดของโดเมนหลัก เช่น *.example.com จะครอบคลุม www.example.com, api.example.com, mail.example.com และทุกซับโดเมนอื่นๆ ทำให้ไม่ต้องสร้างใบรับรองแยกสำหรับแต่ละซับโดเมน

ประหยัดเวลา
ประหยัดค่าใช้จ่าย (ฟรีจาก Let's Encrypt)
จัดการง่าย

1 เตรียมความพร้อม (Prerequisites)

ระบบปฏิบัติการ

  • Ubuntu 20.04+
  • Debian 11+
  • หรือ Debian-based อื่นๆ

ซอฟต์แวร์

  • certbot
  • curl
  • jq (JSON processor)

Cloudflare Account

  • บัญชี Cloudflare ฟรี
  • เพิ่ม Domain แล้ว
  • สร้าง API Token แล้ว

DNS Settings

  • NS ชี้ไป Cloudflare
  • Domain สถานะ Active
  • DNS propagation เสร็จสิ้น

สำคัญ: ต้องใช้ Cloudflare Nameservers

เพื่อใช้ DNS-01 challenge กับ Let's Encrypt ผ่านสคริปต์นี้ โดเมนของคุณ ต้อง ใช้ Cloudflare nameservers หากไม่ปฏิบัติ การสร้าง/ลบ TXT record อัตโนมัติจะไม่สำเร็จ

วิธีเปลี่ยน Nameservers ไปยัง Cloudflare:

  1. ไปที่หน้าควบคุมเครือข่ายของผู้ให้บริการระดับบน (เช่น GoDaddy, Thailand Data Center)
  2. แก้ไข NS records ให้ชี้ไปที่ Cloudflare (เช่น ns1.cloudflare.com, ns2.cloudflare.com)
  3. รอ DNS Propagation (โดยทั่วไป 5–30 นาที บางครั้งถึง 24 ชม.)
  4. ตรวจสอบใน Cloudflare Dashboard ว่า Domain แสดงสถานะ "Active" แล้ว

2 สร้าง Cloudflare API Token

ขั้นตอนการสร้าง Token

  1. 1

    เข้าสู่ Cloudflare Dashboard

    ไปที่ dash.cloudflare.com

  2. 2

    ไปที่ API Tokens

    คลิก My ProfileAPI Tokens

  3. 3

    สร้าง Token ใหม่

    คลิก Create Token → เลือก Template Edit zone DNS

  4. 4

    กำหนด Permissions

    • • Zone → DNS → Edit
    • • Zone Resources → Include → Specific Zone → เลือกโดเมนของคุณ
    • • Client IP Address Filtering (ถ้าต้องการ)
  5. 5

    สร้างและคัดลอก Token

    ⚠️ คัดลอก Token เก็บไว้ทันที จะไม่แสดงให้เห็นอีก!

3 Bash Script (certbot-wildcard.sh)

certbot-wildcard.sh

Auto-renewal
#!/usr/bin/env bash
# -------------------------------------------------------------
# certbot-wildcard.sh - Create/renew Let's Encrypt Wildcard cert
# -------------------------------------------------------------
set -euo pipefail

# ⚙️ Configuration - แก้ไขค่าเหล่านี้
DOMAIN="example.com"                  # กำหนดโดเมนของคุณ
CF_API_TOKEN="YOUR_CF_TOKEN_HERE"      # ใส่ Token จาก Cloudflare

# 📋 Logging Functions
log(){ echo -e "\e[32m[INFO]\e[0m $*"; }
error(){ echo -e "\e[31m[ERROR]\e[0m $*" >&2; exit 1; }

# 🔍 Prerequisites Check
if ! command -v certbot >/dev/null; then 
    error "กรุณาติดตั้ง certbot ก่อน (sudo apt install certbot)"
fi

if [[ "${1:-}" == "auth" ]]; then
    # 📝 Create DNS TXT record for validation
    VALIDATION="$CERTBOT_VALIDATION"
    RECORD="_acme-challenge.$CERTBOT_DOMAIN"
    
    # Get Zone ID
    log "Getting Zone ID for $DOMAIN..."
    ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
        -H "Authorization: Bearer $CF_API_TOKEN" \
        -H "Content-Type: application/json" | jq -r '.result[0].id')
    
    # Create TXT record
    log "Creating TXT record: $RECORD"
    RESP=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
        -H "Authorization: Bearer $CF_API_TOKEN" \
        -H "Content-Type: application/json" \
        --data "{\"type\":\"TXT\",\"name\":\"$RECORD\",\"content\":\"$VALIDATION\",\"ttl\":120}")
    
    export CF_DNS_RECORD_ID=$(echo $RESP | jq -r '.result.id')
    log "✓ TXT record created (ID=$CF_DNS_RECORD_ID)"
    
    # Wait for DNS propagation
    log "Waiting 30 seconds for DNS propagation..."
    sleep 30

elif [[ "${1:-}" == "cleanup" ]]; then
    # 🧹 Remove DNS TXT record after validation
    if [[ -z "${CF_DNS_RECORD_ID:-}" ]]; then 
        error "DNS record ID not found"
    fi
    
    # Get Zone ID
    ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
        -H "Authorization: Bearer $CF_API_TOKEN" \
        -H "Content-Type: application/json" | jq -r '.result[0].id')
    
    # Delete TXT record
    log "Removing TXT record..."
    curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$CF_DNS_RECORD_ID" \
        -H "Authorization: Bearer $CF_API_TOKEN"
    log "✓ TXT record removed"

else
    # 🚀 Main function - Request certificate
    log "Requesting wildcard certificate for *.$DOMAIN"
    
    certbot certonly \
        --manual \
        --preferred-challenges dns \
        --manual-auth-hook   "$(realpath "$0") auth" \
        --manual-cleanup-hook "$(realpath "$0") cleanup" \
        -d "*.$DOMAIN" \
        -d "$DOMAIN" \
        --non-interactive \
        --agree-tos \
        --email admin@$DOMAIN
    
    log "✓ Certificate created successfully!"
    log "Certificate location: /etc/letsencrypt/live/$DOMAIN/"
fi

หมายเหตุเรื่อง Script

  • • Script นี้ทำงานเป็น 3 ฟังก์ชัน: main, auth, cleanup
  • • Certbot จะเรียก auth ก่อน validation และ cleanup หลัง validation
  • • DNS record จะถูกสร้างและลบอัตโนมัติ

4 ทำให้สคริปต์เป็น Executable

1. ย้ายสคริปต์ไปที่ /usr/local/bin/

sudo mv certbot-wildcard.sh /usr/local/bin/

2. กำหนด Permission ให้ Execute ได้

sudo chmod +x /usr/local/bin/certbot-wildcard.sh

3. แก้ไขค่า Configuration ในสคริปต์

sudo nano /usr/local/bin/certbot-wildcard.sh

แก้ไขค่า DOMAIN และ CF_API_TOKEN ให้ถูกต้อง

5 ทดสอบทำงาน

รันสคริปต์เพื่อทดสอบ

sudo /usr/local/bin/certbot-wildcard.sh

ระบบจะทำการ:

  1. สร้าง TXT record ใน Cloudflare สำหรับ DNS validation
  2. รอ DNS propagation (30 วินาที)
  3. เรียก Let's Encrypt API เพื่อขอ Wildcard Certificate
  4. ลบ TXT record อัตโนมัติหลังจาก validation เสร็จสิ้น
  5. บันทึกใบรับรองไปที่ /etc/letsencrypt/live/example.com/

สำเร็จ!

ถ้าทุกอย่างถูกต้อง คุณจะเห็นข้อความ "Successfully received certificate" พร้อมพาธของไฟล์ใบรับรอง

6 ตรวจสอบสถานะ DNS

ตรวจสอบว่า Domain ใช้ Cloudflare Nameservers หรือไม่

ใช้คำสั่งต่อไปนี้เพื่อตรวจสอบ:

# ใช้ nslookup
nslookup -type=ns example.com

# หรือใช้ dig
dig NS example.com +short

# หรือใช้ host
host -t ns example.com

ผลลัพธ์ที่คาดหวัง:
ควรแสดง nameservers ของ Cloudflare เช่น:
ns1.cloudflare.com และ ns2.cloudflare.com

7 ตั้งค่า Cron เพื่อต่ออายุอัตโนมัติ

1. เปิด Crontab Editor

sudo crontab -e

2. เพิ่ม Cron Job (รันทุก 30 วัน)

# ต่ออายุ Wildcard Certificate ทุก 30 วัน เวลา 02:30 น.
30 2 */30 * * /usr/local/bin/certbot-wildcard.sh >> /var/log/certbot-wildcard.log 2>&1

อธิบาย Cron:
30 2 = เวลา 02:30 น.
*/30 = ทุก 30 วัน
/var/log/certbot-wildcard.log = เก็บ log

เคล็ดลับ

DNS propagation อาจใช้เวลา 1-5 นาที ถ้า script fail ลองเพิ่มเวลานอนจาก 30 เป็น 60 วินาที หรือเพิ่ม retry logic ในสคริปต์

8 ตรวจสอบใบรับรอง

ตรวจสอบวันที่หมดอายุ

openssl x509 -noout -dates -in /etc/letsencrypt/live/example.com/cert.pem

ผลลัพธ์จะแสดงวันที่เริ่มต้น (notBefore) และวันที่หมดอายุ (notAfter) ของใบรับรอง

ตรวจสอบออนไลน์

ใช้เว็บไซต์ตรวจสอบ SSL เพื่อยืนยันว่าใบรับรองทำงาน:

9 แก้ไขปัญหาที่พบบ่อย

DNS Propagation ล้มเหลว

การตรวจสอบ DNS ไม่สำเร็จ

วิธีแก้: ตรวจสอบว่าโดเมนชี้ NS ไปยัง Cloudflare แล้ว (ดูหัวข้อ "ตรวจสอบสถานะ DNS") และรอให้ propagation เสร็จสิ้น

Cloudflare API Token ไม่ถูกต้อง

ข้อความ error เกี่ยวกับ token

วิธีแก้: ตรวจสอบค่า CF_API_TOKEN ว่ามีสิทธิ Zone → DNS → Edit และครอบคลุมโดเมนที่ถูกต้อง

DNS Propagation ช้า

Certbot timeout ขณะรอ DNS

วิธีแก้: เพิ่มเวลานอนจาก 30 เป็น 60 วินาทีในบรรทัด sleep หรือลด TTL ของ DNS records ใน Cloudflare

Rate-limit ของ Cloudflare

ถูกบล็อกโดย Cloudflare

วิธีแก้: เพิ่ม delay ระหว่างการสร้างและลบ TXT record หรือใช้ API Token ที่ไม่มี rate-limit ข้อจำกัด

สรุป

ด้วยสคริปต์ Bash นี้ คุณสามารถสร้างและต่ออายุ Wildcard SSL Certificate จาก Let's Encrypt อย่างอัตโนมัติบน Ubuntu/Debian โดยใช้ Cloudflare DNS API ทำให้ทุกซับโดเมนของคุณปลอดภัยโดยไม่มีค่าใช้จ่าย

รวดเร็ว

ต่ออายุอัตโนมัติ

ฟรี