Skip to content

Commit 8319238

Browse files
committed
added docs, improved logging (still need to write a proper logging library), minor bugs
1 parent 0334966 commit 8319238

File tree

11 files changed

+264
-134
lines changed

11 files changed

+264
-134
lines changed

README.md

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# chisel
22

3-
Chisel is TCP proxy tunnelled over HTTP and Websockets
4-
5-
![how it works](https://docs.google.com/drawings/d/1p53VWxzGNfy8rjr-mW8pvisJmhkoLl82vAgctO_6f1w/pub?w=960&h=720)
3+
Chisel is TCP proxy tunnelled over HTTP WebSockets. Similar to [crowbar](https://github.com/q3k/crowbar) though achieves **much** higher [performance](#Performance). **Warning** this is beta software.
64

75
### Install
86

@@ -11,46 +9,43 @@ Server
119
```
1210
$ go get -v github.com/jpillora/chisel/chiseld
1311
$ chiseld --help
14-
15-
Usage: chiseld [--host 0.0.0.0] [--port 8080] [--auth str]
16-
17-
host defines the HTTP listening host – the
18-
network interface (defaults to 0.0.0.0). You
19-
may also set the HOST environment variable.
20-
21-
port defines the HTTP listening port (defaults
22-
to 8080). You may also set the PORT environment
23-
variable.
24-
25-
auth specifies the exact authentication string
26-
the client must provide to attain access. You
27-
may also set the AUTH environment variable.
2812
```
2913

3014
Forwarder
3115

3216
```
3317
$ go get -v github.com/jpillora/chisel/chisel-forward
34-
$ chisel-forward --help
18+
```
3519

36-
Usage: chisel-forward [--auth str] server remote [remote] [remote] ...
20+
### Demo
3721

38-
where 'server' is the URL to the chiseld server
22+
A Heroku app is running `chiseld` on the public HTTP port. This app
23+
is also running a file server on 3000 (which is normally inaccessible
24+
due to Heroku's firewall). However, if we tunnel in with:
3925

40-
where 'remote' is a remote connection via the server, in the form
41-
example.com:3000 (which means http://0.0.0.0:3000 => http://example.com:3000)
42-
3000:google.com:80 (which means http://0.0.0.0:3000 => http://google.com:80)
26+
```
27+
$ chisel-forward --auth foobar https://chisel-demo.herokuapp.com/ 3000
4328
```
4429

30+
Then open [http://localhost:3000/](http://localhost:3000/), we should
31+
see a directory listing of this app's root.
32+
4533
### Usage
4634

35+
Both command-line programs have useful help text, see `chiseld --help` and `chisel-forward --help`.
36+
37+
Eventually, a programmatic API will be documented and available.
38+
39+
### Security
40+
41+
Currently, secure communications are attained by hosting your HTTP server behind a TLS proxy. Thereby upgrading your server to HTTPS. In the future, the server will allow your to pass in TLS credentials and make use of Go's TLS (HTTPS) server.
4742

4843
### Performance
4944

5045
With crowbar, I was getting extremely slow transfer times
5146

5247
```
53-
#tab 1 (basic file server)
48+
#tab 1 (local file server)
5449
$ serve -p 4000
5550
5651
#tab 2 (tunnel server)
@@ -65,9 +60,9 @@ $ time curl -s "127.0.0.1:3000/largefile.bin" > /dev/null
6560
74.74 real 2.37 user 6.74 sys
6661
```
6762

68-
Here, `largefile.bin` (~200MB) is transferred in 1m14s over localhost (also has high CPU utilisation).
63+
Here, `largefile.bin` (~200MB) is transferred in 1m14s (along with high CPU utilisation).
6964

70-
Enter `chisel`, lets swap in `chiseld` and `chisel-forward`:
65+
Enter `chisel`, lets swap in `chiseld` and `chisel-forward`
7166

7267
```
7368
#tab 2 (tunnel server)
@@ -77,14 +72,29 @@ $ chiseld --auth foo
7772
$ chisel-forward --auth foo http://localhost:8080 3000:4000
7873
2015/02/27 16:13:43 Connected to http://localhost:8080
7974
2015/02/27 16:13:43 Proxy 0.0.0.0:3000 => 0.0.0.0:4000 enabled
75+
```
8076

77+
And now we'll run the test again
78+
79+
```
8180
#tab 4 (transfer test)
8281
$ time curl -s "127.0.0.1:3000/largefile.bin" > /dev/null
8382
0.60 real 0.05 user 0.14 sys
8483
```
8584

8685
Here, the same file was transferred in 0.6s
8786

87+
### Overview
88+
89+
![overview](https://docs.google.com/drawings/d/1p53VWxzGNfy8rjr-mW8pvisJmhkoLl82vAgctO_6f1w/pub?w=960&h=720)
90+
91+
### Todo
92+
93+
* User file with list of whitelisted remotes
94+
* TLS server configuration
95+
* Expose a stats page for proxy throughput
96+
* Tests along with benchmarks
97+
8898
#### MIT License
8999

90100
Copyright © 2014 Jaime Pillora <[email protected]>

chisel-forward/client/client.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package client
33
import (
44
"errors"
55
"fmt"
6-
"log"
76
"net"
87
"net/url"
98
"regexp"
109
"strings"
10+
"sync"
11+
"time"
1112

1213
"github.com/hashicorp/yamux"
1314
"github.com/jpillora/chisel"
@@ -79,16 +80,27 @@ func (c *Client) Start() error {
7980
return err
8081
}
8182

83+
//closed state
8284
markClosed := make(chan bool)
83-
isClosed := false
85+
var o sync.Once
86+
closed := func() {
87+
close(markClosed)
88+
}
89+
go func() {
90+
for {
91+
if session.IsClosed() {
92+
o.Do(closed)
93+
break
94+
}
95+
time.Sleep(time.Second)
96+
}
97+
}()
8498

8599
//proxies all use this function
86100
openStream := func() (net.Conn, error) {
87101
stream, err := session.Open()
88102
if err != nil {
89-
if !isClosed {
90-
close(markClosed)
91-
}
103+
o.Do(closed)
92104
return nil, err
93105
}
94106
return stream, nil
@@ -101,9 +113,8 @@ func (c *Client) Start() error {
101113
c.proxies = append(c.proxies, proxy)
102114
}
103115

104-
log.Printf("Connected to %s\n", c.config.Server)
116+
fmt.Printf("Connected to %s\n", c.config.Server)
105117
<-markClosed
106-
isClosed = true
107-
log.Printf("Disconnected\n")
118+
fmt.Printf("Disconnected\n")
108119
return nil
109120
}

chisel-forward/client/proxy.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package client
22

33
import (
44
"encoding/binary"
5-
"log"
65
"net"
76

87
"github.com/jpillora/chisel"
@@ -27,15 +26,15 @@ func (p *Proxy) start() {
2726

2827
l, err := net.Listen("tcp4", p.remote.LocalHost+":"+p.remote.LocalPort)
2928
if err != nil {
30-
log.Printf("Proxy %s failed: %s", p.remote, err)
29+
chisel.Printf("Proxy [%d] Failed to start: %s", p.id, err)
3130
return
3231
}
3332

34-
log.Printf("Proxy %s enabled", p.remote)
33+
chisel.Printf("Proxy [%d] Enabled (%s)", p.id, p.remote)
3534
for {
3635
src, err := l.Accept()
3736
if err != nil {
38-
log.Println(err)
37+
chisel.Printf("%s", err)
3938
return
4039
}
4140
go p.accept(src)
@@ -46,11 +45,11 @@ func (p *Proxy) accept(src net.Conn) {
4645
p.count++
4746
c := p.count
4847

49-
log.Printf("[#%d] accept conn %d", p.id, c)
48+
chisel.Printf("Proxy [%d] Connection [%d] Open", p.id, c)
5049

5150
dst, err := p.openStream()
5251
if err != nil {
53-
log.Println(err)
52+
chisel.Printf("%s", err)
5453
return
5554
}
5655

@@ -60,7 +59,7 @@ func (p *Proxy) accept(src net.Conn) {
6059
dst.Write(b)
6160

6261
//then pipe
63-
chisel.Pipe(src, dst)
62+
s, r := chisel.Pipe(src, dst)
6463

65-
log.Printf("[#%d] close conn %d", p.id, c)
64+
chisel.Printf("Proxy [%d] Connection [%d] Closed (sent %d received %d)", p.id, c, s, r)
6665
}

chisel-forward/main.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,34 @@ import (
66
"log"
77
"os"
88

9+
"github.com/jpillora/chisel"
910
"github.com/jpillora/chisel/chisel-forward/client"
1011
)
1112

1213
const help = `
1314
14-
Usage: chisel-forward [--auth str] server remote [remote] [remote] ...
15+
Usage: chisel-forward [--auth AUTH] server remote [remote] [remote] ...
1516
16-
where 'server' is the URL to the chiseld server
17+
auth specifies the optional authenication string
18+
used by the server.
1719
18-
where 'remote' is a remote connection via the server, in the form
19-
example.com:3000 (which means http://0.0.0.0:3000 => http://example.com:3000)
20-
3000:google.com:80 (which means http://0.0.0.0:3000 => http://google.com:80)
20+
server is the URL to the chiseld server.
21+
22+
remote is a remote connection via the server, which
23+
comes in the form:
24+
<local-host>:<local-port>:<remote-host>:<remote-port>
25+
26+
* Only remote-port is required.
27+
* local-port defaults to remote-port.
28+
* local-host defaults to 0.0.0.0 (all interfaces).
29+
* remote-host defaults to localhost.
30+
31+
example remotes
32+
33+
3000
34+
example.com:3000
35+
3000:google.com:80
36+
192.168.0.5:3000:google.com:80
2137
2238
Read more:
2339
https://github.com/jpillora/chisel
@@ -38,6 +54,8 @@ func main() {
3854
server := args[0]
3955
remotes := args[1:]
4056

57+
chisel.Debug = true
58+
4159
c, err := client.NewClient(*auth, server, remotes)
4260
if err != nil {
4361
log.Fatal(err)

chiseld/main.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package main
33
import (
44
"flag"
55
"fmt"
6+
"log"
67
"os"
78

9+
"github.com/jpillora/chisel"
810
"github.com/jpillora/chisel/chiseld/server"
911
)
1012

1113
const help = `
12-
Usage: chiseld [--host 0.0.0.0] [--port 8080] [--auth str]
14+
Usage: chiseld [--host 0.0.0.0] [--port 8080] [--auth AUTH] [--proxy PROXY]
1315
1416
host defines the HTTP listening host – the
1517
network interface (defaults to 0.0.0.0). You
@@ -23,6 +25,10 @@ const help = `
2325
the client must provide to attain access. You
2426
may also set the AUTH environment variable.
2527
28+
proxy specifies the default proxy target to use
29+
when chiseld receives a normal HTTP request. You
30+
may also set the PROXY environment variable.
31+
2632
Read more:
2733
https://github.com/jpillora/chisel
2834
@@ -33,6 +39,7 @@ func main() {
3339
hostf := flag.String("host", "", "")
3440
portf := flag.String("port", "", "")
3541
authf := flag.String("auth", "", "")
42+
proxyf := flag.String("proxy", "", "")
3643
flag.Usage = func() {
3744
fmt.Fprintf(os.Stderr, help)
3845
os.Exit(1)
@@ -60,5 +67,19 @@ func main() {
6067
auth = os.Getenv("AUTH")
6168
}
6269

63-
server.NewServer(auth).Start(host, port)
70+
proxy := *proxyf
71+
if proxy == "" {
72+
proxy = os.Getenv("PROXY")
73+
}
74+
75+
chisel.Debug = true
76+
77+
s, err := server.NewServer(auth, proxy)
78+
if err != nil {
79+
log.Fatal(err)
80+
}
81+
err = s.Start(host, port)
82+
if err != nil {
83+
log.Fatal(err)
84+
}
6485
}

chiseld/server/endpoint.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,47 @@
11
package server
22

33
import (
4-
"log"
54
"net"
65

76
"github.com/jpillora/chisel"
87
)
98

109
type Endpoint struct {
11-
id int
12-
count int
13-
addr string
14-
session chan net.Conn
10+
w *WebSocket
11+
id int
12+
count int
13+
addr string
14+
sessions chan net.Conn
1515
}
1616

17-
func NewEndpoint(id int, addr string) *Endpoint {
17+
func NewEndpoint(w *WebSocket, id int, addr string) *Endpoint {
1818
return &Endpoint{
19-
id: id,
20-
addr: addr,
21-
session: make(chan net.Conn),
19+
w: w,
20+
id: id,
21+
addr: addr,
22+
sessions: make(chan net.Conn),
2223
}
2324
}
2425

2526
func (e *Endpoint) start() {
27+
chisel.Printf("Websocket [%d] Proxy [%d] Activate (%s)", e.w.id, e.id, e.addr)
2628
//waiting for incoming streams
27-
for stream := range e.session {
29+
for stream := range e.sessions {
2830
go e.pipe(stream)
2931
}
3032
}
3133

3234
func (e *Endpoint) pipe(src net.Conn) {
3335
dst, err := net.Dial("tcp", e.addr)
3436
if err != nil {
35-
log.Println(err)
37+
chisel.Printf("%s", err)
3638
src.Close()
3739
return
3840
}
3941

4042
e.count++
4143
c := e.count
42-
log.Printf("[#%d] openned connection %d", e.id, c)
44+
chisel.Printf("Websocket [%d] Proxy [%d] Connection [%d] Open", e.w.id, e.id, c)
4345
chisel.Pipe(src, dst)
44-
log.Printf("[#%d] closed connection %d", e.id, c)
46+
chisel.Printf("Websocket [%d] Proxy [%d] Connection [%d] Closed", e.w.id, e.id, c)
4547
}

0 commit comments

Comments
 (0)