https.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2016 fatedier, fatedier@gmail.com
  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 implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package vhost
  15. import (
  16. "fmt"
  17. "io"
  18. "strings"
  19. "time"
  20. frpNet "github.com/fatedier/frp/utils/net"
  21. gnet "github.com/fatedier/golib/net"
  22. "github.com/fatedier/golib/pool"
  23. )
  24. const (
  25. typeClientHello uint8 = 1 // Type client hello
  26. )
  27. // TLS extension numbers
  28. const (
  29. extensionServerName uint16 = 0
  30. extensionStatusRequest uint16 = 5
  31. extensionSupportedCurves uint16 = 10
  32. extensionSupportedPoints uint16 = 11
  33. extensionSignatureAlgorithms uint16 = 13
  34. extensionALPN uint16 = 16
  35. extensionSCT uint16 = 18
  36. extensionSessionTicket uint16 = 35
  37. extensionNextProtoNeg uint16 = 13172 // not IANA assigned
  38. extensionRenegotiationInfo uint16 = 0xff01
  39. )
  40. type HttpsMuxer struct {
  41. *VhostMuxer
  42. }
  43. func NewHttpsMuxer(listener frpNet.Listener, timeout time.Duration) (*HttpsMuxer, error) {
  44. mux, err := NewVhostMuxer(listener, GetHttpsHostname, nil, nil, timeout)
  45. return &HttpsMuxer{mux}, err
  46. }
  47. func readHandshake(rd io.Reader) (host string, err error) {
  48. data := pool.GetBuf(1024)
  49. origin := data
  50. defer pool.PutBuf(origin)
  51. _, err = io.ReadFull(rd, data[:47])
  52. if err != nil {
  53. return
  54. }
  55. length, err := rd.Read(data[47:])
  56. if err != nil {
  57. return
  58. } else {
  59. length += 47
  60. }
  61. data = data[:length]
  62. if uint8(data[5]) != typeClientHello {
  63. err = fmt.Errorf("readHandshake: type[%d] is not clientHello", uint16(data[5]))
  64. return
  65. }
  66. // session
  67. sessionIdLen := int(data[43])
  68. if sessionIdLen > 32 || len(data) < 44+sessionIdLen {
  69. err = fmt.Errorf("readHandshake: sessionIdLen[%d] is long", sessionIdLen)
  70. return
  71. }
  72. data = data[44+sessionIdLen:]
  73. if len(data) < 2 {
  74. err = fmt.Errorf("readHandshake: dataLen[%d] after session is short", len(data))
  75. return
  76. }
  77. // cipher suite numbers
  78. cipherSuiteLen := int(data[0])<<8 | int(data[1])
  79. if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
  80. err = fmt.Errorf("readHandshake: dataLen[%d] after cipher suite is short", len(data))
  81. return
  82. }
  83. data = data[2+cipherSuiteLen:]
  84. if len(data) < 1 {
  85. err = fmt.Errorf("readHandshake: cipherSuiteLen[%d] is long", cipherSuiteLen)
  86. return
  87. }
  88. // compression method
  89. compressionMethodsLen := int(data[0])
  90. if len(data) < 1+compressionMethodsLen {
  91. err = fmt.Errorf("readHandshake: compressionMethodsLen[%d] is long", compressionMethodsLen)
  92. return
  93. }
  94. data = data[1+compressionMethodsLen:]
  95. if len(data) == 0 {
  96. // ClientHello is optionally followed by extension data
  97. err = fmt.Errorf("readHandshake: there is no extension data to get servername")
  98. return
  99. }
  100. if len(data) < 2 {
  101. err = fmt.Errorf("readHandshake: extension dataLen[%d] is too short", len(data))
  102. return
  103. }
  104. extensionsLength := int(data[0])<<8 | int(data[1])
  105. data = data[2:]
  106. if extensionsLength != len(data) {
  107. err = fmt.Errorf("readHandshake: extensionsLen[%d] is not equal to dataLen[%d]", extensionsLength, len(data))
  108. return
  109. }
  110. for len(data) != 0 {
  111. if len(data) < 4 {
  112. err = fmt.Errorf("readHandshake: extensionsDataLen[%d] is too short", len(data))
  113. return
  114. }
  115. extension := uint16(data[0])<<8 | uint16(data[1])
  116. length := int(data[2])<<8 | int(data[3])
  117. data = data[4:]
  118. if len(data) < length {
  119. err = fmt.Errorf("readHandshake: extensionLen[%d] is long", length)
  120. return
  121. }
  122. switch extension {
  123. case extensionRenegotiationInfo:
  124. if length != 1 || data[0] != 0 {
  125. err = fmt.Errorf("readHandshake: extension reNegotiationInfoLen[%d] is short", length)
  126. return
  127. }
  128. case extensionNextProtoNeg:
  129. case extensionStatusRequest:
  130. case extensionServerName:
  131. d := data[:length]
  132. if len(d) < 2 {
  133. err = fmt.Errorf("readHandshake: remiaining dataLen[%d] is short", len(d))
  134. return
  135. }
  136. namesLen := int(d[0])<<8 | int(d[1])
  137. d = d[2:]
  138. if len(d) != namesLen {
  139. err = fmt.Errorf("readHandshake: nameListLen[%d] is not equal to dataLen[%d]", namesLen, len(d))
  140. return
  141. }
  142. for len(d) > 0 {
  143. if len(d) < 3 {
  144. err = fmt.Errorf("readHandshake: extension serverNameLen[%d] is short", len(d))
  145. return
  146. }
  147. nameType := d[0]
  148. nameLen := int(d[1])<<8 | int(d[2])
  149. d = d[3:]
  150. if len(d) < nameLen {
  151. err = fmt.Errorf("readHandshake: nameLen[%d] is not equal to dataLen[%d]", nameLen, len(d))
  152. return
  153. }
  154. if nameType == 0 {
  155. serverName := string(d[:nameLen])
  156. host = strings.TrimSpace(serverName)
  157. return host, nil
  158. }
  159. d = d[nameLen:]
  160. }
  161. }
  162. data = data[length:]
  163. }
  164. err = fmt.Errorf("Unknow error")
  165. return
  166. }
  167. func GetHttpsHostname(c frpNet.Conn) (_ frpNet.Conn, _ map[string]string, err error) {
  168. reqInfoMap := make(map[string]string, 0)
  169. sc, rd := gnet.NewSharedConn(c)
  170. host, err := readHandshake(rd)
  171. if err != nil {
  172. return nil, reqInfoMap, err
  173. }
  174. reqInfoMap["Host"] = host
  175. reqInfoMap["Scheme"] = "https"
  176. return frpNet.WrapConn(sc), reqInfoMap, nil
  177. }