服务器端对客户端的证书进行校验(双向证书校验),客户端访问服务器端,必须校验,如果跳过验证,客户端无法成功地建立与服务器之间的连接,也就是您在浏览器地址访问服务器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开发配置环境相关 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|