Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
G
gost
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
gost
Commits
afac5fe5
Commit
afac5fe5
authored
Aug 02, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add HTTP2 tunnel support
parent
bd5bd7a2
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
353 additions
and
20 deletions
+353
-20
gost/examples/bench/cli.go
gost/examples/bench/cli.go
+12
-3
gost/examples/bench/srv.go
gost/examples/bench/srv.go
+20
-1
gost/examples/http2/http2.go
gost/examples/http2/http2.go
+14
-13
gost/http.go
gost/http.go
+1
-1
gost/http2.go
gost/http2.go
+242
-2
gost/tls.go
gost/tls.go
+64
-0
No files found.
gost/examples/bench/cli.go
View file @
afac5fe5
...
@@ -139,12 +139,21 @@ func main() {
...
@@ -139,12 +139,21 @@ func main() {
},
},
*/
*/
// http+quic
/*
// http+quic
gost.Node{
Addr: "localhost:6121",
Client: &gost.Client{
Connector: gost.HTTPConnector(url.UserPassword("admin", "123456")),
Transporter: gost.QUICTransporter(nil),
},
},
*/
gost
.
Node
{
gost
.
Node
{
Addr
:
"localhost:
6121
"
,
Addr
:
"localhost:
8443
"
,
Client
:
&
gost
.
Client
{
Client
:
&
gost
.
Client
{
Connector
:
gost
.
HTTPConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Connector
:
gost
.
HTTPConnector
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
Transporter
:
gost
.
QUICTransporter
(
nil
),
Transporter
:
gost
.
H2Transporter
(
),
},
},
},
},
)
)
...
...
gost/examples/bench/srv.go
View file @
afac5fe5
...
@@ -8,6 +8,7 @@ import (
...
@@ -8,6 +8,7 @@ import (
"time"
"time"
"github.com/ginuerzh/gost/gost"
"github.com/ginuerzh/gost/gost"
"golang.org/x/net/http2"
)
)
var
(
var
(
...
@@ -19,6 +20,7 @@ func init() {
...
@@ -19,6 +20,7 @@ func init() {
flag
.
BoolVar
(
&
quiet
,
"q"
,
false
,
"quiet mode"
)
flag
.
BoolVar
(
&
quiet
,
"q"
,
false
,
"quiet mode"
)
flag
.
BoolVar
(
&
gost
.
Debug
,
"d"
,
false
,
"debug mode"
)
flag
.
BoolVar
(
&
gost
.
Debug
,
"d"
,
false
,
"debug mode"
)
flag
.
BoolVar
(
&
http2
.
VerboseLogs
,
"v"
,
false
,
"HTTP2 verbose logs"
)
flag
.
Parse
()
flag
.
Parse
()
if
quiet
{
if
quiet
{
...
@@ -40,6 +42,7 @@ func main() {
...
@@ -40,6 +42,7 @@ func main() {
// go tcpRedirectServer()
// go tcpRedirectServer()
go
sshTunnelServer
()
go
sshTunnelServer
()
go
http2Server
()
go
http2Server
()
go
http2TunnelServer
()
go
quicServer
()
go
quicServer
()
go
shadowUDPServer
()
go
shadowUDPServer
()
select
{}
select
{}
...
@@ -230,6 +233,19 @@ func http2Server() {
...
@@ -230,6 +233,19 @@ func http2Server() {
log
.
Fatal
(
s
.
Serve
(
ln
,
h
))
log
.
Fatal
(
s
.
Serve
(
ln
,
h
))
}
}
func
http2TunnelServer
()
{
s
:=
&
gost
.
Server
{}
ln
,
err
:=
gost
.
H2Listener
(
":8443"
,
tlsConfig
())
// HTTP2 h2 mode
// ln, err := gost.H2Listener(":8443", nil) // HTTP2 h2c mode
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
h
:=
gost
.
HTTPHandler
(
gost
.
UsersHandlerOption
(
url
.
UserPassword
(
"admin"
,
"123456"
)),
)
log
.
Fatal
(
s
.
Serve
(
ln
,
h
))
}
func
quicServer
()
{
func
quicServer
()
{
s
:=
&
gost
.
Server
{}
s
:=
&
gost
.
Server
{}
ln
,
err
:=
gost
.
QUICListener
(
"localhost:6121"
,
&
gost
.
QUICConfig
{
TLSConfig
:
tlsConfig
()})
ln
,
err
:=
gost
.
QUICListener
(
"localhost:6121"
,
&
gost
.
QUICConfig
{
TLSConfig
:
tlsConfig
()})
...
@@ -320,5 +336,8 @@ func tlsConfig() *tls.Config {
...
@@ -320,5 +336,8 @@ func tlsConfig() *tls.Config {
if
err
!=
nil
{
if
err
!=
nil
{
panic
(
err
)
panic
(
err
)
}
}
return
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}}
return
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
},
PreferServerCipherSuites
:
true
,
}
}
}
gost/examples/http2/
srv
.go
→
gost/examples/http2/
http2
.go
View file @
afac5fe5
...
@@ -45,8 +45,17 @@ func main() {
...
@@ -45,8 +45,17 @@ func main() {
func
http2Server
()
{
func
http2Server
()
{
s
:=
&
gost
.
Server
{}
s
:=
&
gost
.
Server
{}
var
err
error
ln
,
err
:=
gost
.
TCPListener
(
laddr
)
var
ln
gost
.
Listener
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
var
users
[]
*
url
.
Userinfo
if
user
!=
""
||
passwd
!=
""
{
users
=
append
(
users
,
url
.
UserPassword
(
user
,
passwd
))
}
var
tlsConfig
*
tls
.
Config
if
tlsEnabled
{
if
tlsEnabled
{
cert
,
er
:=
tls
.
LoadX509KeyPair
(
certFile
,
keyFile
)
cert
,
er
:=
tls
.
LoadX509KeyPair
(
certFile
,
keyFile
)
if
er
!=
nil
{
if
er
!=
nil
{
...
@@ -56,20 +65,12 @@ func http2Server() {
...
@@ -56,20 +65,12 @@ func http2Server() {
panic
(
er
)
panic
(
er
)
}
}
}
}
ln
,
err
=
gost
.
TLSListener
(
laddr
,
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}})
// HTTP2 h2 mode
tlsConfig
=
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}}
}
else
{
ln
,
err
=
gost
.
TCPListener
(
laddr
)
}
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
var
users
[]
*
url
.
Userinfo
if
user
!=
""
||
passwd
!=
""
{
users
=
append
(
users
,
url
.
UserPassword
(
user
,
passwd
))
}
}
h
:=
gost
.
HTTP2Handler
(
h
:=
gost
.
HTTP2Handler
(
gost
.
UsersHandlerOption
(
users
...
),
gost
.
UsersHandlerOption
(
users
...
),
gost
.
AddrHandlerOption
(
laddr
),
gost
.
TLSConfigHandlerOption
(
tlsConfig
),
)
)
log
.
Fatal
(
s
.
Serve
(
ln
,
h
))
log
.
Fatal
(
s
.
Serve
(
ln
,
h
))
}
}
...
...
gost/http.go
View file @
afac5fe5
...
@@ -89,7 +89,7 @@ func (h *httpHandler) Handle(conn net.Conn) {
...
@@ -89,7 +89,7 @@ func (h *httpHandler) Handle(conn net.Conn) {
req
,
err
:=
http
.
ReadRequest
(
bufio
.
NewReader
(
conn
))
req
,
err
:=
http
.
ReadRequest
(
bufio
.
NewReader
(
conn
))
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Log
(
"[http]"
,
err
)
log
.
Log
f
(
"[http] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
()
,
err
)
return
return
}
}
...
...
gost/http2.go
View file @
afac5fe5
...
@@ -148,7 +148,99 @@ func (tr *http2Transporter) Multiplex() bool {
...
@@ -148,7 +148,99 @@ func (tr *http2Transporter) Multiplex() bool {
return
true
return
true
}
}
type
h2Transporter
struct
{
clients
map
[
string
]
*
http
.
Client
clientMutex
sync
.
Mutex
tlsConfig
*
tls
.
Config
}
func
H2Transporter
()
Transporter
{
return
&
h2Transporter
{
clients
:
make
(
map
[
string
]
*
http
.
Client
),
tlsConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
true
},
}
}
func
(
tr
*
h2Transporter
)
Dial
(
addr
string
,
options
...
DialOption
)
(
net
.
Conn
,
error
)
{
opts
:=
&
DialOptions
{}
for
_
,
option
:=
range
options
{
option
(
opts
)
}
tr
.
clientMutex
.
Lock
()
client
,
ok
:=
tr
.
clients
[
addr
]
if
!
ok
{
transport
:=
http2
.
Transport
{
TLSClientConfig
:
tr
.
tlsConfig
,
DialTLS
:
func
(
network
,
addr
string
,
cfg
*
tls
.
Config
)
(
net
.
Conn
,
error
)
{
conn
,
err
:=
opts
.
Chain
.
Dial
(
addr
)
if
err
!=
nil
{
return
nil
,
err
}
if
cfg
==
nil
{
return
conn
,
nil
}
return
wrapTLSClient
(
conn
,
cfg
)
},
}
client
=
&
http
.
Client
{
Transport
:
&
transport
}
tr
.
clients
[
addr
]
=
client
}
tr
.
clientMutex
.
Unlock
()
pr
,
pw
:=
io
.
Pipe
()
req
:=
&
http
.
Request
{
Method
:
http
.
MethodConnect
,
URL
:
&
url
.
URL
{
Scheme
:
"https"
,
Host
:
addr
},
Header
:
make
(
http
.
Header
),
Proto
:
"HTTP/2.0"
,
ProtoMajor
:
2
,
ProtoMinor
:
0
,
Body
:
pr
,
Host
:
addr
,
ContentLength
:
-
1
,
}
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
req
,
false
)
log
.
Log
(
"[http2]"
,
string
(
dump
))
}
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
return
nil
,
err
}
if
Debug
{
dump
,
_
:=
httputil
.
DumpResponse
(
resp
,
false
)
log
.
Log
(
"[http2]"
,
string
(
dump
))
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
resp
.
Body
.
Close
()
return
nil
,
errors
.
New
(
resp
.
Status
)
}
conn
:=
&
http2Conn
{
r
:
resp
.
Body
,
w
:
pw
,
closed
:
make
(
chan
struct
{}),
}
conn
.
remoteAddr
,
_
=
net
.
ResolveTCPAddr
(
"tcp"
,
addr
)
conn
.
localAddr
=
&
net
.
TCPAddr
{
IP
:
net
.
IPv4zero
,
Port
:
0
}
return
conn
,
nil
}
func
(
tr
*
h2Transporter
)
Handshake
(
conn
net
.
Conn
,
options
...
HandshakeOption
)
(
net
.
Conn
,
error
)
{
opts
:=
&
HandshakeOptions
{}
for
_
,
option
:=
range
options
{
option
(
opts
)
}
return
conn
,
nil
}
func
(
tr
*
h2Transporter
)
Multiplex
()
bool
{
return
true
}
type
http2Handler
struct
{
type
http2Handler
struct
{
base
*
http
.
Server
server
*
http2
.
Server
server
*
http2
.
Server
options
*
HandlerOptions
options
*
HandlerOptions
}
}
...
@@ -156,18 +248,31 @@ type http2Handler struct {
...
@@ -156,18 +248,31 @@ type http2Handler struct {
// HTTP2Handler creates a server Handler for HTTP2 proxy server.
// HTTP2Handler creates a server Handler for HTTP2 proxy server.
func
HTTP2Handler
(
opts
...
HandlerOption
)
Handler
{
func
HTTP2Handler
(
opts
...
HandlerOption
)
Handler
{
h
:=
&
http2Handler
{
h
:=
&
http2Handler
{
server
:
new
(
http2
.
Server
),
options
:
new
(
HandlerOptions
),
options
:
new
(
HandlerOptions
),
}
}
for
_
,
opt
:=
range
opts
{
for
_
,
opt
:=
range
opts
{
opt
(
h
.
options
)
opt
(
h
.
options
)
}
}
h
.
base
=
&
http
.
Server
{
Addr
:
h
.
options
.
Addr
,
TLSConfig
:
h
.
options
.
TLSConfig
,
Handler
:
http
.
HandlerFunc
(
h
.
handleFunc
),
}
h
.
server
=
new
(
http2
.
Server
)
if
err
:=
http2
.
ConfigureServer
(
h
.
base
,
h
.
server
);
err
!=
nil
{
log
.
Log
(
"[http2]"
,
err
)
}
return
h
return
h
}
}
func
(
h
*
http2Handler
)
Handle
(
conn
net
.
Conn
)
{
func
(
h
*
http2Handler
)
Handle
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
defer
conn
.
Close
()
if
h
.
options
.
TLSConfig
!=
nil
{
conn
=
tls
.
Server
(
conn
,
h
.
options
.
TLSConfig
)
}
if
tc
,
ok
:=
conn
.
(
*
tls
.
Conn
);
ok
{
if
tc
,
ok
:=
conn
.
(
*
tls
.
Conn
);
ok
{
// NOTE: HTTP2 server will check the TLS version,
// NOTE: HTTP2 server will check the TLS version,
// so we must ensure that the TLS connection is handshake completed.
// so we must ensure that the TLS connection is handshake completed.
...
@@ -178,7 +283,8 @@ func (h *http2Handler) Handle(conn net.Conn) {
...
@@ -178,7 +283,8 @@ func (h *http2Handler) Handle(conn net.Conn) {
}
}
opt
:=
http2
.
ServeConnOpts
{
opt
:=
http2
.
ServeConnOpts
{
Handler
:
http
.
HandlerFunc
(
h
.
handleFunc
),
BaseConfig
:
h
.
base
,
Handler
:
http
.
HandlerFunc
(
h
.
handleFunc
),
}
}
h
.
server
.
ServeConn
(
conn
,
&
opt
)
h
.
server
.
ServeConn
(
conn
,
&
opt
)
}
}
...
@@ -292,6 +398,132 @@ func (h *http2Handler) handleFunc(w http.ResponseWriter, r *http.Request) {
...
@@ -292,6 +398,132 @@ func (h *http2Handler) handleFunc(w http.ResponseWriter, r *http.Request) {
log
.
Logf
(
"[http2] %s >-< %s"
,
r
.
RemoteAddr
,
target
)
log
.
Logf
(
"[http2] %s >-< %s"
,
r
.
RemoteAddr
,
target
)
}
}
type
h2Listener
struct
{
net
.
Listener
server
*
http2
.
Server
tlsConfig
*
tls
.
Config
connChan
chan
net
.
Conn
errChan
chan
error
}
func
H2Listener
(
addr
string
,
config
*
tls
.
Config
)
(
Listener
,
error
)
{
ln
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
nil
,
err
}
l
:=
&
h2Listener
{
Listener
:
ln
,
server
:
&
http2
.
Server
{
MaxConcurrentStreams
:
1000
,
PermitProhibitedCipherSuites
:
true
,
},
tlsConfig
:
config
,
connChan
:
make
(
chan
net
.
Conn
,
1024
),
errChan
:
make
(
chan
error
,
1
),
}
go
l
.
listenLoop
()
return
l
,
nil
}
func
H2CListener
(
addr
string
)
(
Listener
,
error
)
{
return
H2Listener
(
addr
,
nil
)
}
func
(
l
*
h2Listener
)
listenLoop
()
{
for
{
conn
,
err
:=
l
.
Listener
.
Accept
()
if
err
!=
nil
{
log
.
Log
(
"[http2] accept:"
,
err
)
l
.
errChan
<-
err
close
(
l
.
errChan
)
return
}
go
l
.
handleLoop
(
conn
)
}
}
func
(
l
*
h2Listener
)
handleLoop
(
conn
net
.
Conn
)
{
if
l
.
tlsConfig
!=
nil
{
conn
=
tls
.
Server
(
conn
,
l
.
tlsConfig
)
}
if
tc
,
ok
:=
conn
.
(
*
tls
.
Conn
);
ok
{
// NOTE: HTTP2 server will check the TLS version,
// so we must ensure that the TLS connection is handshake completed.
if
err
:=
tc
.
Handshake
();
err
!=
nil
{
log
.
Logf
(
"[http2] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
(),
err
)
return
}
}
opt
:=
http2
.
ServeConnOpts
{
Handler
:
http
.
HandlerFunc
(
l
.
handleFunc
),
}
l
.
server
.
ServeConn
(
conn
,
&
opt
)
}
func
(
l
*
h2Listener
)
handleFunc
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
log
.
Logf
(
"[http2] %s %s - %s %s"
,
r
.
Method
,
r
.
RemoteAddr
,
r
.
Host
,
r
.
Proto
)
if
Debug
{
dump
,
_
:=
httputil
.
DumpRequest
(
r
,
false
)
log
.
Log
(
"[http2]"
,
string
(
dump
))
}
w
.
Header
()
.
Set
(
"Proxy-Agent"
,
"gost/"
+
Version
)
conn
,
err
:=
l
.
upgrade
(
w
,
r
)
if
err
!=
nil
{
log
.
Logf
(
"[http2] %s %s - %s %s"
,
r
.
Method
,
r
.
RemoteAddr
,
r
.
Host
,
r
.
Proto
)
return
}
select
{
case
l
.
connChan
<-
conn
:
default
:
conn
.
Close
()
log
.
Logf
(
"[http2] %s - %s: connection queue is full"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
}
<-
conn
.
closed
// wait for streaming
}
func
(
l
*
h2Listener
)
upgrade
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
*
http2Conn
,
error
)
{
if
r
.
Method
!=
http
.
MethodConnect
{
w
.
WriteHeader
(
http
.
StatusMethodNotAllowed
)
return
nil
,
errors
.
New
(
"Method not allowed"
)
}
w
.
WriteHeader
(
http
.
StatusOK
)
if
fw
,
ok
:=
w
.
(
http
.
Flusher
);
ok
{
fw
.
Flush
()
// write header to client
}
remoteAddr
,
_
:=
net
.
ResolveTCPAddr
(
"tcp"
,
r
.
RemoteAddr
)
if
remoteAddr
==
nil
{
remoteAddr
=
&
net
.
TCPAddr
{
IP
:
net
.
IPv4zero
,
Port
:
0
,
}
}
conn
:=
&
http2Conn
{
r
:
r
.
Body
,
w
:
flushWriter
{
w
},
localAddr
:
l
.
Listener
.
Addr
(),
remoteAddr
:
remoteAddr
,
closed
:
make
(
chan
struct
{}),
}
return
conn
,
nil
}
func
(
l
*
h2Listener
)
Accept
()
(
conn
net
.
Conn
,
err
error
)
{
var
ok
bool
select
{
case
conn
=
<-
l
.
connChan
:
case
err
,
ok
=
<-
l
.
errChan
:
if
!
ok
{
err
=
errors
.
New
(
"accpet on closed listener"
)
}
}
return
}
type
http2Session
struct
{
type
http2Session
struct
{
conn
net
.
Conn
conn
net
.
Conn
clientConn
*
http2
.
ClientConn
clientConn
*
http2
.
ClientConn
...
@@ -383,6 +615,7 @@ type http2Conn struct {
...
@@ -383,6 +615,7 @@ type http2Conn struct {
w
io
.
Writer
w
io
.
Writer
remoteAddr
net
.
Addr
remoteAddr
net
.
Addr
localAddr
net
.
Addr
localAddr
net
.
Addr
closed
chan
struct
{}
}
}
func
(
c
*
http2Conn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
func
(
c
*
http2Conn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
...
@@ -394,6 +627,12 @@ func (c *http2Conn) Write(b []byte) (n int, err error) {
...
@@ -394,6 +627,12 @@ func (c *http2Conn) Write(b []byte) (n int, err error) {
}
}
func
(
c
*
http2Conn
)
Close
()
(
err
error
)
{
func
(
c
*
http2Conn
)
Close
()
(
err
error
)
{
select
{
case
<-
c
.
closed
:
return
default
:
close
(
c
.
closed
)
}
if
rc
,
ok
:=
c
.
r
.
(
io
.
Closer
);
ok
{
if
rc
,
ok
:=
c
.
r
.
(
io
.
Closer
);
ok
{
err
=
rc
.
Close
()
err
=
rc
.
Close
()
}
}
...
@@ -470,6 +709,7 @@ func (fw flushWriter) Write(p []byte) (n int, err error) {
...
@@ -470,6 +709,7 @@ func (fw flushWriter) Write(p []byte) (n int, err error) {
if
r
:=
recover
();
r
!=
nil
{
if
r
:=
recover
();
r
!=
nil
{
if
s
,
ok
:=
r
.
(
string
);
ok
{
if
s
,
ok
:=
r
.
(
string
);
ok
{
err
=
errors
.
New
(
s
)
err
=
errors
.
New
(
s
)
log
.
Log
(
"[http2]"
,
err
)
return
return
}
}
err
=
r
.
(
error
)
err
=
r
.
(
error
)
...
...
gost/tls.go
View file @
afac5fe5
...
@@ -2,7 +2,9 @@ package gost
...
@@ -2,7 +2,9 @@ package gost
import
(
import
(
"crypto/tls"
"crypto/tls"
"crypto/x509"
"net"
"net"
"time"
)
)
type
tlsTransporter
struct
{
type
tlsTransporter
struct
{
...
@@ -38,3 +40,65 @@ func TLSListener(addr string, config *tls.Config) (Listener, error) {
...
@@ -38,3 +40,65 @@ func TLSListener(addr string, config *tls.Config) (Listener, error) {
}
}
return
&
tlsListener
{
ln
},
nil
return
&
tlsListener
{
ln
},
nil
}
}
// Wrap a net.Conn into a client tls connection, performing any
// additional verification as needed.
//
// As of go 1.3, crypto/tls only supports either doing no certificate
// verification, or doing full verification including of the peer's
// DNS name. For consul, we want to validate that the certificate is
// signed by a known CA, but because consul doesn't use DNS names for
// node names, we don't verify the certificate DNS names. Since go 1.3
// no longer supports this mode of operation, we have to do it
// manually.
//
// This code is taken from consul:
// https://github.com/hashicorp/consul/blob/master/tlsutil/config.go
func
wrapTLSClient
(
conn
net
.
Conn
,
tlsConfig
*
tls
.
Config
)
(
net
.
Conn
,
error
)
{
var
err
error
var
tlsConn
*
tls
.
Conn
tlsConn
=
tls
.
Client
(
conn
,
tlsConfig
)
// If crypto/tls is doing verification, there's no need to do our own.
if
tlsConfig
.
InsecureSkipVerify
==
false
{
return
tlsConn
,
nil
}
// Similarly if we use host's CA, we can do full handshake
if
tlsConfig
.
RootCAs
==
nil
{
return
tlsConn
,
nil
}
// Otherwise perform handshake, but don't verify the domain
//
// The following is lightly-modified from the doFullHandshake
// method in https://golang.org/src/crypto/tls/handshake_client.go
if
err
=
tlsConn
.
Handshake
();
err
!=
nil
{
tlsConn
.
Close
()
return
nil
,
err
}
opts
:=
x509
.
VerifyOptions
{
Roots
:
tlsConfig
.
RootCAs
,
CurrentTime
:
time
.
Now
(),
DNSName
:
""
,
Intermediates
:
x509
.
NewCertPool
(),
}
certs
:=
tlsConn
.
ConnectionState
()
.
PeerCertificates
for
i
,
cert
:=
range
certs
{
if
i
==
0
{
continue
}
opts
.
Intermediates
.
AddCert
(
cert
)
}
_
,
err
=
certs
[
0
]
.
Verify
(
opts
)
if
err
!=
nil
{
tlsConn
.
Close
()
return
nil
,
err
}
return
tlsConn
,
err
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment