From 843067bb8b3f42809a7e14f0faa8d6c0a9b22522 Mon Sep 17 00:00:00 2001 From: Lleyton Gray Date: Wed, 26 Mar 2025 14:32:39 -0700 Subject: [PATCH 1/3] feat: send proxy protocol headers --- go.mod | 7 +++--- go.sum | 18 ++++++++------ share/settings/remote.go | 25 ++++++++++--------- share/tunnel/tunnel_in_proxy.go | 27 ++++++++++++++++---- share/tunnel/tunnel_in_proxy_udp.go | 38 ++++++++++++++++++++--------- 5 files changed, 76 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 34f0abe2..4fe27da1 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,9 @@ 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.16.0 - golang.org/x/net v0.14.0 + github.com/pires/go-proxyproto v0.8.0 + golang.org/x/crypto v0.21.0 + golang.org/x/net v0.23.0 golang.org/x/sync v0.5.0 ) @@ -18,6 +19,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.15.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index e2f4898d..01925b20 100644 --- a/go.sum +++ b/go.sum @@ -14,18 +14,20 @@ github.com/jpillora/requestlog v1.0.0 h1:bg++eJ74T7DYL3DlIpiwknrtfdUA9oP/M4fL+Pp github.com/jpillora/requestlog v1.0.0/go.mod h1:HTWQb7QfDc2jtHnWe2XEIEeJB7gJPnVdpNn52HXPvy8= github.com/jpillora/sizestr v1.0.0 h1:4tr0FLxs1Mtq3TnsLDV+GYUWG7Q26a6s+tV5Zfw2ygw= github.com/jpillora/sizestr v1.0.0/go.mod h1:bUhLv4ctkknatr6gR42qPxirmd5+ds1u7mzD+MZ33f0= +github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0= +github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY= 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.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/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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= -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/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= diff --git a/share/settings/remote.go b/share/settings/remote.go index bfe6cbae..771708ce 100644 --- a/share/settings/remote.go +++ b/share/settings/remote.go @@ -35,7 +35,7 @@ import ( type Remote struct { LocalHost, LocalPort, LocalProto string RemoteHost, RemotePort, RemoteProto string - Socks, Reverse, Stdio bool + Socks, Reverse, Stdio, ProxyProto bool } const revPrefix = "R:" @@ -129,6 +129,9 @@ func DecodeRemote(s string) (*Remote, error) { if r.Stdio && r.Reverse { return nil, errors.New("stdio cannot be reversed") } + if r.ProxyProto && !r.Reverse { + return nil, errors.New("cannot use proxy protocol for a non-reversed remote") + } return r, nil } @@ -153,7 +156,7 @@ func isHost(s string) bool { var l4Proto = regexp.MustCompile(`(?i)\/(tcp|udp)$`) -//L4Proto extacts the layer-4 protocol from the given string +// L4Proto extacts the layer-4 protocol from the given string func L4Proto(s string) (head, proto string) { if l4Proto.MatchString(s) { l := len(s) @@ -162,7 +165,7 @@ func L4Proto(s string) (head, proto string) { return s, "" } -//implement Stringer +// implement Stringer func (r Remote) String() string { sb := strings.Builder{} if r.Reverse { @@ -177,7 +180,7 @@ func (r Remote) String() string { return sb.String() } -//Encode remote to a string +// Encode remote to a string func (r Remote) Encode() string { if r.LocalPort == "" { r.LocalPort = r.RemotePort @@ -193,7 +196,7 @@ func (r Remote) Encode() string { return local + ":" + remote } -//Local is the decodable local portion +// Local is the decodable local portion func (r Remote) Local() string { if r.Stdio { return "stdio" @@ -204,7 +207,7 @@ func (r Remote) Local() string { return r.LocalHost + ":" + r.LocalPort } -//Remote is the decodable remote portion +// Remote is the decodable remote portion func (r Remote) Remote() string { if r.Socks { return "socks" @@ -215,8 +218,8 @@ func (r Remote) Remote() string { return r.RemoteHost + ":" + r.RemotePort } -//UserAddr is checked when checking if a -//user has access to a given remote +// UserAddr is checked when checking if a +// user has access to a given remote func (r Remote) UserAddr() string { if r.Reverse { return "R:" + r.LocalHost + ":" + r.LocalPort @@ -224,7 +227,7 @@ func (r Remote) UserAddr() string { return r.RemoteHost + ":" + r.RemotePort } -//CanListen checks if the port can be listened on +// CanListen checks if the port can be listened on func (r Remote) CanListen() bool { //valid protocols switch r.LocalProto { @@ -253,7 +256,7 @@ func (r Remote) CanListen() bool { type Remotes []*Remote -//Filter out forward reversed/non-reversed remotes +// Filter out forward reversed/non-reversed remotes func (rs Remotes) Reversed(reverse bool) Remotes { subset := Remotes{} for _, r := range rs { @@ -265,7 +268,7 @@ func (rs Remotes) Reversed(reverse bool) Remotes { return subset } -//Encode back into strings +// Encode back into strings func (rs Remotes) Encode() []string { s := make([]string, len(rs)) for i, r := range rs { diff --git a/share/tunnel/tunnel_in_proxy.go b/share/tunnel/tunnel_in_proxy.go index 007fb0c7..feb49264 100644 --- a/share/tunnel/tunnel_in_proxy.go +++ b/share/tunnel/tunnel_in_proxy.go @@ -9,15 +9,16 @@ import ( "github.com/jpillora/chisel/share/cio" "github.com/jpillora/chisel/share/settings" "github.com/jpillora/sizestr" + "github.com/pires/go-proxyproto" "golang.org/x/crypto/ssh" ) -//sshTunnel exposes a subset of Tunnel to subtypes +// sshTunnel exposes a subset of Tunnel to subtypes type sshTunnel interface { getSSH(ctx context.Context) ssh.Conn } -//Proxy is the inbound portion of a Tunnel +// Proxy is the inbound portion of a Tunnel type Proxy struct { *cio.Logger sshTun sshTunnel @@ -30,7 +31,7 @@ type Proxy struct { mu sync.Mutex } -//NewProxy creates a Proxy +// NewProxy creates a Proxy func NewProxy(logger *cio.Logger, sshTun sshTunnel, index int, remote *settings.Remote) (*Proxy, error) { id := index + 1 p := &Proxy{ @@ -69,8 +70,8 @@ func (p *Proxy) listen() error { return nil } -//Run enables the proxy and blocks while its active, -//close the proxy by cancelling the context. +// Run enables the proxy and blocks while its active, +// close the proxy by cancelling the context. func (p *Proxy) Run(ctx context.Context) error { if p.remote.Stdio { return p.runStdio(ctx) @@ -144,6 +145,22 @@ func (p *Proxy) pipeRemote(ctx context.Context, src io.ReadWriteCloser) { return } go ssh.DiscardRequests(reqs) + //if proxy protocol is requested, send the header + if p.remote.ProxyProto { + conn, ok := src.(net.Conn) + if !ok { + //this should never happen, and if it does, something has gone horribly wrong (file an issue) + panic("attempted to use proxy protocol for a source which is not a network connection") + } + + header := proxyproto.HeaderProxyFromAddrs(2, conn.RemoteAddr(), conn.LocalAddr()) + s, err := header.WriteTo(dst) + if err != nil { + l.Infof("Stream error: %s", err) + return + } + l.Debugf("PROXY v2 header (sent %s)", sizestr.ToString(s)) + } //then pipe s, r := cio.Pipe(src, dst) l.Debugf("Close (sent %s received %s)", sizestr.ToString(s), sizestr.ToString(r)) diff --git a/share/tunnel/tunnel_in_proxy_udp.go b/share/tunnel/tunnel_in_proxy_udp.go index 3f3fa8be..634f63b8 100644 --- a/share/tunnel/tunnel_in_proxy_udp.go +++ b/share/tunnel/tunnel_in_proxy_udp.go @@ -4,6 +4,7 @@ import ( "context" "encoding/gob" "fmt" + "github.com/pires/go-proxyproto" "io" "net" "strings" @@ -18,18 +19,19 @@ import ( "golang.org/x/sync/errgroup" ) -//listenUDP is a special listener which forwards packets via -//the bound ssh connection. tricky part is multiplexing lots of -//udp clients through the entry node. each will listen on its -//own source-port for a response: -// (random) -// src-1 1111->... dst-1 6345->7777 -// src-2 2222->... <---> udp <---> udp <-> dst-1 7543->7777 -// src-3 3333->... listener handler dst-1 1444->7777 +// listenUDP is a special listener which forwards packets via +// the bound ssh connection. tricky part is multiplexing lots of +// udp clients through the entry node. each will listen on its +// own source-port for a response: // -//we must store these mappings (1111-6345, etc) in memory for a length -//of time, so that when the exit node receives a response on 6345, it -//knows to return it to 1111. +// (random) +// src-1 1111->... dst-1 6345->7777 +// src-2 2222->... <---> udp <---> udp <-> dst-1 7543->7777 +// src-3 3333->... listener handler dst-1 1444->7777 +// +// we must store these mappings (1111-6345, etc) in memory for a length +// of time, so that when the exit node receives a response on 6345, it +// knows to return it to 1111. func listenUDP(l *cio.Logger, sshTun sshTunnel, remote *settings.Remote) (*udpListener, error) { a, err := net.ResolveUDPAddr("udp", remote.Local()) if err != nil { @@ -102,8 +104,20 @@ func (u *udpListener) runInbound(ctx context.Context) error { } return u.Errorf("inbound-udpchan: %w", err) } - //send over channel, including source address b := buff[:n] + //if proxy protocol is requested, prepend the header + if u.remote.ProxyProto { + //NOTE: LocalAddr for UDP doesn't actually get the destination IP in the packet + //getting that information is non-trivial and non-portable from what I can see + //therefore, this will suffice for now + header := proxyproto.HeaderProxyFromAddrs(2, addr, u.inbound.LocalAddr()) + formatted, err := header.Format() + if err != nil { + return u.Errorf("header format: %w", err) + } + b = append(formatted, b...) + } + //send over channel, including source address if err := uc.encode(addr.String(), b); err != nil { if strings.HasSuffix(err.Error(), "EOF") { continue //dropped packet... From 440008dab2a482849435a0fc075091f5528a5f0e Mon Sep 17 00:00:00 2001 From: Lleyton Gray Date: Wed, 26 Mar 2025 15:26:30 -0700 Subject: [PATCH 2/3] feat: add proxy flag for reverse connections --- README.md | 9 ++++++++- main.go | 9 ++++++++- share/settings/remote.go | 18 ++++++++++++++---- share/settings/remote_test.go | 23 +++++++++++++++++++++++ test/e2e/base_test.go | 21 +++++++++++++++++++++ test/e2e/setup_test.go | 7 ++++++- 6 files changed, 80 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2b4d2fc5..961fd38b 100644 --- a/README.md +++ b/README.md @@ -237,6 +237,10 @@ $ chisel client --help which does reverse port forwarding, sharing : from the client to the server's :. + additionally, P can be appended after the R flag to send a PROXY v2 header + which can be used to identify the original source of incoming connections: + + RP::::/ example remotes @@ -247,6 +251,7 @@ $ chisel client --help socks 5000:socks R:2222:localhost:22 + RP:2222:localhost:22 R:socks R:5000:socks stdio:example.com:22 @@ -264,7 +269,9 @@ $ chisel client --help will be proxied through the client which specified the remote. Reverse remotes specifying "R:socks" will listen on the server's default socks port (1080) and terminate the connection at the - client's internal SOCKS5 proxy. + client's internal SOCKS5 proxy. Additionally, P can be appended after + the R prefix to have the chisel server pass a PROXY v2 header + which can be used to identify the original source of incoming connections. When stdio is used as local-host, the tunnel will connect standard input/output of this program with the remote. This is useful when diff --git a/main.go b/main.go index 01f9ca3b..6f0f8cf5 100644 --- a/main.go +++ b/main.go @@ -323,6 +323,10 @@ var clientHelp = ` which does reverse port forwarding, sharing : from the client to the server's :. + additionally, P can be appended after the R flag to send a PROXY v2 header + which can be used to identify the original source of incoming connections: + + RP::::/ example remotes @@ -333,6 +337,7 @@ var clientHelp = ` socks 5000:socks R:2222:localhost:22 + RP:2222:localhost:22 R:socks R:5000:socks stdio:example.com:22 @@ -350,7 +355,9 @@ var clientHelp = ` will be proxied through the client which specified the remote. Reverse remotes specifying "R:socks" will listen on the server's default socks port (1080) and terminate the connection at the - client's internal SOCKS5 proxy. + client's internal SOCKS5 proxy. Additionally, P can be appended after + the R prefix to have the chisel server pass a PROXY v2 header + which can be used to identify the original source of incoming connections. When stdio is used as local-host, the tunnel will connect standard input/output of this program with the remote. This is useful when diff --git a/share/settings/remote.go b/share/settings/remote.go index 771708ce..649a689e 100644 --- a/share/settings/remote.go +++ b/share/settings/remote.go @@ -39,10 +39,16 @@ type Remote struct { } const revPrefix = "R:" +const revProxyPrefix = "RP:" func DecodeRemote(s string) (*Remote, error) { + proxy := false reverse := false - if strings.HasPrefix(s, revPrefix) { + if strings.HasPrefix(s, revProxyPrefix) { + s = strings.TrimPrefix(s, revProxyPrefix) + reverse = true + proxy = true + } else if strings.HasPrefix(s, revPrefix) { s = strings.TrimPrefix(s, revPrefix) reverse = true } @@ -50,7 +56,7 @@ func DecodeRemote(s string) (*Remote, error) { if len(parts) <= 0 || len(parts) >= 5 { return nil, errors.New("Invalid remote") } - r := &Remote{Reverse: reverse} + r := &Remote{Reverse: reverse, ProxyProto: proxy} //parse from back to front, to set 'remote' fields first, //then to set 'local' fields second (allows the 'remote' side //to provide the defaults) @@ -168,7 +174,9 @@ func L4Proto(s string) (head, proto string) { // implement Stringer func (r Remote) String() string { sb := strings.Builder{} - if r.Reverse { + if r.Reverse && r.ProxyProto { + sb.WriteString(revProxyPrefix) + } else if r.Reverse { sb.WriteString(revPrefix) } sb.WriteString(strings.TrimPrefix(r.Local(), "0.0.0.0:")) @@ -190,7 +198,9 @@ func (r Remote) Encode() string { if r.RemoteProto == "udp" { remote += "/udp" } - if r.Reverse { + if r.Reverse && r.ProxyProto { + return "RP:" + local + ":" + remote + } else if r.Reverse { return "R:" + local + ":" + remote } return local + ":" + remote diff --git a/share/settings/remote_test.go b/share/settings/remote_test.go index b2ba39bb..9cb5f9d4 100644 --- a/share/settings/remote_test.go +++ b/share/settings/remote_test.go @@ -40,6 +40,17 @@ func TestRemoteDecode(t *testing.T) { }, "R:0.0.0.0:80:google.com:80", }, + { + "RP:google.com:80", + Remote{ + LocalPort: "80", + RemoteHost: "google.com", + RemotePort: "80", + Reverse: true, + ProxyProto: true, + }, + "RP:0.0.0.0:80:google.com:80", + }, { "示例網站.com:80", Remote{ @@ -111,6 +122,18 @@ func TestRemoteDecode(t *testing.T) { }, "R:[::]:3000:[::1]:3000", }, + { + "RP:[::]:3000:[::1]:3000", + Remote{ + LocalHost: "[::]", + LocalPort: "3000", + RemoteHost: "[::1]", + RemotePort: "3000", + Reverse: true, + ProxyProto: true, + }, + "RP:[::]:3000:[::1]:3000", + }, } { //expected defaults expected := test.Output diff --git a/test/e2e/base_test.go b/test/e2e/base_test.go index bb344cbf..a1e800a8 100644 --- a/test/e2e/base_test.go +++ b/test/e2e/base_test.go @@ -46,3 +46,24 @@ func TestReverse(t *testing.T) { t.Fatalf("expected exclamation mark added") } } + +func TestReverseProxyProtocol(t *testing.T) { + tmpPort := availablePort() + //setup server, client, fileserver + teardown := simpleSetup(t, + &chserver.Config{ + Reverse: true, + }, + &chclient.Config{ + Remotes: []string{"RP:" + tmpPort + ":$FILEPORT"}, + }) + defer teardown() + //test remote (this goes through the server and out the client) + result, err := post("http://localhost:"+tmpPort, "foo") + if err != nil { + t.Fatal(err) + } + if result != "foo!" { + t.Fatalf("expected exclamation mark added") + } +} diff --git a/test/e2e/setup_test.go b/test/e2e/setup_test.go index c1611bfb..90d4c5e6 100644 --- a/test/e2e/setup_test.go +++ b/test/e2e/setup_test.go @@ -2,6 +2,7 @@ package e2e_test import ( "context" + "github.com/pires/go-proxyproto" "io" "log" "net" @@ -44,14 +45,18 @@ func (tl *testLayout) setup(t *testing.T) (server *chserver.Server, client *chcl if err != nil { t.Fatal(err) } + pl := &proxyproto.Listener{ + Listener: fl, + } log.Printf("fileserver: listening on %s", fileAddr) go func() { - f.Serve(fl) + f.Serve(pl) cancel() }() go func() { <-ctx.Done() f.Close() + pl.Close() }() } //server From 6ab41da8db61291c154c8f2bccad3f67f44b5629 Mon Sep 17 00:00:00 2001 From: Lleyton Gray Date: Wed, 26 Mar 2025 15:34:45 -0700 Subject: [PATCH 3/3] style: restore original style --- share/settings/remote.go | 20 ++++++++++---------- share/tunnel/tunnel_in_proxy.go | 10 +++++----- share/tunnel/tunnel_in_proxy_udp.go | 23 +++++++++++------------ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/share/settings/remote.go b/share/settings/remote.go index 649a689e..1f4becb2 100644 --- a/share/settings/remote.go +++ b/share/settings/remote.go @@ -162,7 +162,7 @@ func isHost(s string) bool { var l4Proto = regexp.MustCompile(`(?i)\/(tcp|udp)$`) -// L4Proto extacts the layer-4 protocol from the given string +//L4Proto extacts the layer-4 protocol from the given string func L4Proto(s string) (head, proto string) { if l4Proto.MatchString(s) { l := len(s) @@ -171,7 +171,7 @@ func L4Proto(s string) (head, proto string) { return s, "" } -// implement Stringer +//implement Stringer func (r Remote) String() string { sb := strings.Builder{} if r.Reverse && r.ProxyProto { @@ -188,7 +188,7 @@ func (r Remote) String() string { return sb.String() } -// Encode remote to a string +//Encode remote to a string func (r Remote) Encode() string { if r.LocalPort == "" { r.LocalPort = r.RemotePort @@ -206,7 +206,7 @@ func (r Remote) Encode() string { return local + ":" + remote } -// Local is the decodable local portion +//Local is the decodable local portion func (r Remote) Local() string { if r.Stdio { return "stdio" @@ -217,7 +217,7 @@ func (r Remote) Local() string { return r.LocalHost + ":" + r.LocalPort } -// Remote is the decodable remote portion +//Remote is the decodable remote portion func (r Remote) Remote() string { if r.Socks { return "socks" @@ -228,8 +228,8 @@ func (r Remote) Remote() string { return r.RemoteHost + ":" + r.RemotePort } -// UserAddr is checked when checking if a -// user has access to a given remote +//UserAddr is checked when checking if a +//user has access to a given remote func (r Remote) UserAddr() string { if r.Reverse { return "R:" + r.LocalHost + ":" + r.LocalPort @@ -237,7 +237,7 @@ func (r Remote) UserAddr() string { return r.RemoteHost + ":" + r.RemotePort } -// CanListen checks if the port can be listened on +//CanListen checks if the port can be listened on func (r Remote) CanListen() bool { //valid protocols switch r.LocalProto { @@ -266,7 +266,7 @@ func (r Remote) CanListen() bool { type Remotes []*Remote -// Filter out forward reversed/non-reversed remotes +//Filter out forward reversed/non-reversed remotes func (rs Remotes) Reversed(reverse bool) Remotes { subset := Remotes{} for _, r := range rs { @@ -278,7 +278,7 @@ func (rs Remotes) Reversed(reverse bool) Remotes { return subset } -// Encode back into strings +//Encode back into strings func (rs Remotes) Encode() []string { s := make([]string, len(rs)) for i, r := range rs { diff --git a/share/tunnel/tunnel_in_proxy.go b/share/tunnel/tunnel_in_proxy.go index feb49264..4712cb7a 100644 --- a/share/tunnel/tunnel_in_proxy.go +++ b/share/tunnel/tunnel_in_proxy.go @@ -13,12 +13,12 @@ import ( "golang.org/x/crypto/ssh" ) -// sshTunnel exposes a subset of Tunnel to subtypes +//sshTunnel exposes a subset of Tunnel to subtypes type sshTunnel interface { getSSH(ctx context.Context) ssh.Conn } -// Proxy is the inbound portion of a Tunnel +//Proxy is the inbound portion of a Tunnel type Proxy struct { *cio.Logger sshTun sshTunnel @@ -31,7 +31,7 @@ type Proxy struct { mu sync.Mutex } -// NewProxy creates a Proxy +//NewProxy creates a Proxy func NewProxy(logger *cio.Logger, sshTun sshTunnel, index int, remote *settings.Remote) (*Proxy, error) { id := index + 1 p := &Proxy{ @@ -70,8 +70,8 @@ func (p *Proxy) listen() error { return nil } -// Run enables the proxy and blocks while its active, -// close the proxy by cancelling the context. +//Run enables the proxy and blocks while its active, +//close the proxy by cancelling the context. func (p *Proxy) Run(ctx context.Context) error { if p.remote.Stdio { return p.runStdio(ctx) diff --git a/share/tunnel/tunnel_in_proxy_udp.go b/share/tunnel/tunnel_in_proxy_udp.go index 634f63b8..7eac261d 100644 --- a/share/tunnel/tunnel_in_proxy_udp.go +++ b/share/tunnel/tunnel_in_proxy_udp.go @@ -19,19 +19,18 @@ import ( "golang.org/x/sync/errgroup" ) -// listenUDP is a special listener which forwards packets via -// the bound ssh connection. tricky part is multiplexing lots of -// udp clients through the entry node. each will listen on its -// own source-port for a response: +//listenUDP is a special listener which forwards packets via +//the bound ssh connection. tricky part is multiplexing lots of +//udp clients through the entry node. each will listen on its +//own source-port for a response: +// (random) +// src-1 1111->... dst-1 6345->7777 +// src-2 2222->... <---> udp <---> udp <-> dst-1 7543->7777 +// src-3 3333->... listener handler dst-1 1444->7777 // -// (random) -// src-1 1111->... dst-1 6345->7777 -// src-2 2222->... <---> udp <---> udp <-> dst-1 7543->7777 -// src-3 3333->... listener handler dst-1 1444->7777 -// -// we must store these mappings (1111-6345, etc) in memory for a length -// of time, so that when the exit node receives a response on 6345, it -// knows to return it to 1111. +//we must store these mappings (1111-6345, etc) in memory for a length +//of time, so that when the exit node receives a response on 6345, it +//knows to return it to 1111. func listenUDP(l *cio.Logger, sshTun sshTunnel, remote *settings.Remote) (*udpListener, error) { a, err := net.ResolveUDPAddr("udp", remote.Local()) if err != nil {