From a64df5e37c0bbc578fcd863edfe38f72fa70589e Mon Sep 17 00:00:00 2001 From: ip-rw Date: Fri, 26 Aug 2022 20:41:34 +0100 Subject: [PATCH 01/29] Set ServerName (SNI) to *hostname. Useful for spoofing our way through restrictive gateways. --- client/client.go | 4 ++++ client/client_connect.go | 2 +- main.go | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/client/client.go b/client/client.go index 49c7aeb1..40ce1a27 100644 --- a/client/client.go +++ b/client/client.go @@ -50,6 +50,7 @@ type TLSConfig struct { CA string Cert string Key string + ServerName string } //Client represents a client instance @@ -107,6 +108,9 @@ func NewClient(c *Config) (*Client, error) { //configure tls if u.Scheme == "wss" { tc := &tls.Config{} + if c.TLS.ServerName != "" { + tc.ServerName = c.TLS.ServerName + } //certificate verification config if c.TLS.SkipVerify { client.Infof("TLS verification disabled") diff --git a/client/client_connect.go b/client/client_connect.go index b33ea5b9..8841d0ca 100644 --- a/client/client_connect.go +++ b/client/client_connect.go @@ -39,7 +39,7 @@ func (c *Client) connectionLoop(ctx context.Context) error { if attempt > 0 { maxAttemptVal := fmt.Sprint(maxAttempt) if maxAttempt < 0 { - maxAttemptVal = "unlimited"; + maxAttemptVal = "unlimited" } msg += fmt.Sprintf(" (Attempt: %d/%s)", attempt, maxAttemptVal) } diff --git a/main.go b/main.go index bba3e747..7490bb8a 100644 --- a/main.go +++ b/main.go @@ -422,6 +422,7 @@ func client(args []string) { //move hostname onto headers if *hostname != "" { config.Headers.Set("Host", *hostname) + config.TLS.ServerName = *hostname } //ready c, err := chclient.NewClient(&config) From fdc1e1064cc6378b087f7730e1755f1e7224949a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 20:08:32 +0000 Subject: [PATCH 02/29] Bump actions/checkout from 2 to 3.1.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3.1.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afa73f48..e1fd5a4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3.1.0 - name: Build run: go build -v . - name: Test @@ -38,7 +38,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3.1.0 - name: goreleaser if: success() uses: docker://goreleaser/goreleaser:latest From 2b90de64cfb24f4fbba79b48b61e219224c04077 Mon Sep 17 00:00:00 2001 From: ip-rw Date: Tue, 11 Oct 2022 14:11:43 +0200 Subject: [PATCH 03/29] Added --sni switch to control the ServerName when connecting with TLS. Makes 'domain fronting' possible. --- main.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main.go b/main.go index 7490bb8a..ed1dab16 100644 --- a/main.go +++ b/main.go @@ -366,6 +366,9 @@ var clientHelp = ` --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. @@ -401,6 +404,7 @@ func client(args []string) { flags.StringVar(&config.TLS.Key, "tls-key", "", "") flags.Var(&headerFlags{config.Headers}, "header", "") hostname := flags.String("hostname", "", "") + sni := flags.String("sni", "", "") pid := flags.Bool("pid", false, "") verbose := flags.Bool("v", false, "") flags.Usage = func() { @@ -424,6 +428,11 @@ func client(args []string) { config.Headers.Set("Host", *hostname) config.TLS.ServerName = *hostname } + + if *sni != "" { + config.TLS.ServerName = *sni + } + //ready c, err := chclient.NewClient(&config) if err != nil { From 57ddad654a634a66cea0f55c3c9be1de1a01d6e4 Mon Sep 17 00:00:00 2001 From: Pratik Raj Date: Thu, 27 Oct 2022 13:22:38 +0530 Subject: [PATCH 04/29] feat: dependabot workflow automation for updating dependency Signed-off-by: Pratik Raj --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2c7d1708..eafdd78e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,9 @@ updates: directory: "/" schedule: interval: "daily" + +# Dependencies listed in go.mod + - package-ecosystem: "gomod" + directory: "/" # Location of package manifests + schedule: + interval: "weekly" From dd19bc696c6d10efd668fc0dc52a5e54be4231d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 15:10:15 +1100 Subject: [PATCH 05/29] Bump github.com/fsnotify/fsnotify from 1.4.9 to 1.6.0 (#389) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 3 +-- go.sum | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 6ec5d719..d3646874 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 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.4.9 + github.com/fsnotify/fsnotify v1.6.0 github.com/gorilla/websocket v1.4.2 github.com/jpillora/ansi v1.0.2 // indirect github.com/jpillora/backoff v1.0.0 @@ -15,6 +15,5 @@ require ( 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/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect ) diff --git a/go.sum b/go.sum index 4897d75a..0a52b5b5 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/andrew-d/go-termutil v0.0.0-20150726205930-009166a695a2 h1:axBiC50cNZ github.com/andrew-d/go-termutil v0.0.0-20150726205930-009166a695a2/go.mod h1:jnzFpU88PccN/tPPhCpnNU8mZphvKxYM9lLNkd8e+os= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +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= @@ -23,12 +23,11 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GE 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-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= +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= From 230f7147ee5222349d03190de983a964be325a1a Mon Sep 17 00:00:00 2001 From: fsiegmund Date: Mon, 31 Oct 2022 04:41:44 +0000 Subject: [PATCH 06/29] UDP buffer size override with CHISEL_UDP_MAX_SIZE environment variable (#367) --- share/tunnel/tunnel_in_proxy_udp.go | 6 ++++-- share/tunnel/tunnel_out_ssh_udp.go | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/share/tunnel/tunnel_in_proxy_udp.go b/share/tunnel/tunnel_in_proxy_udp.go index 35811c50..3f3fa8be 100644 --- a/share/tunnel/tunnel_in_proxy_udp.go +++ b/share/tunnel/tunnel_in_proxy_udp.go @@ -45,7 +45,9 @@ func listenUDP(l *cio.Logger, sshTun sshTunnel, remote *settings.Remote) (*udpLi sshTun: sshTun, remote: remote, inbound: conn, + maxMTU: settings.EnvInt("UDP_MAX_SIZE", 9012), } + u.Debugf("UDP max size: %d bytes", u.maxMTU) return u, nil } @@ -57,6 +59,7 @@ type udpListener struct { outboundMut sync.Mutex outbound *udpChannel sent, recv int64 + maxMTU int } func (u *udpListener) run(ctx context.Context) error { @@ -80,8 +83,7 @@ func (u *udpListener) run(ctx context.Context) error { } func (u *udpListener) runInbound(ctx context.Context) error { - const maxMTU = 9012 - buff := make([]byte, maxMTU) + buff := make([]byte, u.maxMTU) for !isDone(ctx) { //read from inbound udp u.inbound.SetReadDeadline(time.Now().Add(time.Second)) diff --git a/share/tunnel/tunnel_out_ssh_udp.go b/share/tunnel/tunnel_out_ssh_udp.go index 20a10a63..d3c4c62f 100644 --- a/share/tunnel/tunnel_out_ssh_udp.go +++ b/share/tunnel/tunnel_out_ssh_udp.go @@ -27,7 +27,9 @@ func (t *Tunnel) handleUDP(l *cio.Logger, rwc io.ReadWriteCloser, hostPort strin c: rwc, }, udpConns: conns, + maxMTU: settings.EnvInt("UDP_MAX_SIZE", 9012), } + h.Debugf("UDP max size: %d bytes", h.maxMTU) for { p := udpPacket{} if err := h.handleWrite(&p); err != nil { @@ -41,6 +43,7 @@ type udpHandler struct { hostPort string *udpChannel *udpConns + maxMTU int } func (h *udpHandler) handleWrite(p *udpPacket) error { @@ -77,8 +80,7 @@ func (h *udpHandler) handleWrite(p *udpPacket) error { func (h *udpHandler) handleRead(p *udpPacket, conn *udpConn) { //ensure connection is cleaned up defer h.udpConns.remove(conn.id) - const maxMTU = 9012 - buff := make([]byte, maxMTU) + buff := make([]byte, h.maxMTU) for { //response must arrive within 15 seconds deadline := settings.EnvDuration("UDP_DEADLINE", 15*time.Second) From 3e703ae0fe90b8adbc7e1f93b4b1d8774febcfa4 Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Mon, 31 Oct 2022 01:46:46 -0300 Subject: [PATCH 07/29] Add locking around the connection count to fix a data race. (#342) Co-authored-by: andres-portainer --- share/tunnel/tunnel_in_proxy.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/share/tunnel/tunnel_in_proxy.go b/share/tunnel/tunnel_in_proxy.go index eebdfbb5..007fb0c7 100644 --- a/share/tunnel/tunnel_in_proxy.go +++ b/share/tunnel/tunnel_in_proxy.go @@ -4,6 +4,7 @@ import ( "context" "io" "net" + "sync" "github.com/jpillora/chisel/share/cio" "github.com/jpillora/chisel/share/settings" @@ -26,6 +27,7 @@ type Proxy struct { dialer net.Dialer tcp *net.TCPListener udp *udpListener + mu sync.Mutex } //NewProxy creates a Proxy @@ -122,8 +124,12 @@ func (p *Proxy) runTCP(ctx context.Context) error { func (p *Proxy) pipeRemote(ctx context.Context, src io.ReadWriteCloser) { defer src.Close() + + p.mu.Lock() p.count++ cid := p.count + p.mu.Unlock() + l := p.Fork("conn#%d", cid) l.Debugf("Open") sshConn := p.sshTun.getSSH(ctx) From 28a5018b8bc773104742ac6f5c220703886dc6c5 Mon Sep 17 00:00:00 2001 From: 0xflotus <0xflotus@gmail.com> Date: Mon, 31 Oct 2022 05:52:31 +0100 Subject: [PATCH 08/29] fix: small typo error in main.go (#334) --- README.md | 2 +- main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 39443e96..ee3da3ad 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ $ chisel server --help and you cannot set --tls-domain. --tls-domain, Enables TLS and automatically acquires a TLS key and - certificate using LetsEncypt. Setting --tls-domain requires port 443. + certificate using LetsEncrypt. Setting --tls-domain requires port 443. You may specify multiple --tls-domain flags to serve multiple domains. The resulting files are cached in the "$HOME/.cache/chisel" directory. You can modify this path by setting the CHISEL_LE_CACHE variable, diff --git a/main.go b/main.go index ed1dab16..eb50e6ca 100644 --- a/main.go +++ b/main.go @@ -151,7 +151,7 @@ var serverHelp = ` and you cannot set --tls-domain. --tls-domain, Enables TLS and automatically acquires a TLS key and - certificate using LetsEncypt. Setting --tls-domain requires port 443. + certificate using LetsEncrypt. Setting --tls-domain requires port 443. You may specify multiple --tls-domain flags to serve multiple domains. The resulting files are cached in the "$HOME/.cache/chisel" directory. You can modify this path by setting the CHISEL_LE_CACHE variable, From ed6adb98bcd43377ee00eab7fb4a47dc4700e40c Mon Sep 17 00:00:00 2001 From: BigSully Date: Mon, 31 Oct 2022 12:53:36 +0800 Subject: [PATCH 09/29] Respond to /health and /version by request path rather than by the whole url string (#328) Co-authored-by: bar --- server/server_handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/server_handler.go b/server/server_handler.go index 85229e97..f5804836 100644 --- a/server/server_handler.go +++ b/server/server_handler.go @@ -34,7 +34,7 @@ func (s *Server) handleClientHandler(w http.ResponseWriter, r *http.Request) { return } //no proxy defined, provide access to health/version checks - switch r.URL.String() { + switch r.URL.Path { case "/health": w.Write([]byte("OK\n")) return From 4f58a395f6738c659e28812ae1117960fef74189 Mon Sep 17 00:00:00 2001 From: invist <35263248+c-f@users.noreply.github.com> Date: Mon, 31 Oct 2022 05:54:57 +0100 Subject: [PATCH 10/29] Update version.go (#288) --- server/server_handler.go | 2 +- share/version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server_handler.go b/server/server_handler.go index f5804836..952aa4d8 100644 --- a/server/server_handler.go +++ b/server/server_handler.go @@ -19,7 +19,7 @@ func (s *Server) handleClientHandler(w http.ResponseWriter, r *http.Request) { //websockets upgrade AND has chisel prefix upgrade := strings.ToLower(r.Header.Get("Upgrade")) protocol := r.Header.Get("Sec-WebSocket-Protocol") - if upgrade == "websocket" && strings.HasPrefix(protocol, "chisel-") { + if upgrade == "websocket" { if protocol == chshare.ProtocolVersion { s.handleWebsocket(w, r) return diff --git a/share/version.go b/share/version.go index 46efda9b..f503f85c 100644 --- a/share/version.go +++ b/share/version.go @@ -4,6 +4,6 @@ package chshare //incompatible changes are made, this will //be incremented to signify a protocol //mismatch. -const ProtocolVersion = "chisel-v3" +var ProtocolVersion = "chisel-v3" var BuildVersion = "0.0.0-src" From 200a8e25d790b332458bd0116179be47464efbc9 Mon Sep 17 00:00:00 2001 From: zuzgon Date: Mon, 31 Oct 2022 06:56:27 +0200 Subject: [PATCH 11/29] Providing chisel's client with a logger level (#281) Co-authored-by: Barak Sharoni Co-authored-by: barak-sharoni-velocity <81081183+barak-sharoni-velocity@users.noreply.github.com> --- client/client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/client.go b/client/client.go index 40ce1a27..793e4304 100644 --- a/client/client.go +++ b/client/client.go @@ -42,6 +42,7 @@ type Config struct { Headers http.Header TLS TLSConfig DialContext func(ctx context.Context, network, addr string) (net.Conn, error) + Verbose bool } //TLSConfig for a Client @@ -104,7 +105,7 @@ func NewClient(c *Config) (*Client, error) { tlsConfig: nil, } //set default log level - client.Logger.Info = true + client.Logger.Info = c.Verbose //configure tls if u.Scheme == "wss" { tc := &tls.Config{} From 556db3efada0166880b20ff7b733cdffa2480de8 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Mon, 31 Oct 2022 16:08:20 +1100 Subject: [PATCH 12/29] add EnvBool --- share/settings/env.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/share/settings/env.go b/share/settings/env.go index 17b002be..53beefcc 100644 --- a/share/settings/env.go +++ b/share/settings/env.go @@ -3,15 +3,16 @@ package settings import ( "os" "strconv" + "strings" "time" ) -//Env returns a chisel environment variable +// Env returns a chisel environment variable func Env(name string) string { return os.Getenv("CHISEL_" + name) } -//EnvInt returns an integer using an environment variable, with a default fallback +// EnvInt returns an integer using an environment variable, with a default fallback func EnvInt(name string, def int) int { if n, err := strconv.Atoi(Env(name)); err == nil { return n @@ -19,10 +20,16 @@ func EnvInt(name string, def int) int { return def } -//EnvDuration returns a duration using an environment variable, with a default fallback +// EnvDuration returns a duration using an environment variable, with a default fallback func EnvDuration(name string, def time.Duration) time.Duration { if n, err := time.ParseDuration(Env(name)); err == nil { return n } return def } + +// EnvBool returns a boolean using an environment variable +func EnvBool(name string) bool { + v := Env(name) + return v == "1" || strings.ToLower(v) == "true" +} From fbc8ad9731a8563b2d9c7a8386f279c0fc0c959e Mon Sep 17 00:00:00 2001 From: Guillaume SMAHA Date: Fri, 27 Jan 2023 12:50:23 +0100 Subject: [PATCH 13/29] Fix #390: Use code to generate certificates for client & server (#400) --- .github/workflows/ci.yml | 2 +- test/e2e/cert_utils_test.go | 257 +++++++++++++++++++++++++++++ test/e2e/setup_test.go | 2 +- test/e2e/tls/client-ca/server.crt | 16 -- test/e2e/tls/client-crt/client.crt | 16 -- test/e2e/tls/client-crt/client.key | 15 -- test/e2e/tls/server-ca/client.crt | 16 -- test/e2e/tls/server-crt/server.crt | 16 -- test/e2e/tls/server-crt/server.key | 15 -- test/e2e/tls_test.go | 100 ++++++----- 10 files changed, 307 insertions(+), 148 deletions(-) create mode 100644 test/e2e/cert_utils_test.go delete mode 100644 test/e2e/tls/client-ca/server.crt delete mode 100644 test/e2e/tls/client-crt/client.crt delete mode 100644 test/e2e/tls/client-crt/client.key delete mode 100644 test/e2e/tls/server-ca/client.crt delete mode 100644 test/e2e/tls/server-crt/server.crt delete mode 100644 test/e2e/tls/server-crt/server.key diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1fd5a4e..f412ff31 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: name: Test strategy: matrix: - go-version: [1.13.x, 1.14.x, 1.15.x] + go-version: [1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.18.x, 1.19.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/test/e2e/cert_utils_test.go b/test/e2e/cert_utils_test.go new file mode 100644 index 00000000..379e282b --- /dev/null +++ b/test/e2e/cert_utils_test.go @@ -0,0 +1,257 @@ +package e2e_test + +import ( + "bytes" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "io/ioutil" + "math/big" + "net" + "os" + "path" + "time" + + chclient "github.com/jpillora/chisel/client" + chserver "github.com/jpillora/chisel/server" +) + +type tlsConfig struct { + serverTLS *chserver.TLSConfig + clientTLS *chclient.TLSConfig + tmpDir string +} + +func (t *tlsConfig) Close() { + if t.tmpDir != "" { + os.RemoveAll(t.tmpDir) + } +} + +func newTestTLSConfig() (*tlsConfig, error) { + tlsConfig := &tlsConfig{} + _, serverCertPEM, serverKeyPEM, err := certGetCertificate(&certConfig{ + hosts: []string{ + "0.0.0.0", + "localhost", + }, + extKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + }) + if err != nil { + return nil, err + } + _, clientCertPEM, clientKeyPEM, err := certGetCertificate(&certConfig{ + extKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + }) + if err != nil { + return nil, err + } + + tlsConfig.tmpDir, err = ioutil.TempDir("", "") + if err != nil { + return nil, err + } + + dirServerCA := path.Join(tlsConfig.tmpDir, "server-ca") + if err := os.Mkdir(dirServerCA, 0777); err != nil { + return nil, err + } + pathServerCACrt := path.Join(dirServerCA, "client.crt") + if err := ioutil.WriteFile(pathServerCACrt, clientCertPEM, 0666); err != nil { + return nil, err + } + + dirClientCA := path.Join(tlsConfig.tmpDir, "client-ca") + if err := os.Mkdir(dirClientCA, 0777); err != nil { + return nil, err + } + pathClientCACrt := path.Join(dirClientCA, "server.crt") + if err := ioutil.WriteFile(pathClientCACrt, serverCertPEM, 0666); err != nil { + return nil, err + } + + dirServerCrt := path.Join(tlsConfig.tmpDir, "server-crt") + if err := os.Mkdir(dirServerCrt, 0777); err != nil { + return nil, err + } + pathServerCrtCrt := path.Join(dirServerCrt, "server.crt") + if err := ioutil.WriteFile(pathServerCrtCrt, serverCertPEM, 0666); err != nil { + return nil, err + } + pathServerCrtKey := path.Join(dirServerCrt, "server.key") + if err := ioutil.WriteFile(pathServerCrtKey, serverKeyPEM, 0666); err != nil { + return nil, err + } + + dirClientCrt := path.Join(tlsConfig.tmpDir, "client-crt") + if err := os.Mkdir(dirClientCrt, 0777); err != nil { + return nil, err + } + pathClientCrtCrt := path.Join(dirClientCrt, "client.crt") + if err := ioutil.WriteFile(pathClientCrtCrt, clientCertPEM, 0666); err != nil { + return nil, err + } + pathClientCrtKey := path.Join(dirClientCrt, "client.key") + if err := ioutil.WriteFile(pathClientCrtKey, clientKeyPEM, 0666); err != nil { + return nil, err + } + + // for self signed cert, it needs the server cert, for real cert, this need to be the trusted CA cert + tlsConfig.serverTLS = &chserver.TLSConfig{ + CA: pathServerCACrt, + Cert: pathServerCrtCrt, + Key: pathServerCrtKey, + } + tlsConfig.clientTLS = &chclient.TLSConfig{ + CA: pathClientCACrt, + Cert: pathClientCrtCrt, + Key: pathClientCrtKey, + } + return tlsConfig, nil +} + +type certConfig struct { + signCA *x509.Certificate + isCA bool + hosts []string + validFrom *time.Time + validFor *time.Time + extKeyUsage []x509.ExtKeyUsage + rsaBits int + ecdsaCurve string + ed25519Key bool +} + +func certGetCertificate(c *certConfig) (*x509.Certificate, []byte, []byte, error) { + var err error + var priv interface{} + switch c.ecdsaCurve { + case "": + if c.ed25519Key { + _, priv, err = ed25519.GenerateKey(rand.Reader) + } else { + rsaBits := c.rsaBits + if rsaBits == 0 { + rsaBits = 2048 + } + priv, err = rsa.GenerateKey(rand.Reader, rsaBits) + } + case "P224": + priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + case "P256": + priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + case "P384": + priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + case "P521": + priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + default: + return nil, nil, nil, fmt.Errorf("Unrecognized elliptic curve: %q", c.ecdsaCurve) + } + if err != nil { + return nil, nil, nil, fmt.Errorf("Failed to generate private key: %v", err) + } + + // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature + // KeyUsage bits set in the x509.Certificate template + keyUsage := x509.KeyUsageDigitalSignature + // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In + // the context of TLS this KeyUsage is particular to RSA key exchange and + // authentication. + if _, isRSA := priv.(*rsa.PrivateKey); isRSA { + keyUsage |= x509.KeyUsageKeyEncipherment + } + + notBefore := time.Now() + if c.validFrom != nil { + notBefore = *c.validFrom + } + + notAfter := time.Now().Add(24 * time.Hour) + if c.validFor != nil { + notAfter = *c.validFor + } + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return nil, nil, nil, fmt.Errorf("Failed to generate serial number: %v", err) + } + + cert := &x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + OrganizationalUnit: []string{"test"}, + Organization: []string{"Chisel"}, + Country: []string{"us"}, + Province: []string{"ma"}, + Locality: []string{"Boston"}, + CommonName: "localhost", + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: c.extKeyUsage, + BasicConstraintsValid: true, + } + + for _, h := range c.hosts { + if ip := net.ParseIP(h); ip != nil { + cert.IPAddresses = append(cert.IPAddresses, ip) + } else { + cert.DNSNames = append(cert.DNSNames, h) + } + } + + if c.isCA { + cert.IsCA = true + cert.KeyUsage |= x509.KeyUsageCertSign + } + + ca := cert + if c.signCA != nil { + ca = c.signCA + } + + certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, certGetPublicKey(priv), priv) + if err != nil { + return nil, nil, nil, fmt.Errorf("Failed to create certificate: %v", err) + } + + certPEM := new(bytes.Buffer) + pem.Encode(certPEM, &pem.Block{ + Type: "CERTIFICATE", + Bytes: certBytes, + }) + + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + return nil, nil, nil, fmt.Errorf("Unable to marshal private key: %v", err) + } + certPrivKeyPEM := new(bytes.Buffer) + pem.Encode(certPrivKeyPEM, &pem.Block{ + Type: "PRIVATE KEY", + Bytes: privBytes, + }) + + return cert, certPEM.Bytes(), certPrivKeyPEM.Bytes(), nil +} + +func certGetPublicKey(priv interface{}) interface{} { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + case ed25519.PrivateKey: + return k.Public().(ed25519.PublicKey) + default: + return nil + } +} diff --git a/test/e2e/setup_test.go b/test/e2e/setup_test.go index a01e119c..c6228757 100644 --- a/test/e2e/setup_test.go +++ b/test/e2e/setup_test.go @@ -16,7 +16,7 @@ import ( const debug = true -//test layout configuration +// test layout configuration type testLayout struct { server *chserver.Config client *chclient.Config diff --git a/test/e2e/tls/client-ca/server.crt b/test/e2e/tls/client-ca/server.crt deleted file mode 100644 index 395b2a1a..00000000 --- a/test/e2e/tls/client-ca/server.crt +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICezCCAeQCCQDwdWskfbwmzzANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UEBhMC -dXMxCzAJBgNVBAgMAm1hMQ8wDQYDVQQHDAZCb3N0b24xDzANBgNVBAoMBkNoaXNl -bDENMAsGA1UECwwEdGVzdDESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYJKoZIhvcN -AQkBFhF3aWxseGlhQGdtYWlsLmNvbTAeFw0yMDA4MjQxOTQ4MTdaFw0zMDA4MjIx -OTQ4MTdaMIGBMQswCQYDVQQGEwJ1czELMAkGA1UECAwCbWExDzANBgNVBAcMBkJv -c3RvbjEPMA0GA1UECgwGQ2hpc2VsMQ0wCwYDVQQLDAR0ZXN0MRIwEAYDVQQDDAls -b2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEXdpbGx4aWFAZ21haWwuY29tMIGfMA0G -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC128s6L6YN0eNSNbI40URFHd9xzfnPlUcH -n9n7D6YkJL7LsTAtUfjubNAX0Q1gclDnDZCfYi9UZVzzID4s1gZJZAEZGnce8loO -a+WcPUgIOJngk2bwUHfrWPl+R5mvE9p60rfYNdo86wLMaLAJu+VagNmaoilSU7OS -uZ/AgTUMFQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAEzq2qsH5VfmjUcvlhS4a7X5 -zOAtEIVB1+oef/1NcyT3PaMX0ry0Ddbo3NJs3G9KTF0k+TCGtT7nAG2jRQvs6omZ -3+9C3x+6TQq+95KMBWXuZLZEPNa4iCGFbGrHq4wcWDehBAPSjdctqnmowd8yIgov -gNSN2xEMPNKYIhHt0lyc ------END CERTIFICATE----- diff --git a/test/e2e/tls/client-crt/client.crt b/test/e2e/tls/client-crt/client.crt deleted file mode 100644 index d1f70592..00000000 --- a/test/e2e/tls/client-crt/client.crt +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICfTCCAeYCCQDIXTlEp6na1zANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC -dXMxCzAJBgNVBAgMAm1hMQ8wDQYDVQQHDAZCb3N0b24xDzANBgNVBAoMBkNoaXNl -bDENMAsGA1UECwwEdGVzdDETMBEGA1UEAwwKbVRMU0NsaWVudDEgMB4GCSqGSIb3 -DQEJARYRd2lsbHhpYUBnbWFpbC5jb20wHhcNMjAwODI0MTk0ODQxWhcNMzAwODIy -MTk0ODQxWjCBgjELMAkGA1UEBhMCdXMxCzAJBgNVBAgMAm1hMQ8wDQYDVQQHDAZC -b3N0b24xDzANBgNVBAoMBkNoaXNlbDENMAsGA1UECwwEdGVzdDETMBEGA1UEAwwK -bVRMU0NsaWVudDEgMB4GCSqGSIb3DQEJARYRd2lsbHhpYUBnbWFpbC5jb20wgZ8w -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4jt9TxHsCNegij34we4yzOykAuMVuz -DzW++Jh4/xWeOoU3xb7I2ETIzmusIM70o2lm+e+gy9VfAAXaNgZg63QV54jRn2nk -BWoXJYvYOJwt5YzOsLkbh6epSlrqYI0H34Sy5rEkacXCkcpcEvom/tvJ+SpHyIL1 -PYNN1CCx/eg5AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAJysuLKCgVqMW628SFcpu -ojtBSNy2KETDwmMTaLg/XTaAPOvxAO3W9F7KJ1JxVFf2oIW7ROL9sP862lSMQLZ5 -R45pBlPZycb1CQplD50wMqknaaMJ1qnld9Jkv802cJa2riqzdHb5rnjrewmuLOOB -V0cZ9PJA3KdXbJW1o+WjQz4= ------END CERTIFICATE----- diff --git a/test/e2e/tls/client-crt/client.key b/test/e2e/tls/client-crt/client.key deleted file mode 100644 index a8afa33e..00000000 --- a/test/e2e/tls/client-crt/client.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDOI7fU8R7AjXoIo9+MHuMszspALjFbsw81vviYeP8VnjqFN8W+ -yNhEyM5rrCDO9KNpZvnvoMvVXwAF2jYGYOt0FeeI0Z9p5AVqFyWL2DicLeWMzrC5 -G4enqUpa6mCNB9+EsuaxJGnFwpHKXBL6Jv7byfkqR8iC9T2DTdQgsf3oOQIDAQAB -AoGAArLhAz6s4mR3xokusgzteHa0myZ/qu2rM07uvkBHRqctqPTT9+11N2FRooM8 -Yrk9MnIQr5xxTrfRrkHvFyJJstNX809ve9Klu1vbT+S19se/m+jLKTOtOoYoPRaK -w7ekvjhLct00zQevphEX30xqA2S3HSjWD3HmjVwdadAUgQECQQDz+LShNRkJ97+n -hiRgShHupW7CmAb67hrenbbzkCaY8Kf9cAFiscEmjH+lZsbufCgzVvHKDNKi9/JN -dPTSQvURAkEA2E2D0BqTDOiqjwyueSr2V5m63mzWR0Jd1TAl0dxB6SBumYQQ1FFP -DmQ/J3lcT2RTS+PmKAkuPpSOalw1kqggqQJAbotPVQgZG1IdjguS6epF68sbv6Jg -70v58sqlfgDf7EaG56fbiNuf+BaLM+e41ZB+Kp0Hm5Rp0JvmN0B6OddK8QJAcZbD -UdWiw3SrnNOcDCVzmC0y5Ptiy6kefYX7VmnEcxiE/DlOXTEVwwkB4UjqIQcedwwH -IZ8wmcyJvXEO8SU5gQJAfHxBcFdX2vrDNNjm5GG11zrT86Ii+ieXa0Ty5vapRSsz -FQH3KnM2t7nNDMlFOaHuvVXHmPasudtxBDc5xDoHNA== ------END RSA PRIVATE KEY----- diff --git a/test/e2e/tls/server-ca/client.crt b/test/e2e/tls/server-ca/client.crt deleted file mode 100644 index d1f70592..00000000 --- a/test/e2e/tls/server-ca/client.crt +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICfTCCAeYCCQDIXTlEp6na1zANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC -dXMxCzAJBgNVBAgMAm1hMQ8wDQYDVQQHDAZCb3N0b24xDzANBgNVBAoMBkNoaXNl -bDENMAsGA1UECwwEdGVzdDETMBEGA1UEAwwKbVRMU0NsaWVudDEgMB4GCSqGSIb3 -DQEJARYRd2lsbHhpYUBnbWFpbC5jb20wHhcNMjAwODI0MTk0ODQxWhcNMzAwODIy -MTk0ODQxWjCBgjELMAkGA1UEBhMCdXMxCzAJBgNVBAgMAm1hMQ8wDQYDVQQHDAZC -b3N0b24xDzANBgNVBAoMBkNoaXNlbDENMAsGA1UECwwEdGVzdDETMBEGA1UEAwwK -bVRMU0NsaWVudDEgMB4GCSqGSIb3DQEJARYRd2lsbHhpYUBnbWFpbC5jb20wgZ8w -DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4jt9TxHsCNegij34we4yzOykAuMVuz -DzW++Jh4/xWeOoU3xb7I2ETIzmusIM70o2lm+e+gy9VfAAXaNgZg63QV54jRn2nk -BWoXJYvYOJwt5YzOsLkbh6epSlrqYI0H34Sy5rEkacXCkcpcEvom/tvJ+SpHyIL1 -PYNN1CCx/eg5AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAJysuLKCgVqMW628SFcpu -ojtBSNy2KETDwmMTaLg/XTaAPOvxAO3W9F7KJ1JxVFf2oIW7ROL9sP862lSMQLZ5 -R45pBlPZycb1CQplD50wMqknaaMJ1qnld9Jkv802cJa2riqzdHb5rnjrewmuLOOB -V0cZ9PJA3KdXbJW1o+WjQz4= ------END CERTIFICATE----- diff --git a/test/e2e/tls/server-crt/server.crt b/test/e2e/tls/server-crt/server.crt deleted file mode 100644 index 395b2a1a..00000000 --- a/test/e2e/tls/server-crt/server.crt +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICezCCAeQCCQDwdWskfbwmzzANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UEBhMC -dXMxCzAJBgNVBAgMAm1hMQ8wDQYDVQQHDAZCb3N0b24xDzANBgNVBAoMBkNoaXNl -bDENMAsGA1UECwwEdGVzdDESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYJKoZIhvcN -AQkBFhF3aWxseGlhQGdtYWlsLmNvbTAeFw0yMDA4MjQxOTQ4MTdaFw0zMDA4MjIx -OTQ4MTdaMIGBMQswCQYDVQQGEwJ1czELMAkGA1UECAwCbWExDzANBgNVBAcMBkJv -c3RvbjEPMA0GA1UECgwGQ2hpc2VsMQ0wCwYDVQQLDAR0ZXN0MRIwEAYDVQQDDAls -b2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEXdpbGx4aWFAZ21haWwuY29tMIGfMA0G -CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC128s6L6YN0eNSNbI40URFHd9xzfnPlUcH -n9n7D6YkJL7LsTAtUfjubNAX0Q1gclDnDZCfYi9UZVzzID4s1gZJZAEZGnce8loO -a+WcPUgIOJngk2bwUHfrWPl+R5mvE9p60rfYNdo86wLMaLAJu+VagNmaoilSU7OS -uZ/AgTUMFQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAEzq2qsH5VfmjUcvlhS4a7X5 -zOAtEIVB1+oef/1NcyT3PaMX0ry0Ddbo3NJs3G9KTF0k+TCGtT7nAG2jRQvs6omZ -3+9C3x+6TQq+95KMBWXuZLZEPNa4iCGFbGrHq4wcWDehBAPSjdctqnmowd8yIgov -gNSN2xEMPNKYIhHt0lyc ------END CERTIFICATE----- diff --git a/test/e2e/tls/server-crt/server.key b/test/e2e/tls/server-crt/server.key deleted file mode 100644 index 2225ca98..00000000 --- a/test/e2e/tls/server-crt/server.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC128s6L6YN0eNSNbI40URFHd9xzfnPlUcHn9n7D6YkJL7LsTAt -UfjubNAX0Q1gclDnDZCfYi9UZVzzID4s1gZJZAEZGnce8loOa+WcPUgIOJngk2bw -UHfrWPl+R5mvE9p60rfYNdo86wLMaLAJu+VagNmaoilSU7OSuZ/AgTUMFQIDAQAB -AoGBAJva4JLfXyqc5HsCNdlnz2CEt4irBBsZTiSEpKX7xWFYdIPROP6+L972NmkS -6qnrjtZV08oktXdY344l5eM7EWrFnqKH1pyTRUPnyKGY53jY4yZMad1GYMXLo8Mj -gkEOsfIhuieEBKGXAX54moDLTFzn14q+V+7g3OrLmMYXFN7JAkEA54S00eeuy0Eg -6+qx9dO4iDBp3qut5PShjda4M11MWobRQH71gO0g25qSrnw0x7BXJQl1hhgYtSUy -zbaF+5ZORwJBAMkWxt55YDpXdP4vudugmzP7F8aSB6rUysowlv1uStFhARNYwgs+ -Tl9EGhFPF0ganNv4di1iYLarIKoWas8nNMMCQEex4ekKzSdmUNKeCGQvH3sVOwPY -uG4pj4oED2DgqI90JoLJji9Rv5YiBQCBuDqKkkIG7t0Kw0P9dAEeX9lsT2sCQD5x -iznEmSQkyliwe1d/LRLcMwrfh+/9eieFJS33lNYl+E6IrmENbQraO/oKBGHImdMY -+aGoPf4bb95BbdN8Cj8CQECXWVHkFFVQ2B78r7ENWnmbVG5XJW/iwfaZtmbsPPrI -KqGlB8leQcLLlCC48SCLlc64VtWOaJVxBDyvO4NuD/U= ------END RSA PRIVATE KEY----- diff --git a/test/e2e/tls_test.go b/test/e2e/tls_test.go index 593476e8..304fd937 100644 --- a/test/e2e/tls_test.go +++ b/test/e2e/tls_test.go @@ -1,6 +1,7 @@ package e2e_test import ( + "path" "testing" chclient "github.com/jpillora/chisel/client" @@ -8,25 +9,22 @@ import ( ) func TestTLS(t *testing.T) { + tlsConfig, err := newTestTLSConfig() + if err != nil { + t.Fatal(err) + } + defer tlsConfig.Close() + tmpPort := availablePort() //setup server, client, fileserver teardown := simpleSetup(t, &chserver.Config{ - TLS: chserver.TLSConfig{ - Cert: "tls/server-crt/server.crt", - Key: "tls/server-crt/server.key", - CA: "tls/server-ca/client.crt", - }, + TLS: *tlsConfig.serverTLS, }, &chclient.Config{ Remotes: []string{tmpPort + ":$FILEPORT"}, - TLS: chclient.TLSConfig{ - //for self signed cert, it needs the server cert, for real cert, this need to be the trusted CA cert - CA: "tls/client-ca/server.crt", - Cert: "tls/client-crt/client.crt", - Key: "tls/client-crt/client.key", - }, - Server: "https://localhost:" + tmpPort, + TLS: *tlsConfig.clientTLS, + Server: "https://localhost:" + tmpPort, }) defer teardown() //test remote @@ -40,25 +38,24 @@ func TestTLS(t *testing.T) { } func TestMTLS(t *testing.T) { + tlsConfig, err := newTestTLSConfig() + if err != nil { + t.Fatal(err) + } + defer tlsConfig.Close() + //provide no client cert, server should reject the client request + tlsConfig.serverTLS.CA = path.Dir(tlsConfig.serverTLS.CA) + tmpPort := availablePort() //setup server, client, fileserver teardown := simpleSetup(t, &chserver.Config{ - TLS: chserver.TLSConfig{ - CA: "tls/server-ca", - Cert: "tls/server-crt/server.crt", - Key: "tls/server-crt/server.key", - }, + TLS: *tlsConfig.serverTLS, }, &chclient.Config{ Remotes: []string{tmpPort + ":$FILEPORT"}, - TLS: chclient.TLSConfig{ - //for self signed cert, it needs the server cert, for real cert, this need to be the trusted CA cert - CA: "tls/client-ca/server.crt", - Cert: "tls/client-crt/client.crt", - Key: "tls/client-crt/client.key", - }, - Server: "https://localhost:" + tmpPort, + TLS: *tlsConfig.clientTLS, + Server: "https://localhost:" + tmpPort, }) defer teardown() //test remote @@ -72,60 +69,59 @@ func TestMTLS(t *testing.T) { } func TestTLSMissingClientCert(t *testing.T) { + tlsConfig, err := newTestTLSConfig() + if err != nil { + t.Fatal(err) + } + defer tlsConfig.Close() + //provide no client cert, server should reject the client request + tlsConfig.clientTLS.Cert = "" + tlsConfig.clientTLS.Key = "" + tmpPort := availablePort() //setup server, client, fileserver teardown := simpleSetup(t, &chserver.Config{ - TLS: chserver.TLSConfig{ - CA: "tls/server-ca/client.crt", - Cert: "tls/server-crt/server.crt", - Key: "tls/server-crt/server.key", - }, + TLS: *tlsConfig.serverTLS, }, &chclient.Config{ Remotes: []string{tmpPort + ":$FILEPORT"}, - TLS: chclient.TLSConfig{ - CA: "tls/client-ca/server.crt", - //provide no client cert, server should reject the client request - //Cert: "tls/client-crt/client.crt", - //Key: "tls/client-crt/client.key", - }, - Server: "https://localhost:" + tmpPort, + TLS: *tlsConfig.clientTLS, + Server: "https://localhost:" + tmpPort, }) defer teardown() //test remote - _, err := post("http://localhost:"+tmpPort, "foo") + _, err = post("http://localhost:"+tmpPort, "foo") if err == nil { t.Fatal(err) } } func TestTLSMissingClientCA(t *testing.T) { + tlsConfig, err := newTestTLSConfig() + if err != nil { + t.Fatal(err) + } + defer tlsConfig.Close() + //specify a CA which does not match the client cert + //server should reject the client request + //provide no client cert, server should reject the client request + tlsConfig.serverTLS.CA = tlsConfig.clientTLS.CA + tmpPort := availablePort() //setup server, client, fileserver teardown := simpleSetup(t, &chserver.Config{ - TLS: chserver.TLSConfig{ - //specify a CA which does not match the client cert - //server should reject the client request - CA: "tls/server-crt/server.crt", - Cert: "tls/server-crt/server.crt", - Key: "tls/server-crt/server.key", - }, + TLS: *tlsConfig.serverTLS, }, &chclient.Config{ Remotes: []string{tmpPort + ":$FILEPORT"}, - TLS: chclient.TLSConfig{ - //for self signed cert, it needs the server cert, for real cert, this need to be the trusted CA cert - CA: "tls/client-ca/server.crt", - Cert: "tls/client-crt/client.crt", - Key: "tls/client-crt/client.key", - }, - Server: "https://localhost:" + tmpPort, + TLS: *tlsConfig.clientTLS, + Server: "https://localhost:" + tmpPort, }) defer teardown() //test remote - _, err := post("http://localhost:"+tmpPort, "foo") + _, err = post("http://localhost:"+tmpPort, "foo") if err == nil { t.Fatal(err) } From 4246b649e147e940d2aa0351cd7fe28c724dcad0 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Fri, 27 Jan 2023 23:02:06 +1100 Subject: [PATCH 14/29] docker alpine->google-distroless --- .github/workflows/ci.yml | 41 ++++++++++++++++++++-------------------- Dockerfile | 15 +++++++-------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f412ff31..c9c0001b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,35 +10,33 @@ jobs: name: Test strategy: matrix: - go-version: [1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.18.x, 1.19.x] + go-version: [1.16.x, 1.17.x, 1.18.x, 1.19.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - name: Install Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v3.1.0 + uses: actions/checkout@v3 - name: Build run: go build -v . - name: Test run: go test -v ./... - env: - GODEBUG: x509ignoreCN=0 # ================ - # RELEASE JOB + # RELEASE JOBS # runs after a success test # only runs on push "v*" tag # ================ - release: - name: Release + release_binaries: + name: Release Binaries needs: test if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3.1.0 + uses: actions/checkout@v3 - name: goreleaser if: success() uses: docker://goreleaser/goreleaser:latest @@ -46,6 +44,14 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: args: release --config .github/goreleaser.yml + release_docker: + name: Release Docker Images + needs: test + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx @@ -58,21 +64,16 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker meta id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 + uses: docker/metadata-action@v4 with: images: jpillora/chisel tag-latest: true - # Outputs: - # jpillora/chisel:1.2.3 - # jpillora/chisel:1.2 - # jpillora/chisel:1 - # jpillora/chisel:latest - tag-semver: | - {{version}} - {{major}}.{{minor}} - {{major}} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} - name: Build and push - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 with: context: . platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7,linux/arm/v6 diff --git a/Dockerfile b/Dockerfile index e3e2073e..ae77d376 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,16 @@ # build stage -FROM golang:alpine AS build-env +FROM golang:1.19 as build LABEL maintainer="dev@jpillora.com" -RUN apk update -RUN apk add git ENV CGO_ENABLED 0 ADD . /src WORKDIR /src +RUN go mod download RUN go build \ -ldflags "-X github.com/jpillora/chisel/share.BuildVersion=$(git describe --abbrev=0 --tags)" \ -o chisel -# container stage -FROM alpine -RUN apk update && apk add --no-cache ca-certificates +# run stage +FROM gcr.io/distroless/static-debian11 WORKDIR /app -COPY --from=build-env /src/chisel /app/chisel -ENTRYPOINT ["/app/chisel"] +CMD ["/app"] +COPY --from=build /src/chisel /app/chisel +ENTRYPOINT ["/app/chisel"] \ No newline at end of file From e546a6d6cbc120d4acb25b043ad146a17a630036 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sat, 28 Jan 2023 07:59:05 +1100 Subject: [PATCH 15/29] docker to use scratch --- .github/workflows/ci.yml | 3 +-- Dockerfile | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9c0001b..9d323980 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Build - run: go build -v . + run: go build -v -o /dev/null . - name: Test run: go test -v ./... # ================ @@ -67,7 +67,6 @@ jobs: uses: docker/metadata-action@v4 with: images: jpillora/chisel - tag-latest: true tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} diff --git a/Dockerfile b/Dockerfile index ae77d376..3df37478 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,8 +9,8 @@ RUN go build \ -ldflags "-X github.com/jpillora/chisel/share.BuildVersion=$(git describe --abbrev=0 --tags)" \ -o chisel # run stage -FROM gcr.io/distroless/static-debian11 +FROM scratch +COPY --from=alpine:latest /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ WORKDIR /app -CMD ["/app"] COPY --from=build /src/chisel /app/chisel ENTRYPOINT ["/app/chisel"] \ No newline at end of file From e78ccc3497bc72500438c5d208d93e72ee9d7cfa Mon Sep 17 00:00:00 2001 From: Guillaume SMAHA Date: Fri, 27 Jan 2023 22:00:02 +0100 Subject: [PATCH 16/29] Fix missing NetDialContext: c.config.DialContext (#398) --- client/client_connect.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/client_connect.go b/client/client_connect.go index 8841d0ca..884c7647 100644 --- a/client/client_connect.go +++ b/client/client_connect.go @@ -64,7 +64,7 @@ func (c *Client) connectionLoop(ctx context.Context) error { return nil } -//connectionOnce connects to the chisel server and blocks +// connectionOnce connects to the chisel server and blocks func (c *Client) connectionOnce(ctx context.Context) (connected bool, err error) { //already closed? select { @@ -82,6 +82,7 @@ func (c *Client) connectionOnce(ctx context.Context) (connected bool, err error) TLSClientConfig: c.tlsConfig, ReadBufferSize: settings.EnvInt("WS_BUFF_SIZE", 0), WriteBufferSize: settings.EnvInt("WS_BUFF_SIZE", 0), + NetDialContext: c.config.DialContext, } //optional proxy if p := c.proxyURL; p != nil { From feb571f714f193f5bb13f45c59bcbce881c2df61 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sat, 28 Jan 2023 08:06:36 +1100 Subject: [PATCH 17/29] actions: setup go v3 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d323980..9911b256 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - name: Checkout code From 5ad1141361e10c4eb058ee8e7a87d2e481e17929 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sat, 28 Jan 2023 10:42:29 +1100 Subject: [PATCH 18/29] switch to scratch image --- .github/workflows/ci.yml | 4 ++-- Dockerfile | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9911b256..2469f7e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,9 +58,9 @@ jobs: id: buildx uses: docker/setup-buildx-action@v1 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: - username: ${{ secrets.DOCKERHUB_USERNAME }} + username: jpillora password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker meta id: docker_meta diff --git a/Dockerfile b/Dockerfile index 3df37478..8d2f8ccf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,16 @@ # build stage -FROM golang:1.19 as build -LABEL maintainer="dev@jpillora.com" -ENV CGO_ENABLED 0 +FROM golang:alpine AS build +RUN apk update && apk add git ADD . /src WORKDIR /src -RUN go mod download +ENV CGO_ENABLED 0 RUN go build \ -ldflags "-X github.com/jpillora/chisel/share.BuildVersion=$(git describe --abbrev=0 --tags)" \ - -o chisel + -o /tmp/bin # run stage FROM scratch -COPY --from=alpine:latest /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +LABEL maintainer="dev@jpillora.com" +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ WORKDIR /app -COPY --from=build /src/chisel /app/chisel -ENTRYPOINT ["/app/chisel"] \ No newline at end of file +COPY --from=build /tmp/bin /app/bin +ENTRYPOINT ["/app/bin"] \ No newline at end of file From 3bdf6afc2d96f9146c21f54cc58cf0c1df6a66be Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sat, 28 Jan 2023 10:58:39 +1100 Subject: [PATCH 19/29] update dependabot --- .github/dependabot.yml | 4 ++-- .github/gocompare.sh | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) delete mode 100755 .github/gocompare.sh diff --git a/.github/dependabot.yml b/.github/dependabot.yml index eafdd78e..2dd92b7b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,10 +4,10 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "daily" + interval: "monthly" # Dependencies listed in go.mod - package-ecosystem: "gomod" directory: "/" # Location of package manifests schedule: - interval: "weekly" + interval: "monthly" diff --git a/.github/gocompare.sh b/.github/gocompare.sh deleted file mode 100755 index e3496950..00000000 --- a/.github/gocompare.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# TODO -gocompat compare \ - --go1compat \ - --log-level=debug \ - --git-refs=origin/master..$(git rev-parse --abbrev-ref HEAD) \ - ./... From ce307e580ce0cf2ca948ef44a0b934d86b953e7f Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sat, 28 Jan 2023 17:01:37 +1100 Subject: [PATCH 20/29] move chisel to flyio --- .github/goreleaser.yml | 1 + example/Flyfile | 2 ++ example/fly.toml | 13 +++++++++++++ 3 files changed, 16 insertions(+) create mode 100644 example/Flyfile create mode 100644 example/fly.toml diff --git a/.github/goreleaser.yml b/.github/goreleaser.yml index ec2cdf25..64cb3025 100644 --- a/.github/goreleaser.yml +++ b/.github/goreleaser.yml @@ -35,6 +35,7 @@ archives: files: - none* release: + draft: true prerelease: auto changelog: sort: asc diff --git a/example/Flyfile b/example/Flyfile new file mode 100644 index 00000000..ff87edb2 --- /dev/null +++ b/example/Flyfile @@ -0,0 +1,2 @@ +FROM jpillora/chisel +ENTRYPOINT ["/app/bin", "server", "--port", "443", "--tls-domain", "chisel.jpillora.com"] \ No newline at end of file diff --git a/example/fly.toml b/example/fly.toml new file mode 100644 index 00000000..c9b12f7d --- /dev/null +++ b/example/fly.toml @@ -0,0 +1,13 @@ +app = "jp-chisel" +kill_signal = "SIGINT" +kill_timeout = 5 +processes = [] + +[build] + dockerfile = "Flyfile" + +[[services]] + internal_port = 443 + protocol = "tcp" + [[services.ports]] + port = "443" \ No newline at end of file From 69093be1d960e330369de180e06b98f3fe87875f Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sat, 19 Aug 2023 11:00:41 +1000 Subject: [PATCH 21/29] Bump to Go 1.21 (#440) Co-authored-by: cmeng --- .github/workflows/ci.yml | 2 +- README.md | 56 +++++++++++------ client/client.go | 20 +++--- client/client_test.go | 7 +-- go.mod | 20 +++--- go.sum | 38 +++++------ main.go | 35 ++++++++++- server/server.go | 37 +++++++++-- share/ccrypto/generate_key_go119.go | 42 +++++++++++++ share/ccrypto/keys.go | 32 +++++----- share/ccrypto/keys_helpers.go | 97 +++++++++++++++++++++++++++++ 11 files changed, 298 insertions(+), 88 deletions(-) create mode 100644 share/ccrypto/generate_key_go119.go create mode 100644 share/ccrypto/keys_helpers.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2469f7e3..b79e1621 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: diff --git a/README.md b/README.md index ee3da3ad..3af60c8e 100644 --- a/README.md +++ b/README.md @@ -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: { @@ -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. @@ -341,7 +355,7 @@ $ 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 @@ -349,30 +363,34 @@ Using the `--authfile` option, the server may optionally provide a `user.json` c 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 '' -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=' :9312 socks -``` + ```sh + chisel client --fingerprint '' :9312 socks + ``` -3. Point your SOCKS5 clients (e.g. OS/Browser) to: +1. Point your SOCKS5 clients (e.g. OS/Browser) to: -``` -:1080 -``` + ``` + :1080 + ``` -4. Now you have an encrypted, authenticated SOCKS5 connection over HTTP +1. Now you have an encrypted, authenticated SOCKS5 connection over HTTP #### Caveats @@ -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 diff --git a/client/client.go b/client/client.go index 793e4304..c96edde6 100644 --- a/client/client.go +++ b/client/client.go @@ -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 @@ -45,7 +45,7 @@ type Config struct { Verbose bool } -//TLSConfig for a Client +// TLSConfig for a Client type TLSConfig struct { SkipVerify bool CA string @@ -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 @@ -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") { @@ -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{} @@ -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() @@ -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)) @@ -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 @@ -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() diff --git a/client/client_test.go b/client/client_test.go index a2a45e48..f947171a 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -1,7 +1,6 @@ package chclient import ( - "crypto/ecdsa" "crypto/elliptic" "log" "net/http" @@ -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) } @@ -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) } @@ -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) } diff --git a/go.mod b/go.mod index d3646874..dbb4a0e7 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index 0a52b5b5..6c6389f3 100644 --- a/go.sum +++ b/go.sum @@ -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= @@ -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= diff --git a/main.go b/main.go index eb50e6ca..f78ee156 100644 --- a/main.go +++ b/main.go @@ -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 = ` @@ -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: { @@ -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, "") @@ -187,6 +201,7 @@ 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) @@ -194,6 +209,18 @@ func server(args []string) { } 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") } @@ -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 { diff --git a/server/server.go b/server/server.go index b7df1282..8a702fce 100644 --- a/server/server.go +++ b/server/server.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httputil" "net/url" + "os" "regexp" "time" @@ -23,6 +24,7 @@ import ( // Config is the configuration for the chisel service type Config struct { KeySeed string + KeyFile string AuthFile string Auth string Proxy string @@ -73,13 +75,38 @@ func NewServer(c *Config) (*Server, error) { server.users.AddUser(u) } } - //generate private key (optionally using seed) - key, err := ccrypto.GenerateKey(c.KeySeed) - if err != nil { - log.Fatal("Failed to generate key") + + var pemBytes []byte + var err error + if c.KeyFile != "" { + var key []byte + + if ccrypto.IsChiselKey([]byte(c.KeyFile)) { + key = []byte(c.KeyFile) + } else { + key, err = os.ReadFile(c.KeyFile) + if err != nil { + log.Fatalf("Failed to read key file %s", c.KeyFile) + } + } + + pemBytes = key + if ccrypto.IsChiselKey(key) { + pemBytes, err = ccrypto.ChiselKey2PEM(key) + if err != nil { + log.Fatalf("Invalid key %s", string(key)) + } + } + } else { + //generate private key (optionally using seed) + pemBytes, err = ccrypto.Seed2PEM(c.KeySeed) + if err != nil { + log.Fatal("Failed to generate key") + } } + //convert into ssh.PrivateKey - private, err := ssh.ParsePrivateKey(key) + private, err := ssh.ParsePrivateKey(pemBytes) if err != nil { log.Fatal("Failed to parse key") } diff --git a/share/ccrypto/generate_key_go119.go b/share/ccrypto/generate_key_go119.go new file mode 100644 index 00000000..68e59e3f --- /dev/null +++ b/share/ccrypto/generate_key_go119.go @@ -0,0 +1,42 @@ +package ccrypto + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "io" + "math/big" +) + +var one = new(big.Int).SetInt64(1) + +// This function is copied from ecdsa.GenerateKey() of Go 1.19 +func GenerateKeyGo119(c elliptic.Curve, rand io.Reader) (*ecdsa.PrivateKey, error) { + k, err := randFieldElement(c, rand) + if err != nil { + return nil, err + } + + priv := new(ecdsa.PrivateKey) + priv.PublicKey.Curve = c + priv.D = k + priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) + return priv, nil +} + +// This function is copied from Go 1.19 +func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { + params := c.Params() + // Note that for P-521 this will actually be 63 bits more than the order, as + // division rounds down, but the extra bit is inconsequential. + b := make([]byte, params.N.BitLen()/8+8) + _, err = io.ReadFull(rand, b) + if err != nil { + return + } + + k = new(big.Int).SetBytes(b) + n := new(big.Int).Sub(params.N, one) + k.Mod(k, n) + k.Add(k, one) + return +} diff --git a/share/ccrypto/keys.go b/share/ccrypto/keys.go index 91d875aa..d6d71305 100644 --- a/share/ccrypto/keys.go +++ b/share/ccrypto/keys.go @@ -1,36 +1,34 @@ package ccrypto import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" "crypto/sha256" - "crypto/x509" "encoding/base64" - "encoding/pem" "fmt" + "os" "golang.org/x/crypto/ssh" ) -//GenerateKey for use as an SSH private key +// GenerateKey generates a PEM key func GenerateKey(seed string) ([]byte, error) { - r := rand.Reader - if seed != "" { - r = NewDetermRand([]byte(seed)) - } - priv, err := ecdsa.GenerateKey(elliptic.P256(), r) + return Seed2PEM(seed) +} + +// GenerateKeyFile generates an ChiselKey +func GenerateKeyFile(keyFilePath, seed string) error { + chiselKey, err := seed2ChiselKey(seed) if err != nil { - return nil, err + return err } - b, err := x509.MarshalECPrivateKey(priv) - if err != nil { - return nil, fmt.Errorf("Unable to marshal ECDSA private key: %v", err) + + if keyFilePath == "-" { + fmt.Print(string(chiselKey)) + return nil } - return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}), nil + return os.WriteFile(keyFilePath, chiselKey, 0600) } -//FingerprintKey calculates the SHA256 hash of an SSH public key +// FingerprintKey calculates the SHA256 hash of an SSH public key func FingerprintKey(k ssh.PublicKey) string { bytes := sha256.Sum256(k.Marshal()) return base64.StdEncoding.EncodeToString(bytes[:]) diff --git a/share/ccrypto/keys_helpers.go b/share/ccrypto/keys_helpers.go new file mode 100644 index 00000000..5e21c8bd --- /dev/null +++ b/share/ccrypto/keys_helpers.go @@ -0,0 +1,97 @@ +package ccrypto + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "strings" +) + +const ChiselKeyPrefix = "ck-" + +// Relations between entities: +// +// .............> PEM <........... +// . ^ . +// . | . +// . | . +// Seed -------> PrivateKey . +// . ^ . +// . | . +// . V . +// ..........> ChiselKey ......... + +func Seed2PEM(seed string) ([]byte, error) { + privateKey, err := seed2PrivateKey(seed) + if err != nil { + return nil, err + } + + return privateKey2PEM(privateKey) +} + +func seed2ChiselKey(seed string) ([]byte, error) { + privateKey, err := seed2PrivateKey(seed) + if err != nil { + return nil, err + } + + return privateKey2ChiselKey(privateKey) +} + +func seed2PrivateKey(seed string) (*ecdsa.PrivateKey, error) { + if seed == "" { + return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + } else { + return GenerateKeyGo119(elliptic.P256(), NewDetermRand([]byte(seed))) + } +} + +func privateKey2ChiselKey(privateKey *ecdsa.PrivateKey) ([]byte, error) { + b, err := x509.MarshalECPrivateKey(privateKey) + if err != nil { + return nil, err + } + + encodedPrivateKey := make([]byte, base64.RawStdEncoding.EncodedLen(len(b))) + base64.RawStdEncoding.Encode(encodedPrivateKey, b) + + return append([]byte(ChiselKeyPrefix), encodedPrivateKey...), nil +} + +func privateKey2PEM(privateKey *ecdsa.PrivateKey) ([]byte, error) { + b, err := x509.MarshalECPrivateKey(privateKey) + if err != nil { + return nil, err + } + + return pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}), nil +} + +func chiselKey2PrivateKey(chiselKey []byte) (*ecdsa.PrivateKey, error) { + rawChiselKey := chiselKey[len(ChiselKeyPrefix):] + + decodedPrivateKey := make([]byte, base64.RawStdEncoding.DecodedLen(len(rawChiselKey))) + _, err := base64.RawStdEncoding.Decode(decodedPrivateKey, rawChiselKey) + if err != nil { + return nil, err + } + + return x509.ParseECPrivateKey(decodedPrivateKey) +} + +func ChiselKey2PEM(chiselKey []byte) ([]byte, error) { + privateKey, err := chiselKey2PrivateKey(chiselKey) + if err == nil { + return privateKey2PEM(privateKey) + } + + return nil, err +} + +func IsChiselKey(chiselKey []byte) bool { + return strings.HasPrefix(string(chiselKey), ChiselKeyPrefix) +} From 4eb9e6a87ff57d16c94fe01f98d31d455ab4f759 Mon Sep 17 00:00:00 2001 From: maurerr Date: Sun, 20 Aug 2023 09:50:40 +0300 Subject: [PATCH 22/29] add arm v5 builds (#395) --- .github/goreleaser.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/goreleaser.yml b/.github/goreleaser.yml index 64cb3025..d0cece00 100644 --- a/.github/goreleaser.yml +++ b/.github/goreleaser.yml @@ -25,6 +25,7 @@ builds: - mips64le - s390x goarm: + - 5 - 6 - 7 gomips: From dca1156401f33bc1a420b07be5e4c2fb0a965903 Mon Sep 17 00:00:00 2001 From: guangwu Date: Thu, 19 Oct 2023 19:58:31 +0800 Subject: [PATCH 23/29] chore: remove refs to deprecated io/ioutil (#459) thanks @testwill --- client/client.go | 4 ++-- main.go | 3 +-- server/server_listen.go | 5 ++--- share/cio/stdio.go | 3 +-- share/settings/users.go | 4 ++-- share/tunnel/tunnel.go | 4 ++-- test/bench/main.go | 3 +-- test/e2e/cert_utils_test.go | 15 +++++++-------- test/e2e/setup_test.go | 6 +++--- 9 files changed, 21 insertions(+), 26 deletions(-) diff --git a/client/client.go b/client/client.go index c96edde6..49b62e65 100644 --- a/client/client.go +++ b/client/client.go @@ -8,10 +8,10 @@ import ( "encoding/base64" "errors" "fmt" - "io/ioutil" "net" "net/http" "net/url" + "os" "regexp" "strings" "time" @@ -118,7 +118,7 @@ func NewClient(c *Config) (*Client, error) { tc.InsecureSkipVerify = true } else if c.TLS.CA != "" { rootCAs := x509.NewCertPool() - if b, err := ioutil.ReadFile(c.TLS.CA); err != nil { + if b, err := os.ReadFile(c.TLS.CA); err != nil { return nil, fmt.Errorf("Failed to load file: %s", c.TLS.CA) } else if ok := rootCAs.AppendCertsFromPEM(b); !ok { return nil, fmt.Errorf("Failed to decode PEM: %s", c.TLS.CA) diff --git a/main.go b/main.go index f78ee156..525a2c7d 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,6 @@ package main import ( "flag" "fmt" - "io/ioutil" "log" "net/http" "os" @@ -89,7 +88,7 @@ var commonHelp = ` func generatePidFile() { pid := []byte(strconv.Itoa(os.Getpid())) - if err := ioutil.WriteFile("chisel.pid", pid, 0644); err != nil { + if err := os.WriteFile("chisel.pid", pid, 0644); err != nil { log.Fatal(err) } } diff --git a/server/server_listen.go b/server/server_listen.go index a7dcfe84..f6eb1ffa 100644 --- a/server/server_listen.go +++ b/server/server_listen.go @@ -4,7 +4,6 @@ import ( "crypto/tls" "crypto/x509" "errors" - "io/ioutil" "net" "os" "os/user" @@ -116,7 +115,7 @@ func addCA(ca string, c *tls.Config) error { clientCAPool := x509.NewCertPool() if fileInfo.IsDir() { //this is a directory holding CA bundle files - files, err := ioutil.ReadDir(ca) + files, err := os.ReadDir(ca) if err != nil { return err } @@ -140,7 +139,7 @@ func addCA(ca string, c *tls.Config) error { } func addPEMFile(path string, pool *x509.CertPool) error { - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { return err } diff --git a/share/cio/stdio.go b/share/cio/stdio.go index 24798def..16327989 100644 --- a/share/cio/stdio.go +++ b/share/cio/stdio.go @@ -2,7 +2,6 @@ package cio import ( "io" - "io/ioutil" "os" ) @@ -11,6 +10,6 @@ var Stdio = &struct { io.ReadCloser io.Writer }{ - ioutil.NopCloser(os.Stdin), + io.NopCloser(os.Stdin), os.Stdout, } diff --git a/share/settings/users.go b/share/settings/users.go index ea57f280..a6f0a093 100644 --- a/share/settings/users.go +++ b/share/settings/users.go @@ -4,7 +4,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "os" "regexp" "sync" @@ -125,7 +125,7 @@ func (u *UserIndex) loadUserIndex() error { if u.configFile == "" { return errors.New("configuration file not set") } - b, err := ioutil.ReadFile(u.configFile) + b, err := os.ReadFile(u.configFile) if err != nil { return fmt.Errorf("Failed to read auth file: %s, error: %s", u.configFile, err) } diff --git a/share/tunnel/tunnel.go b/share/tunnel/tunnel.go index 0cfba6fa..c22b737a 100644 --- a/share/tunnel/tunnel.go +++ b/share/tunnel/tunnel.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "errors" - "io/ioutil" + "io" "log" "os" "sync" @@ -57,7 +57,7 @@ func New(c Config) *Tunnel { //setup socks server (not listening on any port!) extra := "" if c.Socks { - sl := log.New(ioutil.Discard, "", 0) + sl := log.New(io.Discard, "", 0) if t.Logger.Debug { sl = log.New(os.Stdout, "[socks]", log.Ldate|log.Ltime) } diff --git a/test/bench/main.go b/test/bench/main.go index 091f2d5d..f47b10c1 100644 --- a/test/bench/main.go +++ b/test/bench/main.go @@ -17,7 +17,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "log" "net/http" "os" @@ -86,7 +85,7 @@ func testTunnel(port string, size int) { fatal(err) } - n, err := io.Copy(ioutil.Discard, resp.Body) + n, err := io.Copy(io.Discard, resp.Body) if err != nil { fatal(err) } diff --git a/test/e2e/cert_utils_test.go b/test/e2e/cert_utils_test.go index 379e282b..f71a13dd 100644 --- a/test/e2e/cert_utils_test.go +++ b/test/e2e/cert_utils_test.go @@ -11,7 +11,6 @@ import ( "crypto/x509/pkix" "encoding/pem" "fmt" - "io/ioutil" "math/big" "net" "os" @@ -53,7 +52,7 @@ func newTestTLSConfig() (*tlsConfig, error) { return nil, err } - tlsConfig.tmpDir, err = ioutil.TempDir("", "") + tlsConfig.tmpDir, err = os.MkdirTemp("", "") if err != nil { return nil, err } @@ -63,7 +62,7 @@ func newTestTLSConfig() (*tlsConfig, error) { return nil, err } pathServerCACrt := path.Join(dirServerCA, "client.crt") - if err := ioutil.WriteFile(pathServerCACrt, clientCertPEM, 0666); err != nil { + if err := os.WriteFile(pathServerCACrt, clientCertPEM, 0666); err != nil { return nil, err } @@ -72,7 +71,7 @@ func newTestTLSConfig() (*tlsConfig, error) { return nil, err } pathClientCACrt := path.Join(dirClientCA, "server.crt") - if err := ioutil.WriteFile(pathClientCACrt, serverCertPEM, 0666); err != nil { + if err := os.WriteFile(pathClientCACrt, serverCertPEM, 0666); err != nil { return nil, err } @@ -81,11 +80,11 @@ func newTestTLSConfig() (*tlsConfig, error) { return nil, err } pathServerCrtCrt := path.Join(dirServerCrt, "server.crt") - if err := ioutil.WriteFile(pathServerCrtCrt, serverCertPEM, 0666); err != nil { + if err := os.WriteFile(pathServerCrtCrt, serverCertPEM, 0666); err != nil { return nil, err } pathServerCrtKey := path.Join(dirServerCrt, "server.key") - if err := ioutil.WriteFile(pathServerCrtKey, serverKeyPEM, 0666); err != nil { + if err := os.WriteFile(pathServerCrtKey, serverKeyPEM, 0666); err != nil { return nil, err } @@ -94,11 +93,11 @@ func newTestTLSConfig() (*tlsConfig, error) { return nil, err } pathClientCrtCrt := path.Join(dirClientCrt, "client.crt") - if err := ioutil.WriteFile(pathClientCrtCrt, clientCertPEM, 0666); err != nil { + if err := os.WriteFile(pathClientCrtCrt, clientCertPEM, 0666); err != nil { return nil, err } pathClientCrtKey := path.Join(dirClientCrt, "client.key") - if err := ioutil.WriteFile(pathClientCrtKey, clientKeyPEM, 0666); err != nil { + if err := os.WriteFile(pathClientCrtKey, clientKeyPEM, 0666); err != nil { return nil, err } diff --git a/test/e2e/setup_test.go b/test/e2e/setup_test.go index c6228757..c1611bfb 100644 --- a/test/e2e/setup_test.go +++ b/test/e2e/setup_test.go @@ -2,7 +2,7 @@ package e2e_test import ( "context" - "io/ioutil" + "io" "log" "net" "net/http" @@ -36,7 +36,7 @@ func (tl *testLayout) setup(t *testing.T) (server *chserver.Server, client *chcl fileAddr := "127.0.0.1:" + filePort f := http.Server{ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - b, _ := ioutil.ReadAll(r.Body) + b, _ := io.ReadAll(r.Body) w.Write(append(b, '!')) }), } @@ -133,7 +133,7 @@ func post(url, body string) (string, error) { if err != nil { return "", err } - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { return "", err } From b75390b2b4d7edae1877c15b7ebbe5d368597fbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Dec 2023 07:44:39 +1100 Subject: [PATCH 24/29] Bump golang.org/x/crypto from 0.12.0 to 0.16.0 (#473) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index dbb4a0e7..e53e3b65 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ 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.12.0 + golang.org/x/crypto v0.16.0 golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 ) @@ -18,6 +18,6 @@ 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.11.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 6c6389f3..1f1e7676 100644 --- a/go.sum +++ b/go.sum @@ -16,16 +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.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 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.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= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= From 2efe855c4d5b3536792021216fcddd4881610051 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Dec 2023 07:45:10 +1100 Subject: [PATCH 25/29] Bump golang.org/x/sync from 0.3.0 to 0.5.0 (#472) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e53e3b65..34f0abe2 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/jpillora/sizestr v1.0.0 golang.org/x/crypto v0.16.0 golang.org/x/net v0.14.0 - golang.org/x/sync v0.3.0 + golang.org/x/sync v0.5.0 ) require ( diff --git a/go.sum b/go.sum index 1f1e7676..e2f4898d 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 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/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= From 3de177432cd23db58e57f376b62ad497cc10840f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 07:46:37 +1100 Subject: [PATCH 26/29] Bump actions/setup-go from 3 to 5 (#484) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b79e1621..846c4c35 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - name: Checkout code From 59e5362e6bd6c0ea3e02f99209a1359416a952aa Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Mon, 5 Aug 2024 15:50:20 +1000 Subject: [PATCH 27/29] Bump to Go 1.22. Add `.rpm` `.deb` and `.akp` to releases. Fix bad version comparison. --- Dockerfile => .github/Dockerfile | 0 .github/goreleaser.yml | 13 +++++++-- .github/workflows/ci.yml | 48 +++++++++++++++++++------------- LICENSE | 2 +- README.md | 3 +- main.go | 3 ++ server/server_handler.go | 16 +++++------ 7 files changed, 52 insertions(+), 33 deletions(-) rename Dockerfile => .github/Dockerfile (100%) diff --git a/Dockerfile b/.github/Dockerfile similarity index 100% rename from Dockerfile rename to .github/Dockerfile diff --git a/.github/goreleaser.yml b/.github/goreleaser.yml index d0cece00..0722c7bf 100644 --- a/.github/goreleaser.yml +++ b/.github/goreleaser.yml @@ -1,6 +1,6 @@ -# test this goreleaser config with: -# - cd chisel -# - goreleaser --skip-publish --rm-dist --config .github/goreleaser.yml +# test this file with +# goreleaser release --config goreleaser.yml --clean --snapshot +version: 2 builds: - env: - CGO_ENABLED=0 @@ -12,6 +12,7 @@ builds: - linux - darwin - windows + - openbsd goarch: - 386 - amd64 @@ -31,6 +32,12 @@ builds: gomips: - hardfloat - softfloat +nfpms: + - maintainer: "https://github.com/{{ .Env.GITHUB_USER }}" + formats: + - deb + - rpm + - apk archives: - format: gz files: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 846c4c35..5f2dcdfa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,33 +1,36 @@ -on: [push, pull_request] name: CI +on: + pull_request: {} + push: {} +permissions: write-all jobs: # ================ - # TEST JOB - # runs on every push and PR - # runs 2x3 times (see matrix) + # BUILD AND TEST JOB # ================ test: - name: Test + name: Build & Test strategy: matrix: - go-version: [1.21.x] + # optionally test/build across multiple platforms/Go-versions + go-version: ['1.22'] # '1.16', '1.17', '1.18, platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - - name: Install Go - uses: actions/setup-go@v5 + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@v3 + check-latest: true - name: Build run: go build -v -o /dev/null . - name: Test run: go test -v ./... # ================ - # RELEASE JOBS - # runs after a success test - # only runs on push "v*" tag + # RELEASE BINARIES (on push "v*" tag) # ================ release_binaries: name: Release Binaries @@ -41,9 +44,13 @@ jobs: if: success() uses: docker://goreleaser/goreleaser:latest env: + GITHUB_USER: ${{ github.repository_owner }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: args: release --config .github/goreleaser.yml + # ================ + # RELEASE DOCKER IMAGES (on push "v*" tag) + # ================ release_docker: name: Release Docker Images needs: test @@ -53,17 +60,16 @@ jobs: - name: Check out code uses: actions/checkout@v3 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub uses: docker/login-action@v2 with: username: jpillora password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Docker meta - id: docker_meta + id: meta uses: docker/metadata-action@v4 with: images: jpillora/chisel @@ -74,8 +80,10 @@ jobs: - name: Build and push uses: docker/build-push-action@v3 with: - context: . + file: .github/Dockerfile platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7,linux/arm/v6 push: true - tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.docker_meta.outputs.labels }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/LICENSE b/LICENSE index 7ae236f7..08d56bd7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Jaime Pillora +Copyright (c) 2024 Jaime Pillora Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3af60c8e..2b4d2fc5 100644 --- a/README.md +++ b/README.md @@ -422,7 +422,8 @@ Since WebSockets support is required: - `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) +- `1.9` - Bump to Go 1.21. Switch from `--key` seed to P256 key strings with `--key{gen,file}` (by @cmenginnz) +- `1.10` - Bump to Go 1.22. Add `.rpm` `.deb` and `.akp` to releases. Fix bad version comparison. ## License diff --git a/main.go b/main.go index 525a2c7d..01f9ca3b 100644 --- a/main.go +++ b/main.go @@ -240,6 +240,9 @@ func server(args []string) { } else if config.KeySeed == "" { config.KeySeed = settings.Env("KEY") } + if config.Auth == "" { + config.Auth = os.Getenv("AUTH") + } s, err := chserver.NewServer(config) if err != nil { log.Fatal(err) diff --git a/server/server_handler.go b/server/server_handler.go index 952aa4d8..a732e2b6 100644 --- a/server/server_handler.go +++ b/server/server_handler.go @@ -19,7 +19,7 @@ func (s *Server) handleClientHandler(w http.ResponseWriter, r *http.Request) { //websockets upgrade AND has chisel prefix upgrade := strings.ToLower(r.Header.Get("Upgrade")) protocol := r.Header.Get("Sec-WebSocket-Protocol") - if upgrade == "websocket" { + if upgrade == "websocket" { if protocol == chshare.ProtocolVersion { s.handleWebsocket(w, r) return @@ -101,13 +101,13 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, req *http.Request) { return } //print if client and server versions dont match - if c.Version != chshare.BuildVersion { - v := c.Version - if v == "" { - v = "" - } - l.Infof("Client version (%s) differs from server version (%s)", - v, chshare.BuildVersion) + cv := strings.TrimPrefix(c.Version, "v") + if cv == "" { + cv = "" + } + sv := strings.TrimPrefix(chshare.BuildVersion, "v") + if cv != sv { + l.Infof("Client version (%s) differs from server version (%s)", cv, sv) } //validate remotes for _, r := range c.Remotes { From 3208da347e4f7d38aa5d9e3def45c4b032dd0b86 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sun, 29 Sep 2024 09:32:04 +1000 Subject: [PATCH 28/29] fix chisel version in docker image (closes #228) --- .github/Dockerfile | 2 +- .github/workflows/ci.yml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/Dockerfile b/.github/Dockerfile index 8d2f8ccf..872f7e00 100644 --- a/.github/Dockerfile +++ b/.github/Dockerfile @@ -3,7 +3,7 @@ FROM golang:alpine AS build RUN apk update && apk add git ADD . /src WORKDIR /src -ENV CGO_ENABLED 0 +ENV CGO_ENABLED=0 RUN go build \ -ldflags "-X github.com/jpillora/chisel/share.BuildVersion=$(git describe --abbrev=0 --tags)" \ -o /tmp/bin diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f2dcdfa..e7fcdf8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: # optionally test/build across multiple platforms/Go-versions - go-version: ['1.22'] # '1.16', '1.17', '1.18, + go-version: ["1.22"] # '1.16', '1.17', '1.18, platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: @@ -80,10 +80,11 @@ jobs: - name: Build and push uses: docker/build-push-action@v3 with: + context: . file: .github/Dockerfile platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/386,linux/arm/v7,linux/arm/v6 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha - cache-to: type=gha,mode=max \ No newline at end of file + cache-to: type=gha,mode=max From ab8f06a83048dca0c24dc0b06932dc98df54e8b1 Mon Sep 17 00:00:00 2001 From: Jaime Pillora Date: Sun, 29 Sep 2024 09:35:05 +1000 Subject: [PATCH 29/29] always test with latest stable binaries are already released with latest goreleaser, docker image uses alpine:go, both are latest stable go, so makes sense to always test with latest stable too --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7fcdf8c..fec9b1a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: # optionally test/build across multiple platforms/Go-versions - go-version: ["1.22"] # '1.16', '1.17', '1.18, + go-version: ["stable"] # '1.16', '1.17', '1.18, platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: