用go搭建tls服务器

tls 简介(来自 wiki

Transport Layer Security (TLS), and its now-deprecated predecessor, Secure Sockets Layer (SSL), are cryptographic protocols designed to provide communications security over a computer network. Several versions of the protocols are widely used in applications such as email, instant messaging, and voice over IP, but its use as the Security layer in HTTPS remains the most publicly visible.

The TLS protocol aims primarily to provide privacy and data integrity between two or more communicating computer applications.

The TLS protocol comprises two layers: the TLS record and the TLS handshake protocols.

TLS is a proposed Internet Engineering Task Force (IETF) standard, first defined in 1999, and the current version is TLS 1.3 defined in August 2018. TLS builds on the earlier SSL specifications (1994, 1995, 1996) developed by Netscape Communications for adding the HTTPS protocol to their Navigator web browser.

TLS和SSL两者都是加密协议,旨在提供计算机网络上的通信安全性。TLS协议的主要目的是在两个或多个通信计算机应用程序之间提供隐私和数据完整性。

tls 与 ssl 的联系与差别

两者都是为网络通信加密的协议。tls 可以说是 ssl 的升级版本,ssl 已经被遗弃了。

Protocol Published Status
SSL 1.0 Unpublished Unpublished
SSL 2.0 1995 Deprecated in 2011
SSL 3.0 1996 Deprecated in 2015
TLS 1.0 1999 Deprecated in 2020
TLS 1.1 2006 Deprecated in 2020
TLS 1.2 2008
TLS 1.3 2018

利用 openssl 来生成证书

搭建 tls 服务器时需要用到证书来证明服务器的身份。

生成 RSA 私钥和自签名证书

openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt
  • req是证书请求的子命令

  • -newkey rsa:2048 -keyout private_key.pem 表示生成私钥(PKCS8格式)

  • -nodes 表示私钥不加密,若不带该参数将提示输入密码。

  • -x509表示输出证书

  • -days 365 为有效期

  • 此后根据提示输入证书拥有者信息,若执行自动输入,可使用-subj 选项。

    openssl req -newkey rsa:2048 -nodes -keyout rsa_private.key -x509 -days 365 -out cert.crt -subj "/C=CN/ST=GD/L=SZ/O=vihoo/OU=dev/CN=vivo.com/emailAddress=yy@vivo.com"
    

生成后缀名为 pem 的证书

openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem

其实后缀名为 .pem 与后缀名为 .crt 的差别不大。因为用这个参数生成的证书都是文本格式的。后缀为.crt的优势是,在window系统下面双击能触发安装证书的程序。

根据 RSA 私钥生成自签名

openssl req -new -x509 -days 365 -key rsa_private.key -out cert.crt

搭建 tls 服务器

go 中有 "crypto/tls",可以方便的处理与 tls 有关的业务。

func StartTcpServerWithTls(addr, certFile, keyFile string) {
	crt, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		panic(err)
	}
	tlsConfig := tls.Config{
		Certificates: []tls.Certificate{crt},
	}
	tlsListener, err := tls.Listen("tcp4", addr, &tlsConfig)
	if err != nil {
		panic(err)
	}

	for true {
		conn, err := tlsListener.Accept()
		if err != nil {
			fmt.Printf("AcceptTCP(),err[%v]\n", err)
			continue
		}
		// 返回的是一个 net.Conn,所以没办法设置 ReadBuffer 和 WriteBuffer
		// 随它去吧
		// 所以用的是系统默认的 tcp buffer
		// linux 下面
		// cat /proc/sys/net/ipv4/tcp_wmem
		// cat /proc/sys/net/ipv4/tcp_rmem

		go func() {
			readBuf := make([]byte, 1024)
			bsCount, err := conn.Read(readBuf)
			if err != nil {
				fmt.Printf("Read(),err[%v]\n", err)
				return
			}
			fmt.Println(string(readBuf[:bsCount]))
			_, err = conn.Write([]byte("hello from server"))
			if err != nil {
				fmt.Printf("Write(),err[%v]\n", err)
				return
			}
		}()
	}
}

搭建 tls 客户端

不验证证书

tls.Config 中的 InsecureSkipVerify 设置为 true 即可。

func tlsClient(address string) {
	conf := &tls.Config{
		InsecureSkipVerify: true,
	}

	conn, err := tls.Dial("tcp", address, conf)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	n, err := conn.Write([]byte("hello from client\n"))
	if err != nil {
		log.Println(n, err)
		return
	}
	buf := make([]byte, 1024)
	n, err = conn.Read(buf)
	if err != nil {
		log.Println(n, err)
		return
	}
	log.Println(string(buf[:n]))
}

验证证书

需要在电脑上安装之前生成的 crt 证书。且一定要把该证书放在受信任的根证书颁发机构下面。

windows下面可以通过certmgr.msc命令来管理证书。

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) []:www.xxx.com		// 注意这里哦
Email Address []:

此外需要将tls.Config中的ServerName设置为之前生成证书时的FADN

func tlsRun(address, serverName string) {
	conf := &tls.Config{
		ServerName: serverName,
	}

	conn, err := tls.Dial("tcp", address, conf)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	n, err := conn.Write([]byte("hello from client\n"))
	if err != nil {
		log.Println(n, err)
		return
	}
	buf := make([]byte, 1024)
	n, err = conn.Read(buf)
	if err != nil {
		log.Println(n, err)
		return
	}
	log.Println(string(buf[:n]))
}

参考链接

https://www.cnblogs.com/guogangj/p/4118605.html

https://blog.csdn.net/gengxiaoming7/article/details/78505107

posted @ 2021-04-25 13:43  机智的小小帅  阅读(923)  评论(0编辑  收藏  举报