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