Skip to content

Commit

Permalink
Sync with upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
OS-kiranmalsetty committed Sep 5, 2023
1 parent b364cdd commit 97263d9
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 151 deletions.
1 change: 1 addition & 0 deletions .github/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ builds:
- mips64le
- s390x
goarm:
- 5
- 6
- 7
gomips:
Expand Down
56 changes: 38 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,23 @@ $ chisel server --help
--port, -p, Defines the HTTP listening port (defaults to the environment
variable PORT and fallsback to port 8080).
--key, An optional string to seed the generation of a ECDSA public
--key, (deprecated use --keygen and --keyfile instead)
An optional string to seed the generation of a ECDSA public
and private key pair. All communications will be secured using this
key pair. Share the subsequent fingerprint with clients to enable detection
of man-in-the-middle attacks (defaults to the CHISEL_KEY environment
variable, otherwise a new key is generate each run).
--keygen, A path to write a newly generated PEM-encoded SSH private key file.
If users depend on your --key fingerprint, you may also include your --key to
output your existing key. Use - (dash) to output the generated key to stdout.
--keyfile, An optional path to a PEM-encoded SSH private key. When
this flag is set, the --key option is ignored, and the provided private key
is used to secure all communications. (defaults to the CHISEL_KEY_FILE
environment variable). Since ECDSA keys are short, you may also set keyfile
to an inline base64 private key (e.g. chisel server --keygen - | base64).
--authfile, An optional path to a users.json file. This file should
be an object with users defined like:
{
Expand Down Expand Up @@ -300,6 +311,9 @@ $ chisel client --help
--hostname, Optionally set the 'Host' header (defaults to the host
found in the server url).
--sni, Override the ServerName when using TLS (defaults to the
hostname).
--tls-ca, An optional root certificate bundle used to verify the
chisel server. Only valid when connecting to the server with
"https" or "wss". By default, the operating system CAs will be used.
Expand Down Expand Up @@ -341,38 +355,42 @@ $ chisel client --help

### Security

Encryption is always enabled. When you start up a chisel server, it will generate an in-memory ECDSA public/private key pair. The public key fingerprint (base64 encoded SHA256) will be displayed as the server starts. Instead of generating a random key, the server may optionally specify a key seed, using the `--key` option, which will be used to seed the key generation. When clients connect, they will also display the server's public key fingerprint. The client can force a particular fingerprint using the `--fingerprint` option. See the `--help` above for more information.
Encryption is always enabled. When you start up a chisel server, it will generate an in-memory ECDSA public/private key pair. The public key fingerprint (base64 encoded SHA256) will be displayed as the server starts. Instead of generating a random key, the server may optionally specify a key file, using the `--keyfile` option. When clients connect, they will also display the server's public key fingerprint. The client can force a particular fingerprint using the `--fingerprint` option. See the `--help` above for more information.

### Authentication

Using the `--authfile` option, the server may optionally provide a `user.json` configuration file to create a list of accepted users. The client then authenticates using the `--auth` option. See [users.json](example/users.json) for an example authentication configuration file. See the `--help` above for more information.

Internally, this is done using the _Password_ authentication method provided by SSH. Learn more about `crypto/ssh` here http://blog.gopheracademy.com/go-and-ssh/.

### SOCKS5 Guide
### SOCKS5 Guide with Docker

1. Print a new private key to the terminal

```sh
chisel server --keygen -
# or save it to disk --keygen /path/to/mykey
```

1. Start your chisel server

```sh
docker run \
--name chisel -p 9312:9312 \
-d --restart always \
jpillora/chisel server -p 9312 --socks5 --key supersecret
```
```sh
jpillora/chisel server --keyfile '<ck-base64 string or file path>' -p 9312 --socks5
```

2. Connect your chisel client (using server's fingerprint)
1. Connect your chisel client (using server's fingerprint)
```sh
chisel client --fingerprint 'rHb55mcxf6vSckL2AezFV09rLs7pfPpavVu++MF7AhQ=' <server-address>:9312 socks
```
```sh
chisel client --fingerprint '<see server output>' <server-address>:9312 socks
```
3. Point your SOCKS5 clients (e.g. OS/Browser) to:
1. Point your SOCKS5 clients (e.g. OS/Browser) to:
```
<client-address>:1080
```
```
<client-address>:1080
```
4. Now you have an encrypted, authenticated SOCKS5 connection over HTTP
1. Now you have an encrypted, authenticated SOCKS5 connection over HTTP
#### Caveats
Expand Down Expand Up @@ -403,6 +421,8 @@ Since WebSockets support is required:
- `1.5` - Added reverse SOCKS support (by @aus)
- `1.6` - Added client stdio support (by @BoleynSu)
- `1.7` - Added UDP support
- `1.8` - Move to a `scratch`Docker image
- `1.9` - Switch from `--key` seed to P256 key strings with `--key{gen,file}` + bump to Go 1.21 (by @cmenginnz)
## License
Expand Down
18 changes: 9 additions & 9 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"golang.org/x/sync/errgroup"
)

//Config represents a client configuration
// Config represents a client configuration
type Config struct {
Fingerprint string
Auth string
Expand All @@ -45,7 +45,7 @@ type Config struct {
Verbose bool
}

//TLSConfig for a Client
// TLSConfig for a Client
type TLSConfig struct {
SkipVerify bool
CA string
Expand All @@ -54,7 +54,7 @@ type TLSConfig struct {
ServerName string
}

//Client represents a client instance
// Client represents a client instance
type Client struct {
*cio.Logger
config *Config
Expand All @@ -69,7 +69,7 @@ type Client struct {
tunnel *tunnel.Tunnel
}

//NewClient creates a new client instance
// NewClient creates a new client instance
func NewClient(c *Config) (*Client, error) {
//apply default scheme
if !strings.HasPrefix(c.Server, "http") {
Expand Down Expand Up @@ -190,7 +190,7 @@ func NewClient(c *Config) (*Client, error) {
return client, nil
}

//Run starts client and blocks while connected
// Run starts client and blocks while connected
func (c *Client) Run() error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down Expand Up @@ -221,7 +221,7 @@ func (c *Client) verifyServer(hostname string, remote net.Addr, key ssh.PublicKe
return nil
}

//verifyLegacyFingerprint calculates and compares legacy MD5 fingerprints
// verifyLegacyFingerprint calculates and compares legacy MD5 fingerprints
func (c *Client) verifyLegacyFingerprint(key ssh.PublicKey) error {
bytes := md5.Sum(key.Marshal())
strbytes := make([]string, len(bytes))
Expand All @@ -236,7 +236,7 @@ func (c *Client) verifyLegacyFingerprint(key ssh.PublicKey) error {
return nil
}

//Start client and does not block
// Start client and does not block
func (c *Client) Start(ctx context.Context) error {
ctx, cancel := context.WithCancel(ctx)
c.stop = cancel
Expand Down Expand Up @@ -293,12 +293,12 @@ func (c *Client) setProxy(u *url.URL, d *websocket.Dialer) error {
return nil
}

//Wait blocks while the client is running.
// Wait blocks while the client is running.
func (c *Client) Wait() error {
return c.eg.Wait()
}

//Close manually stops the client
// Close manually stops the client
func (c *Client) Close() error {
if c.stop != nil {
c.stop()
Expand Down
124 changes: 49 additions & 75 deletions client/client_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package chclient

import (
"crypto/ecdsa"
"crypto/elliptic"
"log"
"net/http"
Expand Down Expand Up @@ -45,87 +44,62 @@ func TestCustomHeaders(t *testing.T) {
c.Close()
}

// with the update Go to 1.20, these Unit Tests start failing,
// since this test is related to client side, and the "fingerprint" flag is not available in cloud-connector
// we can remove/comment these 3 Unit Tests, until fixed in upstream

// func TestFallbackLegacyFingerprint(t *testing.T) {
// config := Config{
// Fingerprint: "a5:32:92:c6:56:7a:9e:61:26:74:1b:81:a6:f5:1b:44",
// }
// c, err := NewClient(&config)
// if err != nil {
// t.Fatal(err)
// }
// r := ccrypto.NewDetermRand([]byte("test123"))
// priv, err := ecdsa.GenerateKey(elliptic.P256(), r)
// if err != nil {
// t.Fatal(err)
// }
// pub, err := ssh.NewPublicKey(&priv.PublicKey)
// if err != nil {
// t.Fatal(err)
// }
// err = c.verifyServer("", nil, pub)
// if err != nil {
// t.Fatal(err)
// }
// }

// func TestVerifyLegacyFingerprint(t *testing.T) {
// config := Config{
// Fingerprint: "a5:32:92:c6:56:7a:9e:61:26:74:1b:81:a6:f5:1b:44",
// }
// c, err := NewClient(&config)
// if err != nil {
// t.Fatal(err)
// }
// r := ccrypto.NewDetermRand([]byte("test123"))
// priv, err := ecdsa.GenerateKey(elliptic.P256(), r)
// if err != nil {
// t.Fatal(err)
// }
// pub, err := ssh.NewPublicKey(&priv.PublicKey)
// if err != nil {
// t.Fatal(err)
// }
// err = c.verifyLegacyFingerprint(pub)
// if err != nil {
// t.Fatal(err)
// }
// }
func TestFallbackLegacyFingerprint(t *testing.T) {
config := Config{
Fingerprint: "a5:32:92:c6:56:7a:9e:61:26:74:1b:81:a6:f5:1b:44",
}
c, err := NewClient(&config)
if err != nil {
t.Fatal(err)
}
r := ccrypto.NewDetermRand([]byte("test123"))
priv, err := ccrypto.GenerateKeyGo119(elliptic.P256(), r)
if err != nil {
t.Fatal(err)
}
pub, err := ssh.NewPublicKey(&priv.PublicKey)
if err != nil {
t.Fatal(err)
}
err = c.verifyServer("", nil, pub)
if err != nil {
t.Fatal(err)
}
}

// func TestVerifyFingerprint(t *testing.T) {
// config := Config{
// Fingerprint: "qmrRoo8MIqePv3jC8+wv49gU6uaFgD3FASQx9V8KdmY=",
// }
// c, err := NewClient(&config)
// if err != nil {
// t.Fatal(err)
// }
// r := ccrypto.NewDetermRand([]byte("test123"))
// priv, err := ecdsa.GenerateKey(elliptic.P256(), r)
// if err != nil {
// t.Fatal(err)
// }
// pub, err := ssh.NewPublicKey(&priv.PublicKey)
// if err != nil {
// t.Fatal(err)
// }
// err = c.verifyServer("", nil, pub)
// if err != nil {
// t.Fatal(err)
// }
// }
func TestVerifyLegacyFingerprint(t *testing.T) {
config := Config{
Fingerprint: "a5:32:92:c6:56:7a:9e:61:26:74:1b:81:a6:f5:1b:44",
}
c, err := NewClient(&config)
if err != nil {
t.Fatal(err)
}
r := ccrypto.NewDetermRand([]byte("test123"))
priv, err := ccrypto.GenerateKeyGo119(elliptic.P256(), r)
if err != nil {
t.Fatal(err)
}
pub, err := ssh.NewPublicKey(&priv.PublicKey)
if err != nil {
t.Fatal(err)
}
err = c.verifyLegacyFingerprint(pub)
if err != nil {
t.Fatal(err)
}
}

func TestVerifyEmptyFingerprint(t *testing.T) {
config := Config{}
func TestVerifyFingerprint(t *testing.T) {
config := Config{
Fingerprint: "qmrRoo8MIqePv3jC8+wv49gU6uaFgD3FASQx9V8KdmY=",
}
c, err := NewClient(&config)
if err != nil {
t.Fatal(err)
}
r := ccrypto.NewDetermRand([]byte("test123"))
priv, err := ecdsa.GenerateKey(elliptic.P256(), r)
priv, err := ccrypto.GenerateKeyGo119(elliptic.P256(), r)
if err != nil {
t.Fatal(err)
}
Expand Down
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module github.com/jpillora/chisel

go 1.20

go 1.21

require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
Expand All @@ -9,15 +10,15 @@ require (
github.com/jpillora/backoff v1.0.0
github.com/jpillora/requestlog v1.0.0
github.com/jpillora/sizestr v1.0.0
golang.org/x/crypto v0.10.0
golang.org/x/net v0.11.0
golang.org/x/crypto v0.12.0
golang.org/x/net v0.14.0
golang.org/x/sync v0.3.0
)

require (
github.com/andrew-d/go-termutil v0.0.0-20150726205930-009166a695a2 // indirect
github.com/jpillora/ansi v1.0.3 // indirect
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
)
29 changes: 10 additions & 19 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,16 @@ github.com/jpillora/sizestr v1.0.0 h1:4tr0FLxs1Mtq3TnsLDV+GYUWG7Q26a6s+tV5Zfw2yg
github.com/jpillora/sizestr v1.0.0/go.mod h1:bUhLv4ctkknatr6gR42qPxirmd5+ds1u7mzD+MZ33f0=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
Loading

0 comments on commit 97263d9

Please sign in to comment.