mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 17:35:40 +08:00
proxy: added the ability to log forwarder
This commit is contained in:
parent
c2425e67de
commit
063dc1bc01
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@ -12,11 +12,6 @@ jobs:
|
|||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
- name: Validates GO releaser config
|
|
||||||
uses: docker://goreleaser/goreleaser:latest
|
|
||||||
with:
|
|
||||||
args: check
|
|
||||||
|
|
||||||
- name: Create release on GitHub
|
- name: Create release on GitHub
|
||||||
uses: docker://goreleaser/goreleaser:latest
|
uses: docker://goreleaser/goreleaser:latest
|
||||||
env:
|
env:
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
# [glider](https://github.com/nadoo/glider)
|
# [glider](https://github.com/nadoo/glider)
|
||||||
|
|
||||||
[](https://travis-ci.org/nadoo/glider)
|
|
||||||
[](https://goreportcard.com/report/github.com/nadoo/glider)
|
[](https://goreportcard.com/report/github.com/nadoo/glider)
|
||||||
[](https://github.com/nadoo/glider/releases)
|
[](https://github.com/nadoo/glider/releases)
|
||||||
[](https://github.com/nadoo/glider/releases)
|
|
||||||
|
|
||||||
glider is a forward proxy with multiple protocols support, and also a dns forwarding server with ipset management features(like dnsmasq).
|
glider is a forward proxy with multiple protocols support, and also a dns forwarding server with ipset management features(like dnsmasq).
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server
|
|||||||
servers := c.GetServers(qname)
|
servers := c.GetServers(qname)
|
||||||
for _, server = range servers {
|
for _, server = range servers {
|
||||||
var rc net.Conn
|
var rc net.Conn
|
||||||
rc, err = dialer.Dial(network, server)
|
rc, _, err = dialer.Dial(network, server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[dns] failed to connect to server %v: %v", server, err)
|
log.F("[dns] failed to connect to server %v: %v", server, err)
|
||||||
continue
|
continue
|
||||||
|
@ -15,7 +15,7 @@ type Dialer interface {
|
|||||||
Addr() string
|
Addr() string
|
||||||
|
|
||||||
// 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, err error)
|
Dial(network, addr string) (c net.Conn, proxy string, err error)
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error)
|
DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error)
|
||||||
|
@ -39,7 +39,7 @@ func NewDirect(intface string) (*Direct, error) {
|
|||||||
func (d *Direct) Addr() string { return "DIRECT" }
|
func (d *Direct) Addr() string { return "DIRECT" }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net
|
// Dial connects to the address addr on the network net
|
||||||
func (d *Direct) Dial(network, addr string) (c net.Conn, err error) {
|
func (d *Direct) Dial(network, addr string) (c net.Conn, p string, err error) {
|
||||||
if d.iface == nil || d.ip != nil {
|
if d.iface == nil || d.ip != nil {
|
||||||
c, err = dial(network, addr, d.ip)
|
c, err = dial(network, addr, d.ip)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -60,7 +60,7 @@ func (d *Direct) Dial(network, addr string) (c net.Conn, err error) {
|
|||||||
err = errors.New("dial failed, maybe the interface link is down, please check it")
|
err = errors.New("dial failed, maybe the interface link is down, please check it")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return c, "DIRECT", err
|
||||||
}
|
}
|
||||||
|
|
||||||
func dial(network, addr string, localIP net.IP) (net.Conn, error) {
|
func dial(network, addr string, localIP net.IP) (net.Conn, error) {
|
||||||
|
@ -142,10 +142,10 @@ func (s *HTTP) Serve(c net.Conn) {
|
|||||||
tgt += ":80"
|
tgt += ":80"
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.dialer.Dial("tcp", tgt)
|
rc, p, err := s.dialer.Dial("tcp", tgt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto)
|
fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto)
|
||||||
log.F("[http] %s <-> %s, error in dial: %v", c.RemoteAddr(), tgt, err)
|
log.F("[http] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
@ -192,7 +192,7 @@ func (s *HTTP) Serve(c net.Conn) {
|
|||||||
writeFirstLine(&respBuf, proto, code, status)
|
writeFirstLine(&respBuf, proto, code, status)
|
||||||
writeHeaders(&respBuf, respHeader)
|
writeHeaders(&respBuf, respHeader)
|
||||||
|
|
||||||
log.F("[http] %s <-> %s", c.RemoteAddr(), tgt)
|
log.F("[http] %s <-> %s, %s", c.RemoteAddr(), tgt, p)
|
||||||
c.Write(respBuf.Bytes())
|
c.Write(respBuf.Bytes())
|
||||||
|
|
||||||
io.Copy(c, respR)
|
io.Copy(c, respR)
|
||||||
@ -200,7 +200,7 @@ func (s *HTTP) Serve(c net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) {
|
func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) {
|
||||||
rc, err := s.dialer.Dial("tcp", requestURI)
|
rc, p, err := s.dialer.Dial("tcp", requestURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Write([]byte(proto))
|
c.Write([]byte(proto))
|
||||||
c.Write([]byte(" 502 ERROR\r\n\r\n"))
|
c.Write([]byte(" 502 ERROR\r\n\r\n"))
|
||||||
@ -210,7 +210,7 @@ func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) {
|
|||||||
|
|
||||||
c.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
|
c.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
|
||||||
|
|
||||||
log.F("[http] %s <-> %s [c]", c.RemoteAddr(), requestURI)
|
log.F("[http] %s <-> %s [c], %s", c.RemoteAddr(), requestURI, p)
|
||||||
|
|
||||||
_, _, err = conn.Relay(c, rc)
|
_, _, err = conn.Relay(c, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -233,11 +233,11 @@ func (s *HTTP) Addr() string {
|
|||||||
func (s *HTTP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *HTTP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
rc, err := s.dialer.Dial(network, s.addr)
|
rc, p, err := s.dialer.Dial(network, s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[http] dial to %s error: %s", s.addr, err)
|
log.F("[http] dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -254,7 +254,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
|||||||
buf.Write([]byte("\r\n"))
|
buf.Write([]byte("\r\n"))
|
||||||
_, err = rc.Write(buf.Bytes())
|
_, err = rc.Write(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := conn.NewConn(rc)
|
c := conn.NewConn(rc)
|
||||||
@ -262,7 +262,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
|||||||
_, code, _, ok := parseFirstLine(tpr)
|
_, code, _, ok := parseFirstLine(tpr)
|
||||||
if ok && code == "200" {
|
if ok && code == "200" {
|
||||||
tpr.ReadMIMEHeader()
|
tpr.ReadMIMEHeader()
|
||||||
return c, err
|
return c, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if code == "407" {
|
if code == "407" {
|
||||||
@ -271,7 +271,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
|||||||
log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr)
|
log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code)
|
return nil, p, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
@ -282,9 +282,7 @@ func (s *HTTP) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Add
|
|||||||
// parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts
|
// parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts
|
||||||
func parseFirstLine(tp *textproto.Reader) (r1, r2, r3 string, ok bool) {
|
func parseFirstLine(tp *textproto.Reader) (r1, r2, r3 string, ok bool) {
|
||||||
line, err := tp.ReadLine()
|
line, err := tp.ReadLine()
|
||||||
// log.F("first line: %s", line)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// log.F("[http] read first line error:%s", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,12 +197,12 @@ func (s *KCP) Addr() string { return s.addr }
|
|||||||
func (s *KCP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *KCP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *KCP) Dial(network, addr string) (net.Conn, error) {
|
func (s *KCP) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
// NOTE: kcp uses udp, we should dial remote server directly here
|
// NOTE: kcp uses udp, we should dial remote server directly here
|
||||||
c, err := kcp.DialWithOptions(s.addr, s.block, s.dataShards, s.parityShards)
|
c, err := kcp.DialWithOptions(s.addr, s.block, s.dataShards, s.parityShards)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tls] dial to %s error: %s", s.addr, err)
|
log.F("[tls] dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change them to customizable later?
|
// TODO: change them to customizable later?
|
||||||
@ -217,7 +217,7 @@ func (s *KCP) Dial(network, addr string) (net.Conn, error) {
|
|||||||
c.SetReadBuffer(4194304)
|
c.SetReadBuffer(4194304)
|
||||||
c.SetWriteBuffer(4194304)
|
c.SetWriteBuffer(4194304)
|
||||||
|
|
||||||
return c, err
|
return c, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -93,14 +93,15 @@ func (s *Obfs) Addr() string { return s.addr }
|
|||||||
func (s *Obfs) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *Obfs) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *Obfs) Dial(network, addr string) (net.Conn, error) {
|
func (s *Obfs) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
c, err := s.dialer.Dial("tcp", s.addr)
|
c, p, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[obfs] dial to %s error: %s", s.addr, err)
|
log.F("[obfs] dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.obfsConn(c)
|
cc, e := s.obfsConn(c)
|
||||||
|
return cc, p, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -104,14 +104,14 @@ func (s *RedirProxy) Serve(c net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.dialer.Dial("tcp", tgt.String())
|
rc, p, err := s.dialer.Dial("tcp", tgt.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[redir] %s <-> %s, error in dial: %v", c.RemoteAddr(), tgt, err)
|
log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
log.F("[redir] %s <-> %s", c.RemoteAddr(), tgt)
|
log.F("[redir] %s <-> %s, %s", c.RemoteAddr(), tgt, p)
|
||||||
|
|
||||||
_, _, err = conn.Relay(c, rc)
|
_, _, err = conn.Relay(c, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,7 +32,9 @@ func (s *Reject) Addr() string { return "REJECT" }
|
|||||||
func (s *Reject) NextDialer(dstAddr string) proxy.Dialer { return s }
|
func (s *Reject) NextDialer(dstAddr string) proxy.Dialer { return s }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *Reject) Dial(network, addr string) (net.Conn, error) { return nil, errors.New("REJECT") }
|
func (s *Reject) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
|
return nil, "REJECT", errors.New("REJECT")
|
||||||
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
func (s *Reject) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
|
func (s *Reject) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
|
||||||
|
@ -131,14 +131,14 @@ func (s *SOCKS5) Serve(c net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.dialer.Dial("tcp", tgt.String())
|
rc, p, err := s.dialer.Dial("tcp", tgt.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5] %s <-> %s, error in dial: %v", c.RemoteAddr(), tgt, err)
|
log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
log.F("[socks5] %s <-> %s", c.RemoteAddr(), tgt)
|
log.F("[socks5] %s <-> %s, %s", c.RemoteAddr(), tgt, p)
|
||||||
|
|
||||||
_, _, err = conn.Relay(c, rc)
|
_, _, err = conn.Relay(c, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -224,30 +224,30 @@ func (s *SOCKS5) Addr() string {
|
|||||||
func (s *SOCKS5) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *SOCKS5) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the SOCKS5 proxy.
|
// Dial connects to the address addr on the network net via the SOCKS5 proxy.
|
||||||
func (s *SOCKS5) Dial(network, addr string) (net.Conn, error) {
|
func (s *SOCKS5) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
switch network {
|
switch network {
|
||||||
case "tcp", "tcp6", "tcp4":
|
case "tcp", "tcp6", "tcp4":
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("[socks5]: no support for connection type " + network)
|
return nil, "", errors.New("[socks5]: no support for connection type " + network)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := s.dialer.Dial(network, s.addr)
|
c, p, err := s.dialer.Dial(network, s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5]: dial to %s error: %s", s.addr, err)
|
log.F("[socks5]: dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.connect(c, addr); err != nil {
|
if err := s.connect(c, addr); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||||
c, err := s.dialer.Dial("tcp", s.addr)
|
c, _, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5] dialudp dial tcp to %s error: %s", s.addr, err)
|
log.F("[socks5] dialudp dial tcp to %s error: %s", s.addr, err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -147,14 +147,14 @@ func (s *SS) Serve(c net.Conn) {
|
|||||||
network = "udp"
|
network = "udp"
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := dialer.Dial(network, tgt.String())
|
rc, p, err := dialer.Dial(network, tgt.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[ss] %s <-> %s, error in dial: %v", c.RemoteAddr(), tgt, err)
|
log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
log.F("[ss] %s <-> %s", c.RemoteAddr(), tgt)
|
log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, p)
|
||||||
|
|
||||||
_, _, err = conn.Relay(c, rc)
|
_, _, err = conn.Relay(c, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -242,29 +242,29 @@ func (s *SS) Addr() string {
|
|||||||
func (s *SS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *SS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *SS) Dial(network, addr string) (net.Conn, error) {
|
func (s *SS) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
target := socks.ParseAddr(addr)
|
target := socks.ParseAddr(addr)
|
||||||
if target == nil {
|
if target == nil {
|
||||||
return nil, errors.New("[ss] unable to parse address: " + addr)
|
return nil, "", errors.New("[ss] unable to parse address: " + addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if network == "uot" {
|
if network == "uot" {
|
||||||
target[0] = target[0] | 0x8
|
target[0] = target[0] | 0x8
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := s.dialer.Dial("tcp", s.addr)
|
c, p, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[ss] dial to %s error: %s", s.addr, err)
|
log.F("[ss] dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c = s.StreamConn(c)
|
c = s.StreamConn(c)
|
||||||
if _, err = c.Write(target); err != nil {
|
if _, err = c.Write(target); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, err
|
return c, p, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,26 +81,26 @@ func (s *SSR) Addr() string {
|
|||||||
func (s *SSR) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *SSR) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
target := socks.ParseAddr(addr)
|
target := socks.ParseAddr(addr)
|
||||||
if target == nil {
|
if target == nil {
|
||||||
return nil, errors.New("[ssr] unable to parse address: " + addr)
|
return nil, "", errors.New("[ssr] unable to parse address: " + addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher, err := shadowsocksr.NewStreamCipher(s.EncryptMethod, s.EncryptPassword)
|
cipher, err := shadowsocksr.NewStreamCipher(s.EncryptMethod, s.EncryptPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := s.dialer.Dial("tcp", s.addr)
|
c, p, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[ssr] dial to %s error: %s", s.addr, err)
|
log.F("[ssr] dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
|
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
|
||||||
if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil {
|
if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil {
|
||||||
return nil, errors.New("[ssr] nil connection")
|
return nil, p, errors.New("[ssr] nil connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
// should initialize obfs/protocol now
|
// should initialize obfs/protocol now
|
||||||
@ -109,7 +109,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
|||||||
|
|
||||||
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
|
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
|
||||||
if ssrconn.IObfs == nil {
|
if ssrconn.IObfs == nil {
|
||||||
return nil, errors.New("[ssr] unsupported obfs type: " + s.Obfs)
|
return nil, p, errors.New("[ssr] unsupported obfs type: " + s.Obfs)
|
||||||
}
|
}
|
||||||
|
|
||||||
obfsServerInfo := &ssr.ServerInfoForObfs{
|
obfsServerInfo := &ssr.ServerInfoForObfs{
|
||||||
@ -122,7 +122,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
|||||||
|
|
||||||
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
|
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
|
||||||
if ssrconn.IProtocol == nil {
|
if ssrconn.IProtocol == nil {
|
||||||
return nil, errors.New("[ssr] unsupported protocol type: " + s.Protocol)
|
return nil, p, errors.New("[ssr] unsupported protocol type: " + s.Protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
protocolServerInfo := &ssr.ServerInfoForObfs{
|
protocolServerInfo := &ssr.ServerInfoForObfs{
|
||||||
@ -145,10 +145,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
|||||||
|
|
||||||
if _, err := ssrconn.Write(target); err != nil {
|
if _, err := ssrconn.Write(target); err != nil {
|
||||||
ssrconn.Close()
|
ssrconn.Close()
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssrconn, err
|
return ssrconn, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
@ -76,14 +76,14 @@ func (s *TCPTun) Serve(c net.Conn) {
|
|||||||
c.SetKeepAlive(true)
|
c.SetKeepAlive(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.dialer.Dial("tcp", s.raddr)
|
rc, p, err := s.dialer.Dial("tcp", s.raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tcptun] %s <-> %s, error in dial: %v", c.RemoteAddr(), s.addr, err)
|
log.F("[tcptun] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), s.addr, err, p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
log.F("[tcptun] %s <-> %s", c.RemoteAddr(), s.raddr)
|
log.F("[tcptun] %s <-> %s, %s", c.RemoteAddr(), s.raddr, p)
|
||||||
|
|
||||||
_, _, err = conn.Relay(c, rc)
|
_, _, err = conn.Relay(c, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,16 +160,16 @@ func (s *TLS) Addr() string { return s.addr }
|
|||||||
func (s *TLS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *TLS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *TLS) Dial(network, addr string) (net.Conn, error) {
|
func (s *TLS) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
cc, err := s.dialer.Dial("tcp", s.addr)
|
cc, p, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tls] dial to %s error: %s", s.addr, err)
|
log.F("[tls] dial to %s error: %s", s.addr, err)
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := stdtls.Client(cc, s.tlsConfig)
|
c := stdtls.Client(cc, s.tlsConfig)
|
||||||
err = c.Handshake()
|
err = c.Handshake()
|
||||||
return c, err
|
return c, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -113,14 +113,14 @@ func (s *Unix) Addr() string {
|
|||||||
func (s *Unix) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *Unix) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *Unix) Dial(network, addr string) (net.Conn, error) {
|
func (s *Unix) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
// NOTE: must be the first dialer in a chain
|
// NOTE: must be the first dialer in a chain
|
||||||
rc, err := net.Dial("unix", s.addr)
|
rc, err := net.Dial("unix", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc, err
|
return rc, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -69,7 +69,7 @@ func (s *UoTTun) ListenAndServe() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.dialer.Dial("uot", s.raddr)
|
rc, p, err := s.dialer.Dial("uot", s.raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
|
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
|
||||||
continue
|
continue
|
||||||
@ -99,7 +99,7 @@ func (s *UoTTun) ListenAndServe() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.F("[uottun] %s <-> %s", clientAddr, s.raddr)
|
log.F("[uottun] %s <-> %s, %s", clientAddr, s.raddr, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,13 +90,14 @@ func (s *VMess) Addr() string {
|
|||||||
func (s *VMess) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *VMess) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *VMess) Dial(network, addr string) (net.Conn, error) {
|
func (s *VMess) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
rc, err := s.dialer.Dial("tcp", s.addr)
|
rc, p, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.client.NewConn(rc, addr)
|
cc, e := s.client.NewConn(rc, addr)
|
||||||
|
return cc, p, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
@ -76,13 +76,14 @@ func (s *WS) Addr() string {
|
|||||||
func (s *WS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
func (s *WS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *WS) Dial(network, addr string) (net.Conn, error) {
|
func (s *WS) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
rc, err := s.dialer.Dial("tcp", s.addr)
|
rc, p, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.client.NewConn(rc, addr)
|
cc, e := s.client.NewConn(rc, addr)
|
||||||
|
return cc, p, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
24
rule/rule.go
24
rule/rule.go
@ -12,8 +12,8 @@ import (
|
|||||||
|
|
||||||
// Dialer struct
|
// Dialer struct
|
||||||
type Dialer struct {
|
type Dialer struct {
|
||||||
gDialer proxy.Dialer
|
gDialer *strategy.Dialer
|
||||||
dialers []proxy.Dialer
|
dialers []*strategy.Dialer
|
||||||
|
|
||||||
domainMap sync.Map
|
domainMap sync.Map
|
||||||
ipMap sync.Map
|
ipMap sync.Map
|
||||||
@ -21,7 +21,7 @@ type Dialer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewDialer returns a new rule dialer
|
// NewDialer returns a new rule dialer
|
||||||
func NewDialer(rules []*Config, gDialer proxy.Dialer) *Dialer {
|
func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer {
|
||||||
rd := &Dialer{gDialer: gDialer}
|
rd := &Dialer{gDialer: gDialer}
|
||||||
|
|
||||||
for _, r := range rules {
|
for _, r := range rules {
|
||||||
@ -98,17 +98,13 @@ func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dial dials to targer addr and return a conn
|
// Dial dials to targer addr and return a conn
|
||||||
func (rd *Dialer) Dial(network, addr string) (net.Conn, error) {
|
func (rd *Dialer) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
d := rd.NextDialer(addr)
|
return rd.NextDialer(addr).Dial(network, addr)
|
||||||
log.F("[dial] %s => %s", addr, d.Addr())
|
|
||||||
return d.Dial(network, addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
func (rd *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
func (rd *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||||
d := rd.NextDialer(addr)
|
return rd.NextDialer(addr).DialUDP(network, addr)
|
||||||
log.F("[dial-udp] %s => %s", addr, d.Addr())
|
|
||||||
return d.DialUDP(network, addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddDomainIP used to update ipMap rules according to domainMap rule
|
// AddDomainIP used to update ipMap rules according to domainMap rule
|
||||||
@ -131,13 +127,9 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error {
|
|||||||
|
|
||||||
// Check .
|
// Check .
|
||||||
func (rd *Dialer) Check() {
|
func (rd *Dialer) Check() {
|
||||||
if checker, ok := rd.gDialer.(strategy.Checker); ok {
|
rd.gDialer.Check()
|
||||||
checker.Check()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range rd.dialers {
|
for _, d := range rd.dialers {
|
||||||
if checker, ok := d.(strategy.Checker); ok {
|
d.Check()
|
||||||
checker.Check()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package proxy
|
package strategy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/nadoo/glider/common/log"
|
"github.com/nadoo/glider/common/log"
|
||||||
|
"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
|
||||||
@ -15,7 +16,7 @@ type StatusHandler func(*Forwarder)
|
|||||||
|
|
||||||
// Forwarder is a forwarder
|
// Forwarder is a forwarder
|
||||||
type Forwarder struct {
|
type Forwarder struct {
|
||||||
Dialer
|
proxy.Dialer
|
||||||
addr string
|
addr string
|
||||||
priority uint32
|
priority uint32
|
||||||
maxFailures uint32 // maxfailures to set to Disabled
|
maxFailures uint32 // maxfailures to set to Disabled
|
||||||
@ -40,14 +41,14 @@ func ForwarderFromURL(s, intface string) (f *Forwarder, err error) {
|
|||||||
iface = f.intface
|
iface = f.intface
|
||||||
}
|
}
|
||||||
|
|
||||||
var d Dialer
|
var d proxy.Dialer
|
||||||
d, err = NewDirect(iface)
|
d, err = proxy.NewDirect(iface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, url := range strings.Split(ss[0], ",") {
|
for _, url := range strings.Split(ss[0], ",") {
|
||||||
d, err = DialerFromURL(url, d)
|
d, err = proxy.DialerFromURL(url, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -57,12 +58,21 @@ func ForwarderFromURL(s, intface string) (f *Forwarder, err error) {
|
|||||||
f.addr = d.Addr()
|
f.addr = d.Addr()
|
||||||
|
|
||||||
// set forwarder to disabled by default
|
// set forwarder to disabled by default
|
||||||
// TODO: check here
|
|
||||||
f.Disable()
|
f.Disable()
|
||||||
|
|
||||||
return f, err
|
return f, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirectForwarder returns a direct forwarder
|
||||||
|
func DirectForwarder(intface string) *Forwarder {
|
||||||
|
d, err := proxy.NewDirect(intface)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Forwarder{Dialer: d, addr: d.Addr()}
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Forwarder) parseOption(option string) error {
|
func (f *Forwarder) parseOption(option string) error {
|
||||||
query, err := url.ParseQuery(option)
|
query, err := url.ParseQuery(option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -87,8 +97,8 @@ func (f *Forwarder) Addr() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dial .
|
// Dial .
|
||||||
func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
|
func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) {
|
||||||
c, err = f.Dialer.Dial(network, addr)
|
c, p, err = f.Dialer.Dial(network, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.IncFailures()
|
f.IncFailures()
|
||||||
if f.Failures() >= f.MaxFailures() && f.Enabled() {
|
if f.Failures() >= f.MaxFailures() && f.Enabled() {
|
||||||
@ -97,7 +107,7 @@ func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, err
|
return c, p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failures returns the failuer count of forwarder
|
// Failures returns the failuer count of forwarder
|
@ -31,7 +31,7 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// forwarder slice orderd by priority
|
// forwarder slice orderd by priority
|
||||||
type priSlice []*proxy.Forwarder
|
type priSlice []*Forwarder
|
||||||
|
|
||||||
func (p priSlice) Len() int { return len(p) }
|
func (p priSlice) Len() int { return len(p) }
|
||||||
func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() }
|
func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() }
|
||||||
@ -41,19 +41,19 @@ func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|||||||
type Dialer struct {
|
type Dialer struct {
|
||||||
config *Config
|
config *Config
|
||||||
fwdrs priSlice
|
fwdrs priSlice
|
||||||
available []*proxy.Forwarder
|
available []*Forwarder
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
index uint32
|
index uint32
|
||||||
priority uint32
|
priority uint32
|
||||||
|
|
||||||
nextForwarder func(addr string) *proxy.Forwarder
|
nextForwarder func(addr string) *Forwarder
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDialer returns a new strategy dialer.
|
// NewDialer returns a new strategy dialer.
|
||||||
func NewDialer(s []string, c *Config) proxy.Dialer {
|
func NewDialer(s []string, c *Config) *Dialer {
|
||||||
var fwdrs []*proxy.Forwarder
|
var fwdrs []*Forwarder
|
||||||
for _, chain := range s {
|
for _, chain := range s {
|
||||||
fwdr, err := proxy.ForwarderFromURL(chain, c.IntFace)
|
fwdr, err := ForwarderFromURL(chain, c.IntFace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -62,22 +62,16 @@ func NewDialer(s []string, c *Config) proxy.Dialer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(fwdrs) == 0 {
|
if len(fwdrs) == 0 {
|
||||||
d, err := proxy.NewDirect(c.IntFace)
|
// direct forwarder
|
||||||
if err != nil {
|
fwdrs = append(fwdrs, DirectForwarder(c.IntFace))
|
||||||
log.Fatal(err)
|
c.Strategy = "rr"
|
||||||
}
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fwdrs) == 1 {
|
|
||||||
return fwdrs[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newDialer(fwdrs, c)
|
return newDialer(fwdrs, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newDialer returns a new rrDialer
|
// newDialer returns a new rrDialer
|
||||||
func newDialer(fwdrs []*proxy.Forwarder, c *Config) *Dialer {
|
func newDialer(fwdrs []*Forwarder, c *Config) *Dialer {
|
||||||
d := &Dialer{fwdrs: fwdrs, config: c}
|
d := &Dialer{fwdrs: fwdrs, config: c}
|
||||||
sort.Sort(d.fwdrs)
|
sort.Sort(d.fwdrs)
|
||||||
|
|
||||||
@ -90,19 +84,19 @@ func newDialer(fwdrs []*proxy.Forwarder, c *Config) *Dialer {
|
|||||||
switch c.Strategy {
|
switch c.Strategy {
|
||||||
case "rr":
|
case "rr":
|
||||||
d.nextForwarder = d.scheduleRR
|
d.nextForwarder = d.scheduleRR
|
||||||
log.F("forward to remote servers in round robin mode.")
|
log.F("[strategy] forward to remote servers in round robin mode.")
|
||||||
case "ha":
|
case "ha":
|
||||||
d.nextForwarder = d.scheduleHA
|
d.nextForwarder = d.scheduleHA
|
||||||
log.F("forward to remote servers in high availability mode.")
|
log.F("[strategy] forward to remote servers in high availability mode.")
|
||||||
case "lha":
|
case "lha":
|
||||||
d.nextForwarder = d.scheduleLHA
|
d.nextForwarder = d.scheduleLHA
|
||||||
log.F("forward to remote servers in latency based high availability mode.")
|
log.F("[strategy] forward to remote servers in latency based high availability mode.")
|
||||||
case "dh":
|
case "dh":
|
||||||
d.nextForwarder = d.scheduleDH
|
d.nextForwarder = d.scheduleDH
|
||||||
log.F("forward to remote servers in destination hashing mode.")
|
log.F("[strategy] forward to remote servers in destination hashing mode.")
|
||||||
default:
|
default:
|
||||||
d.nextForwarder = d.scheduleRR
|
d.nextForwarder = d.scheduleRR
|
||||||
log.F("not supported forward mode '%s', use round robin mode.", c.Strategy)
|
log.F("[strategy] not supported forward mode '%s', use round robin mode.", c.Strategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range fwdrs {
|
for _, f := range fwdrs {
|
||||||
@ -116,8 +110,10 @@ func newDialer(fwdrs []*proxy.Forwarder, c *Config) *Dialer {
|
|||||||
func (d *Dialer) Addr() string { return "STRATEGY" }
|
func (d *Dialer) Addr() string { return "STRATEGY" }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net.
|
// Dial connects to the address addr on the network net.
|
||||||
func (d *Dialer) Dial(network, addr string) (net.Conn, error) {
|
func (d *Dialer) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
return d.NextDialer(addr).Dial(network, addr)
|
nd := d.NextDialer(addr)
|
||||||
|
c, _, err := nd.Dial(network, addr)
|
||||||
|
return c, nd.Addr(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address.
|
// DialUDP connects to the given address.
|
||||||
@ -164,7 +160,7 @@ func (d *Dialer) initAvailable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// onStatusChanged will be called when fwdr's status changed.
|
// onStatusChanged will be called when fwdr's status changed.
|
||||||
func (d *Dialer) onStatusChanged(fwdr *proxy.Forwarder) {
|
func (d *Dialer) onStatusChanged(fwdr *Forwarder) {
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
@ -192,9 +188,12 @@ func (d *Dialer) onStatusChanged(fwdr *proxy.Forwarder) {
|
|||||||
|
|
||||||
// Check implements the Checker interface.
|
// Check implements the Checker interface.
|
||||||
func (d *Dialer) Check() {
|
func (d *Dialer) Check() {
|
||||||
|
// no need to check when there's only 1 forwarder
|
||||||
|
if len(d.fwdrs) > 1 {
|
||||||
for i := 0; i < len(d.fwdrs); i++ {
|
for i := 0; i < len(d.fwdrs); i++ {
|
||||||
go d.check(i)
|
go d.check(i)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) check(i int) {
|
func (d *Dialer) check(i int) {
|
||||||
@ -216,7 +215,7 @@ func (d *Dialer) check(i int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
rc, err := f.Dial("tcp", d.config.CheckWebSite)
|
rc, _, err := f.Dial("tcp", d.config.CheckWebSite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Disable()
|
f.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err)
|
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err)
|
||||||
@ -253,17 +252,17 @@ func (d *Dialer) check(i int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Round Robin
|
// Round Robin
|
||||||
func (d *Dialer) scheduleRR(dstAddr string) *proxy.Forwarder {
|
func (d *Dialer) scheduleRR(dstAddr string) *Forwarder {
|
||||||
return d.available[atomic.AddUint32(&d.index, 1)%uint32(len(d.available))]
|
return d.available[atomic.AddUint32(&d.index, 1)%uint32(len(d.available))]
|
||||||
}
|
}
|
||||||
|
|
||||||
// High Availability
|
// High Availability
|
||||||
func (d *Dialer) scheduleHA(dstAddr string) *proxy.Forwarder {
|
func (d *Dialer) scheduleHA(dstAddr string) *Forwarder {
|
||||||
return d.available[0]
|
return d.available[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Latency based High Availability
|
// Latency based High Availability
|
||||||
func (d *Dialer) scheduleLHA(dstAddr string) *proxy.Forwarder {
|
func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder {
|
||||||
fwdr := d.available[0]
|
fwdr := d.available[0]
|
||||||
lowest := fwdr.Latency()
|
lowest := fwdr.Latency()
|
||||||
for _, f := range d.available {
|
for _, f := range d.available {
|
||||||
@ -276,7 +275,7 @@ func (d *Dialer) scheduleLHA(dstAddr string) *proxy.Forwarder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destination Hashing
|
// Destination Hashing
|
||||||
func (d *Dialer) scheduleDH(dstAddr string) *proxy.Forwarder {
|
func (d *Dialer) scheduleDH(dstAddr string) *Forwarder {
|
||||||
fnv1a := fnv.New32a()
|
fnv1a := fnv.New32a()
|
||||||
fnv1a.Write([]byte(dstAddr))
|
fnv1a.Write([]byte(dstAddr))
|
||||||
return d.available[fnv1a.Sum32()%uint32(len(d.available))]
|
return d.available[fnv1a.Sum32()%uint32(len(d.available))]
|
||||||
|
Loading…
Reference in New Issue
Block a user