• TLS通信

    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错误,这种错误在正式使用中我们直接忽略,报错时服务端直接关闭客户端连接即可。