mirror of
https://github.com/nadoo/glider.git
synced 2025-04-21 19:52:07 +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.
|
// Client is a dns client struct.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
cache *Cache
|
cache *Cache
|
||||||
config *Config
|
config *Config
|
||||||
upServers []string
|
upServers []string
|
||||||
@ -37,9 +37,9 @@ type Client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new dns client.
|
// NewClient returns a new dns client.
|
||||||
func NewClient(dialer proxy.Dialer, config *Config) (*Client, error) {
|
func NewClient(proxy proxy.Proxy, config *Config) (*Client, error) {
|
||||||
c := &Client{
|
c := &Client{
|
||||||
dialer: dialer,
|
proxy: proxy,
|
||||||
cache: NewCache(),
|
cache: NewCache(),
|
||||||
config: config,
|
config: config,
|
||||||
upServers: config.Servers,
|
upServers: config.Servers,
|
||||||
@ -126,7 +126,7 @@ func (c *Client) Exchange(reqBytes []byte, clientAddr string, preferTCP bool) ([
|
|||||||
func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server, network string, respBytes []byte, err error) {
|
func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server, network string, respBytes []byte, err error) {
|
||||||
// use tcp to connect upstream server default
|
// use tcp to connect upstream server default
|
||||||
network = "tcp"
|
network = "tcp"
|
||||||
dialer := c.dialer.NextDialer(qname + ":53")
|
dialer := c.proxy.NextDialer(qname + ":53")
|
||||||
|
|
||||||
// if we are resolving the dialer's domain, then use Direct to avoid denpency loop
|
// if we are resolving the dialer's domain, then use Direct to avoid denpency loop
|
||||||
// TODO: dialer.Addr() == "reject", tricky
|
// TODO: dialer.Addr() == "reject", tricky
|
||||||
@ -143,7 +143,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server
|
|||||||
servers := c.GetServers(qname)
|
servers := c.GetServers(qname)
|
||||||
for _, server = range servers {
|
for _, server = range servers {
|
||||||
var rc net.Conn
|
var rc net.Conn
|
||||||
rc, _, err = dialer.Dial(network, server)
|
rc, err = dialer.Dial(network, server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[dns] failed to connect to server %v: %v", server, err)
|
log.F("[dns] failed to connect to server %v: %v", server, err)
|
||||||
continue
|
continue
|
||||||
|
@ -22,8 +22,8 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewServer returns a new dns server.
|
// NewServer returns a new dns server.
|
||||||
func NewServer(addr string, dialer proxy.Dialer, config *Config) (*Server, error) {
|
func NewServer(addr string, proxy proxy.Proxy, config *Config) (*Server, error) {
|
||||||
c, err := NewClient(dialer, config)
|
c, err := NewClient(proxy, config)
|
||||||
s := &Server{
|
s := &Server{
|
||||||
addr: addr,
|
addr: addr,
|
||||||
Client: c,
|
Client: c,
|
||||||
|
12
main.go
12
main.go
@ -42,15 +42,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// global rule dialer
|
// global rule proxy
|
||||||
dialer := rule.NewDialer(conf.rules, strategy.NewDialer(conf.Forward, &conf.StrategyConfig))
|
p := rule.NewProxy(conf.rules, strategy.NewProxy(conf.Forward, &conf.StrategyConfig))
|
||||||
|
|
||||||
// ipset manager
|
// ipset manager
|
||||||
ipsetM, _ := ipset.NewManager(conf.rules)
|
ipsetM, _ := ipset.NewManager(conf.rules)
|
||||||
|
|
||||||
// check and setup dns server
|
// check and setup dns server
|
||||||
if conf.DNS != "" {
|
if conf.DNS != "" {
|
||||||
d, err := dns.NewServer(conf.DNS, dialer, &conf.DNSConfig)
|
d, err := dns.NewServer(conf.DNS, p, &conf.DNSConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add a handler to update proxy rules when a domain resolved
|
// add a handler to update proxy rules when a domain resolved
|
||||||
d.AddHandler(dialer.AddDomainIP)
|
d.AddHandler(p.AddDomainIP)
|
||||||
if ipsetM != nil {
|
if ipsetM != nil {
|
||||||
d.AddHandler(ipsetM.AddDomainIP)
|
d.AddHandler(ipsetM.AddDomainIP)
|
||||||
}
|
}
|
||||||
@ -74,11 +74,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable checkers
|
// enable checkers
|
||||||
dialer.Check()
|
p.Check()
|
||||||
|
|
||||||
// Proxy Servers
|
// Proxy Servers
|
||||||
for _, listen := range conf.Listen {
|
for _, listen := range conf.Listen {
|
||||||
local, err := proxy.ServerFromURL(listen, dialer)
|
local, err := proxy.ServerFromURL(listen, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -9,19 +9,16 @@ import (
|
|||||||
"github.com/nadoo/glider/common/log"
|
"github.com/nadoo/glider/common/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dialer means to establish a connection and relay it.
|
// Dialer is used to create connection.
|
||||||
type Dialer interface {
|
type Dialer interface {
|
||||||
// Addr()
|
// Addr is the dialer's addr
|
||||||
Addr() string
|
Addr() string
|
||||||
|
|
||||||
// Dial connects to the given address via the proxy.
|
// Dial connects to the given address
|
||||||
Dial(network, addr string) (c net.Conn, proxy string, err error)
|
Dial(network, addr string) (c net.Conn, err error)
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address
|
||||||
DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error)
|
DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error)
|
||||||
|
|
||||||
// Get the dialer by dstAddr
|
|
||||||
NextDialer(dstAddr string) Dialer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialerCreator is a function to create dialers.
|
// DialerCreator is a function to create dialers.
|
||||||
@ -31,7 +28,7 @@ var (
|
|||||||
dialerMap = make(map[string]DialerCreator)
|
dialerMap = make(map[string]DialerCreator)
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterDialer is used to register a dialer
|
// RegisterDialer is used to register a dialer.
|
||||||
func RegisterDialer(name string, c DialerCreator) {
|
func RegisterDialer(name string, c DialerCreator) {
|
||||||
dialerMap[name] = c
|
dialerMap[name] = c
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func NewDirect(intface string) (*Direct, error) {
|
|||||||
func (d *Direct) Addr() string { return "DIRECT" }
|
func (d *Direct) Addr() string { return "DIRECT" }
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net
|
// Dial connects to the address addr on the network net
|
||||||
func (d *Direct) Dial(network, addr string) (c net.Conn, p string, err error) {
|
func (d *Direct) Dial(network, addr string) (c net.Conn, err error) {
|
||||||
if d.iface == nil || d.ip != nil {
|
if d.iface == nil || d.ip != nil {
|
||||||
c, err = dial(network, addr, d.ip)
|
c, err = dial(network, addr, d.ip)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -60,7 +60,7 @@ func (d *Direct) Dial(network, addr string) (c net.Conn, p string, err error) {
|
|||||||
err = errors.New("dial failed, maybe the interface link is down, please check it")
|
err = errors.New("dial failed, maybe the interface link is down, please check it")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, "DIRECT", err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func dial(network, addr string, localIP net.IP) (net.Conn, error) {
|
func dial(network, addr string, localIP net.IP) (net.Conn, error) {
|
||||||
@ -107,9 +107,6 @@ func (d *Direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error)
|
|||||||
return pc, uAddr, err
|
return pc, uAddr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (d *Direct) NextDialer(dstAddr string) Dialer { return d }
|
|
||||||
|
|
||||||
// IFaceIPs returns ip addresses according to the specified interface
|
// IFaceIPs returns ip addresses according to the specified interface
|
||||||
func (d *Direct) IFaceIPs() (ips []net.IP) {
|
func (d *Direct) IFaceIPs() (ips []net.IP) {
|
||||||
ipnets, err := d.iface.Addrs()
|
ipnets, err := d.iface.Addrs()
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
// HTTP struct
|
// HTTP struct
|
||||||
type HTTP struct {
|
type HTTP struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
user string
|
user string
|
||||||
password string
|
password string
|
||||||
@ -36,7 +37,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTP returns a http proxy
|
// NewHTTP returns a http proxy
|
||||||
func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
|
func NewHTTP(s string, d proxy.Dialer, p proxy.Proxy) (*HTTP, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -48,7 +49,8 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
|
|||||||
pass, _ := u.User.Password()
|
pass, _ := u.User.Password()
|
||||||
|
|
||||||
h := &HTTP{
|
h := &HTTP{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
|
proxy: p,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
user: user,
|
user: user,
|
||||||
password: pass,
|
password: pass,
|
||||||
@ -64,13 +66,13 @@ func NewHTTP(s string, dialer proxy.Dialer) (*HTTP, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPDialer returns a http proxy dialer
|
// NewHTTPDialer returns a http proxy dialer
|
||||||
func NewHTTPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewHTTPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewHTTP(s, dialer)
|
return NewHTTP(s, d, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPServer returns a http proxy server
|
// NewHTTPServer returns a http proxy server
|
||||||
func NewHTTPServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewHTTPServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewHTTP(s, dialer)
|
return NewHTTP(s, nil, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
@ -142,7 +144,7 @@ func (s *HTTP) Serve(c net.Conn) {
|
|||||||
tgt += ":80"
|
tgt += ":80"
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, p, err := s.dialer.Dial("tcp", tgt)
|
rc, p, err := s.proxy.Dial("tcp", tgt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto)
|
fmt.Fprintf(c, "%s 502 ERROR\r\n\r\n", proto)
|
||||||
log.F("[http] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
log.F("[http] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
@ -200,7 +202,7 @@ func (s *HTTP) Serve(c net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) {
|
func (s *HTTP) servHTTPS(method, requestURI, proto string, c net.Conn) {
|
||||||
rc, p, err := s.dialer.Dial("tcp", requestURI)
|
rc, p, err := s.proxy.Dial("tcp", requestURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Write([]byte(proto))
|
c.Write([]byte(proto))
|
||||||
c.Write([]byte(" 502 ERROR\r\n\r\n"))
|
c.Write([]byte(" 502 ERROR\r\n\r\n"))
|
||||||
@ -229,15 +231,12 @@ func (s *HTTP) Addr() string {
|
|||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *HTTP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *HTTP) Dial(network, addr string) (net.Conn, error) {
|
||||||
rc, p, err := s.dialer.Dial(network, s.addr)
|
rc, err := s.dialer.Dial(network, s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[http] dial to %s error: %s", s.addr, err)
|
log.F("[http] dial to %s error: %s", s.addr, err)
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@ -254,7 +253,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
buf.Write([]byte("\r\n"))
|
buf.Write([]byte("\r\n"))
|
||||||
_, err = rc.Write(buf.Bytes())
|
_, err = rc.Write(buf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := conn.NewConn(rc)
|
c := conn.NewConn(rc)
|
||||||
@ -262,7 +261,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
_, code, _, ok := parseFirstLine(tpr)
|
_, code, _, ok := parseFirstLine(tpr)
|
||||||
if ok && code == "200" {
|
if ok && code == "200" {
|
||||||
tpr.ReadMIMEHeader()
|
tpr.ReadMIMEHeader()
|
||||||
return c, p, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if code == "407" {
|
if code == "407" {
|
||||||
@ -271,7 +270,7 @@ func (s *HTTP) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr)
|
log.F("[http] 'CONNECT' method not allowed by proxy %s", s.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, p, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code)
|
return nil, errors.New("[http] can not connect remote address: " + addr + ". error code: " + code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
// KCP struct
|
// KCP struct
|
||||||
type KCP struct {
|
type KCP struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
key string
|
key string
|
||||||
@ -36,7 +37,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewKCP returns a kcp proxy struct
|
// NewKCP returns a kcp proxy struct
|
||||||
func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
|
func NewKCP(s string, d proxy.Dialer, p proxy.Proxy) (*KCP, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[kcp] parse url err: %s", err)
|
log.F("[kcp] parse url err: %s", err)
|
||||||
@ -73,8 +74,9 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &KCP{
|
k := &KCP{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
|
proxy: p,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
key: key,
|
key: key,
|
||||||
crypt: crypt,
|
crypt: crypt,
|
||||||
@ -82,10 +84,10 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
|
|||||||
parityShards: int(parityShards),
|
parityShards: int(parityShards),
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.crypt != "" {
|
if k.crypt != "" {
|
||||||
pass := pbkdf2.Key([]byte(p.key), []byte("kcp-go"), 4096, 32, sha1.New)
|
pass := pbkdf2.Key([]byte(k.key), []byte("kcp-go"), 4096, 32, sha1.New)
|
||||||
var block kcp.BlockCrypt
|
var block kcp.BlockCrypt
|
||||||
switch p.crypt {
|
switch k.crypt {
|
||||||
case "sm4":
|
case "sm4":
|
||||||
block, _ = kcp.NewSM4BlockCrypt(pass[:16])
|
block, _ = kcp.NewSM4BlockCrypt(pass[:16])
|
||||||
case "tea":
|
case "tea":
|
||||||
@ -113,22 +115,22 @@ func NewKCP(s string, dialer proxy.Dialer) (*KCP, error) {
|
|||||||
case "salsa20":
|
case "salsa20":
|
||||||
block, _ = kcp.NewSalsa20BlockCrypt(pass)
|
block, _ = kcp.NewSalsa20BlockCrypt(pass)
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("[kcp] unknown crypt type '" + p.crypt + "'")
|
return nil, errors.New("[kcp] unknown crypt type '" + k.crypt + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.block = block
|
k.block = block
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return k, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKCPDialer returns a kcp proxy dialer
|
// NewKCPDialer returns a kcp proxy dialer
|
||||||
func NewKCPDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewKCPDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewKCP(s, dialer)
|
return NewKCP(s, d, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKCPServer returns a kcp proxy server
|
// NewKCPServer returns a kcp proxy server
|
||||||
func NewKCPServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewKCPServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
transport := strings.Split(s, ",")
|
transport := strings.Split(s, ",")
|
||||||
|
|
||||||
// prepare transport listener
|
// prepare transport listener
|
||||||
@ -137,17 +139,17 @@ func NewKCPServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
|||||||
return nil, errors.New("[kcp] malformd listener:" + s)
|
return nil, errors.New("[kcp] malformd listener:" + s)
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := NewKCP(transport[0], dialer)
|
k, err := NewKCP(transport[0], nil, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.server, err = proxy.ServerFromURL(transport[1], dialer)
|
k.server, err = proxy.ServerFromURL(transport[1], p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return k, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
@ -193,16 +195,13 @@ func (s *KCP) Serve(c net.Conn) {
|
|||||||
// Addr returns forwarder's address
|
// Addr returns forwarder's address
|
||||||
func (s *KCP) Addr() string { return s.addr }
|
func (s *KCP) Addr() string { return s.addr }
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *KCP) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *KCP) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *KCP) Dial(network, addr string) (net.Conn, error) {
|
||||||
// NOTE: kcp uses udp, we should dial remote server directly here
|
// NOTE: kcp uses udp, we should dial remote server directly here
|
||||||
c, err := kcp.DialWithOptions(s.addr, s.block, s.dataShards, s.parityShards)
|
c, err := kcp.DialWithOptions(s.addr, s.block, s.dataShards, s.parityShards)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tls] dial to %s error: %s", s.addr, err)
|
log.F("[kcp] dial to %s error: %s", s.addr, err)
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change them to customizable later?
|
// TODO: change them to customizable later?
|
||||||
@ -217,7 +216,7 @@ func (s *KCP) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
c.SetReadBuffer(4194304)
|
c.SetReadBuffer(4194304)
|
||||||
c.SetWriteBuffer(4194304)
|
c.SetWriteBuffer(4194304)
|
||||||
|
|
||||||
return c, "", err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -27,11 +27,11 @@ var httpMethods = [...][]byte{
|
|||||||
|
|
||||||
// MixedProxy struct
|
// MixedProxy struct
|
||||||
type MixedProxy struct {
|
type MixedProxy struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
http *http.HTTP
|
http *http.HTTP
|
||||||
socks5 *socks5.SOCKS5
|
socks5 *socks5.Socks5
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -39,27 +39,27 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMixedProxy returns a mixed proxy
|
// NewMixedProxy returns a mixed proxy
|
||||||
func NewMixedProxy(s string, dialer proxy.Dialer) (*MixedProxy, error) {
|
func NewMixedProxy(s string, p proxy.Proxy) (*MixedProxy, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &MixedProxy{
|
m := &MixedProxy{
|
||||||
dialer: dialer,
|
proxy: p,
|
||||||
addr: u.Host,
|
addr: u.Host,
|
||||||
}
|
}
|
||||||
|
|
||||||
p.http, _ = http.NewHTTP(s, dialer)
|
m.http, _ = http.NewHTTP(s, nil, p)
|
||||||
p.socks5, _ = socks5.NewSOCKS5(s, dialer)
|
m.socks5, _ = socks5.NewSocks5(s, nil, p)
|
||||||
|
|
||||||
return p, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMixedProxyServer returns a mixed proxy server
|
// NewMixedProxyServer returns a mixed proxy server
|
||||||
func NewMixedProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewMixedProxyServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewMixedProxy(s, dialer)
|
return NewMixedProxy(s, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
|
@ -28,7 +28,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewObfs returns a proxy struct
|
// NewObfs returns a proxy struct
|
||||||
func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) {
|
func NewObfs(s string, d proxy.Dialer) (*Obfs, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse url err: %s", err)
|
log.F("parse url err: %s", err)
|
||||||
@ -59,7 +59,7 @@ func NewObfs(s string, dialer proxy.Dialer) (*Obfs, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := &Obfs{
|
p := &Obfs{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
obfsType: obfsType,
|
obfsType: obfsType,
|
||||||
obfsHost: obfsHost,
|
obfsHost: obfsHost,
|
||||||
@ -89,19 +89,16 @@ func NewObfsDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
|||||||
// Addr returns forwarder's address
|
// Addr returns forwarder's address
|
||||||
func (s *Obfs) Addr() string { return s.addr }
|
func (s *Obfs) Addr() string { return s.addr }
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *Obfs) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *Obfs) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *Obfs) Dial(network, addr string) (net.Conn, error) {
|
||||||
c, p, err := s.dialer.Dial("tcp", s.addr)
|
c, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[obfs] dial to %s error: %s", s.addr, err)
|
log.F("[obfs] dial to %s error: %s", s.addr, err)
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, e := s.obfsConn(c)
|
cc, e := s.obfsConn(c)
|
||||||
return cc, p, e
|
return cc, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
15
proxy/proxy.go
Normal file
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,7 +25,7 @@ const (
|
|||||||
|
|
||||||
// RedirProxy struct
|
// RedirProxy struct
|
||||||
type RedirProxy struct {
|
type RedirProxy struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
ipv6 bool
|
ipv6 bool
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewRedirProxy returns a redirect proxy.
|
// NewRedirProxy returns a redirect proxy.
|
||||||
func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error) {
|
func NewRedirProxy(s string, p proxy.Proxy, ipv6 bool) (*RedirProxy, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -45,7 +45,7 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
|
|||||||
|
|
||||||
addr := u.Host
|
addr := u.Host
|
||||||
r := &RedirProxy{
|
r := &RedirProxy{
|
||||||
dialer: dialer,
|
proxy: p,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
ipv6: ipv6,
|
ipv6: ipv6,
|
||||||
}
|
}
|
||||||
@ -54,13 +54,13 @@ func NewRedirProxy(s string, dialer proxy.Dialer, ipv6 bool) (*RedirProxy, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewRedirServer returns a redir server.
|
// NewRedirServer returns a redir server.
|
||||||
func NewRedirServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewRedirServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewRedirProxy(s, dialer, false)
|
return NewRedirProxy(s, p, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRedir6Server returns a redir server for ipv6.
|
// NewRedir6Server returns a redir server for ipv6.
|
||||||
func NewRedir6Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewRedir6Server(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewRedirProxy(s, dialer, true)
|
return NewRedirProxy(s, p, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
@ -104,7 +104,7 @@ func (s *RedirProxy) Serve(c net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, p, err := s.dialer.Dial("tcp", tgt.String())
|
rc, p, err := s.proxy.Dial("tcp", tgt.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
log.F("[redir] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
return
|
return
|
||||||
|
@ -16,24 +16,21 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewReject returns a reject proxy, reject://
|
// NewReject returns a reject proxy, reject://
|
||||||
func NewReject(s string, dialer proxy.Dialer) (*Reject, error) {
|
func NewReject(s string, d proxy.Dialer) (*Reject, error) {
|
||||||
return &Reject{}, nil
|
return &Reject{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRejectDialer returns a reject proxy dialer.
|
// NewRejectDialer returns a reject proxy dialer.
|
||||||
func NewRejectDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewRejectDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewReject(s, dialer)
|
return NewReject(s, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addr returns forwarder's address.
|
// Addr returns forwarder's address.
|
||||||
func (s *Reject) Addr() string { return "REJECT" }
|
func (s *Reject) Addr() string { return "REJECT" }
|
||||||
|
|
||||||
// NextDialer returns the next dialer.
|
|
||||||
func (s *Reject) NextDialer(dstAddr string) proxy.Dialer { return s }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *Reject) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *Reject) Dial(network, addr string) (net.Conn, error) {
|
||||||
return nil, "REJECT", errors.New("REJECT")
|
return nil, errors.New("REJECT")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
@ -19,7 +19,7 @@ type Server interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ServerCreator is a function to create proxy servers
|
// ServerCreator is a function to create proxy servers
|
||||||
type ServerCreator func(s string, dialer Dialer) (Server, error)
|
type ServerCreator func(s string, proxy Proxy) (Server, error)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
serverMap = make(map[string]ServerCreator)
|
serverMap = make(map[string]ServerCreator)
|
||||||
@ -32,8 +32,8 @@ func RegisterServer(name string, c ServerCreator) {
|
|||||||
|
|
||||||
// ServerFromURL calls the registered creator to create proxy servers
|
// ServerFromURL calls the registered creator to create proxy servers
|
||||||
// dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function
|
// dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function
|
||||||
func ServerFromURL(s string, dialer Dialer) (Server, error) {
|
func ServerFromURL(s string, p Proxy) (Server, error) {
|
||||||
if dialer == nil {
|
if p == nil {
|
||||||
return nil, errors.New("ServerFromURL: dialer cannot be nil")
|
return nil, errors.New("ServerFromURL: dialer cannot be nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func ServerFromURL(s string, dialer Dialer) (Server, error) {
|
|||||||
|
|
||||||
c, ok := serverMap[strings.ToLower(u.Scheme)]
|
c, ok := serverMap[strings.ToLower(u.Scheme)]
|
||||||
if ok {
|
if ok {
|
||||||
return c(s, dialer)
|
return c(s, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unknown scheme '" + u.Scheme + "'")
|
return nil, errors.New("unknown scheme '" + u.Scheme + "'")
|
||||||
|
@ -30,9 +30,10 @@ import (
|
|||||||
// Version is socks5 version number.
|
// Version is socks5 version number.
|
||||||
const Version = 5
|
const Version = 5
|
||||||
|
|
||||||
// SOCKS5 is a base socks5 struct.
|
// Socks5 is a base socks5 struct.
|
||||||
type SOCKS5 struct {
|
type Socks5 struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
user string
|
user string
|
||||||
password string
|
password string
|
||||||
@ -43,9 +44,9 @@ func init() {
|
|||||||
proxy.RegisterServer("socks5", NewSocks5Server)
|
proxy.RegisterServer("socks5", NewSocks5Server)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSOCKS5 returns a Proxy that makes SOCKS v5 connections to the given address
|
// NewSocks5 returns a Proxy that makes SOCKS v5 connections to the given address
|
||||||
// with an optional username and password. (RFC 1928)
|
// with an optional username and password. (RFC 1928)
|
||||||
func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
|
func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -56,8 +57,9 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
|
|||||||
user := u.User.Username()
|
user := u.User.Username()
|
||||||
pass, _ := u.User.Password()
|
pass, _ := u.User.Password()
|
||||||
|
|
||||||
h := &SOCKS5{
|
h := &Socks5{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
|
proxy: p,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
user: user,
|
user: user,
|
||||||
password: pass,
|
password: pass,
|
||||||
@ -67,23 +69,23 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSocks5Dialer returns a socks5 proxy dialer.
|
// NewSocks5Dialer returns a socks5 proxy dialer.
|
||||||
func NewSocks5Dialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewSocks5Dialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewSOCKS5(s, dialer)
|
return NewSocks5(s, d, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSocks5Server returns a socks5 proxy server.
|
// NewSocks5Server returns a socks5 proxy server.
|
||||||
func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewSocks5Server(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewSOCKS5(s, dialer)
|
return NewSocks5(s, nil, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe serves socks5 requests.
|
// ListenAndServe serves socks5 requests.
|
||||||
func (s *SOCKS5) ListenAndServe() {
|
func (s *Socks5) ListenAndServe() {
|
||||||
go s.ListenAndServeUDP()
|
go s.ListenAndServeUDP()
|
||||||
s.ListenAndServeTCP()
|
s.ListenAndServeTCP()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServeTCP listen and serve on tcp port.
|
// ListenAndServeTCP listen and serve on tcp port.
|
||||||
func (s *SOCKS5) ListenAndServeTCP() {
|
func (s *Socks5) ListenAndServeTCP() {
|
||||||
l, err := net.Listen("tcp", s.addr)
|
l, err := net.Listen("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5] failed to listen on %s: %v", s.addr, err)
|
log.F("[socks5] failed to listen on %s: %v", s.addr, err)
|
||||||
@ -104,7 +106,7 @@ func (s *SOCKS5) ListenAndServeTCP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serve serves a connection.
|
// Serve serves a connection.
|
||||||
func (s *SOCKS5) Serve(c net.Conn) {
|
func (s *Socks5) Serve(c net.Conn) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
if c, ok := c.(*net.TCPConn); ok {
|
if c, ok := c.(*net.TCPConn); ok {
|
||||||
@ -131,7 +133,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, p, err := s.dialer.Dial("tcp", tgt.String())
|
rc, p, err := s.proxy.Dial("tcp", tgt.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
log.F("[socks5] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
||||||
return
|
return
|
||||||
@ -150,7 +152,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServeUDP serves udp requests.
|
// ListenAndServeUDP serves udp requests.
|
||||||
func (s *SOCKS5) ListenAndServeUDP() {
|
func (s *Socks5) ListenAndServeUDP() {
|
||||||
lc, err := net.ListenPacket("udp", s.addr)
|
lc, err := net.ListenPacket("udp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5-udp] failed to listen on %s: %v", s.addr, err)
|
log.F("[socks5-udp] failed to listen on %s: %v", s.addr, err)
|
||||||
@ -213,41 +215,38 @@ func (s *SOCKS5) ListenAndServeUDP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Addr returns forwarder's address.
|
// Addr returns forwarder's address.
|
||||||
func (s *SOCKS5) Addr() string {
|
func (s *Socks5) Addr() string {
|
||||||
if s.addr == "" {
|
if s.addr == "" {
|
||||||
return s.dialer.Addr()
|
return s.dialer.Addr()
|
||||||
}
|
}
|
||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer.
|
|
||||||
func (s *SOCKS5) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the SOCKS5 proxy.
|
// Dial connects to the address addr on the network net via the SOCKS5 proxy.
|
||||||
func (s *SOCKS5) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *Socks5) Dial(network, addr string) (net.Conn, error) {
|
||||||
switch network {
|
switch network {
|
||||||
case "tcp", "tcp6", "tcp4":
|
case "tcp", "tcp6", "tcp4":
|
||||||
default:
|
default:
|
||||||
return nil, "", errors.New("[socks5]: no support for connection type " + network)
|
return nil, errors.New("[socks5]: no support for connection type " + network)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, p, err := s.dialer.Dial(network, s.addr)
|
c, err := s.dialer.Dial(network, s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5]: dial to %s error: %s", s.addr, err)
|
log.F("[socks5]: dial to %s error: %s", s.addr, err)
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.connect(c, addr); err != nil {
|
if err := s.connect(c, addr); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, p, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
func (s *Socks5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||||
c, _, err := s.dialer.Dial("tcp", s.addr)
|
c, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[socks5] dialudp dial tcp to %s error: %s", s.addr, err)
|
log.F("[socks5] dialudp dial tcp to %s error: %s", s.addr, err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -295,7 +294,7 @@ func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.A
|
|||||||
// connect takes an existing connection to a socks5 proxy server,
|
// connect takes an existing connection to a socks5 proxy server,
|
||||||
// and commands the server to extend that connection to target,
|
// and commands the server to extend that connection to target,
|
||||||
// which must be a canonical address with a host and port.
|
// which must be a canonical address with a host and port.
|
||||||
func (s *SOCKS5) connect(conn net.Conn, target string) error {
|
func (s *Socks5) connect(conn net.Conn, target string) error {
|
||||||
host, portStr, err := net.SplitHostPort(target)
|
host, portStr, err := net.SplitHostPort(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -426,7 +425,7 @@ func (s *SOCKS5) connect(conn net.Conn, target string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handshake fast-tracks SOCKS initialization to get target address to connect.
|
// Handshake fast-tracks SOCKS initialization to get target address to connect.
|
||||||
func (s *SOCKS5) handshake(rw io.ReadWriter) (socks.Addr, error) {
|
func (s *Socks5) handshake(rw io.ReadWriter) (socks.Addr, error) {
|
||||||
// Read RFC 1928 for request and reply structure and sizes
|
// Read RFC 1928 for request and reply structure and sizes
|
||||||
buf := make([]byte, socks.MaxAddrLen)
|
buf := make([]byte, socks.MaxAddrLen)
|
||||||
// read VER, NMETHODS, METHODS
|
// read VER, NMETHODS, METHODS
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
// SS is a base ss struct.
|
// SS is a base ss struct.
|
||||||
type SS struct {
|
type SS struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
core.Cipher
|
core.Cipher
|
||||||
@ -30,7 +31,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSS returns a ss proxy.
|
// NewSS returns a ss proxy.
|
||||||
func NewSS(s string, dialer proxy.Dialer) (*SS, error) {
|
func NewSS(s string, d proxy.Dialer, p proxy.Proxy) (*SS, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -46,23 +47,24 @@ func NewSS(s string, dialer proxy.Dialer) (*SS, error) {
|
|||||||
log.Fatalf("[ss] PickCipher for '%s', error: %s", method, err)
|
log.Fatalf("[ss] PickCipher for '%s', error: %s", method, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &SS{
|
ss := &SS{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
|
proxy: p,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
Cipher: ciph,
|
Cipher: ciph,
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return ss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSSDialer returns a ss proxy dialer.
|
// NewSSDialer returns a ss proxy dialer.
|
||||||
func NewSSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewSSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewSS(s, dialer)
|
return NewSS(s, d, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSSServer returns a ss proxy server.
|
// NewSSServer returns a ss proxy server.
|
||||||
func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewSSServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewSS(s, dialer)
|
return NewSS(s, nil, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe serves ss requests.
|
// ListenAndServe serves ss requests.
|
||||||
@ -108,7 +110,7 @@ func (s *SS) Serve(c net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := s.dialer.NextDialer(tgt.String())
|
dialer := s.proxy.NextDialer(tgt.String())
|
||||||
|
|
||||||
// udp over tcp?
|
// udp over tcp?
|
||||||
uot := socks.UoT(tgt[0])
|
uot := socks.UoT(tgt[0])
|
||||||
@ -147,14 +149,14 @@ func (s *SS) Serve(c net.Conn) {
|
|||||||
network = "udp"
|
network = "udp"
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, p, err := dialer.Dial(network, tgt.String())
|
rc, err := dialer.Dial(network, tgt.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, p)
|
log.F("[ss] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), tgt, err, dialer.Addr())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, p)
|
log.F("[ss] %s <-> %s, %s", c.RemoteAddr(), tgt, dialer.Addr())
|
||||||
|
|
||||||
_, _, err = conn.Relay(c, rc)
|
_, _, err = conn.Relay(c, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -238,33 +240,30 @@ func (s *SS) Addr() string {
|
|||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer.
|
|
||||||
func (s *SS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *SS) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *SS) Dial(network, addr string) (net.Conn, error) {
|
||||||
target := socks.ParseAddr(addr)
|
target := socks.ParseAddr(addr)
|
||||||
if target == nil {
|
if target == nil {
|
||||||
return nil, "", errors.New("[ss] unable to parse address: " + addr)
|
return nil, errors.New("[ss] unable to parse address: " + addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if network == "uot" {
|
if network == "uot" {
|
||||||
target[0] = target[0] | 0x8
|
target[0] = target[0] | 0x8
|
||||||
}
|
}
|
||||||
|
|
||||||
c, p, err := s.dialer.Dial("tcp", s.addr)
|
c, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[ss] dial to %s error: %s", s.addr, err)
|
log.F("[ss] dial to %s error: %s", s.addr, err)
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c = s.StreamConn(c)
|
c = s.StreamConn(c)
|
||||||
if _, err = c.Write(target); err != nil {
|
if _, err = c.Write(target); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, p, err
|
return c, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSSR returns a shadowsocksr proxy, ssr://method:pass@host:port/query
|
// NewSSR returns a shadowsocksr proxy, ssr://method:pass@host:port/query
|
||||||
func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
|
func NewSSR(s string, d proxy.Dialer) (*SSR, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -49,7 +49,7 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
|
|||||||
pass, _ := u.User.Password()
|
pass, _ := u.User.Password()
|
||||||
|
|
||||||
p := &SSR{
|
p := &SSR{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
EncryptMethod: method,
|
EncryptMethod: method,
|
||||||
EncryptPassword: pass,
|
EncryptPassword: pass,
|
||||||
@ -65,8 +65,8 @@ func NewSSR(s string, dialer proxy.Dialer) (*SSR, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSSRDialer returns a ssr proxy dialer.
|
// NewSSRDialer returns a ssr proxy dialer.
|
||||||
func NewSSRDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewSSRDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewSSR(s, dialer)
|
return NewSSR(s, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addr returns forwarder's address
|
// Addr returns forwarder's address
|
||||||
@ -77,30 +77,27 @@ func (s *SSR) Addr() string {
|
|||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *SSR) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *SSR) Dial(network, addr string) (net.Conn, error) {
|
||||||
target := socks.ParseAddr(addr)
|
target := socks.ParseAddr(addr)
|
||||||
if target == nil {
|
if target == nil {
|
||||||
return nil, "", errors.New("[ssr] unable to parse address: " + addr)
|
return nil, errors.New("[ssr] unable to parse address: " + addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher, err := shadowsocksr.NewStreamCipher(s.EncryptMethod, s.EncryptPassword)
|
cipher, err := shadowsocksr.NewStreamCipher(s.EncryptMethod, s.EncryptPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, p, err := s.dialer.Dial("tcp", s.addr)
|
c, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[ssr] dial to %s error: %s", s.addr, err)
|
log.F("[ssr] dial to %s error: %s", s.addr, err)
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
|
ssrconn := shadowsocksr.NewSSTCPConn(c, cipher)
|
||||||
if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil {
|
if ssrconn.Conn == nil || ssrconn.RemoteAddr() == nil {
|
||||||
return nil, p, errors.New("[ssr] nil connection")
|
return nil, errors.New("[ssr] nil connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
// should initialize obfs/protocol now
|
// should initialize obfs/protocol now
|
||||||
@ -109,7 +106,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
|
|
||||||
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
|
ssrconn.IObfs = obfs.NewObfs(s.Obfs)
|
||||||
if ssrconn.IObfs == nil {
|
if ssrconn.IObfs == nil {
|
||||||
return nil, p, errors.New("[ssr] unsupported obfs type: " + s.Obfs)
|
return nil, errors.New("[ssr] unsupported obfs type: " + s.Obfs)
|
||||||
}
|
}
|
||||||
|
|
||||||
obfsServerInfo := &ssr.ServerInfoForObfs{
|
obfsServerInfo := &ssr.ServerInfoForObfs{
|
||||||
@ -122,7 +119,7 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
|
|
||||||
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
|
ssrconn.IProtocol = protocol.NewProtocol(s.Protocol)
|
||||||
if ssrconn.IProtocol == nil {
|
if ssrconn.IProtocol == nil {
|
||||||
return nil, p, errors.New("[ssr] unsupported protocol type: " + s.Protocol)
|
return nil, errors.New("[ssr] unsupported protocol type: " + s.Protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
protocolServerInfo := &ssr.ServerInfoForObfs{
|
protocolServerInfo := &ssr.ServerInfoForObfs{
|
||||||
@ -145,10 +142,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, string, error) {
|
|||||||
|
|
||||||
if _, err := ssrconn.Write(target); err != nil {
|
if _, err := ssrconn.Write(target); err != nil {
|
||||||
ssrconn.Close()
|
ssrconn.Close()
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ssrconn, p, err
|
return ssrconn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
// TCPTun struct
|
// TCPTun struct
|
||||||
type TCPTun struct {
|
type TCPTun struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
raddr string
|
raddr string
|
||||||
@ -23,7 +23,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPTun returns a tcptun proxy
|
// NewTCPTun returns a tcptun proxy
|
||||||
func NewTCPTun(s string, dialer proxy.Dialer) (*TCPTun, error) {
|
func NewTCPTun(s string, p proxy.Proxy) (*TCPTun, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -33,18 +33,18 @@ func NewTCPTun(s string, dialer proxy.Dialer) (*TCPTun, error) {
|
|||||||
addr := u.Host
|
addr := u.Host
|
||||||
d := strings.Split(addr, "=")
|
d := strings.Split(addr, "=")
|
||||||
|
|
||||||
p := &TCPTun{
|
t := &TCPTun{
|
||||||
dialer: dialer,
|
proxy: p,
|
||||||
addr: d[0],
|
addr: d[0],
|
||||||
raddr: d[1],
|
raddr: d[1],
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPTunServer returns a udp tunnel server
|
// NewTCPTunServer returns a udp tunnel server
|
||||||
func NewTCPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewTCPTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewTCPTun(s, dialer)
|
return NewTCPTun(s, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
@ -76,7 +76,7 @@ func (s *TCPTun) Serve(c net.Conn) {
|
|||||||
c.SetKeepAlive(true)
|
c.SetKeepAlive(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, p, err := s.dialer.Dial("tcp", s.raddr)
|
rc, p, err := s.proxy.Dial("tcp", s.raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tcptun] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), s.addr, err, p)
|
log.F("[tcptun] %s <-> %s, %s, error in dial: %v", c.RemoteAddr(), s.addr, err, p)
|
||||||
return
|
return
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
// TLS struct
|
// TLS struct
|
||||||
type TLS struct {
|
type TLS struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
tlsConfig *stdtls.Config
|
tlsConfig *stdtls.Config
|
||||||
@ -34,7 +35,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTLS returns a tls proxy struct
|
// NewTLS returns a tls proxy struct
|
||||||
func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
|
func NewTLS(s string, d proxy.Dialer, p proxy.Proxy) (*TLS, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse url err: %s", err)
|
log.F("parse url err: %s", err)
|
||||||
@ -53,9 +54,9 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
|
|||||||
certFile := query.Get("cert")
|
certFile := query.Get("cert")
|
||||||
keyFile := query.Get("key")
|
keyFile := query.Get("key")
|
||||||
|
|
||||||
p := &TLS{
|
t := &TLS{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
addr: addr,
|
proxy: p,
|
||||||
serverName: serverName,
|
serverName: serverName,
|
||||||
skipVerify: false,
|
skipVerify: false,
|
||||||
certFile: certFile,
|
certFile: certFile,
|
||||||
@ -63,15 +64,15 @@ func NewTLS(s string, dialer proxy.Dialer) (*TLS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if skipVerify == "true" {
|
if skipVerify == "true" {
|
||||||
p.skipVerify = true
|
t.skipVerify = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTLSDialer returns a tls proxy dialer
|
// NewTLSDialer returns a tls proxy dialer
|
||||||
func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewTLSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
p, err := NewTLS(s, dialer)
|
p, err := NewTLS(s, d, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -87,7 +88,7 @@ func NewTLSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTLSServer returns a tls transport layer before the real server
|
// NewTLSServer returns a tls transport layer before the real server
|
||||||
func NewTLSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewTLSServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
transport := strings.Split(s, ",")
|
transport := strings.Split(s, ",")
|
||||||
|
|
||||||
// prepare transport listener
|
// prepare transport listener
|
||||||
@ -96,28 +97,28 @@ func NewTLSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
|||||||
return nil, errors.New("[tls] malformd listener:" + s)
|
return nil, errors.New("[tls] malformd listener:" + s)
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := NewTLS(transport[0], dialer)
|
t, err := NewTLS(transport[0], nil, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cert, err := stdtls.LoadX509KeyPair(p.certFile, p.keyFile)
|
cert, err := stdtls.LoadX509KeyPair(t.certFile, t.keyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tls] unable to load cert: %s, key %s", p.certFile, p.keyFile)
|
log.F("[tls] unable to load cert: %s, key %s", t.certFile, t.keyFile)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.tlsConfig = &stdtls.Config{
|
t.tlsConfig = &stdtls.Config{
|
||||||
Certificates: []stdtls.Certificate{cert},
|
Certificates: []stdtls.Certificate{cert},
|
||||||
MinVersion: stdtls.VersionTLS10,
|
MinVersion: stdtls.VersionTLS10,
|
||||||
}
|
}
|
||||||
|
|
||||||
p.server, err = proxy.ServerFromURL(transport[1], dialer)
|
t.server, err = proxy.ServerFromURL(transport[1], p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
@ -156,20 +157,17 @@ func (s *TLS) Serve(c net.Conn) {
|
|||||||
// Addr returns forwarder's address
|
// Addr returns forwarder's address
|
||||||
func (s *TLS) Addr() string { return s.addr }
|
func (s *TLS) Addr() string { return s.addr }
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *TLS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy
|
// Dial connects to the address addr on the network net via the proxy
|
||||||
func (s *TLS) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *TLS) Dial(network, addr string) (net.Conn, error) {
|
||||||
cc, p, err := s.dialer.Dial("tcp", s.addr)
|
cc, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[tls] dial to %s error: %s", s.addr, err)
|
log.F("[tls] dial to %s error: %s", s.addr, err)
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c := stdtls.Client(cc, s.tlsConfig)
|
c := stdtls.Client(cc, s.tlsConfig)
|
||||||
err = c.Handshake()
|
err = c.Handshake()
|
||||||
return c, p, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
// TProxy struct
|
// TProxy struct
|
||||||
type TProxy struct {
|
type TProxy struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTProxy returns a tproxy.
|
// NewTProxy returns a tproxy.
|
||||||
func NewTProxy(s string, dialer proxy.Dialer) (*TProxy, error) {
|
func NewTProxy(s string, p proxy.Proxy) (*TProxy, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -37,17 +37,17 @@ func NewTProxy(s string, dialer proxy.Dialer) (*TProxy, error) {
|
|||||||
|
|
||||||
addr := u.Host
|
addr := u.Host
|
||||||
|
|
||||||
p := &TProxy{
|
tp := &TProxy{
|
||||||
dialer: dialer,
|
proxy: p,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return tp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTProxyServer returns a udp tunnel server.
|
// NewTProxyServer returns a udp tunnel server.
|
||||||
func NewTProxyServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewTProxyServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewTProxy(s, dialer)
|
return NewTProxy(s, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe .
|
// ListenAndServe .
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// UDPTun is a base udptun struct.
|
// UDPTun is a base udptun struct.
|
||||||
type UDPTun struct {
|
type UDPTun struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
taddr string // tunnel addr string
|
taddr string // tunnel addr string
|
||||||
tuaddr *net.UDPAddr // tunnel addr
|
tuaddr *net.UDPAddr // tunnel addr
|
||||||
@ -25,7 +25,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewUDPTun returns a UDPTun proxy.
|
// NewUDPTun returns a UDPTun proxy.
|
||||||
func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) {
|
func NewUDPTun(s string, p proxy.Proxy) (*UDPTun, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[udptun] parse err: %s", err)
|
log.F("[udptun] parse err: %s", err)
|
||||||
@ -35,19 +35,19 @@ func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) {
|
|||||||
addr := u.Host
|
addr := u.Host
|
||||||
d := strings.Split(addr, "=")
|
d := strings.Split(addr, "=")
|
||||||
|
|
||||||
p := &UDPTun{
|
ut := &UDPTun{
|
||||||
dialer: dialer,
|
proxy: p,
|
||||||
addr: d[0],
|
addr: d[0],
|
||||||
taddr: d[1],
|
taddr: d[1],
|
||||||
}
|
}
|
||||||
|
|
||||||
p.tuaddr, err = net.ResolveUDPAddr("udp", p.taddr)
|
ut.tuaddr, err = net.ResolveUDPAddr("udp", ut.taddr)
|
||||||
return p, err
|
return ut, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUDPTunServer returns a udp tunnel server.
|
// NewUDPTunServer returns a udp tunnel server.
|
||||||
func NewUDPTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewUDPTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewUDPTun(s, dialer)
|
return NewUDPTun(s, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe listen and serves on the given address.
|
// ListenAndServe listen and serves on the given address.
|
||||||
@ -75,7 +75,7 @@ func (s *UDPTun) ListenAndServe() {
|
|||||||
|
|
||||||
v, ok := nm.Load(raddr.String())
|
v, ok := nm.Load(raddr.String())
|
||||||
if !ok && v == nil {
|
if !ok && v == nil {
|
||||||
pc, _, err = s.dialer.DialUDP("udp", s.taddr)
|
pc, _, err = s.proxy.DialUDP("udp", s.taddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[udptun] remote dial error: %v", err)
|
log.F("[udptun] remote dial error: %v", err)
|
||||||
continue
|
continue
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
// Unix domain socket struct
|
// Unix domain socket struct
|
||||||
type Unix struct {
|
type Unix struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
server proxy.Server
|
server proxy.Server
|
||||||
@ -25,28 +26,29 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewUnix returns unix fomain socket proxy
|
// NewUnix returns unix fomain socket proxy
|
||||||
func NewUnix(s string, dialer proxy.Dialer) (*Unix, error) {
|
func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse url err: %s", err)
|
log.F("parse url err: %s", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &Unix{
|
unix := &Unix{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
|
proxy: p,
|
||||||
addr: u.Path,
|
addr: u.Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return unix, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnixDialer returns a unix domain socket dialer
|
// NewUnixDialer returns a unix domain socket dialer
|
||||||
func NewUnixDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewUnixDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewUnix(s, dialer)
|
return NewUnix(s, d, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUnixServer returns a unix domain socket server
|
// NewUnixServer returns a unix domain socket server
|
||||||
func NewUnixServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewUnixServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
transport := strings.Split(s, ",")
|
transport := strings.Split(s, ",")
|
||||||
|
|
||||||
// prepare transport listener
|
// prepare transport listener
|
||||||
@ -55,17 +57,17 @@ func NewUnixServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
|||||||
return nil, errors.New("[unix] malformd listener:" + s)
|
return nil, errors.New("[unix] malformd listener:" + s)
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := NewUnix(transport[0], dialer)
|
unix, err := NewUnix(transport[0], nil, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.server, err = proxy.ServerFromURL(transport[1], dialer)
|
unix.server, err = proxy.ServerFromURL(transport[1], p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return unix, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe serves requests
|
// ListenAndServe serves requests
|
||||||
@ -109,18 +111,10 @@ func (s *Unix) Addr() string {
|
|||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *Unix) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *Unix) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *Unix) Dial(network, addr string) (net.Conn, error) {
|
||||||
// NOTE: must be the first dialer in a chain
|
// NOTE: must be the first dialer in a chain
|
||||||
rc, err := net.Dial("unix", s.addr)
|
return net.Dial("unix", s.addr)
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc, "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
// DialUDP connects to the given address via the proxy
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// UoTTun is a base udp over tcp tunnel struct.
|
// UoTTun is a base udp over tcp tunnel struct.
|
||||||
type UoTTun struct {
|
type UoTTun struct {
|
||||||
dialer proxy.Dialer
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
|
|
||||||
raddr string
|
raddr string
|
||||||
@ -25,7 +25,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewUoTTun returns a UoTTun proxy.
|
// NewUoTTun returns a UoTTun proxy.
|
||||||
func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) {
|
func NewUoTTun(s string, p proxy.Proxy) (*UoTTun, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse err: %s", err)
|
log.F("parse err: %s", err)
|
||||||
@ -35,18 +35,18 @@ func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) {
|
|||||||
addr := u.Host
|
addr := u.Host
|
||||||
d := strings.Split(addr, "=")
|
d := strings.Split(addr, "=")
|
||||||
|
|
||||||
p := &UoTTun{
|
ut := &UoTTun{
|
||||||
dialer: dialer,
|
proxy: p,
|
||||||
addr: d[0],
|
addr: d[0],
|
||||||
raddr: d[1],
|
raddr: d[1],
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return ut, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUoTTunServer returns a uot tunnel server.
|
// NewUoTTunServer returns a uot tunnel server.
|
||||||
func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
|
func NewUoTTunServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
return NewUoTTun(s, dialer)
|
return NewUoTTun(s, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenAndServe listen and serve on tcp.
|
// ListenAndServe listen and serve on tcp.
|
||||||
@ -69,7 +69,7 @@ func (s *UoTTun) ListenAndServe() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, p, err := s.dialer.Dial("uot", s.raddr)
|
rc, p, err := s.proxy.Dial("uot", s.raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
|
log.F("[uottun] failed to connect to server %v: %v", s.raddr, err)
|
||||||
continue
|
continue
|
||||||
|
@ -27,7 +27,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewVMess returns a vmess proxy.
|
// NewVMess returns a vmess proxy.
|
||||||
func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) {
|
func NewVMess(s string, d proxy.Dialer) (*VMess, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse url err: %s", err)
|
log.F("parse url err: %s", err)
|
||||||
@ -62,7 +62,7 @@ func NewVMess(s string, dialer proxy.Dialer) (*VMess, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := &VMess{
|
p := &VMess{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
alterID: int(alterID),
|
alterID: int(alterID),
|
||||||
@ -86,18 +86,14 @@ func (s *VMess) Addr() string {
|
|||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer
|
|
||||||
func (s *VMess) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *VMess) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *VMess) Dial(network, addr string) (net.Conn, error) {
|
||||||
rc, p, err := s.dialer.Dial("tcp", s.addr)
|
rc, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, e := s.client.NewConn(rc, addr)
|
return s.client.NewConn(rc, addr)
|
||||||
return cc, p, e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
@ -24,7 +24,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewWS returns a websocket proxy.
|
// NewWS returns a websocket proxy.
|
||||||
func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
|
func NewWS(s string, d proxy.Dialer) (*WS, error) {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("parse url err: %s", err)
|
log.F("parse url err: %s", err)
|
||||||
@ -35,7 +35,7 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
|
|||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
addr = dialer.Addr()
|
addr = d.Addr()
|
||||||
}
|
}
|
||||||
|
|
||||||
colonPos := strings.LastIndex(addr, ":")
|
colonPos := strings.LastIndex(addr, ":")
|
||||||
@ -51,7 +51,7 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := &WS{
|
p := &WS{
|
||||||
dialer: dialer,
|
dialer: d,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
@ -60,8 +60,8 @@ func NewWS(s string, dialer proxy.Dialer) (*WS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewWSDialer returns a ws proxy dialer.
|
// NewWSDialer returns a ws proxy dialer.
|
||||||
func NewWSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
|
func NewWSDialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
|
||||||
return NewWS(s, dialer)
|
return NewWS(s, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addr returns forwarder's address.
|
// Addr returns forwarder's address.
|
||||||
@ -72,18 +72,14 @@ func (s *WS) Addr() string {
|
|||||||
return s.addr
|
return s.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer.
|
|
||||||
func (s *WS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net via the proxy.
|
// Dial connects to the address addr on the network net via the proxy.
|
||||||
func (s *WS) Dial(network, addr string) (net.Conn, string, error) {
|
func (s *WS) Dial(network, addr string) (net.Conn, error) {
|
||||||
rc, p, err := s.dialer.Dial("tcp", s.addr)
|
rc, err := s.dialer.Dial("tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, p, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, e := s.client.NewConn(rc, addr)
|
return s.client.NewConn(rc, addr)
|
||||||
return cc, p, e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy.
|
// DialUDP connects to the given address via the proxy.
|
||||||
|
74
rule/rule.go
74
rule/rule.go
@ -10,23 +10,23 @@ import (
|
|||||||
"github.com/nadoo/glider/strategy"
|
"github.com/nadoo/glider/strategy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dialer struct
|
// Proxy struct
|
||||||
type Dialer struct {
|
type Proxy struct {
|
||||||
gDialer *strategy.Dialer
|
proxy *strategy.Proxy
|
||||||
dialers []*strategy.Dialer
|
proxies []*strategy.Proxy
|
||||||
|
|
||||||
domainMap sync.Map
|
domainMap sync.Map
|
||||||
ipMap sync.Map
|
ipMap sync.Map
|
||||||
cidrMap sync.Map
|
cidrMap sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDialer returns a new rule dialer
|
// NewProxy returns a new rule proxy
|
||||||
func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer {
|
func NewProxy(rules []*Config, proxy *strategy.Proxy) *Proxy {
|
||||||
rd := &Dialer{gDialer: gDialer}
|
rd := &Proxy{proxy: proxy}
|
||||||
|
|
||||||
for _, r := range rules {
|
for _, r := range rules {
|
||||||
sd := strategy.NewDialer(r.Forward, &r.StrategyConfig)
|
sd := strategy.NewProxy(r.Forward, &r.StrategyConfig)
|
||||||
rd.dialers = append(rd.dialers, sd)
|
rd.proxies = append(rd.proxies, sd)
|
||||||
|
|
||||||
for _, domain := range r.Domain {
|
for _, domain := range r.Domain {
|
||||||
rd.domainMap.Store(strings.ToLower(domain), sd)
|
rd.domainMap.Store(strings.ToLower(domain), sd)
|
||||||
@ -46,31 +46,38 @@ func NewDialer(rules []*Config, gDialer *strategy.Dialer) *Dialer {
|
|||||||
return rd
|
return rd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addr returns RuleDialer's address, always be "RULES"
|
// Dial dials to targer addr and return a conn
|
||||||
func (rd *Dialer) Addr() string { return "RULE DIALER, DEFAULT: " + rd.gDialer.Addr() }
|
func (p *Proxy) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
|
return p.nextProxy(addr).Dial(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
// NextDialer return next dialer according to rule
|
// DialUDP connects to the given address via the proxy
|
||||||
func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer {
|
func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||||
|
return p.nextProxy(addr).DialUDP(network, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// nextProxy return next proxy according to rule
|
||||||
|
func (p *Proxy) nextProxy(dstAddr string) *strategy.Proxy {
|
||||||
host, _, err := net.SplitHostPort(dstAddr)
|
host, _, err := net.SplitHostPort(dstAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: check here
|
// TODO: check here
|
||||||
// logf("[rule] SplitHostPort ERROR: %s", err)
|
// logf("[rule] SplitHostPort ERROR: %s", err)
|
||||||
return rd.gDialer
|
return p.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// find ip
|
// find ip
|
||||||
if ip := net.ParseIP(host); ip != nil {
|
if ip := net.ParseIP(host); ip != nil {
|
||||||
// check ip
|
// check ip
|
||||||
if dialer, ok := rd.ipMap.Load(ip.String()); ok {
|
if proxy, ok := p.ipMap.Load(ip.String()); ok {
|
||||||
return dialer.(proxy.Dialer)
|
return proxy.(*strategy.Proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret proxy.Dialer
|
var ret *strategy.Proxy
|
||||||
// check cidr
|
// check cidr
|
||||||
rd.cidrMap.Range(func(key, value interface{}) bool {
|
p.cidrMap.Range(func(key, value interface{}) bool {
|
||||||
cidr := key.(*net.IPNet)
|
cidr := key.(*net.IPNet)
|
||||||
if cidr.Contains(ip) {
|
if cidr.Contains(ip) {
|
||||||
ret = value.(proxy.Dialer)
|
ret = value.(*strategy.Proxy)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,26 +96,21 @@ func (rd *Dialer) NextDialer(dstAddr string) proxy.Dialer {
|
|||||||
domain := strings.Join(domainParts[i:length], ".")
|
domain := strings.Join(domainParts[i:length], ".")
|
||||||
|
|
||||||
// find in domainMap
|
// find in domainMap
|
||||||
if dialer, ok := rd.domainMap.Load(domain); ok {
|
if proxy, ok := p.domainMap.Load(domain); ok {
|
||||||
return dialer.(proxy.Dialer)
|
return proxy.(*strategy.Proxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rd.gDialer
|
return p.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dial dials to targer addr and return a conn
|
// NextDialer return next dialer according to rule
|
||||||
func (rd *Dialer) Dial(network, addr string) (net.Conn, string, error) {
|
func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer {
|
||||||
return rd.NextDialer(addr).Dial(network, addr)
|
return p.nextProxy(dstAddr).NextDialer(dstAddr)
|
||||||
}
|
|
||||||
|
|
||||||
// DialUDP connects to the given address via the proxy
|
|
||||||
func (rd *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
|
||||||
return rd.NextDialer(addr).DialUDP(network, addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddDomainIP used to update ipMap rules according to domainMap rule
|
// AddDomainIP used to update ipMap rules according to domainMap rule
|
||||||
func (rd *Dialer) AddDomainIP(domain, ip string) error {
|
func (p *Proxy) AddDomainIP(domain, ip string) error {
|
||||||
if ip != "" {
|
if ip != "" {
|
||||||
domainParts := strings.Split(domain, ".")
|
domainParts := strings.Split(domain, ".")
|
||||||
length := len(domainParts)
|
length := len(domainParts)
|
||||||
@ -116,8 +118,8 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error {
|
|||||||
pDomain := strings.ToLower(strings.Join(domainParts[i:length], "."))
|
pDomain := strings.ToLower(strings.Join(domainParts[i:length], "."))
|
||||||
|
|
||||||
// find in domainMap
|
// find in domainMap
|
||||||
if dialer, ok := rd.domainMap.Load(pDomain); ok {
|
if dialer, ok := p.domainMap.Load(pDomain); ok {
|
||||||
rd.ipMap.Store(ip, dialer)
|
p.ipMap.Store(ip, dialer)
|
||||||
log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, pDomain, domain, ip)
|
log.F("[rule] add ip=%s, based on rule: domain=%s & domain/ip: %s/%s\n", ip, pDomain, domain, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,10 +128,10 @@ func (rd *Dialer) AddDomainIP(domain, ip string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check .
|
// Check .
|
||||||
func (rd *Dialer) Check() {
|
func (p *Proxy) Check() {
|
||||||
rd.gDialer.Check()
|
p.proxy.Check()
|
||||||
|
|
||||||
for _, d := range rd.dialers {
|
for _, d := range p.proxies {
|
||||||
d.Check()
|
d.Check()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,8 +97,8 @@ func (f *Forwarder) Addr() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dial .
|
// Dial .
|
||||||
func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error) {
|
func (f *Forwarder) Dial(network, addr string) (c net.Conn, err error) {
|
||||||
c, p, err = f.Dialer.Dial(network, addr)
|
c, err = f.Dialer.Dial(network, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.IncFailures()
|
f.IncFailures()
|
||||||
if f.Failures() >= f.MaxFailures() && f.Enabled() {
|
if f.Failures() >= f.MaxFailures() && f.Enabled() {
|
||||||
@ -107,7 +107,7 @@ func (f *Forwarder) Dial(network, addr string) (c net.Conn, p string, err error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, p, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failures returns the failuer count of forwarder
|
// Failures returns the failuer count of forwarder
|
||||||
|
@ -32,8 +32,8 @@ func (p priSlice) Len() int { return len(p) }
|
|||||||
func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() }
|
func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() }
|
||||||
func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||||
|
|
||||||
// Dialer is base dialer struct.
|
// Proxy is base proxy struct.
|
||||||
type Dialer struct {
|
type Proxy struct {
|
||||||
config *Config
|
config *Config
|
||||||
fwdrs priSlice
|
fwdrs priSlice
|
||||||
available []*Forwarder
|
available []*Forwarder
|
||||||
@ -44,8 +44,8 @@ type Dialer struct {
|
|||||||
nextForwarder func(addr string) *Forwarder
|
nextForwarder func(addr string) *Forwarder
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDialer returns a new strategy dialer.
|
// NewProxy returns a new strategy proxy.
|
||||||
func NewDialer(s []string, c *Config) *Dialer {
|
func NewProxy(s []string, c *Config) *Proxy {
|
||||||
var fwdrs []*Forwarder
|
var fwdrs []*Forwarder
|
||||||
for _, chain := range s {
|
for _, chain := range s {
|
||||||
fwdr, err := ForwarderFromURL(chain, c.IntFace)
|
fwdr, err := ForwarderFromURL(chain, c.IntFace)
|
||||||
@ -62,12 +62,12 @@ func NewDialer(s []string, c *Config) *Dialer {
|
|||||||
c.Strategy = "rr"
|
c.Strategy = "rr"
|
||||||
}
|
}
|
||||||
|
|
||||||
return newDialer(fwdrs, c)
|
return newProxy(fwdrs, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newDialer returns a new rrDialer
|
// newProxy returns a new rrProxy
|
||||||
func newDialer(fwdrs []*Forwarder, c *Config) *Dialer {
|
func newProxy(fwdrs []*Forwarder, c *Config) *Proxy {
|
||||||
d := &Dialer{fwdrs: fwdrs, config: c}
|
d := &Proxy{fwdrs: fwdrs, config: c}
|
||||||
sort.Sort(d.fwdrs)
|
sort.Sort(d.fwdrs)
|
||||||
|
|
||||||
d.initAvailable()
|
d.initAvailable()
|
||||||
@ -101,112 +101,103 @@ func newDialer(fwdrs []*Forwarder, c *Config) *Dialer {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addr returns forwarder's address.
|
|
||||||
func (d *Dialer) Addr() string {
|
|
||||||
if d.fwdrs.Len() == 1 {
|
|
||||||
return d.fwdrs[0].Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
return "STRATEGY"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dial connects to the address addr on the network net.
|
// Dial connects to the address addr on the network net.
|
||||||
func (d *Dialer) Dial(network, addr string) (net.Conn, string, error) {
|
func (p *Proxy) Dial(network, addr string) (net.Conn, string, error) {
|
||||||
nd := d.NextDialer(addr)
|
nd := p.NextDialer(addr)
|
||||||
c, _, err := nd.Dial(network, addr)
|
c, err := nd.Dial(network, addr)
|
||||||
return c, nd.Addr(), err
|
return c, nd.Addr(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialUDP connects to the given address.
|
// DialUDP connects to the given address.
|
||||||
func (d *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
func (p *Proxy) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||||
return d.NextDialer(addr).DialUDP(network, addr)
|
return p.NextDialer(addr).DialUDP(network, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextDialer returns the next dialer.
|
// NextDialer returns the next dialer.
|
||||||
func (d *Dialer) NextDialer(dstAddr string) proxy.Dialer {
|
func (p *Proxy) NextDialer(dstAddr string) proxy.Dialer {
|
||||||
d.mu.RLock()
|
p.mu.RLock()
|
||||||
defer d.mu.RUnlock()
|
defer p.mu.RUnlock()
|
||||||
|
|
||||||
return d.nextForwarder(dstAddr)
|
return p.nextForwarder(dstAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority returns the active priority of dialer.
|
// Priority returns the active priority of dialer.
|
||||||
func (d *Dialer) Priority() uint32 { return atomic.LoadUint32(&d.priority) }
|
func (p *Proxy) Priority() uint32 { return atomic.LoadUint32(&p.priority) }
|
||||||
|
|
||||||
// SetPriority sets the active priority of daler.
|
// SetPriority sets the active priority of daler.
|
||||||
func (d *Dialer) SetPriority(p uint32) { atomic.StoreUint32(&d.priority, p) }
|
func (p *Proxy) SetPriority(pri uint32) { atomic.StoreUint32(&p.priority, pri) }
|
||||||
|
|
||||||
// initAvailable traverse d.fwdrs and init the available forwarder slice.
|
// initAvailable traverse d.fwdrs and init the available forwarder slice.
|
||||||
func (d *Dialer) initAvailable() {
|
func (p *Proxy) initAvailable() {
|
||||||
for _, f := range d.fwdrs {
|
for _, f := range p.fwdrs {
|
||||||
if f.Enabled() {
|
if f.Enabled() {
|
||||||
d.SetPriority(f.Priority())
|
p.SetPriority(f.Priority())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d.available = nil
|
p.available = nil
|
||||||
for _, f := range d.fwdrs {
|
for _, f := range p.fwdrs {
|
||||||
if f.Enabled() && f.Priority() >= d.Priority() {
|
if f.Enabled() && f.Priority() >= p.Priority() {
|
||||||
d.available = append(d.available, f)
|
p.available = append(p.available, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(d.available) == 0 {
|
if len(p.available) == 0 {
|
||||||
// no available forwarders, set priority to 0 to check all forwarders in check func
|
// no available forwarders, set priority to 0 to check all forwarders in check func
|
||||||
d.SetPriority(0)
|
p.SetPriority(0)
|
||||||
log.F("[strategy] no available forwarders, just use: %s, please check your settings or network", d.fwdrs[0].Addr())
|
log.F("[strategy] no available forwarders, just use: %s, please check your settings or network", p.fwdrs[0].Addr())
|
||||||
d.available = append(d.available, d.fwdrs[0])
|
p.available = append(p.available, p.fwdrs[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// onStatusChanged will be called when fwdr's status changed.
|
// onStatusChanged will be called when fwdr's status changed.
|
||||||
func (d *Dialer) onStatusChanged(fwdr *Forwarder) {
|
func (p *Proxy) onStatusChanged(fwdr *Forwarder) {
|
||||||
d.mu.Lock()
|
p.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if fwdr.Enabled() {
|
if fwdr.Enabled() {
|
||||||
log.F("[strategy] %s changed status from Disabled to Enabled ", fwdr.Addr())
|
log.F("[strategy] %s changed status from Disabled to Enabled ", fwdr.Addr())
|
||||||
if fwdr.Priority() == d.Priority() {
|
if fwdr.Priority() == p.Priority() {
|
||||||
d.available = append(d.available, fwdr)
|
p.available = append(p.available, fwdr)
|
||||||
} else if fwdr.Priority() > d.Priority() {
|
} else if fwdr.Priority() > p.Priority() {
|
||||||
d.initAvailable()
|
p.initAvailable()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.F("[strategy] %s changed status from Enabled to Disabled", fwdr.Addr())
|
log.F("[strategy] %s changed status from Enabled to Disabled", fwdr.Addr())
|
||||||
for i, f := range d.available {
|
for i, f := range p.available {
|
||||||
if f == fwdr {
|
if f == fwdr {
|
||||||
d.available[i], d.available = d.available[len(d.available)-1], d.available[:len(d.available)-1]
|
p.available[i], p.available = p.available[len(p.available)-1], p.available[:len(p.available)-1]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(d.available) == 0 {
|
if len(p.available) == 0 {
|
||||||
d.initAvailable()
|
p.initAvailable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check implements the Checker interface.
|
// Check implements the Checker interface.
|
||||||
func (d *Dialer) Check() {
|
func (p *Proxy) Check() {
|
||||||
// no need to check when there's only 1 forwarder
|
// no need to check when there's only 1 forwarder
|
||||||
if len(d.fwdrs) > 1 {
|
if len(p.fwdrs) > 1 {
|
||||||
for i := 0; i < len(d.fwdrs); i++ {
|
for i := 0; i < len(p.fwdrs); i++ {
|
||||||
go d.check(i)
|
go p.check(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) check(i int) {
|
func (p *Proxy) check(i int) {
|
||||||
f := d.fwdrs[i]
|
f := p.fwdrs[i]
|
||||||
retry := 1
|
retry := 1
|
||||||
buf := make([]byte, 4)
|
buf := make([]byte, 4)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Duration(d.config.CheckInterval) * time.Second * time.Duration(retry>>1))
|
time.Sleep(time.Duration(p.config.CheckInterval) * time.Second * time.Duration(retry>>1))
|
||||||
|
|
||||||
// check all forwarders at least one time
|
// check all forwarders at least one time
|
||||||
if retry > 1 && f.Priority() < d.Priority() {
|
if retry > 1 && f.Priority() < p.Priority() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,10 +207,10 @@ func (d *Dialer) check(i int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
rc, _, err := f.Dial("tcp", d.config.CheckWebSite)
|
rc, err := f.Dial("tcp", p.config.CheckWebSite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Disable()
|
f.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err)
|
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,24 +219,24 @@ func (d *Dialer) check(i int) {
|
|||||||
_, err = io.ReadFull(rc, buf)
|
_, err = io.ReadFull(rc, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Disable()
|
f.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err)
|
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err)
|
||||||
} else if bytes.Equal([]byte("HTTP"), buf) {
|
} else if bytes.Equal([]byte("HTTP"), buf) {
|
||||||
|
|
||||||
readTime := time.Since(startTime)
|
readTime := time.Since(startTime)
|
||||||
f.SetLatency(int64(readTime))
|
f.SetLatency(int64(readTime))
|
||||||
|
|
||||||
if readTime > time.Duration(d.config.CheckTimeout)*time.Second {
|
if readTime > time.Duration(p.config.CheckTimeout)*time.Second {
|
||||||
f.Disable()
|
f.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime)
|
log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime)
|
||||||
} else {
|
} else {
|
||||||
retry = 2
|
retry = 2
|
||||||
f.Enable()
|
f.Enable()
|
||||||
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime)
|
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
f.Disable()
|
f.Disable()
|
||||||
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, buf)
|
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc.Close()
|
rc.Close()
|
||||||
@ -253,20 +244,20 @@ func (d *Dialer) check(i int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Round Robin
|
// Round Robin
|
||||||
func (d *Dialer) scheduleRR(dstAddr string) *Forwarder {
|
func (p *Proxy) scheduleRR(dstAddr string) *Forwarder {
|
||||||
return d.available[atomic.AddUint32(&d.index, 1)%uint32(len(d.available))]
|
return p.available[atomic.AddUint32(&p.index, 1)%uint32(len(p.available))]
|
||||||
}
|
}
|
||||||
|
|
||||||
// High Availability
|
// High Availability
|
||||||
func (d *Dialer) scheduleHA(dstAddr string) *Forwarder {
|
func (p *Proxy) scheduleHA(dstAddr string) *Forwarder {
|
||||||
return d.available[0]
|
return p.available[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Latency based High Availability
|
// Latency based High Availability
|
||||||
func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder {
|
func (p *Proxy) scheduleLHA(dstAddr string) *Forwarder {
|
||||||
fwdr := d.available[0]
|
fwdr := p.available[0]
|
||||||
lowest := fwdr.Latency()
|
lowest := fwdr.Latency()
|
||||||
for _, f := range d.available {
|
for _, f := range p.available {
|
||||||
if f.Latency() < lowest {
|
if f.Latency() < lowest {
|
||||||
lowest = f.Latency()
|
lowest = f.Latency()
|
||||||
fwdr = f
|
fwdr = f
|
||||||
@ -276,8 +267,8 @@ func (d *Dialer) scheduleLHA(dstAddr string) *Forwarder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destination Hashing
|
// Destination Hashing
|
||||||
func (d *Dialer) scheduleDH(dstAddr string) *Forwarder {
|
func (p *Proxy) scheduleDH(dstAddr string) *Forwarder {
|
||||||
fnv1a := fnv.New32a()
|
fnv1a := fnv.New32a()
|
||||||
fnv1a.Write([]byte(dstAddr))
|
fnv1a.Write([]byte(dstAddr))
|
||||||
return d.available[fnv1a.Sum32()%uint32(len(d.available))]
|
return p.available[fnv1a.Sum32()%uint32(len(p.available))]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user