proxy: add a new interface proxy to distinguish client and server

This commit is contained in:
nadoo 2019-09-18 19:40:14 +08:00
parent 6c8141e43b
commit edcb21236a
27 changed files with 371 additions and 398 deletions

View File

@ -28,7 +28,7 @@ type Config struct {
// Client is a dns client struct. // Client is a dns client struct.
type Client struct { type Client struct {
dialer proxy.Dialer proxy proxy.Proxy
cache *Cache cache *Cache
config *Config config *Config
upServers []string upServers []string
@ -37,9 +37,9 @@ type Client struct {
} }
// NewClient returns a new dns client. // NewClient returns a new dns client.
func NewClient(dialer proxy.Dialer, config *Config) (*Client, error) { func NewClient(proxy proxy.Proxy, config *Config) (*Client, error) {
c := &Client{ c := &Client{
dialer: dialer, proxy: proxy,
cache: NewCache(), cache: NewCache(),
config: config, config: config,
upServers: config.Servers, upServers: config.Servers,
@ -126,7 +126,7 @@ func (c *Client) Exchange(reqBytes []byte, clientAddr string, preferTCP bool) ([
func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server, network string, respBytes []byte, err error) { func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server, network string, respBytes []byte, err error) {
// use tcp to connect upstream server default // use tcp to connect upstream server default
network = "tcp" network = "tcp"
dialer := c.dialer.NextDialer(qname + ":53") dialer := c.proxy.NextDialer(qname + ":53")
// if we are resolving the dialer's domain, then use Direct to avoid denpency loop // if we are resolving the dialer's domain, then use Direct to avoid denpency loop
// TODO: dialer.Addr() == "reject", tricky // TODO: dialer.Addr() == "reject", tricky
@ -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

@ -22,8 +22,8 @@ type Server struct {
} }
// NewServer returns a new dns server. // NewServer returns a new dns server.
func NewServer(addr string, dialer proxy.Dialer, config *Config) (*Server, error) { func NewServer(addr string, proxy proxy.Proxy, config *Config) (*Server, error) {
c, err := NewClient(dialer, config) c, err := NewClient(proxy, config)
s := &Server{ s := &Server{
addr: addr, addr: addr,
Client: c, Client: c,

12
main.go
View File

@ -42,15 +42,15 @@ func main() {
} }
} }
// global rule dialer // global rule proxy
dialer := rule.NewDialer(conf.rules, strategy.NewDialer(conf.Forward, &conf.StrategyConfig)) p := rule.NewProxy(conf.rules, strategy.NewProxy(conf.Forward, &conf.StrategyConfig))
// ipset manager // ipset manager
ipsetM, _ := ipset.NewManager(conf.rules) ipsetM, _ := ipset.NewManager(conf.rules)
// check and setup dns server // check and setup dns server
if conf.DNS != "" { if conf.DNS != "" {
d, err := dns.NewServer(conf.DNS, dialer, &conf.DNSConfig) d, err := dns.NewServer(conf.DNS, p, &conf.DNSConfig)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -65,7 +65,7 @@ func main() {
} }
// add a handler to update proxy rules when a domain resolved // add a handler to update proxy rules when a domain resolved
d.AddHandler(dialer.AddDomainIP) d.AddHandler(p.AddDomainIP)
if ipsetM != nil { if ipsetM != nil {
d.AddHandler(ipsetM.AddDomainIP) d.AddHandler(ipsetM.AddDomainIP)
} }
@ -74,11 +74,11 @@ func main() {
} }
// enable checkers // enable checkers
dialer.Check() p.Check()
// Proxy Servers // Proxy Servers
for _, listen := range conf.Listen { for _, listen := range conf.Listen {
local, err := proxy.ServerFromURL(listen, dialer) local, err := proxy.ServerFromURL(listen, p)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -9,19 +9,16 @@ import (
"github.com/nadoo/glider/common/log" "github.com/nadoo/glider/common/log"
) )
// Dialer means to establish a connection and relay it. // Dialer is used to create connection.
type Dialer interface { type Dialer interface {
// Addr() // Addr is the dialer's addr
Addr() string Addr() string
// Dial connects to the given address via the proxy. // Dial connects to the given address
Dial(network, addr string) (c net.Conn, proxy string, err error) Dial(network, addr string) (c net.Conn, err error)
// DialUDP connects to the given address via the proxy. // DialUDP connects to the given address
DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error)
// Get the dialer by dstAddr
NextDialer(dstAddr string) Dialer
} }
// DialerCreator is a function to create dialers. // DialerCreator is a function to create dialers.
@ -31,7 +28,7 @@ var (
dialerMap = make(map[string]DialerCreator) dialerMap = make(map[string]DialerCreator)
) )
// RegisterDialer is used to register a dialer // RegisterDialer is used to register a dialer.
func RegisterDialer(name string, c DialerCreator) { func RegisterDialer(name string, c DialerCreator) {
dialerMap[name] = c dialerMap[name] = c
} }

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, p string, err error) { func (d *Direct) Dial(network, addr string) (c net.Conn, 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, p string, 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 c, "DIRECT", err return c, err
} }
func dial(network, addr string, localIP net.IP) (net.Conn, error) { func dial(network, addr string, localIP net.IP) (net.Conn, error) {
@ -107,9 +107,6 @@ func (d *Direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error)
return pc, uAddr, err return pc, uAddr, err
} }
// NextDialer returns the next dialer
func (d *Direct) NextDialer(dstAddr string) Dialer { return d }
// IFaceIPs returns ip addresses according to the specified interface // IFaceIPs returns ip addresses according to the specified interface
func (d *Direct) IFaceIPs() (ips []net.IP) { func (d *Direct) IFaceIPs() (ips []net.IP) {
ipnets, err := d.iface.Addrs() ipnets, err := d.iface.Addrs()

View File

@ -24,6 +24,7 @@ import (
// HTTP struct // HTTP struct
type HTTP struct { type HTTP struct {
dialer proxy.Dialer dialer proxy.Dialer
proxy proxy.Proxy
addr string addr string
user string user string
password string password string
@ -36,7 +37,7 @@ func init() {
} }
// NewHTTP returns a http proxy // NewHTTP returns a http proxy
func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) { func NewHTTP(s string, d proxy.Dialer, p proxy.Proxy) (*HTTP, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -48,7 +49,8 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
pass, _ := u.User.Password() pass, _ := u.User.Password()
h := &HTTP{ h := &HTTP{
dialer: dialer, dialer: d,
proxy: p,
addr: addr, addr: addr,
user: user, user: user,
password: pass, password: pass,
@ -64,13 +66,13 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
} }
// NewHTTPDialer returns a http proxy dialer // NewHTTPDialer returns a http proxy dialer
func NewHTTPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewHTTPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewHTTP(s, dialer) return NewHTTP(s, d, nil)
} }
// NewHTTPServer returns a http proxy server // NewHTTPServer returns a http proxy server
func NewHTTPServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewHTTPServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewHTTP(s, dialer) return NewHTTP(s, nil, p)
} }
// ListenAndServe . // ListenAndServe .
@ -142,7 +144,7 @@ func (s *HTTP) Serve(c net.Conn) {
tgt += ":80" tgt += ":80"
} }
rc, p, err := s.dialer.Dial("tcp", tgt) rc, p, err := s.proxy.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, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) log.F("[http] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
@ -200,7 +202,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, p, err := s.dialer.Dial("tcp", requestURI) rc, p, err := s.proxy.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"))
@ -229,15 +231,12 @@ func (s *HTTP) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer
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, string, error) { func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
rc, p, err := s.dialer.Dial(network, s.addr) rc, 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, p, err return nil, err
} }
var buf bytes.Buffer var buf bytes.Buffer
@ -254,7 +253,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, 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, p, err return nil, err
} }
c := conn.NewConn(rc) c := conn.NewConn(rc)
@ -262,7 +261,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
_, code, _, ok := parseFirstLine(tpr) _, code, _, ok := parseFirstLine(tpr)
if ok && code == "200" { if ok && code == "200" {
tpr.ReadMIMEHeader() tpr.ReadMIMEHeader()
return c, p, err return c, err
} }
if code == "407" { if code == "407" {
@ -271,7 +270,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, 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, p, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code) return nil, 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

View File

@ -18,6 +18,7 @@ import (
// KCP struct // KCP struct
type KCP struct { type KCP struct {
dialer proxy.Dialer dialer proxy.Dialer
proxy proxy.Proxy
addr string addr string
key string key string
@ -36,7 +37,7 @@ func init() {
} }
// NewKCP returns a kcp proxy struct // NewKCP returns a kcp proxy struct
func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) { func NewKCP(s string, d proxy.Dialer, p proxy.Proxy) (*KCP, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("[kcp] parse url err: %s", err) log.F("[kcp] parse url err: %s", err)
@ -73,8 +74,9 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
return nil, err return nil, err
} }
p := &KCP{ k := &KCP{
dialer: dialer, dialer: d,
proxy: p,
addr: addr, addr: addr,
key: key, key: key,
crypt: crypt, crypt: crypt,
@ -82,10 +84,10 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
parityShards: int(parityShards), parityShards: int(parityShards),
} }
if p.crypt != "" { if k.crypt != "" {
pass := pbkdf2.Key([]byte(p.key), []byte("kcp-go"), 4096, 32, sha1.New) pass := pbkdf2.Key([]byte(k.key), []byte("kcp-go"), 4096, 32, sha1.New)
var block kcp.BlockCrypt var block kcp.BlockCrypt
switch p.crypt { switch k.crypt {
case "sm4": case "sm4":
block, _ = kcp.NewSM4BlockCrypt(pass[:16]) block, _ = kcp.NewSM4BlockCrypt(pass[:16])
case "tea": case "tea":
@ -113,22 +115,22 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
case "salsa20": case "salsa20":
block, _ = kcp.NewSalsa20BlockCrypt(pass) block, _ = kcp.NewSalsa20BlockCrypt(pass)
default: default:
return nil, errors.New("[kcp] unknown crypt type '" + p.crypt + "'") return nil, errors.New("[kcp] unknown crypt type '" + k.crypt + "'")
} }
p.block = block k.block = block
} }
return p, nil return k, nil
} }
// NewKCPDialer returns a kcp proxy dialer // NewKCPDialer returns a kcp proxy dialer
func NewKCPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewKCPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewKCP(s, dialer) return NewKCP(s, d, nil)
} }
// NewKCPServer returns a kcp proxy server // NewKCPServer returns a kcp proxy server
func NewKCPServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewKCPServer(s string, p proxy.Proxy) (proxy.Server, error) {
transport := strings.Split(s, ",") transport := strings.Split(s, ",")
// prepare transport listener // prepare transport listener
@ -137,17 +139,17 @@ func NewKCPServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return nil, errors.New("[kcp] malformd listener:" + s) return nil, errors.New("[kcp] malformd listener:" + s)
} }
p, err := NewKCP(transport[0], dialer) k, err := NewKCP(transport[0], nil, p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.server, err = proxy.ServerFromURL(transport[1], dialer) k.server, err = proxy.ServerFromURL(transport[1], p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return p, nil return k, nil
} }
// ListenAndServe . // ListenAndServe .
@ -193,16 +195,13 @@ func (s *KCP) Serve(c net.Conn) {
// Addr returns forwarder's address // Addr returns forwarder's address
func (s *KCP) Addr() string { return s.addr } func (s *KCP) Addr() string { return s.addr }
// NextDialer returns the next dialer
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, string, error) { func (s *KCP) Dial(network, addr string) (net.Conn, 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("[kcp] 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 +216,7 @@ func (s *KCP) Dial(network, addr string) (net.Conn, string, 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

@ -27,11 +27,11 @@ var httpMethods = [...][]byte{
// MixedProxy struct // MixedProxy struct
type MixedProxy struct { type MixedProxy struct {
dialer proxy.Dialer proxy proxy.Proxy
addr string addr string
http *http.HTTP http *http.HTTP
socks5 *socks5.SOCKS5 socks5 *socks5.Socks5
} }
func init() { func init() {
@ -39,27 +39,27 @@ func init() {
} }
// NewMixedProxy returns a mixed proxy // NewMixedProxy returns a mixed proxy
func NewMixedProxy(s string, dialer proxy.Dialer) (*MixedProxy, error) { func NewMixedProxy(s string, p proxy.Proxy) (*MixedProxy, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
return nil, err return nil, err
} }
p := &MixedProxy{ m := &MixedProxy{
dialer: dialer, proxy: p,
addr: u.Host, addr: u.Host,
} }
p.http, _ = http.NewHTTP(s, dialer) m.http, _ = http.NewHTTP(s, nil, p)
p.socks5, _ = socks5.NewSOCKS5(s, dialer) m.socks5, _ = socks5.NewSocks5(s, nil, p)
return p, nil return m, nil
} }
// NewMixedProxyServer returns a mixed proxy server // NewMixedProxyServer returns a mixed proxy server
func NewMixedProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewMixedProxyServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewMixedProxy(s, dialer) return NewMixedProxy(s, p)
} }
// ListenAndServe . // ListenAndServe .

View File

@ -28,7 +28,7 @@ func init() {
} }
// NewObfs returns a proxy struct // NewObfs returns a proxy struct
func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) { func NewObfs(s string, d proxy.Dialer) (*Obfs, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse url err: %s", err) log.F("parse url err: %s", err)
@ -59,7 +59,7 @@ func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) {
} }
p := &Obfs{ p := &Obfs{
dialer: dialer, dialer: d,
addr: addr, addr: addr,
obfsType: obfsType, obfsType: obfsType,
obfsHost: obfsHost, obfsHost: obfsHost,
@ -89,19 +89,16 @@ func NewObfsDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
// Addr returns forwarder's address // Addr returns forwarder's address
func (s *Obfs) Addr() string { return s.addr } func (s *Obfs) Addr() string { return s.addr }
// NextDialer returns the next dialer
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, string, error) { func (s *Obfs) Dial(network, addr string) (net.Conn, error) {
c, p, err := s.dialer.Dial("tcp", s.addr) c, 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, p, err return nil, err
} }
cc, e := s.obfsConn(c) cc, e := s.obfsConn(c)
return cc, p, e return cc, e
} }
// DialUDP connects to the given address via the proxy // DialUDP connects to the given address via the proxy

15
proxy/proxy.go Normal file
View File

@ -0,0 +1,15 @@
package proxy
import "net"
// Proxy is a dialer manager
type Proxy interface {
// Dial connects to the given address via the proxy.
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)
// Get the dialer by dstAddr
NextDialer(dstAddr string) Dialer
}

View File

@ -25,7 +25,7 @@ const (
// RedirProxy struct // RedirProxy struct
type RedirProxy struct { type RedirProxy struct {
dialer proxy.Dialer proxy proxy.Proxy
addr string addr string
ipv6 bool ipv6 bool
} }
@ -36,7 +36,7 @@ func init() {
} }
// NewRedirProxy returns a redirect proxy. // NewRedirProxy returns a redirect proxy.
func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error) { func NewRedirProxy(s string, p proxy.Proxy, ipv6 bool) (*RedirProxy, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -45,7 +45,7 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
addr := u.Host addr := u.Host
r := &RedirProxy{ r := &RedirProxy{
dialer: dialer, proxy: p,
addr: addr, addr: addr,
ipv6: ipv6, ipv6: ipv6,
} }
@ -54,13 +54,13 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
} }
// NewRedirServer returns a redir server. // NewRedirServer returns a redir server.
func NewRedirServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewRedirServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewRedirProxy(s, dialer, false) return NewRedirProxy(s, p, false)
} }
// NewRedir6Server returns a redir server for ipv6. // NewRedir6Server returns a redir server for ipv6.
func NewRedir6Server(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewRedir6Server(s string, p proxy.Proxy) (proxy.Server, error) {
return NewRedirProxy(s, dialer, true) return NewRedirProxy(s, p, true)
} }
// ListenAndServe . // ListenAndServe .
@ -104,7 +104,7 @@ func (s *RedirProxy) Serve(c net.Conn) {
return return
} }
rc, p, err := s.dialer.Dial("tcp", tgt.String()) rc, p, err := s.proxy.Dial("tcp", tgt.String())
if err != nil { if err != nil {
log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
return return

View File

@ -16,24 +16,21 @@ func init() {
} }
// NewReject returns a reject proxy, reject:// // NewReject returns a reject proxy, reject://
func NewReject(s string, dialer proxy.Dialer) (*Reject, error) { func NewReject(s string, d proxy.Dialer) (*Reject, error) {
return &Reject{}, nil return &Reject{}, nil
} }
// NewRejectDialer returns a reject proxy dialer. // NewRejectDialer returns a reject proxy dialer.
func NewRejectDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewRejectDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewReject(s, dialer) return NewReject(s, d)
} }
// Addr returns forwarder's address. // Addr returns forwarder's address.
func (s *Reject) Addr() string { return "REJECT" } func (s *Reject) Addr() string { return "REJECT" }
// NextDialer returns the next dialer.
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, string, error) { func (s *Reject) Dial(network, addr string) (net.Conn, error) {
return nil, "REJECT", errors.New("REJECT") return nil, errors.New("REJECT")
} }
// DialUDP connects to the given address via the proxy. // DialUDP connects to the given address via the proxy.

View File

@ -19,7 +19,7 @@ type Server interface {
} }
// ServerCreator is a function to create proxy servers // ServerCreator is a function to create proxy servers
type ServerCreator func(s string, dialer Dialer) (Server, error) type ServerCreator func(s string, proxy Proxy) (Server, error)
var ( var (
serverMap = make(map[string]ServerCreator) serverMap = make(map[string]ServerCreator)
@ -32,8 +32,8 @@ func RegisterServer(name string, c ServerCreator) {
// ServerFromURL calls the registered creator to create proxy servers // ServerFromURL calls the registered creator to create proxy servers
// dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function // dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function
func ServerFromURL(s string, dialer Dialer) (Server, error) { func ServerFromURL(s string, p Proxy) (Server, error) {
if dialer == nil { if p == nil {
return nil, errors.New("ServerFromURL: dialer cannot be nil") return nil, errors.New("ServerFromURL: dialer cannot be nil")
} }
@ -49,7 +49,7 @@ func ServerFromURL(s string, dialer Dialer) (Server, error) {
c, ok := serverMap[strings.ToLower(u.Scheme)] c, ok := serverMap[strings.ToLower(u.Scheme)]
if ok { if ok {
return c(s, dialer) return c(s, p)
} }
return nil, errors.New("unknown scheme '" + u.Scheme + "'") return nil, errors.New("unknown scheme '" + u.Scheme + "'")

View File

@ -30,9 +30,10 @@ import (
// Version is socks5 version number. // Version is socks5 version number.
const Version = 5 const Version = 5
// SOCKS5 is a base socks5 struct. // Socks5 is a base socks5 struct.
type SOCKS5 struct { type Socks5 struct {
dialer proxy.Dialer dialer proxy.Dialer
proxy proxy.Proxy
addr string addr string
user string user string
password string password string
@ -43,9 +44,9 @@ func init() {
proxy.RegisterServer("socks5", NewSocks5Server) proxy.RegisterServer("socks5", NewSocks5Server)
} }
// NewSOCKS5 returns a Proxy that makes SOCKS v5 connections to the given address // NewSocks5 returns a Proxy that makes SOCKS v5 connections to the given address
// with an optional username and password. (RFC 1928) // with an optional username and password. (RFC 1928)
func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) { func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -56,8 +57,9 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
user := u.User.Username() user := u.User.Username()
pass, _ := u.User.Password() pass, _ := u.User.Password()
h := &SOCKS5{ h := &Socks5{
dialer: dialer, dialer: d,
proxy: p,
addr: addr, addr: addr,
user: user, user: user,
password: pass, password: pass,
@ -67,23 +69,23 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
} }
// NewSocks5Dialer returns a socks5 proxy dialer. // NewSocks5Dialer returns a socks5 proxy dialer.
func NewSocks5Dialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewSocks5Dialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSOCKS5(s, dialer) return NewSocks5(s, d, nil)
} }
// NewSocks5Server returns a socks5 proxy server. // NewSocks5Server returns a socks5 proxy server.
func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewSocks5Server(s string, p proxy.Proxy) (proxy.Server, error) {
return NewSOCKS5(s, dialer) return NewSocks5(s, nil, p)
} }
// ListenAndServe serves socks5 requests. // ListenAndServe serves socks5 requests.
func (s *SOCKS5) ListenAndServe() { func (s *Socks5) ListenAndServe() {
go s.ListenAndServeUDP() go s.ListenAndServeUDP()
s.ListenAndServeTCP() s.ListenAndServeTCP()
} }
// ListenAndServeTCP listen and serve on tcp port. // ListenAndServeTCP listen and serve on tcp port.
func (s *SOCKS5) ListenAndServeTCP() { func (s *Socks5) ListenAndServeTCP() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
log.F("[socks5] failed to listen on %s: %v", s.addr, err) log.F("[socks5] failed to listen on %s: %v", s.addr, err)
@ -104,7 +106,7 @@ func (s *SOCKS5) ListenAndServeTCP() {
} }
// Serve serves a connection. // Serve serves a connection.
func (s *SOCKS5) Serve(c net.Conn) { func (s *Socks5) Serve(c net.Conn) {
defer c.Close() defer c.Close()
if c, ok := c.(*net.TCPConn); ok { if c, ok := c.(*net.TCPConn); ok {
@ -131,7 +133,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
return return
} }
rc, p, err := s.dialer.Dial("tcp", tgt.String()) rc, p, err := s.proxy.Dial("tcp", tgt.String())
if err != nil { if err != nil {
log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
return return
@ -150,7 +152,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
} }
// ListenAndServeUDP serves udp requests. // ListenAndServeUDP serves udp requests.
func (s *SOCKS5) ListenAndServeUDP() { func (s *Socks5) ListenAndServeUDP() {
lc, err := net.ListenPacket("udp", s.addr) lc, err := net.ListenPacket("udp", s.addr)
if err != nil { if err != nil {
log.F("[socks5-udp] failed to listen on %s: %v", s.addr, err) log.F("[socks5-udp] failed to listen on %s: %v", s.addr, err)
@ -213,41 +215,38 @@ func (s *SOCKS5) ListenAndServeUDP() {
} }
// Addr returns forwarder's address. // Addr returns forwarder's address.
func (s *SOCKS5) Addr() string { func (s *Socks5) Addr() string {
if s.addr == "" { if s.addr == "" {
return s.dialer.Addr() return s.dialer.Addr()
} }
return s.addr return s.addr
} }
// NextDialer returns the next dialer.
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, string, error) { func (s *Socks5) Dial(network, addr string) (net.Conn, 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, p, err := s.dialer.Dial(network, s.addr) c, 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, p, err return nil, err
} }
if err := s.connect(c, addr); err != nil { if err := s.connect(c, addr); err != nil {
c.Close() c.Close()
return nil, p, err return nil, err
} }
return c, p, nil return c, 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
@ -295,7 +294,7 @@ func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.A
// connect takes an existing connection to a socks5 proxy server, // connect takes an existing connection to a socks5 proxy server,
// and commands the server to extend that connection to target, // and commands the server to extend that connection to target,
// which must be a canonical address with a host and port. // which must be a canonical address with a host and port.
func (s *SOCKS5) connect(conn net.Conn, target string) error { func (s *Socks5) connect(conn net.Conn, target string) error {
host, portStr, err := net.SplitHostPort(target) host, portStr, err := net.SplitHostPort(target)
if err != nil { if err != nil {
return err return err
@ -426,7 +425,7 @@ func (s *SOCKS5) connect(conn net.Conn, target string) error {
} }
// Handshake fast-tracks SOCKS initialization to get target address to connect. // Handshake fast-tracks SOCKS initialization to get target address to connect.
func (s *SOCKS5) handshake(rw io.ReadWriter) (socks.Addr, error) { func (s *Socks5) handshake(rw io.ReadWriter) (socks.Addr, error) {
// Read RFC 1928 for request and reply structure and sizes // Read RFC 1928 for request and reply structure and sizes
buf := make([]byte, socks.MaxAddrLen) buf := make([]byte, socks.MaxAddrLen)
// read VER, NMETHODS, METHODS // read VER, NMETHODS, METHODS

View File

@ -19,6 +19,7 @@ import (
// SS is a base ss struct. // SS is a base ss struct.
type SS struct { type SS struct {
dialer proxy.Dialer dialer proxy.Dialer
proxy proxy.Proxy
addr string addr string
core.Cipher core.Cipher
@ -30,7 +31,7 @@ func init() {
} }
// NewSS returns a ss proxy. // NewSS returns a ss proxy.
func NewSS(s string, dialer proxy.Dialer) (*SS, error) { func NewSS(s string, d proxy.Dialer, p proxy.Proxy) (*SS, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -46,23 +47,24 @@ func NewSS(s string, dialer proxy.Dialer) (*SS, error) {
log.Fatalf("[ss] PickCipher for '%s', error: %s", method, err) log.Fatalf("[ss] PickCipher for '%s', error: %s", method, err)
} }
p := &SS{ ss := &SS{
dialer: dialer, dialer: d,
proxy: p,
addr: addr, addr: addr,
Cipher: ciph, Cipher: ciph,
} }
return p, nil return ss, nil
} }
// NewSSDialer returns a ss proxy dialer. // NewSSDialer returns a ss proxy dialer.
func NewSSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewSSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSS(s, dialer) return NewSS(s, d, nil)
} }
// NewSSServer returns a ss proxy server. // NewSSServer returns a ss proxy server.
func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewSSServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewSS(s, dialer) return NewSS(s, nil, p)
} }
// ListenAndServe serves ss requests. // ListenAndServe serves ss requests.
@ -108,7 +110,7 @@ func (s *SS) Serve(c net.Conn) {
return return
} }
dialer := s.dialer.NextDialer(tgt.String()) dialer := s.proxy.NextDialer(tgt.String())
// udp over tcp? // udp over tcp?
uot := socks.UoT(tgt[0]) uot := socks.UoT(tgt[0])
@ -147,14 +149,14 @@ func (s *SS) Serve(c net.Conn) {
network = "udp" network = "udp"
} }
rc, p, err := dialer.Dial(network, tgt.String()) rc, err := dialer.Dial(network, tgt.String())
if err != nil { if err != nil {
log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p) log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, dialer.Addr())
return return
} }
defer rc.Close() defer rc.Close()
log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, p) log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, dialer.Addr())
_, _, err = conn.Relay(c, rc) _, _, err = conn.Relay(c, rc)
if err != nil { if err != nil {
@ -238,33 +240,30 @@ func (s *SS) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer.
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, string, error) { func (s *SS) Dial(network, addr string) (net.Conn, 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, p, err := s.dialer.Dial("tcp", s.addr) c, 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, p, err return nil, 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, p, err return nil, err
} }
return c, p, err return c, err
} }

View File

@ -37,7 +37,7 @@ func init() {
} }
// NewSSR returns a shadowsocksr proxy, ssr://method:pass@host:port/query // NewSSR returns a shadowsocksr proxy, ssr://method:pass@host:port/query
func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) { func NewSSR(s string, d proxy.Dialer) (*SSR, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -49,7 +49,7 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
pass, _ := u.User.Password() pass, _ := u.User.Password()
p := &SSR{ p := &SSR{
dialer: dialer, dialer: d,
addr: addr, addr: addr,
EncryptMethod: method, EncryptMethod: method,
EncryptPassword: pass, EncryptPassword: pass,
@ -65,8 +65,8 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
} }
// NewSSRDialer returns a ssr proxy dialer. // NewSSRDialer returns a ssr proxy dialer.
func NewSSRDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewSSRDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSSR(s, dialer) return NewSSR(s, d)
} }
// Addr returns forwarder's address // Addr returns forwarder's address
@ -77,30 +77,27 @@ func (s *SSR) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer
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, string, error) { func (s *SSR) Dial(network, addr string) (net.Conn, 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, p, err := s.dialer.Dial("tcp", s.addr) c, 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, p, err return nil, 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, p, errors.New("[ssr] nil connection") return nil, errors.New("[ssr] nil connection")
} }
// should initialize obfs/protocol now // should initialize obfs/protocol now
@ -109,7 +106,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
ssrconn.IObfs = obfs.NewObfs(s.Obfs) ssrconn.IObfs = obfs.NewObfs(s.Obfs)
if ssrconn.IObfs == nil { if ssrconn.IObfs == nil {
return nil, p, errors.New("[ssr] unsupported obfs type: " + s.Obfs) return nil, errors.New("[ssr] unsupported obfs type: " + s.Obfs)
} }
obfsServerInfo := &ssr.ServerInfoForObfs{ obfsServerInfo := &ssr.ServerInfoForObfs{
@ -122,7 +119,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol) ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
if ssrconn.IProtocol == nil { if ssrconn.IProtocol == nil {
return nil, p, errors.New("[ssr] unsupported protocol type: " + s.Protocol) return nil, errors.New("[ssr] unsupported protocol type: " + s.Protocol)
} }
protocolServerInfo := &ssr.ServerInfoForObfs{ protocolServerInfo := &ssr.ServerInfoForObfs{
@ -145,10 +142,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
if _, err := ssrconn.Write(target); err != nil { if _, err := ssrconn.Write(target); err != nil {
ssrconn.Close() ssrconn.Close()
return nil, p, err return nil, err
} }
return ssrconn, p, err return ssrconn, err
} }
// DialUDP connects to the given address via the proxy. // DialUDP connects to the given address via the proxy.

View File

@ -12,7 +12,7 @@ import (
// TCPTun struct // TCPTun struct
type TCPTun struct { type TCPTun struct {
dialer proxy.Dialer proxy proxy.Proxy
addr string addr string
raddr string raddr string
@ -23,7 +23,7 @@ func init() {
} }
// NewTCPTun returns a tcptun proxy // NewTCPTun returns a tcptun proxy
func NewTCPTun(s string, dialer proxy.Dialer) (*TCPTun, error) { func NewTCPTun(s string, p proxy.Proxy) (*TCPTun, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -33,18 +33,18 @@ func NewTCPTun(s string, dialer proxy.Dialer) (*TCPTun, error) {
addr := u.Host addr := u.Host
d := strings.Split(addr, "=") d := strings.Split(addr, "=")
p := &TCPTun{ t := &TCPTun{
dialer: dialer, proxy: p,
addr: d[0], addr: d[0],
raddr: d[1], raddr: d[1],
} }
return p, nil return t, nil
} }
// NewTCPTunServer returns a udp tunnel server // NewTCPTunServer returns a udp tunnel server
func NewTCPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewTCPTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewTCPTun(s, dialer) return NewTCPTun(s, p)
} }
// ListenAndServe . // ListenAndServe .
@ -76,7 +76,7 @@ func (s *TCPTun) Serve(c net.Conn) {
c.SetKeepAlive(true) c.SetKeepAlive(true)
} }
rc, p, err := s.dialer.Dial("tcp", s.raddr) rc, p, err := s.proxy.Dial("tcp", s.raddr)
if err != nil { if err != nil {
log.F("[tcptun] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), s.addr, err, p) log.F("[tcptun] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), s.addr, err, p)
return return

View File

@ -14,6 +14,7 @@ import (
// TLS struct // TLS struct
type TLS struct { type TLS struct {
dialer proxy.Dialer dialer proxy.Dialer
proxy proxy.Proxy
addr string addr string
tlsConfig *stdtls.Config tlsConfig *stdtls.Config
@ -34,7 +35,7 @@ func init() {
} }
// NewTLS returns a tls proxy struct // NewTLS returns a tls proxy struct
func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) { func NewTLS(s string, d proxy.Dialer, p proxy.Proxy) (*TLS, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse url err: %s", err) log.F("parse url err: %s", err)
@ -53,9 +54,9 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
certFile := query.Get("cert") certFile := query.Get("cert")
keyFile := query.Get("key") keyFile := query.Get("key")
p := &TLS{ t := &TLS{
dialer: dialer, dialer: d,
addr: addr, proxy: p,
serverName: serverName, serverName: serverName,
skipVerify: false, skipVerify: false,
certFile: certFile, certFile: certFile,
@ -63,15 +64,15 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
} }
if skipVerify == "true" { if skipVerify == "true" {
p.skipVerify = true t.skipVerify = true
} }
return p, nil return t, nil
} }
// NewTLSDialer returns a tls proxy dialer // NewTLSDialer returns a tls proxy dialer
func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewTLSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
p, err := NewTLS(s, dialer) p, err := NewTLS(s, d, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -87,7 +88,7 @@ func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
} }
// NewTLSServer returns a tls transport layer before the real server // NewTLSServer returns a tls transport layer before the real server
func NewTLSServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewTLSServer(s string, p proxy.Proxy) (proxy.Server, error) {
transport := strings.Split(s, ",") transport := strings.Split(s, ",")
// prepare transport listener // prepare transport listener
@ -96,28 +97,28 @@ func NewTLSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return nil, errors.New("[tls] malformd listener:" + s) return nil, errors.New("[tls] malformd listener:" + s)
} }
p, err := NewTLS(transport[0], dialer) t, err := NewTLS(transport[0], nil, p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
cert, err := stdtls.LoadX509KeyPair(p.certFile, p.keyFile) cert, err := stdtls.LoadX509KeyPair(t.certFile, t.keyFile)
if err != nil { if err != nil {
log.F("[tls] unable to load cert: %s, key %s", p.certFile, p.keyFile) log.F("[tls] unable to load cert: %s, key %s", t.certFile, t.keyFile)
return nil, err return nil, err
} }
p.tlsConfig = &stdtls.Config{ t.tlsConfig = &stdtls.Config{
Certificates: []stdtls.Certificate{cert}, Certificates: []stdtls.Certificate{cert},
MinVersion: stdtls.VersionTLS10, MinVersion: stdtls.VersionTLS10,
} }
p.server, err = proxy.ServerFromURL(transport[1], dialer) t.server, err = proxy.ServerFromURL(transport[1], p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return p, nil return t, nil
} }
// ListenAndServe . // ListenAndServe .
@ -156,20 +157,17 @@ func (s *TLS) Serve(c net.Conn) {
// Addr returns forwarder's address // Addr returns forwarder's address
func (s *TLS) Addr() string { return s.addr } func (s *TLS) Addr() string { return s.addr }
// NextDialer returns the next dialer
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, string, error) { func (s *TLS) Dial(network, addr string) (net.Conn, error) {
cc, p, err := s.dialer.Dial("tcp", s.addr) cc, 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, p, err return nil, err
} }
c := stdtls.Client(cc, s.tlsConfig) c := stdtls.Client(cc, s.tlsConfig)
err = c.Handshake() err = c.Handshake()
return c, p, err return c, err
} }
// DialUDP connects to the given address via the proxy // DialUDP connects to the given address via the proxy

View File

@ -19,7 +19,7 @@ import (
// TProxy struct // TProxy struct
type TProxy struct { type TProxy struct {
dialer proxy.Dialer proxy proxy.Proxy
addr string addr string
} }
@ -28,7 +28,7 @@ func init() {
} }
// NewTProxy returns a tproxy. // NewTProxy returns a tproxy.
func NewTProxy(s string, dialer proxy.Dialer) (*TProxy, error) { func NewTProxy(s string, p proxy.Proxy) (*TProxy, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -37,17 +37,17 @@ func NewTProxy(s string, dialer proxy.Dialer) (*TProxy, error) {
addr := u.Host addr := u.Host
p := &TProxy{ tp := &TProxy{
dialer: dialer, proxy: p,
addr: addr, addr: addr,
} }
return p, nil return tp, nil
} }
// NewTProxyServer returns a udp tunnel server. // NewTProxyServer returns a udp tunnel server.
func NewTProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewTProxyServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewTProxy(s, dialer) return NewTProxy(s, p)
} }
// ListenAndServe . // ListenAndServe .

View File

@ -14,7 +14,7 @@ import (
// UDPTun is a base udptun struct. // UDPTun is a base udptun struct.
type UDPTun struct { type UDPTun struct {
dialer proxy.Dialer proxy proxy.Proxy
addr string addr string
taddr string // tunnel addr string taddr string // tunnel addr string
tuaddr *net.UDPAddr // tunnel addr tuaddr *net.UDPAddr // tunnel addr
@ -25,7 +25,7 @@ func init() {
} }
// NewUDPTun returns a UDPTun proxy. // NewUDPTun returns a UDPTun proxy.
func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) { func NewUDPTun(s string, p proxy.Proxy) (*UDPTun, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("[udptun] parse err: %s", err) log.F("[udptun] parse err: %s", err)
@ -35,19 +35,19 @@ func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) {
addr := u.Host addr := u.Host
d := strings.Split(addr, "=") d := strings.Split(addr, "=")
p := &UDPTun{ ut := &UDPTun{
dialer: dialer, proxy: p,
addr: d[0], addr: d[0],
taddr: d[1], taddr: d[1],
} }
p.tuaddr, err = net.ResolveUDPAddr("udp", p.taddr) ut.tuaddr, err = net.ResolveUDPAddr("udp", ut.taddr)
return p, err return ut, err
} }
// NewUDPTunServer returns a udp tunnel server. // NewUDPTunServer returns a udp tunnel server.
func NewUDPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewUDPTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewUDPTun(s, dialer) return NewUDPTun(s, p)
} }
// ListenAndServe listen and serves on the given address. // ListenAndServe listen and serves on the given address.
@ -75,7 +75,7 @@ func (s *UDPTun) ListenAndServe() {
v, ok := nm.Load(raddr.String()) v, ok := nm.Load(raddr.String())
if !ok && v == nil { if !ok && v == nil {
pc, _, err = s.dialer.DialUDP("udp", s.taddr) pc, _, err = s.proxy.DialUDP("udp", s.taddr)
if err != nil { if err != nil {
log.F("[udptun] remote dial error: %v", err) log.F("[udptun] remote dial error: %v", err)
continue continue

View File

@ -14,6 +14,7 @@ import (
// Unix domain socket struct // Unix domain socket struct
type Unix struct { type Unix struct {
dialer proxy.Dialer dialer proxy.Dialer
proxy proxy.Proxy
addr string addr string
server proxy.Server server proxy.Server
@ -25,28 +26,29 @@ func init() {
} }
// NewUnix returns unix fomain socket proxy // NewUnix returns unix fomain socket proxy
func NewUnix(s string, dialer proxy.Dialer) (*Unix, error) { func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse url err: %s", err) log.F("parse url err: %s", err)
return nil, err return nil, err
} }
p := &Unix{ unix := &Unix{
dialer: dialer, dialer: d,
proxy: p,
addr: u.Path, addr: u.Path,
} }
return p, nil return unix, nil
} }
// NewUnixDialer returns a unix domain socket dialer // NewUnixDialer returns a unix domain socket dialer
func NewUnixDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewUnixDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewUnix(s, dialer) return NewUnix(s, d, nil)
} }
// NewUnixServer returns a unix domain socket server // NewUnixServer returns a unix domain socket server
func NewUnixServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewUnixServer(s string, p proxy.Proxy) (proxy.Server, error) {
transport := strings.Split(s, ",") transport := strings.Split(s, ",")
// prepare transport listener // prepare transport listener
@ -55,17 +57,17 @@ func NewUnixServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return nil, errors.New("[unix] malformd listener:" + s) return nil, errors.New("[unix] malformd listener:" + s)
} }
p, err := NewUnix(transport[0], dialer) unix, err := NewUnix(transport[0], nil, p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.server, err = proxy.ServerFromURL(transport[1], dialer) unix.server, err = proxy.ServerFromURL(transport[1], p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return p, nil return unix, nil
} }
// ListenAndServe serves requests // ListenAndServe serves requests
@ -109,18 +111,10 @@ func (s *Unix) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer
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, string, error) { func (s *Unix) Dial(network, addr string) (net.Conn, 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) return net.Dial("unix", s.addr)
if err != nil {
return nil, "", err
}
return rc, "", err
} }
// DialUDP connects to the given address via the proxy // DialUDP connects to the given address via the proxy

View File

@ -14,7 +14,7 @@ import (
// UoTTun is a base udp over tcp tunnel struct. // UoTTun is a base udp over tcp tunnel struct.
type UoTTun struct { type UoTTun struct {
dialer proxy.Dialer proxy proxy.Proxy
addr string addr string
raddr string raddr string
@ -25,7 +25,7 @@ func init() {
} }
// NewUoTTun returns a UoTTun proxy. // NewUoTTun returns a UoTTun proxy.
func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) { func NewUoTTun(s string, p proxy.Proxy) (*UoTTun, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse err: %s", err) log.F("parse err: %s", err)
@ -35,18 +35,18 @@ func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) {
addr := u.Host addr := u.Host
d := strings.Split(addr, "=") d := strings.Split(addr, "=")
p := &UoTTun{ ut := &UoTTun{
dialer: dialer, proxy: p,
addr: d[0], addr: d[0],
raddr: d[1], raddr: d[1],
} }
return p, nil return ut, nil
} }
// NewUoTTunServer returns a uot tunnel server. // NewUoTTunServer returns a uot tunnel server.
func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewUoTTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewUoTTun(s, dialer) return NewUoTTun(s, p)
} }
// ListenAndServe listen and serve on tcp. // ListenAndServe listen and serve on tcp.
@ -69,7 +69,7 @@ func (s *UoTTun) ListenAndServe() {
continue continue
} }
rc, p, err := s.dialer.Dial("uot", s.raddr) rc, p, err := s.proxy.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

View File

@ -27,7 +27,7 @@ func init() {
} }
// NewVMess returns a vmess proxy. // NewVMess returns a vmess proxy.
func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) { func NewVMess(s string, d proxy.Dialer) (*VMess, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse url err: %s", err) log.F("parse url err: %s", err)
@ -62,7 +62,7 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) {
} }
p := &VMess{ p := &VMess{
dialer: dialer, dialer: d,
addr: addr, addr: addr,
uuid: uuid, uuid: uuid,
alterID: int(alterID), alterID: int(alterID),
@ -86,18 +86,14 @@ func (s *VMess) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer
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, string, error) { func (s *VMess) Dial(network, addr string) (net.Conn, error) {
rc, p, err := s.dialer.Dial("tcp", s.addr) rc, err := s.dialer.Dial("tcp", s.addr)
if err != nil { if err != nil {
return nil, p, err return nil, err
} }
cc, e := s.client.NewConn(rc, addr) return 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

@ -24,7 +24,7 @@ func init() {
} }
// NewWS returns a websocket proxy. // NewWS returns a websocket proxy.
func NewWS(s string, dialer proxy.Dialer) (*WS, error) { func NewWS(s string, d proxy.Dialer) (*WS, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
log.F("parse url err: %s", err) log.F("parse url err: %s", err)
@ -35,7 +35,7 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
// TODO: // TODO:
if addr == "" { if addr == "" {
addr = dialer.Addr() addr = d.Addr()
} }
colonPos := strings.LastIndex(addr, ":") colonPos := strings.LastIndex(addr, ":")
@ -51,7 +51,7 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
} }
p := &WS{ p := &WS{
dialer: dialer, dialer: d,
addr: addr, addr: addr,
client: client, client: client,
} }
@ -60,8 +60,8 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
} }
// NewWSDialer returns a ws proxy dialer. // NewWSDialer returns a ws proxy dialer.
func NewWSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewWSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewWS(s, dialer) return NewWS(s, d)
} }
// Addr returns forwarder's address. // Addr returns forwarder's address.
@ -72,18 +72,14 @@ func (s *WS) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer.
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, string, error) { func (s *WS) Dial(network, addr string) (net.Conn, error) {
rc, p, err := s.dialer.Dial("tcp", s.addr) rc, err := s.dialer.Dial("tcp", s.addr)
if err != nil { if err != nil {
return nil, p, err return nil, err
} }
cc, e := s.client.NewConn(rc, addr) return 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

@ -10,23 +10,23 @@ import (
"github.com/nadoo/glider/strategy" "github.com/nadoo/glider/strategy"
) )
// Dialer struct // Proxy struct
type Dialer struct { type Proxy struct {
gDialer *strategy.Dialer proxy *strategy.Proxy
dialers []*strategy.Dialer proxies []*strategy.Proxy
domainMap sync.Map domainMap sync.Map
ipMap sync.Map ipMap sync.Map
cidrMap sync.Map cidrMap sync.Map
} }
// NewDialer returns a new rule dialer // NewProxy returns a new rule proxy
func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer { func NewProxy(rules []*Config, proxy *strategy.Proxy) *Proxy {
rd := &Dialer{gDialer: gDialer} rd := &Proxy{proxy: proxy}
for _, r := range rules { for _, r := range rules {
sd := strategy.NewDialer(r.Forward, &r.StrategyConfig) sd := strategy.NewProxy(r.Forward, &r.StrategyConfig)
rd.dialers = append(rd.dialers, sd) rd.proxies = append(rd.proxies, sd)
for _, domain := range r.Domain { for _, domain := range r.Domain {
rd.domainMap.Store(strings.ToLower(domain), sd) rd.domainMap.Store(strings.ToLower(domain), sd)
@ -46,31 +46,38 @@ func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer {
return rd return rd
} }
// Addr returns RuleDialer's address, always be "RULES" // Dial dials to targer addr and return a conn
func (rd *Dialer) Addr() string { return "RULE DIALER, DEFAULT: " + rd.gDialer.Addr() } func (p *Proxy) Dial(network, addr string) (net.Conn, string, error) {
return p.nextProxy(addr).Dial(network, addr)
}
// NextDialer return next dialer according to rule // DialUDP connects to the given address via the proxy
func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer { func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
return p.nextProxy(addr).DialUDP(network, addr)
}
// nextProxy return next proxy according to rule
func (p *Proxy) nextProxy(dstAddr string) *strategy.Proxy {
host, _, err := net.SplitHostPort(dstAddr) host, _, err := net.SplitHostPort(dstAddr)
if err != nil { if err != nil {
// TODO: check here // TODO: check here
// logf("[rule] SplitHostPort ERROR: %s", err) // logf("[rule] SplitHostPort ERROR: %s", err)
return rd.gDialer return p.proxy
} }
// find ip // find ip
if ip := net.ParseIP(host); ip != nil { if ip := net.ParseIP(host); ip != nil {
// check ip // check ip
if dialer, ok := rd.ipMap.Load(ip.String()); ok { if proxy, ok := p.ipMap.Load(ip.String()); ok {
return dialer.(proxy.Dialer) return proxy.(*strategy.Proxy)
} }
var ret proxy.Dialer var ret *strategy.Proxy
// check cidr // check cidr
rd.cidrMap.Range(func(key, value interface{}) bool { p.cidrMap.Range(func(key, value interface{}) bool {
cidr := key.(*net.IPNet) cidr := key.(*net.IPNet)
if cidr.Contains(ip) { if cidr.Contains(ip) {
ret = value.(proxy.Dialer) ret = value.(*strategy.Proxy)
return false return false
} }
@ -89,26 +96,21 @@ func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer {
domain := strings.Join(domainParts[i:length], ".") domain := strings.Join(domainParts[i:length], ".")
// find in domainMap // find in domainMap
if dialer, ok := rd.domainMap.Load(domain); ok { if proxy, ok := p.domainMap.Load(domain); ok {
return dialer.(proxy.Dialer) return proxy.(*strategy.Proxy)
} }
} }
return rd.gDialer return p.proxy
} }
// Dial dials to targer addr and return a conn // NextDialer return next dialer according to rule
func (rd *Dialer) Dial(network, addr string) (net.Conn, string, error) { func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer {
return rd.NextDialer(addr).Dial(network, addr) return p.nextProxy(dstAddr).NextDialer(dstAddr)
}
// DialUDP connects to the given address via the proxy
func (rd *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
return rd.NextDialer(addr).DialUDP(network, addr)
} }
// AddDomainIP used to update ipMap rules according to domainMap rule // AddDomainIP used to update ipMap rules according to domainMap rule
func (rd *Dialer) AddDomainIP(domain, ip string) error { func (p *Proxy) AddDomainIP(domain, ip string) error {
if ip != "" { if ip != "" {
domainParts := strings.Split(domain, ".") domainParts := strings.Split(domain, ".")
length := len(domainParts) length := len(domainParts)
@ -116,8 +118,8 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error {
pDomain := strings.ToLower(strings.Join(domainParts[i:length], ".")) pDomain := strings.ToLower(strings.Join(domainParts[i:length], "."))
// find in domainMap // find in domainMap
if dialer, ok := rd.domainMap.Load(pDomain); ok { if dialer, ok := p.domainMap.Load(pDomain); ok {
rd.ipMap.Store(ip, dialer) p.ipMap.Store(ip, dialer)
log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, pDomain, domain, ip) log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, pDomain, domain, ip)
} }
} }
@ -126,10 +128,10 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error {
} }
// Check . // Check .
func (rd *Dialer) Check() { func (p *Proxy) Check() {
rd.gDialer.Check() p.proxy.Check()
for _, d := range rd.dialers { for _, d := range p.proxies {
d.Check() d.Check()
} }
} }

View File

@ -97,8 +97,8 @@ func (f *Forwarder) Addr() string {
} }
// Dial . // Dial .
func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) { func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
c, p, err = f.Dialer.Dial(network, addr) c, 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() {
@ -107,7 +107,7 @@ func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error)
} }
} }
return c, p, err return c, err
} }
// Failures returns the failuer count of forwarder // Failures returns the failuer count of forwarder

View File

@ -32,8 +32,8 @@ 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() }
func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Dialer is base dialer struct. // Proxy is base proxy struct.
type Dialer struct { type Proxy struct {
config *Config config *Config
fwdrs priSlice fwdrs priSlice
available []*Forwarder available []*Forwarder
@ -44,8 +44,8 @@ type Dialer struct {
nextForwarder func(addr string) *Forwarder nextForwarder func(addr string) *Forwarder
} }
// NewDialer returns a new strategy dialer. // NewProxy returns a new strategy proxy.
func NewDialer(s []string, c *Config) *Dialer { func NewProxy(s []string, c *Config) *Proxy {
var fwdrs []*Forwarder var fwdrs []*Forwarder
for _, chain := range s { for _, chain := range s {
fwdr, err := ForwarderFromURL(chain, c.IntFace) fwdr, err := ForwarderFromURL(chain, c.IntFace)
@ -62,12 +62,12 @@ func NewDialer(s []string, c *Config) *Dialer {
c.Strategy = "rr" c.Strategy = "rr"
} }
return newDialer(fwdrs, c) return newProxy(fwdrs, c)
} }
// newDialer returns a new rrDialer // newProxy returns a new rrProxy
func newDialer(fwdrs []*Forwarder, c *Config) *Dialer { func newProxy(fwdrs []*Forwarder, c *Config) *Proxy {
d := &Dialer{fwdrs: fwdrs, config: c} d := &Proxy{fwdrs: fwdrs, config: c}
sort.Sort(d.fwdrs) sort.Sort(d.fwdrs)
d.initAvailable() d.initAvailable()
@ -101,112 +101,103 @@ func newDialer(fwdrs []*Forwarder, c *Config) *Dialer {
return d return d
} }
// Addr returns forwarder's address.
func (d *Dialer) Addr() string {
if d.fwdrs.Len() == 1 {
return d.fwdrs[0].Addr()
}
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, string, error) { func (p *Proxy) Dial(network, addr string) (net.Conn, string, error) {
nd := d.NextDialer(addr) nd := p.NextDialer(addr)
c, _, err := nd.Dial(network, addr) c, err := nd.Dial(network, addr)
return c, nd.Addr(), err return c, nd.Addr(), err
} }
// DialUDP connects to the given address. // DialUDP connects to the given address.
func (d *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
return d.NextDialer(addr).DialUDP(network, addr) return p.NextDialer(addr).DialUDP(network, addr)
} }
// NextDialer returns the next dialer. // NextDialer returns the next dialer.
func (d *Dialer) NextDialer(dstAddr string) proxy.Dialer { func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer {
d.mu.RLock() p.mu.RLock()
defer d.mu.RUnlock() defer p.mu.RUnlock()
return d.nextForwarder(dstAddr) return p.nextForwarder(dstAddr)
} }
// Priority returns the active priority of dialer. // Priority returns the active priority of dialer.
func (d *Dialer) Priority() uint32 { return atomic.LoadUint32(&d.priority) } func (p *Proxy) Priority() uint32 { return atomic.LoadUint32(&p.priority) }
// SetPriority sets the active priority of daler. // SetPriority sets the active priority of daler.
func (d *Dialer) SetPriority(p uint32) { atomic.StoreUint32(&d.priority, p) } func (p *Proxy) SetPriority(pri uint32) { atomic.StoreUint32(&p.priority, pri) }
// initAvailable traverse d.fwdrs and init the available forwarder slice. // initAvailable traverse d.fwdrs and init the available forwarder slice.
func (d *Dialer) initAvailable() { func (p *Proxy) initAvailable() {
for _, f := range d.fwdrs { for _, f := range p.fwdrs {
if f.Enabled() { if f.Enabled() {
d.SetPriority(f.Priority()) p.SetPriority(f.Priority())
break break
} }
} }
d.available = nil p.available = nil
for _, f := range d.fwdrs { for _, f := range p.fwdrs {
if f.Enabled() && f.Priority() >= d.Priority() { if f.Enabled() && f.Priority() >= p.Priority() {
d.available = append(d.available, f) p.available = append(p.available, f)
} }
} }
if len(d.available) == 0 { if len(p.available) == 0 {
// no available forwarders, set priority to 0 to check all forwarders in check func // no available forwarders, set priority to 0 to check all forwarders in check func
d.SetPriority(0) p.SetPriority(0)
log.F("[strategy] no available forwarders, just use: %s, please check your settings or network", d.fwdrs[0].Addr()) log.F("[strategy] no available forwarders, just use: %s, please check your settings or network", p.fwdrs[0].Addr())
d.available = append(d.available, d.fwdrs[0]) p.available = append(p.available, p.fwdrs[0])
} }
} }
// onStatusChanged will be called when fwdr's status changed. // onStatusChanged will be called when fwdr's status changed.
func (d *Dialer) onStatusChanged(fwdr *Forwarder) { func (p *Proxy) onStatusChanged(fwdr *Forwarder) {
d.mu.Lock() p.mu.Lock()
defer d.mu.Unlock() defer p.mu.Unlock()
if fwdr.Enabled() { if fwdr.Enabled() {
log.F("[strategy] %s changed status from Disabled to Enabled ", fwdr.Addr()) log.F("[strategy] %s changed status from Disabled to Enabled ", fwdr.Addr())
if fwdr.Priority() == d.Priority() { if fwdr.Priority() == p.Priority() {
d.available = append(d.available, fwdr) p.available = append(p.available, fwdr)
} else if fwdr.Priority() > d.Priority() { } else if fwdr.Priority() > p.Priority() {
d.initAvailable() p.initAvailable()
} }
} else { } else {
log.F("[strategy] %s changed status from Enabled to Disabled", fwdr.Addr()) log.F("[strategy] %s changed status from Enabled to Disabled", fwdr.Addr())
for i, f := range d.available { for i, f := range p.available {
if f == fwdr { if f == fwdr {
d.available[i], d.available = d.available[len(d.available)-1], d.available[:len(d.available)-1] p.available[i], p.available = p.available[len(p.available)-1], p.available[:len(p.available)-1]
break break
} }
} }
} }
if len(d.available) == 0 { if len(p.available) == 0 {
d.initAvailable() p.initAvailable()
} }
} }
// Check implements the Checker interface. // Check implements the Checker interface.
func (d *Dialer) Check() { func (p *Proxy) Check() {
// no need to check when there's only 1 forwarder // no need to check when there's only 1 forwarder
if len(d.fwdrs) > 1 { if len(p.fwdrs) > 1 {
for i := 0; i < len(d.fwdrs); i++ { for i := 0; i < len(p.fwdrs); i++ {
go d.check(i) go p.check(i)
} }
} }
} }
func (d *Dialer) check(i int) { func (p *Proxy) check(i int) {
f := d.fwdrs[i] f := p.fwdrs[i]
retry := 1 retry := 1
buf := make([]byte, 4) buf := make([]byte, 4)
for { for {
time.Sleep(time.Duration(d.config.CheckInterval) * time.Second * time.Duration(retry>>1)) time.Sleep(time.Duration(p.config.CheckInterval) * time.Second * time.Duration(retry>>1))
// check all forwarders at least one time // check all forwarders at least one time
if retry > 1 && f.Priority() < d.Priority() { if retry > 1 && f.Priority() < p.Priority() {
continue continue
} }
@ -216,10 +207,10 @@ 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", p.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(), p.config.CheckWebSite, err)
continue continue
} }
@ -228,24 +219,24 @@ func (d *Dialer) check(i int) {
_, err = io.ReadFull(rc, buf) _, err = io.ReadFull(rc, buf)
if err != nil { if err != nil {
f.Disable() f.Disable()
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err) log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err)
} else if bytes.Equal([]byte("HTTP"), buf) { } else if bytes.Equal([]byte("HTTP"), buf) {
readTime := time.Since(startTime) readTime := time.Since(startTime)
f.SetLatency(int64(readTime)) f.SetLatency(int64(readTime))
if readTime > time.Duration(d.config.CheckTimeout)*time.Second { if readTime > time.Duration(p.config.CheckTimeout)*time.Second {
f.Disable() f.Disable()
log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime) log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime)
} else { } else {
retry = 2 retry = 2
f.Enable() f.Enable()
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime) log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime)
} }
} else { } else {
f.Disable() f.Disable()
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, buf) log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, buf)
} }
rc.Close() rc.Close()
@ -253,20 +244,20 @@ func (d *Dialer) check(i int) {
} }
// Round Robin // Round Robin
func (d *Dialer) scheduleRR(dstAddr string) *Forwarder { func (p *Proxy) scheduleRR(dstAddr string) *Forwarder {
return d.available[atomic.AddUint32(&d.index, 1)%uint32(len(d.available))] return p.available[atomic.AddUint32(&p.index, 1)%uint32(len(p.available))]
} }
// High Availability // High Availability
func (d *Dialer) scheduleHA(dstAddr string) *Forwarder { func (p *Proxy) scheduleHA(dstAddr string) *Forwarder {
return d.available[0] return p.available[0]
} }
// Latency based High Availability // Latency based High Availability
func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder { func (p *Proxy) scheduleLHA(dstAddr string) *Forwarder {
fwdr := d.available[0] fwdr := p.available[0]
lowest := fwdr.Latency() lowest := fwdr.Latency()
for _, f := range d.available { for _, f := range p.available {
if f.Latency() < lowest { if f.Latency() < lowest {
lowest = f.Latency() lowest = f.Latency()
fwdr = f fwdr = f
@ -276,8 +267,8 @@ func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder {
} }
// Destination Hashing // Destination Hashing
func (d *Dialer) scheduleDH(dstAddr string) *Forwarder { func (p *Proxy) 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 p.available[fnv1a.Sum32()%uint32(len(p.available))]
} }