frp/test/e2e/v1/basic/basic.go

525 lines
15 KiB
Go
Raw Normal View History

2020-09-07 06:57:23 +00:00
package basic
import (
2021-08-02 05:07:28 +00:00
"crypto/tls"
2020-09-07 06:57:23 +00:00
"fmt"
"strings"
2023-05-28 15:06:35 +00:00
"time"
2020-09-07 06:57:23 +00:00
2023-02-27 06:44:16 +00:00
"github.com/onsi/ginkgo/v2"
2022-08-28 17:02:53 +00:00
2021-08-02 05:07:28 +00:00
"github.com/fatedier/frp/pkg/transport"
2020-09-07 06:57:23 +00:00
"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
2021-08-02 05:07:28 +00:00
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
2021-06-18 08:48:36 +00:00
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
2021-03-31 08:57:39 +00:00
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"
2020-09-07 06:57:23 +00:00
)
2022-08-28 17:02:53 +00:00
var _ = ginkgo.Describe("[Feature: Basic]", func() {
2020-09-07 06:57:23 +00:00
f := framework.NewDefaultFramework()
2022-08-28 17:02:53 +00:00
ginkgo.Describe("TCP && UDP", func() {
2020-09-07 06:57:23 +00:00
types := []string{"tcp", "udp"}
for _, t := range types {
proxyType := t
2022-08-28 17:02:53 +00:00
ginkgo.It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
2020-09-07 06:57:23 +00:00
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
localPortName := ""
protocol := "tcp"
switch proxyType {
case "tcp":
localPortName = framework.TCPEchoServerPort
protocol = "tcp"
case "udp":
localPortName = framework.UDPEchoServerPort
protocol = "udp"
}
getProxyConf := func(proxyName string, portName string, extra string) string {
return fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
[[proxies]]
name = "%s"
type = "%s"
localPort = {{ .%s }}
remotePort = {{ .%s }}
2020-09-07 06:57:23 +00:00
`+extra, proxyName, proxyType, localPortName, portName)
}
tests := []struct {
proxyName string
portName string
extraConfig string
}{
{
proxyName: "normal",
2021-03-31 08:57:39 +00:00
portName: port.GenName("Normal"),
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-encryption",
2021-03-31 08:57:39 +00:00
portName: port.GenName("WithEncryption"),
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useEncryption = true",
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-compression",
2021-03-31 08:57:39 +00:00
portName: port.GenName("WithCompression"),
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useCompression = true",
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-encryption-and-compression",
2021-03-31 08:57:39 +00:00
portName: port.GenName("WithEncryptionAndCompression"),
2020-09-07 06:57:23 +00:00
extraConfig: `
2023-09-13 08:32:39 +00:00
transport.useEncryption = true
transport.useCompression = true
2020-09-07 06:57:23 +00:00
`,
},
}
// build all client config
for _, test := range tests {
clientConf += getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n"
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})
for _, test := range tests {
2021-03-31 08:57:39 +00:00
framework.NewRequestExpect(f).
2021-06-18 08:48:36 +00:00
Protocol(protocol).
2021-03-31 08:57:39 +00:00
PortName(test.portName).
Explain(test.proxyName).
Ensure()
2020-09-07 06:57:23 +00:00
}
})
}
})
2022-08-28 17:02:53 +00:00
ginkgo.Describe("HTTP", func() {
ginkgo.It("proxy to HTTP server", func() {
2021-06-18 08:48:36 +00:00
serverConf := consts.DefaultServerConfig
vhostHTTPPort := f.AllocPort()
serverConf += fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
vhostHTTPPort = %d
2021-06-18 08:48:36 +00:00
`, vhostHTTPPort)
clientConf := consts.DefaultClientConfig
getProxyConf := func(proxyName string, customDomains string, extra string) string {
return fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
[[proxies]]
name = "%s"
type = "http"
localPort = {{ .%s }}
customDomains = %s
2021-06-18 08:48:36 +00:00
`+extra, proxyName, framework.HTTPSimpleServerPort, customDomains)
}
tests := []struct {
proxyName string
customDomains string
extraConfig string
}{
{
proxyName: "normal",
},
{
proxyName: "with-encryption",
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useEncryption = true",
2021-06-18 08:48:36 +00:00
},
{
proxyName: "with-compression",
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useCompression = true",
2021-06-18 08:48:36 +00:00
},
{
proxyName: "with-encryption-and-compression",
extraConfig: `
2023-09-13 08:32:39 +00:00
transport.useEncryption = true
transport.useCompression = true
`,
2021-06-18 08:48:36 +00:00
},
{
proxyName: "multiple-custom-domains",
2023-09-13 08:32:39 +00:00
customDomains: `["a.example.com", "b.example.com"]`,
2021-06-18 08:48:36 +00:00
},
}
// build all client config
for i, test := range tests {
if tests[i].customDomains == "" {
2023-09-13 08:32:39 +00:00
tests[i].customDomains = fmt.Sprintf(`["%s"]`, test.proxyName+".example.com")
2021-06-18 08:48:36 +00:00
}
clientConf += getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n"
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})
for _, test := range tests {
for _, domain := range strings.Split(test.customDomains, ",") {
domain = strings.TrimSpace(domain)
2023-09-13 08:32:39 +00:00
domain = strings.TrimLeft(domain, "[\"")
domain = strings.TrimRight(domain, "]\"")
2021-06-18 08:48:36 +00:00
framework.NewRequestExpect(f).
Explain(test.proxyName + "-" + domain).
Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost(domain)
}).
Ensure()
}
}
// not exist host
framework.NewRequestExpect(f).
Explain("not exist host").
Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("not-exist.example.com")
}).
Ensure(framework.ExpectResponseCode(404))
})
})
2022-08-28 17:02:53 +00:00
ginkgo.Describe("HTTPS", func() {
ginkgo.It("proxy to HTTPS server", func() {
2021-08-02 05:07:28 +00:00
serverConf := consts.DefaultServerConfig
vhostHTTPSPort := f.AllocPort()
serverConf += fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
vhostHTTPSPort = %d
2021-08-02 05:07:28 +00:00
`, vhostHTTPSPort)
localPort := f.AllocPort()
clientConf := consts.DefaultClientConfig
getProxyConf := func(proxyName string, customDomains string, extra string) string {
return fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
[[proxies]]
name = "%s"
type = "https"
localPort = %d
customDomains = %s
2021-08-02 05:07:28 +00:00
`+extra, proxyName, localPort, customDomains)
}
tests := []struct {
proxyName string
customDomains string
extraConfig string
}{
{
proxyName: "normal",
},
{
proxyName: "with-encryption",
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useEncryption = true",
2021-08-02 05:07:28 +00:00
},
{
proxyName: "with-compression",
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useCompression = true",
2021-08-02 05:07:28 +00:00
},
{
proxyName: "with-encryption-and-compression",
extraConfig: `
2023-09-13 08:32:39 +00:00
transport.useEncryption = true
transport.useCompression = true
2021-08-02 05:07:28 +00:00
`,
},
{
proxyName: "multiple-custom-domains",
2023-09-13 08:32:39 +00:00
customDomains: `["a.example.com", "b.example.com"]`,
2021-08-02 05:07:28 +00:00
},
}
// build all client config
for i, test := range tests {
if tests[i].customDomains == "" {
2023-09-13 08:32:39 +00:00
tests[i].customDomains = fmt.Sprintf(`["%s"]`, test.proxyName+".example.com")
2021-08-02 05:07:28 +00:00
}
clientConf += getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n"
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
2022-08-28 17:02:53 +00:00
httpserver.WithTLSConfig(tlsConfig),
2021-08-02 05:07:28 +00:00
httpserver.WithResponse([]byte("test")),
)
f.RunServer("", localServer)
for _, test := range tests {
for _, domain := range strings.Split(test.customDomains, ",") {
domain = strings.TrimSpace(domain)
2023-09-13 08:32:39 +00:00
domain = strings.TrimLeft(domain, "[\"")
domain = strings.TrimRight(domain, "]\"")
2021-08-02 05:07:28 +00:00
framework.NewRequestExpect(f).
Explain(test.proxyName + "-" + domain).
Port(vhostHTTPSPort).
RequestModify(func(r *request.Request) {
r.HTTPS().HTTPHost(domain).TLSConfig(&tls.Config{
ServerName: domain,
InsecureSkipVerify: true,
})
}).
ExpectResp([]byte("test")).
Ensure()
}
}
// not exist host
notExistDomain := "not-exist.example.com"
framework.NewRequestExpect(f).
Explain("not exist host").
Port(vhostHTTPSPort).
RequestModify(func(r *request.Request) {
r.HTTPS().HTTPHost(notExistDomain).TLSConfig(&tls.Config{
ServerName: notExistDomain,
InsecureSkipVerify: true,
})
}).
ExpectError(true).
Ensure()
})
})
2023-05-28 15:06:35 +00:00
ginkgo.Describe("STCP && SUDP && XTCP", func() {
types := []string{"stcp", "sudp", "xtcp"}
2020-09-07 06:57:23 +00:00
for _, t := range types {
proxyType := t
2022-08-28 17:02:53 +00:00
ginkgo.It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
2020-09-07 06:57:23 +00:00
serverConf := consts.DefaultServerConfig
2023-09-13 08:32:39 +00:00
clientServerConf := consts.DefaultClientConfig + "\nuser = \"user1\""
clientVisitorConf := consts.DefaultClientConfig + "\nuser = \"user1\""
clientUser2VisitorConf := consts.DefaultClientConfig + "\nuser = \"user2\""
2020-09-07 06:57:23 +00:00
localPortName := ""
protocol := "tcp"
switch proxyType {
case "stcp":
localPortName = framework.TCPEchoServerPort
protocol = "tcp"
case "sudp":
localPortName = framework.UDPEchoServerPort
protocol = "udp"
2023-05-28 15:06:35 +00:00
case "xtcp":
localPortName = framework.TCPEchoServerPort
protocol = "tcp"
2023-07-20 14:32:32 +00:00
ginkgo.Skip("stun server is not stable")
2020-09-07 06:57:23 +00:00
}
correctSK := "abc"
wrongSK := "123"
getProxyServerConf := func(proxyName string, extra string) string {
return fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
[[proxies]]
name = "%s"
type = "%s"
secretKey = "%s"
localPort = {{ .%s }}
2020-09-07 06:57:23 +00:00
`+extra, proxyName, proxyType, correctSK, localPortName)
}
getProxyVisitorConf := func(proxyName string, portName, visitorSK, extra string) string {
2023-06-04 12:11:07 +00:00
return fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
[[visitors]]
name = "%s"
type = "%s"
serverName = "%s"
secretKey = "%s"
bindPort = {{ .%s }}
2020-09-07 06:57:23 +00:00
`+extra, proxyName, proxyType, proxyName, visitorSK, portName)
}
tests := []struct {
proxyName string
bindPortName string
visitorSK string
commonExtraConfig string
proxyExtraConfig string
visitorExtraConfig string
expectError bool
deployUser2Client bool
// skipXTCP is used to skip xtcp test case
skipXTCP bool
2020-09-07 06:57:23 +00:00
}{
{
proxyName: "normal",
2021-03-31 08:57:39 +00:00
bindPortName: port.GenName("Normal"),
2020-09-07 06:57:23 +00:00
visitorSK: correctSK,
skipXTCP: true,
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-encryption",
bindPortName: port.GenName("WithEncryption"),
visitorSK: correctSK,
2023-09-13 08:32:39 +00:00
commonExtraConfig: "transport.useEncryption = true",
skipXTCP: true,
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-compression",
bindPortName: port.GenName("WithCompression"),
visitorSK: correctSK,
2023-09-13 08:32:39 +00:00
commonExtraConfig: "transport.useCompression = true",
skipXTCP: true,
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-encryption-and-compression",
2021-03-31 08:57:39 +00:00
bindPortName: port.GenName("WithEncryptionAndCompression"),
2020-09-07 06:57:23 +00:00
visitorSK: correctSK,
commonExtraConfig: `
2023-09-13 08:32:39 +00:00
transport.useEncryption = true
transport.useCompression = true
2020-09-07 06:57:23 +00:00
`,
2023-07-20 14:32:32 +00:00
skipXTCP: true,
2020-09-07 06:57:23 +00:00
},
{
proxyName: "with-error-sk",
2021-03-31 08:57:39 +00:00
bindPortName: port.GenName("WithErrorSK"),
2020-09-07 06:57:23 +00:00
visitorSK: wrongSK,
expectError: true,
},
{
proxyName: "allowed-user",
bindPortName: port.GenName("AllowedUser"),
visitorSK: correctSK,
2023-09-13 08:32:39 +00:00
proxyExtraConfig: `allowUsers = ["another", "user2"]`,
visitorExtraConfig: `serverUser = "user1"`,
deployUser2Client: true,
},
{
proxyName: "not-allowed-user",
bindPortName: port.GenName("NotAllowedUser"),
visitorSK: correctSK,
2023-09-13 08:32:39 +00:00
proxyExtraConfig: `allowUsers = ["invalid"]`,
visitorExtraConfig: `serverUser = "user1"`,
expectError: true,
},
{
proxyName: "allow-all",
bindPortName: port.GenName("AllowAll"),
visitorSK: correctSK,
2023-09-13 08:32:39 +00:00
proxyExtraConfig: `allowUsers = ["*"]`,
visitorExtraConfig: `serverUser = "user1"`,
deployUser2Client: true,
},
2020-09-07 06:57:23 +00:00
}
// build all client config
for _, test := range tests {
clientServerConf += getProxyServerConf(test.proxyName, test.commonExtraConfig+"\n"+test.proxyExtraConfig) + "\n"
2020-09-07 06:57:23 +00:00
}
for _, test := range tests {
config := getProxyVisitorConf(
test.proxyName, test.bindPortName, test.visitorSK, test.commonExtraConfig+"\n"+test.visitorExtraConfig,
) + "\n"
if test.deployUser2Client {
clientUser2VisitorConf += config
} else {
clientVisitorConf += config
}
2020-09-07 06:57:23 +00:00
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientServerConf, clientVisitorConf, clientUser2VisitorConf})
2020-09-07 06:57:23 +00:00
for _, test := range tests {
timeout := time.Second
if t == "xtcp" {
if test.skipXTCP {
continue
}
timeout = 10 * time.Second
}
2021-03-31 08:57:39 +00:00
framework.NewRequestExpect(f).
2023-05-28 15:06:35 +00:00
RequestModify(func(r *request.Request) {
r.Timeout(timeout)
2023-05-28 15:06:35 +00:00
}).
2021-06-18 08:48:36 +00:00
Protocol(protocol).
2021-03-31 08:57:39 +00:00
PortName(test.bindPortName).
Explain(test.proxyName).
ExpectError(test.expectError).
Ensure()
2020-09-07 06:57:23 +00:00
}
})
}
})
2021-03-31 08:57:39 +00:00
2022-08-28 17:02:53 +00:00
ginkgo.Describe("TCPMUX", func() {
ginkgo.It("Type tcpmux", func() {
2021-03-31 08:57:39 +00:00
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig
tcpmuxHTTPConnectPortName := port.GenName("TCPMUX")
serverConf += fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
tcpmuxHTTPConnectPort = {{ .%s }}
2021-03-31 08:57:39 +00:00
`, tcpmuxHTTPConnectPortName)
getProxyConf := func(proxyName string, extra string) string {
return fmt.Sprintf(`
2023-09-13 08:32:39 +00:00
[[proxies]]
name = "%s"
type = "tcpmux"
multiplexer = "httpconnect"
localPort = {{ .%s }}
customDomains = ["%s"]
`+extra, proxyName, port.GenName(proxyName), proxyName)
2021-03-31 08:57:39 +00:00
}
tests := []struct {
proxyName string
extraConfig string
}{
{
proxyName: "normal",
},
{
proxyName: "with-encryption",
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useEncryption = true",
2021-03-31 08:57:39 +00:00
},
{
proxyName: "with-compression",
2023-09-13 08:32:39 +00:00
extraConfig: "transport.useCompression = true",
2021-03-31 08:57:39 +00:00
},
{
proxyName: "with-encryption-and-compression",
extraConfig: `
2023-09-13 08:32:39 +00:00
transport.useEncryption = true
transport.useCompression = true
2021-03-31 08:57:39 +00:00
`,
},
}
// build all client config
for _, test := range tests {
clientConf += getProxyConf(test.proxyName, test.extraConfig) + "\n"
2021-06-18 08:48:36 +00:00
localServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(f.AllocPort()), streamserver.WithRespContent([]byte(test.proxyName)))
f.RunServer(port.GenName(test.proxyName), localServer)
2021-03-31 08:57:39 +00:00
}
2021-03-31 08:57:39 +00:00
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})
// Request without HTTP connect should get error
framework.NewRequestExpect(f).
PortName(tcpmuxHTTPConnectPortName).
ExpectError(true).
Explain("request without HTTP connect expect error").
Ensure()
proxyURL := fmt.Sprintf("http://127.0.0.1:%d", f.PortByName(tcpmuxHTTPConnectPortName))
// Request with incorrect connect hostname
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
2021-06-18 08:48:36 +00:00
r.Addr("invalid").Proxy(proxyURL)
2021-03-31 08:57:39 +00:00
}).ExpectError(true).Explain("request without HTTP connect expect error").Ensure()
// Request with correct connect hostname
for _, test := range tests {
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
2021-06-18 08:48:36 +00:00
r.Addr(test.proxyName).Proxy(proxyURL)
}).ExpectResp([]byte(test.proxyName)).Explain(test.proxyName).Ensure()
2021-03-31 08:57:39 +00:00
}
})
})
2020-09-07 06:57:23 +00:00
})