client.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package webtunnel
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "net"
  7. "net/url"
  8. "strings"
  9. pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
  10. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel/transport/httpupgrade"
  11. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel/transport/tls"
  12. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
  13. )
  14. type clientConfig struct {
  15. RemoteAddresses []string
  16. Path string
  17. TLSKind string
  18. TLSServerName string
  19. UTLSFingerprint string
  20. }
  21. type clientFactory struct {
  22. parent base.Transport
  23. }
  24. func (c *clientFactory) Transport() base.Transport {
  25. return c.parent
  26. }
  27. func (c *clientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
  28. i, err := c.parseArgs(args)
  29. if err != nil {
  30. pt.Log(pt.LogSeverityError, fmt.Sprintf("Error parsing args: %v", err))
  31. return nil, err
  32. }
  33. return i, nil
  34. }
  35. func (c *clientFactory) parseArgs(args *pt.Args) (interface{}, error) {
  36. var config clientConfig
  37. if urlStr, ok := args.Get("url"); ok {
  38. url, err := url.Parse(urlStr)
  39. if err != nil {
  40. return nil, fmt.Errorf("url parse error: %s", err)
  41. }
  42. defaultPort := ""
  43. switch url.Scheme {
  44. case "https":
  45. config.TLSKind = "tls"
  46. defaultPort = "443"
  47. case "http":
  48. config.TLSKind = ""
  49. defaultPort = "80"
  50. default:
  51. return nil, fmt.Errorf("url parse error: unknown scheme")
  52. }
  53. config.Path = strings.TrimPrefix(url.EscapedPath(), "/")
  54. config.TLSServerName = url.Hostname()
  55. port := url.Port()
  56. if port == "" {
  57. port = defaultPort
  58. }
  59. config.RemoteAddresses, err = getAddressesFromHostname(url.Hostname(), port)
  60. if err != nil {
  61. log.Println(err)
  62. return nil, errors.New("")
  63. }
  64. config.TLSServerName = url.Hostname()
  65. }
  66. if tlsServerName, ok := args.Get("servername"); ok {
  67. config.TLSServerName = tlsServerName
  68. }
  69. if uTLSFingerprint, ok := args.Get("utls"); ok {
  70. config.UTLSFingerprint = uTLSFingerprint
  71. if config.UTLSFingerprint == "" {
  72. config.UTLSFingerprint = "hellorandomizednoalpn"
  73. }
  74. if config.UTLSFingerprint == "none" {
  75. config.UTLSFingerprint = ""
  76. }
  77. }
  78. return config, nil
  79. }
  80. func (c *clientFactory) Dial(network, address string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
  81. conn, err := c.dial(network, address, dialFn, args)
  82. if err != nil {
  83. pt.Log(pt.LogSeverityError, fmt.Sprintf("Error dialing: %v", err))
  84. return nil, err
  85. }
  86. return conn, nil
  87. }
  88. func (c *clientFactory) dial(network, address string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
  89. config := args.(clientConfig)
  90. var conn net.Conn
  91. for _, addr := range config.RemoteAddresses {
  92. if tcpConn, err := dialFn("tcp", addr); err == nil {
  93. conn = tcpConn
  94. break
  95. }
  96. }
  97. if conn == nil {
  98. return nil, fmt.Errorf("Can't connect to %v", config.RemoteAddresses)
  99. }
  100. if config.TLSKind != "" {
  101. conf := &tls.Config{ServerName: config.TLSServerName}
  102. if config.UTLSFingerprint == "" {
  103. if tlsTransport, err := tls.NewTLSTransport(conf); err != nil {
  104. return nil, err
  105. } else {
  106. if tlsConn, err := tlsTransport.Client(conn); err != nil {
  107. return nil, err
  108. } else {
  109. conn = tlsConn
  110. }
  111. }
  112. } else {
  113. utlsConfig := &uTLSConfig{ServerName: config.TLSServerName, uTLSFingerprint: config.UTLSFingerprint}
  114. if utlsTransport, err := newUTLSTransport(utlsConfig); err != nil {
  115. return nil, err
  116. } else {
  117. if utlsConn, err := utlsTransport.Client(conn); err != nil {
  118. return nil, err
  119. } else {
  120. conn = utlsConn
  121. }
  122. }
  123. }
  124. }
  125. upgradeConfig := httpupgrade.Config{Path: config.Path, Host: config.TLSServerName}
  126. if httpupgradeTransport, err := httpupgrade.NewHTTPUpgradeTransport(&upgradeConfig); err != nil {
  127. return nil, err
  128. } else {
  129. if httpUpgradeConn, err := httpupgradeTransport.Client(conn); err != nil {
  130. return nil, err
  131. } else {
  132. conn = httpUpgradeConn
  133. }
  134. }
  135. return conn, nil
  136. }
  137. // Not yet implemented
  138. func (cf *clientFactory) OnEvent(f func(base.TransportEvent)) {}
  139. func getAddressesFromHostname(hostname, port string) ([]string, error) {
  140. addresses := []string{}
  141. addr, err := net.LookupHost(hostname)
  142. if err != nil {
  143. return addresses, fmt.Errorf("Lookup error for host %s: %v", hostname, err)
  144. }
  145. for _, a := range addr {
  146. ip := net.ParseIP(a)
  147. if ip == nil || ip.IsLoopback() || ip.IsUnspecified() || ip.IsMulticast() || ip.IsLinkLocalUnicast() || ip.IsPrivate() {
  148. continue
  149. }
  150. if ip.To4() != nil {
  151. addresses = append(addresses, a+":"+port)
  152. } else {
  153. addresses = append(addresses, "["+a+"]:"+port)
  154. }
  155. }
  156. if len(addresses) == 0 {
  157. return addresses, fmt.Errorf("Could not find any valid IP for %s", hostname)
  158. }
  159. return addresses, nil
  160. }