1.支持指定IP出口,参数为bind=x.x.x.x

2.支持多网卡服务器,入口网卡作为出口网卡。
This commit is contained in:
赟翼 2020-08-31 13:29:10 +08:00
parent 2707a8f0a9
commit 737b77981a
9 changed files with 119 additions and 5 deletions

View File

@ -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
}
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

8
sni.go
View File

@ -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

View File

@ -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

13
ss.go
View File

@ -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