func Dial(dest v2net.Destination) (net.Conn, error) { var ip net.IP if dest.Address().IsIPv4() || dest.Address().IsIPv6() { ip = dest.Address().IP() } else { ips, err := net.LookupIP(dest.Address().Domain()) if err != nil { return nil, err } if len(ips) == 0 { return nil, ErrInvalidHost } ip = ips[dice.Roll(len(ips))] } if dest.IsTCP() { return net.DialTCP("tcp", nil, &net.TCPAddr{ IP: ip, Port: int(dest.Port()), }) } else { return net.DialUDP("udp", nil, &net.UDPAddr{ IP: ip, Port: int(dest.Port()), }) } }
func Dial(dest v2net.Destination) (net.Conn, error) { if dest.Address().IsDomain() { dialer := &net.Dialer{ Timeout: time.Second * 60, DualStack: true, } network := "tcp" if dest.IsUDP() { network = "udp" } return dialer.Dial(network, dest.NetAddr()) } ip := dest.Address().IP() if dest.IsTCP() { return net.DialTCP("tcp", nil, &net.TCPAddr{ IP: ip, Port: int(dest.Port()), }) } else { return net.DialUDP("udp", nil, &net.UDPAddr{ IP: ip, Port: int(dest.Port()), }) } }
func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error { defer ray.OutboundInput().Release() defer ray.OutboundOutput().Close() var rec *protocol.ServerSpec var conn internet.Connection err := retry.Timed(5, 100).On(func() error { rec = this.serverPicker.PickServer() rawConn, err := internet.Dial(this.meta.Address, rec.Destination(), this.meta.StreamSettings) if err != nil { return err } conn = rawConn return nil }) if err != nil { log.Error("VMess|Outbound: Failed to find an available destination:", err) return err } log.Info("VMess|Outbound: Tunneling request to ", target, " via ", rec.Destination) command := protocol.RequestCommandTCP if target.IsUDP() { command = protocol.RequestCommandUDP } request := &protocol.RequestHeader{ Version: encoding.Version, User: rec.PickUser(), Command: command, Address: target.Address(), Port: target.Port(), Option: protocol.RequestOptionChunkStream, } defer conn.Close() conn.SetReusable(true) if conn.Reusable() { // Conn reuse may be disabled on transportation layer request.Option.Set(protocol.RequestOptionConnectionReuse) } input := ray.OutboundInput() output := ray.OutboundOutput() var requestFinish, responseFinish sync.Mutex requestFinish.Lock() responseFinish.Lock() session := encoding.NewClientSession(protocol.DefaultIDHash) go this.handleRequest(session, conn, request, payload, input, &requestFinish) go this.handleResponse(session, conn, request, rec.Destination(), output, &responseFinish) requestFinish.Lock() responseFinish.Lock() return nil }
func socks5UDPRequest(address v2net.Destination, payload []byte) []byte { request := make([]byte, 0, 1024) request = append(request, 0, 0, 0) request = appendAddress(request, address.Address()) request = address.Port().Bytes(request) request = append(request, payload...) return request }
func (this *FieldRule) Apply(dest v2net.Destination) bool { address := dest.Address() if len(this.Domain) > 0 { if !address.IsDomain() { return false } foundMatch := false for _, domain := range this.Domain { if domain.Match(address.Domain()) { foundMatch = true break } } if !foundMatch { return false } } if this.IP != nil && len(this.IP) > 0 { if !(address.IsIPv4() || address.IsIPv6()) { return false } foundMatch := false for _, ipnet := range this.IP { if ipnet.Contains(address.IP()) { foundMatch = true break } } if !foundMatch { return false } } if this.Port != nil { port := dest.Port() if port.Value() < this.Port.From().Value() || port.Value() > this.Port.To().Value() { return false } } if this.Network != nil { if !this.Network.HasNetwork(v2net.Network(dest.Network())) { return false } } return true }
func DialKCP(src v2net.Address, dest v2net.Destination) (internet.Connection, error) { udpDest := v2net.UDPDestination(dest.Address(), dest.Port()) log.Info("Dialling KCP to ", udpDest) conn, err := internet.DialToDest(src, udpDest) if err != nil { return nil, err } cpip := NewSimpleAuthenticator() conv := uint16(atomic.AddUint32(&globalConv, 1)) session := NewConnection(conv, conn, conn.LocalAddr().(*net.UDPAddr), conn.RemoteAddr().(*net.UDPAddr), cpip) session.FetchInputFrom(conn) return session, nil }
// @Private func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination { ips := this.dnsServer.Get(dest.Address().Domain()) if len(ips) == 0 { return nil } dests := make([]v2net.Destination, len(ips)) for idx, ip := range ips { if dest.IsTCP() { dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port()) } else { dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port()) } } return dests }
func (this *Listener) OnReceive(payload *alloc.Buffer, src v2net.Destination) { defer payload.Release() if valid := this.block.Open(payload); !valid { log.Info("KCP|Listener: discarding invalid payload from ", src) return } if !this.running { return } this.Lock() defer this.Unlock() if !this.running { return } if payload.Len() < 4 { return } conv := serial.BytesToUint16(payload.Value) cmd := Command(payload.Value[2]) sourceId := src.NetAddr() + "|" + serial.Uint16ToString(conv) conn, found := this.sessions[sourceId] if !found { if cmd == CommandTerminate { return } log.Debug("KCP|Listener: Creating session with id(", sourceId, ") from ", src) writer := &Writer{ id: sourceId, hub: this.hub, dest: src, listener: this, } srcAddr := &net.UDPAddr{ IP: src.Address().IP(), Port: int(src.Port()), } conn = NewConnection(conv, writer, this.localAddr, srcAddr, this.block) select { case this.awaitingConns <- conn: case <-time.After(time.Second * 5): conn.Close() return } this.sessions[sourceId] = conn } conn.Input(payload.Value) }
func (this *VMessOutboundHandler) startCommunicate(request *proto.RequestHeader, dest v2net.Destination, ray ray.OutboundRay, firstPacket v2net.Packet) error { var destIP net.IP if dest.Address().IsIPv4() || dest.Address().IsIPv6() { destIP = dest.Address().IP() } else { ips, err := net.LookupIP(dest.Address().Domain()) if err != nil { return err } destIP = ips[0] } conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: destIP, Port: int(dest.Port()), }) if err != nil { log.Error("Failed to open ", dest, ": ", err) if ray != nil { close(ray.OutboundOutput()) } return err } log.Info("VMessOut: Tunneling request to ", request.Address, " via ", dest) defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() var requestFinish, responseFinish sync.Mutex requestFinish.Lock() responseFinish.Lock() session := raw.NewClientSession(proto.DefaultIDHash) go this.handleRequest(session, conn, request, firstPacket, input, &requestFinish) go this.handleResponse(session, conn, request, dest, output, &responseFinish) requestFinish.Lock() conn.CloseWrite() responseFinish.Lock() return nil }
func startCommunicate(request *protocol.VMessRequest, dest v2net.Destination, ray ray.OutboundRay, firstPacket v2net.Packet) error { var destIp net.IP if dest.Address().IsIPv4() || dest.Address().IsIPv6() { destIp = dest.Address().IP() } else { ips, err := net.LookupIP(dest.Address().Domain()) if err != nil { return err } destIp = ips[0] } conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: destIp, Port: int(dest.Port()), }) if err != nil { log.Error("Failed to open ", dest, ": ", err) if ray != nil { close(ray.OutboundOutput()) } return err } log.Info("VMessOut: Tunneling request to ", request.Address, " via ", dest) defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() var requestFinish, responseFinish sync.Mutex requestFinish.Lock() responseFinish.Lock() go handleRequest(conn, request, firstPacket, input, &requestFinish) go handleResponse(conn, request, output, &responseFinish, (request.Command == protocol.CmdUDP)) requestFinish.Lock() conn.CloseWrite() responseFinish.Lock() return nil }
// @Private func (this *FreedomConnection) ResolveIP(destination v2net.Destination) v2net.Destination { if !destination.Address().IsDomain() { return destination } ips := this.dns.Get(destination.Address().Domain()) if len(ips) == 0 { log.Info("Freedom: DNS returns nil answer. Keep domain as is.") return destination } ip := ips[dice.Roll(len(ips))] var newDest v2net.Destination if destination.IsTCP() { newDest = v2net.TCPDestination(v2net.IPAddress(ip), destination.Port()) } else { newDest = v2net.UDPDestination(v2net.IPAddress(ip), destination.Port()) } log.Info("Freedom: Changing destination from ", destination, " to ", newDest) return newDest }
func socks5Request(command byte, address v2net.Destination) []byte { request := []byte{socks5Version, command, 0} request = appendAddress(request, address.Address()) request = address.Port().Bytes(request) return request }
func (this *UDPHub) WriteTo(payload []byte, dest v2net.Destination) (int, error) { return this.conn.WriteToUDP(payload, &net.UDPAddr{ IP: dest.Address().IP(), Port: int(dest.Port()), }) }
func (this *PortMatcher) Apply(dest v2net.Destination) bool { return this.port.Contains(dest.Port()) }