Skip to content

Commit 6d83df3

Browse files
committed
Merge branch 'client-socks' of https://github.com/aus/chisel into red
2 parents c9b6bf9 + 0791425 commit 6d83df3

File tree

5 files changed

+46
-21
lines changed

5 files changed

+46
-21
lines changed

client/client.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"strings"
1212
"time"
1313

14+
"github.com/armon/go-socks5"
1415
"github.com/gorilla/websocket"
1516
"github.com/jpillora/backoff"
1617
"github.com/aus/chisel/share"
@@ -42,6 +43,7 @@ type Client struct {
4243
running bool
4344
runningc chan error
4445
connStats chshare.ConnStats
46+
socksServer *socks5.Server
4547
}
4648

4749
//NewClient creates a new client instance
@@ -68,11 +70,15 @@ func NewClient(config *Config) (*Client, error) {
6870
//swap to websockets scheme
6971
u.Scheme = strings.Replace(u.Scheme, "http", "ws", 1)
7072
shared := &chshare.Config{}
73+
createSocksServer := false
7174
for _, s := range config.Remotes {
7275
r, err := chshare.DecodeRemote(s)
7376
if err != nil {
7477
return nil, fmt.Errorf("Failed to decode remote '%s': %s", s, err)
7578
}
79+
if r.Socks && r.Reverse {
80+
createSocksServer = true
81+
}
7682
shared.Remotes = append(shared.Remotes, r)
7783
}
7884
config.shared = shared
@@ -102,6 +108,14 @@ func NewClient(config *Config) (*Client, error) {
102108
Timeout: 30 * time.Second,
103109
}
104110

111+
if createSocksServer {
112+
socksConfig := &socks5.Config{}
113+
client.socksServer, err = socks5.New(socksConfig)
114+
if err != nil {
115+
return nil, err
116+
}
117+
}
118+
105119
return client, nil
106120
}
107121

@@ -272,13 +286,24 @@ func (c *Client) Close() error {
272286
func (c *Client) connectStreams(chans <-chan ssh.NewChannel) {
273287
for ch := range chans {
274288
remote := string(ch.ExtraData())
289+
socks := remote == "socks"
290+
if socks && c.socksServer == nil {
291+
c.Debugf("Denied socks request, please enable client socks remote.")
292+
ch.Reject(ssh.Prohibited, "SOCKS5 is not enabled on the client")
293+
continue
294+
}
275295
stream, reqs, err := ch.Accept()
276296
if err != nil {
277297
c.Debugf("Failed to accept stream: %s", err)
278298
continue
279299
}
280300
go ssh.DiscardRequests(reqs)
281301
l := c.Logger.Fork("conn#%d", c.connStats.New())
282-
go chshare.HandleTCPStream(l, &c.connStats, stream, remote)
302+
if socks {
303+
go chshare.HandleSocksStream(l, c.socksServer, &c.connStats, stream)
304+
} else {
305+
go chshare.HandleTCPStream(l, &c.connStats, stream, remote)
306+
}
307+
283308
}
284309
}

main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ var clientHelp = `
224224
socks
225225
5000:socks
226226
R:2222:localhost:22
227+
R:socks
228+
R:5000:socks
227229
228230
When the chisel server has --socks5 enabled, remotes can
229231
specify "socks" in place of remote-host and remote-port.
@@ -235,6 +237,8 @@ var clientHelp = `
235237
be prefixed with R to denote that they are reversed. That
236238
is, the server will listen and accept connections, and they
237239
will be proxied through the client which specified the remote.
240+
Reverse remotes specifying "R:socks" will terminate a connection
241+
at the client's internal SOCKS5 proxy.
238242
239243
Options:
240244

server/handler.go

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package chserver
22

33
import (
44
"context"
5-
"io"
65
"net/http"
76
"strings"
87
"sync/atomic"
@@ -179,22 +178,9 @@ func (s *Server) handleSSHChannels(clientLog *chshare.Logger, chans <-chan ssh.N
179178
//handle stream type
180179
connID := s.connStats.New()
181180
if socks {
182-
go s.handleSocksStream(clientLog.Fork("socksconn#%d", connID), stream)
181+
go chshare.HandleSocksStream(clientLog.Fork("socksconn#%d", connID), s.socksServer, &s.connStats, stream)
183182
} else {
184183
go chshare.HandleTCPStream(clientLog.Fork("conn#%d", connID), &s.connStats, stream, remote)
185184
}
186185
}
187186
}
188-
189-
func (s *Server) handleSocksStream(l *chshare.Logger, src io.ReadWriteCloser) {
190-
conn := chshare.NewRWCConn(src)
191-
s.connStats.Open()
192-
l.Debugf("%s Opening", s.connStats)
193-
err := s.socksServer.ServeConn(conn)
194-
s.connStats.Close()
195-
if err != nil && !strings.HasSuffix(err.Error(), "EOF") {
196-
l.Debugf("%s: Closed (error: %s)", s.connStats, err)
197-
} else {
198-
l.Debugf("%s: Closed", s.connStats)
199-
}
200-
}

share/remote.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ func DecodeRemote(s string) (*Remote, error) {
4343
p := parts[i]
4444
//last part "socks"?
4545
if i == len(parts)-1 && p == "socks" {
46-
if reverse {
47-
// TODO allow reverse+socks by having client
48-
// automatically start local SOCKS5 server
49-
return nil, errors.New("'socks' incompatible with reverse port forwarding")
50-
}
5146
r.Socks = true
5247
continue
5348
}

share/ssh.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net"
1313
"strings"
1414

15+
"github.com/armon/go-socks5"
1516
"github.com/jpillora/sizestr"
1617
"golang.org/x/crypto/ssh"
1718
)
@@ -56,3 +57,17 @@ func HandleTCPStream(l *Logger, connStats *ConnStats, src io.ReadWriteCloser, re
5657
connStats.Close()
5758
l.Debugf("%s: Close (sent %s received %s)", connStats, sizestr.ToString(s), sizestr.ToString(r))
5859
}
60+
61+
func HandleSocksStream(l *Logger, server *socks5.Server, connStats *ConnStats, src io.ReadWriteCloser) {
62+
conn := NewRWCConn(src)
63+
connStats.Open()
64+
l.Debugf("%s Opening", connStats)
65+
err := server.ServeConn(conn)
66+
connStats.Close()
67+
68+
if err != nil && !strings.HasSuffix(err.Error(), "EOF") {
69+
l.Debugf("%s: Closed (error: %s)", connStats, err)
70+
} else {
71+
l.Debugf("%s: Closed", connStats)
72+
}
73+
}

0 commit comments

Comments
 (0)