add more tests
This commit is contained in:
parent
d3b03e4231
commit
bb1afcc437
21
Dockerfile.mod
Normal file
21
Dockerfile.mod
Normal file
@ -0,0 +1,21 @@
|
||||
FROM golang:1-alpine as builder
|
||||
|
||||
RUN apk add --no-cache musl-dev git gcc
|
||||
|
||||
ADD . /data
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
ENV GO111MODULE=on
|
||||
|
||||
RUN cd cmd/gost && go build
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
WORKDIR /bin/
|
||||
|
||||
COPY --from=builder /data/cmd/gost/gost .
|
||||
|
||||
RUN /bin/gost -V
|
||||
|
||||
ENTRYPOINT ["/bin/gost"]
|
@ -110,6 +110,8 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
wsOpts.WriteBufferSize = node.GetInt("wbuf")
|
||||
wsOpts.UserAgent = node.Get("agent")
|
||||
|
||||
var host string
|
||||
|
||||
var tr gost.Transporter
|
||||
switch node.Transport {
|
||||
case "tls":
|
||||
@ -160,6 +162,7 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
case "obfs4":
|
||||
tr = gost.Obfs4Transporter()
|
||||
case "ohttp":
|
||||
host = node.Get("host")
|
||||
tr = gost.ObfsHTTPTransporter()
|
||||
default:
|
||||
tr = gost.TCPTransporter()
|
||||
@ -197,9 +200,12 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
gost.TimeoutDialOption(time.Duration(timeout)*time.Second),
|
||||
)
|
||||
|
||||
if host == "" {
|
||||
host = node.Host
|
||||
}
|
||||
handshakeOptions := []gost.HandshakeOption{
|
||||
gost.AddrHandshakeOption(node.Addr),
|
||||
gost.HostHandshakeOption(node.Host),
|
||||
gost.HostHandshakeOption(host),
|
||||
gost.UserHandshakeOption(node.User),
|
||||
gost.TLSConfigHandshakeOption(tlsCfg),
|
||||
gost.IntervalHandshakeOption(time.Duration(node.GetInt("ping")) * time.Second),
|
||||
|
9
http2.go
9
http2.go
@ -34,6 +34,11 @@ func HTTP2Connector(user *url.Userinfo) Connector {
|
||||
}
|
||||
|
||||
func (c *http2Connector) Connect(conn net.Conn, addr string, options ...ConnectOption) (net.Conn, error) {
|
||||
opts := &ConnectOptions{}
|
||||
for _, option := range options {
|
||||
option(opts)
|
||||
}
|
||||
|
||||
cc, ok := conn.(*http2ClientConn)
|
||||
if !ok {
|
||||
return nil, errors.New("wrong connection type")
|
||||
@ -142,7 +147,7 @@ func (tr *http2Transporter) Dial(addr string, options ...DialOption) (net.Conn,
|
||||
}
|
||||
client = &http.Client{
|
||||
Transport: &transport,
|
||||
Timeout: timeout,
|
||||
// Timeout: timeout,
|
||||
}
|
||||
tr.clients[addr] = client
|
||||
}
|
||||
@ -214,7 +219,7 @@ func (tr *h2Transporter) Dial(addr string, options ...DialOption) (net.Conn, err
|
||||
}
|
||||
client = &http.Client{
|
||||
Transport: &transport,
|
||||
Timeout: timeout,
|
||||
// Timeout: timeout,
|
||||
}
|
||||
tr.clients[addr] = client
|
||||
}
|
||||
|
49
obfs.go
49
obfs.go
@ -67,10 +67,7 @@ func (l *obfsHTTPListener) Accept() (net.Conn, error) {
|
||||
type obfsHTTPConn struct {
|
||||
net.Conn
|
||||
host string
|
||||
request *http.Request
|
||||
response *http.Response
|
||||
rbuf []byte
|
||||
wbuf []byte
|
||||
buf []byte
|
||||
isServer bool
|
||||
handshaked bool
|
||||
handshakeMutex sync.Mutex
|
||||
@ -99,19 +96,19 @@ func (c *obfsHTTPConn) Handshake() (err error) {
|
||||
|
||||
func (c *obfsHTTPConn) serverHandshake() (err error) {
|
||||
br := bufio.NewReader(c.Conn)
|
||||
c.request, err = http.ReadRequest(br)
|
||||
r, err := http.ReadRequest(br)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if Debug {
|
||||
dump, _ := httputil.DumpRequest(c.request, false)
|
||||
dump, _ := httputil.DumpRequest(r, false)
|
||||
log.Logf("[ohttp] %s -> %s\n%s", c.Conn.RemoteAddr(), c.Conn.LocalAddr(), string(dump))
|
||||
}
|
||||
|
||||
if br.Buffered() > 0 {
|
||||
c.rbuf, err = br.Peek(br.Buffered())
|
||||
if r.ContentLength > 0 {
|
||||
c.buf, err = ioutil.ReadAll(r.Body)
|
||||
} else {
|
||||
c.rbuf, err = ioutil.ReadAll(c.request.Body)
|
||||
c.buf, err = br.Peek(br.Buffered())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -120,13 +117,13 @@ func (c *obfsHTTPConn) serverHandshake() (err error) {
|
||||
}
|
||||
|
||||
b := bytes.Buffer{}
|
||||
if c.request.Header.Get("Upgrade") == "websocket" {
|
||||
if r.Header.Get("Upgrade") == "websocket" {
|
||||
b.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
|
||||
b.WriteString("Server: nginx/1.10.0\r\n")
|
||||
b.WriteString("Date: " + time.Now().Format(time.RFC1123) + "\r\n")
|
||||
b.WriteString("Connection: Upgrade\r\n")
|
||||
b.WriteString("Upgrade: websocket\r\n")
|
||||
b.WriteString(fmt.Sprintf("Sec-WebSocket-Accept: %s\r\n", computeAcceptKey(c.request.Header.Get("Sec-WebSocket-Key"))))
|
||||
b.WriteString(fmt.Sprintf("Sec-WebSocket-Accept: %s\r\n", computeAcceptKey(r.Header.Get("Sec-WebSocket-Key"))))
|
||||
b.WriteString("\r\n")
|
||||
} else {
|
||||
b.WriteString("HTTP/1.1 200 OK\r\n")
|
||||
@ -146,24 +143,19 @@ func (c *obfsHTTPConn) serverHandshake() (err error) {
|
||||
}
|
||||
|
||||
func (c *obfsHTTPConn) clientHandshake() (err error) {
|
||||
r := c.request
|
||||
if r == nil {
|
||||
r = &http.Request{
|
||||
r := &http.Request{
|
||||
Method: http.MethodGet,
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
URL: &url.URL{Scheme: "http", Host: c.host},
|
||||
Header: make(http.Header),
|
||||
}
|
||||
r.Header.Set("Connection", "keep-alive")
|
||||
r.Header.Set("User-Agent", "curl/7.49.1")
|
||||
r.Header.Set("Connection", "Upgrade")
|
||||
r.Header.Set("Upgrade", "websocket")
|
||||
r.Header.Set("User-Agent", DefaultUserAgent)
|
||||
if len(c.wbuf) > 0 {
|
||||
log.Log("write buf", len(c.wbuf))
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(c.wbuf))
|
||||
r.ContentLength = int64(len(c.wbuf))
|
||||
}
|
||||
}
|
||||
key, _ := generateChallengeKey()
|
||||
r.Header.Set("Sec-WebSocket-Key", key)
|
||||
|
||||
if err = r.Write(c.Conn); err != nil {
|
||||
return
|
||||
}
|
||||
@ -182,6 +174,7 @@ func (c *obfsHTTPConn) clientHandshake() (err error) {
|
||||
dump, _ := httputil.DumpResponse(resp, false)
|
||||
log.Logf("[ohttp] %s <- %s\n%s", c.Conn.LocalAddr(), c.Conn.RemoteAddr(), string(dump))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -189,24 +182,18 @@ func (c *obfsHTTPConn) Read(b []byte) (n int, err error) {
|
||||
if err = c.Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
if len(c.rbuf) > 0 {
|
||||
n = copy(b, c.rbuf)
|
||||
c.rbuf = c.rbuf[n:]
|
||||
if len(c.buf) > 0 {
|
||||
n = copy(b, c.buf)
|
||||
c.buf = c.buf[n:]
|
||||
return
|
||||
}
|
||||
return c.Conn.Read(b)
|
||||
}
|
||||
|
||||
func (c *obfsHTTPConn) Write(b []byte) (n int, err error) {
|
||||
handshaked := c.handshaked
|
||||
c.wbuf = b
|
||||
if err = c.Handshake(); err != nil {
|
||||
return
|
||||
}
|
||||
if !handshaked {
|
||||
n = len(c.wbuf)
|
||||
return
|
||||
}
|
||||
return c.Conn.Write(b)
|
||||
}
|
||||
|
||||
|
371
obfs_test.go
Normal file
371
obfs_test.go
Normal file
@ -0,0 +1,371 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func httpOverObfsHTTPRoundtrip(targetURL string, data []byte,
|
||||
clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: HTTPConnector(clientInfo),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: HTTPHandler(
|
||||
UsersHandlerOption(serverInfo...),
|
||||
),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return proxyRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestHTTPOverObfsHTTP(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
for i, tc := range httpProxyTests {
|
||||
tc := tc
|
||||
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||
err := httpOverObfsHTTPRoundtrip(httpSrv.URL, sendData, tc.cliUser, tc.srvUsers)
|
||||
if err == nil {
|
||||
if tc.errStr != "" {
|
||||
t.Errorf("#%d should failed with error %s", i, tc.errStr)
|
||||
}
|
||||
} else {
|
||||
if tc.errStr == "" {
|
||||
t.Errorf("#%d got error %v", i, err)
|
||||
}
|
||||
if err.Error() != tc.errStr {
|
||||
t.Errorf("#%d got error %v, want %v", i, err, tc.errStr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHTTPOverObfsHTTP(b *testing.B) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
// b.Log(ln.Addr())
|
||||
|
||||
client := &Client{
|
||||
Connector: HTTPConnector(url.UserPassword("admin", "123456")),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: HTTPHandler(
|
||||
UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||
),
|
||||
}
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := proxyRoundtrip(client, server, httpSrv.URL, sendData); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHTTPOverObfsHTTPParallel(b *testing.B) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: HTTPConnector(url.UserPassword("admin", "123456")),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: HTTPHandler(
|
||||
UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||
),
|
||||
}
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
if err := proxyRoundtrip(client, server, httpSrv.URL, sendData); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func socks5OverObfsHTTPRoundtrip(targetURL string, data []byte,
|
||||
clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SOCKS5Connector(clientInfo),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SOCKS5Handler(
|
||||
UsersHandlerOption(serverInfo...),
|
||||
),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return proxyRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSOCKS5OverObfsHTTP(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
for i, tc := range socks5ProxyTests {
|
||||
err := socks5OverObfsHTTPRoundtrip(httpSrv.URL, sendData,
|
||||
tc.cliUser,
|
||||
tc.srvUsers,
|
||||
)
|
||||
if err == nil {
|
||||
if !tc.pass {
|
||||
t.Errorf("#%d should failed", i)
|
||||
}
|
||||
} else {
|
||||
// t.Logf("#%d %v", i, err)
|
||||
if tc.pass {
|
||||
t.Errorf("#%d got error: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func socks4OverObfsHTTPRoundtrip(targetURL string, data []byte) error {
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SOCKS4Connector(),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SOCKS4Handler(),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return proxyRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSOCKS4OverObfsHTTP(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
err := socks4OverObfsHTTPRoundtrip(httpSrv.URL, sendData)
|
||||
// t.Logf("#%d %v", i, err)
|
||||
if err != nil {
|
||||
t.Errorf("got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func socks4aOverObfsHTTPRoundtrip(targetURL string, data []byte) error {
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SOCKS4AConnector(),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SOCKS4Handler(),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return proxyRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSOCKS4AOverObfsHTTP(t *testing.T) {
|
||||
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
err := socks4aOverObfsHTTPRoundtrip(httpSrv.URL, sendData)
|
||||
// t.Logf("#%d %v", i, err)
|
||||
if err != nil {
|
||||
t.Errorf("got error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func ssOverObfsHTTPRoundtrip(targetURL string, data []byte,
|
||||
clientInfo, serverInfo *url.Userinfo) error {
|
||||
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: ShadowConnector(clientInfo),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: ShadowHandler(
|
||||
UsersHandlerOption(serverInfo),
|
||||
),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return proxyRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSSOverObfsHTTP(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
for i, tc := range ssProxyTests {
|
||||
err := ssOverObfsHTTPRoundtrip(httpSrv.URL, sendData,
|
||||
tc.clientCipher,
|
||||
tc.serverCipher,
|
||||
)
|
||||
if err == nil {
|
||||
if !tc.pass {
|
||||
t.Errorf("#%d should failed", i)
|
||||
}
|
||||
} else {
|
||||
// t.Logf("#%d %v", i, err)
|
||||
if tc.pass {
|
||||
t.Errorf("#%d got error: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sniOverObfsHTTPRoundtrip(targetURL string, data []byte, host string) error {
|
||||
ln, err := ObfsHTTPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u, err := url.Parse(targetURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SNIConnector(host),
|
||||
Transporter: ObfsHTTPTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SNIHandler(HostHandlerOption(u.Host)),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return sniRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSNIOverObfsHTTP(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
httpsSrv := httptest.NewTLSServer(httpTestHandler)
|
||||
defer httpsSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
var sniProxyTests = []struct {
|
||||
targetURL string
|
||||
host string
|
||||
pass bool
|
||||
}{
|
||||
{httpSrv.URL, "", true},
|
||||
{httpSrv.URL, "example.com", true},
|
||||
{httpsSrv.URL, "", true},
|
||||
{httpsSrv.URL, "example.com", true},
|
||||
}
|
||||
|
||||
for i, tc := range sniProxyTests {
|
||||
tc := tc
|
||||
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||
err := sniOverObfsHTTPRoundtrip(tc.targetURL, sendData, tc.host)
|
||||
if err == nil {
|
||||
if !tc.pass {
|
||||
t.Errorf("#%d should failed", i)
|
||||
}
|
||||
} else {
|
||||
// t.Logf("#%d %v", i, err)
|
||||
if tc.pass {
|
||||
t.Errorf("#%d got error: %v", i, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
13
ssh.go
13
ssh.go
@ -95,13 +95,15 @@ func (c *sshRemoteForwardConnector) Connect(conn net.Conn, addr string, options
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log.Log("[ssh-rtcp] listening on", ln.Addr())
|
||||
|
||||
for {
|
||||
rc, err := ln.Accept()
|
||||
if err != nil {
|
||||
log.Logf("[ssh-rtcp] %s <-> %s accpet : %s", ln.Addr(), addr, err)
|
||||
return
|
||||
}
|
||||
|
||||
// log.Log("[ssh-rtcp] accept", rc.LocalAddr(), rc.RemoteAddr())
|
||||
select {
|
||||
case cc.session.connChan <- rc:
|
||||
default:
|
||||
@ -593,7 +595,6 @@ func (h *sshForwardHandler) tcpipForwardRequest(sshConn ssh.Conn, req *ssh.Reque
|
||||
return
|
||||
}
|
||||
|
||||
log.Log("[ssh-rtcp] listening on tcp", addr)
|
||||
ln, err := net.Listen("tcp", addr) //tie to the client connection
|
||||
if err != nil {
|
||||
log.Log("[ssh-rtcp]", err)
|
||||
@ -602,6 +603,8 @@ func (h *sshForwardHandler) tcpipForwardRequest(sshConn ssh.Conn, req *ssh.Reque
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
log.Log("[ssh-rtcp] listening on tcp", ln.Addr())
|
||||
|
||||
replyFunc := func() error {
|
||||
if t.Port == 0 && req.WantReply { // Client sent port 0. let them know which port is actually being used
|
||||
_, port, err := getHostPortFromAddr(ln.Addr())
|
||||
@ -850,15 +853,15 @@ func (c *sshNopConn) RemoteAddr() net.Addr {
|
||||
}
|
||||
|
||||
func (c *sshNopConn) SetDeadline(t time.Time) error {
|
||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||
return &net.OpError{Op: "set", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||
}
|
||||
|
||||
func (c *sshNopConn) SetReadDeadline(t time.Time) error {
|
||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||
return &net.OpError{Op: "set", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||
}
|
||||
|
||||
func (c *sshNopConn) SetWriteDeadline(t time.Time) error {
|
||||
return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||
return &net.OpError{Op: "set", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||
}
|
||||
|
||||
type sshConn struct {
|
||||
|
170
ssh_test.go
170
ssh_test.go
@ -4,11 +4,181 @@ import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func sshDirectForwardRoundtrip(targetURL string, data []byte) error {
|
||||
ln, err := TCPListener("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SSHDirectForwardConnector(),
|
||||
Transporter: SSHForwardTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SSHForwardHandler(),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
return proxyRoundtrip(client, server, targetURL, data)
|
||||
}
|
||||
|
||||
func TestSSHDirectForward(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
err := sshDirectForwardRoundtrip(httpSrv.URL, sendData)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSSHDirectForward(b *testing.B) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
ln, err := TCPListener("")
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SSHDirectForwardConnector(),
|
||||
Transporter: SSHForwardTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SSHForwardHandler(),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if err := proxyRoundtrip(client, server, httpSrv.URL, sendData); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSSHDirectForwardParallel(b *testing.B) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
ln, err := TCPListener("")
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SSHDirectForwardConnector(),
|
||||
Transporter: SSHForwardTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SSHForwardHandler(),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
if err := proxyRoundtrip(client, server, httpSrv.URL, sendData); err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func sshRemoteForwardRoundtrip(t *testing.T, targetURL string, data []byte) (err error) {
|
||||
ln, err := TCPListener("")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Connector: SSHRemoteForwardConnector(),
|
||||
Transporter: SSHForwardTransporter(),
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Listener: ln,
|
||||
Handler: SSHForwardHandler(),
|
||||
}
|
||||
|
||||
go server.Run()
|
||||
defer server.Close()
|
||||
|
||||
conn, err := proxyConn(client, server)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
go func() {
|
||||
conn, err = client.Connect(conn, ":0")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
c, err := net.Dial("tcp", conn.LocalAddr().String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
u, err := url.Parse(targetURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cc, err := net.Dial("tcp", u.Host)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
go transport(conn, cc)
|
||||
|
||||
t.Log("httpRoundtrip")
|
||||
return httpRoundtrip(c, targetURL, data)
|
||||
}
|
||||
|
||||
func _TestSSHRemoteForward(t *testing.T) {
|
||||
httpSrv := httptest.NewServer(httpTestHandler)
|
||||
defer httpSrv.Close()
|
||||
|
||||
sendData := make([]byte, 128)
|
||||
rand.Read(sendData)
|
||||
|
||||
err := sshRemoteForwardRoundtrip(t, httpSrv.URL, sendData)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func httpOverSSHTunnelRoundtrip(targetURL string, data []byte, tlsConfig *tls.Config,
|
||||
clientInfo *url.Userinfo, serverInfo []*url.Userinfo) error {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user