From 737b77981a862afef0a4853d89dd41aadf102c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=9F=E7=BF=BC?= Date: Mon, 31 Aug 2020 13:29:10 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=94=AF=E6=8C=81=E6=8C=87=E5=AE=9AIP?= =?UTF-8?q?=E5=87=BA=E5=8F=A3=EF=BC=8C=E5=8F=82=E6=95=B0=E4=B8=BAbind=3Dx.?= =?UTF-8?q?x.x.x=202.=E6=94=AF=E6=8C=81=E5=A4=9A=E7=BD=91=E5=8D=A1?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=EF=BC=8C=E5=85=A5=E5=8F=A3=E7=BD=91?= =?UTF-8?q?=E5=8D=A1=E4=BD=9C=E4=B8=BA=E5=87=BA=E5=8F=A3=E7=BD=91=E5=8D=A1?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chain.go | 23 +++++++++++++++++++---- forward.go | 20 +++++++++++++++++++- http.go | 8 ++++++++ http2.go | 8 ++++++++ node.go | 6 ++++++ relay.go | 14 ++++++++++++++ sni.go | 8 ++++++++ socks.go | 24 ++++++++++++++++++++++++ ss.go | 13 +++++++++++++ 9 files changed, 119 insertions(+), 5 deletions(-) diff --git a/chain.go b/chain.go index bedeb6f..a11bfc9 100644 --- a/chain.go +++ b/chain.go @@ -151,17 +151,24 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op } if route.IsEmpty() { + d := &net.Dialer{ + Timeout: timeout, + } switch network { + case "tcp", "tcp4", "tcp6": + d.LocalAddr = &net.TCPAddr{ + IP: options.BindAddr, + } case "udp", "udp4", "udp6": if address == "" { return net.ListenUDP(network, nil) } + d.LocalAddr = &net.UDPAddr{ + IP: options.BindAddr, + } default: } - d := &net.Dialer{ - Timeout: timeout, - // LocalAddr: laddr, // TODO: optional local address - } + return d.DialContext(ctx, network, ipAddr) } @@ -325,6 +332,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) { // ChainOptions holds options for Chain. type ChainOptions struct { Retries int + BindAddr net.IP //绑定地址 Timeout time.Duration Hosts *Hosts Resolver Resolver @@ -360,3 +368,10 @@ func ResolverChainOption(resolver Resolver) ChainOption { opts.Resolver = resolver } } + +// BindChainOption specifies tcp bind address used by Chain.Dial. +func BindChainOption(bindAddr net.IP) ChainOption { + return func(opts *ChainOptions) { + opts.BindAddr = bindAddr + } +} diff --git a/forward.go b/forward.go index 11ea0ae..cb81371 100644 --- a/forward.go +++ b/forward.go @@ -128,9 +128,17 @@ func (h *tcpDirectForwardHandler) Handle(conn net.Conn) { } } + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + bindAddr = conn.LocalAddr().(*net.TCPAddr).IP + }else { + bindAddr = h.options.Node.BindAddr + } cc, err = h.options.Chain.Dial(node.Addr, RetryChainOption(h.options.Retries), TimeoutChainOption(h.options.Timeout), + BindChainOption(bindAddr), ) if err != nil { log.Logf("[tcp] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err) @@ -197,7 +205,17 @@ func (h *udpDirectForwardHandler) Handle(conn net.Conn) { } } - cc, err := h.options.Chain.DialContext(context.Background(), "udp", node.Addr) + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + bindAddr = conn.LocalAddr().(*net.UDPAddr).IP + }else { + bindAddr = h.options.Node.BindAddr + } + cc, err := h.options.Chain.DialContext(context.Background(), + "udp", + node.Addr, + BindChainOption(bindAddr),) if err != nil { node.MarkDead() log.Logf("[udp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err) diff --git a/http.go b/http.go index 2027dc8..37c5fe9 100644 --- a/http.go +++ b/http.go @@ -261,10 +261,18 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) { continue } + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + bindAddr = conn.LocalAddr().(*net.TCPAddr).IP + }else { + bindAddr = h.options.Node.BindAddr + } cc, err = route.Dial(host, TimeoutChainOption(h.options.Timeout), HostsChainOption(h.options.Hosts), ResolverChainOption(h.options.Resolver), + BindChainOption(bindAddr), ) if err == nil { break diff --git a/http2.go b/http2.go index 1c3cf5a..24266b6 100644 --- a/http2.go +++ b/http2.go @@ -424,10 +424,18 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(&buf, "%s", host) log.Log("[route]", buf.String()) + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + bindAddr = net.ParseIP(laddr) + }else { + bindAddr = h.options.Node.BindAddr + } cc, err = route.Dial(host, TimeoutChainOption(h.options.Timeout), HostsChainOption(h.options.Hosts), ResolverChainOption(h.options.Resolver), + BindChainOption(bindAddr), ) if err == nil { break diff --git a/node.go b/node.go index f64afc4..2a8abe3 100644 --- a/node.go +++ b/node.go @@ -3,6 +3,7 @@ package gost import ( "errors" "fmt" + "net" "net/url" "strconv" "strings" @@ -22,6 +23,8 @@ type Node struct { Host string Protocol string Transport string + BindAddr net.IP // 绑定出口 + OutFromIn bool // 是否使用入口IP网卡作为出口网卡,只有当没有绑定出口时才有效 Remote string // remote address, used by tcp/udp port forwarding url *url.URL // raw url User *url.Userinfo @@ -54,12 +57,15 @@ func ParseNode(s string) (node Node, err error) { node = Node{ Addr: u.Host, Host: u.Host, + BindAddr: net.ParseIP(u.Query().Get("bind")), Remote: strings.Trim(u.EscapedPath(), "/"), Values: u.Query(), User: u.User, marker: &failMarker{}, url: u, } + outFromIn, _ := strconv.ParseBool(u.Query().Get("outFromIn")) + node.OutFromIn = outFromIn u.RawQuery = "" u.User = nil diff --git a/relay.go b/relay.go index be25c9c..63db30f 100644 --- a/relay.go +++ b/relay.go @@ -221,10 +221,24 @@ func (h *relayHandler) Handle(conn net.Conn) { } log.Logf("[relay] %s -> %s -> %s", conn.RemoteAddr(), conn.LocalAddr(), raddr) + + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP + if h.options.Node.BindAddr == nil { + switch addr := conn.LocalAddr().(type) { + case *net.TCPAddr: + bindAddr = addr.IP + case *net.UDPAddr: + bindAddr = addr.IP + } + }else { + bindAddr = h.options.Node.BindAddr + } cc, err = h.options.Chain.DialContext(ctx, network, raddr, RetryChainOption(h.options.Retries), TimeoutChainOption(h.options.Timeout), + BindChainOption(bindAddr), ) if err != nil { log.Logf("[relay] %s -> %s : %s", conn.RemoteAddr(), raddr, err) diff --git a/sni.go b/sni.go index e57d4a0..7189b27 100644 --- a/sni.go +++ b/sni.go @@ -151,10 +151,18 @@ func (h *sniHandler) Handle(conn net.Conn) { fmt.Fprintf(&buf, "%s", host) log.Log("[route]", buf.String()) + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + bindAddr = conn.LocalAddr().(*net.TCPAddr).IP + }else { + bindAddr = h.options.Node.BindAddr + } cc, err = route.Dial(host, TimeoutChainOption(h.options.Timeout), HostsChainOption(h.options.Hosts), ResolverChainOption(h.options.Resolver), + BindChainOption(bindAddr), ) if err == nil { break diff --git a/socks.go b/socks.go index 39a7a9e..70b3f9e 100644 --- a/socks.go +++ b/socks.go @@ -939,10 +939,24 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) { fmt.Fprintf(&buf, "%s", host) log.Log("[route]", buf.String()) + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + switch addr := conn.LocalAddr().(type) { + case *net.TCPAddr: + bindAddr = addr.IP + case *net.UDPAddr: + bindAddr = addr.IP + } + }else { + bindAddr = h.options.Node.BindAddr + } + cc, err = route.Dial(host, TimeoutChainOption(h.options.Timeout), HostsChainOption(h.options.Hosts), ResolverChainOption(h.options.Resolver), + BindChainOption(bindAddr), ) if err == nil { break @@ -1754,10 +1768,20 @@ func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) { fmt.Fprintf(&buf, "%s", addr) log.Log("[route]", buf.String()) + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + //socks4 只支持tcp + var bindAddr net.IP + if h.options.Node.BindAddr == nil { + bindAddr = conn.LocalAddr().(*net.TCPAddr).IP + }else { + bindAddr = h.options.Node.BindAddr + } + cc, err = route.Dial(addr, TimeoutChainOption(h.options.Timeout), HostsChainOption(h.options.Hosts), ResolverChainOption(h.options.Resolver), + BindChainOption(bindAddr), ) if err == nil { break diff --git a/ss.go b/ss.go index e3532fd..7ec25f9 100644 --- a/ss.go +++ b/ss.go @@ -181,10 +181,23 @@ func (h *shadowHandler) Handle(conn net.Conn) { fmt.Fprintf(&buf, "%s", host) log.Log("[route]", buf.String()) + //指定出口IP地址,没有绑定出口IP地址才考虑以入口网卡作为出口 + var bindAddr net.IP; + if h.options.Node.BindAddr == nil { + switch addr := conn.LocalAddr().(type) { + case *net.TCPAddr: + bindAddr = addr.IP + case *net.UDPAddr: + bindAddr = addr.IP + } + }else { + bindAddr = h.options.Node.BindAddr + } cc, err = route.Dial(host, TimeoutChainOption(h.options.Timeout), HostsChainOption(h.options.Hosts), ResolverChainOption(h.options.Resolver), + BindChainOption(bindAddr), ) if err == nil { break