type http/tcpmux proxy support route_by_http_user, tcpmux support passthourgh mode (#2932)

This commit is contained in:
fatedier
2022-05-26 23:57:30 +08:00
committed by GitHub
parent bd89eaba2f
commit 4af85da0c2
22 changed files with 606 additions and 283 deletions

View File

@@ -10,7 +10,6 @@ import (
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
"github.com/fatedier/frp/test/e2e/pkg/request"
"github.com/fatedier/frp/test/e2e/pkg/utils"
"github.com/gorilla/websocket"
. "github.com/onsi/ginkgo"
@@ -59,28 +58,83 @@ var _ = Describe("[Feature: HTTP]", func() {
f.RunProcesses([]string{serverConf}, []string{clientConf})
// foo path
framework.NewRequestExpect(f).Explain("foo path").Port(vhostHTTPPort).
tests := []struct {
path string
expectResp string
desc string
}{
{path: "/foo", expectResp: "foo", desc: "foo path"},
{path: "/bar", expectResp: "bar", desc: "bar path"},
{path: "/other", expectResp: "foo", desc: "other path"},
}
for _, test := range tests {
framework.NewRequestExpect(f).Explain(test.desc).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com").HTTPPath(test.path)
}).
ExpectResp([]byte(test.expectResp)).
Ensure()
}
})
It("HTTP route by HTTP user", func() {
vhostHTTPPort := f.AllocPort()
serverConf := getDefaultServerConf(vhostHTTPPort)
fooPort := f.AllocPort()
f.RunServer("", newHTTPServer(fooPort, "foo"))
barPort := f.AllocPort()
f.RunServer("", newHTTPServer(barPort, "bar"))
otherPort := f.AllocPort()
f.RunServer("", newHTTPServer(otherPort, "other"))
clientConf := consts.DefaultClientConfig
clientConf += fmt.Sprintf(`
[foo]
type = http
local_port = %d
custom_domains = normal.example.com
route_by_http_user = user1
[bar]
type = http
local_port = %d
custom_domains = normal.example.com
route_by_http_user = user2
[catchAll]
type = http
local_port = %d
custom_domains = normal.example.com
`, fooPort, barPort, otherPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
// user1
framework.NewRequestExpect(f).Explain("user1").Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com").HTTPPath("/foo")
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("user1", "")
}).
ExpectResp([]byte("foo")).
Ensure()
// bar path
framework.NewRequestExpect(f).Explain("bar path").Port(vhostHTTPPort).
// user2
framework.NewRequestExpect(f).Explain("user2").Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com").HTTPPath("/bar")
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("user2", "")
}).
ExpectResp([]byte("bar")).
Ensure()
// other path
framework.NewRequestExpect(f).Explain("other path").Port(vhostHTTPPort).
// other user
framework.NewRequestExpect(f).Explain("other user").Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com").HTTPPath("/other")
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("user3", "")
}).
ExpectResp([]byte("foo")).
ExpectResp([]byte("other")).
Ensure()
})
@@ -110,18 +164,14 @@ var _ = Describe("[Feature: HTTP]", func() {
// set incorrect auth header
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com").HTTPHeaders(map[string]string{
"Authorization": utils.BasicAuth("test", "invalid"),
})
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("test", "invalid")
}).
Ensure(framework.ExpectResponseCode(401))
// set correct auth header
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com").HTTPHeaders(map[string]string{
"Authorization": utils.BasicAuth("test", "test"),
})
r.HTTP().HTTPHost("normal.example.com").HTTPAuth("test", "test")
}).
Ensure()
})

View File

@@ -60,7 +60,7 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
ExpectNoError(err)
time.Sleep(500 * time.Millisecond)
}
time.Sleep(500 * time.Millisecond)
time.Sleep(time.Second)
return currentServerProcesses, currentClientProcesses
}

View File

@@ -13,6 +13,7 @@ import (
"time"
"github.com/fatedier/frp/test/e2e/pkg/rpc"
"github.com/fatedier/frp/test/e2e/pkg/utils"
libdial "github.com/fatedier/golib/net/dial"
)
@@ -20,10 +21,11 @@ type Request struct {
protocol string
// for all protocol
addr string
port int
body []byte
timeout time.Duration
addr string
port int
body []byte
timeout time.Duration
resolver *net.Resolver
// for http or https
method string
@@ -32,6 +34,8 @@ type Request struct {
headers map[string]string
tlsConfig *tls.Config
authValue string
proxyURL string
}
@@ -40,8 +44,9 @@ func New() *Request {
protocol: "tcp",
addr: "127.0.0.1",
method: "GET",
path: "/",
method: "GET",
path: "/",
headers: map[string]string{},
}
}
@@ -108,6 +113,11 @@ func (r *Request) HTTPHeaders(headers map[string]string) *Request {
return r
}
func (r *Request) HTTPAuth(user, password string) *Request {
r.authValue = utils.BasicAuth(user, password)
return r
}
func (r *Request) TLSConfig(tlsConfig *tls.Config) *Request {
r.tlsConfig = tlsConfig
return r
@@ -123,6 +133,11 @@ func (r *Request) Body(content []byte) *Request {
return r
}
func (r *Request) Resolver(resolver *net.Resolver) *Request {
r.resolver = resolver
return r
}
func (r *Request) Do() (*Response, error) {
var (
conn net.Conn
@@ -150,11 +165,12 @@ func (r *Request) Do() (*Response, error) {
return nil, err
}
} else {
dialer := &net.Dialer{Resolver: r.resolver}
switch r.protocol {
case "tcp":
conn, err = net.Dial("tcp", addr)
conn, err = dialer.Dial("tcp", addr)
case "udp":
conn, err = net.Dial("udp", addr)
conn, err = dialer.Dial("udp", addr)
default:
return nil, fmt.Errorf("invalid protocol")
}
@@ -198,11 +214,15 @@ func (r *Request) sendHTTPRequest(method, urlstr string, host string, headers ma
for k, v := range headers {
req.Header.Set(k, v)
}
if r.authValue != "" {
req.Header.Set("Authorization", r.authValue)
}
tr := &http.Transport{
DialContext: (&net.Dialer{
Timeout: time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
Resolver: r.resolver,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,

View File

@@ -12,7 +12,6 @@ import (
"github.com/fatedier/frp/test/e2e/pkg/cert"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"
"github.com/fatedier/frp/test/e2e/pkg/utils"
. "github.com/onsi/ginkgo"
)
@@ -181,9 +180,7 @@ var _ = Describe("[Feature: Client-Plugins]", func() {
// from http proxy with auth
framework.NewRequestExpect(f).Request(
framework.NewHTTPRequest().HTTPHost("other.example.com").HTTPPath("/test_static_file").Port(vhostPort).HTTPHeaders(map[string]string{
"Authorization": utils.BasicAuth("abc", "123"),
}),
framework.NewHTTPRequest().HTTPHost("other.example.com").HTTPPath("/test_static_file").Port(vhostPort).HTTPAuth("abc", "123"),
).ExpectResp([]byte("foo")).Ensure()
})