TLS通信

gtcp模块支持TLS加密通信服务端及客户端,在对安全要求比较高的场景中非常必要。TLS服务端创建可以通过NewServerTLS或者NewServerKeyCrt方法实现。TLS客户端创建可以通过NewConnKeyCrt或者NewConnTLS方法实现。

使用示例:

https://github.com/gogf/gf/tree/master/geg/net/gtcp/tls

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/g/net/gtcp"
  5. "github.com/gogf/gf/g/os/glog"
  6. "github.com/gogf/gf/g/util/gconv"
  7. "time"
  8. )
  9. func main() {
  10. address := "127.0.0.1:8999"
  11. crtFile := "server.crt"
  12. keyFile := "server.key"
  13. // TLS Server
  14. go gtcp.NewServerKeyCrt(address, crtFile, keyFile, func(conn *gtcp.Conn) {
  15. defer conn.Close()
  16. for {
  17. data, err := conn.Recv(-1)
  18. if len(data) > 0 {
  19. fmt.Println(string(data))
  20. }
  21. if err != nil {
  22. // if client closes, err will be: EOF
  23. glog.Error(err)
  24. break
  25. }
  26. }
  27. }).Run()
  28. time.Sleep(time.Second)
  29. // Client
  30. conn, err := gtcp.NewConnKeyCrt(address, crtFile, keyFile)
  31. if err != nil {
  32. panic(err)
  33. }
  34. defer conn.Close()
  35. for i := 0; i < 10; i++ {
  36. if err := conn.Send([]byte(gconv.String(i))); err != nil {
  37. glog.Error(err)
  38. }
  39. time.Sleep(time.Second)
  40. if i == 5 {
  41. conn.Close()
  42. break
  43. }
  44. }
  45. // exit after 5 seconds
  46. time.Sleep(5 * time.Second)
  47. }

执行后,可以看到客户端执行时报错:

  1. panic: x509: certificate has expired or is not yet valid

那是因为我们的证书是手动创建的,并且已经过期了,为了演示方便,我们在客户端代码中去掉客户端对证书的校验。

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/g/net/gtcp"
  5. "github.com/gogf/gf/g/os/glog"
  6. "github.com/gogf/gf/g/util/gconv"
  7. "time"
  8. )
  9. func main() {
  10. address := "127.0.0.1:8999"
  11. crtFile := "server.crt"
  12. keyFile := "server.key"
  13. // TLS Server
  14. go gtcp.NewServerKeyCrt(address, crtFile, keyFile, func(conn *gtcp.Conn) {
  15. defer conn.Close()
  16. for {
  17. data, err := conn.Recv(-1)
  18. if len(data) > 0 {
  19. fmt.Println(string(data))
  20. }
  21. if err != nil {
  22. // if client closes, err will be: EOF
  23. glog.Error(err)
  24. break
  25. }
  26. }
  27. }).Run()
  28. time.Sleep(time.Second)
  29. // Client
  30. tlsConfig, err := gtcp.LoadKeyCrt(crtFile, keyFile)
  31. if err != nil {
  32. panic(err)
  33. }
  34. tlsConfig.InsecureSkipVerify = true
  35. conn, err := gtcp.NewConnTLS(address, tlsConfig)
  36. if err != nil {
  37. panic(err)
  38. }
  39. defer conn.Close()
  40. for i := 0; i < 10; i++ {
  41. if err := conn.Send([]byte(gconv.String(i))); err != nil {
  42. glog.Error(err)
  43. }
  44. time.Sleep(time.Second)
  45. if i == 5 {
  46. conn.Close()
  47. break
  48. }
  49. }
  50. // exit after 5 seconds
  51. time.Sleep(5 * time.Second)
  52. }

执行后,终端输出结果为:

  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 2019-06-05 00:13:12.488 [ERRO] EOF
  8. Stack:
  9. 1. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/net/gtcp/tls/gtcp_server_client.go:25

其中客户端在5秒后关闭了连接,因此服务端在接收数据时获取到了一个EOF错误,这种错误在正式使用中我们直接忽略,报错时服务端直接关闭客户端连接即可。