開源軟體的雙面刃:免費背後的隱藏成本
每日例行地開啟最愛的 Save for later,準備觀看有哪些部落格更新、產品釋出新版本時,一行醒目的提示告訴你「我們即將關閉伺服器」。 錯愕,這是 2024 年十月底每一位 Omnivore App 難民的心情。 一、開源軟體的普及與迷思 說到開源軟體,不外乎就是 free 或是 freedom 的軟體,可以說是免費的軟體,也可以說是自由的軟體。 早期的 LAMP Stack 相較於 Microsoft 的 Windows Server、IBM 或是 Oracle 付費的服務,每個組件都是免費的,廣泛受到 Geek 到大中小型企業的使用 同時,開源軟體顧名思義是開放原始碼,在授權許可下可以自由使用、修改、分享,許多人將開源與安全劃上等號。 二、開源軟體的安全現況 多雙眼睛的侷限 即便開放原始碼,所有人都能查看開放原始碼,如果有任何 bug 或是安全漏洞,都「應該」會被發現。 我使用「應該」一詞,正因為許多人(包含我)在安裝開源軟體時,就如同安裝閉源軟體一樣,並不會查看全部的程式碼,確認安全後才進行安裝。而是做一個「大家都看過了,應該很安全」的假設。 例如當你想用 Nginx 取代 Apache 時,可能僅會比較兩者的 feature 與 benchmark,並不會查看內部 tcp socket 是如何管理等等,或是 buffer overflow 時的錯誤處理機制。 開源是否暴露更多漏洞? ####安全問題的挑戰 當我們將軟體開源,等於是將所有安全問題也給暴露了出來。 舉例來說,假如我們 self-hosted 一個 NAS 服務,這個 NAS 使用指定的 port 進行 web 與 API 的存取,例如 :8787。 當一個 Hacker 看到該 NAS 的 Auth 並沒有任何 rate limit,就可以直接在 NAS 內進行 port scan 或是 brute force 攻擊,取得這個 NAS 服務的控制權。...
Golang 1.22 中 http routing 的改進
Golang 作為一個偏向 server 應用的程式語言,一般的 web server 並不會直接使用原生的 package net/http,而更多的使用 gin-gonic/gin 或是 gorilla/mux,後來也有 labstack/echo 以及 go-chi/chi 等等選擇,在效能、輕量、好維護、好擴充中,都能找到對應的 third party package,其中的原因不外乎是原生的 package 提供的功能過於簡潔。 好在 1.22 中,官方改進了 net/http 中對於多工器、路由,甚至出了一篇部落格,現在更可以「大膽的」直接使用 standard library。 Path Parameter 若要將應用的 Web API 定義成 RESTful,我們會使用 /資源/{資源唯一識別符}/子資源/{子資源唯一識別符} 來定義路徑。假如要獲取一個使用者的訂單,則會使用 GET /users/1/orders 來獲取。在 1.22 以前,我們只能定義到 /users,再自行解析往後的 path: http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) { subPath := strings.TrimPrefix(req.URL.Path, "/users/") if len(subPath) == 0 { xxx } else { ooo } ... }) 而在 1.22 中新增了 net....
使用 TinyGo 與 Raspberry pi pico 實現溫濕度感測器
前言 作為嵌入式系統學習的微小專案,我決定使用 TinyGo 來實現一個簡單的溫濕度感測器。過去我大多使用 Arduino 作為微控制器(MCU)開發平台,但這次想嘗試使用 TinyGo 來進行單片機的學習。 TinyGo 是 Go 語言的一個子集,專門針對小型設備和微控制器進行了優化,使得我們可以在資源受限的硬體上運行 Go 程式。 全部的程式碼都可以到 omegaatt36/pico-bme280 中找到。 硬體選擇 Raspberry Pi Pico 我選擇了 Raspberry Pi Pico 作為本專案的主控板。Pico 是一款基於 RP2040 晶片的微控制器開發板,具有以下特點: 雙核 ARM Cortex-M0+ 處理器,時脈可達 133 MHz 264KB 的 SRAM 和 2MB 的板載閃存 支援 USB 1.1 主機和設備功能 低功耗睡眠和休眠模式 可編程 I/O(PIO)狀態機 30 個 GPIO 引腳 便宜 價格僅需要 5 美元,後繼款的 Pico 2 仍然維持 5 美元,還額外增加了 RISC-V 架構的支援,可以一次玩到兩種處理器架構。 Pico 的這些特性使其非常適合用於各種嵌入式專案,包括我們的溫濕度感測器。 BME280 感測器 最初我購買了 BMP280 感測器,但後來發現它只能測量溫度和氣壓,無法測量濕度。因此,我轉而選擇了 BME280 感測器,它可以同時測量溫度、濕度和氣壓。...
A smarter way to change directory: zoxide
在日常的開發工作中,我們經常需要在不同的目錄間切換。雖然 cd 命令已經足夠好用,但如果有一個更聰明的工具能記住我們最常用的目錄,並讓我們用最少的按鍵就能快速跳轉,那豈不是更棒? 這就是 zoxide 的用武之地。zoxide 是一個由 Rust 編寫的「更聰明的 cd 命令」,靈感來自 z 和 autojump。它會記住你最常使用的目錄,讓你只需輸入幾個字符就能快速跳轉。 zoxide 的主要特性 自動匹配: 不需要輸入完整路徑,zoxide 會根據輸入自動匹配最相關的目錄: 自動紀錄過去的目錄: zoxide 會記住你最常使用的目錄,讓你只需輸入幾個字符就能快速跳轉。這些資料可以使用 zoxide query 來查詢,或是 zoxide edit 來管理。 互動式選擇: 結合 fzf,可以互動式地選擇目標目錄 輕量快速: 用 Rust 編寫,啟動迅速,幾乎不會影響 shell 的啟動時間 安裝與配置 zoxide 的安裝可以參考 官方文件,我們就不多贅述了。 安裝完成後,我們需要在 shell 的配置文件中添加初始化命令。以 zsh 為例,在 ~/.zshrc 的末尾添加: eval "$(zoxide init zsh)" 重新打開終端或執行 source ~/.zshrc 後,zoxide 就可以使用了。 使用方法 zoxide 的基本用法非常直觀,經過自動執行 zoxide init zsh 後,我們可以使用 z 和 zi 自動匹配: ❯ ls boo bar baz ❯ z bo ❯ pwd /home/raiven/boo 即便沒有輸入完整路徑,也能夠自動匹配最相關的目錄 ❯ pwd /home/raiven/dev/omegaatt-blog ❯ z ❯ pwd /home/raiven ❯ z blog ❯ pwd /home/raiven/dev/omegaatt-blog 互動式選擇: ❯ zi ~ < 98/98(0) 296....
使用 Bitwarden 與自架後端 Vaultwarden 來管理密碼與 2FA Authenticator
在尋覓有哪些 self-hosted 專案好玩時,偶然發現了 1password、LastPass 的開源替代方案,甚至後端資料庫能自架,決定架來用用看。 使用 Bitwarden 來管理密碼 Bitwarden 是一款流行且功能強大的密碼管理工具,它提供了一個安全的方法來存儲和管理所有密碼。作為一個開源產品,Bitwarden 允許用戶選擇自行托管其服務,這意味著用戶可以在自己的服務器上運行 Bitwarden,從而更好地控制自己的數據安全。 Bitwarden 的特點 安全性: Bitwarden 使用端到端加密,確保只有您可以訪問您的密碼。 跨平台支持: 支持 Windows、macOS、Linux、Android 和 iOS。 易於使用: 提供直觀的用戶界面和簡單的操作流程。 開源: 開源,增加了透明度和安全性。 Bitwarden 同時支援基於時間的一次性密碼,讓 TOTP 也能自動填入。也能透過 github.com/scito/extract_otp_secrets 來提取 Google Authenticator 內的 2FA 資訊,儲存進 Bitwarden 中。 Bitwarden 開源了 client 與 server,在 server 端的選擇有以下: 使用 Bitwarden 提供的官方服務,又分為免費跟付費,但這個選擇就跟 1p 沒太多區別。 自架 Bitwarden 提供的 open source server,由於是使用 C# 與 mssql,吃的記憶體著實太多。 自架 Bitwarden 相容的後端,我採用的是 rust 實做的 Vaultwarden,搭配 sqlite,記憶體使用量與官方的 C# 不是一個量級的。 Bitwarden 架構 bitwarden 的 local storage 都是儲存加密後的密碼資料,不會使用明碼儲存,故上傳到 server 上的也僅僅是加密後的密碼資料。...
在 Firefox 上使用 PWA 將網頁應用安裝成 Desktop App
前言 開應用時,跨平台的桌面解決方案時常困擾開發者,在 Linux Desktop 上要支援多種桌面協議與桌面管理系統,更是複雜許多。時常會看到 Electron 等等基於 chromium 的技術。 當然也可以像是 zed.dev 這樣的 geek 精神,自己寫了一套跨平台的 GUI 框架,但多數新創公司可能沒有這些資源來實現。例如已經非常成熟的 Notion.so、Obsidian 等等都是基於 Electron 實現的。 我並非一個 anti-Electron 或是 deGoogle 的人,但試圖找到其他解決方案正式樂趣之所在。 PWA(Progressive Web App) 詳盡的 PWA 技術可以到 mozilla 的文件中查看,對我來說只要可以達到目的:可以在 Windows、Mac、Linux 上封裝成 Desktop Aplication 即可。 官方支援 mozilla 官方有一個文件針對「安裝網頁應用到桌面環境」的歷史講解,可以參考官方文件。 文中提到過去將網址「儲存」在桌面上的類似「書籤」的方法(SSB),以及與 PWA 的不同之處:PWA 的使用者資料是儲存在桌面環境中。 PWA Add-on 上述文件內有提到需要使用 Fan-maded 的 PWA Add-on 來安裝 PWA:Progressive Web Apps for Firefox by Filip Štamcar。 他是一個開源的 Firefox 擴充套件(filips123/PWAsForFirefox),具有完整的文件。 安裝過程 在 Firefox 瀏覽氣上安裝 PWA Add-on 瀏覽器會自動跳到設定頁面,首先會需要同意 EULA 接著會需要安裝 connector,需要透過該 connector 才能連結瀏覽器本身與 extension。 connector 由 Rust 編寫,使該 extension 可以在跨平台的桌面環境中管理 firefox 設定檔、runtime 等等未開放給 extension 存取的資源。 Windows: Windows 的 connector 除了手動安裝外,也推薦使用 winget 來安裝,類似於 apt/yum 的套件管理工具。 Linux Linux 的 connector 可以到 github release 上找到,例如我的作業系統是 OpenSUSE Tumbleweed,則可以下載 ....
透過內建的 pprof 工具來分析 Golang 發生的 memory leak
前言 某天下午,公司的 cronjob daemon 無預警的被 GCP OOM Kill 了,且程式碼沒有看出明顯的原因。 根據過去的經驗,local 開發時會使用 go tool pprof 來分析 CPU profile 或是 memory 與 trace 的問題,詳細可以參考 Go 官方文件。 由於我們的程式碼是一個基於 gin 的 http service,因此可以使用 gin 提供的 pprof 來快速建立 endpoint。 gin pprof gin 的 pprof package 提供了數個基於 net/http/pprof 的 endpoint,可以分別為: /: 基本的 pprof 的 static page,可以分析 CPU 與 memory 的問題。 /cmdline: 分析 command line 的問題。 /profile: 分析 CPU profile 的問題,可以透過 query string 來指定 CPU profile 的 duration。 /symbol: 分析 symbol table 的問題。 /trace: 分析 trace 的問題。 /goroutine: 分析 goroutine 的問題,這也是本文中重點查看的 endpoint。 /heap: 分析 heap 的問題。 可以在 http server 中加入以下程式碼來啟用 pprof:...
從實務經驗重新認識 TLS
因為工作需要部署 grafana,重新認識了 TLS 的流程,藉此機會把學習過程紀錄下來。 主要分為理論與案例分享兩個大章節,理論章節主要是在講「應該要知道但學過就會忘」的內行,案例分享則為這一次部署 grafana 時的經驗分享。 理論 介紹 TLS 是什麼 TLS(Transport Layer Security,傳輸層安全協議)是用來保護互聯網通訊安全的協議。它能夠確保數據在互聯網上傳輸過程中的機密性、完整性和真實性。TLS 是從 SSL(Secure Sockets Layer)發展而來的,因此我們可能也可以把它稱為 SSL/TLS。 為什麼需要 TLS 在現代互聯網環境中,數據安全性變得至關重要。無論是電商、網路銀行或是社交平台,都需要確保用戶的機敏資訊不會被攔截或篡改。TLS 可以加密通訊內容,防止第三方竊聽,並且能驗證通訊雙方的身份,防止中間人攻擊(MITM)。 TLS 的應用場景 TLS 被廣泛應用於各種需要保護數據傳輸的場景,包括但不限於: 網站和應用程式的 HTTPS 通訊 電子郵件的加密傳輸(如 SMTPS、IMAPS、POP3S) VPN 通訊 即時消息應用程式 各類雲服務和 API TLS 基本概念 公鑰加密和私鑰加密 公鑰加密和私鑰加密是 TLS 的基礎。每個參與通訊的實體都擁有一對密鑰:公鑰和私鑰。公鑰是公開的,任何人都可以用來加密訊息,而私鑰是保密的,只有擁有者可以用來解密訊息。這樣的機制確保了即使加密訊息被攔截,也只有擁有私鑰的人能夠解密,細節可以回顧密碼學或計算機概論。 對稱加密和非對稱加密 對稱加密使用相同的密鑰來加密和解密數據,而非對稱加密則使用一對密鑰(公鑰和私鑰)。TLS 結合了這兩種加密方式:在握手階段使用非對稱加密來安全地交換對稱加密的密鑰,之後的通訊則使用對稱加密來提高效率。 數位證書和證書授權機構(CA) 數位證書是用來證明公鑰擁有者身份的電子文件,通常由證書授權機構(CA)簽發。證書包含公鑰、擁有者訊息以及 CA 的數字簽名。瀏覽器和其他應用程式可以驗證證書的真實性,確保通訊對象的身份。 數位證書的主要類型有: 域名驗證(DV)證書:僅驗證域名的所有權。 組織驗證(OV)證書:除了驗證域名,還驗證組織的合法性。 擴展驗證(EV)證書:提供最高級別的驗證,包括嚴格的身份檢查,瀏覽器地址欄顯示綠色的公司名稱。 TLS 的工作原理 握手過程(Handshake Process) TLS 握手過程是建立安全連接的第一步,確保通訊雙方能夠安全地交換加密訊息。握手過程大致分為以下幾個步驟: 客戶端問候(Client Hello):客戶端發送一個問候消息給伺服器,包含支持的 TLS 版本、加密算法、隨機數和其他必要訊息。 伺服器問候(Server Hello):伺服器回應客戶端的問候消息,選擇一個加密算法,並發送伺服器的隨機數。 伺服器證書(Server Certificate):伺服器發送其數位證書給客戶端,用於驗證伺服器的身份。證書包含伺服器的公鑰和由 CA 簽名的證書。 密鑰交換(Key Exchange):伺服器和客戶端交換密鑰訊息,使用非對稱加密算法(如 RSA、ECDHE)安全地生成會話密鑰。這個會話密鑰將用於之後的對稱加密通訊。 加密通訊(Encrypted Communication):客戶端和伺服器使用協商好的會話密鑰進行加密通訊。這確保了後續的數據傳輸是安全的。 以 TLS 1....
透過 throughput 與 latency 的關係解決高延遲問題
在軟體工程中,我們常會面臨服務 high latency 的問題,而要解決這個問題,理解 throughput 與 latency 的關係是關鍵。 名詞定義 什麼是 throughput 與 latency? latency:指從 server 收到請求到回應的時間,通常以毫秒為單位計算。latency 越低,代表回應速度越快。 throughput:指 server 在特定時間內處理的請求數量,通常以每秒請求數(RPS 或 QPS)表示。throughput 越高,代表 server 處理能力越強。 server 如何工作 server 接收請求後,由一個或多執行緒(threads)處理請求並生成回應。單執行緒 server 一次只能處理一個請求,而多執行緒 server 可以同時處理多個請求。 舉例說明:自助洗衣店 latency:從顧客開始操作洗衣機到洗衣完成的時間。這包括顧客等候空閒洗衣機的時間,以及實際洗衣的時間。等候時間越長,latency 越高。 throughput:洗衣店每小時完成的洗衣次數。洗衣機數量越多,洗衣店能處理的顧客數量越多,throughput 越高。 latency 與 throughput 的關係 latency 與 throughput 之間存在緊密的關係,通常在系統負載增加時,latency 也會增加。當請求數量超過 server 的處理能力時,請求會被排隊等待處理,這就是 queueing latency。 例如,一個洗衣店有四台洗衣機,每台洗衣機需要30分鐘來完成一輪洗衣。當顧客數量增加,所有洗衣機都在運作時,新來的顧客需要等候空閒洗衣機,這樣就產生了 latency。如果每小時來的顧客數量超過洗衣機的處理能力,就會導致顧客排隊等候,latency 增加。 解決方法 增加處理能力:增加洗衣機的數量,提升洗衣店的最大 throughput。 增加洗衣機數量或開設更多分店,可以有效提升最大 throughput,減少顧客等候時間。 優化內部處理:降低單個洗衣過程的時間,減少內部 latency。 通過使用更高效的洗衣機,縮短洗衣時間,可以降低單次洗衣的時間。 實例分析 假設一個洗衣店有四台洗衣機,每台洗衣機需要30分鐘來完成一輪洗衣。當每小時來的顧客數量增加到5人時,洗衣店的最大 throughput 為每小時8人次,因此新來的顧客需要排隊等候空閒洗衣機,導致 latency 增加。通過增加洗衣機數量,可以提高洗衣店的最大 throughput,減少顧客排隊等候,降低 latency。...
基於 Golang 的 Grafana Dashboard 與 JWT 認證的前後端實作
在工作上有一個需求是需要做一些 OLAP,原訂計畫是使用 Google Looker(ver. Google Cloud Core),礙於量小不符合經濟效益,決定用 Grafana 這個較熟悉的開源套件來幫助我們做視覺化的處理。 這篇文章的範例可以在 omegaatt36/grafana-embed-example 中找到所有的 source code 我的 Use Case 為已經有一組 SHA512 產生的 Key,以下的內容為使用 HS512 進行簽名與認證。 流程 sequenceDiagram autonumber participant U as User participant B as Browser participant I as iframe participant S as Server participant G as Grafana rect rgb(236,239,244) U->>B: Open Web Page B->>S: Request JWT Token S->>B: Return JWT Token B->>I: Load iframe I->>G: Request Dashboard with JWT Token G->>I: Return Dashboard I->>B: Display Dashboard in iframe B->>U: Show Dashboard end Grafana 配置 主要是針對 grafana....