mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 09:25:41 +08:00
rule: optimized codes
This commit is contained in:
parent
84b00d6db6
commit
04c65fb444
@ -88,10 +88,10 @@ Use the linux server's ip as your dns server.
|
|||||||
|
|
||||||
#### When client requesting to access http://example1.com (in office.rule), the whole process:
|
#### When client requesting to access http://example1.com (in office.rule), the whole process:
|
||||||
DNS Resolving:
|
DNS Resolving:
|
||||||
1. client sends a udp dns request to linux server, and glider will receive the request(as it listen on default dns port :53)
|
1. client sends a udp dns request to linux server, and glider will receive the request(as it listens on the default dns port :53)
|
||||||
2. upstream dns server choice: glider will lookup it's rule config and find out the dns server to use for this domain(matched "example1.com" in office.rule, so 208.67.222.222:53 will be chosen)
|
2. upstream dns server choice: glider will lookup it's rule config and find out the dns server to use for this domain(matched "example1.com" in office.rule, so 208.67.222.222:53 will be chosen)
|
||||||
3. glider uses the forwarder in office.rule to ask 208.67.222.222:53 for the resolve answers.
|
3. glider uses the forwarder in office.rule to ask 208.67.222.222:53 for the resolve answers(dns over proxy).
|
||||||
4. glider updates it's office rule config, add the resolved ip address to it.
|
4. glider updates it's office rule config, adds the resolved ip address to it.
|
||||||
5. glider adds the resolved ip into ipset "glider", and return the dns answer to client.
|
5. glider adds the resolved ip into ipset "glider", and return the dns answer to client.
|
||||||
|
|
||||||
Destination Accessing:
|
Destination Accessing:
|
||||||
|
6
go.mod
6
go.mod
@ -9,9 +9,9 @@ require (
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/xtaci/kcp-go/v5 v5.5.15
|
github.com/xtaci/kcp-go/v5 v5.5.15
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
|
golang.org/x/net v0.0.0-20200923182212-328152dc79b1 // indirect
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860 // indirect
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect
|
||||||
golang.org/x/tools v0.0.0-20200923053713-ba800b16d873 // indirect
|
golang.org/x/tools v0.0.0-20200923182640-463111b69878 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
12
go.sum
12
go.sum
@ -104,8 +104,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgN
|
|||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
golang.org/x/net v0.0.0-20200923182212-328152dc79b1 h1:Iu68XRPd67wN4aRGGWwwq6bZo/25jR6uu52l/j2KkUE=
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200923182212-328152dc79b1/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -120,15 +120,15 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs=
|
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs=
|
||||||
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860 h1:YEu4SMq7D0cmT7CBbXfcH0NZeuChAXwsHe/9XueUO6o=
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es=
|
||||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
|
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
|
||||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200923053713-ba800b16d873 h1:Q5Sq7Lt0bkn6Ax1NAraQhKRN7xxxy1LV4guxsyFHZx4=
|
golang.org/x/tools v0.0.0-20200923182640-463111b69878 h1:VUw1+Jf6KJPf82mbTQMia6HCnNMv2BbAipkEZ4KTcqQ=
|
||||||
golang.org/x/tools v0.0.0-20200923053713-ba800b16d873/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
golang.org/x/tools v0.0.0-20200923182640-463111b69878/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
10
main.go
10
main.go
@ -50,14 +50,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// global rule proxy
|
// global rule proxy
|
||||||
p := rule.NewProxy(conf.Forward, &conf.StrategyConfig, conf.rules)
|
pxy := rule.NewProxy(conf.Forward, &conf.StrategyConfig, conf.rules)
|
||||||
|
|
||||||
// ipset manager
|
// ipset manager
|
||||||
ipsetM, _ := ipset.NewManager(conf.rules)
|
ipsetM, _ := ipset.NewManager(conf.rules)
|
||||||
|
|
||||||
// check and setup dns server
|
// check and setup dns server
|
||||||
if conf.DNS != "" {
|
if conf.DNS != "" {
|
||||||
d, err := dns.NewServer(conf.DNS, p, &conf.DNSConfig)
|
d, err := dns.NewServer(conf.DNS, pxy, &conf.DNSConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add a handler to update proxy rules when a domain resolved
|
// add a handler to update proxy rules when a domain resolved
|
||||||
d.AddHandler(p.AddDomainIP)
|
d.AddHandler(pxy.AddDomainIP)
|
||||||
if ipsetM != nil {
|
if ipsetM != nil {
|
||||||
d.AddHandler(ipsetM.AddDomainIP)
|
d.AddHandler(ipsetM.AddDomainIP)
|
||||||
}
|
}
|
||||||
@ -90,11 +90,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable checkers
|
// enable checkers
|
||||||
p.Check()
|
pxy.Check()
|
||||||
|
|
||||||
// Proxy Servers
|
// Proxy Servers
|
||||||
for _, listen := range conf.Listen {
|
for _, listen := range conf.Listen {
|
||||||
local, err := proxy.ServerFromURL(listen, p)
|
local, err := proxy.ServerFromURL(listen, pxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/nadoo/glider/common/log"
|
"github.com/nadoo/glider/common/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Direct proxy
|
// Direct proxy.
|
||||||
type Direct struct {
|
type Direct struct {
|
||||||
iface *net.Interface // interface specified by user
|
iface *net.Interface // interface specified by user
|
||||||
ip net.IP
|
ip net.IP
|
||||||
@ -16,7 +16,7 @@ type Direct struct {
|
|||||||
relayTimeout time.Duration
|
relayTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default dialer
|
// Default dialer.
|
||||||
var Default = &Direct{dialTimeout: time.Second * 3}
|
var Default = &Direct{dialTimeout: time.Second * 3}
|
||||||
|
|
||||||
// NewDirect returns a Direct dialer.
|
// NewDirect returns a Direct dialer.
|
||||||
|
@ -2,7 +2,7 @@ package proxy
|
|||||||
|
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
// Proxy is a dialer manager
|
// Proxy is a dialer manager.
|
||||||
type Proxy interface {
|
type Proxy interface {
|
||||||
// Dial connects to the given address via the proxy.
|
// Dial connects to the given address via the proxy.
|
||||||
Dial(network, addr string) (c net.Conn, dialer Dialer, err error)
|
Dial(network, addr string) (c net.Conn, dialer Dialer, err error)
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/nadoo/conflag"
|
"github.com/nadoo/conflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config of rule dialer.
|
// Config is config of rule.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
@ -24,6 +24,19 @@ type Config struct {
|
|||||||
CIDR []string
|
CIDR []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StrategyConfig is config of strategy.
|
||||||
|
type StrategyConfig struct {
|
||||||
|
Strategy string
|
||||||
|
CheckWebSite string
|
||||||
|
CheckInterval int
|
||||||
|
CheckTimeout int
|
||||||
|
CheckDisabledOnly bool
|
||||||
|
MaxFailures int
|
||||||
|
DialTimeout int
|
||||||
|
RelayTimeout int
|
||||||
|
IntFace string
|
||||||
|
}
|
||||||
|
|
||||||
// NewConfFromFile returns a new config from file.
|
// NewConfFromFile returns a new config from file.
|
||||||
func NewConfFromFile(ruleFile string) (*Config, error) {
|
func NewConfFromFile(ruleFile string) (*Config, error) {
|
||||||
p := &Config{Name: ruleFile}
|
p := &Config{Name: ruleFile}
|
||||||
|
@ -12,10 +12,10 @@ import (
|
|||||||
"github.com/nadoo/glider/proxy"
|
"github.com/nadoo/glider/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StatusHandler function will be called when the forwarder's status changed
|
// StatusHandler function will be called when the forwarder's status changed.
|
||||||
type StatusHandler func(*Forwarder)
|
type StatusHandler func(*Forwarder)
|
||||||
|
|
||||||
// Forwarder is a forwarder
|
// Forwarder associates with a `-forward` command, usually a dialer or a chain of dialers.
|
||||||
type Forwarder struct {
|
type Forwarder struct {
|
||||||
proxy.Dialer
|
proxy.Dialer
|
||||||
addr string
|
addr string
|
||||||
|
@ -15,20 +15,7 @@ import (
|
|||||||
"github.com/nadoo/glider/proxy"
|
"github.com/nadoo/glider/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StrategyConfig is strategy config struct.
|
// forwarder slice orderd by priority.
|
||||||
type StrategyConfig struct {
|
|
||||||
Strategy string
|
|
||||||
CheckWebSite string
|
|
||||||
CheckInterval int
|
|
||||||
CheckTimeout int
|
|
||||||
CheckDisabledOnly bool
|
|
||||||
MaxFailures int
|
|
||||||
DialTimeout int
|
|
||||||
RelayTimeout int
|
|
||||||
IntFace string
|
|
||||||
}
|
|
||||||
|
|
||||||
// forwarder slice orderd by priority
|
|
||||||
type priSlice []*Forwarder
|
type priSlice []*Forwarder
|
||||||
|
|
||||||
func (p priSlice) Len() int { return len(p) }
|
func (p priSlice) Len() int { return len(p) }
|
||||||
@ -69,7 +56,7 @@ func NewFwdrGroup(name string, s []string, c *StrategyConfig) *FwdrGroup {
|
|||||||
return newFwdrGroup(name, fwdrs, c)
|
return newFwdrGroup(name, fwdrs, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFwdrGroup returns a new Proxy.
|
// newFwdrGroup returns a new FwdrGroup.
|
||||||
func newFwdrGroup(name string, fwdrs []*Forwarder, c *StrategyConfig) *FwdrGroup {
|
func newFwdrGroup(name string, fwdrs []*Forwarder, c *StrategyConfig) *FwdrGroup {
|
||||||
p := &FwdrGroup{fwdrs: fwdrs, config: c}
|
p := &FwdrGroup{fwdrs: fwdrs, config: c}
|
||||||
sort.Sort(p.fwdrs)
|
sort.Sort(p.fwdrs)
|
||||||
@ -80,22 +67,28 @@ func newFwdrGroup(name string, fwdrs []*Forwarder, c *StrategyConfig) *FwdrGroup
|
|||||||
p.config.CheckWebSite += ":80"
|
p.config.CheckWebSite += ":80"
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c.Strategy {
|
// default scheduler
|
||||||
case "rr":
|
p.next = p.scheduleRR
|
||||||
p.next = p.scheduleRR
|
|
||||||
log.F("[strategy] %s: forward in round robin mode.", name)
|
// if there're more than 1 forwarders, we care about the strategy.
|
||||||
case "ha":
|
if count := len(fwdrs); count > 1 {
|
||||||
p.next = p.scheduleHA
|
switch c.Strategy {
|
||||||
log.F("[strategy] %s: forward in high availability mode.", name)
|
case "rr":
|
||||||
case "lha":
|
p.next = p.scheduleRR
|
||||||
p.next = p.scheduleLHA
|
log.F("[strategy] %s: %d forwarders forward in round robin mode.", name, count)
|
||||||
log.F("[strategy] %s: forward in latency based high availability mode.", name)
|
case "ha":
|
||||||
case "dh":
|
p.next = p.scheduleHA
|
||||||
p.next = p.scheduleDH
|
log.F("[strategy] %s: %d forwarders forward in high availability mode.", name, count)
|
||||||
log.F("[strategy] %s: forward in destination hashing mode.", name)
|
case "lha":
|
||||||
default:
|
p.next = p.scheduleLHA
|
||||||
p.next = p.scheduleRR
|
log.F("[strategy] %s: %d forwarders forward in latency based high availability mode.", name, count)
|
||||||
log.F("[strategy] %s: not supported forward mode '%s', use round robin mode.", name, c.Strategy)
|
case "dh":
|
||||||
|
p.next = p.scheduleDH
|
||||||
|
log.F("[strategy] %s: %d forwarders forward in destination hashing mode.", name, count)
|
||||||
|
default:
|
||||||
|
p.next = p.scheduleRR
|
||||||
|
log.F("[strategy] %s: not supported forward mode '%s', use round robin mode for %d forwarders.", name, c.Strategy, count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range fwdrs {
|
for _, f := range fwdrs {
|
||||||
@ -129,22 +122,6 @@ func (p *FwdrGroup) NextDialer(dstAddr string) proxy.Dialer {
|
|||||||
return p.next(dstAddr)
|
return p.next(dstAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record records result while using the dialer from proxy.
|
|
||||||
func (p *FwdrGroup) Record(dialer proxy.Dialer, success bool) {
|
|
||||||
OnRecord(dialer, success)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnRecord records result while using the dialer from proxy.
|
|
||||||
func OnRecord(dialer proxy.Dialer, success bool) {
|
|
||||||
if fwdr, ok := dialer.(*Forwarder); ok {
|
|
||||||
if !success {
|
|
||||||
fwdr.IncFailures()
|
|
||||||
} else {
|
|
||||||
fwdr.Enable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Priority returns the active priority of dialer.
|
// Priority returns the active priority of dialer.
|
||||||
func (p *FwdrGroup) Priority() uint32 { return atomic.LoadUint32(&p.priority) }
|
func (p *FwdrGroup) Priority() uint32 { return atomic.LoadUint32(&p.priority) }
|
||||||
|
|
||||||
@ -170,7 +147,7 @@ func (p *FwdrGroup) init() {
|
|||||||
if len(p.avail) == 0 {
|
if len(p.avail) == 0 {
|
||||||
// no available forwarders, set priority to 0 to check all forwarders in check func
|
// no available forwarders, set priority to 0 to check all forwarders in check func
|
||||||
p.SetPriority(0)
|
p.SetPriority(0)
|
||||||
// log.F("[strategy] no available forwarders, please check your config file or network settings")
|
// log.F("[group] no available forwarders, please check your config file or network settings")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,14 +157,14 @@ func (p *FwdrGroup) onStatusChanged(fwdr *Forwarder) {
|
|||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if fwdr.Enabled() {
|
if fwdr.Enabled() {
|
||||||
log.F("[strategy] %s changed status from Disabled to Enabled ", fwdr.Addr())
|
log.F("[group] %s(%d) changed status from DISABLED to ENABLED ", fwdr.Addr(), fwdr.Priority())
|
||||||
if fwdr.Priority() == p.Priority() {
|
if fwdr.Priority() == p.Priority() {
|
||||||
p.avail = append(p.avail, fwdr)
|
p.avail = append(p.avail, fwdr)
|
||||||
} else if fwdr.Priority() > p.Priority() {
|
} else if fwdr.Priority() > p.Priority() {
|
||||||
p.init()
|
p.init()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.F("[strategy] %s changed status from Enabled to Disabled", fwdr.Addr())
|
log.F("[group] %s(%d) changed status from ENABLED to DISABLED", fwdr.Addr(), fwdr.Priority())
|
||||||
for i, f := range p.avail {
|
for i, f := range p.avail {
|
||||||
if f == fwdr {
|
if f == fwdr {
|
||||||
p.avail[i], p.avail = p.avail[len(p.avail)-1], p.avail[:len(p.avail)-1]
|
p.avail[i], p.avail = p.avail[len(p.avail)-1], p.avail[:len(p.avail)-1]
|
||||||
@ -250,7 +227,7 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []
|
|||||||
rc, err := fwdr.Dial("tcp", website)
|
rc, err := fwdr.Dial("tcp", website)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fwdr.Disable()
|
fwdr.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", fwdr.Addr(), fwdr.Priority(),
|
log.F("[check] %s(%d) -> %s, FAILED. error in dial: %s", fwdr.Addr(), fwdr.Priority(),
|
||||||
website, err)
|
website, err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -263,7 +240,7 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []
|
|||||||
_, err = io.WriteString(rc, "GET / HTTP/1.0\r\n\r\n")
|
_, err = io.WriteString(rc, "GET / HTTP/1.0\r\n\r\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fwdr.Disable()
|
fwdr.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. error in write: %s", fwdr.Addr(), fwdr.Priority(),
|
log.F("[check] %s(%d) -> %s, FAILED. error in write: %s", fwdr.Addr(), fwdr.Priority(),
|
||||||
website, err)
|
website, err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -271,14 +248,14 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []
|
|||||||
_, err = io.ReadFull(rc, buf)
|
_, err = io.ReadFull(rc, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fwdr.Disable()
|
fwdr.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", fwdr.Addr(), fwdr.Priority(),
|
log.F("[check] %s(%d) -> %s, FAILED. error in read: %s", fwdr.Addr(), fwdr.Priority(),
|
||||||
website, err)
|
website, err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal([]byte("HTTP"), buf) {
|
if !bytes.Equal([]byte("HTTP"), buf) {
|
||||||
fwdr.Disable()
|
fwdr.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", fwdr.Addr(), fwdr.Priority(),
|
log.F("[check] %s(%d) -> %s, FAILED. server response: %s", fwdr.Addr(), fwdr.Priority(),
|
||||||
website, buf)
|
website, buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -288,29 +265,29 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []
|
|||||||
|
|
||||||
if readTime > timeout {
|
if readTime > timeout {
|
||||||
fwdr.Disable()
|
fwdr.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", fwdr.Addr(), fwdr.Priority(),
|
log.F("[check] %s(%d) -> %s, FAILED. check timeout: %s", fwdr.Addr(), fwdr.Priority(),
|
||||||
website, readTime)
|
website, readTime)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fwdr.Enable()
|
fwdr.Enable()
|
||||||
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", fwdr.Addr(), fwdr.Priority(),
|
log.F("[check] %s(%d) -> %s, SUCCEEDED. connect time: %s", fwdr.Addr(), fwdr.Priority(),
|
||||||
website, readTime)
|
website, readTime)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round Robin
|
// Round Robin.
|
||||||
func (p *FwdrGroup) scheduleRR(dstAddr string) *Forwarder {
|
func (p *FwdrGroup) scheduleRR(dstAddr string) *Forwarder {
|
||||||
return p.avail[atomic.AddUint32(&p.index, 1)%uint32(len(p.avail))]
|
return p.avail[atomic.AddUint32(&p.index, 1)%uint32(len(p.avail))]
|
||||||
}
|
}
|
||||||
|
|
||||||
// High Availability
|
// High Availability.
|
||||||
func (p *FwdrGroup) scheduleHA(dstAddr string) *Forwarder {
|
func (p *FwdrGroup) scheduleHA(dstAddr string) *Forwarder {
|
||||||
return p.avail[0]
|
return p.avail[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Latency based High Availability
|
// Latency based High Availability.
|
||||||
func (p *FwdrGroup) scheduleLHA(dstAddr string) *Forwarder {
|
func (p *FwdrGroup) scheduleLHA(dstAddr string) *Forwarder {
|
||||||
fwdr := p.avail[0]
|
fwdr := p.avail[0]
|
||||||
lowest := fwdr.Latency()
|
lowest := fwdr.Latency()
|
||||||
@ -323,7 +300,7 @@ func (p *FwdrGroup) scheduleLHA(dstAddr string) *Forwarder {
|
|||||||
return fwdr
|
return fwdr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destination Hashing
|
// Destination Hashing.
|
||||||
func (p *FwdrGroup) scheduleDH(dstAddr string) *Forwarder {
|
func (p *FwdrGroup) scheduleDH(dstAddr string) *Forwarder {
|
||||||
fnv1a := fnv.New32a()
|
fnv1a := fnv.New32a()
|
||||||
fnv1a.Write([]byte(dstAddr))
|
fnv1a.Write([]byte(dstAddr))
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/nadoo/glider/proxy"
|
"github.com/nadoo/glider/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Proxy struct.
|
// Proxy implements the proxy.Proxy interface with rule support.
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
main *FwdrGroup
|
main *FwdrGroup
|
||||||
all []*FwdrGroup
|
all []*FwdrGroup
|
||||||
@ -41,11 +41,14 @@ func NewProxy(mainForwarders []string, mainStrategy *StrategyConfig, rules []*Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if there's any forwarder defined in main config, make sure they will be accessed directly.
|
||||||
if len(mainForwarders) > 0 {
|
if len(mainForwarders) > 0 {
|
||||||
direct := NewFwdrGroup("backup", nil, mainStrategy)
|
direct := NewFwdrGroup("", nil, mainStrategy)
|
||||||
for _, f := range rd.main.fwdrs {
|
for _, f := range rd.main.fwdrs {
|
||||||
// Note: the addr maybe ip address, but no matter here.
|
host := strings.Split(f.addr, ":")[0]
|
||||||
rd.domainMap.Store(strings.ToLower(strings.Split(f.addr, ":")[0]), direct)
|
if ip := net.ParseIP(host); ip == nil {
|
||||||
|
rd.domainMap.Store(strings.ToLower(host), direct)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,20 +57,18 @@ func NewProxy(mainForwarders []string, mainStrategy *StrategyConfig, rules []*Co
|
|||||||
|
|
||||||
// Dial dials to targer addr and return a conn.
|
// Dial dials to targer addr and return a conn.
|
||||||
func (p *Proxy) Dial(network, addr string) (net.Conn, proxy.Dialer, error) {
|
func (p *Proxy) Dial(network, addr string) (net.Conn, proxy.Dialer, error) {
|
||||||
return p.chooseProxy(addr).Dial(network, addr)
|
return p.findDialer(addr).Dial(network, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||||
return p.chooseProxy(addr).DialUDP(network, addr)
|
return p.findDialer(addr).DialUDP(network, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// chooseProxy returns a proxy according to rule.
|
// findDialer returns a dialer by dstAddr according to rule.
|
||||||
func (p *Proxy) chooseProxy(dstAddr string) *FwdrGroup {
|
func (p *Proxy) findDialer(dstAddr string) *FwdrGroup {
|
||||||
host, _, err := net.SplitHostPort(dstAddr)
|
host, _, err := net.SplitHostPort(dstAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: check here
|
|
||||||
// logf("[rule] SplitHostPort ERROR: %s", err)
|
|
||||||
return p.main
|
return p.main
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +87,6 @@ func (p *Proxy) chooseProxy(dstAddr string) *FwdrGroup {
|
|||||||
ret = value.(*FwdrGroup)
|
ret = value.(*FwdrGroup)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -109,12 +109,18 @@ func (p *Proxy) chooseProxy(dstAddr string) *FwdrGroup {
|
|||||||
|
|
||||||
// NextDialer returns next dialer according to rule.
|
// NextDialer returns next dialer according to rule.
|
||||||
func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer {
|
func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer {
|
||||||
return p.chooseProxy(dstAddr).NextDialer(dstAddr)
|
return p.findDialer(dstAddr).NextDialer(dstAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record records result while using the dialer from proxy.
|
// Record records result while using the dialer from proxy.
|
||||||
func (p *Proxy) Record(dialer proxy.Dialer, success bool) {
|
func (p *Proxy) Record(dialer proxy.Dialer, success bool) {
|
||||||
OnRecord(dialer, success)
|
if fwdr, ok := dialer.(*Forwarder); ok {
|
||||||
|
if !success {
|
||||||
|
fwdr.IncFailures()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fwdr.Enable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddDomainIP used to update ipMap rules according to domainMap rule.
|
// AddDomainIP used to update ipMap rules according to domainMap rule.
|
||||||
@ -125,18 +131,19 @@ func (p *Proxy) AddDomainIP(domain, ip string) error {
|
|||||||
i = strings.LastIndexByte(domain[:i], '.')
|
i = strings.LastIndexByte(domain[:i], '.')
|
||||||
if dialer, ok := p.domainMap.Load(domain[i+1:]); ok {
|
if dialer, ok := p.domainMap.Load(domain[i+1:]); ok {
|
||||||
p.ipMap.Store(ip, dialer)
|
p.ipMap.Store(ip, dialer)
|
||||||
log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, domain[i+1:], domain, ip)
|
log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n",
|
||||||
|
ip, domain[i+1:], domain, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check .
|
// Check checks availability of forwarders inside proxy.
|
||||||
func (p *Proxy) Check() {
|
func (p *Proxy) Check() {
|
||||||
p.main.Check()
|
p.main.Check()
|
||||||
|
|
||||||
for _, fwdr := range p.all {
|
for _, fwdrGroup := range p.all {
|
||||||
fwdr.Check()
|
fwdrGroup.Check()
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user