|
|
|
package features
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
|
|
|
|
|
|
"github.com/fatedier/frp/pkg/transport"
|
|
|
|
"github.com/fatedier/frp/test/e2e/framework"
|
|
|
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
|
|
|
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
|
|
|
|
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
|
|
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
|
|
|
"github.com/fatedier/frp/test/e2e/pkg/ssh"
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
|
|
|
|
f := framework.NewDefaultFramework()
|
|
|
|
|
|
|
|
ginkgo.It("tcp", func() {
|
|
|
|
sshPort := f.AllocPort()
|
|
|
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
|
|
|
sshTunnelGateway.bindPort = %d
|
|
|
|
`, sshPort)
|
|
|
|
|
|
|
|
f.RunProcesses([]string{serverConf}, nil)
|
|
|
|
|
|
|
|
localPort := f.PortByName(framework.TCPEchoServerPort)
|
|
|
|
remotePort := f.AllocPort()
|
|
|
|
tc := ssh.NewTunnelClient(
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
|
|
|
fmt.Sprintf("tcp --remote-port %d", remotePort),
|
|
|
|
)
|
|
|
|
framework.ExpectNoError(tc.Start())
|
|
|
|
defer tc.Close()
|
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
framework.NewRequestExpect(f).Port(remotePort).Ensure()
|
|
|
|
})
|
|
|
|
|
|
|
|
ginkgo.It("http", func() {
|
|
|
|
sshPort := f.AllocPort()
|
|
|
|
vhostPort := f.AllocPort()
|
|
|
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
|
|
|
vhostHTTPPort = %d
|
|
|
|
sshTunnelGateway.bindPort = %d
|
|
|
|
`, vhostPort, sshPort)
|
|
|
|
|
|
|
|
f.RunProcesses([]string{serverConf}, nil)
|
|
|
|
|
|
|
|
localPort := f.PortByName(framework.HTTPSimpleServerPort)
|
|
|
|
tc := ssh.NewTunnelClient(
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
|
|
|
"http --custom-domain test.example.com",
|
|
|
|
)
|
|
|
|
framework.ExpectNoError(tc.Start())
|
|
|
|
defer tc.Close()
|
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
framework.NewRequestExpect(f).Port(vhostPort).
|
|
|
|
RequestModify(func(r *request.Request) {
|
|
|
|
r.HTTP().HTTPHost("test.example.com")
|
|
|
|
}).
|
|
|
|
Ensure()
|
|
|
|
})
|
|
|
|
|
|
|
|
ginkgo.It("https", func() {
|
|
|
|
sshPort := f.AllocPort()
|
|
|
|
vhostPort := f.AllocPort()
|
|
|
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
|
|
|
vhostHTTPSPort = %d
|
|
|
|
sshTunnelGateway.bindPort = %d
|
|
|
|
`, vhostPort, sshPort)
|
|
|
|
|
|
|
|
f.RunProcesses([]string{serverConf}, nil)
|
|
|
|
|
|
|
|
localPort := f.AllocPort()
|
|
|
|
testDomain := "test.example.com"
|
|
|
|
tc := ssh.NewTunnelClient(
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
|
|
|
fmt.Sprintf("https --custom-domain %s", testDomain),
|
|
|
|
)
|
|
|
|
framework.ExpectNoError(tc.Start())
|
|
|
|
defer tc.Close()
|
|
|
|
|
|
|
|
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
|
|
|
|
framework.ExpectNoError(err)
|
|
|
|
localServer := httpserver.New(
|
|
|
|
httpserver.WithBindPort(localPort),
|
|
|
|
httpserver.WithTLSConfig(tlsConfig),
|
|
|
|
httpserver.WithResponse([]byte("test")),
|
|
|
|
)
|
|
|
|
f.RunServer("", localServer)
|
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
framework.NewRequestExpect(f).
|
|
|
|
Port(vhostPort).
|
|
|
|
RequestModify(func(r *request.Request) {
|
|
|
|
r.HTTPS().HTTPHost(testDomain).TLSConfig(&tls.Config{
|
|
|
|
ServerName: testDomain,
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
})
|
|
|
|
}).
|
|
|
|
ExpectResp([]byte("test")).
|
|
|
|
Ensure()
|
|
|
|
})
|
|
|
|
|
|
|
|
ginkgo.It("tcpmux", func() {
|
|
|
|
sshPort := f.AllocPort()
|
|
|
|
tcpmuxPort := f.AllocPort()
|
|
|
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
|
|
|
tcpmuxHTTPConnectPort = %d
|
|
|
|
sshTunnelGateway.bindPort = %d
|
|
|
|
`, tcpmuxPort, sshPort)
|
|
|
|
|
|
|
|
f.RunProcesses([]string{serverConf}, nil)
|
|
|
|
|
|
|
|
localPort := f.AllocPort()
|
|
|
|
testDomain := "test.example.com"
|
|
|
|
tc := ssh.NewTunnelClient(
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
|
|
|
fmt.Sprintf("tcpmux --mux=httpconnect --custom-domain %s", testDomain),
|
|
|
|
)
|
|
|
|
framework.ExpectNoError(tc.Start())
|
|
|
|
defer tc.Close()
|
|
|
|
|
|
|
|
localServer := streamserver.New(
|
|
|
|
streamserver.TCP,
|
|
|
|
streamserver.WithBindPort(localPort),
|
|
|
|
streamserver.WithRespContent([]byte("test")),
|
|
|
|
)
|
|
|
|
f.RunServer("", localServer)
|
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
// Request without HTTP connect should get error
|
|
|
|
framework.NewRequestExpect(f).
|
|
|
|
Port(tcpmuxPort).
|
|
|
|
ExpectError(true).
|
|
|
|
Explain("request without HTTP connect expect error").
|
|
|
|
Ensure()
|
|
|
|
|
|
|
|
proxyURL := fmt.Sprintf("http://127.0.0.1:%d", tcpmuxPort)
|
|
|
|
// Request with incorrect connect hostname
|
|
|
|
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
|
|
|
|
r.Addr("invalid").Proxy(proxyURL)
|
|
|
|
}).ExpectError(true).Explain("request without HTTP connect expect error").Ensure()
|
|
|
|
|
|
|
|
// Request with correct connect hostname
|
|
|
|
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
|
|
|
|
r.Addr(testDomain).Proxy(proxyURL)
|
|
|
|
}).ExpectResp([]byte("test")).Ensure()
|
|
|
|
})
|
|
|
|
|
|
|
|
ginkgo.It("stcp", func() {
|
|
|
|
sshPort := f.AllocPort()
|
|
|
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
|
|
|
sshTunnelGateway.bindPort = %d
|
|
|
|
`, sshPort)
|
|
|
|
|
|
|
|
bindPort := f.AllocPort()
|
|
|
|
visitorConf := consts.DefaultClientConfig + fmt.Sprintf(`
|
|
|
|
[[visitors]]
|
|
|
|
name = "stcp-test-visitor"
|
|
|
|
type = "stcp"
|
|
|
|
serverName = "stcp-test"
|
|
|
|
secretKey = "abcdefg"
|
|
|
|
bindPort = %d
|
|
|
|
`, bindPort)
|
|
|
|
|
|
|
|
f.RunProcesses([]string{serverConf}, []string{visitorConf})
|
|
|
|
|
|
|
|
localPort := f.PortByName(framework.TCPEchoServerPort)
|
|
|
|
tc := ssh.NewTunnelClient(
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", localPort),
|
|
|
|
fmt.Sprintf("127.0.0.1:%d", sshPort),
|
|
|
|
"stcp -n stcp-test --sk=abcdefg --allow-users=\"*\"",
|
|
|
|
)
|
|
|
|
framework.ExpectNoError(tc.Start())
|
|
|
|
defer tc.Close()
|
|
|
|
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
framework.NewRequestExpect(f).
|
|
|
|
Port(bindPort).
|
|
|
|
Ensure()
|
|
|
|
})
|
|
|
|
})
|