Skip to content

Commit

Permalink
Bump to Go 1.21 (#440)
Browse files Browse the repository at this point in the history
Co-authored-by: cmeng <cmenginnz@gmail.com>
  • Loading branch information
jpillora and cmenginnz committed Aug 19, 2023
1 parent ce307e5 commit 69093be
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x]
go-version: [1.21.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
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
20 changes: 10 additions & 10 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 @@ -105,7 +105,7 @@ func NewClient(c *Config) (*Client, error) {
tlsConfig: nil,
}
//set default log level
client.Logger.Info = c.Verbose
client.Logger.Info = true
//configure tls
if u.Scheme == "wss" {
tc := &tls.Config{}
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
7 changes: 3 additions & 4 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 @@ -54,7 +53,7 @@ func TestFallbackLegacyFingerprint(t *testing.T) {
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 All @@ -77,7 +76,7 @@ func TestVerifyLegacyFingerprint(t *testing.T) {
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 All @@ -100,7 +99,7 @@ func TestVerifyFingerprint(t *testing.T) {
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
20 changes: 12 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
module github.com/jpillora/chisel

go 1.13
go 1.21

require (
github.com/andrew-d/go-termutil v0.0.0-20150726205930-009166a695a2 // indirect
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/fsnotify/fsnotify v1.6.0
github.com/gorilla/websocket v1.4.2
github.com/jpillora/ansi v1.0.2 // indirect
github.com/gorilla/websocket v1.5.0
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.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/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
)
38 changes: 16 additions & 22 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jpillora/ansi v1.0.2 h1:+Ei5HCAH0xsrQRCT2PDr4mq9r4Gm4tg+arNdXRkB22s=
github.com/jpillora/ansi v1.0.2/go.mod h1:D2tT+6uzJvN1nBVQILYWkIdq7zG+b5gcFN5WI/VyjMY=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jpillora/ansi v1.0.3 h1:nn4Jzti0EmRfDxm7JtEs5LzCbNwd5sv+0aE+LdS9/ZQ=
github.com/jpillora/ansi v1.0.3/go.mod h1:D2tT+6uzJvN1nBVQILYWkIdq7zG+b5gcFN5WI/VyjMY=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jpillora/requestlog v1.0.0 h1:bg++eJ74T7DYL3DlIpiwknrtfdUA9oP/M4fL+PpqnyA=
Expand All @@ -16,22 +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.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
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=
35 changes: 32 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import (
chclient "github.com/jpillora/chisel/client"
chserver "github.com/jpillora/chisel/server"
chshare "github.com/jpillora/chisel/share"
"github.com/jpillora/chisel/share/ccrypto"
"github.com/jpillora/chisel/share/cos"
"github.com/jpillora/chisel/share/settings"
)

var help = `
Expand Down Expand Up @@ -103,12 +105,23 @@ var serverHelp = `
--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 @@ -170,6 +183,7 @@ func server(args []string) {

config := &chserver.Config{}
flags.StringVar(&config.KeySeed, "key", "", "")
flags.StringVar(&config.KeyFile, "keyfile", "", "")
flags.StringVar(&config.AuthFile, "authfile", "", "")
flags.StringVar(&config.Auth, "auth", "", "")
flags.DurationVar(&config.KeepAlive, "keepalive", 25*time.Second, "")
Expand All @@ -187,13 +201,26 @@ func server(args []string) {
port := flags.String("port", "", "")
pid := flags.Bool("pid", false, "")
verbose := flags.Bool("v", false, "")
keyGen := flags.String("keygen", "", "")

flags.Usage = func() {
fmt.Print(serverHelp)
os.Exit(0)
}
flags.Parse(args)

if *keyGen != "" {
if err := ccrypto.GenerateKeyFile(*keyGen, config.KeySeed); err != nil {
log.Fatal(err)
}
return
}

if config.KeySeed != "" {
log.Print("Option `--key` is deprecated and will be removed in a future version of chisel.")
log.Print("Please use `chisel server --keygen /file/path`, followed by `chisel server --keyfile /file/path` to specify the SSH private key")
}

if *host == "" {
*host = os.Getenv("HOST")
}
Expand All @@ -209,8 +236,10 @@ func server(args []string) {
if *port == "" {
*port = "8080"
}
if config.KeySeed == "" {
config.KeySeed = os.Getenv("CHISEL_KEY")
if config.KeyFile == "" {
config.KeyFile = settings.Env("KEY_FILE")
} else if config.KeySeed == "" {
config.KeySeed = settings.Env("KEY")
}
s, err := chserver.NewServer(config)
if err != nil {
Expand Down
Loading

0 comments on commit 69093be

Please sign in to comment.