ทุกวันนี้การเชื่อมต่อเว็บต่างๆ แทบทั้งหมดกลายเป็นการเชื่อมต่อแบบเข้ารหัส หลังจาก Let's Encrypt เปิดให้บริการเมื่อปี 2015 ตั้งแต่ปี 2018 เป็นต้นมาอัตราการเชื่อมต่อเว็บด้วย HTTPS ขึ้นไปถึง 94-95% และคงที่อยู่ที่เดิมเสมอมา เว็บสาธารณะที่เราใช้งานแทบทั้งหมดแม้อาจจะมีหลายเว็บยังให้บริการแบบ HTTP อยู่แต่ก็มักจะรองรับ HTTPS ไปพร้อมกัน อย่างไรก็ดียังมีเว็บกลุ่มหนึ่งที่เราใช้ HTTP เสมอ นั่นคือเว็บของอุปกรณ์ในบ้านหรือภายในองค์กร ไม่ว่าจะเป็นเราท์เตอร์หรือสตอเรจ ตลอดจนอุปกรณ์อื่นๆ
การขอใบรับรองเข้ารหัสจาก Let's Encrypt นั้นโดยปกติแล้วเรามักอาศัยกระบวนการยืนยันเจ้าของโดเมนแบบ HTTP-01 ที่ต้องการเว็บเซิร์ฟเวอร์ที่เข้าถึงจากอินเทอร์เน็ตได้เพราะทาง Let's Encrypt จะเข้ามาดาวน์โหลดข้อมูลยืนยันเจ้าของโดเมนจากเว็บ กระบวนการ HTTP-01 ไม่เหมาะกับการยืนยันตัวตนเซิร์ฟเวอร์ภายในและเราท์เตอร์ เนื่องจากอุปกรณ์เหล่านี้มันมีเฉพาะไอพีภายในเช่น 10.0.0.0/8 หรือ 192.168.1.0/24 เป็นต้น ทำให้หากเรากำหนดชื่อโดเมนให้กับอุปกรณ์เหล่านี้ เครื่องเหล่านี้ก็เข้าถึงจากอินเทอร์เน็ตไม่ได้อยู่ดี ทำให้เซิร์ฟเวอร์ Let's Encrypt ไม่สามารถเข้ามาตรวจสอบเพื่อออกใบรับรองผ่านกระบวนการ HTTP-01 ได้
Let's Encrypt ยังรองรับกระบวนการยืนยันเจ้าของโดเมนแบบ DNS-01 ที่อาศัยการตรวจสอบฟิลด์ TXT แทนที่จะเป็นการเชื่อมต่อไปยังเซิร์ฟเวอร์โดยตรง กระบวนการ DNS-01 กำหนดให้เจ้าของโดเมนต้องตั้งค่าฟิลด์ TXT ให้กับโดเมน _acme_challenge.[ชื่อโดเมน]
ตามที่กำหนด
ปัญหาของ DNS-01 คือกระบวนการปรับแก้ข้อมูลใน DNS นั้นไม่สะดวกนัก โดยปกติแล้วผู้ดูแลเว็บเซิร์ฟเวอร์ไม่มีสิทธิ์ในการปรับแก้ข้อมูลด้วยตัวเอง หรือกระบวนการปรับแก้สะดวกนัก เช่น ต้องล็อกอินเข้าเว็บเพื่อปรับแก้ไขค่าเป็นครั้งๆ แต่ทุกวันนี้เรามีบริการ Dynamic DNS ที่หลายคนนิยม ในกรณีนี้ผมเลือกบริการ Dynamic DNS ของ Hurricane Electric เพราะเป็นบริการฟรีที่รองรับฟิลด์หลากหลาย ทั้ง IPv4, IPv6, และฟิลด์ TXT รวมถึงมีบริการ Dynamic TXT สามารถกำหนดค่าฟิลด์ TXT ได้โดยไม่ต้องล็อกอินเว็บโดยตรง (ตอนนี้โปรแกรมขอใบรับรอง Let's Encypt ยังไม่มีตัวใดรองรับฟีเจอร์นี้) และสามารถกำหนดหมายเลขไอพีได้เองจากไคลเอนต์ Dynamic DNS ทำให้ใช้งานกับเน็ตเวิร์คภายในได้ง่าย เราสามารถตั้งสริปต์ให้แก้ไขค่า DNS จากภายในตัวอุปกรณ์ได้อัตโนมัติเมื่อมีการแก้ไขหมายเลขไอพี
ในบทความนี้ผมใช้เราท์เตอร์ของ MikroTik เป็นตัวอย่าง เราท์เตอร์ตามบ้านที่เรามักได้รับจากผู้ให้บริการอินเทอร์เน็ตส่วนมากรองรับการให้บริการผ่าน HTTPS และสามารถติดตั้งใบรับรองได้เช่นกัน อย่างไรก็ดีผู้ให้บริการอินเทอร์เน็ตในไทยหลายรายมักแก้ไขรอมเป็นของตัวเองและตัดฟีเจอร์ HTTPS ออก
กระบวนการขอใบรับรองจาก Let's Encrypt นั้นเริ่มจากการโอนโดเมนเราไปอยู่กับ Hurricane Electric ก่อน ด้วยการตั้งค่า name server ไปเป็น ns1.he.net, ns2.he.net, ns3.he.net, ns4.he.net, และ ns5.he.net จากนั้นสร้างบัญชีบนเว็บ dns.he.net และเพิ่มโดเมนของเราเข้าไป เราจะสามารถตั้งค่า DNS ได้เอง
จากนั้นเราต้องหาลินุกซ์สักเครื่องเพื่อรันไคลเอนต์ของ Let's Encrypt ในกรณีของผมใช้โปรแกรม acme.sh สามารถติดตั้งได้ด้วยคำสั่ง curl https://get.acme.sh | sh -
ในกรณีของผมต้องติดตั้งแพ็กเกจ curl และ openssl ลงในลินุกซ์เพิ่มเติม
ก่อนจะรัน acme.sh
เราจำเป็นต้องกำหนดตัวแปรเพื่อให้โปรแกรมรู้รหัสผ่าน Hurricane Electric ของเราก่อน เป็นค่า HE_Username
และ HE_Password
หากในอนาคต acme.sh
รองรับฟีเจอร์ใหม่ของ Hurricane Electric ก็น่าจะสามารถใส่โทเค็นเฉพาะโดเมนเพื่อตั้งค่า Dynamic TXT แทนที่จะใส่รหัสผ่านไปทั้งหมดเช่นนี้ ค่าเริ่มต้นนั้น acme.sh
จะติดตั้งอยู่ใน ~/.acme.sh
ให้เข้าไปในโฟลเดอร์นี้ หลังจากนั้นรันคำสั่ง
./acme.sh --issue --dns dns_he -d [domain name]
กระบวนการขอรับรองจะใช้เวลา 2-5 นาทีเนื่องจากต้องแน่ใจว่าค่าฟิลด์ TXT อัพเดตใน DNS เรียบร้อยแล้ว เมื่อตรวจสอบจนเสร็จสิ้นแล้วทาง Let's Encrypt จะออกใบรับรองมาให้ อยู่ใน ~/.acme.sh/[domain name]/
กระบวนการติดตั้งใบรับรองเข้าเราท์เตอร์เป็นอีกส่วนหนึ่ง เราอาจจะดาวน์โหลดไฟล์ไปติดตั้งในหน้าเว็บของ Mikrotik ได้โดยตรง แต่ควรระวังว่าใบรับรองของ Let's Encrypt นั้นมีอายุเพียง 3 เดือน ควรหาทางเขียนสคริปต์เพื่ออัพเดตอัตโนมัติให้เรียบร้อย เริ่มจากสร้างกุญแจ SSH เพื่อให้สามารถเขียนสคริปต์ติดตังใบรับรองได้ โดยใช้คำสั่ง ssh-keygen
หากใช้ค่าเริ่มต้นจะได้รับกุญแจแบบ RSA (ผมลองกุญแจแบบอื่นๆ แต่ใช้งานกับ MikroTik ไม่สำเร็จ) ในไฟล์ ~/.ssh/id_rsa
และกุญแจสาธารณะ ~/.ssh/id_rsa.pub
นำกุญแจสาธารณะเข้าไปผูกกับบัญชี โดยต้องอัพโหลดกุญแจสาธารณะเข้าไปยังไฟล์ก่อน แล้วผูกกับบัญชีผู้ดูแลระบบทางเมนู System > Users > SSH Keys > Import SSH Key เมื่อผูกบัญชีสำเร็จ เราสามารถล็อกอินผ่านทาง SSH ด้วยคำสั่ง ssh admin@[router IP]
ได้ทันที โดยไม่ถูกถามรหัสผ่านอีกต่อไป
เมื่อล็อกอินผ่าน SSH ได้แล้วให้เริ่มอิมพอร์ตใบรับรองโดเมนเข้าไปยัง MikroTik
cd ~/.acme.sh/[domain name]/ export router="ssh admin@[router IP]" scp fullchain.cer admin@[router IP]:fullchain.cer scp [domain name].key admin@[router IP]:private.key $router /certificate import file-name=fullchain.cer passphrase=\"\" $router /certificate import file-name=private.key passphrase=\"\"
ถึงขั้นตอนนี้หากเราเข้าไปดูเว็บ MikroTik ในเมนู System > Certificates ก็จะเห็นใบรับรองตามโดเมนที่เราจดทะเบียนมาแล้ว เช่น
กระบวนการหลังจากนี้จะเป็นการตั้งค่าใบรับรองเข้าไปยัง บริการของ MikroTik โดยบริการหลักคือหน้าเว็บ แต่เราสามารถใช้กับบริการอื่น เช่น API ด้วยเช่นกัน คำสั่งตั้งค่าเว็บให้เป็น HTTPS เป็น
$router /ip service set www-ssl certificate=fullchain.cer_0
ตัวบริการ www-ssl นี้ค่าเริ่มต้นบน MikroTik ไม่ได้เปิดใช้งานไว้ อาจจะต้องไปเปิดใช้งานเองก่อน
หากเราตั้งฟิลด์ A ของโดเมนไว้ตรงกับไอพีของเราท์เตอร์เราแล้ว เราจะพบว่าเราสามารถใช้งานเราท์เตอร์ผ่านทาง HTTPS ได้แล้ว
การขอใบรับรองจาก Let's Encrypt นั้นหลังจากขอครั้งแรกแล้ว acme.sh
จะตั้ง cron สำหรับขอต่ออายุใบรับรองโดยอัตโนมัติ เราควรนำคำสั่งสำหรับติดตั้งใบรับรองเข้าไปยัง MikroTik ไปเขียนเป็นสคริปต์รันใน cron ล้อไปพร้อมกันเพื่อให้เราท์เตอร์มีใบรับรองใหม่เสมอเช่นกัน
บทความนี้แสดงให้เห็นว่าเราสามารถทำให้การเชื่อมต่อกับบริการต่างๆ ภายในเน็ตเวิร์คของเราเองเป็น HTTPS ได้แล้วในยุคนี้ แม้การใช้งานตามบ้านอาจจะเกินความจำเป็นไปบ้างเนื่องจากความเสี่ยงที่จะถูกดักฟังหรือถูกคั่นกลางการเชื่อมต่อ (man-in-the-middle) นั้นค่อนข้างต่ำ แต่ในเน็ตเวิร์คที่มีขนาดใหญ่ขึ้นเช่นเน็ตเวิร์คระดับองค์กร ความเสี่ยงเหล่านี้เพิ่มขึ้นเป็นเงาตามตัว และการทำให้บริการทั้งหมดเป็น HTTPS ก็ช่วยให้ผู้ใช้ในองค์กรไม่ชินกับการเข้าเว็บไม่เข้ารหัส หรือเว็บที่ใช้ใบรับรองไม่ถูกต้องได้
บริการ DNS เช่น Hurricane Electric นั้นช่วยลดความยุ่งยากในการตั้งเซิร์ฟเวอร์ DNS ด้วยตัวเอง และหากในอนาคตไคลเอนต์ของ Let's Encrypt รองรับฟีเจอร์เต็มรูปแบบแล้ว องค์กรอาจจะสามารถกระจายความรับผิดชอบให้ผู้ดูแลเซิร์ฟเวอร์แต่ละตัวสามารถตั้งค่าไอพีด้วยตัวเองและขอใบรับรองเข้ารหัสด้วยตัวเอง โดยใช้โทเค็นสำหรับ Dynamic DNS ทำให้ไม่ต้องแชร์รหัสผ่านกันแต่อย่างใด
Comments
ตอนนี้มี remote เข้าบ้านแค่ Home Assistant โชคดีที่มันทำ DuckDNS + Let's Encrypt บน IPv6 อัตโนมัติได้เลย
ส่วน THDDNS ของ AIS เองทำใบรับรอง Let's Encrypt ไม่ผ่าน ?
สคริปต์น่าจะคล้ายๆ กันนี่ล่ะครับ
แอบเซ็งๆ อยู่ที่ MikroTik ไม่รองรับในตัวแบบนี้
lewcpe.com, @wasonliw
ของผมทำแบบบรรลัยโลกว่า ยิง DuckDNS ไป GCP แล้วขอ cert จากทางนั้น แล้วดาวน์โหลดกลับมาเก็บไว้ที่บ้านแล้วโยง DuckDNS กลับมาที่บ้านเหมือนเดิม 55555
มีข้อดียังไงบ้างครับ ขายบ้างๆ
จริง ๆ วิธีนี้ค่อนข้างยุ่งยากนะ แต่เป็นเพราะ 3BB ปิดพอร์ต 80 และ 443 (ซึ่งก็รู้ ๆ กันว่าเพราะอะไร) มันเป็นวิธีเดียวที่ผมจะขอ cert ได้ ตอนนี้ผมกำลังนึกหาวิธี automate อยู่ แต่ต้องศึกษา API ของ DuckDNS ถึงจะเริ่มทำได้ ตอนนี้ก็ setup แบบ manual ไปก่อน
ข้อดีอย่างเดียวเลยคือ มันหลบพอร์ต 3BB ได้ 555555 (ผมใช้แค่ไว้เปิด API กับ WebSocket)
ขอบคุณครับ
ผมภายในก็แบบนี้นะครับ มีตัวขอ cert ทุกชื่อที่เดียว แล้วค่อยกระจายข้างใน
lewcpe.com, @wasonliw
Microtik -> Mikrotik
ผมลดความยุ่งยากด้วยการซื้อ certificate ตัวถูก ๆ ที่ใช้การ validate ผ่านอีเมล หรือ DNS แล้วมีอายุ 1 ปีแทน ?
ปีละรอบก็ไม่ไหวแฮะ ใช้ไม่บ่อยแล้วมันลืม ยุ่งยาก
lewcpe.com, @wasonliw
ใช้ของ cloudflare เลยได้รึเปล่าครับ มันให้มาตั้ง 15 ปี
ตอนนี้ certificate ขอทีใช้ได้แค่ 1 ปีนิดๆ ครับ ยังไงก็ต้องเปลี่ยนทุกปีอยู่แล้ว
thanks for a great article krub :)
..: เรื่อยไป
DNS A record ผมใช้ script ในเว็บ Mikrotik เลยครับ
แล้วตั้ง Scheduler ไว้ให้ทำงานทุกๆ 10 นาที
Dynamic DNS Update Script for Hurricane Electric DNS
เสียดายตัวสคริปต์ของ MikroTik มันจำกัดมาก ไม่งั้นใส่ acme.sh ลงไปให้มันขอ cert ในตัวเลยจะเนียนกว่านี้มาก
lewcpe.com, @wasonliw