使用go的tls库搭建客户端服务器加密通信

文章目录

使用OpenSSL生成证书

Win系统安装openssl
  1. 安装地址 https://slproweb.com/products/Win32OpenSSL.html
  2. 设置环境变量
  1. cmd命令检验 openssl version
生成证书
  1. 生成CA证书和密钥(可选,但推荐用于验证):
bash 复制代码
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=My CA"
  1. 生成服务器密钥和证书签名请求(CSR)
bash 复制代码
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
  1. 使用CA证书签名服务器CSR以生成服务器证书
bash 复制代码
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365

现在你应该有了ca.crt(CA证书),server.crt(服务器证书),和server.key(服务器私钥)。

非HTTP 直接tcp通信

基本和前面的net通信一模一样,只是

  • net.Dial() -> tls.Dial()
  • net.Listen() -> tls.Listen() 参数多了一个tls.config
服务器代码
go 复制代码
package main

import (
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net"
)

const (
	CERTFILEPATH = "E:\\Martin_Code\\Go\\src\\lesson-03-tls\\02-myTls\\server.crt"
	KEYFILEPATH  = "E:\\Martin_Code\\Go\\src\\lesson-03-tls\\02-myTls\\server.key"
)

func handleConn(conn net.Conn) {
	log.Printf("服务器收到连接:%s", conn.RemoteAddr())
    defer conn.Close()
	
	conn.Write([]byte("Hello, 这里是配置了TLS的服务器!\n"))
	
	for{
		buf := make([]byte, 1024)
        n, err := conn.Read(buf)
        if err != nil {
            if err == io.EOF {
                log.Println("客户端关闭连接")
            } else {
                log.Printf("服务器读取数据失败:%s", err)
            }
            return
        }
        fmt.Printf("服务器收到数据:%s\n", string(buf[:n]))
	}
}

func main() {
	// 1. 服务器 加载证书和私钥
	cert, err := tls.LoadX509KeyPair(CERTFILEPATH, KEYFILEPATH)
	if err != nil {
		log.Fatalf("服务器加载证书失败:%s", err)
	}
	log.Println("服务器加载证书成功!")

	// 2. 创建TLS配置,并指定证书和私钥
	config := &tls.Config{
		Certificates: []tls.Certificate{cert},
	}
	log.Println("服务器TLS配置创建成功!")

	// 3. 监听
	listen, err := tls.Listen("tcp", ":8443", config)
	if err != nil {
		log.Fatalf("服务器监听失败: %s", err)
	}
	log.Println("服务器监听成功!")
	defer listen.Close()

	// 4. 开启Accept
	for {
		conn, err := listen.Accept()
		if err != nil {
			log.Printf("服务器Accept()失败:%s", err)
			continue
		}
		// 5. 处理连接
		go handleConn(conn)

	}
}
客户端代码
go 复制代码
package main

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"log"
	"os"
)

func main() {
	// 1. 配置tls
	config := &tls.Config{
		InsecureSkipVerify: true, // 注意:在生产环境中不应跳过证书验证
	}

	// 2. 建立tls连接
	conn, err := tls.Dial("tcp", "localhost:8443", config)
	if err != nil {
		log.Fatalf("客户端Dial()失败:%s", err)
	}
	log.Printf("客户端连接的服务器地址:%s", conn.RemoteAddr())
	defer conn.Close()

	// 通过客户端的终端发送单行数据
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Print("请输入要发送的内容:")
		// 读取一行输入
		msg, _ := reader.ReadString('\n')
		if msg == "exit\r\n" {
			fmt.Println("退出连接")
			conn.Close()
			break
		}
		n, _ := conn.Write([]byte(msg))
		fmt.Println("Sent", n, "bytes to server")
	}
}
通信效果

服务器:

go 复制代码
PS E:\Martin_Code\Go\src\lesson-03-tls> go run .\02-myTls\non-HTTP\server\main.go
2024/07/31 11:20:54 服务器加载证书成功!
2024/07/31 11:20:54 服务器TLS配置创建成功!
2024/07/31 11:20:54 服务器监听成功!
2024/07/31 11:21:20 服务器收到连接:[::1]:52068
服务器收到数据:123\r\n
服务器收到数据:456\r\n
2024/07/31 11:21:42 客户端关闭连接

客户端

go 复制代码
PS E:\Martin_Code\Go\src\lesson-03-tls> go run .\02-myTls\non-HTTP\client\main.go
2024/07/31 11:21:20 客户端连接的服务器地址:[::1]:8443
请输入要发送的内容:123
Sent 5 bytes to server
请输入要发送的内容:456
Sent 5 bytes to server
请输入要发送的内容:exit
退出连接
相关推荐
KingRumn1 分钟前
Linux进程间通信之消息队列(POSIX)
linux·服务器
laoliu19965 分钟前
Odoo 18企业版源码 包含 部署教程
运维·服务器
鹿角片ljp35 分钟前
智能家居控制系统Java实现
java·开发语言·智能家居
开开心心就好43 分钟前
免费卸载工具,可清理残留批量管理启动项
linux·运维·服务器·windows·随机森林·pdf·1024程序员节
xiaolang_8616_wjl1 小时前
c++超级细致的基本框架
开发语言·数据结构·c++·算法
Lbwnb丶1 小时前
检测服务器是否是虚拟化,如KVM,VM等
linux·运维·服务器
老猿讲编程1 小时前
【车载信息安全系列4】基于Linux中UIO的HSE应用实现
linux·运维·服务器
星辰落满衣1 小时前
股票实时交易数据之Python、Java等多种主流语言实例代码演示通过股票数据接口
java·开发语言·python
毕设源码-钟学长2 小时前
【开题答辩全过程】以 基于java的点餐猫在线个性化点餐系统的设计与实现为例,包含答辩的问题和答案
java·开发语言
wanhengidc2 小时前
巨椰 云手机 云游戏稳定运行
运维·服务器·arm开发·游戏·云计算