methods.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (C) 2015 Audrius Butkevicius and Contributors (see the CONTRIBUTORS file).
  2. package client
  3. import (
  4. "crypto/tls"
  5. "fmt"
  6. "net"
  7. "net/url"
  8. "strconv"
  9. "strings"
  10. "time"
  11. syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
  12. "github.com/syncthing/syncthing/lib/relay/protocol"
  13. )
  14. func GetInvitationFromRelay(uri *url.URL, id syncthingprotocol.DeviceID, certs []tls.Certificate) (protocol.SessionInvitation, error) {
  15. if uri.Scheme != "relay" {
  16. return protocol.SessionInvitation{}, fmt.Errorf("Unsupported relay scheme: %v", uri.Scheme)
  17. }
  18. conn, err := tls.Dial("tcp", uri.Host, configForCerts(certs))
  19. if err != nil {
  20. return protocol.SessionInvitation{}, err
  21. }
  22. conn.SetDeadline(time.Now().Add(10 * time.Second))
  23. if err := performHandshakeAndValidation(conn, uri); err != nil {
  24. return protocol.SessionInvitation{}, err
  25. }
  26. defer conn.Close()
  27. request := protocol.ConnectRequest{
  28. ID: id[:],
  29. }
  30. if err := protocol.WriteMessage(conn, request); err != nil {
  31. return protocol.SessionInvitation{}, err
  32. }
  33. message, err := protocol.ReadMessage(conn)
  34. if err != nil {
  35. return protocol.SessionInvitation{}, err
  36. }
  37. switch msg := message.(type) {
  38. case protocol.Response:
  39. return protocol.SessionInvitation{}, fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
  40. case protocol.SessionInvitation:
  41. l.Debugln("Received invitation", msg, "via", conn.LocalAddr())
  42. ip := net.IP(msg.Address)
  43. if len(ip) == 0 || ip.IsUnspecified() {
  44. msg.Address = conn.RemoteAddr().(*net.TCPAddr).IP[:]
  45. }
  46. return msg, nil
  47. default:
  48. return protocol.SessionInvitation{}, fmt.Errorf("protocol error: unexpected message %v", msg)
  49. }
  50. }
  51. func JoinSession(invitation protocol.SessionInvitation) (net.Conn, error) {
  52. addr := net.JoinHostPort(net.IP(invitation.Address).String(), strconv.Itoa(int(invitation.Port)))
  53. conn, err := net.Dial("tcp", addr)
  54. if err != nil {
  55. return nil, err
  56. }
  57. request := protocol.JoinSessionRequest{
  58. Key: invitation.Key,
  59. }
  60. conn.SetDeadline(time.Now().Add(10 * time.Second))
  61. err = protocol.WriteMessage(conn, request)
  62. if err != nil {
  63. return nil, err
  64. }
  65. message, err := protocol.ReadMessage(conn)
  66. if err != nil {
  67. return nil, err
  68. }
  69. conn.SetDeadline(time.Time{})
  70. switch msg := message.(type) {
  71. case protocol.Response:
  72. if msg.Code != 0 {
  73. return nil, fmt.Errorf("Incorrect response code %d: %s", msg.Code, msg.Message)
  74. }
  75. return conn, nil
  76. default:
  77. return nil, fmt.Errorf("protocol error: expecting response got %v", msg)
  78. }
  79. }
  80. func TestRelay(uri *url.URL, certs []tls.Certificate, sleep time.Duration, times int) bool {
  81. id := syncthingprotocol.NewDeviceID(certs[0].Certificate[0])
  82. invs := make(chan protocol.SessionInvitation, 1)
  83. c := NewProtocolClient(uri, certs, invs)
  84. go c.Serve()
  85. defer func() {
  86. close(invs)
  87. c.Stop()
  88. }()
  89. for i := 0; i < times; i++ {
  90. _, err := GetInvitationFromRelay(uri, id, certs)
  91. if err == nil {
  92. return true
  93. }
  94. if !strings.Contains(err.Error(), "Incorrect response code") {
  95. return false
  96. }
  97. time.Sleep(sleep)
  98. }
  99. return false
  100. }
  101. func configForCerts(certs []tls.Certificate) *tls.Config {
  102. return &tls.Config{
  103. Certificates: certs,
  104. NextProtos: []string{protocol.ProtocolName},
  105. ClientAuth: tls.RequestClientCert,
  106. SessionTicketsDisabled: true,
  107. InsecureSkipVerify: true,
  108. MinVersion: tls.VersionTLS12,
  109. CipherSuites: []uint16{
  110. tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
  111. tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
  112. tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
  113. tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
  114. tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
  115. tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
  116. },
  117. }
  118. }