httpNormalizer.go 21 KB

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