Natcha Luang - Aroonchai

Trust me I'm Petdo

Bangkok, Thailand

[Howto] ติดตั้ง Let's Encrypt SSL บน Google AppEngine

สิ่งที่น่าจับตามองอีกอย่างหนึ่งในช่วงนี้คือยุคของการเข้ารหัส website ใช่แล้ว! ต่อจากนี้ไปบราวเซอร์จะเริ่มแสดงข้อความเตือนบรรดา website ทั้งหลายที่ยังใช้งาน HTTP แบบไม่เข้ารหัสอยู่ ซึ่งก็มีหลายคนที่ไม่พร้อมสำหรับการเข้ารหัส website เป็นค่าเริ่มต้น เนื่องจากค่าใช้จ่ายต่อปีที่ถือว่าแพงพอสมควร ถึงแม้ว่า CloudFlare จะให้บริการ free SSL มาสักระยะแล้วก็ตาม แต่การ migrate ระบบไปอยู่บน CloudFlare สำหรับหน่วยงานที่ไม่ได้ถือครอง domain name เองก็คงจะเป็นเรื่องยุ่งยากไม่น้อย

แต่วันนี้เรามีบริการ free SSL ที่ชื่อว่า Let's Encrypt สำหรับสร้าง SSL certificate เองได้แล้ว มาดูวิธีการสร้างและติดตั้งบน Google AppEngine กันครับ

สารบัญ

CloudFlare และ Let's Encrypt แตกต่างกันอย่างไร?

สำหรับใครที่อาจจะสงสัยว่าระหว่างสองตัวนี้มีความแตกต่างกันอย่างไร​ ในเมื่อก็เป็นบริการฟรีเหมือนกัน? แล้วใครดีกว่ากันล่ะ?

ก่อนอื่นต้องบอกว่าหลักการทำงานของทั้งสองบริการนี้ คนละเรื่องกันเลย สำหรับ CloudFlare ให้บริการ free SSL ในรูปแบบของ MITM (man-in-the-middle) โดยบริการของ CloudFlare จะให้เราชี้ A/AAAA records เข้ามาที่ CloudFlare ทำให้ทุก request ที่เข้ามายัง website เราไม่ได้เข้าไปที่ server ตรง ๆ แต่เป็นการเรียก website ผ่านทาง CloudFlare อีกทีนึงนั่นเอง ทำให้ CloudFlare สามารถส่ง certificate มาพร้อม ๆ กับ packet ที่ร้องขอได้นั่นเอง

ส่วนของ Let's Encrypt จะเป็นบริการสร้าง SSL certificate ที่ได้รับการยอมรับจาก CA (Certificate Authority) ทำให้ certificate ที่ออกโดย Let's Encrypt จะเป็นสีเขียว แตกต่างกับ certificate ที่ออกด้วย openssl ตามปกติที่เรียกกันว่า self signed นั่นเอง

ถ้าจะเทียบให้เห็นภาพก็ประมาณนี้

CloudFlare

---------------      --------------                ----------
| Real server | ---> | CloudFlare | --- Cache ---> | Client |
---------------      --------------                ----------

Let's Encrypt

---------------      ----------
| Real server | ---> | Client |
---------------      ----------

ดังนั้นถ้าเทียบหลักการแล้ว Let's Encrypt จะยุ่งยากในการ signed certificate มากกว่าของ CloudFlare แน่นอนครับ อ่ะ! อย่าเพิ่งปิดเว็บไปสิครับ มาลองใช้งานกันก่อนถึงจะยุ่งยากก็ลองหน่อยน่ะ

วิธี generate SSL certificate

สำหรับคนที่รักความลำบากในชีวิต เรามาดูวิธีกันดีกว่าครับว่าจะสร้าง certificate file ได้ยังไง ขั้นตอนจะแตกต่างออกไปจากการ self signed ที่ใช้ openssl ในการสร้าง เนื่องจาก Let's Encrypt ได้เตรียมเครื่องมือมาให้เราพร้อมสำหรับใช้งานแล้วนั่นเอง

ก่อนอื่นต้องติดตั้ง GIT ลงในเครื่องกันก่อน วิธีติดตั้ง GIT จากนั้นให้ clone repository ของ Let's Encrypt ลงมาในเครื่อง

$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt

ทดลองเรียกใช้งานด้วยคำสั่งด้านล่าง เพื่อดูรายการ help

$ ./letsencrypt-auto --help

สำหรับคนที่ใช้ Mac จะมีคำเตือนว่ายังอยู่ในช่วง experimental สำหรับ Mac ต้องใส่ parameter --debug ต่อท้ายทุก ๆ คำสั่งด้วย

เท่าที่สังเกต Let's Encrypt จำเป็นจะต้องเขียนไฟล์ลงที่ /etc ดังนั้นแนะนำให้ run คำสั่งต่อจากนี้ด้วยสิทธิ์ระดับ root แทน

$ sudo -s

จากนั้นการ generate certificate ในครั้งนี้จะเป็นแบบ standalone ไม่จำเป็นต้องติดตั้ง Apache2 หรือ NGINX แต่สิ่งที่ต้องการคือ website ที่ติดตั้งอยู่ใน production ซึ่งในที่นี้ production ของเราก็คือ AppEngine เนื่องจากเราจำเป็นต้องสร้าง route สำหรับตอบกลับ challenge response ของ Let's Encrypt เพื่อ validation domain main

เริ่มต้นการสร้าง certificate ด้วยคำสั่ง

$ sudo ./letsencrypt-auto -a manual certonly -d www.example.com

ตรง www.example.com ก็เปลี่ยนชื่อเป็น domain name ของท่านเอง จากนั้นให้ enter จนกระทั้งเห็นข้อความแบบนี้ขึ้น และ อย่าเพิ่ง enter จนกว่าจะสร้าง route สำหรับ domain validation เรียบร้อยแล้ว

Let's Encrypt challenge

ที่วงไว้ในภาพด้านบนอันแรกคือส่วนของ challenge route และอันที่สองคือ challenge response โดยจะต้องส่ง response type กลับมาเป็น text/plain ด้วย

Domain name validation

ขั้นตอนต่อมาสำหรับทำ domain name validation ถ้าเป็น server ของเราเองอาจจะไม่ยุ่งยากสักเท่าไรนัก แต่ถ้าเป็น AppEngine เราจำเป็นต้องประกาศ route ใน app.yml ก่อน ซึ่งผมใช้ Go ในการสร้างเว็บไซต์ เลยจะเขียนตัวอย่างเป็น Go ด้วยแพคเกจ net/http แบบง่าย ๆ ตามนี้

app.yml

application: your-application-id
version: 1
runtime: go
api_version: go1

handlers:
  - url: /.well-known/acme-challenge/.*
    script: _go_app

main.go

package main

import (
  "fmt"
  "net/http"
)

func init() {
  http.HandleFunc("/.well-known/acme-challenge/bjDwYWcxzD6jrWkpEWOh2rkhy0kkpNlRh9oRp0AmUUU", func(rw http.ResponseWriter, r *http.Request) {
    rw.Header().Set("Content-Type", "text/plain")
    fmt.Fprintf(rw, "bjDwYWcxzD6jrWkpEWOh2rkhy0kkpNlRh9oRp0AmUUU.E87O2-1WmkH7T7ufHPSp2rTeOnn53FIH3FpMi9D7rOo")
  })
}

ตรงนี้ก็ให้เปลี่ยน route เป็นของท่านเอง และ response ก็ตามที่ Let's Encrypt สร้างให้

เมื่ออัพโหลด application ขึ้ง AppEngine เรียบร้อยแล้วถึงจะสามารถ enter ไปขั้นตอนถัดเพื่อให้ Let's Encrypt validate จนกว่าจะเรียบร้อย

เปิดใช้งาน SSL บน AppEngine

เมื่อเสร็จสิ้นขั้นตอน validate domain name เรียบร้อยแล้วเราจะได้ไฟล์ SSL key อยู่ที่ /etc/letsencrypt/live/www.example.com เราจะใช้คำสั่ง openssl เพื่อแปลง convert key สักเล็กน้อยเพื่อให้ใช้งานได้บน AppEngine

$ sudo openssl rsa -inform pem -outform pem -in /etc/letsencrypt/live/www.example.com/private.pem > private_converted.pem

จากนั้นให้อัพโหลดไฟล์​ cert.pem และ private_converted.pem ขึ้นที่ AppEngine เข้าไปที่ AppEngine > Settings > SSL Certificates > Upload a new certificate

Upload a new certificate

เมื่ออัพโหลดเสร็จสิ้นแล้วให้คลิกเข้าไปที่ SSL certificate จะมีหน้าต่างสำหรับ click เพื่อ enable SSL สำหรับแต่ละ domain name แบบนี้

Edit certificate

เลือก domain name ที่ต้องการก็เป็นอันเรียบร้อย และนี้คือตัวอย่าง SSL ที่ติดตั้งเรียบร้อยแล้ว

SSL certificate


อ้างอิง

Comments