Try   HackMD

KTLS - Linux 核心中的 TLS 實作

contributed by < OscarShiang >

TLS 簡介

HTTPS 的 "S",原先是網景公司 (Netscape) 為了開發網路瀏覽器所研發的一款工具集合 SSL (Secure Socket Layer),經由 IETF 列入 RFC 標準後,稱作 TLS(Transport Layer Security)。
主要用於保障應用程式間的通訊不會遭到竊聽與竄改。

是一種 ULP(Upper Layer Protocol) ,可以在通訊協定上建立加密的機制,因此稱為傳輸層安全協定(TLS)

在協定上大致可分為兩個部分:

  1. Handshake protocol (交握協商): 透過雙方交握建立連線的機制並協調雙方要使用的加密演算法並交換金鑰
  2. Record protocol (加密與封裝): 將要傳送的資料運用交握時決定的演算法與金鑰進行加密並傳送

TLS in kernel

Facebook 與 RedHat 工程師共同開發的核心模組,主要專注於降低使用 TLS 所造成的系統負載

由於在使用 TLS 傳送靜態內容時需要先將資料讀到 user space 並進行加密,接著才能將加密後的資料傳送出去。而 Facebook 發現在使用 TLS 的過程中,會花費 2% 的 CPU 在處理 copy from/to user space ,還有 10% 的 CPU 用於加密。

而透過將 TLS 放到 kernel 中,不僅可以使用 kernel 內部已存在的加密系統來進行加密,更有機會可以使用 sendfile()splice() 這種系統呼叫來做到 Zero-Copy,加速資料的傳輸。

Dave Watson 原先想將 KTLS 做成一種 socket 的類型,即 ktls/af_ktls,但是將 KTLS 做成 socket 的類型無法讓使用者自由選用要使用 ipv4 或是其他的選項。

所以他們後續在 Linux Kernel 中發展出了 ULP (Upper Layer Protocol) 的機制。該機制最主要的用途就是將 TLS 獨立成另外一個網路的分層,只要將不同的 socket 設定與 KTLS 做綁定,就可以實現不同種類的 socket 都可以使用 KTLS

KTLS 已在 Linux 4.13 版本中整併至核心內部。

好處

  • 將 SSL 憑證集中在核心中統一保管,避免多個伺服器與應用程式分別或共同持有憑證所造成的問題
  • 將加密的工作移到 kernel space 中進行,增進資料的保密性,因為在 user space 中執行的程式有被竊聽的可能性。
  • 未來可以將加密與解密的操作交由硬體來處理,進一步減少 CPU 的負載。

TLS Handshake

建立 TLS 的連線機制與協調加密演算法的使用與交換金鑰

  • client Hello
    • 支援的 TLS 版本
    • 可使用的加密演算法集合 (Cipher Suite)
  • server hello
    • 伺服器所選擇的演算法集合 (Cipher Suite)
    • 伺服器的 CA(Certificate Authority)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Cipher Suite

主要包含以下內容:

  • Key Exchange Algorithm: 用以交換伺服器端與客戶端的金鑰
  • Bulk Encryption Algorithm: 用以加密要傳輸的資料
  • MAC Algorithm: 用以確保在傳輸的過程中資料沒有損壞

key exchange

保障在使用不安全的通道通訊可以取得金鑰,以進行接下來的通訊
主要使用下列的演算法來進行交換:

  • RSA
  • Diffie-Hellman key exchange

使用流程

在設定 user space server 之前,需要先確定 KTLS 的功能已經被開啟

$ lsmod | grep tls

如果尚未開啟的話,可以使用以下的指令開啟 KTLS

$ sudo modprobe tls

使用 modprobe 的好處在於載入該模組時會將該模組的相依模組一併載入到核心中

接著針對 server 進行設定:

  1. 利用 user-space 的 library 建立連線機制並決定要使用的加密演算法集合。
  2. 將取得的金鑰以及要使用的演算法使用 setsockopt(2) 傳送到 kernel 中保存以及後續使用。
  3. 在設定好後,即可以使用 KTLS socket 的 fd 進行標準的系統呼叫(如 read(2), write(2), sendfile(2), splice(2) 等等)
  4. 在使用這些系統呼叫傳送資料的過程中, kernel 就會將要傳輸的資料進行加密,並將接收到的資料解密後傳送回 user space 供應用程式使用。

使用 KTLS 與直接使用 user space library 的流程大致相同,唯一有差異的部分在於若是要使用 KTLS ,需要在使用 user space library 完成 handshake 後,將加密的參數利用 setsockopt 傳到 kernel 內部

TLS 1.3 的更動

  • 在 TLS 1.2 中如果要完成 handshake 需要兩階段的訊息往返
  • 在 TLS 1.3 中則改為一個階段即完成 handshake
  • 加入了 0-RTT(0 round trip time) 與 TLS false start 等功能,以減少 handshake 的時間成本

QUIC

由 Google 所推出的一款基於 UDP 的連線協定,目的在解決使用 TCP/IP 協定所遇到的封包缺失的問題

HTTP/3 (QUIC + TLS 1.3)

原先是由 Google 所研發的技術,是基於 UDP 的協定在搭配封包復原等等技術而成。目的在提升傳輸效率之外,減少使用無線、行動網路封包丟失的問題。

已被 IETF 接受,目前正在由專案小組進行標準化,而在 HTTP/3 的安全的部分就是使用 TLS 1.3 來保證其安全性。

截至今日已來到 draft-shade-quic-http2-mapping,目前還不是正式的標準(查看進度

TLS v1.3 Handshake Mechanism

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 簡化交握的過程
  • clientHello 與 Keyshare 的動作合併

Set up KTLS on server

  • OpenSSL
  • WolfSSL

因為目前 OpenSSL 的主要分支已更新到 1.x 版本,而在 ktls/af_ktls_test 中所使用的 OpenSSL 函式庫為 0.x 版本

如何在伺服器上使用 KTLS

因為 KTLS 著重處理 TLS 的加密與解密等環節,所以以方便性而言可以使用 OpenSSL, GnuSSL 等 user space 的函式庫來協助交握流程的操作

  • OpenSSL: IV, salt, key 等資訊保存在 EVP_CIPHER_CTX 中,預計在 OpenSSL 3.0 中支援 Linux KTLS
  • WolfSSL: 需要透過修改 API 以使用 KTLS
  • GnuTLS: 整體使用流程較為複雜

參考資料

  1. KTLS: Linux Kernel Transport Layer Security
  2. Kernel TLS and hardware TLS offload in FreeBSD 13
  3. Playing With Kernel TLS in Linux 4.13 and Go
  4. ktls/af_ktls-test
  5. ktls/af_ktls
  6. Optimization and implementation of AF_KTLS in user-space applications
  7. Linux 4.13/4.14内核中带来的ULP(Upper Layer Protocol)
  8. Linux Kernel TLS(KTLS), ULP 和OpenSSL的大坑
tags: linux2020