Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ Since WebSockets support is required:
- client exits non-zero when `--max-retry-count` is exhausted; new `--min-retry-interval` (default 1s); `socks5://` accepted for `--proxy`
- `go install` builds report their real version; sessions and failed logins are logged at info level
- new `--disable-forward` server flag refuses connections through forward (non-reverse) remotes; this flag is specific to this fork and is not in upstream
- refused outbound connections are logged at info level with the requested target (`Denied outbound connection to "<host:port>"`)
- releases now ship goreleaser-built multi-arch Docker images to GHCR and Docker Hub with correctly stamped versions; releasing is two-stage — tagging builds a draft GitHub release plus version-tagged images, and publishing the draft promotes the Docker `latest` / `X` / `X.Y` tags

### Upgrading to 1.12
Expand Down
3 changes: 2 additions & 1 deletion share/tunnel/tunnel_out_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ func (t *Tunnel) handleSSHChannels(ctx context.Context, chans <-chan ssh.NewChan

func (t *Tunnel) handleSSHChannel(ctx context.Context, ch ssh.NewChannel) {
if !t.Config.Outbound {
t.Debugf("Denied outbound connection")
//info-level so refusals are visible without -v; the target is client-controlled, so quote it
t.Infof("Denied outbound connection to %q", string(ch.ExtraData()))
ch.Reject(ssh.Prohibited, "Denied outbound connection")
return
}
Expand Down
46 changes: 46 additions & 0 deletions share/tunnel/tunnel_out_ssh_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package tunnel

import (
"bytes"
"testing"

"github.com/jpillora/chisel/share/cio"
"golang.org/x/crypto/ssh"
)

type rejectedChannel struct {
extra string
reason ssh.RejectionReason
message string
}

func (c *rejectedChannel) Accept() (ssh.Channel, <-chan *ssh.Request, error) {
panic("channel should not be accepted")
}

func (c *rejectedChannel) Reject(reason ssh.RejectionReason, message string) error {
c.reason, c.message = reason, message
return nil
}

func (c *rejectedChannel) ChannelType() string { return "chisel" }
func (c *rejectedChannel) ExtraData() []byte { return []byte(c.extra) }

func TestDeniedOutboundConnectionLoggedAtInfo(t *testing.T) {
var logs bytes.Buffer
logger := cio.NewLoggerFlag("server", 0)
logger.Info = true
logger.SetOutput(&logs)
tun := &Tunnel{Config: Config{Logger: logger, Outbound: false}}

ch := &rejectedChannel{extra: "example.com:80\nserver: forged"}
tun.handleSSHChannel(nil, ch)

if ch.reason != ssh.Prohibited || ch.message != "Denied outbound connection" {
t.Fatalf("unexpected rejection: %v %q", ch.reason, ch.message)
}
const want = "server: Denied outbound connection to \"example.com:80\\nserver: forged\"\n"
if got := logs.String(); got != want {
t.Fatalf("unexpected log:\n got: %q\nwant: %q", got, want)
}
}
Loading