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.
type Client struct {
dialer proxy.Dialer
proxy proxy.Proxy
cache *Cache
config *Config
upServers []string
@ -37,9 +37,9 @@ type Client struct {
}
// 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{
dialer: dialer,
proxy: proxy,
cache: NewCache(),
config: config,
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) {
// use tcp to connect upstream server default
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
// TODO: dialer.Addr() == "reject", tricky
@ -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

View File

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

12
main.go
View File

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

View File

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

View File

@ -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, p string, err error) {
func (d *Direct) Dial(network, addr string) (c net.Conn, 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, p string, err error) {
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) {
@ -107,9 +107,6 @@ func (d *Direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error)
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
func (d *Direct) IFaceIPs() (ips []net.IP) {
ipnets, err := d.iface.Addrs()

View File

@ -24,6 +24,7 @@ import (
// HTTP struct
type HTTP struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
user string
password string
@ -36,7 +37,7 @@ func init() {
}
// 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)
if err != nil {
log.F("parse err: %s", err)
@ -48,7 +49,8 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
pass, _ := u.User.Password()
h := &HTTP{
dialer: dialer,
dialer: d,
proxy: p,
addr: addr,
user: user,
password: pass,
@ -64,13 +66,13 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
}
// NewHTTPDialer returns a http proxy dialer
func NewHTTPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewHTTP(s, dialer)
func NewHTTPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewHTTP(s, d, nil)
}
// NewHTTPServer returns a http proxy server
func NewHTTPServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewHTTP(s, dialer)
func NewHTTPServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewHTTP(s, nil, p)
}
// ListenAndServe .
@ -142,7 +144,7 @@ func (s *HTTP) Serve(c net.Conn) {
tgt += ":80"
}
rc, p, err := s.dialer.Dial("tcp", tgt)
rc, p, err := s.proxy.Dial("tcp", tgt)
if err != nil {
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)
@ -200,7 +202,7 @@ func (s *HTTP) Serve(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 {
c.Write([]byte(proto))
c.Write([]byte(" 502 ERROR\r\n\r\n"))
@ -229,15 +231,12 @@ func (s *HTTP) Addr() string {
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
func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
rc, p, err := s.dialer.Dial(network, s.addr)
func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
rc, err := s.dialer.Dial(network, s.addr)
if err != nil {
log.F("[http] dial to %s error: %s", s.addr, err)
return nil, p, err
return nil, err
}
var buf bytes.Buffer
@ -254,7 +253,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
buf.Write([]byte("\r\n"))
_, err = rc.Write(buf.Bytes())
if err != nil {
return nil, p, err
return nil, err
}
c := conn.NewConn(rc)
@ -262,7 +261,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
_, code, _, ok := parseFirstLine(tpr)
if ok && code == "200" {
tpr.ReadMIMEHeader()
return c, p, err
return c, err
}
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)
}
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

View File

@ -18,6 +18,7 @@ import (
// KCP struct
type KCP struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
key string
@ -36,7 +37,7 @@ func init() {
}
// 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)
if err != nil {
log.F("[kcp] parse url err: %s", err)
@ -73,8 +74,9 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
return nil, err
}
p := &KCP{
dialer: dialer,
k := &KCP{
dialer: d,
proxy: p,
addr: addr,
key: key,
crypt: crypt,
@ -82,10 +84,10 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
parityShards: int(parityShards),
}
if p.crypt != "" {
pass := pbkdf2.Key([]byte(p.key), []byte("kcp-go"), 4096, 32, sha1.New)
if k.crypt != "" {
pass := pbkdf2.Key([]byte(k.key), []byte("kcp-go"), 4096, 32, sha1.New)
var block kcp.BlockCrypt
switch p.crypt {
switch k.crypt {
case "sm4":
block, _ = kcp.NewSM4BlockCrypt(pass[:16])
case "tea":
@ -113,22 +115,22 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
case "salsa20":
block, _ = kcp.NewSalsa20BlockCrypt(pass)
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
func NewKCPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewKCP(s, dialer)
func NewKCPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewKCP(s, d, nil)
}
// 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, ",")
// 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)
}
p, err := NewKCP(transport[0], dialer)
k, err := NewKCP(transport[0], nil, p)
if err != nil {
return nil, err
}
p.server, err = proxy.ServerFromURL(transport[1], dialer)
k.server, err = proxy.ServerFromURL(transport[1], p)
if err != nil {
return nil, err
}
return p, nil
return k, nil
}
// ListenAndServe .
@ -193,16 +195,13 @@ func (s *KCP) Serve(c net.Conn) {
// Addr returns forwarder's address
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
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
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
log.F("[kcp] dial to %s error: %s", s.addr, err)
return nil, err
}
// 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.SetWriteBuffer(4194304)
return c, "", err
return c, err
}
// DialUDP connects to the given address via the proxy

View File

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

View File

@ -28,7 +28,7 @@ func init() {
}
// 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)
if err != nil {
log.F("parse url err: %s", err)
@ -59,7 +59,7 @@ func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) {
}
p := &Obfs{
dialer: dialer,
dialer: d,
addr: addr,
obfsType: obfsType,
obfsHost: obfsHost,
@ -89,19 +89,16 @@ func NewObfsDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
// Addr returns forwarder's address
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
func (s *Obfs) Dial(network, addr string) (net.Conn, string, error) {
c, p, err := s.dialer.Dial("tcp", s.addr)
func (s *Obfs) Dial(network, addr string) (net.Conn, error) {
c, err := s.dialer.Dial("tcp", s.addr)
if err != nil {
log.F("[obfs] dial to %s error: %s", s.addr, err)
return nil, p, err
return nil, err
}
cc, e := s.obfsConn(c)
return cc, p, e
return cc, e
}
// 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
type RedirProxy struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
ipv6 bool
}
@ -36,7 +36,7 @@ func init() {
}
// 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)
if err != nil {
log.F("parse err: %s", err)
@ -45,7 +45,7 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
addr := u.Host
r := &RedirProxy{
dialer: dialer,
proxy: p,
addr: addr,
ipv6: ipv6,
}
@ -54,13 +54,13 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
}
// NewRedirServer returns a redir server.
func NewRedirServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewRedirProxy(s, dialer, false)
func NewRedirServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewRedirProxy(s, p, false)
}
// NewRedir6Server returns a redir server for ipv6.
func NewRedir6Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewRedirProxy(s, dialer, true)
func NewRedir6Server(s string, p proxy.Proxy) (proxy.Server, error) {
return NewRedirProxy(s, p, true)
}
// ListenAndServe .
@ -104,7 +104,7 @@ func (s *RedirProxy) Serve(c net.Conn) {
return
}
rc, p, err := s.dialer.Dial("tcp", tgt.String())
rc, p, err := s.proxy.Dial("tcp", tgt.String())
if err != nil {
log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
return

View File

@ -16,24 +16,21 @@ func init() {
}
// 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
}
// NewRejectDialer returns a reject proxy dialer.
func NewRejectDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewReject(s, dialer)
func NewRejectDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewReject(s, d)
}
// Addr returns forwarder's address.
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.
func (s *Reject) Dial(network, addr string) (net.Conn, string, error) {
return nil, "REJECT", errors.New("REJECT")
func (s *Reject) Dial(network, addr string) (net.Conn, error) {
return nil, errors.New("REJECT")
}
// 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
type ServerCreator func(s string, dialer Dialer) (Server, error)
type ServerCreator func(s string, proxy Proxy) (Server, error)
var (
serverMap = make(map[string]ServerCreator)
@ -32,8 +32,8 @@ func RegisterServer(name string, c ServerCreator) {
// 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
func ServerFromURL(s string, dialer Dialer) (Server, error) {
if dialer == nil {
func ServerFromURL(s string, p Proxy) (Server, error) {
if p == 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)]
if ok {
return c(s, dialer)
return c(s, p)
}
return nil, errors.New("unknown scheme '" + u.Scheme + "'")

View File

@ -30,9 +30,10 @@ import (
// Version is socks5 version number.
const Version = 5
// SOCKS5 is a base socks5 struct.
type SOCKS5 struct {
// Socks5 is a base socks5 struct.
type Socks5 struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
user string
password string
@ -43,9 +44,9 @@ func init() {
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)
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)
if err != nil {
log.F("parse err: %s", err)
@ -56,8 +57,9 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
user := u.User.Username()
pass, _ := u.User.Password()
h := &SOCKS5{
dialer: dialer,
h := &Socks5{
dialer: d,
proxy: p,
addr: addr,
user: user,
password: pass,
@ -67,23 +69,23 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
}
// NewSocks5Dialer returns a socks5 proxy dialer.
func NewSocks5Dialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewSOCKS5(s, dialer)
func NewSocks5Dialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSocks5(s, d, nil)
}
// NewSocks5Server returns a socks5 proxy server.
func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewSOCKS5(s, dialer)
func NewSocks5Server(s string, p proxy.Proxy) (proxy.Server, error) {
return NewSocks5(s, nil, p)
}
// ListenAndServe serves socks5 requests.
func (s *SOCKS5) ListenAndServe() {
func (s *Socks5) ListenAndServe() {
go s.ListenAndServeUDP()
s.ListenAndServeTCP()
}
// ListenAndServeTCP listen and serve on tcp port.
func (s *SOCKS5) ListenAndServeTCP() {
func (s *Socks5) ListenAndServeTCP() {
l, err := net.Listen("tcp", s.addr)
if err != nil {
log.F("[socks5] failed to listen on %s: %v", s.addr, err)
@ -104,7 +106,7 @@ func (s *SOCKS5) ListenAndServeTCP() {
}
// Serve serves a connection.
func (s *SOCKS5) Serve(c net.Conn) {
func (s *Socks5) Serve(c net.Conn) {
defer c.Close()
if c, ok := c.(*net.TCPConn); ok {
@ -131,7 +133,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
return
}
rc, p, err := s.dialer.Dial("tcp", tgt.String())
rc, p, err := s.proxy.Dial("tcp", tgt.String())
if err != nil {
log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
return
@ -150,7 +152,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
}
// ListenAndServeUDP serves udp requests.
func (s *SOCKS5) ListenAndServeUDP() {
func (s *Socks5) ListenAndServeUDP() {
lc, err := net.ListenPacket("udp", s.addr)
if err != nil {
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.
func (s *SOCKS5) Addr() string {
func (s *Socks5) Addr() string {
if s.addr == "" {
return s.dialer.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.
func (s *SOCKS5) Dial(network, addr string) (net.Conn, string, error) {
func (s *Socks5) Dial(network, addr string) (net.Conn, 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, p, err := s.dialer.Dial(network, s.addr)
c, err := s.dialer.Dial(network, s.addr)
if err != nil {
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 {
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.
func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
c, _, err := s.dialer.Dial("tcp", s.addr)
func (s *Socks5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
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
@ -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,
// and commands the server to extend that connection to target,
// 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)
if err != nil {
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.
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
buf := make([]byte, socks.MaxAddrLen)
// read VER, NMETHODS, METHODS

View File

@ -19,6 +19,7 @@ import (
// SS is a base ss struct.
type SS struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
core.Cipher
@ -30,7 +31,7 @@ func init() {
}
// 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)
if err != nil {
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)
}
p := &SS{
dialer: dialer,
ss := &SS{
dialer: d,
proxy: p,
addr: addr,
Cipher: ciph,
}
return p, nil
return ss, nil
}
// NewSSDialer returns a ss proxy dialer.
func NewSSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewSS(s, dialer)
func NewSSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSS(s, d, nil)
}
// NewSSServer returns a ss proxy server.
func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewSS(s, dialer)
func NewSSServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewSS(s, nil, p)
}
// ListenAndServe serves ss requests.
@ -108,7 +110,7 @@ func (s *SS) Serve(c net.Conn) {
return
}
dialer := s.dialer.NextDialer(tgt.String())
dialer := s.proxy.NextDialer(tgt.String())
// udp over tcp?
uot := socks.UoT(tgt[0])
@ -147,14 +149,14 @@ func (s *SS) Serve(c net.Conn) {
network = "udp"
}
rc, p, err := dialer.Dial(network, tgt.String())
rc, err := dialer.Dial(network, tgt.String())
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
}
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)
if err != nil {
@ -238,33 +240,30 @@ func (s *SS) Addr() string {
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.
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)
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, p, err := s.dialer.Dial("tcp", s.addr)
c, err := s.dialer.Dial("tcp", s.addr)
if err != nil {
log.F("[ss] dial to %s error: %s", s.addr, err)
return nil, p, err
return nil, err
}
c = s.StreamConn(c)
if _, err = c.Write(target); err != nil {
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
func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
func NewSSR(s string, d proxy.Dialer) (*SSR, error) {
u, err := url.Parse(s)
if err != nil {
log.F("parse err: %s", err)
@ -49,7 +49,7 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
pass, _ := u.User.Password()
p := &SSR{
dialer: dialer,
dialer: d,
addr: addr,
EncryptMethod: method,
EncryptPassword: pass,
@ -65,8 +65,8 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
}
// NewSSRDialer returns a ssr proxy dialer.
func NewSSRDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewSSR(s, dialer)
func NewSSRDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSSR(s, d)
}
// Addr returns forwarder's address
@ -77,30 +77,27 @@ func (s *SSR) Addr() string {
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.
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)
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, p, err := s.dialer.Dial("tcp", s.addr)
c, err := s.dialer.Dial("tcp", s.addr)
if err != nil {
log.F("[ssr] dial to %s error: %s", s.addr, err)
return nil, p, err
return nil, err
}
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
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
@ -109,7 +106,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
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{
@ -122,7 +119,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
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{
@ -145,10 +142,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
if _, err := ssrconn.Write(target); err != nil {
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.

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ import (
// Unix domain socket struct
type Unix struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
server proxy.Server
@ -25,28 +26,29 @@ func init() {
}
// 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)
if err != nil {
log.F("parse url err: %s", err)
return nil, err
}
p := &Unix{
dialer: dialer,
unix := &Unix{
dialer: d,
proxy: p,
addr: u.Path,
}
return p, nil
return unix, nil
}
// NewUnixDialer returns a unix domain socket dialer
func NewUnixDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewUnix(s, dialer)
func NewUnixDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewUnix(s, d, nil)
}
// 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, ",")
// 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)
}
p, err := NewUnix(transport[0], dialer)
unix, err := NewUnix(transport[0], nil, p)
if err != nil {
return nil, err
}
p.server, err = proxy.ServerFromURL(transport[1], dialer)
unix.server, err = proxy.ServerFromURL(transport[1], p)
if err != nil {
return nil, err
}
return p, nil
return unix, nil
}
// ListenAndServe serves requests
@ -109,18 +111,10 @@ func (s *Unix) Addr() string {
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.
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
rc, err := net.Dial("unix", s.addr)
if err != nil {
return nil, "", err
}
return rc, "", err
return net.Dial("unix", s.addr)
}
// 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.
type UoTTun struct {
dialer proxy.Dialer
proxy proxy.Proxy
addr string
raddr string
@ -25,7 +25,7 @@ func init() {
}
// 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)
if err != nil {
log.F("parse err: %s", err)
@ -35,18 +35,18 @@ func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) {
addr := u.Host
d := strings.Split(addr, "=")
p := &UoTTun{
dialer: dialer,
ut := &UoTTun{
proxy: p,
addr: d[0],
raddr: d[1],
}
return p, nil
return ut, nil
}
// NewUoTTunServer returns a uot tunnel server.
func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewUoTTun(s, dialer)
func NewUoTTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
return NewUoTTun(s, p)
}
// ListenAndServe listen and serve on tcp.
@ -69,7 +69,7 @@ func (s *UoTTun) ListenAndServe() {
continue
}
rc, p, err := s.dialer.Dial("uot", s.raddr)
rc, p, err := s.proxy.Dial("uot", s.raddr)
if err != nil {
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
continue

View File

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

View File

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

View File

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

View File

@ -97,8 +97,8 @@ func (f *Forwarder) Addr() string {
}
// Dial .
func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) {
c, p, err = f.Dialer.Dial(network, addr)
func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
c, err = f.Dialer.Dial(network, addr)
if err != nil {
f.IncFailures()
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

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