文章目录
-
-
- 使用OpenSSL生成证书
- [非HTTP 直接tcp通信](#非HTTP 直接tcp通信)
-
使用OpenSSL生成证书
Win系统安装openssl
- 安装地址 https://slproweb.com/products/Win32OpenSSL.html
- 设置环境变量
- cmd命令检验
openssl version
生成证书
- 生成CA证书和密钥(可选,但推荐用于验证):
bash
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=My CA"
- 生成服务器密钥和证书签名请求(CSR):
bash
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
- 使用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
退出连接