前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >go https 笔记

go https 笔记

作者头像
solate
发布于 2019-07-22 09:54:27
发布于 2019-07-22 09:54:27
87800
代码可运行
举报
文章被收录于专栏:solate 杂货铺solate 杂货铺
运行总次数:0
代码可运行

理解为运行在SSL(Secure Sockets Layer)或TLS(Transport Layer Security)协议所构建的安全层之上的HTTP协议

SSL和TLS

SSL/TLS协议运行机制的概述

图解SSL/TLS协议

自建证书

在使用https 之前,需要自己建立一个证书, 以便测试使用。正式使用需要去权威的CA机构申请证书。

自建证书配置HTTPS服务器

使用Go实现TLS 服务器和客户端

这个时候需要用到openssl 但是低版本的是有漏洞的,需要升级一下。

openssl是一个开源程序的套件、这个套件有三个部分组成:

  1. libcryto,这是一个具有通用功能的加密库,里面实现了众多的加密库;
  2. libssl,这个是实现ssl机制的,它是用于实现TLS/SSL的功能;
  3. openssl,是个多功能命令行工具,它可以实现加密解密,甚至还可以当CA来用,可以让你创建证书、吊销证书。

mac 安装升级openssl

其他系统使用连接中的方式下载升级, 因为我用的mac, 升级过程碰到一些问题,所以这里记一下。

OSX 有一个系统完整性保护,所以没权限删除系统自带的openssl, 但是我们不需要删除,只需要做软连接就可以解决

  1. 确认环境变量 $PATH
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo $PATH //打印环境变量

/usr/local/bin:<....>:/usr/bin:/bin

设置/usr/local/bin/usr/bin 之前,这样保证我们设置到/usr/local/bin先起作用。

如果不是这样,就需要设置$PATH

  1. 修改 $PATH
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo $SHELL   //确认自己使用的shell

/bin/bash  //修改 ~/.bash_profile/bin/zsh  //修改 ~/.zshrc
  1. homebrew 安装和软连接
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
brew install openssl

brew link openssl

//如果失败 加参数 --farce

brew link openssl --farce
  1. 新打开终端, 查看版本
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
openssl version -a

证书生成

服务器端的证书生成

互联网全站HTTPS的时代已经到来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//生成服务器端的私钥, 要使用2048位生成,1024位已经不安全了, 看上面的链接
openssl genrsa -out server.key 2048

//生成服务器端证书
openssl req -new -x509 -key server.key -out server.pem -days 365
客户端的证书生成
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//生成客户端的私钥
openssl genrsa -out client.key 2048

//生成客户端的证书
openssl req -new -x509 -key client.key -out client.pem -days 365

go https 实现

Go和HTTPS

服务端

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w,
        "Hi, This is an example of https service in golang!")
}

func main() {
	http.HandleFunc("/", handler)
	//server.crt  服务端证书地址
	//server.key  服务端私钥地址
	http.ListenAndServeTLS(":8081", "server.crt", "server.key", nil)
}

让这个例子能先Run起来,我们在程序所在目录先执行下面命令,利用openssl生成server.crt和server.key文件,供程序使用.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
openssl genrsa -out server.key 2048

openssl req -new -x509 -key server.key -out server.crt -days 365

显示为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$openssl genrsa -out server.key 2048

Generating RSA private key, 2048 bit long modulus
…………….+++
……………+++
e is 65537 (0×10001)

$openssl req -new -x509 -key server.key -out server.crt -days 365

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) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost   //这里注意输入
Email Address []:

然后 go run test.go 运行

在浏览器中输入 https://localhost:8081 , 忽略继续后,返回结果

或者使用 curl -k https://localhost:8081 测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
注意如果不加-k,curl会报如下错误:

$curl https://localhost:8081
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the –cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or –insecure) option.

客户端 :

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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://localhost:8081")

    if err != nil {
        fmt.Println("error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

go tcp 证书使用

服务器证书的使用

服务端代码:

首先从上面我们创建的服务器私钥和pem文件中得到证书cert,并且生成一个tls.Config对象。这个对象有多个字段可以设置,本例中我们使用它的默认值。 然后用tls.Listen开始监听客户端的连接,accept后得到一个net.Conn,后续处理和普通的TCP程序一样。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main
import (
	"bufio"
	"crypto/tls"
	"log"
	"net"
)
func main() {
	cert, err := tls.LoadX509KeyPair("server.pem", "server.key")
	if err != nil {
		log.Println(err)
		return
	}
	config := &tls.Config{Certificates: []tls.Certificate{cert}}
	ln, err := tls.Listen("tcp", ":443", config)
	if err != nil {
		log.Println(err)
		return
	}
	defer ln.Close()
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		go handleConn(conn)
	}
}
func handleConn(conn net.Conn) {
	defer conn.Close()
	r := bufio.NewReader(conn)
	for {
		msg, err := r.ReadString('\n')
		if err != nil {
			log.Println(err)
			return
		}
		println(msg)
		n, err := conn.Write([]byte("world\n"))
		if err != nil {
			log.Println(n, err)
			return
		}
	}
}

客户端代码:

InsecureSkipVerify用来控制客户端是否证书和服务器主机名。如果设置为true,则不会校验证书以及证书中的主机名和服务器主机名是否一致。 因为在我们的例子中使用自签名的证书,所以设置它为true,仅仅用于测试目的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main
import (
	"crypto/tls"
	"log"
)
func main() {
	conf := &tls.Config{
		InsecureSkipVerify: true,
	}
	conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	n, err := conn.Write([]byte("hello\n"))
	if err != nil {
		log.Println(n, err)
		return
	}
	buf := make([]byte, 100)
	n, err = conn.Read(buf)
	if err != nil {
		log.Println(n, err)
		return
	}
	println(string(buf[:n]))
}

客户端证书的使用

客户端:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main
import (
	"crypto/tls"
	"log"
)
func main() {
	conf := &tls.Config{
		InsecureSkipVerify: true,
	}
	conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	n, err := conn.Write([]byte("hello\n"))
	if err != nil {
		log.Println(n, err)
		return
	}
	buf := make([]byte, 100)
	n, err = conn.Read(buf)
	if err != nil {
		log.Println(n, err)
		return
	}
	println(string(buf[:n]))
}

因为需要验证客户端,我们需要额外配置下面两个字段

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ClientAuth:   tls.RequireAndVerifyClientCert,
ClientCAs:    clientCertPool,

然后客户端也配置这个clientCertPool

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main
import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"log"
)
func main() {
	cert, err := tls.LoadX509KeyPair("client.pem", "client.key")
	if err != nil {
		log.Println(err)
		return
	}
	certBytes, err := ioutil.ReadFile("client.pem")
	if err != nil {
		panic("Unable to read cert.pem")
	}
	clientCertPool := x509.NewCertPool()
	ok := clientCertPool.AppendCertsFromPEM(certBytes)
	if !ok {
		panic("failed to parse root certificate")
	}
	conf := &tls.Config{
		RootCAs:            clientCertPool,
		Certificates:       []tls.Certificate{cert},
		InsecureSkipVerify: true,
	}
	conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	n, err := conn.Write([]byte("hello\n"))
	if err != nil {
		log.Println(n, err)
		return
	}
	buf := make([]byte, 100)
	n, err = conn.Read(buf)
	if err != nil {
		log.Println(n, err)
		return
	}
	println(string(buf[:n]))
}

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用 GoLang 获取 TLS 的 Client Hello Info
TLS(Transport Layer Security)是一个保证信息安全的应用层协议。它的前身是 SSL(Secure Socket Layer)。它是一套定义了如何对由 TCP 传输的报文进行加密的协议。
饶文津
2020/07/14
3.4K0
使用 GoLang 获取 TLS 的 Client Hello Info
golang简单tls协议用法完整示例
本文实例讲述了golang简单tls协议用法。分享给大家供大家参考,具体如下: 生成私钥: openssl genrsa -out key.pem 2048 生成证书: openssl req -new -x509 -key key.pem -out cert.pem -days 3650 https: package main import ( "io" "net/http" "log" ) func HelloServer(w http.ResponseWriter, req *
李海彬
2018/03/26
3.3K0
go-https的简单实现
X.509 Certificate Signing Request (CSR) Management.
fnatic
2022/07/22
24.7K0
为GRPC证书加入双向证书认证如此简单
上一篇文章我们讲解了怎么给 GRPC 配置添加单向证书认证,这一篇我接着分享,如何让 GRPC 服务加入双向证书认证。
小锟哥哥
2022/05/10
1.8K0
为GRPC证书加入双向证书认证如此简单
https原理以及golang基本实现
大致上分为两类,基于key的加密算法与不基于key的加密算法。现在的算法基本都是基于key的,key就以一串随机数数,更换了key之后,算法还可以继续使用。
我的小碗汤
2018/08/22
9400
go: grpc tls 应用一览
在go 1.15以上版本,必须使用SAN方式,否则会报"transport: authentication handshake failed: x509: certificate relies on legacy Common Name field, use SANs instead"
超级大猪
2023/01/31
1.3K0
Go和HTTPS -2
F为签名函数。CA自己的私钥是唯一标识CA签名的,因此CA用于生成数字证书的签名函数一定要以自己的私钥作为一个输入参数。在RSA加密 系统中,发送端的解密函数就是一个以私钥作 为参数的函数,因此常常被用作签名函数使用。签名算法是与证书一并发送给接收 端的,比如apple的一个服务的证书中关于签名算法的描述是“带 RSA 加密的 SHA-256 ( 1.2.840.113549.1.1.11 )”。因此CA用私钥解密函数作为F,对C的摘要进行运算得到了客户数字证书的签名,好比大学毕业证上的校长签名,所有毕业证
李海彬
2018/03/23
1.3K0
Golang(十一)TLS 相关知识(二)OpenSSL 生成证书
0. 前言 接前一篇文章,上篇文章我们介绍了数字签名、数字证书等基本概念和原理 本篇我们尝试自己生成证书 参考文献:TLS完全指南(二):OpenSSL操作指南 1. OpenSSL 简介 OpenSSL 是一个开源项目,其组成主要包括三个组件: openssl:多用途的命令行工具 libcrypto:加密算法库 libssl:加密模块应用库,实现了ssl及tls OpenSSL 主要用于秘钥证书管理、对称加密和非对称加密 1.1 指令 常用指令包括:genrsa、req、x509 1.1.1 genrs
西凉风雷
2022/11/23
2.3K0
【实践】如何在本地环境用GO实现HTTPS链接?
本篇文章是基于实操,如何在本地环境用GO实现HTTPS链接。原理部分请参考文章《【深度知识】HTTPS协议原理和流程分析》。
辉哥
2019/05/15
2.5K0
【实践】如何在本地环境用GO实现HTTPS链接?
gRPC,爆赞
gRPC 这项技术真是太棒了,接口约束严格,性能还高,在 k8s 和很多微服务框架中都有应用。
AlwaysBeta
2021/10/12
1.2K0
Go和HTTPS--1
近期在构思一个产品,考虑到安全性的原因,可能需要使用到HTTPS协议以及双向数字证书校验。之前只是粗浅接触过HTTP(使用Golang开 发微信系列)。对HTTPS的了解则始于那次自行搭建ngrok服务,在那个过程中照猫画虎地为服务端生成了一些私钥和证书,虽然结果是好 的:ngrok服务成功搭建起来了,但对HTTPS、数字证书等的基本原理并未求甚解。于是想趁这次的机会,对HTTPS做一些深度挖掘。主要途 径:翻阅网上资料、书籍,并利用golang编写一些实验examples。 一、HTTPS简介 日常生活中
李海彬
2018/03/23
1K0
grpc-go基于双向认证安全通信
grpc-go本身已经支持安全通信,该文是举例介绍下双向认证的安全通信,客户端和服务端是如何实现的。
DifficultWork
2019/05/09
3.8K0
使用https双端互相认证实现设备公网接入
在公网环境下,设备接入要保证安全性,server端既要验证设备的身份,设备也要验证server端的身份,这时就需要做双端互相认证。
海阔天空0
2019/02/23
1.9K0
使用https双端互相认证实现设备公网接入
golang实现http2.0服务端,客户端完整案例
为了学习golang的client源码执行流程,所以笔者通过golang实现http2的服务端和客户端,然后通过单步调试学习源码。下面我们看下整个golang实现http2的服务步骤。
公众号-利志分享
2022/04/25
5.2K0
go 原生代码搞定https双向认证客户端私钥加密
最近有一个https双向认证的项目,客户端的证书是加密的,之前用python requests 做原型测试发现不支持加密,需要运行的时候在终端输入密码。
有福
2019/02/22
3.1K0
go 原生代码搞定https双向认证客户端私钥加密
grpc-go之基本使用(一)
gRPC 是一个高性能、通用的开源 RPC 框架,其由 Google 主要面向移动应用开发并基于 HTTP/2 协议标准而设计,基于 ProtoBuf(Protocol Buffers) 序列化协议开发,且支持众多开发语言。
Johns
2022/09/26
1.5K0
[内网穿透][LanProxy]蛋疼的网络架构探讨
能够访问互联网的机器,去访问: 2.2.2.2:8080,就是访问的mac电脑的80端口 2.2.2.2:8081,就是访问的Windows电脑的1433端口。
landv
2020/05/28
8080
使用openssl演练数字签名
import ( "fmt" "io/ioutil" "net/http" )
charlieroro
2020/03/24
5190
Nginx配置Https单向认证、双向认证以及多证书配置
Nginx为了支持Https需要安装http_ssl_module模块。在编译时需要带上--with-http_ssl_module参数。
IT大咖说
2021/02/24
12.5K3
Nginx配置Https单向认证、双向认证以及多证书配置
Go 每日一库之 rpcx
在之前的两篇文章rpc和json-rpc中,我们介绍了 Go 标准库提供的rpc实现。在实际开发中,rpc库的功能还是有所欠缺。今天我们介绍一个非常优秀的 Go RPC 库——rpcx。rpcx是一位国人大牛开发的,详细开发历程可以在rpcx官方博客了解。rpcx拥有媲美,甚至某种程度上超越gRPC的性能,有完善的中文文档,提供服务发现和治理的插件。
用户7731323
2020/09/08
9210
相关推荐
使用 GoLang 获取 TLS 的 Client Hello Info
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验