tls.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package nettools
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "golang.org/x/net/context"
  6. "net"
  7. "strconv"
  8. "time"
  9. )
  10. type TlsPingResult struct {
  11. ConnectionTime int
  12. HandshakeTime int
  13. TLSVersion uint16
  14. Err error
  15. IP net.IP
  16. }
  17. func (tlsR *TlsPingResult) Result() int {
  18. return tlsR.ConnectionTime + tlsR.HandshakeTime
  19. }
  20. func (tlsR *TlsPingResult) Error() error {
  21. return tlsR.Err
  22. }
  23. func (tlsR *TlsPingResult) String() string {
  24. if tlsR.Err != nil {
  25. return fmt.Sprintf("%s", tlsR.Err)
  26. } else {
  27. return fmt.Sprintf("%s: protocol=%s, connection=%d ms, handshake=%d ms, time=%d ms", tlsR.IP.String(), tlsVersionToString(tlsR.TLSVersion), tlsR.ConnectionTime, tlsR.HandshakeTime, tlsR.Result())
  28. }
  29. }
  30. type TlsPing struct {
  31. Host string
  32. Port uint16
  33. ConnectionTimeout time.Duration
  34. HandshakeTimeout time.Duration
  35. // 以下为可选参数
  36. TlsVersion uint16
  37. Insecure bool
  38. IP net.IP
  39. }
  40. func (tslC *TlsPing) Ping() IPingResult {
  41. return tslC.PingContext(context.Background())
  42. }
  43. func (tslC *TlsPing) PingContext(ctx context.Context) IPingResult {
  44. ip := cloneIP(tslC.IP)
  45. if ip == nil {
  46. var err error
  47. ip, err = LookupFunc(tslC.Host)
  48. if err != nil {
  49. return tslC.errorResult(err)
  50. }
  51. }
  52. dialer := &net.Dialer{
  53. Timeout: tslC.ConnectionTimeout,
  54. KeepAlive: -1,
  55. }
  56. t0 := time.Now()
  57. conn, err := dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), strconv.FormatUint(uint64(tslC.Port), 10)))
  58. if err != nil {
  59. return tslC.errorResult(err)
  60. }
  61. defer conn.Close()
  62. t1 := time.Now()
  63. config := &tls.Config{
  64. ServerName: tslC.Host,
  65. MinVersion: tslC.TlsVersion,
  66. MaxVersion: tslC.TlsVersion,
  67. InsecureSkipVerify: tslC.Insecure,
  68. }
  69. client := tls.Client(conn, config)
  70. client.SetDeadline(time.Now().Add(tslC.HandshakeTimeout))
  71. err = client.Handshake()
  72. if err != nil {
  73. return tslC.errorResult(err)
  74. }
  75. defer client.Close()
  76. t2 := time.Now()
  77. return &TlsPingResult{int(t1.Sub(t0).Milliseconds()), int(t2.Sub(t1).Milliseconds()), client.ConnectionState().Version, nil, ip}
  78. }
  79. func NewTlsPing(host string, port uint16, ct, ht time.Duration) *TlsPing {
  80. return &TlsPing{
  81. Host: host,
  82. Port: port,
  83. ConnectionTimeout: ct,
  84. HandshakeTimeout: ht,
  85. }
  86. }
  87. func (tslC *TlsPing) errorResult(err error) *TlsPingResult {
  88. r := &TlsPingResult{}
  89. r.Err = err
  90. return r
  91. }
  92. var (
  93. _ IPing = (*TlsPing)(nil)
  94. _ IPingResult = (*TlsPingResult)(nil)
  95. )