From 2d5b2484b38e8951593475dccea298ed671e5a8a Mon Sep 17 00:00:00 2001 From: Page Fault Date: Tue, 16 Jun 2020 17:36:19 +0000 Subject: [PATCH] add http proxy, fix bugs --- common/io.go | 8 +- proxy/client/client.go | 25 ++++- proxy/server/server.go | 4 +- test/scenario/proxy_test.go | 6 +- tunnel/adapter/server.go | 101 +++++++++++++++++ tunnel/adapter/tunnel.go | 26 +++++ tunnel/dokodemo/conn.go | 8 +- tunnel/http/http_test.go | 89 +++++++++++++++ tunnel/http/server.go | 205 +++++++++++++++++++++++++++++++++++ tunnel/http/tunnel.go | 26 +++++ tunnel/shadowsocks/client.go | 2 +- tunnel/shadowsocks/server.go | 2 +- tunnel/socks/config.go | 4 +- tunnel/socks/server.go | 37 +++---- tunnel/socks/socks_test.go | 10 +- tunnel/transport/server.go | 2 +- 16 files changed, 510 insertions(+), 45 deletions(-) create mode 100644 tunnel/adapter/server.go create mode 100644 tunnel/adapter/tunnel.go create mode 100644 tunnel/http/http_test.go create mode 100644 tunnel/http/server.go create mode 100644 tunnel/http/tunnel.go diff --git a/common/io.go b/common/io.go index 168a94b..f76532d 100644 --- a/common/io.go +++ b/common/io.go @@ -11,19 +11,19 @@ type RewindReader struct { rawReader io.Reader buf []byte bufReadIdx int - rewinded bool + rewound bool buffering bool bufferSize int } func (r *RewindReader) Read(p []byte) (int, error) { - if r.rewinded { + if r.rewound { if len(r.buf) > r.bufReadIdx { n := copy(p, r.buf[r.bufReadIdx:]) r.bufReadIdx += n return n, nil } - r.rewinded = false //all buffering content has been read + r.rewound = false //all buffering content has been read } n, err := r.rawReader.Read(p) if r.buffering { @@ -62,7 +62,7 @@ func (r *RewindReader) Rewind() { if r.bufferSize == 0 { panic("has no buffer") } - r.rewinded = true + r.rewound = true r.bufReadIdx = 0 } diff --git a/proxy/client/client.go b/proxy/client/client.go index 3202542..5cf5bc9 100644 --- a/proxy/client/client.go +++ b/proxy/client/client.go @@ -4,7 +4,8 @@ import ( "context" "github.com/p4gefau1t/trojan-go/config" "github.com/p4gefau1t/trojan-go/proxy" - "github.com/p4gefau1t/trojan-go/tunnel" + "github.com/p4gefau1t/trojan-go/tunnel/adapter" + "github.com/p4gefau1t/trojan-go/tunnel/http" "github.com/p4gefau1t/trojan-go/tunnel/mux" "github.com/p4gefau1t/trojan-go/tunnel/router" "github.com/p4gefau1t/trojan-go/tunnel/shadowsocks" @@ -43,16 +44,32 @@ func GenerateClientTree(transportPlugin bool, muxEnabled bool, wsEnabled bool, s func init() { proxy.RegisterProxyCreator(Name, func(ctx context.Context) (*proxy.Proxy, error) { cfg := config.FromContext(ctx, Name).(*Config) - serverStack := []string{socks.Name} + + transportServer, err := transport.NewServer(ctx, nil) + if err != nil { + return nil, err + } + + root := &proxy.Node{ + Name: transport.Name, + Next: make(map[string]*proxy.Node), + IsEndpoint: false, + Context: ctx, + Server: transportServer, + } + + root.BuildNext(adapter.Name).BuildNext(http.Name).IsEndpoint = true + root.BuildNext(adapter.Name).BuildNext(socks.Name).IsEndpoint = true + clientStack := GenerateClientTree(cfg.TransportPlugin.Enabled, cfg.Mux.Enabled, cfg.Websocket.Enabled, cfg.Shadowsocks.Enabled, cfg.Router.Enabled) c, err := proxy.CreateClientStack(ctx, clientStack) if err != nil { return nil, err } - s, err := proxy.CreateServerStack(ctx, serverStack) + s := proxy.FindAllEndpoints(root) if err != nil { return nil, err } - return proxy.NewProxy(ctx, []tunnel.Server{s}, c), nil + return proxy.NewProxy(ctx, s, c), nil }) } diff --git a/proxy/server/server.go b/proxy/server/server.go index 62e2e58..1fbc4fe 100644 --- a/proxy/server/server.go +++ b/proxy/server/server.go @@ -21,7 +21,7 @@ const Name = "SERVER" func init() { proxy.RegisterProxyCreator(Name, func(ctx context.Context) (*proxy.Proxy, error) { cfg := config.FromContext(ctx, Name).(*client.Config) - s, err := transport.NewServer(ctx, nil) + transportServer, err := transport.NewServer(ctx, nil) if err != nil { return nil, err } @@ -35,7 +35,7 @@ func init() { Next: make(map[string]*proxy.Node), IsEndpoint: false, Context: ctx, - Server: s, + Server: transportServer, } if !cfg.TransportPlugin.Enabled { diff --git a/test/scenario/proxy_test.go b/test/scenario/proxy_test.go index 64445bd..8eb7e57 100644 --- a/test/scenario/proxy_test.go +++ b/test/scenario/proxy_test.go @@ -23,6 +23,8 @@ import ( _ "net/http/pprof" ) +// test key and cert + var cert = ` -----BEGIN CERTIFICATE----- MIIDZTCCAk0CFFphZh018B5iAD9F5fV4y0AlD0LxMA0GCSqGSIb3DQEBCwUAMG8x @@ -293,7 +295,7 @@ transport-plugin: enabled: true type: plaintext shadowsocks: - enabled: false + enabled: true method: AEAD_CHACHA20_POLY1305 password: 12345678 mux: @@ -316,7 +318,7 @@ transport-plugin: enabled: true type: plaintext shadowsocks: - enabled: false + enabled: true method: AEAD_CHACHA20_POLY1305 password: 12345678 websocket: diff --git a/tunnel/adapter/server.go b/tunnel/adapter/server.go new file mode 100644 index 0000000..35ee3aa --- /dev/null +++ b/tunnel/adapter/server.go @@ -0,0 +1,101 @@ +package adapter + +import ( + "context" + "github.com/p4gefau1t/trojan-go/common" + "github.com/p4gefau1t/trojan-go/log" + "github.com/p4gefau1t/trojan-go/tunnel" + "github.com/p4gefau1t/trojan-go/tunnel/http" + "github.com/p4gefau1t/trojan-go/tunnel/socks" + "github.com/p4gefau1t/trojan-go/tunnel/transport" +) + +type Server struct { + underlay tunnel.Server + socksConn chan tunnel.Conn + httpConn chan tunnel.Conn + nextSocks bool + ctx context.Context + cancel context.CancelFunc +} + +func (s *Server) acceptConnLoop() { + for { + conn, err := s.underlay.AcceptConn(&Tunnel{}) + if err != nil { + select { + case <-s.ctx.Done(): + log.Debug("exiting") + return + default: + continue + } + } + rewindConn := common.NewRewindConn(conn) + rewindConn.SetBufferSize(16) + buf := [3]byte{} + _, err = rewindConn.Read(buf[:]) + rewindConn.Rewind() + rewindConn.StopBuffering() + if err != nil { + log.Error(common.NewError("failed to detect proxy protocol type").Base(err)) + continue + } + if buf[0] == 5 && s.nextSocks { + log.Debug("socks5 connection") + s.socksConn <- &transport.Conn{ + Conn: rewindConn, + } + } else { + log.Debug("http connection") + s.httpConn <- &transport.Conn{ + Conn: rewindConn, + } + } + } +} + +func (s *Server) AcceptConn(overlay tunnel.Tunnel) (tunnel.Conn, error) { + if _, ok := overlay.(*http.Tunnel); ok { + select { + case conn := <-s.httpConn: + return conn, nil + case <-s.ctx.Done(): + return nil, common.NewError("adapter closed") + } + } else if _, ok := overlay.(*socks.Tunnel); ok { + s.nextSocks = true + select { + case conn := <-s.socksConn: + return conn, nil + case <-s.ctx.Done(): + return nil, common.NewError("adapter closed") + } + } else { + panic("invalid overlay") + } +} + +func (s *Server) AcceptPacket(tunnel.Tunnel) (tunnel.PacketConn, error) { + // no packet conn available, but it's ok to stuck here + <-s.ctx.Done() + return nil, common.NewError("adapter server closed") +} + +func (s *Server) Close() error { + s.cancel() + return s.underlay.Close() +} + +func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) { + ctx, cancel := context.WithCancel(ctx) + server := &Server{ + underlay: underlay, + socksConn: make(chan tunnel.Conn, 32), + httpConn: make(chan tunnel.Conn, 32), + ctx: ctx, + cancel: cancel, + } + go server.acceptConnLoop() + return server, nil +} diff --git a/tunnel/adapter/tunnel.go b/tunnel/adapter/tunnel.go new file mode 100644 index 0000000..37cdc8b --- /dev/null +++ b/tunnel/adapter/tunnel.go @@ -0,0 +1,26 @@ +package adapter + +import ( + "context" + "github.com/p4gefau1t/trojan-go/tunnel" +) + +const Name = "ADAPTER" + +type Tunnel struct{} + +func (t *Tunnel) Name() string { + return Name +} + +func (t *Tunnel) NewClient(ctx context.Context, client tunnel.Client) (tunnel.Client, error) { + panic("not supported") +} + +func (t *Tunnel) NewServer(ctx context.Context, server tunnel.Server) (tunnel.Server, error) { + return NewServer(ctx, server) +} + +func init() { + tunnel.RegisterTunnel(Name, &Tunnel{}) +} diff --git a/tunnel/dokodemo/conn.go b/tunnel/dokodemo/conn.go index ddc4c1d..f18193a 100644 --- a/tunnel/dokodemo/conn.go +++ b/tunnel/dokodemo/conn.go @@ -2,7 +2,7 @@ package dokodemo import ( "context" - "io" + "github.com/p4gefau1t/trojan-go/common" "net" "github.com/p4gefau1t/trojan-go/tunnel" @@ -58,15 +58,15 @@ func (c *PacketConn) ReadWithMetadata(p []byte) (int, *tunnel.Metadata, error) { n := copy(p, payload) return n, c.M, nil case <-c.Ctx.Done(): - return 0, nil, io.EOF + return 0, nil, common.NewError("dokodemo packet conn closed") } } func (c *PacketConn) WriteWithMetadata(p []byte, m *tunnel.Metadata) (int, error) { select { case c.Output <- p: + return len(p), nil case <-c.Ctx.Done(): - return 0, io.EOF + return 0, common.NewError("dokodemo packet conn failed to write") } - return len(p), nil } diff --git a/tunnel/http/http_test.go b/tunnel/http/http_test.go new file mode 100644 index 0000000..b362be1 --- /dev/null +++ b/tunnel/http/http_test.go @@ -0,0 +1,89 @@ +package http + +import ( + "bufio" + "context" + "fmt" + "github.com/p4gefau1t/trojan-go/common" + "github.com/p4gefau1t/trojan-go/config" + "github.com/p4gefau1t/trojan-go/test/util" + "github.com/p4gefau1t/trojan-go/tunnel/transport" + "io/ioutil" + "net" + "net/http" + "testing" +) + +func TestHTTP(t *testing.T) { + port := common.PickPort("tcp", "127.0.0.1") + ctx := config.WithConfig(context.Background(), transport.Name, &transport.Config{ + LocalHost: "127.0.0.1", + LocalPort: port, + }) + + tcpServer, err := transport.NewServer(ctx, nil) + common.Must(err) + s, err := NewServer(ctx, tcpServer) + common.Must(err) + + for i := 0; i < 10; i++ { + go func() { + http.Get(fmt.Sprintf("http://127.0.0.1:%d", port)) + }() + conn, err := s.AcceptConn(nil) + common.Must(err) + bufReader := bufio.NewReader(bufio.NewReader(conn)) + req, err := http.ReadRequest(bufReader) + fmt.Println(req) + ioutil.ReadAll(req.Body) + req.Body.Close() + resp := `HTTP/1.1 200 OK +Date: Mon, 19 Jul 2004 16:18:20 GMT +Server: Apache +Last-Modified: Sat, 10 Jul 2004 17:29:19 GMT +ETag: "1d0325-2470-40f0276f" +Accept-Ranges: bytes +Content-Length: 4 +Connection: close +Content-Type: text/html + +1234 +` + _, err = conn.Write([]byte(resp)) + common.Must(err) + buf := [100]byte{} + _, err = conn.Read(buf[:]) + if err == nil { + t.Fail() + } + conn.Close() + } + + req, err := http.NewRequest("CONNECT", "https://google.com:443", nil) + common.Must(err) + conn1, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + common.Must(err) + req.Write(conn1) + + conn2, err := s.AcceptConn(nil) + common.Must(err) + + if conn2.Metadata().Port != 443 || conn2.Metadata().DomainName != "google.com" { + t.Fail() + } + + connResp := "HTTP/1.1 200 Connection established\r\n\r\n" + buf := make([]byte, len(connResp)) + conn1.Read(buf) + if string(buf) != connResp { + t.Fail() + } + + if !util.CheckConn(conn1, conn2) { + t.Fail() + } + + conn1.Close() + conn2.Close() + s.Close() +} diff --git a/tunnel/http/server.go b/tunnel/http/server.go new file mode 100644 index 0000000..91765b1 --- /dev/null +++ b/tunnel/http/server.go @@ -0,0 +1,205 @@ +package http + +import ( + "bufio" + "context" + "fmt" + "github.com/p4gefau1t/trojan-go/common" + "github.com/p4gefau1t/trojan-go/log" + "github.com/p4gefau1t/trojan-go/tunnel" + "io" + "io/ioutil" + "net" + "net/http" + "strings" +) + +type ConnectConn struct { + net.Conn + metadata *tunnel.Metadata +} + +func (c *ConnectConn) Metadata() *tunnel.Metadata { + return c.metadata +} + +type OtherConn struct { + net.Conn + metadata *tunnel.Metadata //fixed + reqReader *io.PipeReader + respWriter *io.PipeWriter + ctx context.Context + cancel context.CancelFunc +} + +func (c *OtherConn) Metadata() *tunnel.Metadata { + return c.metadata +} + +func (c *OtherConn) Read(p []byte) (int, error) { + n, err := c.reqReader.Read(p) + if err == io.EOF { + if n != 0 { + panic("non zero") + } + select { + case <-c.ctx.Done(): + return 0, common.NewError("http conn closed") + } + } + return n, err +} + +func (c *OtherConn) Write(p []byte) (int, error) { + return c.respWriter.Write(p) +} + +func (c *OtherConn) Close() error { + c.cancel() + c.reqReader.Close() + c.respWriter.Close() + return nil +} + +type Server struct { + underlay tunnel.Server + connChan chan tunnel.Conn + ctx context.Context + cancel context.CancelFunc +} + +func (s *Server) acceptLoop() { + for { + conn, err := s.underlay.AcceptConn(&Tunnel{}) + if err != nil { + select { + case <-s.ctx.Done(): + log.Error(common.NewError("http closed")) + return + default: + log.Error(common.NewError("http failed to accept connection").Base(err)) + continue + } + } + + go func(conn net.Conn) { + reqBufReader := bufio.NewReader(ioutil.NopCloser(conn)) + req, err := http.ReadRequest(reqBufReader) + if err != nil { + log.Error(common.NewError("not a valid http request").Base(err)) + return + } + if strings.ToUpper(req.Method) == "CONNECT" { // CONNECT + addr, err := tunnel.NewAddressFromAddr("tcp", req.Host) + if err != nil { + log.Error(common.NewError("invalid http dest address").Base(err)) + conn.Close() + return + } + resp := fmt.Sprintf("HTTP/%d.%d 200 Connection established\r\n\r\n", req.ProtoMajor, req.ProtoMinor) + _, err = conn.Write([]byte(resp)) + if err != nil { + log.Error("http failed to respond connect request") + conn.Close() + return + } + s.connChan <- &ConnectConn{ + Conn: conn, + metadata: &tunnel.Metadata{ + Address: addr, + }, + } + } else { // GET, POST, PUT... + defer conn.Close() + for { + ctx, cancel := context.WithCancel(s.ctx) + reqReader, reqWriter := io.Pipe() + respReader, respWriter := io.Pipe() + var addr *tunnel.Address + _, strPort, err := net.SplitHostPort(req.Host) + if err != nil { + if strPort == "" { //default port 80 + addr = tunnel.NewAddressFromHostPort("tcp", req.Host, 80) + } + } else { + addr, err = tunnel.NewAddressFromAddr("tcp", req.Host) + if err != nil { + log.Error(common.NewError("invalid http dest address").Base(err)) + return + } + } + log.Debug("http dest", addr) + newConn := &OtherConn{ + Conn: conn, + metadata: &tunnel.Metadata{ + Address: addr, + }, + ctx: ctx, + cancel: cancel, + reqReader: reqReader, + respWriter: respWriter, + } + s.connChan <- newConn // pass this http session connection to proxy.RelayConn + + err = req.Write(reqWriter) // write request to the remote + if err != nil { + log.Error(common.NewError("http failed to write http request").Base(err)) + return + } + + respBufReader := bufio.NewReader(ioutil.NopCloser(respReader)) // read response from the remote + resp, err := http.ReadResponse(respBufReader, req) + if err != nil { + log.Error(common.NewError("http failed to read http response").Base(err)) + return + } + err = resp.Write(conn) // send the response back to the local + if err != nil { + log.Error(common.NewError("http failed to write the response back").Base(err)) + return + } + newConn.Close() + req.Body.Close() + resp.Body.Close() + + req, err = http.ReadRequest(reqBufReader) //read the next http request from local + if err != nil { + log.Error(common.NewError("http failed to the read request from local").Base(err)) + return + } + } + } + }(conn) + } +} + +func (s *Server) AcceptConn(tunnel.Tunnel) (tunnel.Conn, error) { + select { + case conn := <-s.connChan: + return conn, nil + case <-s.ctx.Done(): + return nil, common.NewError("http server closed") + } +} + +func (s *Server) AcceptPacket(tunnel.Tunnel) (tunnel.PacketConn, error) { + <-s.ctx.Done() + return nil, common.NewError("http server closed") +} + +func (s *Server) Close() error { + s.cancel() + return s.underlay.Close() +} + +func NewServer(ctx context.Context, underlay tunnel.Server) (*Server, error) { + ctx, cancel := context.WithCancel(ctx) + server := &Server{ + underlay: underlay, + connChan: make(chan tunnel.Conn, 32), + ctx: ctx, + cancel: cancel, + } + go server.acceptLoop() + return server, nil +} diff --git a/tunnel/http/tunnel.go b/tunnel/http/tunnel.go new file mode 100644 index 0000000..ca45a78 --- /dev/null +++ b/tunnel/http/tunnel.go @@ -0,0 +1,26 @@ +package http + +import ( + "context" + "github.com/p4gefau1t/trojan-go/tunnel" +) + +const Name = "HTTP" + +type Tunnel struct{} + +func (t *Tunnel) Name() string { + return Name +} + +func (t *Tunnel) NewClient(ctx context.Context, client tunnel.Client) (tunnel.Client, error) { + panic("not supported") +} + +func (t *Tunnel) NewServer(ctx context.Context, server tunnel.Server) (tunnel.Server, error) { + return NewServer(ctx, server) +} + +func init() { + tunnel.RegisterTunnel(Name, &Tunnel{}) +} diff --git a/tunnel/shadowsocks/client.go b/tunnel/shadowsocks/client.go index 42fc3db..2a710d6 100644 --- a/tunnel/shadowsocks/client.go +++ b/tunnel/shadowsocks/client.go @@ -15,7 +15,7 @@ type Client struct { } func (c *Client) DialConn(address *tunnel.Address, tunnel tunnel.Tunnel) (tunnel.Conn, error) { - conn, err := c.underlay.DialConn(address, tunnel) + conn, err := c.underlay.DialConn(address, &Tunnel{}) if err != nil { return nil, err } diff --git a/tunnel/shadowsocks/server.go b/tunnel/shadowsocks/server.go index bac054e..d494f1f 100644 --- a/tunnel/shadowsocks/server.go +++ b/tunnel/shadowsocks/server.go @@ -19,7 +19,7 @@ type Server struct { } func (s *Server) AcceptConn(overlay tunnel.Tunnel) (tunnel.Conn, error) { - conn, err := s.underlay.AcceptConn(overlay) + conn, err := s.underlay.AcceptConn(&Tunnel{}) if err != nil { return nil, common.NewError("shadowsocks failed to accept connection from underlying tunnel") } diff --git a/tunnel/socks/config.go b/tunnel/socks/config.go index d90a590..dfd68a5 100644 --- a/tunnel/socks/config.go +++ b/tunnel/socks/config.go @@ -3,9 +3,7 @@ package socks import "github.com/p4gefau1t/trojan-go/config" type Config struct { - LocalHost string `json:"local_addr" yaml:"local-addr"` - LocalPort int `json:"local_port" yaml:"local-port"` - UDPTimeout int `json:"udp_timeout" yaml:"udp-timeout"` + UDPTimeout int `json:"udp_timeout" yaml:"udp-timeout"` } func init() { diff --git a/tunnel/socks/server.go b/tunnel/socks/server.go index 69b3553..8ac2c0e 100644 --- a/tunnel/socks/server.go +++ b/tunnel/socks/server.go @@ -26,13 +26,13 @@ const ( // Server is a socks5 server type Server struct { - connChan chan tunnel.Conn - packetChan chan tunnel.PacketConn - tcpListener net.Listener - localHost string - timeout time.Duration - ctx context.Context - cancel context.CancelFunc + connChan chan tunnel.Conn + packetChan chan tunnel.PacketConn + underlay tunnel.Server + localHost string + timeout time.Duration + ctx context.Context + cancel context.CancelFunc } func (s *Server) AcceptConn(tunnel.Tunnel) (tunnel.Conn, error) { @@ -55,7 +55,7 @@ func (s *Server) AcceptPacket(tunnel.Tunnel) (tunnel.PacketConn, error) { func (s *Server) Close() error { s.cancel() - return s.tcpListener.Close() + return s.underlay.Close() } func (s *Server) handshake(conn net.Conn) (*Conn, error) { @@ -110,7 +110,7 @@ func (s *Server) associate(conn net.Conn, addr *tunnel.Address) error { func (s *Server) acceptLoop() { for { - conn, err := s.tcpListener.Accept() + conn, err := s.underlay.AcceptConn(&Tunnel{}) if err != nil { log.Error(common.NewError("socks5 accept err").Base(err)) return @@ -134,6 +134,7 @@ func (s *Server) acceptLoop() { case Associate: defer newConn.Close() port := common.PickPort("udp", s.localHost) + // TODO use underlying server associateAddr := tunnel.NewAddressFromHostPort("udp", s.localHost, port) l, err := net.ListenPacket("udp", associateAddr.String()) if err != nil { @@ -160,22 +161,16 @@ func (s *Server) acceptLoop() { // NewServer create a socks server func NewServer(ctx context.Context, underlay tunnel.Server) (tunnel.Server, error) { cfg := config.FromContext(ctx, Name).(*Config) - listenAddr := tunnel.NewAddressFromHostPort("tcp", cfg.LocalHost, cfg.LocalPort) - l, err := net.Listen("tcp", listenAddr.String()) - if err != nil { - return nil, common.NewError("socks5 failed to listen").Base(err) - } ctx, cancel := context.WithCancel(ctx) server := &Server{ - tcpListener: l, - ctx: ctx, - cancel: cancel, - connChan: make(chan tunnel.Conn, 32), - packetChan: make(chan tunnel.PacketConn, 32), - timeout: time.Duration(cfg.UDPTimeout) * time.Second, + underlay: underlay, + ctx: ctx, + cancel: cancel, + connChan: make(chan tunnel.Conn, 32), + packetChan: make(chan tunnel.PacketConn, 32), + timeout: time.Duration(cfg.UDPTimeout) * time.Second, } go server.acceptLoop() - log.Info("socks5 server is listening on tcp:", l.Addr().String()) log.Debug("socks server created") return server, nil } diff --git a/tunnel/socks/socks_test.go b/tunnel/socks/socks_test.go index b16cc0f..74d0f6f 100644 --- a/tunnel/socks/socks_test.go +++ b/tunnel/socks/socks_test.go @@ -7,6 +7,7 @@ import ( "github.com/p4gefau1t/trojan-go/config" "github.com/p4gefau1t/trojan-go/test/util" "github.com/p4gefau1t/trojan-go/tunnel" + "github.com/p4gefau1t/trojan-go/tunnel/transport" "golang.org/x/net/proxy" "net" "sync" @@ -16,12 +17,17 @@ import ( func TestSocks(t *testing.T) { port := common.PickPort("tcp", "127.0.0.1") - ctx := config.WithConfig(context.Background(), Name, &Config{ + ctx := config.WithConfig(context.Background(), transport.Name, &transport.Config{ LocalHost: "127.0.0.1", LocalPort: port, }) + ctx = config.WithConfig(ctx, Name, &Config{ + UDPTimeout: 30, + }) + tcpServer, err := transport.NewServer(ctx, nil) + common.Must(err) addr := tunnel.NewAddressFromHostPort("tcp", "127.0.0.1", port) - s, err := NewServer(ctx, nil) + s, err := NewServer(ctx, tcpServer) common.Must(err) socksClient, err := proxy.SOCKS5("tcp", addr.String(), nil, proxy.Direct) common.Must(err) diff --git a/tunnel/transport/server.go b/tunnel/transport/server.go index 9d0f73d..93a5711 100644 --- a/tunnel/transport/server.go +++ b/tunnel/transport/server.go @@ -80,7 +80,7 @@ func (s *Server) acceptLoop() { func (s *Server) AcceptConn(overlay tunnel.Tunnel) (tunnel.Conn, error) { // TODO fix import cycle - if overlay != nil && overlay.Name() == "WEBSOCKET" { + if overlay != nil && (overlay.Name() == "WEBSOCKET" || overlay.Name() == "HTTP") { s.nextHTTP = true select { case conn := <-s.wsChan: