1.支持指定IP出口,参数为bind=x.x.x.x
2.支持多网卡服务器,入口网卡作为出口网卡。
This commit is contained in:
parent
2707a8f0a9
commit
737b77981a
23
chain.go
23
chain.go
@ -151,17 +151,24 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op
|
|||||||
}
|
}
|
||||||
|
|
||||||
if route.IsEmpty() {
|
if route.IsEmpty() {
|
||||||
|
d := &net.Dialer{
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
switch network {
|
switch network {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
|
d.LocalAddr = &net.TCPAddr{
|
||||||
|
IP: options.BindAddr,
|
||||||
|
}
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
if address == "" {
|
if address == "" {
|
||||||
return net.ListenUDP(network, nil)
|
return net.ListenUDP(network, nil)
|
||||||
}
|
}
|
||||||
|
d.LocalAddr = &net.UDPAddr{
|
||||||
|
IP: options.BindAddr,
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
d := &net.Dialer{
|
|
||||||
Timeout: timeout,
|
|
||||||
// LocalAddr: laddr, // TODO: optional local address
|
|
||||||
}
|
|
||||||
return d.DialContext(ctx, network, ipAddr)
|
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.
|
// ChainOptions holds options for Chain.
|
||||||
type ChainOptions struct {
|
type ChainOptions struct {
|
||||||
Retries int
|
Retries int
|
||||||
|
BindAddr net.IP //绑定地址
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
Hosts *Hosts
|
Hosts *Hosts
|
||||||
Resolver Resolver
|
Resolver Resolver
|
||||||
@ -360,3 +368,10 @@ func ResolverChainOption(resolver Resolver) ChainOption {
|
|||||||
opts.Resolver = resolver
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
20
forward.go
20
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,
|
cc, err = h.options.Chain.Dial(node.Addr,
|
||||||
RetryChainOption(h.options.Retries),
|
RetryChainOption(h.options.Retries),
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[tcp] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
|
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 {
|
if err != nil {
|
||||||
node.MarkDead()
|
node.MarkDead()
|
||||||
log.Logf("[udp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
|
log.Logf("[udp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
|
||||||
|
8
http.go
8
http.go
@ -261,10 +261,18 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
|
|||||||
continue
|
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,
|
cc, err = route.Dial(host,
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
HostsChainOption(h.options.Hosts),
|
HostsChainOption(h.options.Hosts),
|
||||||
ResolverChainOption(h.options.Resolver),
|
ResolverChainOption(h.options.Resolver),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
|
8
http2.go
8
http2.go
@ -424,10 +424,18 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintf(&buf, "%s", host)
|
fmt.Fprintf(&buf, "%s", host)
|
||||||
log.Log("[route]", buf.String())
|
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,
|
cc, err = route.Dial(host,
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
HostsChainOption(h.options.Hosts),
|
HostsChainOption(h.options.Hosts),
|
||||||
ResolverChainOption(h.options.Resolver),
|
ResolverChainOption(h.options.Resolver),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
|
6
node.go
6
node.go
@ -3,6 +3,7 @@ package gost
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -22,6 +23,8 @@ type Node struct {
|
|||||||
Host string
|
Host string
|
||||||
Protocol string
|
Protocol string
|
||||||
Transport string
|
Transport string
|
||||||
|
BindAddr net.IP // 绑定出口
|
||||||
|
OutFromIn bool // 是否使用入口IP网卡作为出口网卡,只有当没有绑定出口时才有效
|
||||||
Remote string // remote address, used by tcp/udp port forwarding
|
Remote string // remote address, used by tcp/udp port forwarding
|
||||||
url *url.URL // raw url
|
url *url.URL // raw url
|
||||||
User *url.Userinfo
|
User *url.Userinfo
|
||||||
@ -54,12 +57,15 @@ func ParseNode(s string) (node Node, err error) {
|
|||||||
node = Node{
|
node = Node{
|
||||||
Addr: u.Host,
|
Addr: u.Host,
|
||||||
Host: u.Host,
|
Host: u.Host,
|
||||||
|
BindAddr: net.ParseIP(u.Query().Get("bind")),
|
||||||
Remote: strings.Trim(u.EscapedPath(), "/"),
|
Remote: strings.Trim(u.EscapedPath(), "/"),
|
||||||
Values: u.Query(),
|
Values: u.Query(),
|
||||||
User: u.User,
|
User: u.User,
|
||||||
marker: &failMarker{},
|
marker: &failMarker{},
|
||||||
url: u,
|
url: u,
|
||||||
}
|
}
|
||||||
|
outFromIn, _ := strconv.ParseBool(u.Query().Get("outFromIn"))
|
||||||
|
node.OutFromIn = outFromIn
|
||||||
|
|
||||||
u.RawQuery = ""
|
u.RawQuery = ""
|
||||||
u.User = nil
|
u.User = nil
|
||||||
|
14
relay.go
14
relay.go
@ -221,10 +221,24 @@ func (h *relayHandler) Handle(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Logf("[relay] %s -> %s -> %s", conn.RemoteAddr(), conn.LocalAddr(), raddr)
|
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,
|
cc, err = h.options.Chain.DialContext(ctx,
|
||||||
network, raddr,
|
network, raddr,
|
||||||
RetryChainOption(h.options.Retries),
|
RetryChainOption(h.options.Retries),
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[relay] %s -> %s : %s", conn.RemoteAddr(), raddr, err)
|
log.Logf("[relay] %s -> %s : %s", conn.RemoteAddr(), raddr, err)
|
||||||
|
8
sni.go
8
sni.go
@ -151,10 +151,18 @@ func (h *sniHandler) Handle(conn net.Conn) {
|
|||||||
fmt.Fprintf(&buf, "%s", host)
|
fmt.Fprintf(&buf, "%s", host)
|
||||||
log.Log("[route]", buf.String())
|
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,
|
cc, err = route.Dial(host,
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
HostsChainOption(h.options.Hosts),
|
HostsChainOption(h.options.Hosts),
|
||||||
ResolverChainOption(h.options.Resolver),
|
ResolverChainOption(h.options.Resolver),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
|
24
socks.go
24
socks.go
@ -939,10 +939,24 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
|
|||||||
fmt.Fprintf(&buf, "%s", host)
|
fmt.Fprintf(&buf, "%s", host)
|
||||||
log.Log("[route]", buf.String())
|
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,
|
cc, err = route.Dial(host,
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
HostsChainOption(h.options.Hosts),
|
HostsChainOption(h.options.Hosts),
|
||||||
ResolverChainOption(h.options.Resolver),
|
ResolverChainOption(h.options.Resolver),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
@ -1754,10 +1768,20 @@ func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) {
|
|||||||
fmt.Fprintf(&buf, "%s", addr)
|
fmt.Fprintf(&buf, "%s", addr)
|
||||||
log.Log("[route]", buf.String())
|
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,
|
cc, err = route.Dial(addr,
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
HostsChainOption(h.options.Hosts),
|
HostsChainOption(h.options.Hosts),
|
||||||
ResolverChainOption(h.options.Resolver),
|
ResolverChainOption(h.options.Resolver),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
|
13
ss.go
13
ss.go
@ -181,10 +181,23 @@ func (h *shadowHandler) Handle(conn net.Conn) {
|
|||||||
fmt.Fprintf(&buf, "%s", host)
|
fmt.Fprintf(&buf, "%s", host)
|
||||||
log.Log("[route]", buf.String())
|
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,
|
cc, err = route.Dial(host,
|
||||||
TimeoutChainOption(h.options.Timeout),
|
TimeoutChainOption(h.options.Timeout),
|
||||||
HostsChainOption(h.options.Hosts),
|
HostsChainOption(h.options.Hosts),
|
||||||
ResolverChainOption(h.options.Resolver),
|
ResolverChainOption(h.options.Resolver),
|
||||||
|
BindChainOption(bindAddr),
|
||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
|
Loading…
Reference in New Issue
Block a user