func TestDomainRule(t *testing.T) { assert := assert.On(t) rule := ParseRule([]byte(`{ "type": "field", "domain": [ "ooxx.com", "oxox.com", "regexp:\\.cn$" ], "network": "tcp", "outboundTag": "direct" }`)) assert.Pointer(rule).IsNotNil() cond, err := rule.BuildCondition() assert.Error(err).IsNil() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("www.ooxx.com"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("www.aabb.com"), 80), })).IsFalse() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), 80), })).IsFalse() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("www.12306.cn"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("www.acn.com"), 80), })).IsFalse() }
func TestChinaSitesJson(t *testing.T) { assert := assert.On(t) rule := ParseRule([]byte(`{ "type": "chinasites", "outboundTag": "y" }`)) assert.String(rule.Tag).Equals("y") cond, err := rule.BuildCondition() assert.Error(err).IsNil() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("v.qq.com"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("www.163.com"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("ngacn.cc"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("12306.cn"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("v2ray.com"), 80), })).IsFalse() }
func TestChinaIPJson(t *testing.T) { assert := assert.On(t) rule := ParseRule([]byte(`{ "type": "chinaip", "outboundTag": "x" }`)) assert.String(rule.Tag).Equals("x") cond, err := rule.BuildCondition() assert.Error(err).IsNil() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("121.14.1.189"), 80), })).IsTrue() // sina.com.cn assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("101.226.103.106"), 80), })).IsTrue() // qq.com assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("115.239.210.36"), 80), })).IsTrue() // image.baidu.com assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("120.135.126.1"), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Destination: v2net.TCPDestination(v2net.ParseAddress("8.8.8.8"), 80), })).IsFalse() }
func (v *FreedomConfig) Build() (*serial.TypedMessage, error) { config := new(freedom.Config) config.DomainStrategy = freedom.Config_AS_IS domainStrategy := strings.ToLower(v.DomainStrategy) if domainStrategy == "useip" || domainStrategy == "use_ip" { config.DomainStrategy = freedom.Config_USE_IP } config.Timeout = 600 if v.Timeout != nil { config.Timeout = *v.Timeout } if len(v.Redirect) > 0 { host, portStr, err := net.SplitHostPort(v.Redirect) if err != nil { return nil, errors.Base(err).Message("Config: Invalid redirect address: ", v.Redirect, ": ", err) } port, err := v2net.PortFromString(portStr) if err != nil { return nil, errors.Base(err).Message("Config: Invalid redirect port: ", v.Redirect, ": ", err) } if len(host) == 0 { host = "127.0.0.1" } config.DestinationOverride = &freedom.DestinationOverride{ Server: &protocol.ServerEndpoint{ Address: v2net.NewIPOrDomain(v2net.ParseAddress(host)), Port: uint32(port), }, } } return serial.ToTypedMessage(config), nil }
func (this *Address) UnmarshalJSON(data []byte) error { var rawStr string if err := json.Unmarshal(data, &rawStr); err != nil { return err } this.Address = v2net.ParseAddress(rawStr) return nil }
func (request *Socks5Request) Destination() v2net.Destination { switch request.AddrType { case AddrTypeIPv4: return v2net.TCPDestination(v2net.IPAddress(request.IPv4[:]), request.Port) case AddrTypeIPv6: return v2net.TCPDestination(v2net.IPAddress(request.IPv6[:]), request.Port) case AddrTypeDomain: return v2net.TCPDestination(v2net.ParseAddress(request.Domain), request.Port) default: panic("Unknown address type") } }
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) { if len(packet) < 5 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } request := new(Socks5UDPRequest) // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: if len(packet) < 10 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case AddrTypeIPv6: if len(packet) < 22 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.ParseAddress(domain) dataBegin = 5 + domainLength + 2 default: return nil, errors.Format("Socks|UDP: Unknown address type %d", addrType) } if len(packet) > dataBegin { b := buf.NewSmall() b.Append(packet[dataBegin:]) request.Data = b } return request, nil }
func parseIP(s string) *router.CIDR { var addr, mask string i := strings.Index(s, "/") if i < 0 { addr = s } else { addr = s[:i] mask = s[i+1:] } ip := v2net.ParseAddress(addr) switch ip.Family() { case v2net.AddressFamilyIPv4: bits := uint32(32) if len(mask) > 0 { bits64, err := strconv.ParseUint(mask, 10, 32) if err != nil { return nil } bits = uint32(bits64) } if bits > 32 { log.Warning("Router: invalid network mask: ", bits) return nil } return &router.CIDR{ Ip: []byte(ip.IP()), Prefix: bits, } case v2net.AddressFamilyIPv6: bits := uint32(128) if len(mask) > 0 { bits64, err := strconv.ParseUint(mask, 10, 32) if err != nil { return nil } bits = uint32(bits64) } if bits > 128 { log.Warning("Router: invalid network mask: ", bits) return nil } return &router.CIDR{ Ip: []byte(ip.IP()), Prefix: bits, } default: log.Warning("Router: unsupported address: ", s) return nil } }
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) { if len(packet) < 5 { return nil, transport.ErrCorruptedPacket } request := new(Socks5UDPRequest) // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: if len(packet) < 10 { return nil, transport.ErrCorruptedPacket } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case AddrTypeIPv6: if len(packet) < 22 { return nil, transport.ErrCorruptedPacket } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, transport.ErrCorruptedPacket } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.ParseAddress(domain) dataBegin = 5 + domainLength + 2 default: log.Warning("Unknown address type ", addrType) return nil, ErrorUnknownAddressType } if len(packet) > dataBegin { request.Data = alloc.NewBuffer().Clear().Append(packet[dataBegin:]) } return request, nil }
func DecodeUDPPacket(packet []byte) (*protocol.RequestHeader, []byte, error) { if len(packet) < 5 { return nil, nil, errors.New("Socks|UDP: Insufficient length of packet.") } request := &protocol.RequestHeader{ Version: socks5Version, Command: protocol.RequestCommandUDP, } // packet[0] and packet[1] are reserved if packet[2] != 0 /* fragments */ { return nil, nil, errors.New("Socks|UDP: Fragmented payload.") } addrType := packet[3] var dataBegin int switch addrType { case addrTypeIPv4: if len(packet) < 10 { return nil, nil, errors.New("Socks|UDP: Insufficient length of packet.") } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case addrTypeIPv6: if len(packet) < 22 { return nil, nil, errors.New("Socks|UDP: Insufficient length of packet.") } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case addrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, nil, errors.New("Socks|UDP: Insufficient length of packet.") } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.ParseAddress(domain) dataBegin = 5 + domainLength + 2 default: return nil, nil, errors.New("Socks|UDP: Unknown address type ", addrType) } return request, packet[dataBegin:], nil }
func (this *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) { cmd := new(protocol.CommandSwitchAccount) if len(data) == 0 { return nil, transport.ErrCorruptedPacket } lenHost := int(data[0]) if len(data) < lenHost+1 { return nil, transport.ErrCorruptedPacket } if lenHost > 0 { cmd.Host = v2net.ParseAddress(string(data[1 : 1+lenHost])) } portStart := 1 + lenHost if len(data) < portStart+2 { return nil, transport.ErrCorruptedPacket } cmd.Port = v2net.PortFromBytes(data[portStart : portStart+2]) idStart := portStart + 2 if len(data) < idStart+16 { return nil, transport.ErrCorruptedPacket } cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16]) alterIdStart := idStart + 16 if len(data) < alterIdStart+2 { return nil, transport.ErrCorruptedPacket } cmd.AlterIds = serial.BytesToUint16(data[alterIdStart : alterIdStart+2]) levelStart := alterIdStart + 2 if len(data) < levelStart+1 { return nil, transport.ErrCorruptedPacket } cmd.Level = protocol.UserLevel(data[levelStart]) timeStart := levelStart + 1 if len(data) < timeStart { return nil, transport.ErrCorruptedPacket } cmd.ValidMin = data[timeStart] return cmd, nil }
func (v *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) { cmd := new(protocol.CommandSwitchAccount) if len(data) == 0 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } lenHost := int(data[0]) if len(data) < lenHost+1 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } if lenHost > 0 { cmd.Host = net.ParseAddress(string(data[1 : 1+lenHost])) } portStart := 1 + lenHost if len(data) < portStart+2 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.Port = net.PortFromBytes(data[portStart : portStart+2]) idStart := portStart + 2 if len(data) < idStart+16 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16]) alterIDStart := idStart + 16 if len(data) < alterIDStart+2 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.AlterIds = serial.BytesToUint16(data[alterIDStart : alterIDStart+2]) levelStart := alterIDStart + 2 if len(data) < levelStart+1 { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.Level = uint32(data[levelStart]) timeStart := levelStart + 1 if len(data) < timeStart { return nil, errors.New("VMess|SwitchAccountCommand: Insufficient length.") } cmd.ValidMin = data[timeStart] return cmd, nil }