frp/test/e2e/v1/features/ssh_tunnel.go

194 lines
5.3 KiB
Go

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()
})
})