Thank you for your interest in contributing to sshpiper. Make sure you have read README.md before starting.
- Go https://go.dev/
- Docker https://www.docker.com/
- Docker Compose https://docs.docker.com/compose/install/
- Git https://git-scm.com/
rememeber to clone the submodules
git clone https://github.com/tg123/sshpiper
cd sshpiper
git submodule update --init --recursive
Note: in vscode, you can use Reopen in dev container to start the develop environment.
# in e2e folder, run:
SSHPIPERD_DEBUG=1 docker-compose up --force-recreate --build -d
you will have two sshd:
host-password:2222
: a password only sshd server (user:user
, password:pass
)host-publickey:2222
: a public key only sshd server (put your public key in/sshconfig_publickey/.config/authorized_keys
)
more settings: https://github.com/linuxserver/docker-openssh-server
after you have done, attach to testrunner container:
docker exec -ti e2e_testrunner_1 bash
then run test in /src/e2e
go test
The crypto
folder contains the source code of the sshpiper seasoned cryto ssh lib.
It based on crypto/ssh and with a drop-in sshpiper.go to expose all low level sshpiper required APIs.
sshpiperd is the daemon wraps the crypto/ssh
library to provide ssh connections management.
It accepts ssh connections from downstream
and routes them to upstream
.
The plugins are responsible to figure out how to authenticate downstream
and map it to upstream
The plugin is typically a grpc server that accepts requrests from sshpiperd
.
The proto defines in sshpiper.proto.
In most of the cases, the plugin connects with sshpiperd
via stdin/stdout
. The ioconnn wraps stdin/stdout to net.Conn for grpc use.
sshpiperd
also supports to create remote grpc connections to a plugin deploy in a different machine.
fixed and simplematch are two good examples of plugins. They are very simple and just less than 50 lines of code.
Take fixed
as an example:
&libplugin.SshPiperPluginConfig{
PasswordCallback: func(conn libplugin.ConnMetadata, password []byte) (*libplugin.Upstream, error) {
return &libplugin.Upstream{
Host: host,
Port: int32(port),
IgnoreHostKey: true,
Auth: libplugin.CreatePasswordAuth(password),
}, nil
},
}
Here means the downstream
is sending password to sshpiperd
. Then sshpiperd
will call plugin's PasswordCallback
to get the upstream
to connect to.
The upstream
object contains host port and auth info about how to connect to the upstream
. you can aslo return an error to deny the connection.
simple build it with:
go build -tags full
you will get the executable in the current directory. say myplugin
. start it with:
sshpiperd /path/to/myplugin