วิธีติดตั้ง HTTPS ด้วย Certificate ของ Let’s Encrypt แบบ wildcard สำหรับ Intranet ที่ไม่สามารถเข้าถึงได้จาก Internet

ความเดิมตอนที่แล้ว

ต่อจาก วิธีติดตั้ง HTTPS ด้วย Certificate ของ Let’s Encrypt ซึ่ง เครื่องที่จะขอใช้ Certificate นั้น ต้องสามารถ “เข้าถึงได้” จาก Internet เพราะ จะต้องสร้าง File ไปวางในตำแหน่งที่ Let’s Encrypt CA สามารถเข้ามาตรวจสอบได้ว่าเป็น ผู้ที่มีสิทธิ์ในการจัดการ Domain Name นั้นจริง

ปัญหาคือ

  • ในองค์กร ถ้าจะให้มีเซิร์ฟเวอร์ ที่สามารถเข้าถึงได้ จาก Internet ต้องเปิด Firewall ขององค์กร ซึ่ง ซับซ้อน และ มีความเสี่ยง
  • แล้ว ถ้ามีเครื่องภายใต้โดเมนเดียวกันอีกหลายเครื่อง ต้องทำทุกเครื่อง ซึ่งไม่สะดวกเลย

ต้องเข้าใจก่อน

Let’s encrypt มีวิธีการตรวจสอบความเป็นเจ้าของ Domain Name หรือที่เรียกว่า “Challenge” หลายวิธี ได้แก่

  1. HTTP-01 Challenge
  2. DNS-01 Challenge
  3. TLS-SNI-01 Challenge
  4. TLS-ALPN-01 Challenge

วิธีที่ง่าย และทำกันทั่วไป คือ HTTP-01 คือ เมื่อ certbot client รับคำสั่งขอ certificate สำหรับโดเมนที่ต้องการแล้ว จะต้องเอาไฟล์ ไปวางที่

http://<YOUR_DOMAIN>/.well-known/acme-challenge/<TOKEN>

ซึ่ง ชื่อต้องตรงกับที่กำหนด และในไฟล์ จะเป็น Token และ Thumbprint ของ account key

(ในทางเทคนิค อาจจะให้มีสักเครื่องในองค์กรที่เปิดให้เข้าถึงจาก Internet ได้ ทำหน้าที่ร้องขอ Certificate ได้ แล้วทำ HTTP-01 Challenge ให้ผ่าน ก็จะสามารถขอ Certificate ให้กับ Subdomain อื่น ๆ ได้)

แต่มีอีกวิธีหนึ่ง คือ DNS-01 Challenge ซึ่ง ไม่จำเป็นต้องมีเครื่องที่เข้าถึงได้จาก Internet (แต่สามารถ ออก Internet ได้) แต่อาศัยการสร้าง TXT Record ตามที่กำหนดแทน ประมาณนี้

_acme-challenge.<YOUR_DOMAIN> 300 IN TXT "<TOKEN>"

วิธีการมีดังนี้

0. เราจะขอ wildcard certificate โดเมนของ abc.ijk.xyz.psu.ac.th โดยการติดตั้ง Let’s Encrypts certbot client บน Ubuntu 20.04 ซึ่งเครื่องนี้ สามารถต่อ Internet ได้ แต่ไม่สามารถเข้าถึงได้จาก Internet

1.ติดตั้ง Let’s Encrypts certbot client (ยุ่งยากหน่อย แต่จะได้ certbot version 1.19)

sudo apt update
sudo snap install core; sudo snap refresh core
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

หรือสั้นๆ ทำอย่างนี้ก็ได้ (ไม่ต้องใช้ snap แต่จะได้ certbot version 0.40)

sudo apt update
sudo apt install certbot

2. สั่ง certbot ให้ไปขอเฉพาะ certificate จากนั้นบอกว่าจะติดตั้งเอง (manual) และ ขอใช้ DNS-01 Challenge

sudo certbot certonly --manual --preferred-challenges dns

3. กรอกข้อมูล โดเมนเนม ที่ต้องการ ในที่นี้ จะขอใช้ wildcard คือ *.abc.ijk.xyz.psu.ac.th

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): *.abc.ijk.xyz.psu.ac.th
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for *.abc.ijk.xyz.psu.ac.th

NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.
Are you OK with your IP being logged?

(Y)es/(N)o: y

Please deploy a DNS TXT record under the name
_acme-challenge.abc.ijk.xyz.medicine.psu.ac.th with the following value:
xjid...4u1znkFXut0Y...n3ck89gGaUl75K4fI
Before continuing, verify the record is deployed.

Press Enter to Continue

**** ตรงนี้ อย่าเพิ่งเคาะ Enter เด็ดขาด จนกว่า DNS admin จะดำเนินการเสร็จ *****

4. แจ้งผู้ดูแล DNS ขององค์กร ว่า ให้เพิ่ม TXT Record ส่งข้อความตามนี้ไปให้เค้าก็น่าจะได้

Please deploy a DNS TXT record under the name
_acme-challenge.abc.ijk.xyz.medicine.psu.ac.th with the following value:
xjid...4u1znkFXut0Y...n3ck89gGaUl75K4fI

หรือจะให้ดี แจ้งไปตรง ๆ ว่า จะเอาแบบนี้

_acme-challenge.abc.ijk.xyz.medicine.psu.ac.th 300 IN TXT 
"xjid...4u1znkFXut0Y...n3ck89gGaUl75K4fI"

5. รอ รอ รอ จนกว่า DNS Admin บอกว่า เสร็จแล้ว (แนะนำว่า ควรทำในเวลาที่สามารถประสานงานกับ DNS Admin ได้ เพราะ ในขั้นตอนข้อ 3. นั้น จะเคาะผ่านไม่ได้ หากแจ้ง DNS admin ไปแล้ว แต่เค้ายังไม่ทันทำให้ แล้วเราดันไปเคาะ Enter ผ่านไปก่อน TOKEN ที่แจ้งไป ก็จะใช้ไม่ได้)

ตรวจสอบด้วย Google Admin Toolbox ก็ได้ ว่าได้ TXT ตรงตามที่กำหนดมาแล้ว ที่

https://toolbox.googleapps.com/apps/dig/#TXT/

สิ่งที่ควรได้ น่าจะมีหน้าตาประมาณนี้

เมื่อมั่นใจว่า TXT Record ตรงกันแล้ว ค่อยกลับไปที่หน้าต่างในข้อ 3. แล้วกด Enter

Let’s Encrypt certbot client จะแจ้งไปยัง CA server ให้ตรวจสอบ ถ้าผ่านก็จะได้ข้อคาวมประมาณนี้

Waiting for verification…
Cleaning up challenges
Subscribe to the EFF mailing list (email: kanakorn.h@g.psu.ac.th).
IMPORTANT NOTES:
Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/abc.ijk.xyz.psu.ac.th/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/abc.ijk.xyz.psu.ac.th/privkey.pem
Your cert will expire on 2021-02-17. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew all of your certificates, run
"certbot renew"
If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

ตรวจสอบ Certification ด้วยคำสั่ง

sudo certbot certificates

จะได้รายละเอียดว่า Certificate ที่ได้มา เป็นของ domain อะไรบ้าง

Found the following certs:
Certificate Name: abc.ijk.xyz.psu.ac.th
Serial Number: 3808642657a...........bbeacd6df8bacc
Domains: *.abc.ijk.xyz.psu.ac.th
Expiry Date: 2021-02-17 02:59:43+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/abc.ijk.xyz.psu.ac.th/fullchain.pem
Private Key Path: /etc/letsencrypt/live/abc.ijk.xyz.psu.ac.th/privkey.pem

สุดท้าย เอา fullchain.pem และ privkey.pem ไปไว้ในเครื่อง web server ที่จะต้องการใช้ https เป็น subdomain ของ abc.ijk.xyz.psu.ac.th

จากนั้น ตั้งค่าใน Web Server เช่น Apache2 ให้ใช้ Certificate ประมาณนี้

<VirtualHost *:443>
# ...
   SSLEngine on
   SSLCertificateFile /etc/ssl/letsencrypt/fullchain.pem
   SSLCertificateKeyFile /etc/ssl/letsencrypt/privkey.pem
</VirtualHost>

แล้วก็ restart เป็นอันเรียบร้อย

ตรวจสอบการใช้งานจริง โดยการใช้ https://server1.abc.ijk.xyz.psu.ac.th/ จะได้แบบนี้

หวังว่าจะเป็นประโยชน์ครับ