新聞中心
安全傳輸層協(xié)議 TLS,以前稱為 SSL(Secure Sockets Layer) ,由于HTTPS的推出受到了很多人的歡迎。但是正如TLS的名稱 Transport Layer Security 所示的那樣,它實際上是獨立于 HTTP,一個更深入的安全協(xié)議,我們可以將 TLS 視為 TCP 的安全版本,其提供了對 socket 通信進(jìn)行加密和簽名的功能。在我們的日常開發(fā)中,會將 gRPC 協(xié)議運行在TLS之上以確保安全。

站在用戶的角度思考問題,與客戶深入溝通,找到南票網(wǎng)站設(shè)計與南票網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站建設(shè)、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋南票地區(qū)。
今天我們來了解一下如何創(chuàng)建一個通過 TLS 加密的 socket 服務(wù)。
1.TLS socket server
服務(wù)端示例
- func main() {
- port := flag.String("port", "8360", "listening port")
- certFile := flag.String("cert", "cert.pem", "certificate PEM file")
- keyFile := flag.String("key", "key.pem", "key PEM file")
- flag.Parse()
- cert, err := tls.LoadX509KeyPair(*certFile, *keyFile)
- if err != nil {
- log.Fatal(err)
- }
- config := &tls.Config{Certificates: []tls.Certificate{cert}}
- log.Printf("listening on port %s\n", *port)
- l, err := tls.Listen("tcp", ":"+*port, config)
- if err != nil {
- log.Fatal(err)
- }
- defer l.Close()
- for {
- conn, err := l.Accept()
- if err != nil {
- log.Fatal(err)
- }
- log.Printf("accepted connection from %s\n", conn.RemoteAddr())
- go func(c net.Conn) {
- io.Copy(c, c)
- c.Close()
- log.Printf("closing connection from %s\n", conn.RemoteAddr())
- }(conn)
- }
- }
這個服務(wù)端程序接受來自多個客戶端并發(fā)請求,并向客戶端發(fā)送的所有的鏡像數(shù)據(jù)。和非TLS服務(wù)相比,這里用 tls.Listen 替換了 net.Listen,同時需要提供一個可用的 tls.Config,我們可以使用 mkcert 命令來生成證書和密鑰對文件。
2.TLS socket client
客戶端示例:
- func main() {
- port := flag.String("port", "8360", "port to connect")
- certFile := flag.String("certfile", "cert.pem", "trusted CA certificate")
- flag.Parse()
- cert, err := os.ReadFile(*certFile)
- if err != nil {
- log.Fatal(err)
- }
- certPool := x509.NewCertPool()
- if ok := certPool.AppendCertsFromPEM(cert); !ok {
- log.Fatalf("unable to parse cert from %s", *certFile)
- }
- config := &tls.Config{RootCAs: certPool}
- conn, err := tls.Dial("tcp", "localhost:"+*port, config)
- if err != nil {
- log.Fatal(err)
- }
- _, err = io.WriteString(conn, "Hello simple secure Server\n")
- if err != nil {
- log.Fatal("client write error:", err)
- }
- if err = conn.CloseWrite(); err != nil {
- log.Fatal(err)
- }
- buf := make([]byte, 256)
- n, err := conn.Read(buf)
- if err != nil && err != io.EOF {
- log.Fatal(err)
- }
- fmt.Println("client read:", string(buf[:n]))
- conn.Close()
- }
和非 TLS 客戶端相比,我們同樣也只是把 net.Dial 換成 tls.Dial, tls.Config 中填寫的證書可以選擇權(quán)威 ca 頒發(fā)的證書,也可以使用自簽名證書。
3.證書鏈
一般來說,我們將自己生成的 CSR 提交給簽名商,他們用中級證書機(jī)構(gòu)的私鑰 Private Key 給我們的簽名成證書,Root CA 通過它的私鑰對中級機(jī)構(gòu)提交的CSR進(jìn)行簽名。
證書頒發(fā)機(jī)構(gòu)是一個樹形結(jié)構(gòu)的。比如在驗證我們證書X的有效性的時候,會一層層的去尋找頒發(fā)者的證書,直到自簽名的根證書,然后通過相應(yīng)的公鑰再反過來驗證下一級的數(shù)字簽名的正確性。直到找到X證書,這就是證書鏈(Certificate Chains)。
我們可以使用以下程序檢查任何服務(wù)器的證書鏈:
- func main() {
- addr := flag.String("addr", "localhost:8360", "dial address")
- flag.Parse()
- cfg := tls.Config{}
- conn, err := tls.Dial("tcp", *addr, &cfg)
- if err != nil {
- log.Fatal("TLS connection failed: " + err.Error())
- }
- defer conn.Close()
- certChain := conn.ConnectionState().PeerCertificates
- for i, cert := range certChain {
- fmt.Println(i)
- fmt.Println("Issuer:", cert.Issuer)
- fmt.Println("Subject:", cert.Subject)
- fmt.Println("Version:", cert.Version)
- fmt.Println("NotAfter:", cert.NotAfter)
- fmt.Println("DNS names:", cert.DNSNames)
- fmt.Println("")
- }
- }
給定IP地址后,啟動程序后會與服務(wù)器建立一條 TLS 連接,并上報其使用的證書給服務(wù)端。如果我們使用未處理過的自簽的證書,TLS 服務(wù)端驗證是通不過的。所以我們需要權(quán)威ca 頒發(fā)的證書,或者使用 mkcert 為我們的服務(wù)器生成證書來使他生效。
打開終端,執(zhí)行 mkcert 命令:
- kangkai-iri ./mkcert localhost
- kangkai-iri go run tls-socket-server.go -cert localhost.pem -key localhost-key.pem
新打開一個終端,運行 tls-dial-port:
- kangkai-iri go run tls-dial-port.go -addr localhost:4040
我們看到生成了證書 mkcert。由于 mkcert 將此證書添加到服務(wù)器的系統(tǒng)根存儲中,直接使用 tls.Dial 將信任該證書。
文章標(biāo)題:使用Go實現(xiàn)TLSsocketserver
URL網(wǎng)址:http://m.5511xx.com/article/cceghdd.html


咨詢
建站咨詢
