func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool { if !dest.Address().Family().IsDomain() { return false } domain := dest.Address().Domain() return this.pattern.MatchString(strings.ToLower(domain)) }
func wsDial(src v2net.Address, dest v2net.Destination) (*wsconn, error) { commonDial := func(network, addr string) (net.Conn, error) { return internet.DialToDest(src, dest) } tlsconf := &tls.Config{ServerName: dest.Address().Domain(), InsecureSkipVerify: effectiveConfig.DeveloperInsecureSkipVerify} dialer := websocket.Dialer{NetDial: commonDial, ReadBufferSize: 65536, WriteBufferSize: 65536, TLSClientConfig: tlsconf} effpto := calcPto(dest) uri := func(dst v2net.Destination, pto string, path string) string { return fmt.Sprintf("%v://%v/%v", pto, dst.NetAddr(), path) }(dest, effpto, effectiveConfig.Path) conn, resp, err := dialer.Dial(uri, nil) if err != nil { if resp != nil { reason, reasonerr := ioutil.ReadAll(resp.Body) log.Info(string(reason), reasonerr) } return nil, err } return func() internet.Connection { connv2ray := &wsconn{wsc: conn, connClosing: false} connv2ray.setup() return connv2ray }().(*wsconn), nil }
func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool { if !dest.Address().Family().IsDomain() { return false } domain := dest.Address().Domain() return strings.Contains(domain, this.pattern) }
func (this *FreedomConnection) Dispatch(destination v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error { log.Info("Freedom: Opening connection to ", destination) defer payload.Release() defer ray.OutboundInput().Release() defer ray.OutboundOutput().Close() var conn internet.Connection if this.domainStrategy == DomainStrategyUseIP && destination.Address().Family().IsDomain() { destination = this.ResolveIP(destination) } err := retry.Timed(5, 100).On(func() error { rawConn, err := internet.Dial(this.meta.Address, destination, this.meta.StreamSettings) if err != nil { return err } conn = rawConn return nil }) if err != nil { log.Warning("Freedom: Failed to open connection to ", destination, ": ", err) return err } defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() if !payload.IsEmpty() { conn.Write(payload.Value) } go func() { v2writer := v2io.NewAdaptiveWriter(conn) defer v2writer.Release() v2io.Pipe(input, v2writer) if tcpConn, ok := conn.(*tcp.RawConnection); ok { tcpConn.CloseWrite() } }() var reader io.Reader = conn timeout := this.timeout if destination.IsUDP() { timeout = 16 } if timeout > 0 { reader = v2net.NewTimeOutReader(int(timeout) /* seconds */, conn) } v2reader := v2io.NewAdaptiveReader(reader) v2io.Pipe(v2reader, output) v2reader.Release() ray.OutboundOutput().Close() return nil }
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 *VMessOutboundHandler) handleCommand(dest v2net.Destination, cmd protocol.ResponseCommand) { switch typedCommand := cmd.(type) { case *protocol.CommandSwitchAccount: if typedCommand.Host == nil { typedCommand.Host = dest.Address() } this.handleSwitchAccount(typedCommand) default: } }
// Private: Visible for testing. 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 Dial(src v2net.Address, dest v2net.Destination, settings *StreamSettings) (Connection, error) { var connection Connection var err error if dest.IsTCP() { switch { case settings.IsCapableOf(StreamConnectionTypeTCP): connection, err = TCPDialer(src, dest) case settings.IsCapableOf(StreamConnectionTypeKCP): connection, err = KCPDialer(src, dest) case settings.IsCapableOf(StreamConnectionTypeWebSocket): connection, err = WSDialer(src, dest) /*Warning: Hours wasted: the following item must be last one internet.StreamConnectionType have a default value of 1, so the following attempt will catch all. */ case settings.IsCapableOf(StreamConnectionTypeRawTCP): connection, err = RawTCPDialer(src, dest) default: return nil, ErrUnsupportedStreamType } if err != nil { return nil, err } if settings.Security == StreamSecurityTypeNone { return connection, nil } config := settings.TLSSettings.GetTLSConfig() if dest.Address().Family().IsDomain() { config.ServerName = dest.Address().Domain() } tlsConn := tls.Client(connection, config) return v2tls.NewConnection(tlsConn), nil } return UDPDialer(src, dest) }
func DialKCP(src v2net.Address, dest v2net.Destination) (internet.Connection, error) { udpDest := v2net.UDPDestination(dest.Address(), dest.Port()) log.Info("KCP|Dialer: Dialing KCP to ", udpDest) conn, err := internet.DialToDest(src, udpDest) if err != nil { log.Error("KCP|Dialer: Failed to dial to dest: ", err) return nil, err } cpip, err := effectiveConfig.GetAuthenticator() if err != nil { log.Error("KCP|Dialer: Failed to create authenticator: ", err) return nil, err } 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: Visible for testing. func (this *FreedomConnection) ResolveIP(destination v2net.Destination) v2net.Destination { if !destination.Address().Family().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 (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) { for _, rule := range this.config.Rules { if rule.Apply(dest) { return rule.Tag, nil } } if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().Family().IsDomain() { log.Info("Router: Looking up IP for ", dest) ipDests := this.ResolveIP(dest) if ipDests != nil { for _, ipDest := range ipDests { log.Info("Router: Trying IP ", ipDest) for _, rule := range this.config.Rules { if rule.Apply(ipDest) { return rule.Tag, nil } } } } } return "", ErrNoRuleApplicable }
func (this *IPv4Matcher) Apply(dest v2net.Destination) bool { if !dest.Address().Family().Either(v2net.AddressFamilyIPv4) { return false } return this.ipv4net.Contains(dest.Address().IP()) }
func (this *CIDRMatcher) Apply(dest v2net.Destination) bool { if !dest.Address().Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) { return false } return this.cidr.Contains(dest.Address().IP()) }
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 socks5Request(command byte, address v2net.Destination) []byte { request := []byte{socks5Version, command, 0} request = appendAddress(request, address.Address()) request = address.Port().Bytes(request) return request }