# 告別 localhost:3000 — 反向代理完全上手指南 ![reverse-proxy-cover](https://hackmd.io/_uploads/rJMXTqyvbe.jpg) `localhost:3000` 是前端、`localhost:8080` 是 API、`localhost:5432` 是資料庫管理介面、`localhost:9000` 是另一個微服務... 我甚至得開一個備忘錄記錄哪個 port 是什麼服務,不然隔天醒來完全想不起來。 更慘的是,當我想測試一個需要 HTTPS 的功能時,瀏覽器跳出那個刺眼的「您的連線不安全」警告,點了好幾次「繼續前往」才能看到畫面。這種開發體驗,說實話,真的很差。 --- ## 反向代理:你的網站需要一個「前台」 怎麼說呢,你可以把反向代理想像成公司的前台。 想像一下:如果一間公司沒有前台,訪客直接闖進辦公區找人會發生什麼事?有人找工程部、有人找業務部、有人其實是來推銷的、有人根本走錯棟...整個辦公室會亂成一團。 所以公司會設一個前台。訪客先到前台,說明來意,前台確認身份後再引導到正確的部門。推銷員?直接擋掉。可疑人物?通報保全。 ![reverse-proxy-comparison](https://hackmd.io/_uploads/Hk2Ea91vZe.jpg) 反向代理做的就是這件事,只是場景換成了網路世界。 所有來自網路的請求,不會直接打到你的後端伺服器,而是先經過反向代理這個「前台」。反向代理會檢查請求、決定要轉發給哪個服務、處理一些雜事(像是 SSL 加解密),然後把回應送回給使用者。 你的後端服務們呢?它們只需要專心做自己的事,不用煩惱外面的世界有多混亂。 ### 正向 vs 反向,三秒區分 這兩個詞很容易搞混,我用一個簡單的方式區分: **正向代理**:幫「你」出去拿東西。你不想讓外面知道你是誰,所以派一個代理人出去。VPN 就是這個概念。 **反向代理**:幫「伺服器」接待客人。外面的人不知道裡面有幾台伺服器、長什麼樣子,只看到一個統一的入口。 一句話記住:正向保護客戶端,反向保護伺服器。 --- ## 它能幫你做什麼? 好,概念懂了,但反向代理到底能解決什麼問題? ### 統一入口,告別 port 地獄 這是我當初最有感的一點。有了反向代理,你可以這樣設定: - `myapp.local` → 前端服務 - `api.myapp.local` → API 服務 - `admin.myapp.local` → 管理後台 全部走 443 port,全部用漂亮的網址,再也不用記那些該死的 port 號。 ### 自動 HTTPS,一勞永逸 現在很多功能都需要 HTTPS 才能用:地理定位、相機存取、Service Worker... 在本地開發環境搞 HTTPS 以前是件很痛苦的事,要自己生憑證、設定信任、每次都要點「繼續前往不安全的網站」。 但有些反向代理工具(像 Caddy)可以自動幫你處理 SSL 憑證。在生產環境它會自動向 Let's Encrypt 申請免費憑證,在本地開發則可以搭配 mkcert 產生被系統信任的憑證。 ### 負載均衡 當你的服務開始有流量,一台伺服器撐不住的時候,反向代理可以幫你把請求分散到多台伺服器。這就是所謂的負載均衡。 ``` ┌─ Server 1 使用者 → 反向代理 ──┼─ Server 2 └─ Server 3 ``` 反向代理會用各種演算法(輪詢、最少連線、IP Hash)來決定要把請求送到哪台伺服器。 ### 安全防護 因為外部請求不會直接接觸到後端伺服器,所以: - 後端伺服器的真實 IP 被隱藏 - 可以在反向代理層做速率限制,擋掉惡意請求 - 可以設定 WAF(Web Application Firewall)過濾攻擊 - DDoS 攻擊打到的是反向代理,不是你的應用伺服器 ### 快取加速 反向代理可以快取靜態資源(圖片、CSS、JS),這樣重複的請求就不用每次都打到後端,大幅減少伺服器負擔。 --- ## 四大天王,怎麼選? ![reverse-proxy-software](https://hackmd.io/_uploads/BJjHT9yv-e.jpg) 市面上反向代理的選擇很多,但最常被拿出來討論的就是這四個:Nginx、Caddy、Traefik、HAProxy。 我花了不少時間研究和實測,簡單分享一下心得。 ### Nginx:穩如老狗的老將 Nginx 大概是最多人用的反向代理,從 2004 年就存在了。效能極強、資源消耗低、文件和社群資源超級豐富。 但說實話,它的設定檔對新手不太友善。光是要設定一個基本的反向代理,就要寫這麼一大段: ```nginx server { listen 443 ssl; server_name example.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` 如果你追求極致效能、需要非常細緻的控制,或是你已經很熟悉 Nginx,那它絕對是好選擇。 ### Caddy:簡單到不可思議的新星 Caddy 是這幾年竄起來的新選擇,主打「簡單」和「自動 HTTPS」。 同樣的功能,Caddy 的設定長這樣: ``` example.com { reverse_proxy localhost:3000 } ``` 沒了。就這三行。 HTTPS 憑證?它會自動幫你處理。HTTP 轉 HTTPS?預設就會。 我第一次用 Caddy 的時候真的有點驚訝,怎麼可以這麼簡單?效能雖然比 Nginx 稍微差一點,但對大多數應用來說根本感覺不出來。 如果你是新手,或是你只是想快速把事情搞定,Caddy 是我最推薦的選擇。 ### Traefik:為容器而生 如果你的服務都跑在 Docker 或 Kubernetes 上,Traefik 會讓你很驚豔。 它可以自動偵測 Docker 容器的啟動和關閉,不用手動改設定檔。你只要在 docker-compose.yml 裡加幾個 label,Traefik 就會自動幫你設定好路由。 ```yaml services: myapp: image: myapp labels: - "traefik.enable=true" - "traefik.http.routers.myapp.rule=Host(`myapp.local`)" ``` 缺點是學習曲線比較陡,概念也比較多(providers、routers、middlewares...),效能也是四個裡面最差的。但在容器環境裡,那個自動化的體驗真的很香。 ### HAProxy:負載均衡之王 HAProxy 專注在負載均衡這件事上,做到極致。很多大公司的高流量系統都用它。 但它不是 web server,沒有內建快取功能,設定也相對複雜。如果你的場景主要是「把流量分散到很多台伺服器」,HAProxy 是專業選擇。一般使用的話,Nginx 或 Caddy 就夠了。 ### 所以到底怎麼選? | 你的情況 | 推薦 | |---------|------| | 新手、想快速上手 | Caddy | | 追求極致效能 | Nginx | | Docker/Kubernetes 環境 | Traefik | | 大規模負載均衡 | HAProxy | | 不知道選什麼 | Caddy | --- ## 動手做:5 分鐘搞定本地開發環境 說了這麼多,來實際操作一下。我會用最簡單的方式,讓你在本地開發環境用上 HTTPS 和自訂域名。 ### 第一步:安裝 mkcert mkcert 是一個工具,可以產生被本機系統信任的 SSL 憑證。 ```bash # macOS brew install mkcert nss # 安裝本地 CA(只需要執行一次) mkcert -install ``` ### 第二步:產生憑證 ```bash # 在你的專案目錄下 mkdir certs && cd certs mkcert myapp.local "*.myapp.local" ``` 這會產生兩個檔案:`myapp.local+1.pem`(憑證)和 `myapp.local+1-key.pem`(私鑰)。 ### 第三步:設定 hosts 檔案 ```bash # 編輯 /etc/hosts(需要 sudo) sudo nano /etc/hosts # 加入這行 127.0.0.1 myapp.local api.myapp.local ``` ### 第四步:建立 Caddyfile ``` myapp.local { tls ./certs/myapp.local+1.pem ./certs/myapp.local+1-key.pem reverse_proxy localhost:3000 } api.myapp.local { tls ./certs/myapp.local+1.pem ./certs/myapp.local+1-key.pem reverse_proxy localhost:8080 } ``` ### 第五步:啟動 Caddy ```bash # 安裝 Caddy(如果還沒裝) brew install caddy # 啟動 caddy run ``` 完成。現在打開瀏覽器,輸入 `https://myapp.local`,你會看到漂亮的綠色鎖頭,連到你的前端服務。 如果你用 Docker Compose,可以把 Caddy 也容器化,整個開發環境一個 `docker-compose up` 就搞定。 --- ## 下一步 反向代理這個概念其實不複雜,但它能解決的問題比你想像的多。 從今天開始,試著在你的下一個專案用上它。不一定要用在生產環境,光是本地開發就能讓你的體驗好上很多。 當你開始習慣 `https://myapp.local` 這種開發方式,你就回不去了。 至於更進階的主題——雲端部署、安全配置、Kubernetes Ingress——那就是另一個故事了。 先把基礎打好,其他的慢慢來。 --- ## 延伸閱讀 - [Caddy 官方文件](https://caddyserver.com/docs/) - 深入了解 Caddy 的所有功能 - [Nginx 官方文件](https://nginx.org/en/docs/) - Nginx 完整參考 --- *如果這篇文章對你有幫助,歡迎分享給同樣在跟 port 地獄奮戰的朋友。*