diff --git a/common/net/json/host.go b/common/net/json/host.go new file mode 100644 index 000000000..41fade702 --- /dev/null +++ b/common/net/json/host.go @@ -0,0 +1,53 @@ +package json + +import ( + "encoding/json" + "net" +) + +type Host struct { + domain string + ip net.IP +} + +func NewIPHost(ip net.IP) *Host { + return &Host{ + ip: ip, + } +} + +func NewDomainHost(domain string) *Host { + return &Host{ + domain: domain, + } +} + +func (this *Host) UnmarshalJSON(data []byte) error { + var rawStr string + if err := json.Unmarshal(data, &rawStr); err != nil { + return err + } + ip := net.ParseIP(rawStr) + if ip != nil { + this.ip = ip + } else { + this.domain = rawStr + } + return nil +} + +func (this *Host) IsIP() bool { + return this.ip != nil +} + +func (this *Host) IsDomain() bool { + return !this.IsIP() +} + +func (this *Host) IP() net.IP { + return this.ip +} + +func (this *Host) Domain() string { + return this.domain +} diff --git a/common/net/json/host_test.go b/common/net/json/host_test.go new file mode 100644 index 000000000..6eee6633f --- /dev/null +++ b/common/net/json/host_test.go @@ -0,0 +1,35 @@ +package json_test + +import ( + "encoding/json" + "net" + "testing" + + . "github.com/v2ray/v2ray-core/common/net/json" + v2testing "github.com/v2ray/v2ray-core/testing" + "github.com/v2ray/v2ray-core/testing/assert" +) + +func TestIPParsing(t *testing.T) { + v2testing.Current(t) + + rawJson := "\"8.8.8.8\"" + host := &Host{} + err := json.Unmarshal([]byte(rawJson), host) + assert.Error(err).IsNil() + assert.Bool(host.IsIP()).IsTrue() + assert.Bool(host.IsDomain()).IsFalse() + assert.Bool(host.IP().Equal(net.ParseIP("8.8.8.8"))).IsTrue() +} + +func TestDomainParsing(t *testing.T) { + v2testing.Current(t) + + rawJson := "\"v2ray.com\"" + host := &Host{} + err := json.Unmarshal([]byte(rawJson), host) + assert.Error(err).IsNil() + assert.Bool(host.IsIP()).IsFalse() + assert.Bool(host.IsDomain()).IsTrue() + assert.StringLiteral(host.Domain()).Equals("v2ray.com") +} diff --git a/proxy/dokodemo/dokodemo_test.go b/proxy/dokodemo/dokodemo_test.go index e7dec464d..702e566ce 100644 --- a/proxy/dokodemo/dokodemo_test.go +++ b/proxy/dokodemo/dokodemo_test.go @@ -42,7 +42,7 @@ func TestDokodemoTCP(t *testing.T) { InboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "dokodemo-door", SettingsValue: &json.DokodemoConfig{ - Host: "127.0.0.1", + Host: v2netjson.NewIPHost(net.ParseIP("127.0.0.1")), Port: port, NetworkList: &networkList, TimeoutValue: 0, @@ -104,7 +104,7 @@ func TestDokodemoUDP(t *testing.T) { InboundConfigValue: &mocks.ConnectionConfig{ ProtocolValue: "dokodemo-door", SettingsValue: &json.DokodemoConfig{ - Host: "127.0.0.1", + Host: v2netjson.NewIPHost(net.ParseIP("127.0.0.1")), Port: port, NetworkList: &networkList, TimeoutValue: 0, diff --git a/proxy/dokodemo/json/json.go b/proxy/dokodemo/json/json.go index 72a503c73..560aad72e 100644 --- a/proxy/dokodemo/json/json.go +++ b/proxy/dokodemo/json/json.go @@ -1,26 +1,23 @@ package json import ( - "net" - v2net "github.com/v2ray/v2ray-core/common/net" v2netjson "github.com/v2ray/v2ray-core/common/net/json" "github.com/v2ray/v2ray-core/proxy/common/config/json" ) type DokodemoConfig struct { - Host string `json:"address"` + Host *v2netjson.Host `json:"address"` Port v2net.Port `json:"port"` NetworkList *v2netjson.NetworkList `json:"network"` TimeoutValue int `json:"timeout"` } func (this *DokodemoConfig) Address() v2net.Address { - ip := net.ParseIP(this.Host) - if ip != nil { - return v2net.IPAddress(ip, this.Port) + if this.Host.IsIP() { + return v2net.IPAddress(this.Host.IP(), this.Port) } else { - return v2net.DomainAddress(this.Host, this.Port) + return v2net.DomainAddress(this.Host.Domain(), this.Port) } } diff --git a/proxy/vmess/outbound/json/outbound.go b/proxy/vmess/outbound/json/outbound.go index 47d8e63ac..d08b8aa54 100644 --- a/proxy/vmess/outbound/json/outbound.go +++ b/proxy/vmess/outbound/json/outbound.go @@ -2,10 +2,10 @@ package json import ( "encoding/json" - "net" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + v2netjson "github.com/v2ray/v2ray-core/common/net/json" proxyconfig "github.com/v2ray/v2ray-core/proxy/common/config" jsonconfig "github.com/v2ray/v2ray-core/proxy/common/config/json" "github.com/v2ray/v2ray-core/proxy/vmess" @@ -20,7 +20,7 @@ type ConfigTarget struct { func (t *ConfigTarget) UnmarshalJSON(data []byte) error { type RawConfigTarget struct { - Address string `json:"address"` + Address *v2netjson.Host `json:"address"` Port v2net.Port `json:"port"` Users []*vmessjson.ConfigUser `json:"users"` } @@ -33,12 +33,15 @@ func (t *ConfigTarget) UnmarshalJSON(data []byte) error { return proxyconfig.BadConfiguration } t.Users = rawConfig.Users - ip := net.ParseIP(rawConfig.Address) - if ip == nil { - log.Error("Unable to parse IP: %s", rawConfig.Address) + if rawConfig.Address == nil { + log.Error("Address is not set in VMess outbound config.") return proxyconfig.BadConfiguration } - t.Address = v2net.IPAddress(ip, rawConfig.Port) + if rawConfig.Address.IsIP() { + t.Address = v2net.IPAddress(rawConfig.Address.IP(), rawConfig.Port) + } else { + t.Address = v2net.DomainAddress(rawConfig.Address.Domain(), rawConfig.Port) + } return nil }