Use dns in router

pull/168/head
v2ray 2016-05-16 00:25:34 -07:00
parent 3b545abe02
commit dac1339d6e
15 changed files with 92 additions and 34 deletions

View File

@ -1,4 +1,4 @@
package internal
package dns
import (
v2net "github.com/v2ray/v2ray-core/common/net"

View File

@ -1,6 +1,6 @@
// +build json
package internal
package dns
import (
"encoding/json"

View File

@ -28,10 +28,6 @@ func (this *contextedDnsServer) Get(domain string) []net.IP {
return this.dnsCache.Get(this.context, domain)
}
func CreateDNSServer(rawConfig interface{}) (Server, error) {
return nil, nil
}
func init() {
app.Register(APP_ID, func(context app.Context, obj interface{}) interface{} {
dcContext := obj.(dnsServerWithContext)

View File

@ -1,4 +1,4 @@
package internal
package dns
import (
"math/rand"

View File

@ -1,4 +1,4 @@
package internal
package dns
import (
"net"
@ -19,14 +19,14 @@ type DomainRecord struct {
A *ARecord
}
type Server struct {
type CacheServer struct {
sync.RWMutex
records map[string]*DomainRecord
servers []NameServer
}
func NewServer(space app.Space, config *Config) *Server {
server := &Server{
func NewCacheServer(space app.Space, config *Config) *CacheServer {
server := &CacheServer{
records: make(map[string]*DomainRecord),
servers: make([]NameServer, len(config.NameServers)),
}
@ -38,7 +38,7 @@ func NewServer(space app.Space, config *Config) *Server {
}
//@Private
func (this *Server) GetCached(domain string) []net.IP {
func (this *CacheServer) GetCached(domain string) []net.IP {
this.RLock()
defer this.RUnlock()
@ -48,7 +48,7 @@ func (this *Server) GetCached(domain string) []net.IP {
return nil
}
func (this *Server) Get(context app.Context, domain string) []net.IP {
func (this *CacheServer) Get(context app.Context, domain string) []net.IP {
domain = dns.Fqdn(domain)
ips := this.GetCached(domain)
if ips != nil {

View File

@ -1,4 +1,4 @@
package internal_test
package dns_test
import (
"net"
@ -6,7 +6,7 @@ import (
"github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/dispatcher"
. "github.com/v2ray/v2ray-core/app/dns/internal"
. "github.com/v2ray/v2ray-core/app/dns"
apptesting "github.com/v2ray/v2ray-core/app/testing"
v2net "github.com/v2ray/v2ray-core/common/net"
netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
@ -45,8 +45,8 @@ func TestDnsAdd(t *testing.T) {
spaceController.Bind(dispatcher.APP_ID, d)
space := spaceController.ForContext("test")
domain := "v2ray.com"
server := NewServer(space, &Config{
domain := "local.v2ray.com"
server := NewCacheServer(space, &Config{
NameServers: []v2net.Destination{
v2net.UDPDestination(v2net.IPAddress([]byte{8, 8, 8, 8}), v2net.Port(53)),
},
@ -54,6 +54,6 @@ func TestDnsAdd(t *testing.T) {
ips := server.Get(&apptesting.Context{
CallerTagValue: "a",
}, domain)
assert.Int(len(ips)).Equals(2)
netassert.IP(ips[0].To4()).Equals(net.IP([]byte{104, 27, 154, 107}))
assert.Int(len(ips)).Equals(1)
netassert.IP(ips[0].To4()).Equals(net.IP([]byte{127, 0, 0, 1}))
}

View File

@ -1,6 +1,7 @@
package router
import (
"github.com/v2ray/v2ray-core/app"
v2net "github.com/v2ray/v2ray-core/common/net"
)
@ -9,7 +10,7 @@ type Router interface {
}
type RouterFactory interface {
Create(rawConfig interface{}) (Router, error)
Create(rawConfig interface{}, space app.Space) (Router, error)
}
var (
@ -22,9 +23,9 @@ func RegisterRouter(name string, factory RouterFactory) error {
return nil
}
func CreateRouter(name string, rawConfig interface{}) (Router, error) {
func CreateRouter(name string, rawConfig interface{}, space app.Space) (Router, error) {
if factory, found := routerCache[name]; found {
return factory.Create(rawConfig)
return factory.Create(rawConfig, space)
}
return nil, ErrorRouterNotFound
}

View File

@ -21,7 +21,7 @@ func TestRouter(t *testing.T) {
pointConfig, err := point.LoadConfig(filepath.Join(baseDir, "vpoint_socks_vmess.json"))
assert.Error(err).IsNil()
router, err := CreateRouter(pointConfig.RouterConfig.Strategy, pointConfig.RouterConfig.Settings)
router, err := CreateRouter(pointConfig.RouterConfig.Strategy, pointConfig.RouterConfig.Settings, nil)
assert.Error(err).IsNil()
dest := v2net.TCPDestination(v2net.IPAddress(net.ParseIP("120.135.126.1")), 80)

View File

@ -13,7 +13,15 @@ func (this *Rule) Apply(dest v2net.Destination) bool {
return this.Condition.Apply(dest)
}
type DomainStrategy int
var (
DomainAsIs = DomainStrategy(0)
AlwaysUseIP = DomainStrategy(1)
UseIPIfNonMatch = DomainStrategy(2)
)
type RouterRuleConfig struct {
Rules []*Rule
ResolveDomain bool
Rules []*Rule
DomainStrategy DomainStrategy
}

View File

@ -117,16 +117,22 @@ func ParseRule(msg json.RawMessage) *Rule {
func init() {
router.RegisterRouterConfig("rules", func(data []byte) (interface{}, error) {
type JsonConfig struct {
RuleList []json.RawMessage `json:"rules"`
ResolveDomain bool `json:"resolveDomain"`
RuleList []json.RawMessage `json:"rules"`
DomainStrategy string `json:"domainStrategy"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return nil, err
}
config := &RouterRuleConfig{
Rules: make([]*Rule, len(jsonConfig.RuleList)),
ResolveDomain: jsonConfig.ResolveDomain,
Rules: make([]*Rule, len(jsonConfig.RuleList)),
DomainStrategy: DomainAsIs,
}
domainStrategy := serial.StringLiteral(jsonConfig.DomainStrategy).ToLower()
if domainStrategy.String() == "alwaysip" {
config.DomainStrategy = AlwaysUseIP
} else if domainStrategy.String() == "ipifnonmatch" {
config.DomainStrategy = UseIPIfNonMatch
}
for idx, rawRule := range jsonConfig.RuleList {
rule := ParseRule(rawRule)

View File

@ -4,6 +4,8 @@ import (
"errors"
"time"
"github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/collect"
v2net "github.com/v2ray/v2ray-core/common/net"
@ -40,21 +42,54 @@ func (this *cacheEntry) Extend() {
type Router struct {
config *RouterRuleConfig
cache *collect.ValidityMap
space app.Space
}
func NewRouter(config *RouterRuleConfig) *Router {
func NewRouter(config *RouterRuleConfig, space app.Space) *Router {
return &Router{
config: config,
cache: collect.NewValidityMap(3600),
space: space,
}
}
// @Private
func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
dnsServer := this.space.GetApp(dns.APP_ID).(dns.Server)
ips := 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 *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().IsDomain() {
ipDests := this.ResolveIP(dest)
if ipDests != nil {
for _, ipDest := range ipDests {
for _, rule := range this.config.Rules {
if rule.Apply(ipDest) {
return rule.Tag, nil
}
}
}
}
}
return "", ErrorNoRuleApplicable
}
@ -72,8 +107,8 @@ func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
type RouterFactory struct {
}
func (this *RouterFactory) Create(rawConfig interface{}) (router.Router, error) {
return NewRouter(rawConfig.(*RouterRuleConfig)), nil
func (this *RouterFactory) Create(rawConfig interface{}, space app.Space) (router.Router, error) {
return NewRouter(rawConfig.(*RouterRuleConfig), space), nil
}
func init() {

View File

@ -21,7 +21,7 @@ func TestSimpleRouter(t *testing.T) {
},
}
router := NewRouter(config)
router := NewRouter(config, nil)
tag, err := router.TakeDetour(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80))
assert.Error(err).IsNil()

View File

@ -1,6 +1,7 @@
package point
import (
"github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
@ -47,6 +48,7 @@ type Config struct {
Port v2net.Port
LogConfig *LogConfig
RouterConfig *router.Config
DNSConfig *dns.Config
InboundConfig *ConnectionConfig
OutboundConfig *ConnectionConfig
InboundDetours []*InboundDetourConfig

View File

@ -8,6 +8,7 @@ import (
"os"
"strings"
"github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
@ -22,6 +23,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
Port v2net.Port `json:"port"` // Port of this Point server.
LogConfig *LogConfig `json:"log"`
RouterConfig *router.Config `json:"routing"`
DNSConfig *dns.Config `json:"dns"`
InboundConfig *ConnectionConfig `json:"inbound"`
OutboundConfig *ConnectionConfig `json:"outbound"`
InboundDetours []*InboundDetourConfig `json:"inboundDetour"`
@ -38,6 +40,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
this.OutboundConfig = jsonConfig.OutboundConfig
this.InboundDetours = jsonConfig.InboundDetours
this.OutboundDetours = jsonConfig.OutboundDetours
this.DNSConfig = jsonConfig.DNSConfig
return nil
}

View File

@ -7,6 +7,7 @@ package point
import (
"github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/dispatcher"
"github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/proxyman"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/log"
@ -120,9 +121,15 @@ func NewPoint(pConfig *Config) (*Point, error) {
}
}
dnsConfig := pConfig.DNSConfig
if dnsConfig != nil {
dnsServer := dns.NewCacheServer(vpoint.space.ForContext("system.dns"), dnsConfig)
vpoint.space.Bind(dns.APP_ID, dnsServer)
}
routerConfig := pConfig.RouterConfig
if routerConfig != nil {
r, err := router.CreateRouter(routerConfig.Strategy, routerConfig.Settings)
r, err := router.CreateRouter(routerConfig.Strategy, routerConfig.Settings, vpoint.space.ForContext("system.router"))
if err != nil {
log.Error("Failed to create router: ", err)
return nil, ErrorBadConfiguration