mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +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
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Validates GO releaser config
|
||||
uses: docker://goreleaser/goreleaser:latest
|
||||
with:
|
||||
args: check
|
||||
|
||||
- name: Create release on GitHub
|
||||
uses: docker://goreleaser/goreleaser:latest
|
||||
env:
|
||||
|
@ -1,9 +1,7 @@
|
||||
# [glider](https://github.com/nadoo/glider)
|
||||
|
||||
[](https://travis-ci.org/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).
|
||||
|
||||
|
@ -143,7 +143,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server
|
||||
servers := c.GetServers(qname)
|
||||
for _, server = range servers {
|
||||
var rc net.Conn
|
||||
rc, err = dialer.Dial(network, server)
|
||||
rc, _, err = dialer.Dial(network, server)
|
||||
if err != nil {
|
||||
log.F("[dns] failed to connect to server %v: %v", server, err)
|
||||
continue
|
||||
|
@ -15,7 +15,7 @@ type Dialer interface {
|
||||
Addr() string
|
||||
|
||||
// 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(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" }
|
||||
|
||||
// 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 {
|
||||
c, err = dial(network, addr, d.ip)
|
||||
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")
|
||||
}
|
||||
|
||||
return
|
||||
return c, "DIRECT", err
|
||||
}
|
||||
|
||||
func dial(network, addr string, localIP net.IP) (net.Conn, error) {
|
||||
|
@ -142,10 +142,10 @@ func (s *HTTP) Serve(c net.Conn) {
|
||||
tgt += ":80"
|
||||
}
|
||||
|
||||
rc, err := s.dialer.Dial("tcp", tgt)
|
||||
rc, p, err := s.dialer.Dial("tcp", tgt)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
defer rc.Close()
|
||||
@ -192,7 +192,7 @@ func (s *HTTP) Serve(c net.Conn) {
|
||||
writeFirstLine(&respBuf, proto, code, status)
|
||||
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())
|
||||
|
||||
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) {
|
||||
rc, err := s.dialer.Dial("tcp", requestURI)
|
||||
rc, p, err := s.dialer.Dial("tcp", requestURI)
|
||||
if err != nil {
|
||||
c.Write([]byte(proto))
|
||||
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"))
|
||||
|
||||
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)
|
||||
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) }
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy
|
||||
func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
||||
rc, err := s.dialer.Dial(network, s.addr)
|
||||
func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
|
||||
rc, p, err := s.dialer.Dial(network, s.addr)
|
||||
if err != nil {
|
||||
log.F("[http] dial to %s error: %s", s.addr, err)
|
||||
return nil, err
|
||||
return nil, p, err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
@ -254,7 +254,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
||||
buf.Write([]byte("\r\n"))
|
||||
_, err = rc.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, p, err
|
||||
}
|
||||
|
||||
c := conn.NewConn(rc)
|
||||
@ -262,7 +262,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
||||
_, code, _, ok := parseFirstLine(tpr)
|
||||
if ok && code == "200" {
|
||||
tpr.ReadMIMEHeader()
|
||||
return c, err
|
||||
return c, p, err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
@ -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
|
||||
func parseFirstLine(tp *textproto.Reader) (r1, r2, r3 string, ok bool) {
|
||||
line, err := tp.ReadLine()
|
||||
// log.F("first line: %s", line)
|
||||
if err != nil {
|
||||
// log.F("[http] read first line error:%s", err)
|
||||
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) }
|
||||
|
||||
// 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
|
||||
c, err := kcp.DialWithOptions(s.addr, s.block, s.dataShards, s.parityShards)
|
||||
if err != nil {
|
||||
log.F("[tls] dial to %s error: %s", s.addr, err)
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// TODO: change them to customizable later?
|
||||
@ -217,7 +217,7 @@ func (s *KCP) Dial(network, addr string) (net.Conn, error) {
|
||||
c.SetReadBuffer(4194304)
|
||||
c.SetWriteBuffer(4194304)
|
||||
|
||||
return c, err
|
||||
return c, "", err
|
||||
}
|
||||
|
||||
// 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) }
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy
|
||||
func (s *Obfs) Dial(network, addr string) (net.Conn, error) {
|
||||
c, err := s.dialer.Dial("tcp", s.addr)
|
||||
func (s *Obfs) Dial(network, addr string) (net.Conn, string, error) {
|
||||
c, p, err := s.dialer.Dial("tcp", s.addr)
|
||||
if err != nil {
|
||||
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
|
||||
|
@ -104,14 +104,14 @@ func (s *RedirProxy) Serve(c net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
rc, err := s.dialer.Dial("tcp", tgt.String())
|
||||
rc, p, err := s.dialer.Dial("tcp", tgt.String())
|
||||
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
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
|
@ -32,7 +32,9 @@ func (s *Reject) Addr() string { return "REJECT" }
|
||||
func (s *Reject) NextDialer(dstAddr string) proxy.Dialer { return s }
|
||||
|
||||
// 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.
|
||||
func (s *Reject) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
|
||||
|
@ -131,14 +131,14 @@ func (s *SOCKS5) Serve(c net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
rc, err := s.dialer.Dial("tcp", tgt.String())
|
||||
rc, p, err := s.dialer.Dial("tcp", tgt.String())
|
||||
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
|
||||
}
|
||||
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)
|
||||
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) }
|
||||
|
||||
// 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 {
|
||||
case "tcp", "tcp6", "tcp4":
|
||||
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 {
|
||||
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 {
|
||||
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.
|
||||
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 {
|
||||
log.F("[socks5] dialudp dial tcp to %s error: %s", s.addr, err)
|
||||
return nil, nil, err
|
||||
|
@ -147,14 +147,14 @@ func (s *SS) Serve(c net.Conn) {
|
||||
network = "udp"
|
||||
}
|
||||
|
||||
rc, err := dialer.Dial(network, tgt.String())
|
||||
rc, p, err := dialer.Dial(network, tgt.String())
|
||||
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
|
||||
}
|
||||
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)
|
||||
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) }
|
||||
|
||||
// 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)
|
||||
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" {
|
||||
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 {
|
||||
log.F("[ss] dial to %s error: %s", s.addr, err)
|
||||
return nil, err
|
||||
return nil, p, err
|
||||
}
|
||||
|
||||
c = s.StreamConn(c)
|
||||
if _, err = c.Write(target); err != nil {
|
||||
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) }
|
||||
|
||||
// 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)
|
||||
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)
|
||||
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 {
|
||||
log.F("[ssr] dial to %s error: %s", s.addr, err)
|
||||
return nil, err
|
||||
return nil, p, err
|
||||
}
|
||||
|
||||
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
|
||||
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
|
||||
@ -109,7 +109,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
||||
|
||||
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
|
||||
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{
|
||||
@ -122,7 +122,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
||||
|
||||
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
|
||||
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{
|
||||
@ -145,10 +145,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
||||
|
||||
if _, err := ssrconn.Write(target); err != nil {
|
||||
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.
|
||||
|
@ -76,14 +76,14 @@ func (s *TCPTun) Serve(c net.Conn) {
|
||||
c.SetKeepAlive(true)
|
||||
}
|
||||
|
||||
rc, err := s.dialer.Dial("tcp", s.raddr)
|
||||
rc, p, err := s.dialer.Dial("tcp", s.raddr)
|
||||
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
|
||||
}
|
||||
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)
|
||||
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) }
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy
|
||||
func (s *TLS) Dial(network, addr string) (net.Conn, error) {
|
||||
cc, err := s.dialer.Dial("tcp", s.addr)
|
||||
func (s *TLS) Dial(network, addr string) (net.Conn, string, error) {
|
||||
cc, p, err := s.dialer.Dial("tcp", s.addr)
|
||||
if err != nil {
|
||||
log.F("[tls] dial to %s error: %s", s.addr, err)
|
||||
return nil, err
|
||||
return nil, p, err
|
||||
}
|
||||
|
||||
c := stdtls.Client(cc, s.tlsConfig)
|
||||
err = c.Handshake()
|
||||
return c, err
|
||||
return c, p, err
|
||||
}
|
||||
|
||||
// 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) }
|
||||
|
||||
// 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
|
||||
rc, err := net.Dial("unix", s.addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return rc, err
|
||||
return rc, "", err
|
||||
}
|
||||
|
||||
// DialUDP connects to the given address via the proxy
|
||||
|
@ -69,7 +69,7 @@ func (s *UoTTun) ListenAndServe() {
|
||||
continue
|
||||
}
|
||||
|
||||
rc, err := s.dialer.Dial("uot", s.raddr)
|
||||
rc, p, err := s.dialer.Dial("uot", s.raddr)
|
||||
if err != nil {
|
||||
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
|
||||
continue
|
||||
@ -99,7 +99,7 @@ func (s *UoTTun) ListenAndServe() {
|
||||
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) }
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy.
|
||||
func (s *VMess) Dial(network, addr string) (net.Conn, error) {
|
||||
rc, err := s.dialer.Dial("tcp", s.addr)
|
||||
func (s *VMess) Dial(network, addr string) (net.Conn, string, error) {
|
||||
rc, p, err := s.dialer.Dial("tcp", s.addr)
|
||||
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.
|
||||
|
@ -76,13 +76,14 @@ func (s *WS) Addr() string {
|
||||
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.
|
||||
func (s *WS) Dial(network, addr string) (net.Conn, error) {
|
||||
rc, err := s.dialer.Dial("tcp", s.addr)
|
||||
func (s *WS) Dial(network, addr string) (net.Conn, string, error) {
|
||||
rc, p, err := s.dialer.Dial("tcp", s.addr)
|
||||
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.
|
||||
|
24
rule/rule.go
24
rule/rule.go
@ -12,8 +12,8 @@ import (
|
||||
|
||||
// Dialer struct
|
||||
type Dialer struct {
|
||||
gDialer proxy.Dialer
|
||||
dialers []proxy.Dialer
|
||||
gDialer *strategy.Dialer
|
||||
dialers []*strategy.Dialer
|
||||
|
||||
domainMap sync.Map
|
||||
ipMap sync.Map
|
||||
@ -21,7 +21,7 @@ type Dialer struct {
|
||||
}
|
||||
|
||||
// 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}
|
||||
|
||||
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
|
||||
func (rd *Dialer) Dial(network, addr string) (net.Conn, error) {
|
||||
d := rd.NextDialer(addr)
|
||||
log.F("[dial] %s => %s", addr, d.Addr())
|
||||
return d.Dial(network, addr)
|
||||
func (rd *Dialer) Dial(network, addr string) (net.Conn, string, error) {
|
||||
return rd.NextDialer(addr).Dial(network, addr)
|
||||
}
|
||||
|
||||
// DialUDP connects to the given address via the proxy
|
||||
func (rd *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||
d := rd.NextDialer(addr)
|
||||
log.F("[dial-udp] %s => %s", addr, d.Addr())
|
||||
return d.DialUDP(network, addr)
|
||||
return rd.NextDialer(addr).DialUDP(network, addr)
|
||||
}
|
||||
|
||||
// AddDomainIP used to update ipMap rules according to domainMap rule
|
||||
@ -131,13 +127,9 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error {
|
||||
|
||||
// Check .
|
||||
func (rd *Dialer) Check() {
|
||||
if checker, ok := rd.gDialer.(strategy.Checker); ok {
|
||||
checker.Check()
|
||||
}
|
||||
rd.gDialer.Check()
|
||||
|
||||
for _, d := range rd.dialers {
|
||||
if checker, ok := d.(strategy.Checker); ok {
|
||||
checker.Check()
|
||||
}
|
||||
d.Check()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package proxy
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"net"
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/nadoo/glider/common/log"
|
||||
"github.com/nadoo/glider/proxy"
|
||||
)
|
||||
|
||||
// StatusHandler function will be called when the forwarder's status changed
|
||||
@ -15,7 +16,7 @@ type StatusHandler func(*Forwarder)
|
||||
|
||||
// Forwarder is a forwarder
|
||||
type Forwarder struct {
|
||||
Dialer
|
||||
proxy.Dialer
|
||||
addr string
|
||||
priority uint32
|
||||
maxFailures uint32 // maxfailures to set to Disabled
|
||||
@ -40,14 +41,14 @@ func ForwarderFromURL(s, intface string) (f *Forwarder, err error) {
|
||||
iface = f.intface
|
||||
}
|
||||
|
||||
var d Dialer
|
||||
d, err = NewDirect(iface)
|
||||
var d proxy.Dialer
|
||||
d, err = proxy.NewDirect(iface)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, url := range strings.Split(ss[0], ",") {
|
||||
d, err = DialerFromURL(url, d)
|
||||
d, err = proxy.DialerFromURL(url, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -57,12 +58,21 @@ func ForwarderFromURL(s, intface string) (f *Forwarder, err error) {
|
||||
f.addr = d.Addr()
|
||||
|
||||
// set forwarder to disabled by default
|
||||
// TODO: check here
|
||||
f.Disable()
|
||||
|
||||
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 {
|
||||
query, err := url.ParseQuery(option)
|
||||
if err != nil {
|
||||
@ -87,8 +97,8 @@ func (f *Forwarder) Addr() string {
|
||||
}
|
||||
|
||||
// Dial .
|
||||
func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
|
||||
c, err = f.Dialer.Dial(network, addr)
|
||||
func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) {
|
||||
c, p, err = f.Dialer.Dial(network, addr)
|
||||
if err != nil {
|
||||
f.IncFailures()
|
||||
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
|
@ -31,7 +31,7 @@ type Config struct {
|
||||
}
|
||||
|
||||
// forwarder slice orderd by priority
|
||||
type priSlice []*proxy.Forwarder
|
||||
type priSlice []*Forwarder
|
||||
|
||||
func (p priSlice) Len() int { return len(p) }
|
||||
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 {
|
||||
config *Config
|
||||
fwdrs priSlice
|
||||
available []*proxy.Forwarder
|
||||
available []*Forwarder
|
||||
mu sync.RWMutex
|
||||
index uint32
|
||||
priority uint32
|
||||
|
||||
nextForwarder func(addr string) *proxy.Forwarder
|
||||
nextForwarder func(addr string) *Forwarder
|
||||
}
|
||||
|
||||
// NewDialer returns a new strategy dialer.
|
||||
func NewDialer(s []string, c *Config) proxy.Dialer {
|
||||
var fwdrs []*proxy.Forwarder
|
||||
func NewDialer(s []string, c *Config) *Dialer {
|
||||
var fwdrs []*Forwarder
|
||||
for _, chain := range s {
|
||||
fwdr, err := proxy.ForwarderFromURL(chain, c.IntFace)
|
||||
fwdr, err := ForwarderFromURL(chain, c.IntFace)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -62,22 +62,16 @@ func NewDialer(s []string, c *Config) proxy.Dialer {
|
||||
}
|
||||
|
||||
if len(fwdrs) == 0 {
|
||||
d, err := proxy.NewDirect(c.IntFace)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
if len(fwdrs) == 1 {
|
||||
return fwdrs[0]
|
||||
// direct forwarder
|
||||
fwdrs = append(fwdrs, DirectForwarder(c.IntFace))
|
||||
c.Strategy = "rr"
|
||||
}
|
||||
|
||||
return newDialer(fwdrs, c)
|
||||
}
|
||||
|
||||
// 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}
|
||||
sort.Sort(d.fwdrs)
|
||||
|
||||
@ -90,19 +84,19 @@ func newDialer(fwdrs []*proxy.Forwarder, c *Config) *Dialer {
|
||||
switch c.Strategy {
|
||||
case "rr":
|
||||
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":
|
||||
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":
|
||||
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":
|
||||
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:
|
||||
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 {
|
||||
@ -116,8 +110,10 @@ func newDialer(fwdrs []*proxy.Forwarder, c *Config) *Dialer {
|
||||
func (d *Dialer) Addr() string { return "STRATEGY" }
|
||||
|
||||
// Dial connects to the address addr on the network net.
|
||||
func (d *Dialer) Dial(network, addr string) (net.Conn, error) {
|
||||
return d.NextDialer(addr).Dial(network, addr)
|
||||
func (d *Dialer) Dial(network, addr string) (net.Conn, string, error) {
|
||||
nd := d.NextDialer(addr)
|
||||
c, _, err := nd.Dial(network, addr)
|
||||
return c, nd.Addr(), err
|
||||
}
|
||||
|
||||
// DialUDP connects to the given address.
|
||||
@ -164,7 +160,7 @@ func (d *Dialer) initAvailable() {
|
||||
}
|
||||
|
||||
// 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()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
@ -192,8 +188,11 @@ func (d *Dialer) onStatusChanged(fwdr *proxy.Forwarder) {
|
||||
|
||||
// Check implements the Checker interface.
|
||||
func (d *Dialer) Check() {
|
||||
for i := 0; i < len(d.fwdrs); i++ {
|
||||
go d.check(i)
|
||||
// no need to check when there's only 1 forwarder
|
||||
if len(d.fwdrs) > 1 {
|
||||
for i := 0; i < len(d.fwdrs); i++ {
|
||||
go d.check(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +215,7 @@ func (d *Dialer) check(i int) {
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
rc, err := f.Dial("tcp", d.config.CheckWebSite)
|
||||
rc, _, err := f.Dial("tcp", d.config.CheckWebSite)
|
||||
if err != nil {
|
||||
f.Disable()
|
||||
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
|
||||
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))]
|
||||
}
|
||||
|
||||
// High Availability
|
||||
func (d *Dialer) scheduleHA(dstAddr string) *proxy.Forwarder {
|
||||
func (d *Dialer) scheduleHA(dstAddr string) *Forwarder {
|
||||
return d.available[0]
|
||||
}
|
||||
|
||||
// Latency based High Availability
|
||||
func (d *Dialer) scheduleLHA(dstAddr string) *proxy.Forwarder {
|
||||
func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder {
|
||||
fwdr := d.available[0]
|
||||
lowest := fwdr.Latency()
|
||||
for _, f := range d.available {
|
||||
@ -276,7 +275,7 @@ func (d *Dialer) scheduleLHA(dstAddr string) *proxy.Forwarder {
|
||||
}
|
||||
|
||||
// Destination Hashing
|
||||
func (d *Dialer) scheduleDH(dstAddr string) *proxy.Forwarder {
|
||||
func (d *Dialer) scheduleDH(dstAddr string) *Forwarder {
|
||||
fnv1a := fnv.New32a()
|
||||
fnv1a.Write([]byte(dstAddr))
|
||||
return d.available[fnv1a.Sum32()%uint32(len(d.available))]
|
||||
|
Loading…
Reference in New Issue
Block a user