Technology

ACME Protocol — ระบบจัดการ SSL Certificate อัตโนมัติ

acme protocol คมอฉบบสมบรณ 2026
ACME Protocol | SiamCafe Blog
2025-10-07· อ. บอม — SiamCafe.net· 11,700 คำ

ACME Protocol คืออะไรและทำงานอย่างไร

ACME Protocol (Automatic Certificate Management Environment) เป็นโปรโตคอลมาตรฐานที่ถูกพัฒนาโดย ISRG (Internet Security Research Group) ซึ่งเป็นองค์กรเดียวกับที่อยู่เบื้องหลัง Let's Encrypt โปรโตคอลนี้ถูกกำหนดเป็นมาตรฐานใน RFC 8555 เพื่อใช้ในการจัดการ SSL/TLS Certificate แบบอัตโนมัติตั้งแต่การขอออกใบรับรองไปจนถึงการต่ออายุและการเพิกถอน

หลักการทำงานของ ACME Protocol ประกอบด้วยขั้นตอนหลัก 3 ส่วนคือ Account Registration, Order Placement และ Challenge Verification โดย ACME Client จะสื่อสารกับ ACME Server ผ่าน HTTPS เพื่อพิสูจน์ว่าผู้ขอเป็นเจ้าของโดเมนจริง จากนั้น Server จะออก Certificate ให้อัตโนมัติ

ACME Protocol รองรับ Challenge หลายประเภทได้แก่ HTTP-01 Challenge ที่ต้องวางไฟล์บน Web Server, DNS-01 Challenge ที่ต้องสร้าง TXT Record บน DNS และ TLS-ALPN-01 Challenge ที่ใช้ TLS handshake ในการยืนยัน แต่ละประเภทมีข้อดีข้อเสียแตกต่างกันขึ้นอยู่กับสถาปัตยกรรมของระบบ

ในเชิงเทคนิค ACME ใช้ JSON Web Signature (JWS) ในการเซ็นข้อมูลทุกคำร้องที่ส่งไปยัง Server เพื่อป้องกันการปลอมแปลงข้อมูล นอกจากนี้ยังมีกลไก Replay Protection ด้วยการใช้ Nonce เพื่อป้องกัน replay attack อีกด้วย

ติดตั้งและตั้งค่า Certbot สำหรับ ACME

Certbot เป็น ACME Client ที่ได้รับความนิยมสูงสุดพัฒนาโดย EFF (Electronic Frontier Foundation) รองรับ Web Server หลายตัวและสามารถขอ Certificate จาก Let's Encrypt ได้อัตโนมัติ การติดตั้ง Certbot บน Ubuntu/Debian ทำได้ดังนี้

# อัพเดทระบบและติดตั้ง snapd
sudo apt update && sudo apt upgrade -y
sudo apt install snapd -y

# ติดตั้ง Certbot ผ่าน Snap (แนะนำ)
sudo snap install --classic certbot

# สร้าง symbolic link เพื่อใช้งานจาก PATH
sudo ln -s /snap/bin/certbot /usr/bin/certbot

# ตรวจสอบเวอร์ชัน
certbot --version
# Output: certbot 2.11.0

# สำหรับ CentOS/RHEL ใช้คำสั่ง
sudo dnf install epel-release -y
sudo dnf install certbot python3-certbot-nginx -y

สำหรับผู้ที่ต้องการใช้ ACME Client ตัวอื่นก็มีตัวเลือกมากมายเช่น acme.sh ที่เขียนด้วย Shell Script ล้วนไม่ต้องพึ่งพา dependency ภายนอก, Lego ที่เขียนด้วย Go รองรับ DNS Provider มากกว่า 100 ราย หรือ win-acme สำหรับ Windows Server

การติดตั้ง acme.sh ทำได้ง่ายมากดังนี้

# ติดตั้ง acme.sh
curl https://get.acme.sh | sh -s email=admin@example.com

# รีโหลด shell
source ~/.bashrc

# ตั้งค่า Default CA เป็น Let's Encrypt
acme.sh --set-default-ca --server letsencrypt

# ดูรายการ Certificate ที่มี
acme.sh --list

ขอ SSL Certificate อัตโนมัติด้วย ACME Protocol

การขอ SSL Certificate ด้วย ACME Protocol มีหลายวิธีขึ้นอยู่กับประเภทของ Challenge ที่เลือกใช้ วิธีที่ง่ายที่สุดสำหรับเว็บเซิร์ฟเวอร์ทั่วไปคือใช้ HTTP-01 Challenge ผ่าน Certbot

สำหรับ Nginx ใช้คำสั่งเพียงบรรทัดเดียว

# ขอ Certificate สำหรับ Nginx (อัตโนมัติ)
sudo certbot --nginx -d example.com -d www.example.com --non-interactive --agree-tos -m admin@example.com

# ขอแบบ Standalone (ไม่ต้องมี Web Server)
sudo certbot certonly --standalone -d example.com --preferred-challenges http

# ขอแบบ Webroot (ไม่ต้องหยุด Web Server)
sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com

# ตรวจสอบ Certificate ที่ได้
sudo certbot certificates
# Output:
# Certificate Name: example.com
# Domains: example.com www.example.com
# Expiry Date: 2026-05-28 (VALID: 89 days)
# Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
# Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem

สำหรับการขอ Wildcard Certificate ต้องใช้ DNS-01 Challenge เท่านั้น เนื่องจากต้องพิสูจน์ว่าเป็นเจ้าของโดเมนทั้งหมดไม่ใช่แค่ subdomain เดียว

# ขอ Wildcard Certificate ด้วย DNS-01 Challenge
sudo certbot certonly --manual --preferred-challenges dns \
  -d "*.example.com" -d example.com \
  --agree-tos -m admin@example.com

# ระบบจะแสดงข้อความให้สร้าง DNS TXT Record:
# Please deploy a DNS TXT record under the name:
# _acme-challenge.example.com
# with the following value:
# gfj9Xq...Rg5nTzI

# ตรวจสอบว่า DNS Record พร้อมแล้ว
dig -t TXT _acme-challenge.example.com +short

# ใช้ acme.sh กับ Cloudflare DNS API (อัตโนมัติ)
export CF_Token="your-cloudflare-api-token"
export CF_Zone_ID="your-zone-id"
acme.sh --issue --dns dns_cf -d example.com -d "*.example.com"

ตั้งค่า Auto-Renew และ Wildcard Certificate

Certificate จาก Let's Encrypt มีอายุเพียง 90 วัน ดังนั้นการตั้งค่า Auto-Renew จึงสำคัญมาก Certbot จะติดตั้ง systemd timer หรือ cron job ให้อัตโนมัติเมื่อติดตั้งผ่าน snap แต่ควรตรวจสอบให้แน่ใจว่าทำงานถูกต้อง

# ตรวจสอบ systemd timer สำหรับ auto-renew
sudo systemctl status snap.certbot.renew.timer
# Output:
# Active: active (waiting)
# Trigger: Tue 2026-03-01 03:12:00 UTC

# ทดสอบการ renew แบบ dry-run
sudo certbot renew --dry-run
# Output: Congratulations, all simulated renewals succeeded

# ตั้งค่า cron job สำหรับ auto-renew (ถ้าไม่มี systemd timer)
sudo crontab -e
# เพิ่มบรรทัดนี้ (รันทุกวันตี 3)
0 3 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"

# สำหรับ acme.sh ระบบจะสร้าง cron job ให้อัตโนมัติ
crontab -l | grep acme
# Output: 0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh"

# ตั้งค่า deploy hook สำหรับ acme.sh
acme.sh --install-cert -d example.com \
  --key-file /etc/ssl/private/example.key \
  --fullchain-file /etc/ssl/certs/example.crt \
  --reloadcmd "systemctl reload nginx"

การตั้งค่า Deploy Hook มีความสำคัญเพราะหลังจาก Certificate ถูก renew แล้ว Web Server จำเป็นต้องโหลด Certificate ใหม่จึงจะมีผล ถ้าไม่ตั้ง hook ไว้ Certificate จะถูก renew แต่ Web Server ยังใช้ Certificate เก่าอยู่จนกว่าจะ restart

ACME Protocol กับ Nginx และ Apache

การตั้งค่า Nginx ให้ใช้งาน SSL Certificate ที่ได้จาก ACME Protocol ต้องแก้ไข server block ดังนี้

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;
    
    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # SSL Certificate จาก Let's Encrypt
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # SSL Configuration (Best Practice)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    
    # Security Headers
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options DENY;
    
    root /var/www/example.com;
    index index.html;
}

สำหรับ Apache การตั้งค่าจะแตกต่างเล็กน้อย Certbot สามารถแก้ไข configuration ให้อัตโนมัติได้เลย

# ขอ Certificate สำหรับ Apache
sudo certbot --apache -d example.com -d www.example.com

# Apache Virtual Host Configuration ที่ Certbot สร้างให้
# /etc/apache2/sites-available/example.com-le-ssl.conf
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com
    
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    
    # Modern SSL Configuration
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLHonorCipherOrder off
    SSLSessionTickets off
    
    Header always set Strict-Transport-Security "max-age=63072000"
</VirtualHost>

# เปิดใช้งาน mod_ssl และ mod_headers
sudo a2enmod ssl headers
sudo a2ensite example.com-le-ssl
sudo systemctl reload apache2

สำหรับระบบที่ใช้ Reverse Proxy เช่น Traefik หรือ Caddy จะมี ACME Client ในตัวทำให้ไม่ต้องติดตั้ง Certbot แยก Caddy จะขอและ renew Certificate ให้อัตโนมัติเพียงแค่ระบุชื่อโดเมนใน Caddyfile

# Caddyfile - ACME อัตโนมัติ
example.com {
    root * /var/www/html
    file_server
    
    # Caddy จะจัดการ ACME Protocol ให้ทั้งหมด
    # ไม่ต้องตั้งค่า SSL เอง
    
    header {
        Strict-Transport-Security "max-age=63072000"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
    }
}

# Traefik docker-compose.yml
# labels:
#   - "traefik.http.routers.app.tls.certresolver=letsencrypt"
#   - "traefik.http.routers.app.rule=Host(`example.com`)"

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

ปัญหาที่พบบ่อยที่สุดในการใช้ ACME Protocol คือ Challenge Verification ล้มเหลว สาเหตุหลักมีดังนี้

1. HTTP-01 Challenge ล้มเหลว — มักเกิดจาก Firewall บล็อก Port 80 หรือ Web Server ไม่ได้ serve directory .well-known/acme-challenge ตรวจสอบได้ด้วยคำสั่ง

# ตรวจสอบว่า Port 80 เปิดอยู่
sudo ss -tlnp | grep :80

# ตรวจสอบว่า .well-known สามารถเข้าถึงได้
curl -I http://example.com/.well-known/acme-challenge/test

# ถ้าใช้ Cloudflare ต้องปิด Proxy (สีส้ม) ชั่วคราว
# หรือใช้ DNS-01 Challenge แทน

# ตรวจสอบ Firewall (UFW)
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# ตรวจสอบ Firewall (firewalld)
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

2. Rate Limit ของ Let's Encrypt — Let's Encrypt มี Rate Limit ที่สำคัญคือ 50 Certificates ต่อ Registered Domain ต่อสัปดาห์ และ 5 Duplicate Certificates ต่อสัปดาห์ ถ้าโดน Rate Limit ต้องรอหรือใช้ Staging Environment สำหรับทดสอบ

# ใช้ Staging Environment สำหรับทดสอบ (ไม่มี Rate Limit)
sudo certbot certonly --staging --nginx -d example.com

# ตรวจสอบ Rate Limit ปัจจุบัน
# เข้าไปที่ https://crt.sh/?q=example.com

# สำหรับ acme.sh ใช้ --staging flag
acme.sh --issue --staging -d example.com --webroot /var/www/html

3. DNS-01 Challenge ล้มเหลว — มักเกิดจาก DNS Propagation ยังไม่เสร็จ ต้องรอ 1-5 นาทีก่อนกด continue หรือตั้งค่า DNS API ให้ถูกต้อง

4. Certificate ไม่ถูก Renew — ตรวจสอบ log ของ Certbot และ systemd timer ให้แน่ใจว่า cron job ทำงานอยู่

# ดู log ของ Certbot
sudo journalctl -u snap.certbot.renew.service --no-pager -n 50

# ดู log ไฟล์
sudo cat /var/log/letsencrypt/letsencrypt.log | tail -100

# Force renew ถ้าจำเป็น
sudo certbot renew --force-renewal

# ตรวจสอบวันหมดอายุ Certificate
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
# Output:
# notBefore=Feb 28 00:00:00 2026 GMT
# notAfter=May 29 23:59:59 2026 GMT

FAQ คำถามที่พบบ่อย

Q: ACME Protocol รองรับ Certificate ประเภทไหนบ้าง?

A: ACME Protocol รองรับ Domain Validation (DV) Certificate เท่านั้น ไม่รองรับ Organization Validation (OV) หรือ Extended Validation (EV) เนื่องจากการยืนยันตัวตนองค์กรไม่สามารถทำอัตโนมัติได้ สำหรับเว็บไซต์ทั่วไป DV Certificate เพียงพอสำหรับการเข้ารหัสข้อมูล

Q: Let's Encrypt Certificate หมดอายุทุกกี่วันและทำไมถึงสั้น?

A: Certificate จาก Let's Encrypt มีอายุ 90 วัน เหตุผลหลักคือเพื่อความปลอดภัย ถ้า Private Key ถูกขโมยไป Certificate จะหมดอายุเร็วทำให้ผลกระทบน้อยลง นอกจากนี้ยังบังคับให้ผู้ใช้ตั้งค่า Auto-Renew ซึ่งเป็น Best Practice อยู่แล้ว Certbot จะ renew ให้อัตโนมัติเมื่อ Certificate เหลืออายุน้อยกว่า 30 วัน

Q: ใช้ ACME Protocol กับ Internal Server หรือ Private Network ได้ไหม?

A: สำหรับ HTTP-01 Challenge ใช้ไม่ได้เพราะ Let's Encrypt Server ต้องเข้าถึง Web Server ของคุณจากอินเทอร์เน็ต แต่สามารถใช้ DNS-01 Challenge ได้ถ้าโดเมนมี Public DNS อีกทางเลือกคือใช้ Private ACME Server เช่น Step-ca หรือ Smallstep ที่ติดตั้งภายในองค์กรเพื่อออก Certificate สำหรับ Internal Server โดยเฉพาะ

Q: ACME Protocol ปลอดภัยแค่ไหน?

A: ACME Protocol ใช้ JWS (JSON Web Signature) ในการเซ็นทุก request มี Nonce สำหรับป้องกัน replay attack และสื่อสารผ่าน HTTPS เท่านั้น นอกจากนี้ยังมี Certificate Transparency Log ที่บันทึก Certificate ทุกใบที่ออกเพื่อให้ตรวจสอบได้ว่ามี Certificate ปลอมถูกออกให้โดเมนของคุณหรือไม่

Q: มี ACME Server อื่นนอกจาก Let's Encrypt ไหม?

A: มีหลายตัวเช่น ZeroSSL ที่ให้ Certificate ฟรีเช่นกัน, BuyPass Go SSL, Google Trust Services และ SSL.com ทุกตัวรองรับ ACME Protocol มาตรฐานเดียวกัน สามารถเปลี่ยน ACME Server ใน Certbot ได้ด้วยคำสั่ง --server flag สำหรับองค์กรขนาดใหญ่ที่ต้องการ Private CA สามารถใช้ Step-ca, Vault PKI หรือ EJBCA ที่รองรับ ACME Protocol ได้

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

ACME Protocol สำหรับมือใหม่ Step by Stepอ่านบทความ → ACME Protocol Open Source Contributionอ่านบทความ → ACME Protocol Observability Stackอ่านบทความ → ACME Protocol Network Segmentationอ่านบทความ →

📚 ดูบทความทั้งหมด →