GO 中如何設定 HTTPS 分享

小魔童哪吒發表於2021-06-09

先回顧一下上次說到關於HTTP相關的知識點

HTTPS 是什麼?

說到 HTTPS 我們就來看看 HTTPS 是個啥

HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer),即超文字傳輸安全協議,是一種通過計算機網路進行安全通訊的傳輸協議

HTTPS 為啥會出現?

正是因為現有的HTTP在安全上有缺陷,為了解決身份認證的問題,保護交換資料的隱私與完整性,HTTPS 便出現了。

HTTP 的原理是啥?

那麼我們來說說HTTP簡單原理

  • 客戶端的瀏覽器先和伺服器建立連線,通過傳輸層的協議TCP來完成的。預設的TCP連線的埠號是80埠

  • 建立連線後,客戶端傳送請求給到服務端,格式為:

    • URL(統一資源識別符號)
    • 協議版本號
    • MIME資訊 (修飾符,客戶端的資訊,許可內容)
  • 伺服器收到請求後,給予回應,回應格式為

    • 狀態行
    • 協議版本號
    • 成功/錯誤 的程式碼
    • MIME資訊(服務端資訊,實體訊息,其他內容)

HTTPS 實際上是怎麼實現的呢?

應用安全套接層( SSL )作為 HTTP 應用的子層

  • HTTPS 對應使用使用443埠

  • HTTP 對應使用80埠

HTTPS 有啥作用?

  • 建立一個資訊保安通道,來保證資料傳輸的安全
  • 確認網站的真實性,凡是使用了 HTTPS 的網站,都可以通過點選瀏覽器位址列的鎖頭標誌來檢視網站認證之後的真實資訊,也可以通過 CA 機構頒發的安全簽章來進行查詢

那麼 HTTPS 和 HTTP 有啥區別?

  • HTTP 協議需要到 CA 申請證照,一般免費證照很少,大多是需要花錢買的

  • HTTP 是超文字傳輸協議,資訊是明文傳輸,HTTPS 則是具有安全性的ssl加密傳輸協議。

  • HTTP 和 HTTPS 使用的是完全不同的連線方式,用的埠也不一樣

  • HTTP 的連線很簡單,是無狀態的

  • HTTPS 協議是由 SSL / TLS + HTTP協議 構建的可進行加密傳輸、身份認證的網路協議,比HTTP 協議安全。

說到這裡,那麼 SSL 是個啥?

是一種安全協議

目的是為網路通訊提供安全及資料完整性才有的這個協議

SSL協議分為2層:

  • SSL記錄協議(SSL Record Protocol)

SSL他是在傳輸層協議上面的,他可以為高層協議提供資料封裝壓縮加密等基本功能的支援

  • SSL握手協議(SSL Handshake Protocol)

用於在實際的資料傳輸開始之前,通訊雙方進行身份認證協商加密演算法交換加密金鑰等。

SSL協議能夠提供哪些服務呢?

簡單說下 SSL 協議能夠提供哪些服務:

  • 認證使用者和伺服器,確保資料傳送到正確的客戶機和伺服器

  • 加密資料以防止資料中途被竊取

  • 維護資料的完整性,確保資料在傳輸過程中不被改變。

那麼HTTPS涉及了哪些加密演算法呢?

  • 加密:RSA / DH

DH演算法解決了金鑰在雙方不直接傳遞金鑰的情況下完成金鑰交換,感興趣的小夥伴的進一步詳細瞭解一下

  • 身份驗證 / 數字簽名:RSA 演算法

RSA 簽名 的數學邏輯與 RSA加密 完全一致。只是顛倒使用了私鑰與公鑰。

RSA 公開金鑰密碼體制的原理是:

根據數論,尋求兩個大素數比較簡單,而將它們的乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密金鑰

加密簡單流程

解密簡單流程

RSA 非對稱加密演算法 原理:

雙方都得到了會話金鑰,拿到公鑰的一方先生成隨機的會話金鑰,然後利用公鑰加密它;再把加密結果發給對方,對方用私鑰進行解密

先分享這些基本的點,關於 HTTPS 細節原理,加密演算法原理以及程式碼具體實現,我們後續再進行細化 , 接下來我們繼續我們的主題,GO 如何設定 HTTPS

GO 如何設定 HTTPS

img

Golang 中設定HTTPS,需要用到一箇中介軟體,

沒錯,不用我們自己實現底層,我們可以站在巨人的肩膀上進行繪製巨集偉藍圖

這個中介軟體是 Secure

是 Go 的 HTTP 中介軟體,可促進快速獲得安全性。

Secure是一個標準的net / http Handler,可以與許多框架一起使用,直接與 Go 的 net / http 包一起使用也是沒有問題的

package main

import (
   "github.com/unrolled/secure"
   "net/http"
)

var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   w.Write([]byte("<h1>hello xiaomotong!!</h1>"))
})

func main() {
   secureMid := secure.New(secure.Options{
      AllowedHosts:          []string{"hello\\.com", ".*\\.hello\\.com"},
      AllowedHostsAreRegex:  true,
      HostsProxyHeaders:     []string{"X-Forwarded-Host"},
      SSLRedirect:           true,
      SSLHost:               "ssl.hello.com",
      SSLProxyHeaders:       map[string]string{"X-Forwarded-Proto": "https"},
      STSSeconds:            21365000,
      STSIncludeSubdomains:  true,
      STSPreload:            true,
      FrameDeny:             true,
      ContentTypeNosniff:    true,
      BrowserXssFilter:      true,
      ContentSecurityPolicy: "script-src $NONCE",
      IsDevelopment:         true,
   })

   handler := secureMid.Handler(myHandler)
   http.ListenAndServe("127.0.0.1:8888", handler)
}

我們在開發除錯的時候 將 引數 IsDevelopment 設定 為 true 即可

如果IsDevelopmenttrue則AllowedHosts,SSLRedirect,STS頭和HPKP頭將無效。

我們在開發的時候,就預設使用HTTP,否則會被重定向到HTTPS

這使您可以在開發/測試模式下工作,而不必進行任何惱人的重定向到HTTPS(即,開發可以在HTTP上進行),或者阻止localhost主機出現問題。

我們來看看Options的引數

// Options is a struct for specifying configuration options for the secure.Secure middleware.
type Options struct {
   // If BrowserXssFilter is true, adds the X-XSS-Protection header with the value `1; mode=block`. Default is false.
   BrowserXssFilter bool // nolint: golint
   // If ContentTypeNosniff is true, adds the X-Content-Type-Options header with the value `nosniff`. Default is false.
   ContentTypeNosniff bool
   // If ForceSTSHeader is set to true, the STS header will be added even when the connection is HTTP. Default is false.
   ForceSTSHeader bool
   // If FrameDeny is set to true, adds the X-Frame-Options header with the value of `DENY`. Default is false.
   FrameDeny bool
   // When developing, the AllowedHosts, SSL, and STS options can cause some unwanted effects. Usually testing happens on http, not https, and on localhost, not your production domain... so set this to true for dev environment.
   // If you would like your development environment to mimic production with complete Host blocking, SSL redirects, and STS headers, leave this as false. Default if false.
   IsDevelopment bool
   // nonceEnabled is used internally for dynamic nouces.
   nonceEnabled bool
   // If SSLRedirect is set to true, then only allow https requests. Default is false.
   SSLRedirect bool
   // If SSLForceHost is true and SSLHost is set, requests will be forced to use SSLHost even the ones that are already using SSL. Default is false.
   SSLForceHost bool
   // If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
   SSLTemporaryRedirect bool
   // If STSIncludeSubdomains is set to true, the `includeSubdomains` will be appended to the Strict-Transport-Security header. Default is false.
   STSIncludeSubdomains bool
   // If STSPreload is set to true, the `preload` flag will be appended to the Strict-Transport-Security header. Default is false.
   STSPreload bool
   // ContentSecurityPolicy allows the Content-Security-Policy header value to be set with a custom value. Default is "".
   ContentSecurityPolicy string
   // ContentSecurityPolicyReportOnly allows the Content-Security-Policy-Report-Only header value to be set with a custom value. Default is "".
   ContentSecurityPolicyReportOnly string
   // CustomBrowserXssValue allows the X-XSS-Protection header value to be set with a custom value. This overrides the BrowserXssFilter option. Default is "".
   CustomBrowserXssValue string // nolint: golint
   // Passing a template string will replace `$NONCE` with a dynamic nonce value of 16 bytes for each request which can be later retrieved using the Nonce function.
   // Eg: script-src $NONCE -> script-src 'nonce-a2ZobGFoZg=='
   // CustomFrameOptionsValue allows the X-Frame-Options header value to be set with a custom value. This overrides the FrameDeny option. Default is "".
   CustomFrameOptionsValue string
   // PublicKey implements HPKP to prevent MITM attacks with forged certificates. Default is "".
   // Deprecated: This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible.
   PublicKey string
   // ReferrerPolicy allows sites to control when browsers will pass the Referer header to other sites. Default is "".
   ReferrerPolicy string
   // FeaturePolicy allows to selectively enable and disable use of various browser features and APIs. Default is "".
   // Deprecated: This header has been renamed to Permissions-Policy.
   FeaturePolicy string
   // PermissionsPolicy allows to selectively enable and disable use of various browser features and APIs. Default is "".
   PermissionsPolicy string
   // SSLHost is the host name that is used to redirect http requests to https. Default is "", which indicates to use the same host.
   SSLHost string
   // AllowedHosts is a list of fully qualified domain names that are allowed. Default is empty list, which allows any and all host names.
   AllowedHosts []string
   // AllowedHostsAreRegex determines, if the provided slice contains valid regular expressions. If this flag is set to true, every request's
   // host will be checked against these expressions. Default is false for backwards compatibility.
   AllowedHostsAreRegex bool
   // HostsProxyHeaders is a set of header keys that may hold a proxied hostname value for the request.
   HostsProxyHeaders []string
   // SSLHostFunc is a function pointer, the return value of the function is the host name that has same functionality as `SSHost`. Default is nil.
   // If SSLHostFunc is nil, the `SSLHost` option will be used.
   SSLHostFunc *SSLHostFunc
   // SSLProxyHeaders is set of header keys with associated values that would indicate a valid https request. Useful when using Nginx: `map[string]string{"X-Forwarded-Proto": "https"}`. Default is blank map.
   SSLProxyHeaders map[string]string
   // STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header.
   STSSeconds int64
   // ExpectCTHeader allows the Expect-CT header value to be set with a custom value. Default is "".
   ExpectCTHeader string
   // SecureContextKey allows a custom key to be specified for context storage.
   SecureContextKey string
}

感興趣同學可以詳細的瞭解一下 secure 包中的每個引數細節

我們來看看 如何 將HTTP重定向到 HTTPS

HTTP 重定向到 HTTPS

我們的服務起來後,預設訪問本機的 localhost:8888, 會被 HTTPS 重定向到lcoalhost:4433

package main

import (
   "log"
   "net/http"

   "github.com/unrolled/secure"
)

var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   w.Write([]byte("<h1>hello xiaomotong!! HTTPS </h1>"))
})

func main() {
   secureMiddleware := secure.New(secure.Options{
      SSLRedirect: true,
      // 這在生產中是可選的。預設行為是將請求重定向到 HTTPS 協議
      SSLHost:     "localhost:4433",
   })

   han := secureMiddleware.Handler(myHandler)

   // HTTP
   go func() {
      log.Fatal(http.ListenAndServe(":8888", han))
   }()

   log.Fatal(http.ListenAndServeTLS(":4433", "cert.pem", "key.pem", han))
}

程式碼中的 兩個檔案

  • cert.pem
  • key.pem

可以通過如下命令生成,將生成檔案放到程式碼同級目錄即可

go run $GOROOT/src/crypto/tls/generate_cert.go --host="localhost"

實際效果

  • 服務開啟後,訪問本機的 localhost:8888,會被 HTTPS 重定向到lcoalhost:4433
  • 第一次執行第一步後,瀏覽器會彈出一個不安全的頁面, 點選 繼續 即可看到我們的重定向結果頁面

總結

  • 簡單 分享了 HTTPS , HTTPS 和HTTP的區別
  • SSL 是什麼,涉及到的加密演算法
  • Golang中設定 HTTP 重定向到 HTTPS , 希望對你有點幫助

歡迎點贊,關注,收藏

朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力

好了,本次就到這裡,*下一次 GO的併發程式設計分享 *

技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章