1
0

https.go 5.2 KB

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