昨天介紹了怎麼取得 Domain,再用 Cloudflare 的 DNS record 把名稱指向 EC2。不過,前面的教學仍然使用 http://。如果之後網站要讓使用者登入、填寫資料,這些內容在傳送途中,要怎麼避免被別人偷看或修改呢?
今天就來認識 HTTPS、TLS 與憑證,看看網站連線需要哪些保護!
之前我們使用的是超文字傳輸協定(Hypertext Transfer Protocol,HTTP),讓瀏覽器向網站發出請求,再由網站回傳頁面或資料。
但目前使用的 HTTP 連線沒有加密。有能力攔截這段網路流量的人,就可能讀取傳送中的內容,甚至修改回傳的網頁。
而安全超文字傳輸協定(Hypertext Transfer Protocol Secure,HTTPS),則透過**傳輸層安全性協定(Transport Layer Security,TLS)**保護 HTTP 通訊。可以先想成:原本的網站請求、回應,改在受到 TLS 保護的連線中傳送。
TLS 主要提供三種保護:
| 保護 | 在網站連線中做什麼 |
|---|---|
| 加密(Encryption) | 讓途中攔截到資料的人,無法直接讀出原本內容 |
| 完整性(Integrity) | 偵測傳輸中的資料是否被竄改,避免悄悄接受改過的內容 |
| 身分驗證(Authentication) | 協助瀏覽器確認,對方有資格代表正在造訪的網域 |
這裡的身分驗證,指的是瀏覽器對網站驗證;而使用者輸入帳號密碼登入,則是網站自己另外處理的功能。
另外,查資料時常看到的 SSL 憑證,所謂的 SSL 也就是安全通訊端層(Secure Sockets Layer),也是 TLS 的前身。而現代 HTTPS 使用的是 TLS。
昨天我們透過 DNS 找到 IP 後,瀏覽器還是需要確認:這個連上的 Server,真的是代表網址裡的名稱嗎?
這時就會用到 TLS 憑證(TLS Certificate)。它包含適用的 Domain name、公開金鑰(Public Key)、有效期間,以及簽發者等資訊。其中 Public Key 是可以分享,而對應的**私密金鑰(Private Key)則由網站端保管,用來在連線過程中證明其身分用的。
而公開網站的憑證通常由憑證授權機構(Certificate Authority,CA)**簽發。瀏覽器則是負責檢查憑證,例如名稱是否符合、是否在有效期間內,以及能否沿著簽發關係,連到自己信任的 CA。
Server 也需要有證明自己持有對應的 Private Key,才能避免有人只拿一張別人的公開憑證就冒充網站。
以 example.com 為例,就算讓 www.example.com 也指向同一台 EC2,仍要確保憑證涵蓋這兩個名稱。可以用一張憑證涵蓋兩者,也可以分別使用不同的憑證。指到相同 IP,不代表憑證就自動適用喔!
瀏覽器與 Server 建立 TLS 連線的過程,稱為 TLS 交握(TLS Handshake)。過程中會驗證網站身分、協商保護連線的方式與 Key,來保護後續的 HTTP 資料。
不一定。像我們要用的 Let's Encrypt 就是提供免費 TLS 憑證的 CA。
申請這類憑證時,需要證明自己能控制該 Domain。例如,依指定方式在網站提供驗證內容,或建立指定的 DNS Record,讓 CA 查驗。
這個過程可以透過自動化憑證管理環境(Automatic Certificate Management Environment,ACME)協定,由軟體完成申請與更新。
憑證是有有效期限,所以也必須要安排續期(Renewal),在到期前取得新的有效憑證。像是後面要使用的 Caddy,就能幫忙處理這些工作。
這裡驗證的是指 Domain 控制權。網站有 HTTPS,不代表網站內容或經營者一定可信;仿冒網站也是有可能替自己的 Domain 取得有效憑證,所以造訪時仍要看清楚名稱喔!
那我們的 Next.js 網站要怎麼加上 HTTPS 呢?
這個系列會使用 Caddy 網頁伺服器(Web Server),把它放在 Next.js 前面。瀏覽器先連到 Web Server,再由 Web Server 把請求轉交給原本的應用,收到回應後傳回瀏覽器。這種角色稱為反向代理(Reverse Proxy)。
127.0.0.1 是回送位址(Loopback Address),EC2 本機。而在這個架構中,Caddy 執行在 EC2 主機上,我們會讓 Docker 把 Next.js 的服務發布在 EC2 的 127.0.0.1:3000,供 Caddy 存取。這樣,瀏覽器到 EC2 的連線使用 HTTPS;Caddy 收到並解密請求後,再透過 EC2 內的 HTTP 連線交給 Next.js。TLS 的保護到 Caddy 為止,後面這段沒有加密,因此這裡明確限定在同一台 EC2 的部署方式。
Caddy 的**自動 HTTPS(Automatic HTTPS)功能,可以替設定中的 Domain 申請、續期憑證,並把 HTTP 請求重新導向(Redirect)**到 HTTPS。不過,Domain 解析、外部連線,以及憑證資料的保存位置等條件都要準備好,才能正常運作。
我們也會延續 Cloudflare 的 DNS only 模式。Cloudflare 負責回答名稱查詢,瀏覽器的網站連線直接交給 EC2 上的 Caddy。
今天可以先用電腦版 Chrome 開啟 Let's Encrypt 官網,點選網址左側的網站資訊圖示,查看連線狀態。
不同瀏覽器與版本的圖示可能不同,不一定是一個鎖頭。重點是查看瀏覽器對這段連線的判斷,而不是只看網址文字裡有沒有 https://。
回到自己的網站,HTTPS 的預設 Port 是 443,但只在 Security Group 開放 443,還不會讓原本的 HTTP 應用開始處理 TLS。
下一篇就來安裝與設定 Caddy,讓它接手 EC2 主機的 80/443,再把目前 Docker 的 -p 80:3000 改成僅供 EC2 本機存取的對應,最後驗證自己的 HTTPS 網站!