在网络通信中,安全性至关重要。SSL/TLS协议是一种广泛使用的加密通信协议,用于保护敏感数据的传输。在本文中,我们将介绍如何使用Golang编程语言实现一个SSL/TLS协议的服务器,以确保我们的网络通信是安全可靠的。
1. SSL/TLS简介
SSL/TLS(Secure Sockets Layer/Transport Layer Security)是一组加密协议,用于在计算机网络上提供安全的数据传输。它们位于传输层,确保在客户端和服务器之间的通信过程中数据的机密性、完整性和身份验证。
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 36500 -key ca.key -out ca.crt
创建SSL证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
mkdir demoCA &&cd demoCA&&mkdir newcerts&&echo '10' > serial &&touch index.txt&&cd ..
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
openssl x509 -in server.crt -noout -text
Mac系统如果根证书签署SSL证书时报错:
Using configuration from /private/etc/ssl/openssl.cnf
variable lookup failed for ca::default_ca
140704333022784:error:0EFFF06C:configuration file routines:CRYPTO_internal:no value:/AppleInternal/Library/BuildRoots/c2cb9645-dafc-11ed-aa26-6ec1e3b3f7b3/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/conf/conf_lib.c:322:group=ca name=default_ca
是因为系统默认的openssl使用的/private/etc/ssl/openssl.cnf配置文件中缺失 default_ca 的配置。
解决方法:使用 brew 安装的openssl而不使用系统默认的openssl, brew 安装好 openssl后在终端执行命令
export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"
使用"crypto/tls"包,我们可以轻松地为我们的服务器生成自签名的证书,并将其用于SSL/TLS连接。
package main
import (
"crypto/tls"
"github.com/sirupsen/logrus"
"log"
"net"
)
func handleConnection(conn net.Conn) {
defer conn.Close()
buffer := make([]byte, 1024)
for {
l, err := conn.Read(buffer)
if err != nil {
log.Println(err.Error())
break
}
logrus.Infoln("Receive Data: %s\n", string(buffer[:l]))
}
logrus.Infoln("Client " + conn.RemoteAddr().String() + " Connection Closed.....")
}
func main() {
port := "8888"
crt, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatalln(err.Error())
}
tlsConfig := &tls.Config{}
tlsConfig.Certificates = []tls.Certificate{crt}
ln, err := tls.Listen("tcp", ":"+port, tlsConfig)
if err != nil {
logrus.Fatalf("TCP server failed to listen on port %s. Error: %s", port, err.Error())
}
logrus.Infof("TCP server listening on port %s", port)
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
logrus.Fatalf("TCP server failed to accept connection on port %s. Error: %v", port, err)
} else {
go handleConnection(conn)
}
}
}
运行结果:
INFO[0000] TCP server listening on port 8888
INFO[0221] Receive Data: %s
Hello SSL/TLS
2023/06/25 21:33:52 EOF
INFO[0221] Client 127.0.0.1:50909 Connection Closed.....
INFO[0271] Receive Data: %s
Hello SSL/TLS
2023/06/25 21:34:41 EOF
INFO[0271] Client 127.0.0.1:50915 Connection Closed.....
客户端需要配置InsecureSkipVerify参数,该参数表示客户端跳过对证书链的校验,因为CA证书是不是自己生成的,不是系统信任的证书。
package main
import (
"crypto/tls"
"io"
"log"
)
func main() {
conf := &tls.Config{
InsecureSkipVerify: true,
}
conn, err := tls.Dial("tcp", "127.0.0.1:8888", conf)
if err != nil {
log.Fatalln(err.Error())
}
defer conn.Close()
io.WriteString(conn, "Hello SSL/TLS")
}