I wanted it to be possible to establish a tunnel like the following in go
$ ssh -f -L 2376:localhost:2376 \
-o ExitOnForwardFailure=yes \
-o ProxyCommand="ssh -l jumpuser1 -i /Users/abc/.ssh/id_rsa_jump_host1 10.0.0.1 -W %h:%p" \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-i /Users/abc/.ssh/id_rsa_end_host \
endhostuser@20.0.0.1 \
sleep 10
In this scenario the end host
is only accessible via the jump host
localhost:2376 --(j)--> 10.0.0.1:22 --(e)--> 20.0.0.1:2376 -> 127.0.0.1:2376
`host A` `jump host` `end host `end host`
package main
import (
"log"
"time"
fw "github.com/mavogel/go-ssh-forward"
)
func main() {
forwardConfig := &fw.Config{
JumpHostConfigs: []*fw.SSHConfig{
&fw.SSHConfig{
Address: "10.0.0.1:22",
User: "jumpuser1",
PrivateKeyFile: "/Users/abc/.ssh/id_rsa_jump_host1",
},
},
EndHostConfig: &fw.SSHConfig{
Address: "20.0.0.1:22",
User: "endhostuser",
PrivateKeyFile: "/Users/abc/.ssh/id_rsa_end_host",
},
LocalAddress: "localhost:2376",
RemoteAddress: "localhost:2376",
}
forward, forwardErrors, bootstrapErr := fw.NewForward(forwardConfig)
handleForwardErrors(forward)
defer forward.Stop()
if bootstrapErr != nil {
log.Printf("bootstrapErr: %s", bootstrapErr)
return
}
// run commands against 127.0.0.1:2376
// ...
}
func handleForwardErrors(forwardErrors chan error) {
go func() {
for {
select {
case forwardError := <-forwardErrors:
log.Printf("forward err: %s", forwardError)
case <-time.After(3 * time.Second):
log.Printf("NO forward err...")
}
}
}()
}
$ VERSION=vX.Y.Z make release
# EXAMPLE:
$ VERSION=v0.11.3 make release
Copyright (c) 2018-2021 Manuel Vogel
Source code is open source and released under the MIT license.