httpNormalizer.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*
  2. * Copyright (c) 2023, 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 transforms
  20. import (
  21. "bytes"
  22. std_errors "errors"
  23. "io"
  24. "net"
  25. "net/textproto"
  26. "strconv"
  27. "sync/atomic"
  28. "time"
  29. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  30. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  31. )
  32. const (
  33. // httpNormalizerReadReqLineAndHeader HTTPNormalizer is waiting to finish
  34. // reading the Request-Line, and headers, of the next request from the
  35. // underlying net.Conn.
  36. httpNormalizerReadReqLineAndHeader = 0
  37. // httpNormalizerReadBody HTTPNormalizer is waiting to finish reading the
  38. // current request body from the underlying net.Conn.
  39. httpNormalizerReadBody = 1
  40. // httpNormalizerRequestLine is a valid Request-Line used by the normalizer.
  41. httpNormalizerRequestLine = "POST / HTTP/1.1"
  42. hostHeader = "Host"
  43. contentLengthHeader = "Content-Length"
  44. cookieHeader = "Cookie"
  45. rangeHeader = "Range"
  46. )
  47. var ErrPassthroughActive = std_errors.New("passthrough")
  48. // HTTPNormalizer wraps a net.Conn, intercepting Read calls, and normalizes any
  49. // HTTP requests that are read. The HTTP request components preceeding the body
  50. // are normalized; i.e. the Request-Line and headers.
  51. //
  52. // Each HTTP request read from the underlying net.Conn is normalized and then
  53. // returned over subsequent Read calls.
  54. //
  55. // HTTPNormalizer is not safe for concurrent use.
  56. type HTTPNormalizer struct {
  57. // state is the HTTPNormalizer state. Possible values are
  58. // httpNormalizerReadReqLineAndHeader and httpNormalizerReadBody.
  59. state int64
  60. // b is used to buffer the accumulated bytes of the current request
  61. // until the Request-Line, and headers, are read from the underlying
  62. // net.Conn, normalized, and returned in one, or more, Read calls. May
  63. // contain bytes of the current request body and subsequent requests until
  64. // they are processed.
  65. b bytes.Buffer
  66. // maxReqLineAndHeadersSize is the maximum number of bytes the normalizer
  67. // will read before establishing a passthrough session, or rejecting the
  68. // connection, if the request body of the current request has not been
  69. // reached.
  70. // No limit is applied if the value is 0.
  71. maxReqLineAndHeadersSize int
  72. // scanIndex is the index that the bytes in b have been processed up to.
  73. // Bytes before this index in b will not contain the RequestLine, or
  74. // headers, of the current request after a Read call. Applies when state is
  75. // httpNormalizerReadReqLineAndHeader.
  76. scanIndex int
  77. // readRequestLine is set to true when the Request-Line of the current
  78. // request has been read. Applies when state is httpNormalizerReadReqLineAndHeader.
  79. readRequestLine bool
  80. // reqLineAndHeadersBuf is the buffer used to stage the next normalized
  81. // Request-Line, and headers, before outputting them in Read.
  82. reqLineAndHeadersBuf bytes.Buffer
  83. // headers is the staging area for preserved headers and is reset after the
  84. // Request-Line, and headers, of the current request are processed.
  85. headers map[string][]byte
  86. // contentLength of the current request. Reset after the Request-Line, and
  87. // headers, of the current request are processed
  88. contentLength *uint64
  89. // preserveHeaders are the headers to preserve during request normalization.
  90. preserveHeaders []string
  91. // prohibitedHeaders is a list of HTTP headers to check for in the
  92. // request. If one of these headers is found, then a passthrough is
  93. // performed. This is used to defend against abuse.
  94. // Limitation: prohibited headers are only logged when passthrough is
  95. // configured and passthroughLogPassthrough is set.
  96. prohibitedHeaders []string
  97. // headerWriteOrder is the order in which headers are written if set. Used
  98. // for testing.
  99. headerWriteOrder []string
  100. // readRemain is the number of remaining request body bytes of the current
  101. // request to read from the underlying net.Conn.
  102. readRemain uint64
  103. // copyRemain is the number of remaining bytes of the current request to
  104. // return over one, or more, Read calls.
  105. copyRemain uint64
  106. // validateMeekCookie is called with the cookie header value of the current
  107. // request when it is received and a passthrough session is established if
  108. // false is returned.
  109. // Note: if there are multiple cookie headers, even though prohibited by
  110. // rfc6265, then validateMeekCookie will only be invoked once with the
  111. // first one received.
  112. validateMeekCookie func(rawCookies []byte) ([]byte, error)
  113. // ValidateMeekCookieResult stores the result from calling
  114. // validateMeekCookie.
  115. ValidateMeekCookieResult []byte
  116. // passthrough is set to 1 if the normalizer has established a passthrough
  117. // session; otherwise 0.
  118. // Note: may be accessed concurrently so must be get and set atomically.
  119. // E.g. the net.Conn interface methods implemented by HTTPNormalizer may be
  120. // called concurrent to each other.
  121. passthrough int32
  122. // passthroughDialer is used to establish any passthrough sessions.
  123. passthroughDialer func(network, address string) (net.Conn, error)
  124. // passthroughAddress is the passthrough address that will be used for any
  125. // passthrough sessions.
  126. passthroughAddress string
  127. // passthroughLogPassthrough is called when a passthrough session is
  128. // initiated.
  129. passthroughLogPassthrough func(clientIP string, tunnelError error, logFields map[string]interface{})
  130. net.Conn
  131. }
  132. func NewHTTPNormalizer(conn net.Conn) *HTTPNormalizer {
  133. t := HTTPNormalizer{
  134. Conn: conn,
  135. }
  136. // TODO/perf: could pre-alloc n.b, and n.reqLineAndHeadersBuf,
  137. // with (*bytes.Buffer).Grow().
  138. t.reqLineAndHeadersBuf.WriteString(httpNormalizerRequestLine)
  139. t.preserveHeaders = []string{
  140. hostHeader,
  141. contentLengthHeader,
  142. cookieHeader,
  143. rangeHeader,
  144. }
  145. return &t
  146. }
  147. // Read implements the net.Conn interface.
  148. //
  149. // Note: it is assumed that the underlying transport, net.Conn, is a reliable
  150. // stream transport, i.e. TCP, therefore it is required that the caller stop
  151. // calling Read() on an instance of HTTPNormalizer after an error is returned
  152. // because, following this assumption, the connection will have failed when a
  153. // Read() call to the underlying net.Conn fails; a new connection must be
  154. // established, net.Conn, and wrapped with a new HTTPNormalizer.
  155. //
  156. // Warning: Does not handle chunked encoding. Must be called synchronously.
  157. func (t *HTTPNormalizer) Read(buffer []byte) (int, error) {
  158. if atomic.LoadInt32(&t.passthrough) == 1 {
  159. return 0, io.EOF
  160. }
  161. // TODO/perf: allocate on-demand
  162. if t.headers == nil {
  163. t.headers = make(map[string][]byte)
  164. }
  165. if t.state == httpNormalizerReadReqLineAndHeader {
  166. // perf: read into caller's buffer instead of allocating a new one.
  167. // perf: theoretically it could be more performant to read directly
  168. // into t.b, but there is no mechanism to do so with bytes.Buffer.
  169. n, err := t.Conn.Read(buffer)
  170. if n > 0 {
  171. // Do not need to check return value. Applies to all subsequent
  172. // calls to t.b.Write() and this comment will not be repeated for
  173. // each. See https://github.com/golang/go/blob/1e9ff255a130200fcc4ec5e911d28181fce947d5/src/bytes/buffer.go#L164.
  174. t.b.Write(buffer[:n])
  175. }
  176. crlf := []byte("\r\n")
  177. doublecrlf := []byte("\r\n\r\n")
  178. // Check if the maximum number of bytes to read before the request body
  179. // has been exceeded first.
  180. // Note: could check if max header size will be exceeded before Read
  181. // call or ensure the buffer passed into Read is no larger than
  182. // t.maxReqLineAndHeadersSize-t.b.Len().
  183. if t.maxReqLineAndHeadersSize > 0 && t.b.Len() > t.maxReqLineAndHeadersSize && !bytes.Contains(t.b.Bytes()[:t.maxReqLineAndHeadersSize], doublecrlf) {
  184. if t.passthroughConfigured() {
  185. t.startPassthrough(errors.TraceNew("maxReqLineAndHeadersSize exceeded before request body received"), nil)
  186. return 0, nil
  187. }
  188. return 0, errors.Tracef("%d exceeds maxReqLineAndHeadersSize %d", t.b.Len(), t.maxReqLineAndHeadersSize)
  189. }
  190. if err != nil {
  191. // Do not wrap any I/O err returned by Conn
  192. return 0, err
  193. }
  194. // preserve headers
  195. //
  196. // TODO/perf: instead of storing headers in a map they could be
  197. // processed and written as they are parsed, but benchmarking this
  198. // change shows no measurable change in performance.
  199. //
  200. // TODO/perf: skip Request-Line, e.g. "GET /foo HTTP/1.1"
  201. reachedBody := false
  202. for {
  203. // NOTE: could add guard here for t.scanIndex < t.b.Len(),
  204. // but should never happen.
  205. i := bytes.Index(t.b.Bytes()[t.scanIndex:], crlf)
  206. var header []byte
  207. if i == -1 {
  208. break // no more CRLF separated headers in t.b
  209. } else {
  210. header = t.b.Bytes()[t.scanIndex : t.scanIndex+i]
  211. }
  212. if len(header) == 0 && t.readRequestLine {
  213. // Zero-length header line means the end of the request headers
  214. // has been reached.
  215. reachedBody = true
  216. break
  217. }
  218. if !t.readRequestLine {
  219. t.readRequestLine = true
  220. }
  221. if len(t.headers) >= len(t.preserveHeaders) {
  222. t.scanIndex += i + len(crlf)
  223. continue // found all headers, continue until final CRLF
  224. }
  225. colon := bytes.Index(header, []byte(":"))
  226. if colon == -1 {
  227. t.scanIndex += i + len(crlf)
  228. continue // not a header, skip
  229. }
  230. // Allow for space before header and trim whitespace around
  231. // value.
  232. k := textproto.TrimBytes(header[:colon])
  233. v := textproto.TrimBytes(header[colon+1:]) // skip over ":"
  234. err = nil
  235. var logFields map[string]interface{}
  236. if t.validateMeekCookie != nil && t.ValidateMeekCookieResult == nil && bytes.Equal(k, []byte(cookieHeader)) {
  237. t.ValidateMeekCookieResult, err = t.validateMeekCookie(v)
  238. if err != nil {
  239. err = errors.TraceMsg(err, "invalid meek cookie")
  240. }
  241. }
  242. if err == nil {
  243. if bytes.Equal(k, []byte(contentLengthHeader)) {
  244. var cl uint64
  245. cl, err = strconv.ParseUint(string(v), 10, 63)
  246. if err != nil {
  247. err = errors.TraceMsg(err, "invalid Content-Length")
  248. } else {
  249. t.contentLength = &cl
  250. }
  251. }
  252. }
  253. if err == nil {
  254. // Do passthrough if a prohibited header is found
  255. for _, h := range t.prohibitedHeaders {
  256. // TODO/perf: consider using map, but array may be faster
  257. // and use less mem.
  258. if bytes.Equal(k, []byte(h)) {
  259. err = errors.TraceNew("prohibited header")
  260. logFields = map[string]interface{}{
  261. "header": h,
  262. "value": v,
  263. }
  264. break
  265. }
  266. }
  267. }
  268. if err != nil {
  269. if t.passthroughConfigured() {
  270. t.startPassthrough(err, logFields)
  271. return 0, nil
  272. } else {
  273. return 0, errors.Trace(err)
  274. }
  275. }
  276. for _, h := range t.preserveHeaders {
  277. // TODO/perf: consider using map, but array may be faster and
  278. // use less mem.
  279. if bytes.Equal(k, []byte(h)) {
  280. // TODO: if there are multiple preserved headers with the
  281. // same key, then the last header parsed will be the
  282. // preserved value. Consider if this is the desired
  283. // functionality.
  284. t.headers[h] = v
  285. break
  286. }
  287. }
  288. t.scanIndex += i + len(crlf)
  289. }
  290. if !reachedBody {
  291. return 0, nil
  292. } // else: Request-Line and all headers have been read.
  293. bodyOffset := t.scanIndex + len(crlf)
  294. // reset for next request
  295. defer func() {
  296. t.scanIndex = 0
  297. t.readRequestLine = false
  298. t.headers = nil
  299. t.contentLength = nil
  300. }()
  301. err = nil
  302. if t.contentLength == nil {
  303. // Irrecoverable error because either Content-Length header
  304. // is missing, or Content-Length header value is empty, e.g.
  305. // "Content-Length: ", and request body length cannot be
  306. // determined.
  307. err = errors.TraceNew("Content-Length missing")
  308. }
  309. if err == nil {
  310. if t.validateMeekCookie != nil {
  311. // NOTE: could check t.ValidateMeekCookieResult == nil instead
  312. // if it is guaranteed to return a non-nil result if no error is
  313. // returned.
  314. if _, ok := t.headers[cookieHeader]; !ok {
  315. err = errors.TraceNew("cookie missing")
  316. }
  317. }
  318. }
  319. if err != nil {
  320. if t.passthroughConfigured() {
  321. t.startPassthrough(err, nil)
  322. return 0, nil
  323. } else {
  324. return 0, errors.Trace(err)
  325. }
  326. }
  327. // No passthrough will be performed. Discard buffered bytes because
  328. // they are no longer needed to perform a passthrough.
  329. t.b.Next(bodyOffset)
  330. // TODO: technically at this point we could start copying bytes into the
  331. // caller's buffer which would remove the need to copy len(buffer) bytes
  332. // twice; first into the internal buffer and second into the caller's
  333. // buffer.
  334. t.reqLineAndHeadersBuf.Truncate(len(httpNormalizerRequestLine))
  335. if _, ok := t.headers[hostHeader]; !ok {
  336. // net/http expects the host header
  337. t.reqLineAndHeadersBuf.WriteString("\r\nHost: example.com")
  338. }
  339. // Write headers
  340. if t.headerWriteOrder != nil {
  341. // Re-add headers in specified order (for testing)
  342. for _, k := range t.headerWriteOrder {
  343. if v, ok := t.headers[k]; ok {
  344. t.reqLineAndHeadersBuf.WriteString("\r\n" + k + ": ")
  345. t.reqLineAndHeadersBuf.Write(v)
  346. }
  347. }
  348. } else {
  349. for k, v := range t.headers {
  350. t.reqLineAndHeadersBuf.WriteString("\r\n" + k + ": ")
  351. t.reqLineAndHeadersBuf.Write(v)
  352. }
  353. }
  354. t.reqLineAndHeadersBuf.Write(doublecrlf)
  355. // TODO/perf: could eliminate copy of header by copying it direct into
  356. // the caller's buffer instead of copying the bytes over to t.b first.
  357. header := t.reqLineAndHeadersBuf.Bytes()
  358. // Copy any request body bytes received before resetting the
  359. // buffer.
  360. var reqBody []byte
  361. reqBodyLen := t.b.Len() // number of request body bytes received
  362. if reqBodyLen > 0 {
  363. reqBody = make([]byte, reqBodyLen)
  364. copy(reqBody, t.b.Bytes())
  365. }
  366. t.b.Reset()
  367. t.b.Write(header)
  368. if len(reqBody) > 0 {
  369. t.b.Write(reqBody)
  370. }
  371. // Calculate number of bytes remaining to:
  372. // - read from the underlying net.Conn
  373. // - return to the caller
  374. t.state = httpNormalizerReadBody
  375. totalReqBytes := len(header) + int(*t.contentLength)
  376. t.copyRemain = uint64(totalReqBytes)
  377. bytesOfBodyRead := t.b.Len() - len(header)
  378. if bytesOfBodyRead > totalReqBytes-len(header) {
  379. t.readRemain = 0
  380. } else {
  381. t.readRemain = *t.contentLength - uint64(bytesOfBodyRead)
  382. }
  383. return t.copy(buffer), nil
  384. }
  385. // Request-Line, and headers, have been normalized. Return any remaining
  386. // bytes of these and then read, and return, the bytes of the request body
  387. // from the underlying net.Conn.
  388. var n int
  389. var err error
  390. // Read more bytes from the underlying net.Conn once all the remaining
  391. // bytes in t.b have been copied into the caller's buffer in previous Read
  392. // calls.
  393. if t.b.Len() == 0 {
  394. // perf: read bytes directly into the caller's buffer.
  395. bufferLen := len(buffer)
  396. if uint64(bufferLen) > t.readRemain {
  397. bufferLen = int(t.readRemain)
  398. }
  399. // TODO: could attempt to read more bytes and only copy bufferLen bytes
  400. // into buffer but this adds an extra copy.
  401. n, err = t.Conn.Read(buffer[:bufferLen])
  402. if uint64(n) >= t.readRemain {
  403. t.readRemain = 0
  404. // Do not reset t.b because it may contain bytes of subsequent
  405. // requests.
  406. t.state = httpNormalizerReadReqLineAndHeader
  407. } else {
  408. t.readRemain -= uint64(n)
  409. }
  410. // Do not wrap any I/O err returned by Conn
  411. return n, err
  412. }
  413. // Copy remaining bytes in t.b into the caller's buffer.
  414. return t.copy(buffer), nil
  415. }
  416. func (t *HTTPNormalizer) copy(buffer []byte) int {
  417. // Do not return any bytes from subsequent requests which have been
  418. // buffered internally because they need to be normalized first.
  419. bytesToCopy := t.copyRemain
  420. if uint64(t.b.Len()) < t.copyRemain {
  421. bytesToCopy = uint64(t.b.Len())
  422. }
  423. // Copy bytes to caller's buffer
  424. n := copy(buffer, t.b.Bytes()[:bytesToCopy])
  425. // Remove returned bytes from internal buffer and update number of bytes
  426. // remaining to return to the caller.
  427. t.b.Next(n) // perf: advance read cursor instead of copying bytes to front of buffer
  428. t.copyRemain -= uint64(n)
  429. if t.copyRemain == 0 && t.readRemain == 0 {
  430. // Shift buffer back to 0 copying any remaining bytes to the start of
  431. // the buffer.
  432. // TODO/perf: technically bytes.Buffer takes a similar, and more
  433. // efficient, approach internally so this should not be necessary.
  434. nextBytes := t.b.Bytes()
  435. t.b.Reset()
  436. if len(nextBytes) > 0 {
  437. t.b.Write(nextBytes)
  438. }
  439. // All bytes of the current request have been read and returned to the
  440. // caller. Start normalizing the header of the next request.
  441. // NOTE: if t.b contains CRLF separated lines, of the next request and
  442. // there is remaining space in the buffer supplied by the caller, then
  443. // technically we could start processing the next request instead of
  444. // returning here.
  445. // Do not reset t.b because it may contain bytes of subsequent requests.
  446. t.state = httpNormalizerReadReqLineAndHeader
  447. }
  448. return n
  449. }
  450. func (t *HTTPNormalizer) passthroughConfigured() bool {
  451. return t.passthroughDialer != nil && t.passthroughAddress != ""
  452. }
  453. func (t *HTTPNormalizer) startPassthrough(tunnelError error, logFields map[string]interface{}) {
  454. if t.passthroughLogPassthrough != nil {
  455. clientAddr := t.Conn.RemoteAddr().String()
  456. clientIP, _, _ := net.SplitHostPort(clientAddr)
  457. t.passthroughLogPassthrough(clientIP, errors.TraceMsg(tunnelError, "passthrough"), logFields)
  458. }
  459. go passthrough(t.Conn, t.passthroughAddress, t.passthroughDialer, t.b.Bytes())
  460. atomic.StoreInt32(&t.passthrough, 1)
  461. }
  462. func passthrough(conn net.Conn, address string, dialer func(network, address string) (net.Conn, error), buf []byte) {
  463. // Perform the passthrough relay.
  464. //
  465. // Limitations:
  466. //
  467. // - The local TCP stack may differ from passthrough target in a
  468. // detectable way.
  469. //
  470. // - There may be detectable timing characteristics due to the network hop
  471. // to the passthrough target.
  472. //
  473. // - Application-level socket operations may produce detectable
  474. // differences (e.g., CloseWrite/FIN).
  475. //
  476. // - The dial to the passthrough, or other upstream network operations,
  477. // may fail. These errors are not logged.
  478. //
  479. // - There's no timeout on the passthrough dial and no time limit on the
  480. // passthrough relay so that the invalid client can't detect a timeout
  481. // shorter than the passthrough target; this may cause additional load.
  482. defer conn.Close()
  483. // Remove any pre-existing deadlines to ensure the passthrough
  484. // is not interrupted.
  485. _ = conn.SetDeadline(time.Time{})
  486. passthroughConn, err := dialer("tcp", address)
  487. if err != nil {
  488. return
  489. }
  490. defer passthroughConn.Close()
  491. _, err = passthroughConn.Write(buf)
  492. if err != nil {
  493. return
  494. }
  495. go func() {
  496. _, _ = io.Copy(passthroughConn, conn)
  497. passthroughConn.Close()
  498. }()
  499. _, _ = io.Copy(conn, passthroughConn)
  500. }
  501. func (t *HTTPNormalizer) Write(b []byte) (n int, err error) {
  502. if atomic.LoadInt32(&t.passthrough) == 1 {
  503. return 0, ErrPassthroughActive
  504. }
  505. return t.Conn.Write(b)
  506. }
  507. func (t *HTTPNormalizer) Close() error {
  508. if atomic.LoadInt32(&t.passthrough) == 1 {
  509. return nil
  510. }
  511. return t.Conn.Close()
  512. }
  513. func (t *HTTPNormalizer) SetDeadline(tt time.Time) error {
  514. if atomic.LoadInt32(&t.passthrough) == 1 {
  515. return nil
  516. }
  517. return t.Conn.SetDeadline(tt)
  518. }
  519. func (t *HTTPNormalizer) SetReadDeadline(tt time.Time) error {
  520. if atomic.LoadInt32(&t.passthrough) == 1 {
  521. return nil
  522. }
  523. return t.Conn.SetReadDeadline(tt)
  524. }
  525. func (t *HTTPNormalizer) SetWriteDeadline(tt time.Time) error {
  526. if atomic.LoadInt32(&t.passthrough) == 1 {
  527. return nil
  528. }
  529. return t.Conn.SetWriteDeadline(tt)
  530. }
  531. // GetMetrics implements the common.MetricsSource interface.
  532. func (t *HTTPNormalizer) GetMetrics() common.LogFields {
  533. // Relay any metrics from the underlying conn.
  534. m, ok := t.Conn.(common.MetricsSource)
  535. if ok {
  536. return m.GetMetrics()
  537. }
  538. return nil
  539. }
  540. // Note: all config fields must be set before calling Accept.
  541. type HTTPNormalizerListener struct {
  542. HeaderWriteOrder []string
  543. MaxReqLineAndHeadersSize int
  544. ProhibitedHeaders []string
  545. PassthroughAddress string
  546. PassthroughDialer func(network, address string) (net.Conn, error)
  547. PassthroughLogPassthrough func(clientIP string, tunnelError error, logFields map[string]interface{})
  548. ValidateMeekCookie func(clientIP string, rawCookies []byte) ([]byte, error)
  549. net.Listener
  550. }
  551. func (t *HTTPNormalizerListener) Accept() (net.Conn, error) {
  552. conn, err := t.Listener.Accept()
  553. if err != nil {
  554. // Do not wrap any err returned by Listener
  555. return nil, err
  556. }
  557. normalizer := NewHTTPNormalizer(conn)
  558. normalizer.headerWriteOrder = t.HeaderWriteOrder // for testing
  559. normalizer.maxReqLineAndHeadersSize = t.MaxReqLineAndHeadersSize
  560. normalizer.prohibitedHeaders = t.ProhibitedHeaders
  561. normalizer.passthroughAddress = t.PassthroughAddress
  562. normalizer.passthroughDialer = t.PassthroughDialer
  563. normalizer.passthroughLogPassthrough = t.PassthroughLogPassthrough
  564. if t.ValidateMeekCookie != nil {
  565. clientIP, _, err := net.SplitHostPort(conn.RemoteAddr().String())
  566. if err != nil {
  567. return nil, errors.Trace(err)
  568. }
  569. normalizer.validateMeekCookie = func(cookie []byte) ([]byte, error) {
  570. b, err := t.ValidateMeekCookie(clientIP, cookie)
  571. if err != nil {
  572. return nil, errors.Trace(err)
  573. }
  574. return b, nil
  575. }
  576. }
  577. return normalizer, nil
  578. }
  579. func WrapListenerWithHTTPNormalizer(listener net.Listener) *HTTPNormalizerListener {
  580. return &HTTPNormalizerListener{
  581. Listener: listener,
  582. }
  583. }