Golang 服务器端对客户端的证书进行校验(双向证书校验)

前端之家收集整理的这篇文章主要介绍了Golang 服务器端对客户端的证书进行校验(双向证书校验)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

服务器端对客户端的证书进行校验(双向证书校验),客户端访问服务器端,必须校验,如果跳过验证,客户端无法成功地建立与服务器之间的连接,也就是您在浏览器地址访问服务器api接口时,会同样象单向校验那样出现“Your connection is not secure”,即使您此时在浏览器页面上选择添加安全异常,也无法建立与服务器连接。

[root@contoso ~]# echo "192.168.10.100 zigoo.com" >> /etc/hosts ##配置IP到域名的映射,如果存在映射关系,跳过此条指令
[root@contoso ~]# more /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.100 zigoo.com
[root@contoso ~]#

[root@contoso ~]# tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构

/root/code/go/src/contoso.org
├── client
│ └── client.go
└── server
└── server.go

2 directories,2 files
[root@contoso ~]#

服务端可以要求对客户端的证书进行校验,以更严格识别客户端的身份,限制客户端的访问。
要对客户端数字证书进行校验,首先客户端需要先有自己的证书。接下来我们来建立我们自己的CA,需要生成一个CA私钥和一个CA的数字证书。

[root@contoso ~]# cd $GOPATH/src/contoso.org/client
[root@contoso client]# openssl genrsa -out ca.key 2048 ## 1). 生成一个CA私钥
Generating RSA private key,2048 bit long modulus
..........+++
...............................+++
e is 65537 (0x10001)
[root@contoso client]# openssl req -x509 -new -nodes -key ca.key -days 365 -out ca.crt ## 2).使用ca私钥生成客户端的数字证书

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.',the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GuangDong
Locality Name (eg,city) [Default City]:ShenZhen
Organization Name (eg,company) [Default Company Ltd]:ZiGoo
Organizational Unit Name (eg,section) []:
Common Name (eg,your name or your server's hostname) []:zigoo.com
Email Address []:24759362@qq.com
[root@contoso client]#
客户端:
私钥文件 ca.key
数字证书 ca.crt

[root@contoso client]#tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org
├── client
│ ├── ca.crt
│ ├── ca.key
│ └── client.go
└── server
└── server.go

2 directories,4 files
[root@contoso client]#

[root@contoso client]#openssl genrsa -out client.key 2048 ## 3).生成客户端的私钥
Generating RSA private key,2048 bit long modulus
..............................+++
............+++
e is 65537 (0x10001)
[root@contoso client]# openssl req -new -key client.key -out client.csr ## 4).使用客户端私钥生成数字证书请求
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,city) [Default City]:ShenZhen
Organization Name (eg,section) []:zigoo.com
Common Name (eg,your name or your server's hostname) []:zigoo.com
Email Address []:24759362@qq.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:12345678
An optional company name []: ## 直接按回车键跳过
[root@contoso client]# echo "extendedKeyUsage=clientAuth" >> client.ext ## 5). 创建客户端扩展配置信息
[root@contoso client]# openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile client.ext -out client.crt -days 365## 6). 使用客户端ca私钥和客户端扩展配置信息签发客户端的数字证书
Signature ok
subject=/C=CN/ST=GuangDong/L=ShenZhen/O=ZiGoo/OU=zigoo.com/CN=zigoo.com/emailAddress=24759362@qq.com
Getting CA Private Key
[root@contoso client]# tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org
├── client
│ ├── ca.crt
│ ├── ca.key
│ ├── ca.srl
│ ├── client.crt
│ ├── client.csr
│ ├── client.ext
│ ├── client.go
│ └── client.key
└── server
└── server.go

2 directories,9 files
[root@contoso client]#

重要提示
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 // 因为没有ExtKeyUsage信息,无法使用client.crt
证书中的ExtKeyUsage信息应该包含clientAuth,创建文件client.ext
内容

extendedKeyUsage=clientAuth

[root@contoso client]#cp ca.crt ca.key $GOPATH/src/contoso.org/server && cd $GOPATH/src/contoso.org/server
[root@contoso server]# openssl genrsa -out server.key 2048## 7). 生成服务器端的私钥
Generating RSA private key,2048 bit long modulus
................+++
.........+++
e is 65537 (0x10001)
[root@contoso server]# openssl req -new -key server.key -out server.csr## 8). 使用服务器端的私钥生成一个数字证书请求
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,your name or your server's hostname) []:zigoo.com
Email Address []:24759362@qq.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:12345678
An optional company name []:
[root@contoso server]# openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 ##使用客户端ca私钥签发服务器端的数字证书
Signature ok
subject=/C=CN/ST=GuangDong/L=ShenZhen/O=ZiGoo/OU=zigoo.com/CN=zigoo.com/emailAddress=24759362@qq.com
Getting CA Private Key
[root@contoso server]#
[root@contoso server]# tree $GOPATH/src/contoso.org -L 3 ##查看项目目录结构
/root/code/go/src/contoso.org
├── client
│ ├── ca.crt
│ ├── ca.key
│ ├── ca.srl
│ ├── client.crt
│ ├── client.csr
│ ├── client.ext
│ ├── client.go
│ └── client.key
└── server
├── ca.crt
├── ca.key
├── ca.srl
├── server.crt
├── server.csr
├── server.go
└── server.key

2 directories,15 files
[root@contoso server]#

服务器端:
私钥文件 server.key
数字证书 server.crt



## 注意 X509v3 Extended Key Usage, X509v3 extensions 和 TLS Web Client Authentication
## 这说明client.crt的Extended Key Usage已经添加成功

[root@contoso server]#cd $GOPATH/src/contoso.org/client
[root@contoso client]# openssl x509 -text -in client.crt -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 13079588882123393112 (0xb58408ca271d0858)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=CN,ST=GuangDong,L=ShenZhen,O=ZiGoo,CN=zigoo.com/emailAddress=24759362@qq.com
Validity
Not Before: Jun 25 11:04:44 2017 GMT
Not After : Jun 25 11:04:44 2018 GMT
Subject: C=CN,OU=zigoo.com,CN=zigoo.com/emailAddress=24759362@qq.com
Subject Public Key Info:
Public Key Algorithm: rSAEncryption
Public-Key: (2048 bit)
Modulus:
00:e4:40:41:bc:fa:31:e1:0a:ce:5f:d1:38:ab:88:
e9:24:d6:63:9f:e5:6e:5f:79:e9:31:c8:0d:8c:5f:
6d:22:c5:a5:71:92:f1:f8:67:d9:59:49:81:85:69:
24:83:c4:69:ea:f8:40:d3:c8:8e:ca:a8:ea:4a:af:
95:fa:8a:8d:20:d7:a4:11:78:bd:ae:cc:da:d0:bf:
c3:a6:e5:2a:a4:f3:99:8b:b9:37:e9:39:63:58:b1:
29:37:e4:c1:77:45:29:76:7a:b1:79:1c:d9:c6:07:
bc:e0:f9:25:55:f4:65:56:49:0f:d1:00:a2:c0:c9:
ae:b0:c2:02:c1:56:cb:a1:2c:e9:8b:5d:29:4d:74:
aa:e5:62:80:e0:b2:12:ba:9d:e5:ec:be:26:e9:b1:
15:72:c3:7f:93:39:62:51:5b:f3:14:90:9b:2e:64:
4c:3f:30:4a:dc:90:6b:1a:d8:50:a8:70:52:8c:d1:
f3:a7:e3:13:4d:29:29:d4:b3:5a:84:07:d6:8f:9f:
38:e6:1a:41:df:68:76:e8:06:61:26:fa:c5:25:be:
4f:9a:27:19:14:ad:2c:77:fb:24:c4:a3:46:a8:b0:
08:14:98:9a:29:44:42:a8:73:20:80:55:1a:9a:ec:
51:79:14:99:a5:eb:bb:77:81:f1:74:d6:fa:45:d7:
fc:f9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Extended Key Usage:
TLS Web Client Authentication

Signature Algorithm: sha1WithRSAEncryption
69:ba:09:84:82:2b:2b:69:6a:cd:00:4d:1a:5c:08:e5:55:39:
da:6a:72:c9:ba:70:a8:15:63:2b:f3:34:e5:a7:06:4a:5d:79:
28:84:68:9d:5c:9d:d7:88:b6:9d:48:7c:e9:47:39:4e:a5:69:
dc:ce:ff:58:52:69:ee:af:57:d9:10:c9:1b:34:d1:22:e0:99:
36:e6:32:3f:fa:fa:6d:01:13:1c:07:00:68:51:33:43:f7:a4:
d5:7a:dc:86:5b:4a:b9:87:7d:a5:c9:cd:1b:4f:19:4a:5c:cd:
54:8a:2e:9c:83:d0:c6:fc:f6:ff:e9:d5:2d:db:2b:8d:b7:95:
b0:5d:ae:7e:cb:15:77:81:b4:f8:0c:81:84:b9:bb:45:fe:ae:
27:c0:42:a9:4d:ac:c2:a3:17:0a:08:88:4f:02:68:4b:de:19:
c1:28:8a:96:30:b6:6a:b5:5e:a0:ed:44:27:1b:4a:45:8f:ff:
d7:d5:27:1c:d9:1e:e8:7a:59:2b:9f:9e:8f:52:73:72:7c:9e:
75:08:71:96:40:15:dc:7a:19:3c:45:9a:35:48:81:07:a8:dd:
d8:b7:f8:7f:4e:e0:59:07:a3:d2:11:a4:6c:94:d3:db:d0:ff:
79:85:9a:c0:a3:31:06:3c:95:85:dd:34:e1:19:d4:f0:b6:34:
2f:82:08:99
[root@contoso client]#


使用Go创建一个HTTPS Web Server

/root/code/go/src/contoso.org/server/server.go :

package main

import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/IoUtil"
"net/http"
)

type MyMux struct {
}

func (p *MyMux) ServeHTTP(res http.ResponseWriter,req *http.Request) {
fmt.Fprintf(res,"Hi,This is an example of https service in golang!\n")

fmt.Fprintf(res,
`[{"Name":"jason","Age":35,"Weight":60.3,"Speciality":"computer science","Hobby":["tennis","swimming","reading"],"score":725.5,"Secret":"SRRMb3ZlFFlvdSE="}]`)
}

func main() {
pool := x509.NewCertPool()
caCertPath := "ca.crt"

caCrt,err := IoUtil.ReadFile(caCertPath)
if err != nil {
fmt.Println("ReadFile err:",err)
return
}
pool.AppendCertsFromPEM(caCrt)

s := &http.Server{
Addr: ":8081",
Handler: &MyMux{},
TLSConfig: &tls.Config{
ClientCAs: pool,
ClientAuth: tls.RequireAndVerifyClientCert,
},
}

err = s.ListenAndServeTLS("server.crt","server.key")
if err != nil {
fmt.Println("ListenAndServeTLS err:",err)
}
}

使用Go创建一个HTTPS WebClient

/root/code/go/src/contoso.org/client/client.go :

package main

import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/IoUtil"
"net/http"
)

func main() {
pool := x509.NewCertPool()
caCertPath := "ca.crt"

caCrt,err)
return
}
pool.AppendCertsFromPEM(caCrt)

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},
}
client := &http.Client{Transport: tr}
resp,err := client.Get("https://zigoo.com:8081")
if err != nil {
fmt.Println("Get error:",err)
return
}
defer resp.Body.Close()
body,err := IoUtil.ReadAll(resp.Body)
fmt.Println(string(body))
}


[root@contoso ~]#cd $GOPATH/src/contoso.org/server ##服务器端路径
[root@contoso server]# go run server.go ##临时性非全局执行程序,注意,要先启动服务器端


[root@contoso ~]# cd $GOPATH/src/contoso.org/client ##客户端路径
[root@contoso client]# go run client.go ##临时性非全局执行程序,注意,要先启动服务器端
Hi,This is an example of https service in golang!
[{"Name":"jason","Secret":"SRRMb3ZlFFlvdSE="}]



[root@contoso ~]# cd $GOPATH/src/contoso.org/client &&
for i in `seq 1 100000`
do
echo $i " : " && go run client.go
done

以上指令可以多打开几个终端窗口,可以看看多个客户端连续请求HTTPS Web Server返回数据的效果

[root@contoso ~]#ulimit -n ##默认1024,客户端连接太多会报错:http: Accept error: accept tcp [::]:8081: accept4: too many open files; retrying in 1s
[root@contoso ~]#echo "* - nofile 409600" >> /etc/security/limits.conf ##修改文件描述符的大小,调整服务器的最大并发处理能力
[root@contoso ~]#echo "ulimit -n 409600" >> /etc/profile && source /etc/profile ##立即永久生效
[root@contoso ~]#more /etc/security/limits.conf

[root@contoso ~]#more /etc/profile

[root@contoso ~]# ulimit -a ##查看当前所有系统限制
core file size (blocks,-c) 0
data seg size (kbytes,-d) unlimited
scheduling priority (-e) 0
file size (blocks,-f) unlimited
pending signals (-i) 63359
max locked memory (kbytes,-l) 64
max memory size (kbytes,-m) unlimited
open files (-n) 1024
pipe size (512 bytes,-p) 8
POSIX message queues (bytes,-q) 819200
real-time priority (-r) 0
stack size (kbytes,-s) 8192
cpu time (seconds,-t) unlimited
max user processes (-u) 63359
virtual memory (kbytes,-v) unlimited
file locks (-x) unlimited
[root@contoso ~]# ulimit -n ##单独查看文件描述符
1024
[root@contoso ~]# cat /proc/sys/fs/file-max ##查看系统最大文件描述符
1607166
[root@contoso ~]# cat /proc/sys/fs/file-nr ##查看系统当前使用的描述符
7520 0 1607166

HTTPS Web Server 收到如下信息:
http: TLS handshake error from 192.168.10.100:50092: EOF
表示客户端强制退出与服务器端的连接

HTTPS Web Client 收到如下信息:

Get error: Get https://zigoo.com:8081: dial tcp 192.168.10.100:8081: getsockopt: connection refused

表示服务器端已关闭



[root@contoso ~]# cat /etc/profile
# System wide environment and startup programs,for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment,as this
# will prevent the need for merging in future updates.

pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}


if [ -x /usr/bin/id ]; then
if [ -z "$EUID" ]; then
# ksh workaround
EUID=`/usr/bin/id -u`
UID=`/usr/bin/id -ru`
fi
USER="`/usr/bin/id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"
fi

# Path manipulation
if [ "$EUID" = "0" ]; then
pathmunge /usr/sbin
pathmunge /usr/local/sbin
else
pathmunge /usr/local/sbin after
pathmunge /usr/sbin after
fi

HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
export HISTCONTROL=ignoreboth
else
export HISTCONTROL=ignoredups
fi

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

# By default,we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
umask 002
else
umask 022
fi

for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done

unset i
unset -f pathmunge

export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin

export GOPATH=~/code/go
export PATH=$PATH:$GOPATH/bin

unset MAILCHECK
ulimit -n 409600

[root@contoso ~]#


备注:以上红字标识前4行与Visual Studio Code开发配置环境相关

原文链接:https://www.f2er.com/go/188343.html

猜你在找的Go相关文章