proxy: added the ability to log forwarder

This commit is contained in:
nadoo 2019-09-18 12:53:04 +08:00
parent c2425e67de
commit 063dc1bc01
22 changed files with 138 additions and 141 deletions

View File

@ -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:

View File

@ -1,9 +1,7 @@
# [glider](https://github.com/nadoo/glider) # [glider](https://github.com/nadoo/glider)
[![Build Status](https://img.shields.io/travis/nadoo/glider.svg?style=flat-square)](https://travis-ci.org/nadoo/glider)
[![Go Report Card](https://goreportcard.com/badge/github.com/nadoo/glider?style=flat-square)](https://goreportcard.com/report/github.com/nadoo/glider) [![Go Report Card](https://goreportcard.com/badge/github.com/nadoo/glider?style=flat-square)](https://goreportcard.com/report/github.com/nadoo/glider)
[![GitHub tag](https://img.shields.io/github/tag/nadoo/glider.svg?style=flat-square)](https://github.com/nadoo/glider/releases) [![GitHub release](https://img.shields.io/github/v/release/nadoo/glider.svg?include_prereleases&style=flat-square)](https://github.com/nadoo/glider/releases)
[![GitHub release](https://img.shields.io/github/release/nadoo/glider.svg?style=flat-square)](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).

View File

@ -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

View File

@ -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)

View File

@ -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) {

View File

@ -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
} }

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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) {

View File

@ -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

View File

@ -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
} }

View File

@ -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.

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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)
} }
} }

View File

@ -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.

View File

@ -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.

View File

@ -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()
}
} }
} }

View File

@ -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

View File

@ -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))]