forwarder: add the ability to specify local ip. #48

This commit is contained in:
nadoo 2018-08-15 00:54:17 +08:00
parent 205b4efac7
commit 39ccbc5adf
7 changed files with 44 additions and 28 deletions

View File

@ -191,10 +191,9 @@ func usage() {
fmt.Fprintf(os.Stderr, " lha: Latency based High Availability mode\n") fmt.Fprintf(os.Stderr, " lha: Latency based High Availability mode\n")
fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "\n")
fmt.Fprintf(os.Stderr, "Forwarder option scheme: FORWARD_URL[#OPTIONS]\n") fmt.Fprintf(os.Stderr, "Forwarder option scheme: FORWARD_URL#OPTIONS\n")
fmt.Fprintf(os.Stderr, " Available options for forwarders:\n")
fmt.Fprintf(os.Stderr, " priority: set the priority of that forwarder, default:0\n") fmt.Fprintf(os.Stderr, " priority: set the priority of that forwarder, default:0\n")
fmt.Fprintf(os.Stderr, " Examples:\n") fmt.Fprintf(os.Stderr, " e.g.:\n")
fmt.Fprintf(os.Stderr, " socks5://1.1.1.1:1080#priority=100\n") fmt.Fprintf(os.Stderr, " socks5://1.1.1.1:1080#priority=100\n")
fmt.Fprintf(os.Stderr, " vmess://[security:]uuid@host:port?alterID=num#priority=200\n") fmt.Fprintf(os.Stderr, " vmess://[security:]uuid@host:port?alterID=num#priority=200\n")
fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "\n")

View File

@ -129,7 +129,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) (server
// 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
if strings.Contains(dialer.Addr(), qname) { if strings.Contains(dialer.Addr(), qname) {
dialer = proxy.Direct dialer = proxy.Default
} }
// If client uses udp and no forwarders specified, use udp // If client uses udp and no forwarders specified, use udp

View File

@ -45,7 +45,7 @@ func DialerFromURL(s string, dialer Dialer) (Dialer, error) {
} }
if dialer == nil { if dialer == nil {
dialer = Direct dialer = Default
} }
c, ok := dialerMap[strings.ToLower(u.Scheme)] c, ok := dialerMap[strings.ToLower(u.Scheme)]

View File

@ -6,20 +6,33 @@ import (
"github.com/nadoo/glider/common/log" "github.com/nadoo/glider/common/log"
) )
// direct proxy
type direct struct{}
// Direct proxy // Direct proxy
var Direct = &direct{} type Direct struct {
*net.Dialer
}
func (d *direct) Addr() string { return "DIRECT" } // Default dialer
var Default = &Direct{Dialer: &net.Dialer{}}
func (d *direct) Dial(network, addr string) (net.Conn, error) { // NewDirect returns a Direct dialer
func NewDirect(localip string) *Direct {
d := &net.Dialer{LocalAddr: &net.TCPAddr{
IP: net.ParseIP(localip),
Port: 0,
}}
return &Direct{Dialer: d}
}
// Addr returns forwarder's address
func (d *Direct) Addr() string { return "DIRECT" }
// Dial connects to the address addr on the network net
func (d *Direct) Dial(network, addr string) (net.Conn, error) {
if network == "uot" { if network == "uot" {
network = "udp" network = "udp"
} }
c, err := net.Dial(network, addr) c, err := d.Dialer.Dial(network, addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -31,8 +44,9 @@ func (d *direct) Dial(network, addr string) (net.Conn, error) {
return c, err return c, err
} }
func (d *direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { // DialUDP connects to the given address
pc, err := net.ListenPacket(network, "") func (d *Direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
pc, err := net.ListenPacket(network, d.Dialer.LocalAddr.String())
if err != nil { if err != nil {
log.F("ListenPacket error: %s", err) log.F("ListenPacket error: %s", err)
return nil, nil, err return nil, nil, err
@ -42,4 +56,5 @@ func (d *direct) DialUDP(network, addr string) (net.PacketConn, net.Addr, error)
return pc, uAddr, err return pc, uAddr, err
} }
func (d *direct) NextDialer(dstAddr string) Dialer { return d } // NextDialer returns the next dialer
func (d *Direct) NextDialer(dstAddr string) Dialer { return d }

View File

@ -19,12 +19,19 @@ type Forwarder struct {
failures uint32 failures uint32
MaxFailures uint32 //maxfailures to set to Disabled MaxFailures uint32 //maxfailures to set to Disabled
latency int64 latency int64
localip string // local ip address
} }
// ForwarderFromURL parses `forward=` command value and returns a new forwarder // ForwarderFromURL parses `forward=` command value and returns a new forwarder
func ForwarderFromURL(s string) (f *Forwarder, err error) { func ForwarderFromURL(s string) (f *Forwarder, err error) {
f = &Forwarder{}
ss := strings.Split(s, "#") ss := strings.Split(s, "#")
var d Dialer if len(ss) > 1 {
err = f.parseOption(ss[1])
}
var d Dialer = NewDirect(f.localip)
for _, url := range strings.Split(ss[0], ",") { for _, url := range strings.Split(ss[0], ",") {
d, err = DialerFromURL(url, d) d, err = DialerFromURL(url, d)
if err != nil { if err != nil {
@ -32,19 +39,12 @@ func ForwarderFromURL(s string) (f *Forwarder, err error) {
} }
} }
f = NewForwarder(d) f.Dialer = d
if len(ss) > 1 { f.addr = d.Addr()
err = f.parseOption(ss[1])
}
return f, err return f, err
} }
// NewForwarder returns a new forwarder
func NewForwarder(dialer Dialer) *Forwarder {
return &Forwarder{Dialer: dialer, addr: dialer.Addr()}
}
func (f *Forwarder) parseOption(option string) error { func (f *Forwarder) parseOption(option string) error {
query, err := url.ParseQuery(option) query, err := url.ParseQuery(option)
if err != nil { if err != nil {
@ -58,6 +58,8 @@ func (f *Forwarder) parseOption(option string) error {
} }
f.Priority = int(priority) f.Priority = int(priority)
f.localip = query.Get("localip")
return err return err
} }

View File

@ -39,7 +39,7 @@ func ServerFromURL(s string, dialer Dialer) (Server, error) {
} }
if dialer == nil { if dialer == nil {
dialer = Direct dialer = Default
} }
c, ok := serverMap[strings.ToLower(u.Scheme)] c, ok := serverMap[strings.ToLower(u.Scheme)]

View File

@ -38,7 +38,7 @@ func NewDialer(s []string, c *Config) proxy.Dialer {
} }
if len(fwdrs) == 0 { if len(fwdrs) == 0 {
return proxy.Direct return proxy.Default
} }
if len(fwdrs) == 1 { if len(fwdrs) == 1 {