1.单向认证
单向认证SSL协议不需要客户拥有CA证书。站点部署了ssl证书就行,任何用户都可以去访问(IP被限制除外等),仅服务端提供身份认证。client需要一个ca.crt,服务器需要server.crt、server.key。
2.最简单的https server
2.1制作证书
openssl genrsa -out server.key 2048 openssl req -new -x509 -key server.key -out server.crt -days 365
2.2编写程序https.go
package main import( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi, This is a https service") } func main() { http.HandleFunc("/", handler) http.ListenAndServeTLS(":9090", "server.crt", "server.key", nil) }
2.3启动服务
go run https.go
2.4运行结果
curl -k https://127.0.0.1:9090
Hi, This is a https service
-k表示忽略验证证书,不验证服务端。
2.5调用代码
package main import( "fmt" "io/ioutil" "net/http" ) func main() { resp, err := http.Get("https://tim:9090") if err != nil { fmt.Println("error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
2.6运行结果
error: Get https://tim:9090: x509: certificate signed by unknown authority因为自己的证书未认证。
3.跳过证书验证
package main import ( "crypto/tls" "fmt" "io/ioutil" "net/http" ) func main() { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr} resp, err := client.Get("https://tim:9090") if err != nil { fmt.Println("error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
上面的tim需要注意,如果设置验证证书的话(TLSClientConfig: &tls.Config{InsecureSkipVerify: false}),那么需要验证两个东西,一个是上证书用的CN的名称一致。
x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs
另一个是证书是否权威签发,否则就是上面的unknown authority了如果设置成true,则无所谓了,不校验证书,当然不一致也无所谓了。
4.校验服务端
4.1安全建立连接
openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=tim" -days 5000 -out ca.crt openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=tim" -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
服务端不需要任何变化,但客户端需要ca证书。
package main import ( "crypto/tls" "crypto/x509" "fmt" "io/ioutil" "net/http" ) func main() { pool := x509.NewCertPool() caCertPath := "/mnt/go/src/test/clinet/ca.crt" caCrt, err := ioutil.ReadFile(caCertPath) if err != nil { fmt.Println("ReadFile err:", err) return } pool.AppendCertsFromPEM(caCrt) tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: pool}, } client := &http.Client{Transport: tr} resp, err := client.Get("https://tim:9090") if err != nil { fmt.Println("Get error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
4.2运行结果
Hi, This is a https service