GO 中如何设置 HTTPS 分享

GO 中如何设置 HTTPS 分享

先回顾一下上次说到关于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 协议》,转载必须注明作者和本文链接
关注微信公众号:阿兵云原生
讨论数量: 1

收获+1,高产高质 :clap:

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!