matchers.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2016 The CMux Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. // implied. See the License for the specific language governing
  13. // permissions and limitations under the License.
  14. package cmux
  15. import (
  16. "bufio"
  17. "crypto/tls"
  18. "io"
  19. "io/ioutil"
  20. "net/http"
  21. "strings"
  22. "golang.org/x/net/http2"
  23. "golang.org/x/net/http2/hpack"
  24. )
  25. // Any is a Matcher that matches any connection.
  26. func Any() Matcher {
  27. return func(r io.Reader) bool { return true }
  28. }
  29. // PrefixMatcher returns a matcher that matches a connection if it
  30. // starts with any of the strings in strs.
  31. func PrefixMatcher(strs ...string) Matcher {
  32. pt := newPatriciaTreeString(strs...)
  33. return pt.matchPrefix
  34. }
  35. func prefixByteMatcher(list ...[]byte) Matcher {
  36. pt := newPatriciaTree(list...)
  37. return pt.matchPrefix
  38. }
  39. var defaultHTTPMethods = []string{
  40. "OPTIONS",
  41. "GET",
  42. "HEAD",
  43. "POST",
  44. "PUT",
  45. "DELETE",
  46. "TRACE",
  47. "CONNECT",
  48. }
  49. // HTTP1Fast only matches the methods in the HTTP request.
  50. //
  51. // This matcher is very optimistic: if it returns true, it does not mean that
  52. // the request is a valid HTTP response. If you want a correct but slower HTTP1
  53. // matcher, use HTTP1 instead.
  54. func HTTP1Fast(extMethods ...string) Matcher {
  55. return PrefixMatcher(append(defaultHTTPMethods, extMethods...)...)
  56. }
  57. // TLS matches HTTPS requests.
  58. //
  59. // By default, any TLS handshake packet is matched. An optional whitelist
  60. // of versions can be passed in to restrict the matcher, for example:
  61. // TLS(tls.VersionTLS11, tls.VersionTLS12)
  62. func TLS(versions ...int) Matcher {
  63. if len(versions) == 0 {
  64. versions = []int{
  65. tls.VersionSSL30,
  66. tls.VersionTLS10,
  67. tls.VersionTLS11,
  68. tls.VersionTLS12,
  69. }
  70. }
  71. prefixes := [][]byte{}
  72. for _, v := range versions {
  73. prefixes = append(prefixes, []byte{22, byte(v >> 8 & 0xff), byte(v & 0xff)})
  74. }
  75. return prefixByteMatcher(prefixes...)
  76. }
  77. const maxHTTPRead = 4096
  78. // HTTP1 parses the first line or upto 4096 bytes of the request to see if
  79. // the conection contains an HTTP request.
  80. func HTTP1() Matcher {
  81. return func(r io.Reader) bool {
  82. br := bufio.NewReader(&io.LimitedReader{R: r, N: maxHTTPRead})
  83. l, part, err := br.ReadLine()
  84. if err != nil || part {
  85. return false
  86. }
  87. _, _, proto, ok := parseRequestLine(string(l))
  88. if !ok {
  89. return false
  90. }
  91. v, _, ok := http.ParseHTTPVersion(proto)
  92. return ok && v == 1
  93. }
  94. }
  95. // grabbed from net/http.
  96. func parseRequestLine(line string) (method, uri, proto string, ok bool) {
  97. s1 := strings.Index(line, " ")
  98. s2 := strings.Index(line[s1+1:], " ")
  99. if s1 < 0 || s2 < 0 {
  100. return
  101. }
  102. s2 += s1 + 1
  103. return line[:s1], line[s1+1 : s2], line[s2+1:], true
  104. }
  105. // HTTP2 parses the frame header of the first frame to detect whether the
  106. // connection is an HTTP2 connection.
  107. func HTTP2() Matcher {
  108. return hasHTTP2Preface
  109. }
  110. // HTTP1HeaderField returns a matcher matching the header fields of the first
  111. // request of an HTTP 1 connection.
  112. func HTTP1HeaderField(name, value string) Matcher {
  113. return func(r io.Reader) bool {
  114. return matchHTTP1Field(r, name, func(gotValue string) bool {
  115. return gotValue == value
  116. })
  117. }
  118. }
  119. // HTTP1HeaderFieldPrefix returns a matcher matching the header fields of the
  120. // first request of an HTTP 1 connection. If the header with key name has a
  121. // value prefixed with valuePrefix, this will match.
  122. func HTTP1HeaderFieldPrefix(name, valuePrefix string) Matcher {
  123. return func(r io.Reader) bool {
  124. return matchHTTP1Field(r, name, func(gotValue string) bool {
  125. return strings.HasPrefix(gotValue, valuePrefix)
  126. })
  127. }
  128. }
  129. // HTTP2HeaderField returns a matcher matching the header fields of the first
  130. // headers frame.
  131. func HTTP2HeaderField(name, value string) Matcher {
  132. return func(r io.Reader) bool {
  133. return matchHTTP2Field(ioutil.Discard, r, name, func(gotValue string) bool {
  134. return gotValue == value
  135. })
  136. }
  137. }
  138. // HTTP2HeaderFieldPrefix returns a matcher matching the header fields of the
  139. // first headers frame. If the header with key name has a value prefixed with
  140. // valuePrefix, this will match.
  141. func HTTP2HeaderFieldPrefix(name, valuePrefix string) Matcher {
  142. return func(r io.Reader) bool {
  143. return matchHTTP2Field(ioutil.Discard, r, name, func(gotValue string) bool {
  144. return strings.HasPrefix(gotValue, valuePrefix)
  145. })
  146. }
  147. }
  148. // HTTP2MatchHeaderFieldSendSettings matches the header field and writes the
  149. // settings to the server. Prefer HTTP2HeaderField over this one, if the client
  150. // does not block on receiving a SETTING frame.
  151. func HTTP2MatchHeaderFieldSendSettings(name, value string) MatchWriter {
  152. return func(w io.Writer, r io.Reader) bool {
  153. return matchHTTP2Field(w, r, name, func(gotValue string) bool {
  154. return gotValue == value
  155. })
  156. }
  157. }
  158. // HTTP2MatchHeaderFieldPrefixSendSettings matches the header field prefix
  159. // and writes the settings to the server. Prefer HTTP2HeaderFieldPrefix over
  160. // this one, if the client does not block on receiving a SETTING frame.
  161. func HTTP2MatchHeaderFieldPrefixSendSettings(name, valuePrefix string) MatchWriter {
  162. return func(w io.Writer, r io.Reader) bool {
  163. return matchHTTP2Field(w, r, name, func(gotValue string) bool {
  164. return strings.HasPrefix(gotValue, valuePrefix)
  165. })
  166. }
  167. }
  168. func hasHTTP2Preface(r io.Reader) bool {
  169. var b [len(http2.ClientPreface)]byte
  170. last := 0
  171. for {
  172. n, err := r.Read(b[last:])
  173. if err != nil {
  174. return false
  175. }
  176. last += n
  177. eq := string(b[:last]) == http2.ClientPreface[:last]
  178. if last == len(http2.ClientPreface) {
  179. return eq
  180. }
  181. if !eq {
  182. return false
  183. }
  184. }
  185. }
  186. func matchHTTP1Field(r io.Reader, name string, matches func(string) bool) (matched bool) {
  187. req, err := http.ReadRequest(bufio.NewReader(r))
  188. if err != nil {
  189. return false
  190. }
  191. return matches(req.Header.Get(name))
  192. }
  193. func matchHTTP2Field(w io.Writer, r io.Reader, name string, matches func(string) bool) (matched bool) {
  194. if !hasHTTP2Preface(r) {
  195. return false
  196. }
  197. done := false
  198. framer := http2.NewFramer(w, r)
  199. hdec := hpack.NewDecoder(uint32(4<<10), func(hf hpack.HeaderField) {
  200. if hf.Name == name {
  201. done = true
  202. if matches(hf.Value) {
  203. matched = true
  204. }
  205. }
  206. })
  207. for {
  208. f, err := framer.ReadFrame()
  209. if err != nil {
  210. return false
  211. }
  212. switch f := f.(type) {
  213. case *http2.SettingsFrame:
  214. // Sender acknoweldged the SETTINGS frame. No need to write
  215. // SETTINGS again.
  216. if f.IsAck() {
  217. break
  218. }
  219. if err := framer.WriteSettings(); err != nil {
  220. return false
  221. }
  222. case *http2.ContinuationFrame:
  223. if _, err := hdec.Write(f.HeaderBlockFragment()); err != nil {
  224. return false
  225. }
  226. done = done || f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
  227. case *http2.HeadersFrame:
  228. if _, err := hdec.Write(f.HeaderBlockFragment()); err != nil {
  229. return false
  230. }
  231. done = done || f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
  232. }
  233. if done {
  234. return matched
  235. }
  236. }
  237. }