mirror of https://github.com/fatedier/frp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.7 KiB
223 lines
5.7 KiB
package basic |
|
|
|
import ( |
|
"bufio" |
|
"fmt" |
|
"net" |
|
"net/http" |
|
|
|
"github.com/onsi/ginkgo/v2" |
|
|
|
httppkg "github.com/fatedier/frp/pkg/util/http" |
|
"github.com/fatedier/frp/test/e2e/framework" |
|
"github.com/fatedier/frp/test/e2e/framework/consts" |
|
"github.com/fatedier/frp/test/e2e/mock/server/streamserver" |
|
"github.com/fatedier/frp/test/e2e/pkg/request" |
|
"github.com/fatedier/frp/test/e2e/pkg/rpc" |
|
) |
|
|
|
var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() { |
|
f := framework.NewDefaultFramework() |
|
|
|
getDefaultServerConf := func(httpconnectPort int) string { |
|
conf := consts.DefaultServerConfig + ` |
|
tcpmuxHTTPConnectPort = %d |
|
` |
|
return fmt.Sprintf(conf, httpconnectPort) |
|
} |
|
newServer := func(port int, respContent string) *streamserver.Server { |
|
return streamserver.New( |
|
streamserver.TCP, |
|
streamserver.WithBindPort(port), |
|
streamserver.WithRespContent([]byte(respContent)), |
|
) |
|
} |
|
|
|
proxyURLWithAuth := func(username, password string, port int) string { |
|
if username == "" { |
|
return fmt.Sprintf("http://127.0.0.1:%d", port) |
|
} |
|
return fmt.Sprintf("http://%s:%s@127.0.0.1:%d", username, password, port) |
|
} |
|
|
|
ginkgo.It("Route by HTTP user", func() { |
|
vhostPort := f.AllocPort() |
|
serverConf := getDefaultServerConf(vhostPort) |
|
|
|
fooPort := f.AllocPort() |
|
f.RunServer("", newServer(fooPort, "foo")) |
|
|
|
barPort := f.AllocPort() |
|
f.RunServer("", newServer(barPort, "bar")) |
|
|
|
otherPort := f.AllocPort() |
|
f.RunServer("", newServer(otherPort, "other")) |
|
|
|
clientConf := consts.DefaultClientConfig |
|
clientConf += fmt.Sprintf(` |
|
[[proxies]] |
|
name = "foo" |
|
type = "tcpmux" |
|
multiplexer = "httpconnect" |
|
localPort = %d |
|
customDomains = ["normal.example.com"] |
|
routeByHTTPUser = "user1" |
|
|
|
[[proxies]] |
|
name = "bar" |
|
type = "tcpmux" |
|
multiplexer = "httpconnect" |
|
localPort = %d |
|
customDomains = ["normal.example.com"] |
|
routeByHTTPUser = "user2" |
|
|
|
[[proxies]] |
|
name = "catchAll" |
|
type = "tcpmux" |
|
multiplexer = "httpconnect" |
|
localPort = %d |
|
customDomains = ["normal.example.com"] |
|
`, fooPort, barPort, otherPort) |
|
|
|
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
|
|
|
// user1 |
|
framework.NewRequestExpect(f).Explain("user1"). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("user1", "", vhostPort)) |
|
}). |
|
ExpectResp([]byte("foo")). |
|
Ensure() |
|
|
|
// user2 |
|
framework.NewRequestExpect(f).Explain("user2"). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("user2", "", vhostPort)) |
|
}). |
|
ExpectResp([]byte("bar")). |
|
Ensure() |
|
|
|
// other user |
|
framework.NewRequestExpect(f).Explain("other user"). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("user3", "", vhostPort)) |
|
}). |
|
ExpectResp([]byte("other")). |
|
Ensure() |
|
}) |
|
|
|
ginkgo.It("Proxy auth", func() { |
|
vhostPort := f.AllocPort() |
|
serverConf := getDefaultServerConf(vhostPort) |
|
|
|
fooPort := f.AllocPort() |
|
f.RunServer("", newServer(fooPort, "foo")) |
|
|
|
clientConf := consts.DefaultClientConfig |
|
clientConf += fmt.Sprintf(` |
|
[[proxies]] |
|
name = "test" |
|
type = "tcpmux" |
|
multiplexer = "httpconnect" |
|
localPort = %d |
|
customDomains = ["normal.example.com"] |
|
httpUser = "test" |
|
httpPassword = "test" |
|
`, fooPort) |
|
|
|
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
|
|
|
// not set auth header |
|
framework.NewRequestExpect(f).Explain("no auth"). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("", "", vhostPort)) |
|
}). |
|
ExpectError(true). |
|
Ensure() |
|
|
|
// set incorrect auth header |
|
framework.NewRequestExpect(f).Explain("incorrect auth"). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("test", "invalid", vhostPort)) |
|
}). |
|
ExpectError(true). |
|
Ensure() |
|
|
|
// set correct auth header |
|
framework.NewRequestExpect(f).Explain("correct auth"). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("test", "test", vhostPort)) |
|
}). |
|
ExpectResp([]byte("foo")). |
|
Ensure() |
|
}) |
|
|
|
ginkgo.It("TCPMux Passthrough", func() { |
|
vhostPort := f.AllocPort() |
|
serverConf := getDefaultServerConf(vhostPort) |
|
serverConf += ` |
|
tcpmuxPassthrough = true |
|
` |
|
|
|
var ( |
|
respErr error |
|
connectRequestHost string |
|
) |
|
newServer := func(port int) *streamserver.Server { |
|
return streamserver.New( |
|
streamserver.TCP, |
|
streamserver.WithBindPort(port), |
|
streamserver.WithCustomHandler(func(conn net.Conn) { |
|
defer conn.Close() |
|
|
|
// read HTTP CONNECT request |
|
bufioReader := bufio.NewReader(conn) |
|
req, err := http.ReadRequest(bufioReader) |
|
if err != nil { |
|
respErr = err |
|
return |
|
} |
|
connectRequestHost = req.Host |
|
|
|
// return ok response |
|
res := httppkg.OkResponse() |
|
if res.Body != nil { |
|
defer res.Body.Close() |
|
} |
|
_ = res.Write(conn) |
|
|
|
buf, err := rpc.ReadBytes(conn) |
|
if err != nil { |
|
respErr = err |
|
return |
|
} |
|
_, _ = rpc.WriteBytes(conn, buf) |
|
}), |
|
) |
|
} |
|
|
|
localPort := f.AllocPort() |
|
f.RunServer("", newServer(localPort)) |
|
|
|
clientConf := consts.DefaultClientConfig |
|
clientConf += fmt.Sprintf(` |
|
[[proxies]] |
|
name = "test" |
|
type = "tcpmux" |
|
multiplexer = "httpconnect" |
|
localPort = %d |
|
customDomains = ["normal.example.com"] |
|
`, localPort) |
|
|
|
f.RunProcesses([]string{serverConf}, []string{clientConf}) |
|
|
|
framework.NewRequestExpect(f). |
|
RequestModify(func(r *request.Request) { |
|
r.Addr("normal.example.com").Proxy(proxyURLWithAuth("", "", vhostPort)).Body([]byte("frp")) |
|
}). |
|
ExpectResp([]byte("frp")). |
|
Ensure() |
|
framework.ExpectNoError(respErr) |
|
framework.ExpectEqualValues(connectRequestHost, "normal.example.com") |
|
}) |
|
})
|
|
|