Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
企猫商务
frp
提交
86b2e686
F
frp
项目概览
企猫商务
/
frp
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
frp
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
86b2e686
编写于
8月 03, 2021
作者:
F
fatedier
提交者:
GitHub
8月 03, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
vhost: use new readClientHello function (#2504)
上级
09f39de7
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
80 addition
and
155 deletion
+80
-155
pkg/util/vhost/https.go
pkg/util/vhost/https.go
+38
-151
pkg/util/vhost/https_test.go
pkg/util/vhost/https_test.go
+38
-0
test/e2e/mock/server/httpserver/server.go
test/e2e/mock/server/httpserver/server.go
+4
-4
未找到文件。
pkg/util/vhost/https.go
浏览文件 @
86b2e686
...
...
@@ -15,32 +15,12 @@
package
vhost
import
(
"
fmt
"
"
crypto/tls
"
"io"
"net"
"strings"
"time"
gnet
"github.com/fatedier/golib/net"
"github.com/fatedier/golib/pool"
)
const
(
typeClientHello
uint8
=
1
// Type client hello
)
// TLS extension numbers
const
(
extensionServerName
uint16
=
0
extensionStatusRequest
uint16
=
5
extensionSupportedCurves
uint16
=
10
extensionSupportedPoints
uint16
=
11
extensionSignatureAlgorithms
uint16
=
13
extensionALPN
uint16
=
16
extensionSCT
uint16
=
18
extensionSessionTicket
uint16
=
35
extensionNextProtoNeg
uint16
=
13172
// not IANA assigned
extensionRenegotiationInfo
uint16
=
0xff01
)
type
HTTPSMuxer
struct
{
...
...
@@ -52,142 +32,49 @@ func NewHTTPSMuxer(listener net.Listener, timeout time.Duration) (*HTTPSMuxer, e
return
&
HTTPSMuxer
{
mux
},
err
}
func
readHandshake
(
rd
io
.
Reader
)
(
host
string
,
err
error
)
{
data
:=
pool
.
GetBuf
(
1024
)
origin
:=
data
defer
pool
.
PutBuf
(
origin
)
_
,
err
=
io
.
ReadFull
(
rd
,
data
[
:
47
])
if
err
!=
nil
{
return
}
length
,
err
:=
rd
.
Read
(
data
[
47
:
])
if
err
!=
nil
{
return
}
length
+=
47
data
=
data
[
:
length
]
if
uint8
(
data
[
5
])
!=
typeClientHello
{
err
=
fmt
.
Errorf
(
"readHandshake: type[%d] is not clientHello"
,
uint16
(
data
[
5
]))
return
}
// session
sessionIDLen
:=
int
(
data
[
43
])
if
sessionIDLen
>
32
||
len
(
data
)
<
44
+
sessionIDLen
{
err
=
fmt
.
Errorf
(
"readHandshake: sessionIdLen[%d] is long"
,
sessionIDLen
)
return
}
data
=
data
[
44
+
sessionIDLen
:
]
if
len
(
data
)
<
2
{
err
=
fmt
.
Errorf
(
"readHandshake: dataLen[%d] after session is short"
,
len
(
data
))
return
}
// cipher suite numbers
cipherSuiteLen
:=
int
(
data
[
0
])
<<
8
|
int
(
data
[
1
])
if
cipherSuiteLen
%
2
==
1
||
len
(
data
)
<
2
+
cipherSuiteLen
{
err
=
fmt
.
Errorf
(
"readHandshake: dataLen[%d] after cipher suite is short"
,
len
(
data
))
return
}
data
=
data
[
2
+
cipherSuiteLen
:
]
if
len
(
data
)
<
1
{
err
=
fmt
.
Errorf
(
"readHandshake: cipherSuiteLen[%d] is long"
,
cipherSuiteLen
)
return
}
// compression method
compressionMethodsLen
:=
int
(
data
[
0
])
if
len
(
data
)
<
1
+
compressionMethodsLen
{
err
=
fmt
.
Errorf
(
"readHandshake: compressionMethodsLen[%d] is long"
,
compressionMethodsLen
)
return
}
data
=
data
[
1
+
compressionMethodsLen
:
]
if
len
(
data
)
==
0
{
// ClientHello is optionally followed by extension data
err
=
fmt
.
Errorf
(
"readHandshake: there is no extension data to get servername"
)
return
}
if
len
(
data
)
<
2
{
err
=
fmt
.
Errorf
(
"readHandshake: extension dataLen[%d] is too short"
,
len
(
data
))
return
}
extensionsLength
:=
int
(
data
[
0
])
<<
8
|
int
(
data
[
1
])
data
=
data
[
2
:
]
if
extensionsLength
!=
len
(
data
)
{
err
=
fmt
.
Errorf
(
"readHandshake: extensionsLen[%d] is not equal to dataLen[%d]"
,
extensionsLength
,
len
(
data
))
return
}
for
len
(
data
)
!=
0
{
if
len
(
data
)
<
4
{
err
=
fmt
.
Errorf
(
"readHandshake: extensionsDataLen[%d] is too short"
,
len
(
data
))
return
}
extension
:=
uint16
(
data
[
0
])
<<
8
|
uint16
(
data
[
1
])
length
:=
int
(
data
[
2
])
<<
8
|
int
(
data
[
3
])
data
=
data
[
4
:
]
if
len
(
data
)
<
length
{
err
=
fmt
.
Errorf
(
"readHandshake: extensionLen[%d] is long"
,
length
)
return
}
switch
extension
{
case
extensionRenegotiationInfo
:
if
length
!=
1
||
data
[
0
]
!=
0
{
err
=
fmt
.
Errorf
(
"readHandshake: extension reNegotiationInfoLen[%d] is short"
,
length
)
return
}
case
extensionNextProtoNeg
:
case
extensionStatusRequest
:
case
extensionServerName
:
d
:=
data
[
:
length
]
if
len
(
d
)
<
2
{
err
=
fmt
.
Errorf
(
"readHandshake: remiaining dataLen[%d] is short"
,
len
(
d
))
return
}
namesLen
:=
int
(
d
[
0
])
<<
8
|
int
(
d
[
1
])
d
=
d
[
2
:
]
if
len
(
d
)
!=
namesLen
{
err
=
fmt
.
Errorf
(
"readHandshake: nameListLen[%d] is not equal to dataLen[%d]"
,
namesLen
,
len
(
d
))
return
}
for
len
(
d
)
>
0
{
if
len
(
d
)
<
3
{
err
=
fmt
.
Errorf
(
"readHandshake: extension serverNameLen[%d] is short"
,
len
(
d
))
return
}
nameType
:=
d
[
0
]
nameLen
:=
int
(
d
[
1
])
<<
8
|
int
(
d
[
2
])
d
=
d
[
3
:
]
if
len
(
d
)
<
nameLen
{
err
=
fmt
.
Errorf
(
"readHandshake: nameLen[%d] is not equal to dataLen[%d]"
,
nameLen
,
len
(
d
))
return
}
if
nameType
==
0
{
serverName
:=
string
(
d
[
:
nameLen
])
host
=
strings
.
TrimSpace
(
serverName
)
return
host
,
nil
}
d
=
d
[
nameLen
:
]
}
}
data
=
data
[
length
:
]
}
err
=
fmt
.
Errorf
(
"Unknown error"
)
return
}
func
GetHTTPSHostname
(
c
net
.
Conn
)
(
_
net
.
Conn
,
_
map
[
string
]
string
,
err
error
)
{
reqInfoMap
:=
make
(
map
[
string
]
string
,
0
)
sc
,
rd
:=
gnet
.
NewSharedConn
(
c
)
host
,
err
:=
readHandshake
(
rd
)
clientHello
,
err
:=
readClientHello
(
rd
)
if
err
!=
nil
{
return
nil
,
reqInfoMap
,
err
}
reqInfoMap
[
"Host"
]
=
host
reqInfoMap
[
"Host"
]
=
clientHello
.
ServerName
reqInfoMap
[
"Scheme"
]
=
"https"
return
sc
,
reqInfoMap
,
nil
}
func
readClientHello
(
reader
io
.
Reader
)
(
*
tls
.
ClientHelloInfo
,
error
)
{
var
hello
*
tls
.
ClientHelloInfo
// Note that Handshake always fails because the readOnlyConn is not a real connection.
// As long as the Client Hello is successfully read, the failure should only happen after GetConfigForClient is called,
// so we only care about the error if hello was never set.
err
:=
tls
.
Server
(
readOnlyConn
{
reader
:
reader
},
&
tls
.
Config
{
GetConfigForClient
:
func
(
argHello
*
tls
.
ClientHelloInfo
)
(
*
tls
.
Config
,
error
)
{
hello
=
&
tls
.
ClientHelloInfo
{}
*
hello
=
*
argHello
return
nil
,
nil
},
})
.
Handshake
()
if
hello
==
nil
{
return
nil
,
err
}
return
hello
,
nil
}
type
readOnlyConn
struct
{
reader
io
.
Reader
}
func
(
conn
readOnlyConn
)
Read
(
p
[]
byte
)
(
int
,
error
)
{
return
conn
.
reader
.
Read
(
p
)
}
func
(
conn
readOnlyConn
)
Write
(
p
[]
byte
)
(
int
,
error
)
{
return
0
,
io
.
ErrClosedPipe
}
func
(
conn
readOnlyConn
)
Close
()
error
{
return
nil
}
func
(
conn
readOnlyConn
)
LocalAddr
()
net
.
Addr
{
return
nil
}
func
(
conn
readOnlyConn
)
RemoteAddr
()
net
.
Addr
{
return
nil
}
func
(
conn
readOnlyConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
nil
}
func
(
conn
readOnlyConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
nil
}
func
(
conn
readOnlyConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
nil
}
pkg/util/vhost/https_test.go
0 → 100644
浏览文件 @
86b2e686
package
vhost
import
(
"crypto/tls"
"net"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func
TestGetHTTPSHostname
(
t
*
testing
.
T
)
{
require
:=
require
.
New
(
t
)
l
,
err
:=
net
.
Listen
(
"tcp"
,
":"
)
require
.
NoError
(
err
)
defer
l
.
Close
()
var
conn
net
.
Conn
go
func
()
{
conn
,
_
=
l
.
Accept
()
require
.
NotNil
(
conn
)
}()
go
func
()
{
time
.
Sleep
(
100
*
time
.
Millisecond
)
tls
.
Dial
(
"tcp"
,
l
.
Addr
()
.
String
(),
&
tls
.
Config
{
InsecureSkipVerify
:
true
,
ServerName
:
"example.com"
,
})
}()
time
.
Sleep
(
200
*
time
.
Millisecond
)
_
,
infos
,
err
:=
GetHTTPSHostname
(
conn
)
require
.
NoError
(
err
)
require
.
Equal
(
"example.com"
,
infos
[
"Host"
])
require
.
Equal
(
"https"
,
infos
[
"Scheme"
])
}
test/e2e/mock/server/httpserver/server.go
浏览文件 @
86b2e686
...
...
@@ -11,7 +11,7 @@ import (
type
Server
struct
{
bindAddr
string
bindPort
int
han
ld
er
http
.
Handler
han
dl
er
http
.
Handler
l
net
.
Listener
tlsConfig
*
tls
.
Config
...
...
@@ -54,14 +54,14 @@ func WithTlsConfig(tlsConfig *tls.Config) Option {
func
WithHandler
(
h
http
.
Handler
)
Option
{
return
func
(
s
*
Server
)
*
Server
{
s
.
han
ld
er
=
h
s
.
han
dl
er
=
h
return
s
}
}
func
WithResponse
(
resp
[]
byte
)
Option
{
return
func
(
s
*
Server
)
*
Server
{
s
.
han
ld
er
=
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
s
.
han
dl
er
=
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Write
(
resp
)
})
return
s
...
...
@@ -76,7 +76,7 @@ func (s *Server) Run() error {
addr
:=
net
.
JoinHostPort
(
s
.
bindAddr
,
strconv
.
Itoa
(
s
.
bindPort
))
hs
:=
&
http
.
Server
{
Addr
:
addr
,
Handler
:
s
.
han
ld
er
,
Handler
:
s
.
han
dl
er
,
TLSConfig
:
s
.
tlsConfig
,
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录