How to manage tons of NoPorts SSH connections with Putty
Overview
This guide will help you setup some very minimal Python scripts to manage connections with NoPorts. In most cases only 4-5 lines of python will be required to setup a new device.
Requirements
Python (version 3)
OpenSSH (acts as a proxy between NoPorts & PuTTY)
Usage
Once you've setup your configuration, you will be able to SSH over NoPorts by double clicking a simple shortcut. It will first launch NoPorts, then once NoPorts is started, it will setup your PuTTY session.
The Base Configuration
The base configuration contains all of the core logic for starting a PuTTY session over NoPorts. Copy this to the folder where you want to store all of your device configurations, name the file noports_base.py.
Open this to copy the code
noports_base.py
from subprocess import run, PIPE, Popen, CREATE_NO_WINDOW
from socket import socket
class noports_config:
# NoPorts configs
client_atsign: str
device_atsign: str
device_name: str
relay_atsign: str
openssh_keyfile: str
upload_public_key: bool = False
# Putty configs
ssh_user: str
local_host: str = "localhost"
local_port: int = None
putty_keyfile: str
def get_ephemeral_port(self) -> int:
sock = socket()
sock.bind(('', 0))
port = sock.getsockname()[1]
sock.close()
return port
def run_noports(self):
if self.local_port == None:
self.local_port = self.get_ephemeral_port()
args = ["C:\\Program Files\\NoPorts\\sshnp.exe",
"-f", self.client_atsign,
"-t", self.device_atsign,
"-d", self.device_name,
"-r", self.relay_atsign,
"-l", f"{self.local_port}",
"-i", self.openssh_keyfile,
"-u", self.ssh_user,
"-x",
]
if self.upload_public_key:
args.append("-s")
result = run(args, stdout=PIPE)
return result.stdout
def run_putty(self):
Popen(["C:\\Program Files\\PuTTY\\putty.exe",
"-proxycmd", self.run_noports(),
f"{self.ssh_user}@{self.local_host}",
"-P", f"{self.local_port}",
"-i", self.putty_keyfile,
], creationflags=CREATE_NO_WINDOW)
# TODO: Change the strings below to setup your default profile values
class my_default_config(noports_config):
client_atsign = "@alice_client"
device_atsign = "@alice_device"
relay_atsign = "@rv_am"
# path to ssh keys in openssh key format
# you may use PuTTYgen to convert from .ppk
openssh_keyfile = "C:\\Users\\chant\\.ssh\\id_ed25519"
# path to ssh keys in putty key format
# you may use PuTTYgen to convert another key to .ppk
putty_keyfile = "C:\\Users\\chant\\.ssh\\id_ed25519.ppk"
# Upload your SSH public key automatically
# -s must be enabled on sshnpd for this to work
upload_public_key = False
# The username to sign in as
ssh_user = "alice"
Setting up a new device
To setup a new device, create a new python (.py) in the same folder where you created noports_base.py. Then copy the following file:
example_config.py
from noports_base import my_default_config
class device(my_default_config):
# TODO: setup device name and override any default config here
# make sure to indent these lines the same
device_name = "my_device_name"
pass
device().run_putty()
Overriding the Default Configuration
If you have a bunch of devices that all use the same configuration values, then you'd want to put that in the noports_base configuration. However, there may be a few devices where you want to use a different value. You can simply override the value from your device profile:
override_defaults.py
from noports_base import my_default_config
class device(my_default_config):
# TODO: setup device name and override any default config here
# make sure to indent these lines the same
device_name = "my_device_name"
# Overriding the client & device atsign:
client_atsign = "@my_other_client_atsign"
device_atsign = "@my_other_device_atsign"
pass
device().run_putty()
Create Shortcuts to Organize your Profiles
Because all of the profiles need to be in the same directory as the noports_base.py file, you can't easily move those files around to organize them. To work around this, simply create shortcuts of all the device profiles, then you can move and rename those shortcuts around freely.