mirror of
https://github.com/nadoo/glider.git
synced 2025-04-18 18:22:09 +08:00
proxy: add a new interface proxy to distinguish client and server
This commit is contained in:
parent
6c8141e43b
commit
edcb21236a
@ -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
|
||||
|
@ -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
12
main.go
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -27,11 +27,11 @@ var httpMethods = [...][]byte{
|
||||
|
||||
// MixedProxy struct
|
||||
type MixedProxy struct {
|
||||
dialer proxy.Dialer
|
||||
addr string
|
||||
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,
|
||||
addr: u.Host,
|
||||
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 .
|
||||
|
@ -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
15
proxy/proxy.go
Normal 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
|
||||
}
|
@ -25,9 +25,9 @@ const (
|
||||
|
||||
// RedirProxy struct
|
||||
type RedirProxy struct {
|
||||
dialer proxy.Dialer
|
||||
addr string
|
||||
ipv6 bool
|
||||
proxy proxy.Proxy
|
||||
addr string
|
||||
ipv6 bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -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,22 +45,22 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
|
||||
|
||||
addr := u.Host
|
||||
r := &RedirProxy{
|
||||
dialer: dialer,
|
||||
addr: addr,
|
||||
ipv6: ipv6,
|
||||
proxy: p,
|
||||
addr: addr,
|
||||
ipv6: ipv6,
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -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.
|
||||
|
@ -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 + "'")
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
|
||||
// TCPTun struct
|
||||
type TCPTun struct {
|
||||
dialer proxy.Dialer
|
||||
addr string
|
||||
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,
|
||||
addr: d[0],
|
||||
raddr: d[1],
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -19,8 +19,8 @@ import (
|
||||
|
||||
// TProxy struct
|
||||
type TProxy struct {
|
||||
dialer proxy.Dialer
|
||||
addr string
|
||||
proxy proxy.Proxy
|
||||
addr string
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -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,
|
||||
addr: addr,
|
||||
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 .
|
||||
|
@ -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,
|
||||
addr: d[0],
|
||||
taddr: d[1],
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -14,8 +14,8 @@ import (
|
||||
|
||||
// UoTTun is a base udp over tcp tunnel struct.
|
||||
type UoTTun struct {
|
||||
dialer proxy.Dialer
|
||||
addr string
|
||||
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,
|
||||
addr: d[0],
|
||||
raddr: d[1],
|
||||
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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
74
rule/rule.go
74
rule/rule.go
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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))]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user