meekConn.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /*
  2. * Copyright (c) 2015, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package psiphon
  20. import (
  21. "bytes"
  22. "crypto/rand"
  23. "encoding/base64"
  24. "encoding/json"
  25. "errors"
  26. "fmt"
  27. "io"
  28. "net"
  29. "net/http"
  30. "net/url"
  31. "strings"
  32. "sync"
  33. "time"
  34. "github.com/Psiphon-Inc/crypto/nacl/box"
  35. "github.com/Psiphon-Inc/goarista/monotime"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  37. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/upstreamproxy"
  38. )
  39. // MeekConn is based on meek-client.go from Tor and Psiphon:
  40. //
  41. // https://gitweb.torproject.org/pluggable-transports/meek.git/blob/HEAD:/meek-client/meek-client.go
  42. // CC0 1.0 Universal
  43. //
  44. // https://bitbucket.org/psiphon/psiphon-circumvention-system/src/default/go/meek-client/meek-client.go
  45. const (
  46. MEEK_PROTOCOL_VERSION = 2
  47. MEEK_COOKIE_MAX_PADDING = 32
  48. MAX_SEND_PAYLOAD_LENGTH = 65536
  49. FULL_RECEIVE_BUFFER_LENGTH = 4194304
  50. READ_PAYLOAD_CHUNK_LENGTH = 65536
  51. MIN_POLL_INTERVAL = 100 * time.Millisecond
  52. MIN_POLL_INTERVAL_JITTER = 0.3
  53. MAX_POLL_INTERVAL = 5 * time.Second
  54. MAX_POLL_INTERVAL_JITTER = 0.1
  55. POLL_INTERVAL_MULTIPLIER = 1.5
  56. POLL_INTERVAL_JITTER = 0.1
  57. MEEK_ROUND_TRIP_RETRY_DEADLINE = 1 * time.Second
  58. MEEK_ROUND_TRIP_RETRY_DELAY = 50 * time.Millisecond
  59. MEEK_ROUND_TRIP_TIMEOUT = 20 * time.Second
  60. )
  61. // MeekConfig specifies the behavior of a MeekConn
  62. type MeekConfig struct {
  63. // DialAddress is the actual network address to dial to establish a
  64. // connection to the meek server. This may be either a fronted or
  65. // direct address. The address must be in the form "host:port",
  66. // where host may be a domain name or IP address.
  67. DialAddress string
  68. // UseHTTPS indicates whether to use HTTPS (true) or HTTP (false).
  69. UseHTTPS bool
  70. // TLSProfile specifies the TLS profile to use for all underlying
  71. // TLS connections created by this meek connection. Valid values
  72. // are the possible values for CustomTLSConfig.TLSProfile.
  73. // TLSProfile will be used only when DialConfig.UseIndistinguishableTLS
  74. // is set in the DialConfig passed in to DialMeek.
  75. TLSProfile string
  76. // UseObfuscatedSessionTickets indicates whether to use obfuscated
  77. // session tickets. Assumes UseHTTPS is true.
  78. UseObfuscatedSessionTickets bool
  79. // SNIServerName is the value to place in the TLS SNI server_name
  80. // field when HTTPS is used.
  81. SNIServerName string
  82. // HostHeader is the value to place in the HTTP request Host header.
  83. HostHeader string
  84. // TransformedHostName records whether a hostname transformation is
  85. // in effect. This value is used for stats reporting.
  86. TransformedHostName bool
  87. // The following values are used to create the obfuscated meek cookie.
  88. PsiphonServerAddress string
  89. SessionID string
  90. MeekCookieEncryptionPublicKey string
  91. MeekObfuscatedKey string
  92. }
  93. // MeekConn is a network connection that tunnels TCP over HTTP and supports "fronting". Meek sends
  94. // client->server flow in HTTP request bodies and receives server->client flow in HTTP response bodies.
  95. // Polling is used to achieve full duplex TCP.
  96. //
  97. // Fronting is an obfuscation technique in which the connection
  98. // to a web server, typically a CDN, is indistinguishable from any other HTTPS connection to the generic
  99. // "fronting domain" -- the HTTP Host header is used to route the requests to the actual destination.
  100. // See https://trac.torproject.org/projects/tor/wiki/doc/meek for more details.
  101. //
  102. // MeekConn also operates in unfronted mode, in which plain HTTP connections are made without routing
  103. // through a CDN.
  104. type MeekConn struct {
  105. url *url.URL
  106. additionalHeaders http.Header
  107. cookie *http.Cookie
  108. pendingConns *common.Conns
  109. transport transporter
  110. mutex sync.Mutex
  111. isClosed bool
  112. broadcastClosed chan struct{}
  113. relayWaitGroup *sync.WaitGroup
  114. emptyReceiveBuffer chan *bytes.Buffer
  115. partialReceiveBuffer chan *bytes.Buffer
  116. fullReceiveBuffer chan *bytes.Buffer
  117. emptySendBuffer chan *bytes.Buffer
  118. partialSendBuffer chan *bytes.Buffer
  119. fullSendBuffer chan *bytes.Buffer
  120. }
  121. // transporter is implemented by both http.Transport and upstreamproxy.ProxyAuthTransport.
  122. type transporter interface {
  123. CancelRequest(req *http.Request)
  124. CloseIdleConnections()
  125. RegisterProtocol(scheme string, rt http.RoundTripper)
  126. RoundTrip(req *http.Request) (resp *http.Response, err error)
  127. }
  128. // DialMeek returns an initialized meek connection. A meek connection is
  129. // an HTTP session which does not depend on an underlying socket connection (although
  130. // persistent HTTP connections are used for performance). This function does not
  131. // wait for the connection to be "established" before returning. A goroutine
  132. // is spawned which will eventually start HTTP polling.
  133. // When frontingAddress is not "", fronting is used. This option assumes caller has
  134. // already checked server entry capabilities.
  135. func DialMeek(
  136. meekConfig *MeekConfig,
  137. dialConfig *DialConfig) (meek *MeekConn, err error) {
  138. // Configure transport
  139. // Note: MeekConn has its own PendingConns to manage the underlying HTTP transport connections,
  140. // which may be interrupted on MeekConn.Close(). This code previously used the establishTunnel
  141. // pendingConns here, but that was a lifecycle mismatch: we don't want to abort HTTP transport
  142. // connections while MeekConn is still in use
  143. pendingConns := new(common.Conns)
  144. // Use a copy of DialConfig with the meek pendingConns
  145. meekDialConfig := new(DialConfig)
  146. *meekDialConfig = *dialConfig
  147. meekDialConfig.PendingConns = pendingConns
  148. var transport transporter
  149. var additionalHeaders http.Header
  150. var proxyUrl func(*http.Request) (*url.URL, error)
  151. if meekConfig.UseHTTPS {
  152. // Custom TLS dialer:
  153. //
  154. // 1. ignores the HTTP request address and uses the fronting domain
  155. // 2. optionally disables SNI -- SNI breaks fronting when used with certain CDNs.
  156. // 3. skips verifying the server cert.
  157. //
  158. // Reasoning for #3:
  159. //
  160. // With a TLS MiM attack in place, and server certs verified, we'll fail to connect because the client
  161. // will refuse to connect. That's not a successful outcome.
  162. //
  163. // With a MiM attack in place, and server certs not verified, we'll fail to connect if the MiM is actively
  164. // targeting Psiphon and classifying the HTTP traffic by Host header or payload signature.
  165. //
  166. // However, in the case of a passive MiM that's just recording traffic or an active MiM that's targeting
  167. // something other than Psiphon, the client will connect. This is a successful outcome.
  168. //
  169. // What is exposed to the MiM? The Host header does not contain a Psiphon server IP address, just an
  170. // unrelated, randomly generated domain name which cannot be used to block direct connections. The
  171. // Psiphon server IP is sent over meek, but it's in the encrypted cookie.
  172. //
  173. // The payload (user traffic) gets its confidentiality and integrity from the underlying SSH protocol.
  174. // So, nothing is leaked to the MiM apart from signatures which could be used to classify the traffic
  175. // as Psiphon to possibly block it; but note that not revealing that the client is Psiphon is outside
  176. // our threat model; we merely seek to evade mass blocking by taking steps that require progressively
  177. // more effort to block.
  178. //
  179. // There is a subtle attack remaining: an adversary that can MiM some CDNs but not others (and so can
  180. // classify Psiphon traffic on some CDNs but not others) may throttle non-MiM CDNs so that our server
  181. // selection always chooses tunnels to the MiM CDN (without any server cert verification, we won't
  182. // exclusively connect to non-MiM CDNs); then the adversary kills the underlying TCP connection after
  183. // some short period. This is mitigated by the "impaired" protocol classification mechanism.
  184. tlsConfig := &CustomTLSConfig{
  185. DialAddr: meekConfig.DialAddress,
  186. Dial: NewTCPDialer(meekDialConfig),
  187. Timeout: meekDialConfig.ConnectTimeout,
  188. SNIServerName: meekConfig.SNIServerName,
  189. SkipVerify: true,
  190. UseIndistinguishableTLS: meekDialConfig.UseIndistinguishableTLS,
  191. TLSProfile: meekConfig.TLSProfile,
  192. TrustedCACertificatesFilename: meekDialConfig.TrustedCACertificatesFilename,
  193. }
  194. if meekConfig.UseObfuscatedSessionTickets {
  195. tlsConfig.ObfuscatedSessionTicketKey = meekConfig.MeekObfuscatedKey
  196. }
  197. dialer := NewCustomTLSDialer(tlsConfig)
  198. // TODO: wrap in an http.Client and use http.Client.Timeout which actually covers round trip
  199. transport = &http.Transport{
  200. Dial: dialer,
  201. ResponseHeaderTimeout: MEEK_ROUND_TRIP_TIMEOUT,
  202. }
  203. } else {
  204. // The dialer ignores address that http.Transport will pass in (derived
  205. // from the HTTP request URL) and always dials meekConfig.DialAddress.
  206. dialer := func(string, string) (net.Conn, error) {
  207. return NewTCPDialer(meekDialConfig)("tcp", meekConfig.DialAddress)
  208. }
  209. // For HTTP, and when the meekConfig.DialAddress matches the
  210. // meekConfig.HostHeader, we let http.Transport handle proxying.
  211. // http.Transport will put the the HTTP server address in the HTTP
  212. // request line. In this one case, we can use an HTTP proxy that does
  213. // not offer CONNECT support.
  214. if strings.HasPrefix(meekDialConfig.UpstreamProxyUrl, "http://") &&
  215. (meekConfig.DialAddress == meekConfig.HostHeader ||
  216. meekConfig.DialAddress == meekConfig.HostHeader+":80") {
  217. url, err := url.Parse(meekDialConfig.UpstreamProxyUrl)
  218. if err != nil {
  219. return nil, common.ContextError(err)
  220. }
  221. proxyUrl = http.ProxyURL(url)
  222. meekDialConfig.UpstreamProxyUrl = ""
  223. // Here, the dialer must use the address that http.Transport
  224. // passes in (which will be proxy address).
  225. dialer = NewTCPDialer(meekDialConfig)
  226. }
  227. // TODO: wrap in an http.Client and use http.Client.Timeout which actually covers round trip
  228. httpTransport := &http.Transport{
  229. Proxy: proxyUrl,
  230. Dial: dialer,
  231. ResponseHeaderTimeout: MEEK_ROUND_TRIP_TIMEOUT,
  232. }
  233. if proxyUrl != nil {
  234. // Wrap transport with a transport that can perform HTTP proxy auth negotiation
  235. transport, err = upstreamproxy.NewProxyAuthTransport(httpTransport, meekDialConfig.CustomHeaders)
  236. if err != nil {
  237. return nil, common.ContextError(err)
  238. }
  239. } else {
  240. transport = httpTransport
  241. }
  242. }
  243. // Scheme is always "http". Otherwise http.Transport will try to do another TLS
  244. // handshake inside the explicit TLS session (in fronting mode).
  245. url := &url.URL{
  246. Scheme: "http",
  247. Host: meekConfig.HostHeader,
  248. Path: "/",
  249. }
  250. if meekConfig.UseHTTPS {
  251. host, _, err := net.SplitHostPort(meekConfig.DialAddress)
  252. if err != nil {
  253. return nil, common.ContextError(err)
  254. }
  255. additionalHeaders = map[string][]string{
  256. "X-Psiphon-Fronting-Address": {host},
  257. }
  258. } else {
  259. if proxyUrl == nil {
  260. additionalHeaders = meekDialConfig.CustomHeaders
  261. }
  262. }
  263. cookie, err := makeMeekCookie(meekConfig)
  264. if err != nil {
  265. return nil, common.ContextError(err)
  266. }
  267. // The main loop of a MeekConn is run in the relay() goroutine.
  268. // A MeekConn implements net.Conn concurrency semantics:
  269. // "Multiple goroutines may invoke methods on a Conn simultaneously."
  270. //
  271. // Read() calls and relay() are synchronized by exchanging control of a single
  272. // receiveBuffer (bytes.Buffer). This single buffer may be:
  273. // - in the emptyReceiveBuffer channel when it is available and empty;
  274. // - in the partialReadBuffer channel when it is available and contains data;
  275. // - in the fullReadBuffer channel when it is available and full of data;
  276. // - "checked out" by relay or Read when they are are writing to or reading from the
  277. // buffer, respectively.
  278. // relay() will obtain the buffer from either the empty or partial channel but block when
  279. // the buffer is full. Read will obtain the buffer from the partial or full channel when
  280. // there is data to read but block when the buffer is empty.
  281. // Write() calls and relay() are synchronized in a similar way, using a single
  282. // sendBuffer.
  283. meek = &MeekConn{
  284. url: url,
  285. additionalHeaders: additionalHeaders,
  286. cookie: cookie,
  287. pendingConns: pendingConns,
  288. transport: transport,
  289. isClosed: false,
  290. broadcastClosed: make(chan struct{}),
  291. relayWaitGroup: new(sync.WaitGroup),
  292. emptyReceiveBuffer: make(chan *bytes.Buffer, 1),
  293. partialReceiveBuffer: make(chan *bytes.Buffer, 1),
  294. fullReceiveBuffer: make(chan *bytes.Buffer, 1),
  295. emptySendBuffer: make(chan *bytes.Buffer, 1),
  296. partialSendBuffer: make(chan *bytes.Buffer, 1),
  297. fullSendBuffer: make(chan *bytes.Buffer, 1),
  298. }
  299. // TODO: benchmark bytes.Buffer vs. built-in append with slices?
  300. meek.emptyReceiveBuffer <- new(bytes.Buffer)
  301. meek.emptySendBuffer <- new(bytes.Buffer)
  302. meek.relayWaitGroup.Add(1)
  303. go meek.relay()
  304. // Enable interruption
  305. if !dialConfig.PendingConns.Add(meek) {
  306. meek.Close()
  307. return nil, common.ContextError(errors.New("pending connections already closed"))
  308. }
  309. return meek, nil
  310. }
  311. // Close terminates the meek connection. Close waits for the relay processing goroutine
  312. // to stop and releases HTTP transport resources.
  313. // A mutex is required to support net.Conn concurrency semantics.
  314. func (meek *MeekConn) Close() (err error) {
  315. meek.mutex.Lock()
  316. isClosed := meek.isClosed
  317. meek.isClosed = true
  318. meek.mutex.Unlock()
  319. if !isClosed {
  320. close(meek.broadcastClosed)
  321. meek.pendingConns.CloseAll()
  322. meek.relayWaitGroup.Wait()
  323. meek.transport.CloseIdleConnections()
  324. }
  325. return nil
  326. }
  327. // IsClosed implements the Closer iterface. The return value
  328. // indicates whether the MeekConn has been closed.
  329. func (meek *MeekConn) IsClosed() bool {
  330. meek.mutex.Lock()
  331. isClosed := meek.isClosed
  332. meek.mutex.Unlock()
  333. return isClosed
  334. }
  335. // Read reads data from the connection.
  336. // net.Conn Deadlines are ignored. net.Conn concurrency semantics are supported.
  337. func (meek *MeekConn) Read(buffer []byte) (n int, err error) {
  338. if meek.IsClosed() {
  339. return 0, common.ContextError(errors.New("meek connection is closed"))
  340. }
  341. // Block until there is received data to consume
  342. var receiveBuffer *bytes.Buffer
  343. select {
  344. case receiveBuffer = <-meek.partialReceiveBuffer:
  345. case receiveBuffer = <-meek.fullReceiveBuffer:
  346. case <-meek.broadcastClosed:
  347. return 0, common.ContextError(errors.New("meek connection has closed"))
  348. }
  349. n, err = receiveBuffer.Read(buffer)
  350. meek.replaceReceiveBuffer(receiveBuffer)
  351. return n, err
  352. }
  353. // Write writes data to the connection.
  354. // net.Conn Deadlines are ignored. net.Conn concurrency semantics are supported.
  355. func (meek *MeekConn) Write(buffer []byte) (n int, err error) {
  356. if meek.IsClosed() {
  357. return 0, common.ContextError(errors.New("meek connection is closed"))
  358. }
  359. // Repeats until all n bytes are written
  360. n = len(buffer)
  361. for len(buffer) > 0 {
  362. // Block until there is capacity in the send buffer
  363. var sendBuffer *bytes.Buffer
  364. select {
  365. case sendBuffer = <-meek.emptySendBuffer:
  366. case sendBuffer = <-meek.partialSendBuffer:
  367. case <-meek.broadcastClosed:
  368. return 0, common.ContextError(errors.New("meek connection has closed"))
  369. }
  370. writeLen := MAX_SEND_PAYLOAD_LENGTH - sendBuffer.Len()
  371. if writeLen > 0 {
  372. if writeLen > len(buffer) {
  373. writeLen = len(buffer)
  374. }
  375. _, err = sendBuffer.Write(buffer[:writeLen])
  376. buffer = buffer[writeLen:]
  377. }
  378. meek.replaceSendBuffer(sendBuffer)
  379. }
  380. return n, err
  381. }
  382. // Stub implementation of net.Conn.LocalAddr
  383. func (meek *MeekConn) LocalAddr() net.Addr {
  384. return nil
  385. }
  386. // Stub implementation of net.Conn.RemoteAddr
  387. func (meek *MeekConn) RemoteAddr() net.Addr {
  388. return nil
  389. }
  390. // Stub implementation of net.Conn.SetDeadline
  391. func (meek *MeekConn) SetDeadline(t time.Time) error {
  392. return common.ContextError(errors.New("not supported"))
  393. }
  394. // Stub implementation of net.Conn.SetReadDeadline
  395. func (meek *MeekConn) SetReadDeadline(t time.Time) error {
  396. return common.ContextError(errors.New("not supported"))
  397. }
  398. // Stub implementation of net.Conn.SetWriteDeadline
  399. func (meek *MeekConn) SetWriteDeadline(t time.Time) error {
  400. return common.ContextError(errors.New("not supported"))
  401. }
  402. func (meek *MeekConn) replaceReceiveBuffer(receiveBuffer *bytes.Buffer) {
  403. switch {
  404. case receiveBuffer.Len() == 0:
  405. meek.emptyReceiveBuffer <- receiveBuffer
  406. case receiveBuffer.Len() >= FULL_RECEIVE_BUFFER_LENGTH:
  407. meek.fullReceiveBuffer <- receiveBuffer
  408. default:
  409. meek.partialReceiveBuffer <- receiveBuffer
  410. }
  411. }
  412. func (meek *MeekConn) replaceSendBuffer(sendBuffer *bytes.Buffer) {
  413. switch {
  414. case sendBuffer.Len() == 0:
  415. meek.emptySendBuffer <- sendBuffer
  416. case sendBuffer.Len() >= MAX_SEND_PAYLOAD_LENGTH:
  417. meek.fullSendBuffer <- sendBuffer
  418. default:
  419. meek.partialSendBuffer <- sendBuffer
  420. }
  421. }
  422. // relay sends and receives tunneled traffic (payload). An HTTP request is
  423. // triggered when data is in the write queue or at a polling interval.
  424. // There's a geometric increase, up to a maximum, in the polling interval when
  425. // no data is exchanged. Only one HTTP request is in flight at a time.
  426. func (meek *MeekConn) relay() {
  427. // Note: meek.Close() calls here in relay() are made asynchronously
  428. // (using goroutines) since Close() will wait on this WaitGroup.
  429. defer meek.relayWaitGroup.Done()
  430. interval := common.JitterDuration(
  431. MIN_POLL_INTERVAL,
  432. MIN_POLL_INTERVAL_JITTER)
  433. timeout := time.NewTimer(interval)
  434. sendPayload := make([]byte, MAX_SEND_PAYLOAD_LENGTH)
  435. for {
  436. timeout.Reset(interval)
  437. // Block until there is payload to send or it is time to poll
  438. var sendBuffer *bytes.Buffer
  439. select {
  440. case sendBuffer = <-meek.partialSendBuffer:
  441. case sendBuffer = <-meek.fullSendBuffer:
  442. case <-timeout.C:
  443. // In the polling case, send an empty payload
  444. case <-meek.broadcastClosed:
  445. // TODO: timeout case may be selected when broadcastClosed is set?
  446. return
  447. }
  448. sendPayloadSize := 0
  449. if sendBuffer != nil {
  450. var err error
  451. sendPayloadSize, err = sendBuffer.Read(sendPayload)
  452. meek.replaceSendBuffer(sendBuffer)
  453. if err != nil {
  454. NoticeAlert("%s", common.ContextError(err))
  455. go meek.Close()
  456. return
  457. }
  458. }
  459. receivedPayload, err := meek.roundTrip(sendPayload[:sendPayloadSize])
  460. if err != nil {
  461. NoticeAlert("%s", common.ContextError(err))
  462. go meek.Close()
  463. return
  464. }
  465. if receivedPayload == nil {
  466. // In this case, meek.roundTrip encountered broadcastClosed. Exit without error.
  467. return
  468. }
  469. receivedPayloadSize, err := meek.readPayload(receivedPayload)
  470. if err != nil {
  471. NoticeAlert("%s", common.ContextError(err))
  472. go meek.Close()
  473. return
  474. }
  475. // Calculate polling interval. When data is received,
  476. // immediately request more. Otherwise, schedule next
  477. // poll with exponential back off. Jitter and coin
  478. // flips are used to avoid trivial, static traffic
  479. // timing patterns.
  480. if receivedPayloadSize > 0 || sendPayloadSize > 0 {
  481. interval = 0
  482. } else if interval == 0 {
  483. interval = common.JitterDuration(
  484. MIN_POLL_INTERVAL,
  485. MIN_POLL_INTERVAL_JITTER)
  486. } else {
  487. if common.FlipCoin() {
  488. interval = common.JitterDuration(
  489. interval,
  490. POLL_INTERVAL_JITTER)
  491. } else {
  492. interval = common.JitterDuration(
  493. time.Duration(float64(interval)*POLL_INTERVAL_MULTIPLIER),
  494. POLL_INTERVAL_JITTER)
  495. }
  496. if interval >= MAX_POLL_INTERVAL {
  497. interval = common.JitterDuration(
  498. MAX_POLL_INTERVAL,
  499. MAX_POLL_INTERVAL_JITTER)
  500. }
  501. }
  502. }
  503. }
  504. // readPayload reads the HTTP response in chunks, making the read buffer available
  505. // to MeekConn.Read() calls after each chunk; the intention is to allow bytes to
  506. // flow back to the reader as soon as possible instead of buffering the entire payload.
  507. func (meek *MeekConn) readPayload(receivedPayload io.ReadCloser) (totalSize int64, err error) {
  508. defer receivedPayload.Close()
  509. totalSize = 0
  510. for {
  511. reader := io.LimitReader(receivedPayload, READ_PAYLOAD_CHUNK_LENGTH)
  512. // Block until there is capacity in the receive buffer
  513. var receiveBuffer *bytes.Buffer
  514. select {
  515. case receiveBuffer = <-meek.emptyReceiveBuffer:
  516. case receiveBuffer = <-meek.partialReceiveBuffer:
  517. case <-meek.broadcastClosed:
  518. return 0, nil
  519. }
  520. // Note: receiveBuffer size may exceed FULL_RECEIVE_BUFFER_LENGTH by up to the size
  521. // of one received payload. The FULL_RECEIVE_BUFFER_LENGTH value is just a threshold.
  522. n, err := receiveBuffer.ReadFrom(reader)
  523. meek.replaceReceiveBuffer(receiveBuffer)
  524. if err != nil {
  525. return 0, common.ContextError(err)
  526. }
  527. totalSize += n
  528. if n == 0 {
  529. break
  530. }
  531. }
  532. return totalSize, nil
  533. }
  534. // roundTrip configures and makes the actual HTTP POST request
  535. func (meek *MeekConn) roundTrip(sendPayload []byte) (io.ReadCloser, error) {
  536. // The retry mitigates intermittent failures between the client and front/server.
  537. //
  538. // Note: Retry will only be effective if entire request failed (underlying transport protocol
  539. // such as SSH will fail if extra bytes are replayed in either direction due to partial relay
  540. // success followed by retry).
  541. // At least one retry is always attempted. We retry when still within a brief deadline and wait
  542. // for a short time before re-dialing.
  543. //
  544. // TODO: in principle, we could retry for min(TUNNEL_WRITE_TIMEOUT, meek-server.MAX_SESSION_STALENESS),
  545. // i.e., as long as the underlying tunnel has not timed out and as long as the server has not
  546. // expired the current meek session. Presently not doing this to avoid excessive connection attempts
  547. // through the first hop. In addition, this will require additional support for timely shutdown.
  548. retries := uint(0)
  549. retryDeadline := monotime.Now().Add(MEEK_ROUND_TRIP_RETRY_DEADLINE)
  550. var err error
  551. var response *http.Response
  552. for {
  553. var request *http.Request
  554. request, err = http.NewRequest("POST", meek.url.String(), bytes.NewReader(sendPayload))
  555. if err != nil {
  556. // Don't retry when can't initialize a Request
  557. break
  558. }
  559. request.Header.Set("Content-Type", "application/octet-stream")
  560. // Set additional headers to the HTTP request using the same method we use for adding
  561. // custom headers to HTTP proxy requests
  562. for name, value := range meek.additionalHeaders {
  563. // hack around special case of "Host" header
  564. // https://golang.org/src/net/http/request.go#L474
  565. // using URL.Opaque, see URL.RequestURI() https://golang.org/src/net/url/url.go#L915
  566. if name == "Host" {
  567. if len(value) > 0 {
  568. if request.URL.Opaque == "" {
  569. request.URL.Opaque = request.URL.Scheme + "://" + request.Host + request.URL.RequestURI()
  570. }
  571. request.Host = value[0]
  572. }
  573. } else {
  574. request.Header[name] = value
  575. }
  576. }
  577. request.AddCookie(meek.cookie)
  578. // The http.Transport.RoundTrip is run in a goroutine to enable cancelling a request in-flight.
  579. type roundTripResponse struct {
  580. response *http.Response
  581. err error
  582. }
  583. roundTripResponseChannel := make(chan *roundTripResponse, 1)
  584. roundTripWaitGroup := new(sync.WaitGroup)
  585. roundTripWaitGroup.Add(1)
  586. go func() {
  587. defer roundTripWaitGroup.Done()
  588. r, err := meek.transport.RoundTrip(request)
  589. roundTripResponseChannel <- &roundTripResponse{r, err}
  590. }()
  591. select {
  592. case roundTripResponse := <-roundTripResponseChannel:
  593. response = roundTripResponse.response
  594. err = roundTripResponse.err
  595. case <-meek.broadcastClosed:
  596. meek.transport.CancelRequest(request)
  597. return nil, nil
  598. }
  599. roundTripWaitGroup.Wait()
  600. if err == nil {
  601. break
  602. }
  603. if retries >= 1 && monotime.Now().After(retryDeadline) {
  604. break
  605. }
  606. retries += 1
  607. time.Sleep(MEEK_ROUND_TRIP_RETRY_DELAY)
  608. }
  609. if err != nil {
  610. return nil, common.ContextError(err)
  611. }
  612. if response.StatusCode != http.StatusOK {
  613. return nil, common.ContextError(fmt.Errorf("http request failed %d", response.StatusCode))
  614. }
  615. // observe response cookies for meek session key token.
  616. // Once found it must be used for all consecutive requests made to the server
  617. for _, c := range response.Cookies() {
  618. if meek.cookie.Name == c.Name {
  619. meek.cookie.Value = c.Value
  620. break
  621. }
  622. }
  623. return response.Body, nil
  624. }
  625. type meekCookieData struct {
  626. ServerAddress string `json:"p"`
  627. SessionID string `json:"s"`
  628. MeekProtocolVersion int `json:"v"`
  629. }
  630. // makeCookie creates the cookie to be sent with initial meek HTTP request.
  631. // The purpose of the cookie is to send the following to the server:
  632. // ServerAddress -- the Psiphon Server address the meek server should relay to
  633. // SessionID -- the Psiphon session ID (used by meek server to relay geolocation
  634. // information obtained from the CDN through to the Psiphon Server)
  635. // MeekProtocolVersion -- tells the meek server that this client understands
  636. // the latest protocol.
  637. // The server will create a session using these values and send the session ID
  638. // back to the client via Set-Cookie header. Client must use that value with
  639. // all consequent HTTP requests
  640. // In unfronted meek mode, the cookie is visible over the adversary network, so the
  641. // cookie is encrypted and obfuscated.
  642. func makeMeekCookie(meekConfig *MeekConfig) (cookie *http.Cookie, err error) {
  643. // Make the JSON data
  644. serverAddress := meekConfig.PsiphonServerAddress
  645. cookieData := &meekCookieData{
  646. ServerAddress: serverAddress,
  647. SessionID: meekConfig.SessionID,
  648. MeekProtocolVersion: MEEK_PROTOCOL_VERSION,
  649. }
  650. serializedCookie, err := json.Marshal(cookieData)
  651. if err != nil {
  652. return nil, common.ContextError(err)
  653. }
  654. // Encrypt the JSON data
  655. // NaCl box is used for encryption. The peer public key comes from the server entry.
  656. // Nonce is always all zeros, and is not sent in the cookie (the server also uses an all-zero nonce).
  657. // http://nacl.cace-project.eu/box.html:
  658. // "There is no harm in having the same nonce for different messages if the {sender, receiver} sets are
  659. // different. This is true even if the sets overlap. For example, a sender can use the same nonce for two
  660. // different messages if the messages are sent to two different public keys."
  661. var nonce [24]byte
  662. var publicKey [32]byte
  663. decodedPublicKey, err := base64.StdEncoding.DecodeString(meekConfig.MeekCookieEncryptionPublicKey)
  664. if err != nil {
  665. return nil, common.ContextError(err)
  666. }
  667. copy(publicKey[:], decodedPublicKey)
  668. ephemeralPublicKey, ephemeralPrivateKey, err := box.GenerateKey(rand.Reader)
  669. if err != nil {
  670. return nil, common.ContextError(err)
  671. }
  672. box := box.Seal(nil, serializedCookie, &nonce, &publicKey, ephemeralPrivateKey)
  673. encryptedCookie := make([]byte, 32+len(box))
  674. copy(encryptedCookie[0:32], ephemeralPublicKey[0:32])
  675. copy(encryptedCookie[32:], box)
  676. // Obfuscate the encrypted data
  677. obfuscator, err := common.NewClientObfuscator(
  678. &common.ObfuscatorConfig{Keyword: meekConfig.MeekObfuscatedKey, MaxPadding: MEEK_COOKIE_MAX_PADDING})
  679. if err != nil {
  680. return nil, common.ContextError(err)
  681. }
  682. obfuscatedCookie := obfuscator.SendSeedMessage()
  683. seedLen := len(obfuscatedCookie)
  684. obfuscatedCookie = append(obfuscatedCookie, encryptedCookie...)
  685. obfuscator.ObfuscateClientToServer(obfuscatedCookie[seedLen:])
  686. // Format the HTTP cookie
  687. // The format is <random letter 'A'-'Z'>=<base64 data>, which is intended to match common cookie formats.
  688. A := int('A')
  689. Z := int('Z')
  690. // letterIndex is integer in range [int('A'), int('Z')]
  691. letterIndex, err := common.MakeSecureRandomInt(Z - A + 1)
  692. if err != nil {
  693. return nil, common.ContextError(err)
  694. }
  695. return &http.Cookie{
  696. Name: string(byte(A + letterIndex)),
  697. Value: base64.StdEncoding.EncodeToString(obfuscatedCookie)},
  698. nil
  699. }