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/publickey_authorized_keys/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