ssh no ports provides a way to ssh to a remote linux host/device without that device or the client having any open ports (not even 22) on external interfaces. All network connectivity is out bound and there is no need to know the IP address the device has been given. As long as the device and client has an IP address (public or private 1918), DNS and Internet access, you will be able to connect to it.
There are five binaries:-
at_activate
: Command line tool to "cut" your atSigns cryptographic keys and place them in ~/.atsign/keys with .atKeys extension
sshnpd
: The daemon that runs on the remote device
sshnp
: The client that sets up a connection to the device which you
can then ssh to via your localhost interface
srvd
: This daemon acts as a rendezvous service and provides Internet routable IP/Ports for sshnpd and srv to connect to
srv
: This client is called by sshnp to connect the local sshd to the rendezvous point
To get going you just need two (or three if you want to use your own srvd service) atSigns and their .atKeys files and the
binaries (from the
latest release).
Once you have the atSigns (free or paid atSigns from atsign.com), drop the binaries in place
on each machine and put the keys in ~/.atsign/keys
directory. You will need
a device atSign and a manager atSign, but each device can also have a unique
device name using the --device argument.
Once in place you can start up the daemon first on the remote device. Remember to start the daemon on start up using rc.local script or similar, examples can be found in the templates directory in this package and in the release tar files. The daemon machine has to be running sshd even if only listening on localhost on an open port.
sshnpd.sh
: bash script
tmux-sshnpd.sh
: bash script that uses tmux
to provide realtime logging/view of the running daemon
./sshnpd --atsign <@your_devices_atsign> --manager <@your_manager_atsign> \
--device <iot_device_name> -u -s
Once that has started up you can run the client code from another machine. The client machine has to be running sshd even if only listening on localhost on an open port.
./sshnp --from <@your_manager_atsign> --to <@your_devices_atsign> \
--host <atSign of srvd or FQDN/IP of client machine> --device <iot_device_name> -s <>
The --host specifies the atSign of the srvd or the DNS name of the openssh server of the client machine that the remote device can connect to. If everything goes to plan the client will complete and tell you how to connect to the remote host for example.
Example command would be:-
./sshnp -f @cconstab -t @ssh_1 -d orac -h @stream -s id_ed25519.pub
Which would output
ssh -p 39011 cconstab@localhost -i /home/cconstab/.ssh/id_ed25519
When you run this you will be connected to the remote machine via a reverse ssh tunnel from the remote device.
If you want to do this in a single command use $(<command>)
for example, note you can specify a ssh public key so you do not get asked for passwords. Use ssh-keygen
to generate a new ssh key if you do not have one already to access the remote sshd.
$(./sshnp -f @myclient -t @myserver -d mymachine -h @myrz -s id_ed25519.pub)
Atsign provides a srvd service but if you want to run your own srvd
you will need a machine that has an internet IP and all ports 1024-65535 unfirewalled and an atSign for the daemon to use.
To run your own rendezvous service, simply run the srvd
binary. You may omit the manager atSign to allow all atSigns to use your rendezvous service. There are also flags like -s
to snoop on traffic passing through the service.
./srvd --atsign <@your_srvd_atsign> --manager <@manager_atsign> --ip <FQDN/IP address sent to clients>
If you can now login using sshnp then you can now turn off sshd from listening on all external interfaces, and instead have ssh listen only on 127.0.0.1.
That is easily done by editing /etc/ssh/sshd_config
#Port 22
#AddressFamily any
ListenAddress 127.0.0.1
#ListenAddress ::
And restarting the ssh daemon. Please make sure you start the sshnpd on startup and reboot and check. As this is beta code it is suggested to wrap the daemon in a shell script or have sysctld make sure it is running.
My preference whilst testing was to run the daemon in TMUX so that it is easy to see the logs (-v).
The daemon can also be deployed as part of a pre-built docker container,
that also has a number of networking tools installed. The container image
is located on Dockerhub as atsigncompany/sshnpd:latest
or you can build
your own using the Dockerfile in the templates folder.
The image expects to have the atKeys for the atSign being used in the
/atsign/.atsign/keys
directory, this can be mounted as a volume at startup
of the docker run command using -v $(pwd):/atsign/.atsign/keys/
assuming
you are in the directory where the atKeys file is located. The full command
to start the container would be something like this:-
docker run -v <location of atKeys>:/atsign/.atsign/keys/ atsigncompany/sshnpd "-a <atSign> -m <atSign> -d <device name> -v -u -s"
Once the container is running to log into the container the sshnp command would be used as normal, but you will log into the container not the host, from the container you could then log into the host or any other local network hosts you have access to.
Docker is very well documented and if you want to keep the container running after a reboot if for some reason the container crashes is all easily achieved.
The scripts directory of this repo contains an example sshnpd.sh
that can
be run in a user's home directory (and assumes that the release has been
untar
'd there too).
Copy the file of interest to your home directory, so the next release does not over write your config e.g.
cp ~/sshnp/sshnpd.sh ~/sshnpd.sh
Make sure to replace the placeholders for sending receiving and .
You might also want to add a crontab entry to run the script on reboot:
@reboot ~/sshnpd.sh > ~/sshnpd.log 2>&1
tmux-sshnpd.sh
and tmux-srvd.sh
- the power of tmux, highly recommended if tmux is installed sudo apt install tmux
This runs the daemon inside a tmux session, which can be connected to in order to see logs.
Copy the file of interest to your home directory, so the next release does not over write your config, e.g.
cp ~/sshnp/tmux-sshnpd.sh ~/tmux-sshnpd.sh
Once again, ensure that the placeholders are replaced, and this can be run by cron using:
@reboot ~/tmux-sshnpd.sh > ~/sshnpd.log 2>&1
The systemd directory contains an example unit file with its own README.
Created by Atsign
Thoughts/bugs/contributions via PR all very welcome!
Original code by @cconstab