From e5d3783ed7dd5d50cf714e298f9cbad6f206f576 Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Thu, 1 Mar 2018 14:22:33 +0100 Subject: [PATCH] consume config in dialer and hub --- transport/internet/http/config.go | 33 ++++++++++++++++++++++++++++ transport/internet/http/dialer.go | 10 +++++++-- transport/internet/http/http_test.go | 15 +++++++++---- transport/internet/http/hub.go | 21 ++++++++++++++++++ 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/transport/internet/http/config.go b/transport/internet/http/config.go index 7bdb71fc..a746b595 100644 --- a/transport/internet/http/config.go +++ b/transport/internet/http/config.go @@ -2,9 +2,42 @@ package http import ( "v2ray.com/core/common" + "v2ray.com/core/common/dice" "v2ray.com/core/transport/internet" ) +func (c *Config) getHosts() []string { + if len(c.Host) == 0 { + return []string{"www.example.com"} + } + return c.Host +} + +func (c *Config) isValidHost(host string) bool { + hosts := c.getHosts() + for _, h := range hosts { + if h == host { + return true + } + } + return false +} + +func (c *Config) getRandomHost() string { + hosts := c.getHosts() + return hosts[dice.Roll(len(hosts))] +} + +func (c *Config) getNormalizedPath() string { + if len(c.Path) == 0 { + return "/" + } + if c.Path[0] != '/' { + return "/" + c.Path + } + return c.Path +} + func init() { common.Must(internet.RegisterProtocolConfigCreator(internet.TransportProtocol_HTTP, func() interface{} { return new(Config) diff --git a/transport/internet/http/dialer.go b/transport/internet/http/dialer.go index 0d029853..025e314d 100644 --- a/transport/internet/http/dialer.go +++ b/transport/internet/http/dialer.go @@ -68,6 +68,12 @@ func getHTTPClient(ctx context.Context, dest net.Destination) (*http.Client, err // Dial dials a new TCP connection to the given destination. func Dial(ctx context.Context, dest net.Destination) (internet.Connection, error) { + rawSettings := internet.TransportSettingsFromContext(ctx) + httpSettings, ok := rawSettings.(*Config) + if !ok { + return nil, newError("HTTP config is not set.").AtError() + } + client, err := getHTTPClient(ctx, dest) if err != nil { return nil, err @@ -76,12 +82,12 @@ func Dial(ctx context.Context, dest net.Destination) (internet.Connection, error preader, pwriter := io.Pipe() request := &http.Request{ Method: "PUT", - Host: "www.v2ray.com", + Host: httpSettings.getRandomHost(), Body: preader, URL: &url.URL{ Scheme: "https", Host: dest.NetAddr(), - Path: "/", + Path: httpSettings.getNormalizedPath(), }, Proto: "HTTP/2", ProtoMajor: 2, diff --git a/transport/internet/http/http_test.go b/transport/internet/http/http_test.go index 03b38dda..acbe6212 100644 --- a/transport/internet/http/http_test.go +++ b/transport/internet/http/http_test.go @@ -22,9 +22,13 @@ func TestHTTPConnection(t *testing.T) { port := tcp.PickPort() - listener, err := Listen(internet.ContextWithSecuritySettings(context.Background(), &tls.Config{ + lctx := context.Background() + lctx = internet.ContextWithSecuritySettings(lctx, &tls.Config{ Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()}, - }), net.LocalHostIP, port, func(conn internet.Connection) { + }) + lctx = internet.ContextWithTransportSettings(lctx, &Config{}) + + listener, err := Listen(lctx, net.LocalHostIP, port, func(conn internet.Connection) { go func() { defer conn.Close() @@ -47,10 +51,13 @@ func TestHTTPConnection(t *testing.T) { time.Sleep(time.Second) - conn, err := Dial(internet.ContextWithSecuritySettings(context.Background(), &tls.Config{ + dctx := context.Background() + dctx = internet.ContextWithSecuritySettings(dctx, &tls.Config{ ServerName: "www.v2ray.com", AllowInsecure: true, - }), net.TCPDestination(net.LocalHostIP, port)) + }) + dctx = internet.ContextWithTransportSettings(dctx, &Config{}) + conn, err := Dial(dctx, net.TCPDestination(net.LocalHostIP, port)) assert(err, IsNil) defer conn.Close() diff --git a/transport/internet/http/hub.go b/transport/internet/http/hub.go index 5005a22c..250ccb33 100644 --- a/transport/internet/http/hub.go +++ b/transport/internet/http/hub.go @@ -4,6 +4,7 @@ import ( "context" "io" "net/http" + "strings" "v2ray.com/core/common" "v2ray.com/core/common/net" @@ -17,6 +18,7 @@ type Listener struct { server *http.Server handler internet.ConnHandler local net.Addr + config Config } func (l *Listener) Addr() net.Addr { @@ -40,6 +42,18 @@ func (fw flushWriter) Write(p []byte) (n int, err error) { } func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request) { + host := request.Host + if !l.config.isValidHost(host) { + writer.WriteHeader(404) + return + } + path := l.config.getNormalizedPath() + if !strings.HasPrefix(request.URL.Path, path) { + writer.WriteHeader(404) + return + } + + writer.Header().Set("Cache-Control", "no-store") writer.WriteHeader(200) if f, ok := writer.(http.Flusher); ok { f.Flush() @@ -56,12 +70,19 @@ func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request) } func Listen(ctx context.Context, address net.Address, port net.Port, handler internet.ConnHandler) (internet.Listener, error) { + rawSettings := internet.TransportSettingsFromContext(ctx) + httpSettings, ok := rawSettings.(*Config) + if !ok { + return nil, newError("HTTP config is not set.").AtError() + } + listener := &Listener{ handler: handler, local: &net.TCPAddr{ IP: address.IP(), Port: int(port), }, + config: *httpSettings, } config := tls.ConfigFromContext(ctx)