Skip to content

Commit

Permalink
SOCKS5: add mux-bind request CMD
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengrui committed Mar 18, 2018
1 parent 22a4d48 commit 2b56558
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 59 deletions.
84 changes: 32 additions & 52 deletions cmd/gost/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"net/url"
"os"
"runtime"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -117,7 +116,7 @@ func (r *route) initChain() (*gost.Chain, error) {
ngroup.AddNode(nodes...)

// parse peer nodes if exists
peerCfg, err := loadPeerConfig(nodes[0].Values.Get("peer"))
peerCfg, err := loadPeerConfig(nodes[0].Get("peer"))
if err != nil {
log.Log(err)
}
Expand Down Expand Up @@ -156,7 +155,7 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
return
}

users, err := parseUsers(node.Values.Get("secrets"))
users, err := parseUsers(node.Get("secrets"))
if err != nil {
return
}
Expand All @@ -168,20 +167,20 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
serverName = "localhost" // default server name
}

rootCAs, err := loadCA(node.Values.Get("ca"))
rootCAs, err := loadCA(node.Get("ca"))
if err != nil {
return
}
tlsCfg := &tls.Config{
ServerName: serverName,
InsecureSkipVerify: !toBool(node.Values.Get("secure")),
InsecureSkipVerify: !node.GetBool("secure"),
RootCAs: rootCAs,
}
wsOpts := &gost.WSOptions{}
wsOpts.EnableCompression = toBool(node.Values.Get("compression"))
wsOpts.ReadBufferSize, _ = strconv.Atoi(node.Values.Get("rbuf"))
wsOpts.WriteBufferSize, _ = strconv.Atoi(node.Values.Get("wbuf"))
wsOpts.UserAgent = node.Values.Get("agent")
wsOpts.EnableCompression = node.GetBool("compression")
wsOpts.ReadBufferSize = node.GetInt("rbuf")
wsOpts.WriteBufferSize = node.GetInt("wbuf")
wsOpts.UserAgent = node.Get("agent")

var tr gost.Transporter
switch node.Transport {
Expand All @@ -203,7 +202,7 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
return nil, errors.New("KCP must be the first node in the proxy chain")
}
*/
config, err := parseKCPConfig(node.Values.Get("c"))
config, err := parseKCPConfig(node.Get("c"))
if err != nil {
return nil, err
}
Expand All @@ -222,16 +221,13 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
*/
config := &gost.QUICConfig{
TLSConfig: tlsCfg,
KeepAlive: toBool(node.Values.Get("keepalive")),
KeepAlive: node.GetBool("keepalive"),
}

timeout, _ := strconv.Atoi(node.Values.Get("timeout"))
config.Timeout = time.Duration(timeout) * time.Second
config.Timeout = time.Duration(node.GetInt("timeout")) * time.Second
config.IdleTimeout = time.Duration(node.GetInt("idle")) * time.Second

idle, _ := strconv.Atoi(node.Values.Get("idle"))
config.IdleTimeout = time.Duration(idle) * time.Second

if key := node.Values.Get("key"); key != "" {
if key := node.Get("key"); key != "" {
sum := sha256.Sum256([]byte(key))
config.Key = sum[:]
}
Expand Down Expand Up @@ -274,36 +270,34 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
case "forward":
connector = gost.ForwardConnector()
case "sni":
connector = gost.SNIConnector(node.Values.Get("host"))
connector = gost.SNIConnector(node.Get("host"))
case "http":
fallthrough
default:
node.Protocol = "http" // default protocol is HTTP
connector = gost.HTTPConnector(node.User)
}

timeout, _ := strconv.Atoi(node.Values.Get("timeout"))
timeout := node.GetInt("timeout")
node.DialOptions = append(node.DialOptions,
gost.TimeoutDialOption(time.Duration(timeout)*time.Second),
)

interval, _ := strconv.Atoi(node.Values.Get("ping"))
retry, _ := strconv.Atoi(node.Values.Get("retry"))
handshakeOptions := []gost.HandshakeOption{
gost.AddrHandshakeOption(node.Addr),
gost.HostHandshakeOption(node.Host),
gost.UserHandshakeOption(node.User),
gost.TLSConfigHandshakeOption(tlsCfg),
gost.IntervalHandshakeOption(time.Duration(interval) * time.Second),
gost.IntervalHandshakeOption(time.Duration(node.GetInt("ping")) * time.Second),
gost.TimeoutHandshakeOption(time.Duration(timeout) * time.Second),
gost.RetryHandshakeOption(retry),
gost.RetryHandshakeOption(node.GetInt("retry")),
}
node.Client = &gost.Client{
Connector: connector,
Transporter: tr,
}

ips := parseIP(node.Values.Get("ip"), sport)
ips := parseIP(node.Get("ip"), sport)
for _, ip := range ips {
node.Addr = ip
node.HandshakeOptions = append(handshakeOptions, gost.AddrHandshakeOption(ip))
Expand All @@ -328,23 +322,23 @@ func (r *route) serve() error {
if err != nil {
return err
}
users, err := parseUsers(node.Values.Get("secrets"))
users, err := parseUsers(node.Get("secrets"))
if err != nil {
return err
}
if node.User != nil {
users = append(users, node.User)
}
certFile, keyFile := node.Values.Get("cert"), node.Values.Get("key")
certFile, keyFile := node.Get("cert"), node.Get("key")
tlsCfg, err := tlsConfig(certFile, keyFile)
if err != nil && certFile != "" && keyFile != "" {
return err
}

wsOpts := &gost.WSOptions{}
wsOpts.EnableCompression = toBool(node.Values.Get("compression"))
wsOpts.ReadBufferSize, _ = strconv.Atoi(node.Values.Get("rbuf"))
wsOpts.WriteBufferSize, _ = strconv.Atoi(node.Values.Get("wbuf"))
wsOpts.EnableCompression = node.GetBool("compression")
wsOpts.ReadBufferSize = node.GetInt("rbuf")
wsOpts.WriteBufferSize = node.GetInt("wbuf")

var ln gost.Listener
switch node.Transport {
Expand All @@ -353,7 +347,7 @@ func (r *route) serve() error {
case "mtls":
ln, err = gost.MTLSListener(node.Addr, tlsCfg)
case "ws":
wsOpts.WriteBufferSize, _ = strconv.Atoi(node.Values.Get("wbuf"))
wsOpts.WriteBufferSize = node.GetInt("wbuf")
ln, err = gost.WSListener(node.Addr, wsOpts)
case "mws":
ln, err = gost.MWSListener(node.Addr, wsOpts)
Expand All @@ -362,7 +356,7 @@ func (r *route) serve() error {
case "mwss":
ln, err = gost.MWSSListener(node.Addr, tlsCfg, wsOpts)
case "kcp":
config, er := parseKCPConfig(node.Values.Get("c"))
config, er := parseKCPConfig(node.Get("c"))
if er != nil {
return er
}
Expand All @@ -380,15 +374,12 @@ func (r *route) serve() error {
case "quic":
config := &gost.QUICConfig{
TLSConfig: tlsCfg,
KeepAlive: toBool(node.Values.Get("keepalive")),
KeepAlive: node.GetBool("keepalive"),
}
timeout, _ := strconv.Atoi(node.Values.Get("timeout"))
config.Timeout = time.Duration(timeout) * time.Second

idle, _ := strconv.Atoi(node.Values.Get("idle"))
config.IdleTimeout = time.Duration(idle) * time.Second
config.Timeout = time.Duration(node.GetInt("timeout")) * time.Second
config.IdleTimeout = time.Duration(node.GetInt("idle")) * time.Second

if key := node.Values.Get("key"); key != "" {
if key := node.Get("key"); key != "" {
sum := sha256.Sum256([]byte(key))
config.Key = sum[:]
}
Expand All @@ -415,14 +406,11 @@ func (r *route) serve() error {
}
ln, err = gost.TCPRemoteForwardListener(node.Addr, chain)
case "udp":
ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
ln, err = gost.UDPDirectForwardListener(node.Addr, time.Duration(ttl)*time.Second)
ln, err = gost.UDPDirectForwardListener(node.Addr, time.Duration(node.GetInt("ttl"))*time.Second)
case "rudp":
ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
ln, err = gost.UDPRemoteForwardListener(node.Addr, chain, time.Duration(ttl)*time.Second)
ln, err = gost.UDPRemoteForwardListener(node.Addr, chain, time.Duration(node.GetInt("ttl"))*time.Second)
case "ssu":
ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
ln, err = gost.ShadowUDPListener(node.Addr, node.User, time.Duration(ttl)*time.Second)
ln, err = gost.ShadowUDPListener(node.Addr, node.User, time.Duration(node.GetInt("ttl"))*time.Second)
case "obfs4":
if err = gost.Obfs4Init(node, true); err != nil {
return err
Expand Down Expand Up @@ -572,14 +560,6 @@ func (l *stringList) Set(value string) error {
return nil
}

func toBool(s string) bool {
if b, _ := strconv.ParseBool(s); b {
return b
}
n, _ := strconv.Atoi(s)
return n > 0
}

func parseKCPConfig(configFile string) (*gost.KCPConfig, error) {
if configFile == "" {
return nil, nil
Expand Down
23 changes: 19 additions & 4 deletions forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,13 @@ func (c *udpServerConn) SetWriteDeadline(t time.Time) error {
}

type tcpRemoteForwardListener struct {
addr net.Addr
chain *Chain
ln net.Listener
closed chan struct{}
addr net.Addr
chain *Chain
ln net.Listener
session *muxSession
once sync.Once
mutex sync.Mutex
closed chan struct{}
}

// TCPRemoteForwardListener creates a Listener for TCP remote port forwarding server.
Expand Down Expand Up @@ -474,6 +477,10 @@ func (l *tcpRemoteForwardListener) accept() (conn net.Conn, err error) {
if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" {
conn, err = l.chain.Dial(l.addr.String())
} else if lastNode.Protocol == "socks5" {
if lastNode.GetBool("mbind") {
return l.muxAccept() // multiplexing support for binding.
}

cc, er := l.chain.Conn()
if er != nil {
return nil, er
Expand All @@ -494,6 +501,14 @@ func (l *tcpRemoteForwardListener) accept() (conn net.Conn, err error) {
return
}

func (l *tcpRemoteForwardListener) muxAccept() (conn net.Conn, err error) {
l.mutex.Lock()
defer l.mutex.Unlock()


return nil, nil
}

func (l *tcpRemoteForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
conn, err := socks5Handshake(conn, l.chain.LastNode().User)
if err != nil {
Expand Down
18 changes: 18 additions & 0 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gost
import (
"fmt"
"net/url"
"strconv"
"strings"
"sync/atomic"
"time"
Expand Down Expand Up @@ -141,6 +142,23 @@ func (node *Node) Clone() Node {
}
}

// Get returns node parameter specified by key.
func (node *Node) Get(key string) string {
return node.Values.Get(key)
}

// GetBool likes Get, but convert parameter value to bool.
func (node *Node) GetBool(key string) bool {
b, _ := strconv.ParseBool(node.Values.Get(key))
return b
}

// GetInt likes Get, but convert parameter value to int.
func (node *Node) GetInt(key string) int {
n, _ := strconv.Atoi(node.Values.Get(key))
return n
}

func (node *Node) String() string {
return fmt.Sprintf("%d@%s", node.ID, node.Addr)
}
Expand Down
Loading

0 comments on commit 2b56558

Please sign in to comment.