123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- package plugin
- import (
- "crypto/tls"
- "fmt"
- "net/http"
- "strconv"
- "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/pkg/cert"
- "github.com/fatedier/frp/test/e2e/pkg/port"
- "github.com/fatedier/frp/test/e2e/pkg/request"
- )
- var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
- f := framework.NewDefaultFramework()
- ginkgo.Describe("UnixDomainSocket", func() {
- ginkgo.It("Expose a unix domain socket echo server", func() {
- serverConf := consts.DefaultServerConfig
- clientConf := consts.DefaultClientConfig
- getProxyConf := func(proxyName string, portName string, extra string) string {
- return fmt.Sprintf(`
- [[proxies]]
- name = "%s"
- type = "tcp"
- remotePort = {{ .%s }}
- `+extra, proxyName, portName) + fmt.Sprintf(`
- [proxies.plugin]
- type = "unix_domain_socket"
- unixPath = "{{ .%s }}"
- `, framework.UDSEchoServerAddr)
- }
- tests := []struct {
- proxyName string
- portName string
- extraConfig string
- }{
- {
- proxyName: "normal",
- portName: port.GenName("Normal"),
- },
- {
- proxyName: "with-encryption",
- portName: port.GenName("WithEncryption"),
- extraConfig: "transport.useEncryption = true",
- },
- {
- proxyName: "with-compression",
- portName: port.GenName("WithCompression"),
- extraConfig: "transport.useCompression = true",
- },
- {
- proxyName: "with-encryption-and-compression",
- portName: port.GenName("WithEncryptionAndCompression"),
- extraConfig: `
- transport.useEncryption = true
- transport.useCompression = true
- `,
- },
- }
- // 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 {
- framework.NewRequestExpect(f).Port(f.PortByName(test.portName)).Ensure()
- }
- })
- })
- ginkgo.It("http_proxy", func() {
- serverConf := consts.DefaultServerConfig
- clientConf := consts.DefaultClientConfig
- remotePort := f.AllocPort()
- clientConf += fmt.Sprintf(`
- [[proxies]]
- name = "tcp"
- type = "tcp"
- remotePort = %d
- [proxies.plugin]
- type = "http_proxy"
- httpUser = "abc"
- httpPassword = "123"
- `, remotePort)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- // http proxy, no auth info
- framework.NewRequestExpect(f).PortName(framework.HTTPSimpleServerPort).RequestModify(func(r *request.Request) {
- r.HTTP().Proxy("http://127.0.0.1:" + strconv.Itoa(remotePort))
- }).Ensure(framework.ExpectResponseCode(407))
- // http proxy, correct auth
- framework.NewRequestExpect(f).PortName(framework.HTTPSimpleServerPort).RequestModify(func(r *request.Request) {
- r.HTTP().Proxy("http://abc:123@127.0.0.1:" + strconv.Itoa(remotePort))
- }).Ensure()
- // connect TCP server by CONNECT method
- framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
- r.TCP().Proxy("http://abc:123@127.0.0.1:" + strconv.Itoa(remotePort))
- })
- })
- ginkgo.It("socks5 proxy", func() {
- serverConf := consts.DefaultServerConfig
- clientConf := consts.DefaultClientConfig
- remotePort := f.AllocPort()
- clientConf += fmt.Sprintf(`
- [[proxies]]
- name = "tcp"
- type = "tcp"
- remotePort = %d
- [proxies.plugin]
- type = "socks5"
- username = "abc"
- password = "123"
- `, remotePort)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- // http proxy, no auth info
- framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
- r.TCP().Proxy("socks5://127.0.0.1:" + strconv.Itoa(remotePort))
- }).ExpectError(true).Ensure()
- // http proxy, correct auth
- framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
- r.TCP().Proxy("socks5://abc:123@127.0.0.1:" + strconv.Itoa(remotePort))
- }).Ensure()
- })
- ginkgo.It("static_file", func() {
- vhostPort := f.AllocPort()
- serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
- vhostHTTPPort = %d
- `, vhostPort)
- clientConf := consts.DefaultClientConfig
- remotePort := f.AllocPort()
- f.WriteTempFile("test_static_file", "foo")
- clientConf += fmt.Sprintf(`
- [[proxies]]
- name = "tcp"
- type = "tcp"
- remotePort = %d
- [proxies.plugin]
- type = "static_file"
- localPath = "%s"
- [[proxies]]
- name = "http"
- type = "http"
- customDomains = ["example.com"]
- [proxies.plugin]
- type = "static_file"
- localPath = "%s"
- [[proxies]]
- name = "http-with-auth"
- type = "http"
- customDomains = ["other.example.com"]
- [proxies.plugin]
- type = "static_file"
- localPath = "%s"
- httpUser = "abc"
- httpPassword = "123"
- `, remotePort, f.TempDirectory, f.TempDirectory, f.TempDirectory)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- // from tcp proxy
- framework.NewRequestExpect(f).Request(
- framework.NewHTTPRequest().HTTPPath("/test_static_file").Port(remotePort),
- ).ExpectResp([]byte("foo")).Ensure()
- // from http proxy without auth
- framework.NewRequestExpect(f).Request(
- framework.NewHTTPRequest().HTTPHost("example.com").HTTPPath("/test_static_file").Port(vhostPort),
- ).ExpectResp([]byte("foo")).Ensure()
- // from http proxy with auth
- framework.NewRequestExpect(f).Request(
- framework.NewHTTPRequest().HTTPHost("other.example.com").HTTPPath("/test_static_file").Port(vhostPort).HTTPAuth("abc", "123"),
- ).ExpectResp([]byte("foo")).Ensure()
- })
- ginkgo.It("http2https", func() {
- serverConf := consts.DefaultServerConfig
- vhostHTTPPort := f.AllocPort()
- serverConf += fmt.Sprintf(`
- vhostHTTPPort = %d
- `, vhostHTTPPort)
- localPort := f.AllocPort()
- clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
- [[proxies]]
- name = "http2https"
- type = "http"
- customDomains = ["example.com"]
- [proxies.plugin]
- type = "http2https"
- localAddr = "127.0.0.1:%d"
- `, localPort)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- tlsConfig, err := transport.NewServerTLSConfig("", "", "")
- framework.ExpectNoError(err)
- localServer := httpserver.New(
- httpserver.WithBindPort(localPort),
- httpserver.WithTLSConfig(tlsConfig),
- httpserver.WithResponse([]byte("test")),
- )
- f.RunServer("", localServer)
- framework.NewRequestExpect(f).
- Port(vhostHTTPPort).
- RequestModify(func(r *request.Request) {
- r.HTTP().HTTPHost("example.com")
- }).
- ExpectResp([]byte("test")).
- Ensure()
- })
- ginkgo.It("https2http", func() {
- generator := &cert.SelfSignedCertGenerator{}
- artifacts, err := generator.Generate("example.com")
- framework.ExpectNoError(err)
- crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
- keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
- serverConf := consts.DefaultServerConfig
- vhostHTTPSPort := f.AllocPort()
- serverConf += fmt.Sprintf(`
- vhostHTTPSPort = %d
- `, vhostHTTPSPort)
- localPort := f.AllocPort()
- clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
- [[proxies]]
- name = "https2http"
- type = "https"
- customDomains = ["example.com"]
- [proxies.plugin]
- type = "https2http"
- localAddr = "127.0.0.1:%d"
- crtPath = "%s"
- keyPath = "%s"
- `, localPort, crtPath, keyPath)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- localServer := httpserver.New(
- httpserver.WithBindPort(localPort),
- httpserver.WithResponse([]byte("test")),
- )
- f.RunServer("", localServer)
- framework.NewRequestExpect(f).
- Port(vhostHTTPSPort).
- RequestModify(func(r *request.Request) {
- r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
- ServerName: "example.com",
- InsecureSkipVerify: true,
- })
- }).
- ExpectResp([]byte("test")).
- Ensure()
- })
- ginkgo.It("https2https", func() {
- generator := &cert.SelfSignedCertGenerator{}
- artifacts, err := generator.Generate("example.com")
- framework.ExpectNoError(err)
- crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
- keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
- serverConf := consts.DefaultServerConfig
- vhostHTTPSPort := f.AllocPort()
- serverConf += fmt.Sprintf(`
- vhostHTTPSPort = %d
- `, vhostHTTPSPort)
- localPort := f.AllocPort()
- clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
- [[proxies]]
- name = "https2https"
- type = "https"
- customDomains = ["example.com"]
- [proxies.plugin]
- type = "https2https"
- localAddr = "127.0.0.1:%d"
- crtPath = "%s"
- keyPath = "%s"
- `, localPort, crtPath, keyPath)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- tlsConfig, err := transport.NewServerTLSConfig("", "", "")
- framework.ExpectNoError(err)
- localServer := httpserver.New(
- httpserver.WithBindPort(localPort),
- httpserver.WithResponse([]byte("test")),
- httpserver.WithTLSConfig(tlsConfig),
- )
- f.RunServer("", localServer)
- framework.NewRequestExpect(f).
- Port(vhostHTTPSPort).
- RequestModify(func(r *request.Request) {
- r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
- ServerName: "example.com",
- InsecureSkipVerify: true,
- })
- }).
- ExpectResp([]byte("test")).
- Ensure()
- })
- ginkgo.Describe("http2http", func() {
- ginkgo.It("host header rewrite", func() {
- serverConf := consts.DefaultServerConfig
- localPort := f.AllocPort()
- remotePort := f.AllocPort()
- clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
- [[proxies]]
- name = "http2http"
- type = "tcp"
- remotePort = %d
- [proxies.plugin]
- type = "http2http"
- localAddr = "127.0.0.1:%d"
- hostHeaderRewrite = "rewrite.test.com"
- `, remotePort, localPort)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- localServer := httpserver.New(
- httpserver.WithBindPort(localPort),
- httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- _, _ = w.Write([]byte(req.Host))
- })),
- )
- f.RunServer("", localServer)
- framework.NewRequestExpect(f).
- Port(remotePort).
- RequestModify(func(r *request.Request) {
- r.HTTP().HTTPHost("example.com")
- }).
- ExpectResp([]byte("rewrite.test.com")).
- Ensure()
- })
- ginkgo.It("set request header", func() {
- serverConf := consts.DefaultServerConfig
- localPort := f.AllocPort()
- remotePort := f.AllocPort()
- clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
- [[proxies]]
- name = "http2http"
- type = "tcp"
- remotePort = %d
- [proxies.plugin]
- type = "http2http"
- localAddr = "127.0.0.1:%d"
- requestHeaders.set.x-from-where = "frp"
- `, remotePort, localPort)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- localServer := httpserver.New(
- httpserver.WithBindPort(localPort),
- httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- _, _ = w.Write([]byte(req.Header.Get("x-from-where")))
- })),
- )
- f.RunServer("", localServer)
- framework.NewRequestExpect(f).
- Port(remotePort).
- RequestModify(func(r *request.Request) {
- r.HTTP().HTTPHost("example.com")
- }).
- ExpectResp([]byte("frp")).
- Ensure()
- })
- })
- ginkgo.It("tls2raw", func() {
- generator := &cert.SelfSignedCertGenerator{}
- artifacts, err := generator.Generate("example.com")
- framework.ExpectNoError(err)
- crtPath := f.WriteTempFile("tls2raw_server.crt", string(artifacts.Cert))
- keyPath := f.WriteTempFile("tls2raw_server.key", string(artifacts.Key))
- serverConf := consts.DefaultServerConfig
- vhostHTTPSPort := f.AllocPort()
- serverConf += fmt.Sprintf(`
- vhostHTTPSPort = %d
- `, vhostHTTPSPort)
- localPort := f.AllocPort()
- clientConf := consts.DefaultClientConfig + fmt.Sprintf(`
- [[proxies]]
- name = "tls2raw-test"
- type = "https"
- customDomains = ["example.com"]
- [proxies.plugin]
- type = "tls2raw"
- localAddr = "127.0.0.1:%d"
- crtPath = "%s"
- keyPath = "%s"
- `, localPort, crtPath, keyPath)
- f.RunProcesses([]string{serverConf}, []string{clientConf})
- localServer := httpserver.New(
- httpserver.WithBindPort(localPort),
- httpserver.WithResponse([]byte("test")),
- )
- f.RunServer("", localServer)
- framework.NewRequestExpect(f).
- Port(vhostHTTPSPort).
- RequestModify(func(r *request.Request) {
- r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
- ServerName: "example.com",
- InsecureSkipVerify: true,
- })
- }).
- ExpectResp([]byte("test")).
- Ensure()
- })
- })
|