先說(shuō)雙向認(rèn)證吧,需要使用openssl生成相應(yīng)的證書(shū)(根證書(shū)、服務(wù)端證書(shū)、多套客戶(hù)端證書(shū))。(建議在linux環(huán)境下進(jìn)行操作),我是centos7。
部署模式大體如下:
客戶(hù)瀏覽器(或其他工具)《==ssl 雙向認(rèn)證的安全通道==》Nginx代理服務(wù)<-- 內(nèi)網(wǎng)非安全通道 -->web服務(wù)(tomcat 或其他)集群
一、Nginx雙向認(rèn)證
1.生成根秘鑰及證書(shū)
openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=CN/ST=HA/L=ZZ/O=topxx/OU=internet/CN=www.xx.top/emailAddress=xxxxxxx@qq.com"
2.生成服務(wù)端證書(shū)
openssl genrsa -des3 -out www.xxx.com.pem 1024
openssl rsa -in queue.qmx.top.pem -out www.xxx.com.key?
openssl req -new -key www.xxx.com.pem -out www.xxx.com.csr -subj "/C=CN/ST=HA/L=ZZ/O=xxx/OU=internet/CN=www.xxx.com/emailAddress=xxxxxx@qq.com"
3.根證書(shū)簽名服務(wù)端證書(shū)
openssl ca -policy policy_anything -days 1460 -cert ca.crt -keyfile ca.key -in www.xxx.com.csr -out www.xxx.com.crt
cat ca.crt >>? www.xxx.com.crt?
4.生成客戶(hù)端證書(shū) (需要在客戶(hù)機(jī)器上安裝)
openssl genrsa -des3 -out client.pem 2048
openssl req -new -key client.pem -out client-req.csr -subj "/C=CN/ST=XZ/L=LS/O=gsj/OU=gss/CN=www.clientdomain.com/emailAddress=xxxx@126.com"
openssl ca -policy policy_anything -days 1460 -cert ca.crt? -keyfile ca.key -in client-req.csr -out client.crt?
openssl pkcs12 -export -clcerts -in client.crt -inkey client.pem -out client.p12
客戶(hù)機(jī)器上雙擊p12文件,進(jìn)行安裝。如需要其他格式文件,使用openssl導(dǎo)出。
5.Nginx安裝(支持ssl模塊,已安裝過(guò)的,可以搜索教程,單單更新安裝ssl模塊)
cd /usr/local/src #進(jìn)入用戶(hù)目錄
wget http://nginx.org/download/nginx-1.15.0.tar.gz #下載最新版本nginx
tar -zxvf nginx-1.15.0.tar.gz #解壓
cd nginx-1.15.0 #進(jìn)入目錄
./configure --prefix=/opt/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre --with-http_realip_module --with-http_image_filter_module #檢測(cè)
說(shuō)明--prefix 指定安裝目錄
make #編譯
make install #安裝
6.Nginx ssl雙向認(rèn)證配置
server {
? listen 443;?
? server_name test.com www.test.com;?
? root html;?
? index index.html index.htm;?
? ssl on; ? ? ? ?#開(kāi)啟ssl?
? ssl_certificate? /usr/ssl/light.cn.crt;? ? #服務(wù)器證書(shū)位置?
? ssl_certificate_key /usr/ssl/light.cn.key;? #服務(wù)器私鑰?
? ssl_client_certificate /usr/ssl/ca.crt;? ? #CA證書(shū)用于驗(yàn)證客戶(hù)端證書(shū)的合法性?
? ssl_verify_client? ? ? on;? ? ? ? ? ? ? ? ? ? ? #開(kāi)啟對(duì)客戶(hù)端的驗(yàn)證?
? ssl_session_timeout 5m;? ? ? ? ? ? ? ? ? ? ? ? #session有效期,5分鐘?
? ssl_protocols TLSv1 TLSv1.1 TLSv1.2;?
? ssl_ciphers 'AES128+EECDH:AES128+EDH:!aNULL';? ? ? #加密算法?
? ssl_prefer_server_ciphers on;?
? location / {?
? ? proxy_pass? http://127.0.0.1:8080;?
? }? ? ? ?
}
7.吊銷(xiāo)證書(shū)
openssl ca -revoke client.crt -cert ca.crt -keyfile ca.key
openssl x509 -in rkz_client.crt -noout -serial -subject #查看證書(shū)序列號(hào)
echo 02 >> crlnumber #02是要吊銷(xiāo)的證書(shū)序號(hào)?
openssl ca -gencrl -out private/ca.crl #生成crl文件
openssl verify -crl_check -CRLfile ca.crl -CAfile ca.crt rkz_client.crt #檢查吊銷(xiāo)狀態(tài)
nginx 要想吊銷(xiāo)證書(shū)生效,需要加入: ssl_crl /opt/mykeys/ca.crl;
吊銷(xiāo)證書(shū)后nginx reload即可。
二、Golang https client 自簽名證書(shū)使用
package main
import (
? "crypto/tls"
? "crypto/x509"
? "fmt"
? "io/ioutil"
? "net/http"
)
func main() {
? pool := x509.NewCertPool()
? addTrust(pool, "./ca.crt") //添加信任的證書(shū),最好是服務(wù)端對(duì)應(yīng)的根證書(shū)
? cliCrt, err := tls.LoadX509KeyPair("./client.crt", "./client.key")
? if err != nil {
? ? ? fmt.Println("Loadx509keypair err:", err)
? ? ? return
? }
? tr := &http.Transport{
? ? ? TLSClientConfig: &tls.Config{
? ? ? ? RootCAs:? ? ? pool,
? ? ? ? Certificates: []tls.Certificate{cliCrt},
? ? ? ? //InsecureSkipVerify: true, //跳過(guò)驗(yàn)證服務(wù)端證書(shū)
? ? ? },
? }
? client := &http.Client{Transport: tr}
? resp, err := client.Get("https://www.xxx.com/myaction.do") //此處必須使用域名或者h(yuǎn)ost內(nèi)的別名
? if err != nil {
? ? ? fmt.Println("Get error:", err)
? ? ? return
? }
? defer resp.Body.Close()
? body, err := ioutil.ReadAll(resp.Body)
? fmt.Println(string(body))
}
func addTrust(pool *x509.CertPool, path string) {
? aCrt, err := ioutil.ReadFile(path)
? if err != nil {
? ? ? fmt.Println("ReadFile err:", err)
? ? ? return
? }
? pool.AppendCertsFromPEM(aCrt)
}
三、雙向認(rèn)證的websocket服務(wù)訪問(wèn)
package main
import (
????"crypto/tls"
????"crypto/x509"
????"io/ioutil"
????"log"
????"golang.org/x/net/websocket"
)
var origin = "https://queue.qmx.top/"
var url = "wss://queue.qmx.top/ws"
//
func addTrust(pool *x509.CertPool, path string) {
????aCrt, err := ioutil.ReadFile(path)
????if err != nil {
????????log.Println("ReadFile err:", err)
????????return
????}
????pool.AppendCertsFromPEM(aCrt)
}
//
func main() {
????//放置證書(shū)的目錄,僅需要跟證書(shū),客戶(hù)證書(shū)及客戶(hù)key即可
????capath := "/Users/myname/Downloads/ssl/demoCA/"
????pool := x509.NewCertPool()
????addTrust(pool, capath+"ca.crt")
????cliCrt, err := tls.LoadX509KeyPair(capath+"client.crt", capath+"client.key")
????if err != nil {
????????log.Println("Loadx509keypair err:", err)
????????return
????}
????//
????ws_cfg, err := websocket.NewConfig(url, origin)
????ws_cfg.TlsConfig = &tls.Config{RootCAs: pool,
????????Certificates: []tls.Certificate{cliCrt},
????}
????if err != nil {
????????log.Println("tls error:", err)
????????return
????}
????//構(gòu)建websocket連接
????ws, err := websocket.DialConfig(ws_cfg)
????if err != nil {
????????log.Println("dial error:", err)
????????return
????}
????log.Println(ws)
????//TODO websocket后續(xù)代碼可參考網(wǎng)上教程
}