|
@@ -0,0 +1,193 @@
|
|
|
+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()
|
|
|
+ })
|
|
|
+})
|