httpNormalizer.go 21 KB

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