func TestHubSocksOption(t *testing.T) { assert := assert.On(t) if os.Geteuid() != 0 { // This test case requires root permission. return } hub, err := ListenUDP(v2net.LocalHostIP, v2net.Port(0), ListenOption{ Callback: func(*buf.Buffer, *proxy.SessionInfo) {}, ReceiveOriginalDest: true, }) assert.Error(err).IsNil() conn := hub.Connection() fd, err := internal.GetSysFd(conn) assert.Error(err).IsNil() val, err := syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT) assert.Error(err).IsNil() assert.Int(val).Equals(1) val, err = syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR) assert.Error(err).IsNil() assert.Int(val).Equals(1) }
func (s *Server) Process(ctx context.Context, network v2net.Network, conn internet.Connection) error { conn.SetReusable(false) timedReader := v2net.NewTimeOutReader(s.config.Timeout, conn) reader := bufio.OriginalReaderSize(timedReader, 2048) request, err := http.ReadRequest(reader) if err != nil { if errors.Cause(err) != io.EOF { log.Warning("HTTP: Failed to read http request: ", err) } return err } log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("HTTP: Malformed proxy host (", host, "): ", err) return err } log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") ctx = proxy.ContextWithDestination(ctx, dest) if strings.ToUpper(request.Method) == "CONNECT" { return s.handleConnect(ctx, request, reader, conn) } else { return s.handlePlainHTTP(ctx, request, reader, conn) } }
func parseStringPort(data []byte) (v2net.Port, v2net.Port, error) { var s string err := json.Unmarshal(data, &s) if err != nil { return v2net.Port(0), v2net.Port(0), err } pair := strings.SplitN(s, "-", 2) if len(pair) == 0 { return v2net.Port(0), v2net.Port(0), v2net.ErrInvalidPortRange } if len(pair) == 1 { port, err := v2net.PortFromString(pair[0]) return port, port, err } fromPort, err := v2net.PortFromString(pair[0]) if err != nil { return v2net.Port(0), v2net.Port(0), err } toPort, err := v2net.PortFromString(pair[1]) if err != nil { return v2net.Port(0), v2net.Port(0), err } return fromPort, toPort, nil }
func (server *Server) Start() (v2net.Destination, error) { listener, err := net.ListenTCP("tcp", &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(server.Port), Zone: "", }) if err != nil { return v2net.Destination{}, err } server.Port = v2net.Port(listener.Addr().(*net.TCPAddr).Port) server.listener = listener go server.acceptConnections(listener) localAddr := listener.Addr().(*net.TCPAddr) return v2net.TCPDestination(v2net.IPAddress(localAddr.IP), v2net.Port(localAddr.Port)), nil }
func (server *Server) Start() (v2net.Destination, error) { conn, err := net.ListenUDP("udp", &net.UDPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(server.Port), Zone: "", }) if err != nil { return nil, err } server.Port = v2net.Port(conn.LocalAddr().(*net.UDPAddr).Port) server.conn = conn go server.handleConnection(conn) localAddr := conn.LocalAddr().(*net.UDPAddr) return v2net.UDPDestination(v2net.IPAddress(localAddr.IP), v2net.Port(localAddr.Port)), nil }
func TestNormalGetRequest(t *testing.T) { assert := assert.On(t) testPacketDispatcher := testdispatcher.NewTestPacketDispatcher(nil) port := v2net.Port(dice.Roll(20000) + 10000) httpProxy := NewServer( &Config{}, testPacketDispatcher, &proxy.InboundHandlerMeta{ Address: v2net.LocalHostIP, Port: port, StreamSettings: &internet.StreamSettings{ Type: internet.StreamConnectionTypeRawTCP, }}) defer httpProxy.Close() err := httpProxy.Start() assert.Error(err).IsNil() assert.Port(port).Equals(httpProxy.Port()) httpClient := &http.Client{} resp, err := httpClient.Get("http://127.0.0.1:" + port.String() + "/") assert.Error(err).IsNil() assert.Int(resp.StatusCode).Equals(400) }
func TestHttpProxy(t *testing.T) { assert := assert.On(t) httpServer := &v2http.Server{ Port: v2net.Port(50042), PathHandler: make(map[string]http.HandlerFunc), } _, err := httpServer.Start() assert.Error(err).IsNil() defer httpServer.Close() assert.Error(InitializeServerSetOnce("test_5")).IsNil() transport := &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { return url.Parse("http://127.0.0.1:50040/") }, } client := &http.Client{ Transport: transport, } resp, err := client.Get("http://127.0.0.1:50042/") assert.Error(err).IsNil() assert.Int(resp.StatusCode).Equals(200) content, err := ioutil.ReadAll(resp.Body) assert.Error(err).IsNil() assert.String(string(content)).Equals("Home") CloseAllServers() }
func (this *InboundConnectionConfig) UnmarshalJSON(data []byte) error { type JsonConfig struct { Port uint16 `json:"port"` Listen *v2net.AddressJson `json:"listen"` Protocol string `json:"protocol"` StreamSetting *internet.StreamSettings `json:"streamSettings"` Settings json.RawMessage `json:"settings"` AllowPassive bool `json:"allowPassive"` } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { return errors.New("Point: Failed to parse inbound config: " + err.Error()) } this.Port = v2net.Port(jsonConfig.Port) this.ListenOn = v2net.AnyIP if jsonConfig.Listen != nil { if jsonConfig.Listen.Address.Family().IsDomain() { return errors.New("Point: Unable to listen on domain address: " + jsonConfig.Listen.Address.Domain()) } this.ListenOn = jsonConfig.Listen.Address } if jsonConfig.StreamSetting != nil { this.StreamSettings = jsonConfig.StreamSetting } this.Protocol = jsonConfig.Protocol this.Settings = jsonConfig.Settings this.AllowPassiveConnection = jsonConfig.AllowPassive return nil }
func TestIPResolution(t *testing.T) { assert := assert.On(t) space := app.NewSpace() space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outbound.New()) space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) r := router.NewRouter(&router.Config{}, space) space.BindApp(router.APP_ID, r) dnsServer := dnsserver.NewCacheServer(space, &dns.Config{ Hosts: map[string]*v2net.IPOrDomain{ "v2ray.com": v2net.NewIPOrDomain(v2net.LocalHostIP), }, }) space.BindApp(dns.APP_ID, dnsServer) freedom := NewFreedomConnection( &Config{DomainStrategy: Config_USE_IP}, space, &proxy.OutboundHandlerMeta{ Address: v2net.AnyIP, StreamSettings: &internet.StreamConfig{ Network: v2net.Network_RawTCP, }, }) space.Initialize() ipDest := freedom.ResolveIP(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), v2net.Port(80))) assert.Destination(ipDest).IsTCP() assert.Address(ipDest.Address).Equals(v2net.LocalHostIP) }
func (v *UDPHub) start() { v.cancel.WaitThread() defer v.cancel.FinishThread() oobBytes := make([]byte, 256) for v.Running() { buffer := buf.NewSmall() var noob int var addr *net.UDPAddr err := buffer.AppendSupplier(func(b []byte) (int, error) { n, nb, _, a, e := ReadUDPMsg(v.conn, b, oobBytes) noob = nb addr = a return n, e }) if err != nil { log.Info("UDP|Hub: Failed to read UDP msg: ", err) buffer.Release() continue } session := new(proxy.SessionInfo) session.Source = v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port)) if v.option.ReceiveOriginalDest && noob > 0 { session.Destination = RetrieveOriginalDest(oobBytes[:noob]) } v.queue.Enqueue(UDPPayload{ payload: buffer, session: session, }) } }
func (this *UDPHub) start() { this.cancel.WaitThread() defer this.cancel.FinishThread() oobBytes := make([]byte, 256) for this.Running() { buffer := this.pool.Allocate() nBytes, noob, _, addr, err := ReadUDPMsg(this.conn, buffer.Value, oobBytes) if err != nil { log.Info("UDP|Hub: Failed to read UDP msg: ", err) buffer.Release() continue } buffer.Slice(0, nBytes) session := new(proxy.SessionInfo) session.Source = v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port)) if this.option.ReceiveOriginalDest && noob > 0 { session.Destination = RetrieveOriginalDest(oobBytes[:noob]) } this.queue.Enqueue(UDPPayload{ payload: buffer, session: session, }) } }
func TestResponseWrite(t *testing.T) { assert := assert.On(t) response := Socks5Response{ socksVersion, ErrorSuccess, AddrTypeIPv4, [4]byte{0x72, 0x72, 0x72, 0x72}, "", [16]byte{}, v2net.Port(53), } buffer := alloc.NewLocalBuffer(2048).Clear() defer buffer.Release() response.Write(buffer) expectedBytes := []byte{ socksVersion, ErrorSuccess, byte(0x00), AddrTypeIPv4, 0x72, 0x72, 0x72, 0x72, byte(0x00), byte(0x035), } assert.Bytes(buffer.Value).Equals(expectedBytes) }
func TestDnsAdd(t *testing.T) { assert := assert.On(t) space := app.NewSpace() outboundHandlerManager := proxyman.NewDefaultOutboundHandlerManager() outboundHandlerManager.SetDefaultHandler( freedom.NewFreedomConnection( &freedom.Config{}, space, &proxy.OutboundHandlerMeta{ Address: v2net.AnyIP, StreamSettings: &internet.StreamSettings{ Type: internet.StreamConnectionTypeRawTCP, }, })) space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager) space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) domain := "local.v2ray.com" server := NewCacheServer(space, &Config{ NameServers: []v2net.Destination{ v2net.UDPDestination(v2net.IPAddress([]byte{8, 8, 8, 8}), v2net.Port(53)), }, }) space.BindApp(APP_ID, server) space.Initialize() ips := server.Get(domain) assert.Int(len(ips)).Equals(1) assert.IP(ips[0].To4()).Equals(net.IP([]byte{127, 0, 0, 1})) }
func TestBlockHTTP(t *testing.T) { assert := assert.On(t) httpServer := &v2http.Server{ Port: net.Port(50042), PathHandler: make(map[string]http.HandlerFunc), } _, err := httpServer.Start() assert.Error(err).IsNil() defer httpServer.Close() assert.Error(InitializeServerSetOnce("test_5")).IsNil() transport := &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { return url.Parse("http://127.0.0.1:50040/") }, } client := &http.Client{ Transport: transport, } resp, err := client.Get("http://127.0.0.1:50049/") assert.Error(err).IsNil() assert.Int(resp.StatusCode).Equals(403) CloseAllServers() }
func TestIPResolution(t *testing.T) { assert := assert.On(t) space := app.NewSpace() space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager()) space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space)) r, _ := router.CreateRouter("rules", &rules.RouterRuleConfig{}, space) space.BindApp(router.APP_ID, r) dnsServer := dns.NewCacheServer(space, &dns.Config{ Hosts: map[string]net.IP{ "v2ray.com": net.IP([]byte{127, 0, 0, 1}), }, }) space.BindApp(dns.APP_ID, dnsServer) freedom := NewFreedomConnection( &Config{DomainStrategy: DomainStrategyUseIP}, space, &proxy.OutboundHandlerMeta{ Address: v2net.AnyIP, StreamSettings: &internet.StreamSettings{ Type: internet.StreamConnectionTypeRawTCP, }, }) space.Initialize() ipDest := freedom.ResolveIP(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), v2net.Port(80))) assert.Destination(ipDest).IsTCP() assert.Address(ipDest.Address()).Equals(v2net.LocalHostIP) }
func (this *Config) UnmarshalJSON(data []byte) error { type JsonConfig struct { Servers []v2net.AddressJson `json:"servers"` Hosts map[string]v2net.AddressJson `json:"hosts"` } jsonConfig := new(JsonConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { return err } this.NameServers = make([]v2net.Destination, len(jsonConfig.Servers)) for idx, server := range jsonConfig.Servers { this.NameServers[idx] = v2net.UDPDestination(server.Address, v2net.Port(53)) } if jsonConfig.Hosts != nil { this.Hosts = make(map[string]net.IP) for domain, ip := range jsonConfig.Hosts { if ip.Address.Family().IsDomain() { return errors.New(ip.Address.String() + " is not an IP.") } this.Hosts[domain] = ip.Address.IP() } } return nil }
func parseIntPort(data []byte) (v2net.Port, error) { var intPort uint32 err := json.Unmarshal(data, &intPort) if err != nil { return v2net.Port(0), err } return v2net.PortFromInt(intPort) }
func pickPort() v2net.Port { listener, err := net.Listen("tcp4", ":0") common.Must(err) defer listener.Close() addr := listener.Addr().(*net.TCPAddr) return v2net.Port(addr.Port) }
func (v *DokodemoDoor) HandleTCPConnection(conn internet.Connection) { defer conn.Close() var dest v2net.Destination if v.config.FollowRedirect { originalDest := GetOriginalDestination(conn) if originalDest.Network != v2net.Network_Unknown { log.Info("Dokodemo: Following redirect to: ", originalDest) dest = originalDest } } if dest.Network == v2net.Network_Unknown && v.address != nil && v.port > v2net.Port(0) { dest = v2net.TCPDestination(v.address, v.port) } if dest.Network == v2net.Network_Unknown { log.Info("Dokodemo: Unknown destination, stop forwarding...") return } log.Info("Dokodemo: Handling request to ", dest) ray := v.packetDispatcher.DispatchToOutbound(&proxy.SessionInfo{ Source: v2net.DestinationFromAddr(conn.RemoteAddr()), Destination: dest, Inbound: v.meta, }) defer ray.InboundOutput().Release() var wg sync.WaitGroup reader := v2net.NewTimeOutReader(v.config.Timeout, conn) defer reader.Release() wg.Add(1) go func() { v2reader := buf.NewReader(reader) defer v2reader.Release() if err := buf.PipeUntilEOF(v2reader, ray.InboundInput()); err != nil { log.Info("Dokodemo: Failed to transport all TCP request: ", err) } wg.Done() ray.InboundInput().Close() }() wg.Add(1) go func() { v2writer := buf.NewWriter(conn) defer v2writer.Release() if err := buf.PipeUntilEOF(ray.InboundOutput(), v2writer); err != nil { log.Info("Dokodemo: Failed to transport all TCP response: ", err) } wg.Done() }() wg.Wait() }
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) { p, err := proxy.CreateInboundHandler(ctx, proxyConfig) if err != nil { return nil, err } h := &AlwaysOnInboundHandler{ proxy: p, } nl := p.Network() pr := receiverConfig.PortRange address := receiverConfig.Listen.AsAddress() if address == nil { address = net.AnyIP } for port := pr.From; port <= pr.To; port++ { if nl.HasNetwork(net.Network_TCP) { log.Debug("Proxyman|DefaultInboundHandler: creating tcp worker on ", address, ":", port) worker := &tcpWorker{ address: address, port: net.Port(port), proxy: p, stream: receiverConfig.StreamSettings, recvOrigDest: receiverConfig.ReceiveOriginalDestination, tag: tag, allowPassiveConn: receiverConfig.AllowPassiveConnection, } h.workers = append(h.workers, worker) } if nl.HasNetwork(net.Network_UDP) { worker := &udpWorker{ tag: tag, proxy: p, address: address, port: net.Port(port), recvOrigDest: receiverConfig.ReceiveOriginalDestination, } h.workers = append(h.workers, worker) } } return h, nil }
func TestServerList(t *testing.T) { assert := assert.On(t) list := NewServerList() list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid())) assert.Uint32(list.Size()).Equals(1) list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second)))) assert.Uint32(list.Size()).Equals(2) server := list.GetServer(1) assert.Port(server.Destination().Port).Equals(2) time.Sleep(2 * time.Second) server = list.GetServer(1) assert.Pointer(server).IsNil() server = list.GetServer(0) assert.Port(server.Destination().Port).Equals(1) }
func TestShadowsocksTCP(t *testing.T) { assert := assert.On(t) tcpServer := &tcp.Server{ Port: v2net.Port(50052), MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } _, err := tcpServer.Start() assert.Error(err).IsNil() defer tcpServer.Close() assert.Error(InitializeServerSetOnce("test_6")).IsNil() for i := 0; i < 1; i++ { conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: 50050, }) assert.Error(err).IsNil() payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) assert.Error(err).IsNil() assert.Int(nBytes).Equals(len(payload)) //conn.CloseWrite() response := buf.New() finished := false expectedResponse := "Processed: " + payload for { err := response.AppendSupplier(buf.ReadFrom(conn)) assert.Error(err).IsNil() if err != nil { break } if response.String() == expectedResponse { finished = true break } if response.Len() > len(expectedResponse) { fmt.Printf("Unexpected response: %v\n", response.Bytes()) break } } assert.Bool(finished).IsTrue() conn.Close() } CloseAllServers() }
func TestPassiveTCPConnection(t *testing.T) { assert := assert.On(t) tcpServer := &tcp.Server{ MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, SendFirst: []byte("Server sends first."), } _, err := tcpServer.Start() assert.Error(err).IsNil() defer tcpServer.Close() assert.Error(InitializeServerSetOnce("test_1")).IsNil() socksPort := v2net.Port(50002) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(socksPort), }) assert.Error(err).IsNil() authRequest := socks5AuthMethodRequest(byte(0)) nBytes, err := conn.Write(authRequest) assert.Int(nBytes).Equals(len(authRequest)) assert.Error(err).IsNil() authResponse := make([]byte, 1024) nBytes, err = conn.Read(authResponse) assert.Error(err).IsNil() assert.Bytes(authResponse[:nBytes]).Equals([]byte{socks5Version, 0}) connectRequest := socks5Request(byte(1), v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), tcpServer.Port)) nBytes, err = conn.Write(connectRequest) assert.Int(nBytes).Equals(len(connectRequest)) assert.Error(err).IsNil() connectResponse := make([]byte, 1024) nBytes, err = conn.Read(connectResponse) assert.Error(err).IsNil() assert.Bytes(connectResponse[:nBytes]).Equals([]byte{socks5Version, 0, 0, 1, 0, 0, 0, 0, 6, 181}) actualResponse := make([]byte, 1024) nResponse, err := conn.Read(actualResponse) assert.Error(err).IsNil() assert.String(string(actualResponse[:nResponse])).Equals(string(tcpServer.SendFirst)) conn.Close() CloseAllServers() }
func TestDokodemoTCP(t *testing.T) { assert := assert.On(t) tcpServer := &tcp.Server{ Port: v2net.Port(50016), MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } _, err := tcpServer.Start() assert.Error(err).IsNil() defer tcpServer.Close() assert.Error(InitializeServerSetOnce("test_2")).IsNil() dokodemoPortStart := v2net.Port(50011) dokodemoPortEnd := v2net.Port(50015) for port := dokodemoPortStart; port <= dokodemoPortEnd; port++ { conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(port), }) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) assert.Error(err).IsNil() assert.Int(nBytes).Equals(len(payload)) conn.CloseWrite() response := make([]byte, 1024) nBytes, err = conn.Read(response) assert.Error(err).IsNil() assert.String("Processed: " + payload).Equals(string(response[:nBytes])) conn.Close() } CloseAllServers() }
func TestConnectionCache(t *testing.T) { assert := assert.On(t) pool := NewConnectionPool() conn := pool.Get(NewConnectionID(v2net.LocalHostIP, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(80)))) assert.Pointer(conn).IsNil() pool.Put(NewConnectionID(v2net.LocalHostIP, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(80))), &TestConnection{id: "test"}) conn = pool.Get(NewConnectionID(v2net.LocalHostIP, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(80)))) assert.String(conn.(*TestConnection).id).Equals("test") }
func TestConnectionRecycle(t *testing.T) { assert := assert.On(t) pool := NewConnectionPool() c := &TestConnection{id: "test"} pool.Put(NewConnectionID(v2net.LocalHostIP, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(80))), c) time.Sleep(6 * time.Second) assert.Bool(c.closed).IsTrue() conn := pool.Get(NewConnectionID(v2net.LocalHostIP, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(80)))) assert.Pointer(conn).IsNil() }
func (this *DokodemoDoor) HandleTCPConnection(conn internet.Connection) { defer conn.Close() var dest v2net.Destination if this.config.FollowRedirect { originalDest := GetOriginalDestination(conn) if originalDest.Network != v2net.Network_Unknown { log.Info("Dokodemo: Following redirect to: ", originalDest) dest = originalDest } } if dest.Network == v2net.Network_Unknown && this.address != nil && this.port > v2net.Port(0) { dest = v2net.TCPDestination(this.address, this.port) } if dest.Network == v2net.Network_Unknown { log.Info("Dokodemo: Unknown destination, stop forwarding...") return } log.Info("Dokodemo: Handling request to ", dest) ray := this.packetDispatcher.DispatchToOutbound(&proxy.SessionInfo{ Source: v2net.DestinationFromAddr(conn.RemoteAddr()), Destination: dest, Inbound: this.meta, }) defer ray.InboundOutput().Release() var wg sync.WaitGroup reader := v2net.NewTimeOutReader(this.config.Timeout, conn) defer reader.Release() wg.Add(1) go func() { v2reader := v2io.NewAdaptiveReader(reader) defer v2reader.Release() v2io.Pipe(v2reader, ray.InboundInput()) wg.Done() ray.InboundInput().Close() }() wg.Add(1) go func() { v2writer := v2io.NewAdaptiveWriter(conn) defer v2writer.Release() v2io.Pipe(ray.InboundOutput(), v2writer) wg.Done() }() wg.Wait() }
func (this *InboundDetourHandlerDynamic) pickUnusedPort() v2net.Port { delta := int(this.config.PortRange.To) - int(this.config.PortRange.From) + 1 for { r := dice.Roll(delta) port := this.config.PortRange.FromPort() + v2net.Port(r) _, used := this.portsInUse[port] if !used { return port } } }
func (this *Server) handleConnection(conn internet.Connection) { defer conn.Close() timedReader := v2net.NewTimeOutReader(this.config.Timeout, conn) reader := bufio.NewReaderSize(timedReader, 2048) request, err := http.ReadRequest(reader) if err != nil { if err != io.EOF { log.Warning("HTTP: Failed to read http request: ", err) } return } log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("HTTP: Malformed proxy host (", host, "): ", err) return } log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") session := &proxy.SessionInfo{ Source: v2net.DestinationFromAddr(conn.RemoteAddr()), Destination: dest, Inbound: this.meta, } if strings.ToUpper(request.Method) == "CONNECT" { this.handleConnect(request, session, reader, conn) } else { this.handlePlainHTTP(request, session, reader, conn) } }
func TestServerPicker(t *testing.T) { assert := assert.On(t) list := NewServerList() list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid())) list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second)))) list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(3)), BeforeTime(time.Now().Add(time.Second)))) picker := NewRoundRobinServerPicker(list) server := picker.PickServer() assert.Port(server.Destination().Port).Equals(1) server = picker.PickServer() assert.Port(server.Destination().Port).Equals(2) server = picker.PickServer() assert.Port(server.Destination().Port).Equals(3) server = picker.PickServer() assert.Port(server.Destination().Port).Equals(1) time.Sleep(2 * time.Second) server = picker.PickServer() assert.Port(server.Destination().Port).Equals(1) server = picker.PickServer() assert.Port(server.Destination().Port).Equals(1) }