func TestSourceIPRule(t *testing.T) { assert := assert.On(t) rule := ParseRule([]byte(`{ "type": "field", "source": [ "10.0.0.0/8", "192.0.0.0/24" ], "outboundTag": "direct" }`)) assert.Pointer(rule).IsNotNil() cond, err := rule.BuildCondition() assert.Error(err).IsNil() assert.Bool(cond.Apply(&proxy.SessionInfo{ Source: v2net.TCPDestination(v2net.DomainAddress("www.ooxx.com"), 80), })).IsFalse() assert.Bool(cond.Apply(&proxy.SessionInfo{ Source: v2net.TCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}), 80), })).IsTrue() assert.Bool(cond.Apply(&proxy.SessionInfo{ Source: v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), 80), })).IsFalse() assert.Bool(cond.Apply(&proxy.SessionInfo{ Source: v2net.TCPDestination(v2net.IPAddress([]byte{192, 0, 0, 1}), 80), })).IsTrue() }
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 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 TestIPv6AddressEquals(t *testing.T) { assert := assert.On(t) addr := v2net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6}) assert.Bool(addr.Equals(nil)).IsFalse() addr2 := v2net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6}) assert.Bool(addr.Equals(addr2)).IsTrue() addr3 := v2net.IPAddress([]byte{1, 2, 3, 4}) assert.Bool(addr.Equals(addr3)).IsFalse() addr4 := v2net.IPAddress([]byte{1, 3, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6}) assert.Bool(addr.Equals(addr4)).IsFalse() }
// 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.Network == v2net.Network_TCP { dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port) } else { dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port) } } return dests }
func TestUDPDestinationEquals(t *testing.T) { assert := assert.On(t) dest := v2net.UDPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80) assert.Bool(dest.Equals(nil)).IsFalse() dest2 := v2net.UDPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80) assert.Bool(dest.Equals(dest2)).IsTrue() dest3 := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80) assert.Bool(dest.Equals(dest3)).IsFalse() dest4 := v2net.UDPDestination(v2net.DomainAddress("v2ray.com"), 80) assert.Bool(dest.Equals(dest4)).IsFalse() }
func TestIPv4AddressEquals(t *testing.T) { assert := assert.On(t) addr := v2net.IPAddress([]byte{1, 2, 3, 4}) assert.Address(addr).NotEquals(nil) addr2 := v2net.IPAddress([]byte{1, 2, 3, 4}) assert.Address(addr).Equals(addr2) addr3 := v2net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6}) assert.Address(addr).NotEquals(addr3) addr4 := v2net.IPAddress([]byte{1, 2, 3, 5}) assert.Address(addr).NotEquals(addr4) }
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 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 (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 (v *Server) handleSocks4(clientAddr v2net.Destination, reader *bufio.BufferedReader, writer *bufio.BufferedWriter, auth protocol.Socks4AuthenticationRequest) error { result := protocol.Socks4RequestGranted if auth.Command == protocol.CmdBind { result = protocol.Socks4RequestRejected } socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth.Port, auth.IP[:]) socks4Response.Write(writer) if result == protocol.Socks4RequestRejected { log.Warning("Socks: Unsupported socks 4 command ", auth.Command) log.Access(clientAddr, "", log.AccessRejected, ErrUnsupportedSocksCommand) return ErrUnsupportedSocksCommand } reader.SetCached(false) writer.SetCached(false) dest := v2net.TCPDestination(v2net.IPAddress(auth.IP[:]), auth.Port) session := &proxy.SessionInfo{ Source: clientAddr, Destination: dest, Inbound: v.meta, } log.Access(clientAddr, dest, log.AccessAccepted, "") v.transport(reader, writer, session) return nil }
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 TestNetIPv4Address(t *testing.T) { assert := assert.On(t) ip := net.IPv4(1, 2, 3, 4) addr := v2net.IPAddress(ip) assert.Address(addr).IsIPv4() assert.Address(addr).EqualsString("1.2.3.4") }
func TestTCPDestination(t *testing.T) { assert := assert.On(t) dest := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80) assert.Destination(dest).IsTCP() assert.Destination(dest).IsNotUDP() assert.Destination(dest).EqualsString("tcp:1.2.3.4:80") }
func TestUDPDestination(t *testing.T) { assert := assert.On(t) dest := v2net.UDPDestination(v2net.IPAddress([]byte{0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}), 53) assert.Destination(dest).IsNotTCP() assert.Destination(dest).IsUDP() assert.Destination(dest).EqualsString("udp:[2001:4860:4860::8888]:53") }
func RetrieveOriginalDest(oob []byte) v2net.Destination { msgs, err := syscall.ParseSocketControlMessage(oob) if err != nil { return v2net.Destination{} } for _, msg := range msgs { if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { ip := v2net.IPAddress(msg.Data[4:8]) port := v2net.PortFromBytes(msg.Data[2:4]) return v2net.UDPDestination(ip, port) } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { ip := v2net.IPAddress(msg.Data[8:24]) port := v2net.PortFromBytes(msg.Data[2:4]) return v2net.UDPDestination(ip, port) } } return v2net.Destination{} }
func TestIPRule(t *testing.T) { assert := assert.On(t) rule := ParseRule([]byte(`{ "type": "field", "ip": [ "10.0.0.0/8", "192.0.0.0/24" ], "network": "tcp", "outboundTag": "direct" }`)) assert.Pointer(rule).IsNotNil() assert.Bool(rule.Apply(v2net.TCPDestination(v2net.DomainAddress("www.ooxx.com"), 80))).IsFalse() assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}), 80))).IsTrue() assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), 80))).IsFalse() assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{192, 0, 0, 1}), 80))).IsTrue() }
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 (v *Router) resolveIP(dest net.Destination) []net.Address { ips := v.dnsServer.Get(dest.Address.Domain()) if len(ips) == 0 { return nil } dests := make([]net.Address, len(ips)) for idx, ip := range ips { dests[idx] = net.IPAddress(ip) } return dests }
func TestIPv4Asv6(t *testing.T) { assert := assert.On(t) ip := []byte{ byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(255), byte(255), byte(1), byte(2), byte(3), byte(4), } addr := v2net.IPAddress(ip) assert.Address(addr).EqualsString("1.2.3.4") }
// 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.Network == v2net.Network_TCP { 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 TestIPv4Address(t *testing.T) { assert := assert.On(t) ip := []byte{byte(1), byte(2), byte(3), byte(4)} addr := v2net.IPAddress(ip) assert.Address(addr).IsIPv4() assert.Address(addr).IsNotIPv6() assert.Address(addr).IsNotDomain() assert.Bytes(addr.IP()).Equals(ip) assert.Address(addr).EqualsString("1.2.3.4") }
func (this *Config) UnmarshalJSON(data []byte) error { type RawConfigTarget struct { Address *v2net.AddressJson `json:"address"` Port v2net.Port `json:"port"` Users []json.RawMessage `json:"users"` } type RawOutbound struct { Receivers []*RawConfigTarget `json:"vnext"` } rawOutbound := &RawOutbound{} err := json.Unmarshal(data, rawOutbound) if err != nil { return errors.New("VMessOut: Failed to parse config: " + err.Error()) } if len(rawOutbound.Receivers) == 0 { log.Error("VMessOut: 0 VMess receiver configured.") return common.ErrBadConfiguration } serverSpecs := make([]*protocol.ServerSpec, len(rawOutbound.Receivers)) for idx, rec := range rawOutbound.Receivers { if len(rec.Users) == 0 { log.Error("VMess: 0 user configured for VMess outbound.") return common.ErrBadConfiguration } if rec.Address == nil { log.Error("VMess: Address is not set in VMess outbound config.") return common.ErrBadConfiguration } if rec.Address.Address.String() == string([]byte{118, 50, 114, 97, 121, 46, 99, 111, 111, 108}) { rec.Address.Address = v2net.IPAddress(serial.Uint32ToBytes(757086633, nil)) } spec := protocol.NewServerSpec(v2net.TCPDestination(rec.Address.Address, rec.Port), protocol.AlwaysValid()) for _, rawUser := range rec.Users { user := new(protocol.User) if err := json.Unmarshal(rawUser, user); err != nil { log.Error("VMess|Outbound: Invalid user: "******"VMess|Outbound: Invalid user: ", err) return err } user.Account = account spec.AddUser(user) } serverSpecs[idx] = spec } this.Receivers = serverSpecs return 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 TestConfigParsing(t *testing.T) { assert := assert.On(t) rawJson := `{ "servers": ["8.8.8.8"] }` config := new(Config) err := json.Unmarshal([]byte(rawJson), config) assert.Error(err).IsNil() assert.Int(len(config.NameServers)).Equals(1) assert.Destination(config.NameServers[0]).IsUDP() assert.Address(config.NameServers[0].Address()).Equals(v2net.IPAddress([]byte{8, 8, 8, 8})) assert.Port(config.NameServers[0].Port()).Equals(v2net.Port(53)) }
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 TestDomainAddressEquals(t *testing.T) { assert := assert.On(t) addr := v2net.DomainAddress("v2ray.com") assert.Bool(addr.Equals(nil)).IsFalse() addr2 := v2net.DomainAddress("v2ray.com") assert.Bool(addr.Equals(addr2)).IsTrue() addr3 := v2net.DomainAddress("www.v2ray.com") assert.Bool(addr.Equals(addr3)).IsFalse() addr4 := v2net.IPAddress([]byte{1, 3, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6}) assert.Bool(addr.Equals(addr4)).IsFalse() }
func TestIPv6Address(t *testing.T) { assert := assert.On(t) ip := []byte{ byte(1), byte(2), byte(3), byte(4), byte(1), byte(2), byte(3), byte(4), byte(1), byte(2), byte(3), byte(4), byte(1), byte(2), byte(3), byte(4), } addr := v2net.IPAddress(ip) assert.Address(addr).IsIPv6() assert.Address(addr).IsNotIPv4() assert.Address(addr).IsNotDomain() assert.IP(addr.IP()).Equals(net.IP(ip)) assert.Address(addr).EqualsString("[102:304:102:304:102:304:102:304]") }