common.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package tapdance
  2. import (
  3. "crypto/rand"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "os"
  8. "strconv"
  9. "time"
  10. "github.com/refraction-networking/gotapdance/ed25519/extra25519"
  11. "golang.org/x/crypto/curve25519"
  12. )
  13. const AES_GCM_TAG_SIZE = 16
  14. const timeoutMax = 30000
  15. const timeoutMin = 20000
  16. const sendLimitMax = 15614
  17. const sendLimitMin = 14400
  18. // timeout for sending TD request and getting a response
  19. const deadlineConnectTDStationMin = 11175
  20. const deadlineConnectTDStationMax = 14231
  21. // deadline to establish TCP connection to decoy
  22. const deadlineTCPtoDecoyMin = deadlineConnectTDStationMin
  23. const deadlineTCPtoDecoyMax = deadlineConnectTDStationMax
  24. // during reconnects we send FIN to server and wait until we get FIN back
  25. const waitForFINDieMin = 2 * deadlineConnectTDStationMin
  26. const waitForFINDieMax = 2 * deadlineConnectTDStationMax
  27. const maxInt16 = int16(^uint16(0) >> 1) // max msg size -> might have to chunk
  28. //const minInt16 = int16(-maxInt16 - 1)
  29. type flowType int8
  30. /*______________________TapdanceFlowConn Mode Chart _________________________________\
  31. |FlowType |Default Tag|Diff from old-school bidirectional | Engines spawned|
  32. |-------------|-----------|-----------------------------------------|----------------|
  33. |Bidirectional| HTTP GET | | Writer, Reader |
  34. |Upload | HTTP POST | acquires upload | Writer, Reader |
  35. |ReadOnly | HTTP GET | yields upload, writer sync ignored | Reader |
  36. |Rendezvous | HTTP GET | passes data in handshake and shuts down | |
  37. \_____________|___________|_________________________________________|_______________*/
  38. const (
  39. flowUpload flowType = 0x1
  40. flowReadOnly flowType = 0x2
  41. flowBidirectional flowType = 0x4
  42. flowRendezvous flowType = 0x0 // rendezvous flows shutdown after handshake
  43. )
  44. func (m *flowType) Str() string {
  45. switch *m {
  46. case flowUpload:
  47. return "FlowUpload"
  48. case flowReadOnly:
  49. return "FlowReadOnly"
  50. case flowBidirectional:
  51. return "FlowBidirectional"
  52. default:
  53. return strconv.Itoa(int(*m))
  54. }
  55. }
  56. type msgType int8
  57. const (
  58. msgRawData msgType = 1
  59. msgProtobuf msgType = 2
  60. )
  61. func (m *msgType) Str() string {
  62. switch *m {
  63. case msgRawData:
  64. return "msg raw_data"
  65. case msgProtobuf:
  66. return "msg protobuf"
  67. default:
  68. return strconv.Itoa(int(*m))
  69. }
  70. }
  71. var errMsgClose = errors.New("MSG CLOSE")
  72. var errNotImplemented = errors.New("Not implemented")
  73. type tdTagType int8
  74. const (
  75. tagHttpGetIncomplete tdTagType = 0
  76. tagHttpGetComplete tdTagType = 1
  77. tagHttpPostIncomplete tdTagType = 2
  78. )
  79. func (m *tdTagType) Str() string {
  80. switch *m {
  81. case tagHttpGetIncomplete:
  82. return "HTTP GET Incomplete"
  83. case tagHttpGetComplete:
  84. return "HTTP GET Complete"
  85. case tagHttpPostIncomplete:
  86. return "HTTP POST Incomplete"
  87. default:
  88. return strconv.Itoa(int(*m))
  89. }
  90. }
  91. // Fixed-Size-Payload has a 1 byte flags field.
  92. // bit 0 (1 << 7) determines if flow is bidirectional(0) or upload-only(1)
  93. // bit 1 (1 << 6) enables dark-decoys
  94. // bits 2-5 are unassigned
  95. // bit 6 determines whether PROXY-protocol-formatted string will be sent
  96. // bit 7 (1 << 0) signals to use TypeLen outer proto
  97. var (
  98. tdFlagUploadOnly = uint8(1 << 7)
  99. // tdFlagDarkDecoy = uint8(1 << 6)
  100. tdFlagProxyHeader = uint8(1 << 1)
  101. tdFlagUseTIL = uint8(1 << 0)
  102. )
  103. var default_flags = tdFlagUseTIL
  104. // Global EnableProxyProtocol() is deprecated,
  105. // use tapdance.Dialer with UseProxyHeader flag instead
  106. //
  107. // Requests station to send client's IP to covert in following form:
  108. // PROXY TCP4 x.x.x.x 127.0.0.1 1111 1234\r\n
  109. // ^__^ ^_____^ ^_________________^
  110. // proto clientIP garbage
  111. func EnableProxyProtocol() {
  112. Logger().Println("tapdance.EnableProxyProtocol() is deprecated, " +
  113. "use tapdance.Dialer with UseProxyHeader flag instead.")
  114. default_flags |= tdFlagProxyHeader
  115. return
  116. }
  117. var tlsSecretLog string
  118. func SetTlsLogFilename(filename string) error {
  119. tlsSecretLog = filename
  120. // Truncate file
  121. f, err := os.Create(filename)
  122. if err != nil {
  123. return err
  124. }
  125. return f.Close()
  126. }
  127. func WriteTlsLog(clientRandom, masterSecret []byte) error {
  128. if tlsSecretLog != "" {
  129. f, err := os.OpenFile(tlsSecretLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
  130. if err != nil {
  131. return err
  132. }
  133. _, err = fmt.Fprintf(f, "CLIENT_RANDOM %s %s\n",
  134. hex.EncodeToString(clientRandom),
  135. hex.EncodeToString(masterSecret))
  136. if err != nil {
  137. return err
  138. }
  139. return f.Close()
  140. }
  141. return nil
  142. }
  143. // How much time to sleep on trying to connect to decoys to prevent overwhelming them
  144. func sleepBeforeConnect(attempt int) (waitTime <-chan time.Time) {
  145. if attempt >= 6 { // return nil for first 6 attempts
  146. waitTime = time.After(time.Second * 1)
  147. }
  148. return
  149. }
  150. // takes Station's Public Key
  151. // returns Shared Secret, and Eligator Representative
  152. func generateEligatorTransformedKey(stationPubkey []byte) ([]byte, []byte, error) {
  153. if len(stationPubkey) != 32 {
  154. return nil, nil, errors.New("Unexpected station pubkey length. Expected: 32." +
  155. " Received: " + strconv.Itoa(len(stationPubkey)) + ".")
  156. }
  157. var sharedSecret, clientPrivate, clientPublic, representative [32]byte
  158. for ok := false; ok != true; {
  159. var sliceKeyPrivate []byte = clientPrivate[:]
  160. _, err := rand.Read(sliceKeyPrivate)
  161. if err != nil {
  162. return nil, nil, err
  163. }
  164. ok = extra25519.ScalarBaseMult(&clientPublic, &representative, &clientPrivate)
  165. }
  166. var stationPubkeyByte32 [32]byte
  167. copy(stationPubkeyByte32[:], stationPubkey)
  168. curve25519.ScalarMult(&sharedSecret, &clientPrivate, &stationPubkeyByte32)
  169. // extra25519.ScalarBaseMult does not randomize most significant bit(sign of y_coord?)
  170. // Other implementations of elligator may have up to 2 non-random bits.
  171. // Here we randomize the bit, expecting it to be flipped back to 0 on station
  172. randByte := make([]byte, 1)
  173. _, err := rand.Read(randByte)
  174. if err != nil {
  175. return nil, nil, err
  176. }
  177. representative[31] |= (0xC0 & randByte[0])
  178. return sharedSecret[:], representative[:], nil
  179. }