u_roller.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package tls
  2. import (
  3. "net"
  4. "sync"
  5. "time"
  6. )
  7. type Roller struct {
  8. HelloIDs []ClientHelloID
  9. HelloIDMu sync.Mutex
  10. WorkingHelloID *ClientHelloID
  11. TcpDialTimeout time.Duration
  12. TlsHandshakeTimeout time.Duration
  13. }
  14. // NewRoller creates Roller object with default range of HelloIDs to cycle through until a
  15. // working/unblocked one is found.
  16. func NewRoller() (*Roller, error) {
  17. tcpDialTimeoutInc, err := getRandInt(14)
  18. if err != nil {
  19. return nil, err
  20. }
  21. tcpDialTimeoutInc = 7 + tcpDialTimeoutInc
  22. tlsHandshakeTimeoutInc, err := getRandInt(20)
  23. if err != nil {
  24. return nil, err
  25. }
  26. tlsHandshakeTimeoutInc = 11 + tlsHandshakeTimeoutInc
  27. return &Roller{
  28. HelloIDs: []ClientHelloID{
  29. HelloChrome_Auto,
  30. HelloFirefox_Auto,
  31. HelloIOS_Auto,
  32. HelloRandomized,
  33. },
  34. TcpDialTimeout: time.Second * time.Duration(tcpDialTimeoutInc),
  35. TlsHandshakeTimeout: time.Second * time.Duration(tlsHandshakeTimeoutInc),
  36. }, nil
  37. }
  38. // Dial attempts to establish connection to given address using different HelloIDs.
  39. // If a working HelloID is found, it is used again for subsequent Dials.
  40. // If tcp connection fails or all HelloIDs are tried, returns with last error.
  41. //
  42. // Usage examples:
  43. // Dial("tcp4", "google.com:443", "google.com")
  44. // Dial("tcp", "10.23.144.22:443", "mywebserver.org")
  45. func (c *Roller) Dial(network, addr, serverName string) (*UConn, error) {
  46. helloIDs, err := shuffleClientHelloIDs(c.HelloIDs)
  47. if err != nil {
  48. return nil, err
  49. }
  50. c.HelloIDMu.Lock()
  51. workingHelloId := c.WorkingHelloID // keep using same helloID, if it works
  52. c.HelloIDMu.Unlock()
  53. if workingHelloId != nil {
  54. for i, ID := range helloIDs {
  55. if ID == *workingHelloId {
  56. helloIDs[i] = helloIDs[0]
  57. helloIDs[0] = *workingHelloId // push working hello ID first
  58. break
  59. }
  60. }
  61. }
  62. var tcpConn net.Conn
  63. for _, helloID := range helloIDs {
  64. tcpConn, err = net.DialTimeout(network, addr, c.TcpDialTimeout)
  65. if err != nil {
  66. return nil, err // on tcp Dial failure return with error right away
  67. }
  68. client := UClient(tcpConn, nil, helloID)
  69. client.SetSNI(serverName)
  70. client.SetDeadline(time.Now().Add(c.TlsHandshakeTimeout))
  71. err = client.Handshake()
  72. client.SetDeadline(time.Time{}) // unset timeout
  73. if err != nil {
  74. continue // on tls Dial error keep trying HelloIDs
  75. }
  76. c.HelloIDMu.Lock()
  77. c.WorkingHelloID = &helloID
  78. c.HelloIDMu.Unlock()
  79. return client, err
  80. }
  81. return nil, err
  82. }
  83. // returns a shuffled copy of input
  84. func shuffleClientHelloIDs(helloIDs []ClientHelloID) ([]ClientHelloID, error) {
  85. perm, err := getRandPerm(len(helloIDs))
  86. if err != nil {
  87. return nil, err
  88. }
  89. shuffled := make([]ClientHelloID, len(helloIDs))
  90. for i, randI := range perm {
  91. shuffled[i] = helloIDs[randI]
  92. }
  93. return shuffled, nil
  94. }