Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This page details everything you need to get started with NoPorts.
To make your NoPorts installation smoother and easier to understand, take a moment to watch this short video explaining NoPorts cryptographic keys.
You'll need to head over to to sign up for a NoPorts subscription or free trial.
During sign up, you will receive your atSigns. Ensure that you make note of them for reference during installation.
We offer a range of installation options to suit your needs. Choose from our quick-start guides, which let you try NoPorts with our test connection, or see our detailed, step-by-step instructions to help you set up your own machines.
NoPorts has endless use cases. We've provided a list of the most common ones:
We recommend reviewing the before beginning your installation.
Download and install the NoPorts Client on the machine you are connecting from.
NoPorts improves remote access security and simplifies network and firewall configuration. Devices using NoPorts have no exposed ports, making them undetectable on a network scan.
NoPorts shifts the security paradigm from “ports are open, I need to close them” to “ports are closed, I need to open them (securely).” Ports are closed and secure by default, allowing you to manage only the things you actively use.
Communication between devices is always peer-to-peer and end-to-end encrypted. Encryption keys are cut and stored securely on the device and controlled by the device owner.
Available via both command line and as a desktop application, NoPorts is already being used in the field to replace VPNs and firewalls, enable zero-trust remote access, improve cloud security, and apply Atsign’s preemptive security approach to a wide range of industries and use cases.
NoPorts management suite
NoPorts command line suite
Click below to learn everything you need to get started with NoPorts.
If you don't understand how something works, or if you want to see the full configuration options, check out the Usage section.
Get started with NoPorts! Find secure remote access setup instructions and installation guides for each OS on this page.
Getting Started Overview
Head over to to sign up for a subscription or free trial.
During registration, you will receive your client and device atSigns. Ensure that you make note of them for future reference.
Follow these guides to try NoPorts using the desktop application. You can establish a remote connection to our test connection page or set up a connection to your own remote machine.
Follow these detailed guides to install NoPorts via the command line and use it for establishing remote connections to your devices.
Select your operating system and remote device to see specific installation instructions.
Start by exploring the available use cases, such as , , , , , and . We also provide in-depth usage information here.
These guides also use shell scripts for installation, but they require manual invocation if you want a truly manual process.
NoPorts Policy Service
Centralizes access controls, allowing administrators to define and enforce security policies for NoPorts connections.
NoPorts Desktop Application
Allows you to make remote connections via a full desktop application for MacOS and Windows. (Also available for Linux, but we do not currently ship release builds)
NoPorts Relay
Acts as an intermediary to facilitate secure connection handshakes acting as the open network surface, so that your devices remain secure.
NoPorts Tunnel Client (npt)
Establishes secure, encrypted tunnels for remote access to any application.
NoPorts SSH Client (sshnp)
Enables remote SSH access without exposing ports by leveraging NoPorts' outbound connectivity.
NoPorts Daemon (sshnpd)
A background agent which enables a machine to act as a NoPorts “endpoint” – to this machine, or machine in the same subnet, depending on how it’s configured.

Installs at Scale
NoPorts daemon `sshnpd` additional configuration
Specify the .atKeys file for the -a, --atsign atSign if it's not stored in ~/.atsign/keys
When set, will update authorized_keys to include public key sent by manager.
Hides the device from advertising its information to the manager atSign. Even with this enabled, sshnpd will still respond to ping requests from the manager. (This takes priority over the [now deprecated] -u / --un-hide flag).
More logging
What to use for outbound ssh connections.
[openssh (default), dart]
atDirectory domain
(Defaults to "root.atsign.org")
The name of this device's group. When delegated authorization is being used then the group name is sent to the authorizer service as well as the device name, this daemon's atSign, and the client atSign which is requesting a connection
(Defaults to "__none__")
Port on which sshd is listening locally on localhost
(Defaults to "22")
When --sshpublickey is enabled, will include the specified permissions in the public key entry in authorized_keys
(Defaults to "")
The permissions which will be added to the authorized_keys file for the ephemeral public keys which are generated when a client is connecting via forward ssh e.g. PermitOpen="host-1:3389",PermitOpen="localhost:80"
(Defaults to "")
Use RSA 4096 keys rather than the default ED25519 keys
[ssh-ed25519 (default), ssh-rsa]
Directory for local storage.
(Defaults to $HOME/.atsign/storage/$atSign/.npd/$deviceName/)
Comma separated-list of host:port to which the daemon will permit a connection from an authorized client. Hosts may be dns names or ip addresses.
(Defaults to "localhost:22,localhost:3389")
Here you'll find instructions for custom operating systems or device installs.
IPFireAt its heart, NoPorts has one guiding principle behind it:
No ports should ever be open where there is any data of value.
Simply put, NoPorts improves network security while simplifying its management.
With NoPorts the paradigm shifts from "things are open, I need to close them" to "things are closed, I need to open them securely". (i.e. closed & secure by default)
NoPorts allows you to stop the impossible task of actively managing everything, instead you only need to manage the things you actually use.
When you activate an atSign, you are doing a handful of steps to prepare the atSign for use. One of these steps is cutting a unique set of cryptographic keys.
The first time you activate, this set of keys that gets generated is a set of management keys. These keys have full permissions to your atServer, the personalized service which powers your atSign.
We recommend cutting the management keys on the client for a few reasons:
It's extremely important that you don't lose these keys:
They are less likely to get lost on your client machine than on your device.
If a device is stolen you still have your management keys to recover from the theft.
For each device we can issue it's own set of cryptographic keys which has a few perks:
This allows us to limit the permissions of those keys to the bare minimum required for NoPorts.
If a device gets compromised, we can safely revoke the set of cryptographic keys associated with that device, without affecting the other devices using the same atSign.
These guides cover our most commonly asked NoPorts installation questions
While these are frequently asked questions, if you are responsible for installing NoPorts for your organization, these guides are worth reading for better understanding.
How to activate an atSignReuse your client atSign on another machineHow to name a deviceHow to generate SSH keysWhy activate the device atSign on the client?Using ssh-keygen
SSH uses keys to authenticate as well as having a fallback of using passwords, but using keys is easier and more secure than "mypassword!". If you already are a seasoned user of SSH then you might have keys already, but if not, then on the client machine you can create a key pair using ssh-keygen.
Example ssh-keygen command to create SSH Key Pair
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519Upgrading to the latest version of sshnp follows the same process as installation, as the installer automatically replaces existing binaries with the new ones.
To upgrade, follow the installation guide up to Step 3, then return to this page to verify the upgrade.
To check the current version of sshnp installed on your machine simply execute the binary:
The first line of output should contain the version information:
The first line of output should contain the version information:
The first line of output should contain the version information:
If you continue to get an old version number, it's likely that there's an old binary which wasn't replaced on the machine. Try the following to debug your binary location:
First, use this command to locate the sshnp binary:
The command should output the location of the binary which is on the PATH. Try deleting this binary then rerunning the installer.
First, use this command to locate the sshnp binary:
The command should output the location of the binary which is on the PATH. Try deleting this binary then rerunning the installer.
Since Windows doesn't include a dedicated installer, upgrading should be as simple as moving the new binary to wherever you installed the previous one.
This page describes using the policy service
The Policy Service must remain running at all times to listen for incoming requests from daemons querying the policy server.
In the context of the Policy Service, a role defines a set of access permissions that determine which atSigns can interact with specific devices or groups of devices through NoPorts.
When creating a role you will need to enter the following information:
After a role is created and saved, the atSigns listed in the User atSigns section will be able to connect to the designated ports and interact with the specified devices using the assigned device atSigns.
If using device groups, be sure the specify the device group name when running the NoPorts Daemon on your device. For example:
How to deploy NoPorts on Oracle Cloud Infrastructure using a cloud-init script
When starting a VM on OCI first click the Show advanced options button having selected the usual options above that.
Then (in the Management tab) select Paste cloud-init script
And paste your customised script into the Cloud-init script box:
#!/bin/bash
# Modify these lines to set the installation specific variables
ATCLIENT="@democlient"
ATDEVICE="@demodevice"
DEVNAME="cloudvm1"
OTP="739128"
USER="opc"
# The rest of the script shouldn't be changed
export HOME="/home/${USER}"
export SUDO_USER="${USER}"
mkdir -p /run/atsign
cd /run/atsign
VERSION=$(wget -q -O- "https://api.github.com/repos/atsign-foundation/noports/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
wget https://github.com/atsign-foundation/noports/releases/download/v${VERSION}/universal.sh
sh universal.sh -t device -c ${ATCLIENT} -d ${ATDEVICE} -n ${DEVNAME}
/usr/local/bin/at_activate enroll -a ${ATDEVICE} -s ${OTP} -p noports -k /home/${USER}/.atsign/keys/${ATDEVICE}_key.atKeys -d ${DEVNAME} -n "sshnp:rw,sshrvd:rw"
chown -R ${USER}:${USER} /home/${USER}/.atsignThe VM is now ready for Create
After a few minutes the APKAM key can be approved:
If the VM isn't quite ready you'll see:
Waiting a little longer and retrying should produce a successful approval:
The VM is now ready for connection with the NoPorts client.
In this guide, we demonstrate how to use the NoPorts Tunnel to bridge SFTP on a remote machine to localhost:2222 so we can access it in an SFTP client locally.
The command should look like:
npt -f @<client> -t @<device> -d <device name> -r @<relay> -p 22 -l 2222Example:
Now you can connect to localhost:2222 in your favorite SFTP client.
When using the NoPorts desktop application, your connection profile should look something like this:
Follow these two steps to install the NoPorts daemon so you can install your own background service.
Change directories into the unpacked download:
cd sshnpThen run the installer:
This will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
Change directories into the unpacked download:
Then run the installer:
This will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
You are on your own for setting up the background service to start sshnpd. See our other options if you need help setting this up.
You can now proceed to , or if you've already done that, check out our .
How to install NoPorts when connecting from Windows to Windows
NoPorts version <5.13.0 should follow old instructions located here: Windows to Windows Legacy
These initial steps set up the machine initiating the connection.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
A flexible suite of policy management tools. Use a standalone database to store and manage policies using our administration interface, or integrate it with your existing policy database or service.
Learn how to install it at Policy Service Installation.
The NoPorts Policy Service is currently in alpha status. Schedule a call with one of our engineers to become an alpha tester.
A streamlined application for managing remote connections.
How to deploy NoPorts on Azure using a cloud-init script
In the Azure Portal select Virtual machines and hit the + Create button.
Choose your preferred options for each sub-page of the Create a virtual machine process.
On the Advanced sub-page there's a Custom data and cloud init section where your customised script can be pasted:
It should look like this:
Once that's complete the VM is ready for Review + create
How to deploy NoPorts on Google Cloud Platform using a cloud-init script
Navigate to Compute Engine > VM instances and hit the + CREATE INSTANCE button as usual, then select Name, Region, Machine configuration etc.
Expand Advanced options at the bottom of the page:
Then scroll down and expand Management:
In the Automation section paste in your customised startup script like:
NB this script is creating a new user noports
NoPorts integrates seamlessly with Linux and macOS SSH configurations, allowing secure outbound connections via OpenSSH config.
For Windows, NoPorts works with PuTTY, enabling efficient management of multiple SSH sessions without exposed ports.
How to install NoPorts as part of creating a new VM
The NoPorts daemon can be installed on a Linux cloud virtual machine (VM) using a cloud-init script of the form:
Some clouds, such as Azure and Oracle Cloud will take the script pretty much as presented above. Other clouds, including AWS and GCP need alternate formatting or additional customisation.
In all cases the variables in the first section of the script should be changed to match the atSigns being used, the desired device name, the Linux username and the one time password (OTP) or semi-permanent passcode (SPP) being used. e.g.:
Once the VM is started (which will generally take a few minutes) the NoPorts daemon will be waiting for an APKAM key in order to start up. That key can be approved using at_activate
How to deploy NoPorts on Amazon Web Services using a cloud-init script
When launching an instance on EC2 choose settings as usual for the instance type etc.
A security group with no external ports open can be created or reused.
Expand the Advanced details section at the bottom of the Launch an Instance page:
Scroll down to the User data - optional box and paste in your customised YAML e.g.:
Which will end up looking something like this:
The VM config should now be ready for Launch instance
The following sequence diagram covers the "Happy path" for the startup of a NoPorts session. When a step fails with an error, then the client halts the process, all existing connections automatically timeout and shutdown after a short period of time.
npt -f @alice_client -t @alice_device -d my_server -r @rv_am -p 22 -l 2222-f, --fromMore logging.
The local port which will be forwarded to the remote sshd port. If this is set to "0", it defers to to the OS to assign an ephemeral port. (Defaults to "0")
The remote port which we expect sshd to be running on.
(Defaults to "22")
The username to use in the ssh session on the remote host.
(a.k.a. the user you want to sign in as)
The username to use for the initial ssh tunnel.
(a.k.a. the user running sshnpd)
Identity file to use for the ssh connection.
Passphrase for identity file.
Send the ssh public key to the remote host for automatic authorization.
Number of seconds after which inactive ssh connections will be closed
(Defaults to "15")
Additional ssh options which are passed to the ssh program.
Enable this flag to pass the -o, --local-ssh-options to the initial ssh tunnel instead of the ssh session.
Which ssh-client to use, openssh (default) or dart.
Request is to a legacy (< 4.0.0) noports daemon.
Output the ssh execution command instead of executing it.
Pass command line arguments via an environment file.
List devices which have discovery (-u) enabled.
MCP
SSH
SFTP
RDP
Web Server
SMB
Be your own VPN









./install.sh sshnpdsudo ./install.sh sshnpdcd sshnp./install.sh sshnpdsudo ./install.sh sshnpdsshnpVersion : x.x.xsshnpcommand -v sshnprm "$(command -v sshnp)"command -v sshnprm "$(command -v sshnp)"sshnp.exeVersion : x.x.xVersion : x.x.x22
Profile Name
My SFTP Connection
Device atSign
@alice_device
Device Name
my_server
Relay
@rv_am
Local Port
2222
Local Host
localhost
Remote Host
Remote Port
If your primary use case involves more than just SSH, start here, or check out some of our use cases below.
If your primary use case is SSH, start here. We also recommend the ssh config integration for a seamless experience.
Name
The role's name
Description
The role's description
Device atSigns
The device atSign(s) to which the policy role will be applied
Devices
The device name(s) associated with the device atSign along with the local ports that NoPorts has permitted for secure access
Device Groups
The device name(s) associated with a group of devices along with the local ports that NoPorts has permitted for secure access
User atSigns
The atSigns that will have access to the devices and/or device groups
a-z (lowercase letters)
0-9 (numbers)
_ (underscore)
- (dash)
Maximum of 36 characters.
Must start with a letter.
Originally we only supported alphanumeric snakecase up to 15 characters, but we loosened the constraints to support uuid v4.
./sshnpd -a @<YOUR DEVICE ATSIGN> -p @<YOUR POLICY ATSIGN> --device-group <DEVICE GROUP>my_host
canary02
oci_mail_0001
dc_001_row_009_rack_0067_ru_014
fa4969ca-9714-42a7-8edd-8d15158ce641[a-z][a-z0-9_-]{0,35}#!/bin/bash
# Modify these lines to set the installation specific variables
ATCLIENT="@changeme_clientatsign"
ATDEVICE="@changeme_deviceatsign"
DEVNAME="changeme_devicename"
OTP="123456"
USER="changeme_user"
# The rest of the script shouldn't be changed
export HOME="/home/${USER}"
export SUDO_USER="${USER}"
mkdir -p /run/atsign
cd /run/atsign
VERSION=$(wget -q -O- "https://api.github.com/repos/atsign-foundation/noports/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
wget https://github.com/atsign-foundation/noports/releases/download/v${VERSION}/universal.sh
sh universal.sh -t device -c ${ATCLIENT} -d ${ATDEVICE} -n ${DEVNAME}
/usr/local/bin/at_activate enroll -a ${ATDEVICE} -s ${OTP} -p noports -k /home/${USER}/.atsign/keys/${ATDEVICE}_key.atKeys -d ${DEVNAME} -n "sshnp:rw,sshrvd:rw"
chown -R ${USER}:${USER} /home/${USER}/.atsign#!/bin/bash
# Modify these lines to set the installation specific variables
ATCLIENT="@democlient"
ATDEVICE="@demodevice"
DEVNAME="cloudvm1"
OTP="643791"
USER="ubuntu"at_activate approve -a @democlient --arx noports --drx cloudvm1Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
@<REPLACE_NAME> with the device name from Step 6.
That's it. You can start using NoPorts or explore some of the documented use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.
at_activate.exe approve -a "@<REPLACE>_np" --arx NoPorts --drx <REPLACE_NAME>With both machines now configured, the final steps bring us back to the machine initiating the connection.
CreateAfter a few minutes the APKAM key can be approved:
If the VM isn't quite ready you'll see:
Waiting a little longer and retrying should produce a successful approval:
The VM is now ready for connection with the NoPorts client.
#!/bin/bash
# Modify these lines to set the installation specific variables
ATCLIENT="@democlient"
ATDEVICE="@demodevice"
DEVNAME="cloudvm1"
OTP="739128"
USER="azureuser"
# The rest of the script shouldn't be changed
export HOME="/home/${USER}"
export SUDO_USER="${USER}"
mkdir -p /run/atsign
cd /run/atsign
VERSION=$(wget -q -O- "https://api.github.com/repos/atsign-foundation/noports/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
wget https://github.com/atsign-foundation/noports/releases/download/v${VERSION}/universal.sh
sh universal.sh -t device -c ${ATCLIENT} -d ${ATDEVICE} -n ${DEVNAME}
/usr/local/bin/at_activate enroll -a ${ATDEVICE} -s ${OTP} -p noports -k /home/${USER}/.atsign/keys/${ATDEVICE}_key.atKeys -d ${DEVNAME} -n "sshnp:rw,sshrvd:rw"
chown -R ${USER}:${USER} /home/${USER}/.atsignIf you don't have an ssh key uploaded on the remote machine, you can upload one by adding -s to the command:
Note: this feature can be disabled in sshnpd. If you get an error when using -s, it is likely that the administrator disabled this feature for security reasons.
When using the NoPorts desktop application, your connection profile should look something like this:
Profile Name
My SSH Connection
Device atSign
@alice_device
Device Name
my_server
Relay
@rv_am
Local Port
2222
Local Host
localhost
Remote Host
Now you can interact with your OpenAPI-based MCP server by connecting to http://localhost:3001 .
When using the NoPorts desktop application, your connection profile should look something like this:
Profile Name
My MCP Connection
Device atSign
@alice_device
Device Name
my_server
Relay
@rv_am
Local Port
3001
Local Host
localhost
Remote Host
Once filled, the box should look something like:
The VM is now ready for Create
After a few minutes the APKAM key can be approved:
If the VM isn't quite ready you'll see:
Waiting a little longer and retrying should produce a successful approval:
The VM is now ready for connection with the NoPorts client.
Now you can mount the SMB share locally using the finder app ( Go->Connect to server) on MacOs
Once mounted, you can use the file share as normal. As you dismount the file share, the NPT command will disconnect.
When using the NoPorts desktop application, your connection profile should look something like this:
Profile Name
My SMB Connection
Device atSign
@alice_device
Device Name
my_server
Relay
@rv_am
Local Port
9000
Local Host
localhost
Remote Host
If the VM isn't quite ready you'll see:
Waiting a little longer and retrying should produce a successful approval:
The VM is now ready for connection with the NoPorts client.
at_activate approve -a @demodevice --arx noports --drx cloudvm1Connecting from Windows
When using the NoPorts desktop application, your connection profile should look something like this:
Profile Name
My RDP Connection
Device atSign
@alice_device
Device Name
my_server
Relay
@rv_am
Local Port
33389
Local Host
localhost
Remote Host
The command should look like:
Example:
Now you can access localhost:80 in your browser to access the web server locally.
When using the NoPorts desktop application, your connection profile should look something like this:
Profile Name
My Web Server Connection
Device atSign
@alice_device
Device Name
my_server
Relay
@rv_am
Local Port
8880
Local Host
localhost
Remote Host
Connecting from Linux
This guide provides instructions for connecting from the NoPorts desktop application, to a machine running macOS .
Complete these steps on the machine you are connecting to (MacOS)
With both machines now configured, the final steps bring us back to the machine initiating the connection.
How to install NoPorts when connecting from Linux to Windows
These initial steps set up the machine initiating the connection.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
Steps for client and device atSigns
NoPorts needs to be installed on both the machine you are going to connect to (device) and the machine you are going to connect from (client). NoPorts uses atSigns as addresses and you will need two, one for the client and one for the device.
If you don't own a pair of atSigns/addresses, please visit my.noports.com before continuing.
Example client atSign
Example device atSign
(1) Run the at_activate command for the client atSign
(2) Enter the One Time Password (OTP) & Check your SPAM/PROMOTIONS folders
at_activate will pause and wait for the input of a one time pin (OTP) before you can continue. You should receive this pin to the contact information associated with the registration of your NoPorts address (i.e. email or text message).
If you are using a gmail.com account we have seen that sometimes the OTP gets stuck in the SPAM or PROMOTIONS folder. If you do not see the OTP check those folders.
Once you receive the message, enter the pin into the application and press enter to continue. The application should proceed to create the cryptographic keys and store them in the ~/.atsign/keys/ directory with a filename that includes the atSign.
1) Run the at_activate command for the device atSign
2) Enter the One Time Password (OTP) & Check your SPAM/PROMOTIONS folders
Again, at_activate will pause and wait for the input of a one time pin (OTP) before you can continue. You should receive this pin to the contact information associated with the registration of your NoPorts address (i.e. email or text message).
If you are using a gmail.com account we have seen that sometimes the OTP gets stuck in the SPAM or PROMOTIONS folder. If you do not see the OTP check those folders.
Once you receive the message, enter the pin into the application and press enter to continue. The application should proceed to create the cryptographic keys and store them in the ~/.atsign/keys/ directory with a filename that includes the atSign.
How to install NoPorts when connecting from Windows to Linux
These initial steps set up the machine initiating the connection.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
A review of two available methods
You can:
A. Generate a new set of cryptographic keys (Recommended)
B. Copy the cryptographic keys from the machine where it's been activated in the past (Not recommended)
To generate a new set of cryptographic keys, there are three main steps. They occur from two different machines, so pay careful attention to which machine you perform each step on.
"Old machine" is the machine that has the original set of cryptographic keys that were generated. "New machine" is the device you want the new set of cryptographic keys on. These new keys will have restricted permissions that only work with NoPorts, and cannot be used for generating other keys.
[Old machine] Generate a Passcode
[New machine] Enroll the new key pair (send a request for keys from the new machine)
[Old machine] Approve the request
For detailed instructions, follow this guide:
The atSign keys file will be located at ~/.atsign/keys/ directory with a filename that will include the atSign. Copy this file from your other machine to the same location on the machine that you are installing SSH No Ports on, using scp or similar.
Why don't we recommend this approach?
When you use method A, it creates a new set of cryptographic keys. These keys can be disabled individually, which means if a device's keys are compromised, you can disable those keys without affecting your other devices.
NoPorts connection establishment and architecture
What is NoPorts? NoPorts is a zero trust security tool that uses Atsign's atPlatform to initiate connections without opening ports on either of your devices. It creates a privacy-first environment, and completely removes network attack surfaces. NoPorts is already being used in the field to do things like , and enable .
How does this technology work? In the simplest explanation, NoPorts utilizes the atPlatform and atSigns to create an encrypted connection between devices over TCP/IP. An intriguing part of this technology is that TCP ports are not open on the endpoints, and the connection is completely invisible to prying eyes with no entry-point for cybersecurity attacks. Any device or application sitting behind NoPorts has no open ports, no static IP address required, and cannot be digitally hacked! This a huge leap forward in cybersecurity as there are no other solutions that can provide this level of system security. Pretty awesome right? We think so too! To further our understanding of how zero trust security is established via NoPorts, let’s briefly discuss the function of an atSign. Then, we can explore the connectivity process with easy to follow diagrams. An atSign is a resolvable address assigned to a device, person, an entire organization, or anything you like. For example, @alice could be an atSign for a person named Alice. An atSign is used to securely exchange information without any chance of surveillance, impersonation, or theft.
Now, let’s look at a diagram of a completed atSign/NoPorts connection between two devices.
In the diagram, you can see two devices connected with atSigns (@PointA and @PointB). The connection is established without having any open external ports on the client or remote machine and any TCP application can be setup to utilize a NoPorts connection. Because all ports are closed, the atSign encrypted tunnel is set up with outbound requests only which are sent to an atServer.
at_activate approve -a @demodevice --arx noports --drx cloudvm1Found 0 matching enrollment records
No matching enrollment(s) foundFound 1 matching enrollment records
Approving enrollmentId 0bd3613d-d3e2-45b3-b175-8cab06c9bad0
Server response: AtEnrollmentResponse{enrollmentId: 0bd3613d-d3e2-45b3-b175-8cab06c9bad0, enrollStatus: EnrollmentStatus.approved}sshnp -f @<client> -t @<device> -d <device name> -r @<relay> -i <your ssh key>sshnp -f @alice_client -t @alice_device -d my_server -r @rv_am -i ~/.ssh/id_ed25519sshnp -f @alice_client -t @alice_device -d my_server -r @rv_am -i ~/.ssh/id_ed25519 -snpt -f @<client> -t @<device> -d <device name> -r @<relay> -p 3000 -l 3001npt -f @alice_client -t @alice_device -d my_server -r @rv_am -p 3000 -l 3001#!/bin/bash
# Modify these lines to set the installation specific variables
ATCLIENT="@democlient"
ATDEVICE="@demodevice"
DEVNAME="cloudvm1"
OTP="739128"
USER="noports"
# The rest of the script shouldn't be changed
useradd ${USER}
export HOME="/home/${USER}"
export SUDO_USER="${USER}"
mkdir -p /run/atsign
cd /run/atsign
VERSION=$(wget -q -O- "https://api.github.com/repos/atsign-foundation/noports/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
wget https://github.com/atsign-foundation/noports/releases/download/v${VERSION}/universal.sh
sh universal.sh -t device -c ${ATCLIENT} -d ${ATDEVICE} -n ${DEVNAME}
/usr/local/bin/at_activate enroll -a ${ATDEVICE} -s ${OTP} -p noports -k /home/${USER}/.atsign/keys/${ATDEVICE}_key.atKeys -d ${DEVNAME} -n "sshnp:rw,sshrvd:rw"
chown -R ${USER}:${USER} /home/${USER}at_activate approve -a @demodevice --arx noports --drx cloudvm1Found 0 matching enrollment records
No matching enrollment(s) foundFound 1 matching enrollment records
Approving enrollmentId 0bd3613d-d3e2-45b3-b175-8cab06c9bad0
Server response: AtEnrollmentResponse{enrollmentId: 0bd3613d-d3e2-45b3-b175-8cab06c9bad0, enrollStatus: EnrollmentStatus.approved}npt -f @<client> -t @<device> -d <device name> -r @<relay> -p 445 \
-h 192.168.1.90 -l 9000npt -f @alice_client -t @alice_device -d my_server -r @rv_am -p 445 \
-h 192.168.1.90 -l 9000#cloud-config
runcmd:
- # Modify these lines to set the installation specific variables
- ATCLIENT="@democlient"
- ATDEVICE="@demodevice"
- DEVNAME="cloudvm1"
- OTP="739128"
- USER="ec2-user"
- # The rest of the script shouldn't be changed
- export HOME="/home/${USER}"
- export SUDO_USER="${USER}"
- mkdir -p /run/atsign
- cd /run/atsign
- VERSION=$(wget -q -O- "https://api.github.com/repos/atsign-foundation/noports/releases/latest" | jq -r .tag_name)
- wget https://github.com/atsign-foundation/noports/releases/download/${VERSION}/universal.sh
- sh universal.sh -t device -c ${ATCLIENT} -d ${ATDEVICE} -n ${DEVNAME}
- /usr/local/bin/at_activate enroll -a ${ATDEVICE} -s ${OTP} -p noports -k /home/${USER}/.atsign/keys/${ATDEVICE}_key.atKeys -d ${DEVNAME} -n "sshnp:rw,sshrvd:rw"
- chown -R ${USER}:${USER} /home/${USER}/.atsignFound 0 matching enrollment records
No matching enrollment(s) foundFound 1 matching enrollment records
Approving enrollmentId 0bd3613d-d3e2-45b3-b175-8cab06c9bad0
Server response: AtEnrollmentResponse{enrollmentId: 0bd3613d-d3e2-45b3-b175-8cab06c9bad0, enrollStatus: EnrollmentStatus.approved}npt -f @<client> -t @<device> -d <device name> -r @<relay> -p 3389 -l 33389npt -f @alice_client -t @alice_device -d my_server -r @rv_am -p 3389 -l 33389npt -f @<client> -t @<device> -d <device name> -r @<relay> -p 8080 -l 80npt -f @alice_client -t @alice_device -d my_server -r @rv_am -p 8080 -l 80at_activate approve -a @demodevice --arx noports --drx cloudvm1Found 0 matching enrollment records
No matching enrollment(s) foundFound 1 matching enrollment records
Approving enrollmentId 0bd3613d-d3e2-45b3-b175-8cab06c9bad0
Server response: AtEnrollmentResponse{enrollmentId: 0bd3613d-d3e2-45b3-b175-8cab06c9bad0, enrollStatus: EnrollmentStatus.approved}Remote Port
22
Remote Port
3000
Remote Port
3389
Remote Port
8080
to macOS
to Linux
to Windows
to macOS
to Linux
to Windows
Remote Port
445

sshnpd is the daemon that runs on a device to facilitate access using NoPorts.
These mainly mirror the parameters from sshnp, but there's one fewer as the socket rendezvous is only ever set by the client.
This argument is the device address, a.k.a. the to address, since this is the address that the device is associated with. This argument is mandatory, in the form of an atSign. For example:
This is the address of the client(s) that will be allowed to connect to the device. For example:
As an alternative to defining a list of managers a policy manager can be used, and the policy defined on that manager will describe which clients are allowed to connect. For example:
The device name. This is used to associate multiple devices with the same atSign. By default the value is default so unless you want that as the device name you will need to include this parameter. For example:
An example of a complete command might look like this:
The daemon should normally be run as a service so that it starts up automatically and can be restarted if it should fail.
Most mainstream Linux distributions use systemd to manage services, and we provide a systemd unit file that's configured by the universal installer. That file can be edited after installation to customize or add additional options. For distributions such as OpenWrt we provide config and init files that can be customized with a text editor or configured through the web admin interface.
The rest of the configuration for sshnpd is contained in a separate guide:
If you installed sshnpd through the universal installer, then you can modify the /etc/systemd/system/sshnpd.service.d/override.conf file to take advantage of the configurations and options listed above to tailor sshnpd to your needs.
Lots of configuration can be done to sshnpd by editing this file, such as changing the user that sshnpd runs as, changing the atSigns, enabling/disabling verbose logging, and more.
Sample override.conffile:
Adding additional arguments is as simple as modifying the Environment=additional_args=""string found inside of override.conf .
The example adds the --permit-open to the string of additional args which enables clients to access ports 22, 3389, and 2221 on localhost.
Don't forget to update sshnpd by executing (may require sudo):
@sshnp_client@sshnp_device~/.local/bin/at_activate -a @<REPLACE>_client~/.local/bin/at_activate -a @<REPLACE>_devicesshnpd -m @<_client> -a @<_device> -d <name> sshnpd ... -a @alice_device ...sshnpd ... -m @alice_client ...sshnpd ... -p @alice_policy ...sshnpd ... -d my_device ...sshnpd -a @alice_device -m @alice_client -d my_server# MANDATORY: User to run the daemon as
User=bob
# MANDATORY: Manager (client) or policy manager address (atSign)
Environment=manager_atsign="@alice"
# MANDATORY: Device address (atSign)
Environment=device_atsign="@bob"
# OPTIONAL: Delegated access policy management
Environment=delegate_policy=""
# Device name
Environment=device_name="atsign"
# Comment if you don't want the daemon to update authorized_keys to include
# public keys sent by authorized manager atSigns
Environment=s="-s"
# Comment to disable verbose logging
Environment=v="-v"
# Any additional command line arguments for sshnpd
Environment=additional_args=""# Any additional command line arguments for sshnpd
Environment=additional_args="--permit-open \"localhost:22,localhost:3389,localhost:2221\""systemctl daemon-reload
systemctl restart sshnpd.service<DEVICE_NAME> with the name of the machine you are on
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <DEVICE_NAME> \
-n "sshnp:rw,sshrvd:rw"The install type
Enter device when prompted.
Your atSigns
Client atSign: e.g., @example01_np
Device atSign: e.g., @example02_np
Your device name
This should be the name of the machine you're currently installing on.
Run the following command to make an authorization request:
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
<PASSCODE> with the passcode generated in Step 5,
@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
Once you see this text, you're ready to continue to the next step.
After a few seconds, the request will also show as approved on the machine you are connecting to.
Click on your atSign in the top right corner of the screen. This will open a list of atSigns that are currently signed into the app.
Select your client atSign in order to switch to it.
If you aren't already on the Connections tab, click on Connections at the top of the Screen. Then click Add New, to create a new profile.
Enter the following information into the profile then click Submit.
Profile Name - The name that will be displayed in the profile list.
Device atSign - Your device atSign (eg example02_np).
Device Name - The name of your remote device.
Relay - Select the relay sever closest to you for optimum speed.
Local Port - The port you will use on your local machine.
Local Host - The hostname or IP address to bind to on your local machine.
Remote Host - The hostname or IP address of the machine you are connecting to.
Remote Port - The port that will be used on the remote machine.
For reference, we've documented our most common use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.
Click the Connect Icon ▶️ to establish a connection with your remote device. If the connection is successful, you will see green. If you see red, hover over the icon to see reason for failure.
curl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.shSubmitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
@<REPLACE_NAME> with the device name from Step 5.
That's it. You can start using NoPorts or explore some of the documented use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.
~/.local/bin/at_activate -a @<REPLACE>_np~/.local/bin/at_activate -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.sh~/.local/bin/at_activate otp -a @<REPLACE>_np~/.local/bin/at_activate approve -a @<REPLACE>_np --arx noports --drx <DEVICE_NAME>The install type
Enter device when prompted.
Your atSigns
Client atSign: e.g., @example01_np
Device atSign: e.g., @example02_np
Your device name
This should be the name of the machine you're currently installing on.
Run the following command to make an authorization request:
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
<PASSCODE> with the passcode generated in Step 4,
@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
Once you see this text, you're ready to continue to the next step.
curl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.shSubmitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <
Download the NoPorts desktop app using one of the links below:
In this installation guide, @example01_np will represent the client atSign, while @example02_np will represent the device atSign.
Launch the NoPorts desktop app and click Get Started.
Enter your client atSign into the text field (e.g., @example01_np), leave the root domain as is, and then click Next.
A one-time password (OTP) will be sent to you via email. Enter this OTP into the app and then click Confirm.
Your atKeys (cryptographic keys) will be used to pair your atSign with this and other devices in future. You can learn more about these keys here.
Click on Save atKeys
Select a memorable location on your machine and save your keys.
Both the atSigns are activated on the machine you are connecting from. Later, you’ll grant your remote machine access to the keys stored on this machine.
You'll need to switch atSigns. To sign out from the client atSign, click on your atSign at the top right of the screen, then select Sign Out.
Click Get Started and enter your device atSign into the text field (e.g., @example02_np). Leave the root domain as is, and then click Next.
A one-time password (OTP) will be sent to you via email. Enter this OTP into the app and then click Confirm.
Your atKeys (cryptographic keys) will be used to pair your atSign with this and other devices in future. You can .
Click on Save atKeys
Select a memorable location on your machine and save your keys.
Click on Authenticator at the top of the screen and then click on OTP. You will use this 4 character code in Step 7.
Please select the operating system running on the machine you are connecting to and follow the relevant instructions:
-f
required
atSign
The client atSign, a.k.a. the from atSign, since we are connecting from the client.
-t
required
atSign
The device atSign, a.k.a. the to atSign, since we are connecting to the device.
-r
required
atSign
Now, let’s discuss what an atServer is and how it functions as part of the overall atPlatform topology. An atServer is responsible for managing identity and maintaining the key-value data store for each atSign. It performs cryptographic identity validation to ensure that each entity is who they claim to be, supporting secure interactions. It serves as a secure repository and only holds data that is either explicitly made public or data that is encrypted. The atServers cannot decrypt or view any encrypted data as they do not hold the keys to decrypt it. Each atSign utilizes a separate atServer, and the atServers complete the negotiation for setting up the connection between the endpoints.
Since we now have a basic understanding of atSigns and atServers we can take a look at a more comprehensive diagram and discuss further details about the atPlatform.
Connection Establishment
So, how exactly does a NoPorts connection get established and what are the steps? Let's look at a summary overview of each step in a NoPorts connection:
NoPorts Client @pointA sends a request to NoPorts Relay service @relay to ask for an IP address and a pair of ports to rendezvous with Remote Machine @pointB.
NoPorts Relay receives the request, allocates a pair of ports on the host it is running on, responds with its IP address and the pair of ports.
Client receives response from Relay
Client sends request to the Remote Machine to connect which includes session information, the client’s intent (such as destination TCP port 3389 on localhost), and the generated public key from an ephemeral asymmetric key-pair.
NoPorts Daemon on Remote Machine sends request to NoPorts Policy service @policy to determine whether or not @pointA is permitted to connect to @pointB on the specified localhost port.
Policy service looks up information accordingly and sends response back to the daemon on Remote Machine.
If request is not allowed, the daemon will not respond to the client, or send a not permitted response.
If request is allowed, the daemon generates a symmetric encryption key and a socket connection to the Relay IP address and port 2. Response is sent to the Client for ‘session started’ and includes the symmetric encryption key which is encrypted with the ephemeral public key which was previously sent by the Client.
NoPorts daemon on Remote Machine sends response to Client as ‘session started’.
Client receives response and creates a socket to the Relay IP address and port 1.
The Relay verifies the authentication strings and joins the authenticated sockets from the Client and Remote Machine.
NoPorts connection established.
And that's it! At this point, the real client application (e.g. RDP) can connect to a local port on the Client to be sent over the NoPorts connection for secure remote access to the Remote Machine.

In this installation guide, @example01_np will represent the client atSign, while @example02_np will represent the device atSign.
Download the installer from GitHub by running the following command:
To check if the installation downloaded correctly:
Make the script executable and run the script by running the command below:
The install type
Enter client when prompted.
Your atSigns (Skip this step)
To skip this step, simply press the Enter/Return key twice. Your atSigns will be activated in the upcoming steps.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
Replace @<REPLACE>_np with your client atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
~/.local/bin/at_activate -a @<REPLACE>_np~/.local/bin/at_activate -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.sh~/.local/bin/at_activate otp -a @<REPLACE>_npThis guide provides instructions for connecting from the NoPorts desktop application, to a machine running Windows.
Complete these steps on the machine you are connecting to (Windows)
With both machines now configured, the final steps bring us back to the machine initiating the connection.
This guide covers the basics to understanding the parameters of and invoking sshnp.
This argument is the client address, a.k.a. the from address, since we are connecting from the client. This argument is mandatory, in the form of an atSign. For example:
This argument is the device address, a.k.a. the to address, since we are connecting to the device. This argument is mandatory, in the form of an atSign. For example:
This argument is the device name, which works in tandem with --to to allow multiple devices to run sshnpd under a single device name. By default, this value is "default", so unless you named your sshnpd device the same thing, you will need to include this parameter. For example:
This argument is the address of the socket rendezvous used to establish the session connection. Atsign currently provides coverage in 3 regions, use whichever is closest to you:
In addition to the four main parameters, it is important to ensure that the appropriate SSH authentication keys are in place.
If you already have an SSH public key installed on the device, use -i to specify it. For example:
If you don't have an SSH public key installed on the device, and -s is enabled for the device, then sshnp can extract the SSH public key from the SSH private key, and send it to the daemon for you. This will automatically authorize your SSH private key. For example:
If you don't have any SSH public keys in place, you must install them yourself. Copy the SSH public key to ~/.ssh/authorized_keys on the remote device. For example:
Then use the associated private key, as mentioned under :
An example of a complete command might look like this:
*Note if the username on the remote machine is different than your local machine you will have to also use the -u flag and the -U flag with the remote username. For example, if the remote username is bocbc. If you used the -u flag when running the sshnpd daemon then you can safely omit the -U flag.
The rest of the configuration for sshnp is contained in a separate guide:
The NoPorts Tunnel (NPT) can carry a wide variety of TCP based protocols such as , , and .
This guide explains how to install and run the NoPorts Policy Service via the command line, and how to use it within the NoPorts desktop application. We recommend running the Policy Server in a Linux environment (virtual machine) for easier management.
Before you begin the installation, please ensure the following steps are complete:
Subscription: You’ve signed up for a NoPorts subscription or free trial.
Installation & Activation: NoPorts is installed and atSigns are activated on at least two machines, one to connect from and one to connect to. .
NoPorts Desktop App : If you didn’t use the NoPorts desktop app during installation, you can download it here:
You're now ready to use the Policy Service. You can find instructions in the NoPorts desktop application .
Upgrading to the latest version of sshnpd follows the same process as installation, as the installer automatically replaces existing binaries with the new ones.
To upgrade, follow the installation guide up to Step 3, then return to this page to complete the process.
To check the current version of sshnpd installed on your machine, simply execute the binary:
Or, if you installed as root:
The first line of output should contain the version information:
Or if you installed as root:
The first line of output should contain the version information:
After upgrading the sshnpd binary, we must restart the sshnpd service so that it runs using the new version. How you proceed is dependent upon the original installation method you used:
The universal.shinstaller script will automatically restart the sshnpd.serviceunit.
Any existing config will be preserved.
The installer automatically restarts your tmux session, no other steps required!
To safely restart the headless service, we must be slightly more careful with the headless installation. First we must grab the process id of sshnpd:
You should get a single number as output, this is the process ID of the sshnpd process.
Example:
Before we continue, it is good practice to make sure that we have the correct ID:
Example:
As you can see, under CMD we have /home/atsign/.local/bin/sshnpd -a @atsign_device -m @atsign_client -d mydevice -suv. This is the command inside our sshnpd.sh service which used to start sshnpd. This is the correct process that we want to kill in order to restart sshnpd.
Now that we have retrieved and verified the process ID, we can use the kill command to kill the process:
Example:
Use the same verification command from before:
Example:
As you can see, there are no entries anymore. This means process 289 has been killed, sshnpd should automatically restart under a new process ID.
How to integrate NoPorts into your native Linux and macOS ssh configuration
This guide will help you setup NoPorts in your SSH configuration. Once set up, you will be able to ssh to machines using NoPorts the same way you would for a normal ssh host. As this is integrated with the SSH configuration, it will also work with other applications that support SSH proxying.
Once you've set up your configuration, you will be able to SSH over NoPorts just like any other host, using your own custom hostnames for devices.
For example, with a device called my_lab:
The following is a template for adding an sshnp connection to your ssh config for ease of use:
You need to replace the values surrounded with <> on lines 1 & 7 with your own values.
host is any valid hostname you would like, this is what you will use to invoke your ssh command, so make sure it's easy to remember and type.
username is the username on the remote machine you wish to login as.
The rest of the values are the normal arguments you would invoke with sshnp, see for more info.
This example shows the configuration for the following equivalent sshnp command:
When you want to connect to this device, this is what you would type:
alice_device maps the the Host alice_device line.
You can add any additional ssh config to the file as you normally would, for example a TCP forwarding:
You can also add any additional flags to the ssh command, for example a TCP forwarding:
If you want to understand each line of the template, and what it does, read on.
<host> is the "nickname" you would use to connect to, e.g. ssh <host>.
Line 2 is mandatory due to the nature of how sshnp works, sshnp must connect over the loopback interface where the NoPorts tunnel was created.
Tell ssh to automatically add the ssh keys to the agent when we load them (we will load them on line 6)
Don't cache the connection to known hosts, since sshnp uses ephemeral ports, it is pointless to do so.
Because we are using ephemeral ports, it is useful to suppress strict host key checking.
The ssh key you would like to load and authenticate with (this is equivalent to ssh -i).
A proxy command, which first executes sshnp to determine the ssh proxy command which will be executed, fill in the arguments on this line as you would normally.
See to learn more about filling in this line.
ControlMaster and ControlPath tell ssh to try to reuse existing ssh connections if you start up multiple. This means only the first connection will setup sshnp, the rest of the connections will use the tunnel that is already there!
Includes stable and beta releases
We recommend choosing a release from stable, if there's one available that's supported on your platform.
Our dedicated desktop app is preferred in most cases.
If your use case is primarily SSH, we recommend using sshnp from the section.
This includes all binaries for NoPorts.
These releases are subject to potential instability or breaking changes as we mature the product-line.
How to install NoPorts onto an OpenWrt router.
We now have our own package repo for the currently supported releases of OpenWrt. Please follow this guide for installing the Atsign key and adding the packages.
First download the latest packages for your chosen architecture from our page.
We've created packages for aarch64_cortex-a53, arm_cortex-a7_neon-vfpv4, mips_siflower, ramips (mipsel_24k) and x86_64; but if your chosen architecture isn't there please let us know by opening an . These packages should work on older OpenWrt (and OpenWrt derivatives like GL.iNet), though note that the LuCI package uses the JavaScript framework that was introduced in OpenWrt 21.02.
With the packages ready to go, sign into the web interface for your router and go to System> Software in the menu. Click on Upload Package and Browse to the csshnpd package you downloaded. Click Open then Upload and Install. Repeat that process with the luci-app-csshnpd package.
For the new menu to appear you'll need to Log out then sign in again.
You can now go to Network>NoPorts and fill out the config tab with your device atSign, manager atSign, device name and the OTP for key generation. Click the Enabled box then hit Save & Apply.
Now go to the NoPorts Enrollment tab and follow the instructions there to generate a device key.
With the key in place navigate to System>Startup and Start the sshnpd service.
The page includes instructions for command line installation. These will work on OpenWrt derivatives that don't use LuCI (e.g. Teltonika) or if you just prefer working on the command line.
Those command line snippets set some variables for the RELEASE number, ARCH for system architecture and PACKAGE name then use wget to download the package from GitHub.
Packages are installed using opkg install for OpenWrt 24.10 and earlier releases that use .ipk type packages, or apk add for newer OpenWrt which uses .apk packages.
For example, to install the c1.0.14 release:
Now edit /etc/config/sshnpd to use your atSigns, device name and device atSign OTP:
Run at_enroll.sh on the device. It will ask you to approvement the enrollment on your client (where you previously activated the atSigns and generated the OTP):
On the device you should see a message saying enrollment is complete, and that the .atKeys file has been written.
Now start the sshnpd service:
And you should be ready to connect to the device:
NoPorts is now upstream in SNAPSHOT builds so you can install luci-app-csshnpd from the System > Software page on LuCI. Or for a command line install run:
"Old machine" is the machine that has the original set of cryptographic keys that were generated. "New machine" is the device you want the new set of cryptographic keys on.
Choose the operating system that is running on your old machine.
Make sure to replace <REPLACE_client> with your client atSign
Choose the operating system that is running on your new machine.
Make sure to replace the appropriate values:
<REPLACE_client> with your client atSign
<client_device_name> with a unique name for the device
<PASSCODE> with the passcode from Step 1
Choose the operating system that is running on your old machine.
Make sure to replace <client_device_name> with the device name from Step 2
This guide provides instructions for connecting from the NoPorts desktop application, to a machine running Linux.
Complete these steps on the machine you are connecting to (Linux)
With both machines now configured, the final steps bring us back to the machine initiating the connection.
Using sshuttle and SSH built in SOCKS proxy.
To follow this guide, you will need to set up a NoPorts device (sshnpd)on your home network. For this, you could use a Raspberry Pi, an old PC running Linux, a virtual machine, or even a docker container—the choice is yours. You can get your NoPorts free trial account here and follow the installation guide to get started.
SSH is a hugely versatile tool for command line access, but what if you want a full IP tunnel, like a VPN?
SSH has you covered with the use of two tools: the first is a built in SOCKS proxy; the second is an open source piece of code called sshuttle. With these two tools you can use your sshnp service as your own VPN.
Once you have NoPorts up and running, you will be able to connect to your device from anywhere on the Internet. You will notice that you did not have to open any ports to the Internet in order to connect. There is no access to the device from the Internet and yet you can connect.
If you are happy with command line access only, great; but you might want to now use your SSH connection as a VPN and have a full IP tunnel. For this, is the perfect tool. However, if you are using Windows, then you will have to set up a local VM/Container. (If that sounds like too much, skip down to the section below on using SOCKS.)
To use sshuttle, we need to make sure that the SSH command itself can log in without any complex arguments. This requires two steps:
Create SSH keys: First, make sure that you have created SSH keys.
Place public keys on the remote device: Next, either:
Manual placement: Place the public keys directly on the remote device.
Once the SSH keys are in place, you can put an entry in ~/.ssh/config to let SSH know which key to use to log into localhost. For example:
The next thing to do is install sshuttle on your machine. The GitHub page details this very well for both Linux and OSX machines.
Once sshuttle is installed, let's use it!
This is a two step process:
Connect to the device using sshnp: Add the -x flag. This flag prints out the SSH command that you can cut and paste to log into the remote device.
Establish the VPN: In another terminal window, run the sshuttle command to connect to the remote device. You'll need to tweak your IP routing to use this connection as a VPN. The important part is to use the port number that the -x flag gave you in the sshuttle command.
With this example, you can see that port 63155 was used in the sshuttle command. You do not need to SSH into the machine—you can just get the port number and use sshuttle. The choice is yours.
This can get a bit tedious to do every day so feel free to script for your environment. Here is an example bash script that does just that!
If you are using Windows, this is likely your best option unless you are comfortable setting up a virtual machine and using sshuttle.
All you need to do is add an option to the normal sshnp command and that will set up a local SOCKS proxy: -o "-D 1080" That's it!
This will set up a local SOCKS proxy on your machine that will forward requests to the remote device. In effect, you will be at home whilst away. To use this SOCKS proxy, you need to tell your browser or your Operating System. The Firefox browser is the simple choice, and in settings you can configure it as shown below:
Once you have setup Firefox, you can browse as if you were at home! On Windows and Mac, you can configure your SOCKS proxy in directly in the OS in settings. This works, but you have to remember to remove the setting once you have disconnected from the sshnpd session.
TimeoutException: Connection timeout to srvd <atsign> service
Check if relay or device atSign exists
TimeoutException: Daemon feature check timed out
Ensure device name is correct and permissions are in place
Symptom You receive the following error while using NoPorts: TimeoutException: Connection timeout to srvd <atsign> service
Possible Causes
The relay atSign (-r) is not running or doesn’t exist
The device atSign (-t) doesn’t exist
Solution
Double-check the relay and device atSigns for typos
Use sshnp --list-devices to verify device availability
Symptom TimeoutException: Daemon feature check timed out
Possible Causes
No device is running with the specified device name (-d)
You lack permission to connect to the device
Solution
Confirm the device is online and registered
Ensure your atSign has permission to access the device
Symptom Keys are not found after device installation
Root Cause sshnpd was installed as root, but the enrollment was also done as root. The keys were saved to /root/.atsign/keys/ instead of the correct user directory.
Solution
Always enroll using the same user that sshnpd runs under
Add a warning in the docs or script to prevent root-based enrollment
Symptom Error message: invalid daemon response: chown failed error: Operation not permitted
Root Cause Raspberry Pi may behave inconsistently with localhost vs 127.0.0.1, or file permissions are incorrect.
Solution
Use --permit-open="127.0.0.1:22,127.0.0.1:3389,localhost:22,localhost:3389"
Ensure ~/.ssh is owned by the correct user:
Symptom NoPorts desktop app hangs on “preparing for activation”
Root Cause Outdated CA certificates on Windows 11
Solution Follow these steps to update root certificates:
Run Windows Update
Open Command Prompt as Administrator
Run:
Verify with certmgr.msc
Symptom Failed to authorise enrollment. Client is not authorised for namespaces in the enrollment request.
Root Cause You’re using a previously enrolled key for a new enrollment.
Solution Use the correct manager keys for enrollment.
Installation of sshnpd on the IPFire.org firewall
npt -f @<your_client_atsign> -t @<your_device_atsign> -r @rv_[am|ap|eu|oc] -d <name> \
-p <remote-port> -l <local-port>npt -f @alice_client -t @alice_device -d my_server -r @rv_am -p 3389 -l 33389sshnp -f @<your_client_atsign> -t @<your_device_atsign> -h @rv_(am|ap|eu|oc) -d <name> -i <~/.ssh<ssh_key> -sThe atSign of the relay service used to establish the session connection. NoPorts currently provides coverage in 4 regions:
@rv_am - Americas
@rv_eu - Europe
@rv_ap - Asia/Pacific @rv_oc - Oceania
-d
required
String
Only [a-z0-9_-] allowed.
Maximum of 36 characters.
Allows multiple devices to run sshnpd under a single device name.
-p
required
Port number. Between 1-65535.
The port you are connecting to on the device/remote side. This port must be included in the --permit-open list and/or policy allowances.
-l
"0"
Port number Between 1024-65535.
The port you are connecting to on the client/local side. Defaults to any unused port.
-h
"localhost"
DNS / ip address
The host that the daemon will connect to. nslookup is resolved on the remote machine where the daemon is running.
-K
N/A
N/A
Keep alive. If a session ends, try to create a new session and re-bind the port. If you are using this in a script or as a daemon, it's recommended that you handle restarts externally (e.g. with an init system) and do not rely on npt -K.
-T
"30s" "24h" (with -K)
Human readable duration: e.g. "7d" or "1h,14m,30s"
How long to keep the npt session open if there have been no connections. To "never" timeout, use "-T 0" which sets a timeout of 365 days.
-x
N/A
N/A
Starts the session in the background under a different process id, then exits, printing the bound port to stdout.
Note that the background npt session will automatically close due to the timeout feature (see -T).
If you are scripting npt, this feature means you will lose control over the session process, do not use this feature if you also intend to control when npt stops or if you need to detect when the npt session dies.
-v / -q
N/A
N/A
Use -v for verbose logging. Use -q for quiet (i.e. less) logging.

/usr/local/bin/sshnpd/usr/local/bin/sshnpd$HOME/.local/bin/sshnpdVersion : x.x.x$HOME/.local/bin/sshnpdVersion : x.x.xRepeat for Trusted Publishers if needed
Keys missing after install
Avoid enrolling as root; match user with SSHNPD install
SSH error on client
Use --permit-open with both 127.0.0.1 and localhost; check file ownership
Stuck on “preparing for activation”
Update CA certificates via certutil
Failed to authorise enrollment
Use manager keys instead of reused ones
sshnp ... -f @alice_client ...sshnp ... -t @alice_device ...sshnp ... -d my_device ...sshnp ... -h @rv_am ...sshnp ... -h @rv_eu ...sshnp ... -h @rv_ap ...sshnp ... -i path/to/my/ssh/private/key ...sshnp ... -i path/to/my/ssh/private/key -s ...ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBOkiUzsOq8wc9/HaEbE4lgcWeQoICBmp8XgRW0vf5T8 (Comment / identifier to remember this key here)sshnp ... -i path/to/my/ssh/private/key ...sshnp -f @alice_client -t @alice_device -d my_server -h @rv_am -i ~/.ssh/id_ed25519sshnp -f @alice_client -t @alice_device -d my_server \
-h @rv_am -i ~/.ssh/id_ed25519 -u bobc -U bobcpgrep -f "$(eval echo \"$( cat $HOME/.local/bin/sshnpd.sh | grep /sshnpd | awk '{$1=$1};1')\" )"cat $HOME/.local/bin/sshnpd.sh | grep /sshnpd | awk '{$1=$1};1'eval echo \"$(...)\"pgrep -f "$(...)"atsign@sshnpd-test:~# pgrep -f "$(eval echo \"$( cat $HOME/.local/bin/sshnpd.sh | grep /sshnpd | awk '{$1=$1};1')\" )"
289ps -fp <process ID>atsign@sshnpd-test:~# ps -fp 289
UID PID PPID C STIME TTY TIME CMD
atsign 289 114 0 11:10 ? 00:00:00 /home/atsign/.local/bin/sshnpd -a @atsign_device -m @atsign_client -d mydevice -suvkill -9 <process ID>root@sshnpd-test:~# kill -9 289ps -fp <process ID>root@sshnpd-test:~# ps -fp 289
UID PID PPID C STIME TTY TIME CMDssh my_labHost <host>
Hostname localhost
AddKeysToAgent yes
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_ed25519
ProxyCommand=$(sshnp -f <client> -t <device> -r <srvd> -d <device_name> -u <username> -x 2>/dev/null) -W "%h:%p" -o "StrictHostKeyChecking=no"
ControlMaster auto
ControlPath ~/.ssh/control-%r@%n:%p
Host alice_device
Hostname localhost
AddKeysToAgent yes
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_ed25519
ProxyCommand=$(sshnp -f @alice_client -t @alice_device -r @rv_am -d my_device -u <username> -x 2>/dev/null) -W "%h:%p" -o "StrictHostKeyChecking=no"
ControlMaster auto
ControlPath ~/.ssh/control-%r@%n:%psshnp -f @alice_client -t @alice_device -d my_server -r @rv_amssh alice_deviceHost my_webdev_server
Hostname localhost
AddKeysToAgent yes
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_ed25519
LocalForward 8080:0:8080
ProxyCommand=...ssh my_webdev_server -L "8080:0:8080"sudo chown -R $USER:$USER ~/.sshcertutil -generateSSTFromWU roots.sst
certutil -addstore -f root roots.sstRun the following command to make an authorization request.
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
<PASSCODE> with the passcode generated in Step 4,
<USER> with your Windows username,
@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
Once you see this text, you're ready to continue to the next step.
The service config lives in C:\Program Data\NoPorts\sshnpd.yaml, you can open it in notepad with this command:
Make sure you run notepad/terminal as administrator or else you won't be able to save your changes!
Ensure you provide the following fields to your service config:
atsign
atsign: example02_np
atsign: '@example02_np'
keys (windows path)
keys: C:\Users\alice\.atsign\keys\@example02_np_key.atKeys
manager
manager: example01_np
manager: '@example01_np'
Examples on how to fill in the fields are inside the config file.
After a few seconds, the request will also show as approved on the machine you are connecting to.
Click on your atSign in the top right corner of the screen. This will open a list of atSigns that are currently signed into the app.
Select your client atSign in order to switch to it.
If you aren't already on the Connections tab, click on Connections at the top of the Screen. Then click Add New, to create a new profile.
Enter the following information into the profile then click Submit.
Profile Name - The name that will be displayed in the profile list.
Device atSign - Your device atSign (eg example02_np).
Device Name - The name of your remote device.
Relay - Select the relay sever closest to you for optimum speed.
Local Port - The port you will use on your local machine.
Local Host - The hostname or IP address to bind to on your local machine.
Remote Host - The hostname or IP address of the machine you are connecting to.
Remote Port - The port that will be used on the remote machine.
For reference, we've documented our most common use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.
Click the Connect Icon ▶️ to establish a connection with your remote device. If the connection is successful, you will see green. If you see red, hover over the icon to see reason for failure.

Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 secondsnotepad C:\ProgramData\NoPorts\sshnpd.yamlat_activate.exe enroll -a "@<REPLACE>_np" `
-s <PASSCODE> `
-p noports `
-k C:\Users\<USER>
1) Click on Authenticator and make note of the One-Time Password displayed on screen.
sshnpd.tgzExample:
Once this is done, extract the contents of the file to your home directory.
After extraction, copy the npp_atserver and at_activate binary to ~/.local/bin (whichever you prefer and whichever is on your PATH)
Run the following command to make an authorization request:
Be sure to replace the following values:
@<REPLACE>_np with your policy atSign,
<PASSCODE> with the passcode generated in Step 2,
@<REPLACE>_np_key with your policy atSign,
<DEVICE_NAME> with the name of the machine you are on
Once you see this text, you're ready to continue to the next step.
After a few seconds, the request will also show as approved on the machine you are connecting to.
Ensure the daemon is running
Your sshnpd process should now be sending heartbeats to the policy service. You should see a log similar to below after waiting 5 minutes.
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 secondscurl -L -o sshnp.tgz <YOUR URL>curl -L -o sshnp.tgz https://github.com/atsign-foundation/noports/releases/download/v5.13.0/sshnp-linux-x64.tgztar -xvzf sshnp.tgz
cd sshnpsudo cp ./npp_atserver ./at_activate ~/.local/bin~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <
risc-v
Windows
MacOS
Linux
x64
sshnp-macos-x64.zip (intel)
arm64
sshnp-macos-arm64.zip (apple)
arm
Windows CLI Client / Device Installer
If the request looks incorrect, then press "Deny" to deny it, and start the process again.
If the request looks correct, then press "Approve" to approve it.
~/.local/bin/at_activate otp -a @<REPLACE_client>~/.local/bin/at_activate enroll -a @<REPLACE_client> \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE_client>_key.atKeys \
-d <client_device_name> \
-n "sshnp:rw,sshrvd:rw"
The install type
Enter device when prompted.
Your atSigns
Client atSign: e.g., @example01_np
Device atSign: e.g., @example02_np
Your device name
This should be the name of the machine you're currently installing on.
Run the following command to make an authorization request:
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
<PASSCODE> with the passcode generated in Step 5,
@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
Once you see this text, you're ready to continue to the next step.
After a few seconds, the request will also show as approved on the machine you are connecting to.
Click on your atSign in the top right corner of the screen. This will open a list of atSigns that are currently signed into the app.
Select your client atSign in order to switch to it.
If you aren't already on the Connections tab, click on Connections at the top of the Screen. Then click Add New, to create a new profile.
Enter the following information into the profile then click Submit.
Profile Name - The name that will be displayed in the profile list.
Device atSign - Your device atSign (eg example02_np).
Device Name - The name of your remote device.
Relay - Select the relay sever closest to you for optimum speed.
Local Port - The port you will use on your local machine.
Local Host - The hostname or IP address to bind to on your local machine.
Remote Host - The hostname or IP address of the machine you are connecting to.
Remote Port - The port that will be used on the remote machine.
For reference, we've documented our most common use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.
Click the Connect Icon ▶️ to establish a connection with your remote device. If the connection is successful, you will see green. If you see red, hover over the icon to see reason for failure.
curl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.shSubmitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <
-ssshnpsshnpd-ssshnpd
Download the msi installer from GitHub. You can run the msi right from the windows-bundle.zip.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
Replace @<REPLACE>_np with your client atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at C:\Users\<user>\.atsign\keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at C:\Users\<user>\.atsign\keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
at_activate.exe -a "@<REPLACE>_np"at_activate.exe -a "@<REPLACE>_np"at_activate.exe otp -a "@<REPLACE>_np"In this installation guide, @example01_np will represent the client atSign, while @example02_np will represent the device atSign.
Download the installer from GitHub by running the following command:
To check if the installation downloaded correctly:
Make the script executable and run the script by running the command below:
The install type
Enter client when prompted.
Your atSigns (Skip this step)
To skip this step, simply press the Enter/Return key twice. Your atSigns will be activated in the upcoming steps.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
~/.local/bin/at_activate -a @<REPLACE>_np~/.local/bin/at_activate -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.sh~/.local/bin/at_activate otp -a @<REPLACE>_npThen run the installer:
This installer must be run as root.
Not available for macOS
After installing the systemd unit, we must configure it. This requires root privileges.
You'll then be greeted with a file that looks like this:
Replace <username> with the linux user running sshnpd (we suggest creating service account not running as root)
Replace <@device_atsign> with the device address
Replace <@manager_atsign> with the client address
Replace <device_name> with your own custom **unique ** identifier for this device. You will need this value later, so don't forget it.
Add any additional config to the end of the line where sshnpd is run, some useful flags you should consider adding:
-u : "unhide" the device, sharing the username and making it discoverable by sshnp --list-devices
-s : "ssh-public-key", allow ssh public keys to be shared by sshnp and automatically authorized by sshd, saves you from dealing with ssh public key management. If multiple people use the device, we recommend leaving this off and managing ssh public keys yourself.
To see the rest of the available options run sshnpd to see the usage.
If you don't own a pair of noports addresses, please visit the registrar before continuing.
We will now activate the device address—you only need to activate the device address now. The client address will be activated later during the client installation.
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
The application will pause and wait for the input of a one-time password (OTP) before you can continue. You should receive this pin to the contact information associated with the registration of your noports address (i.e. email or text message).
***If you are using a gmail.com account we have seen that sometimes the OTP gets stuck in the SPAM or PROMOTIONS folder. If you do not see the OTP check those folders.
Once you receive the message, enter the pin into the application and press Enter to continue. The application should proceed to create the cryptographic keys and store them at ~/.atsign/keys/@my_noports_device_key.atKeys.
An address can only be activated once, to install this address to future devices, you must copy this file to the device (see 3.b.).
If you have activated the device address before, you must copy the address from another machine where it's been activated.
The address will be located at ~/.atsign/keys/@my_noports_device_key.atKeys. Copy this file from your other machine to the same location on the machine that you are installing sshnpd on.
Using systemctl we can enable and start the sshnpd service.
If you need to verify the status of the service:
If you want to follow the logs of the service you can with
There are a number of fiddly things to get in place for ssh to work. The first is the ~/.ssh/authorized_keysfile of the user being used to run the systemd unit.
The file needs to owned by the user running the systemd unit. Currently there is a bug in the script and this sets the user to root, which needs to be corrected if not running as root. You can do this with the following command substituting debain for your username and group.
The file also needs to be only writable by the owner, else the sshd will not allow logins. This can be checked with ls -l and corrected with the chmod command.
Once complete it should look like this.
If you decided to use the root user in the service setup you have a futher couple of steps.
Then you need to make sure that the root user is allowed to login via sshd. Whist this is not recommended, you can get it working by editing the /etc/ssh/sshd_config file and removing the # on this line.
Once removed, you will need to restart the sshd daemon. How to do this varies from distribution/OS so check on how to do it or reboot.
Your systemd service is ready to go. You can now proceed to installing your client, or if you've already done that, check out our usage guide.
cd sshnpsudo ./install.sh systemd sshnpdIn this installation guide, @example01_np will represent the client atSign, while @example02_np will represent the device atSign.
Download the installer from GitHub by running the following command:
To check if the installation downloaded correctly:
Make the script executable and run the script by running the command below.
The install type
Enter client when prompted.
Your atSigns (Skip this step)
To skip this step, simply press the Enter/Return key twice. Your atSigns will be activated in the upcoming steps.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
~/.local/bin/at_activate -a @<REPLACE>_np~/.local/bin/at_activate -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.sh~/.local/bin/at_activate otp -a @<REPLACE>_npChange directories into the unpacked download:
Then run the installer:
This will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
First, ensure tmux is installed on your machine:
[[ -n $(command -v tmux) ]] && echo 'Good to go!' || echo 'Uh oh! Install tmux before continuing...'If tmux is not available, the recommended way to install tmux on macOS is with homebrew.
[[ -n $(command -v brew) ]] && brew install tmux || echo 'brew not installed, first install brew at https://brew.sh, then run this command again.'Change directories into the unpacked download:
cd sshnpThen run the installer:
./install.sh tmux sshnpdThis will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
After installing the startup script, we must configure it, with nano or vi depending upon your preference.
or
You'll then be greeted with a file that looks like this:
Replace $user with the linux user running sshnpd
Replace $device_atsign with the device address
Replace $manager_atsign with the client address
Replace $device_name with your own custom **unique ** identifier for this device. You will need this value later, so don't forget it.
Add any additional config to the end of the line where sshnpd is run, some useful flags you should consider adding:
-u : "unhide" the device, sharing the username and making it discoverable by sshnp --list-devices
-s : "ssh-public-key", allow ssh public keys to be shared by sshnp and automatically authorized by sshd, saves you from dealing with ssh public key management. If multiple people use the device, we recommend leaving this off and managing ssh public keys yourself.
To see the rest of the available options run sshnpd to see the usage.
If you don't own a pair of noports addresses, please visit the registrar before continuing.
We will now activate the device address, you only need to activate the device address now. The client address will be activated later during the client installation.
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
The application will pause and wait for the input of a one-time password (OTP) before you can continue. You should receive this pin to the contact information associated with the registration of your noports address (i.e. email or text message). ***If you are using a gmail.com account we have seen that sometimes the OTP gets stuck in the SPAM or PROMOTIONS folder. If you do not see the OTP check those folders.
Once you receive the message, enter the pin into the application and press Enter to continue. The application should proceed to create the cryptographic keys and store them at ~/.atsign/keys/<address_name>_key.atKeys.
An address can only be activated once, to install this address to future devices, you must copy this file to the device (see 3.b.).
If you have activated the device address before, you must copy the address from another machine where it's been activated.
The address will be located at ~/.atsign/keys/<address_name>_key.atKeys. Copy this file from your other machine to the same location on the machine that you are installing sshnpd on.
The tmux service will automatically be started by the cron @reboot directive when your machine restarts. If you would like to start it immediately, note that you must make sure to disown the tmux process so that it doesn't hang up when you log out.
Run the following command to start it immediately:
You can use regular tmux commands to observe the service:
Your tmux session is ready to go, you can now proceed to installing your client, or if you've already done that, check out our usage guide.
[[ -n $(command -v tmux) ]] && echo 'Good to go!' || echo 'Uh oh! Install tmux before continuing...'cd sshnp./install.sh tmux sshnpdsudo ./install.sh tmux sshnpdChange directories into the unpacked download:
Then run the installer:
This will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
Change directories into the unpacked download:
cd sshnpThen run the installer:
./install.sh headless sshnpdThis will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
sudo ./install.sh headless sshnpdAfter installing the startup script, we must configure it.
You'll then be greeted with a file that looks like this:
Replace $user with the linux user running sshnpd
Replace $device_atsign with the device address
Replace $manager_atsign with the client address
Replace $device_name with your own custom **unique ** identifier for this device. You will need this value later, so don't forget it.
Add any additional config to the end of the line where sshnpd is run, some useful flags you should consider adding:
-u : "unhide" the device, sharing the username and making it discoverable by sshnp --list-devices
-s : "ssh-public-key", allow ssh public keys to be shared by sshnp and automatically authorized by sshd, saves you from dealing with ssh public key management. If multiple people use the device, we recommend leaving this off and managing ssh public keys yourself.
To see the rest of the available options run sshnpd to see the usage.
This service does not do log rotations of the logs stored at $HOME/.sshnpd/logs.
It is recommended that you implement a cron job which handles log rotations.
If you don't own a pair of NoPorts addresses, please visit my.noports.com before continuing.
We will now activate the device address—you only need to activate the device address now. The client address will be activated later during the client installation.
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
The application will pause and wait for the input of a one-time password (OTP) before you can continue. You should receive this pin to the contact information associated with the registration of your NoPorts address (i.e. email or text message).
***If you are using a gmail.com account we have seen that sometimes the OTP gets stuck in the SPAM or PROMOTIONS folder. If you do not see the OTP check those folders.
Once you receive the message, enter the pin into the application and press Enter to continue. The application should proceed to create the cryptographic keys and store them at ~/.atsign/keys/<address_name>_key.atKeys.
An address can only be activated once, to install this address to future devices, you must copy this file to the device (see 3.b.).
If you have activated the device address before, you must copy the address from another machine where it's been activated.
The address will be located at ~/.atsign/keys/<address_name>_key.atKeys. Copy this file from your other machine to the same location on the machine that you are installing sshnpd on.
The headless service will automatically be started by the cron @reboot directive when your machine restarts. If you would like to start it immediately, note that you must make sure to disown the process so that it doesn't hang up when you log out.
Run the following command to start it immediately:
The service should already be running in the background, to observe the logs:
Your headless job is ready to go. You can now proceed to installing your client, or if you've already done that, check out our usage guide.
cd sshnp./install.sh headless sshnpdsudo ./install.sh headless sshnpdSSH No Ports relies on the SSH daemon and so the first step is to enable it on the IPFire Web interface, under System.
We will also need to add the TMUX package via the web interface under the IPFire section click Pakfire, then add TMUX.
IPFire only has a root user after installation, so the first step is to set up a non privileged account. In this example we will use atsign but feel free to pick your own. Log in to the console or via SSH as root and type:
The next step is su to the user you just created and set up the directories sshnpd will need
Using sudo allows you to get access to the root account if you need it, but it's a good (though optional) practice to remain at a non root shell when you don't.
As root you will need to edit the /etc/sudoers file and uncomment the line below as shown by removing the #. Note that you may need to use w! in vi to force the update of the file.
Once done, then you can add the sudo group and then add the username atsign to the group with the following commands as root:
Then add a password to the atsign account again as root:
Once completed, then check everything is working by su - to atsign the using sudo -s to get back to root.
As atsign (not root!) download the SSH No Ports software, which we can do with curl, and then unpack the archive with tar. The curl command below brings in the x64 CPU architecture file. If you are using Arm/Arm64, then curl down the right option by picking the right link from:
To install the software, just cd and run the install command:
You will see some errors at this stage as IPFire uses fcron instead of cron. Installing fcron jobs requires root privileges, which we will address shortly.
The sshnpd is started via a script and that script and that script needs some simple edits. You will need to know your atSign for the device (_device) and manager (_client). to edit use nano/vi on this file.
Then edit the lines as below with your details.
IPFire has non standard base certificates, but we can install the latest versions from Mozilla so the sshnpd daemon can use TLS, by using these commands.
If you have not got your atKeys file you will need to use at_activate to get them as explained in the the advanced installation guide. If you do have the keys for your device then they need to be in the ~/.atsign/keys directory. You can scp them over for instance. Its a good idea to chmod them to 600.
As mentioned above fcron is used not cron so a couple of extra steps are required. First add your username to the /etc/fcron.allow file.
Then add your username ours looks like this
Once that is completed then you can add an entry to atsign's fcron, this can only be done as root and uses vi to edit by default.
Then you will need to add the following line:
That's it. You are done!
To test you can reboot or as atsign run the command below and try and log in using sshnp
At this point you will be able to log in remotely using sshnp. The first time you will need to specify an ssh key using the -i and -s arguments. This will put the public key into the authorized_hosts file on the IPFire machine. In my case, I would use:
Yours will look like something similar depending on your SSH Key pair (you can generate one if you do not have one with ssh-keygen) and your client/device atSigns.
When you get logged in, you can remove the -s and the -i flags and log in on subsequent logins, as the public key will be in place on the IPFire machine. You will have to put the keys you want to use in ~/.ssh/config also on the machine you are ssh'ing from. In my case, I use a single line:
Remember to keep your SSH and atSign keys safe and make a copy offline.
You are now able to log in from anywhere as long as the firewall and you have Internet access. Congrats!
If you would like to remove the ssh daemon from the GREEN side as well then you can edit the /etc/ssh/sshd_config file to only bind on localhost but updating this line:
to:
and then reboot or restart the sshd daemon.
In this installation guide, @example01_np will represent the client atSign, while @example02_np will represent the device atSign.
Download the installer from GitHub by running the following command:
To check if the installation downloaded correctly:
Make the script executable and run the script by running the command below:
The install type
Enter client when prompted.
Your atSigns (Skip this step)
To skip this step, simply press the Enter/Return key twice. Your atSigns will be activated in the upcoming steps.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
Replace @<REPLACE>_np with your client atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at ~/.atsign/keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
~/.local/bin/at_activate -a @<REPLACE>_np~/.local/bin/at_activate -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.sh~/.local/bin/at_activate otp -a @<REPLACE>_npDownload the msi installer from GitHub. You can run the msi right from the windows-bundle.zip.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
Replace @<REPLACE>_np with your client atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at C:\Users\<user>\.atsign\keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at C:\Users\<user>\.atsign\keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
at_activate.exe -a "@<REPLACE>_np"at_activate.exe -a "@<REPLACE>_np"at_activate.exe otp -a "@<REPLACE>_np"Download the msi installer from GitHub. You can run the msi right from the windows-bundle.zip.
If you've already activated your client atSign on another device, this step will not work. Instead, follow this guide: Reuse your client atSign on another machine
This command activates your atSign and prompts you to enter an OTP. This is only done during the setup of a brand new atSign.
Replace @<REPLACE>_np with your client atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at C:\Users\<user>\.atsign\keys.
Run the same command, but for your device atSign.
Replace @<REPLACE>_np with your device atSign.
at_activate will pause and wait for the input of a one-time pin (OTP) sent to your email or phone number.
Once activated, the master keys will save at C:\Users\<user>\.atsign\keys.
Run the following command to generate a 6-character one-time passcode. You will use this passcode in Step 6.
Replace @<REPLACE>_np with your device atSign.
at_activate.exe -a "@<REPLACE>_np"at_activate.exe -a "@<REPLACE>_np"at_activate.exe otp -a "@<REPLACE>_np"~/.local/bin/at_activate approve -a @<REPLACE>_np --arx noports --drx <DEVICE_NAME>Begin with the three steps below
The NoPorts daemon (a.k.a. sshnpd) is installable as a background service in many ways. Choose the best option for your environment. The service may be installed as a systemd unit, docker container, tmux session, or as a background job using cron and nohup. The binaries can also be installed standalone so that you can install your own custom background service.
On Windows, we strongly recommend sticking to our automated installation process on Windows. This is because properly installing NoPorts as a Windows service requires making entries in the registry. If you want to create a custom installer for your organization, please speak to us directly at .
You can , or see the table below to download the latest release for your platform.
Alternatively, if you want to download from the command line, you can do so with curl.
x64:
arm64:
arm:
risc-v:
x64 (intel):
arm64 (apple):
If you downloaded from GitHub, the file name may be slightly different.
See the links in the table below to continue with the installation process.
Integrate RDP and VNC over NoPorts using Remmina (Linux)
Remmina is a Remote Desktop client for Linux which supports a number of remote access protocols. This guide will walk you through setting up Remmina to connect over NoPorts. While it focuses on VNC and RDP, it should work for most of the other protocols available through Remmina.
Prerequisites:
Linux Desktop
NoPorts Cli binaries installed
Dependent on your distribution, the steps may vary. Remmina is quite popular, so you should be able to web search your way to installing Remmina.
When installing Remmina, make sure it is not installed to a sandboxed environment such as Flatpak, otherwise the "Execute a Command" feature in Remmina will not work.
In most cases, the package name is remmina and you will need to make sure that some optional dependencies are installed:
freerdp - if you want to use RDP (a.k.a. Windows app) with Remmina
libvncserver - if you want to VNC (a.k.a. MacOS screen sharing) with Remmina
If you already have Remmina running, you may need to restart it after installing these optional dependencies, otherwise they won't appear as options to create profiles for. By default, Remmina won't full quit when you close the window. So, check your app tray to full quit, or use the killall remmina command.
If Remmina doesn't have access to the PATH, it may not be able to find npt . To mitigate this, we will use the absolute path when we create our hook for Remmina.
Run the following command:
The command should output a path such as:
Save this path for later; we will use it during profile creation.
Create a new profile. There are four settings we should change on this screen:
Name: a nickname for your profile, anything you want.
Protocol: RDP
Server: The loopback interface IP address followed by a random free local port of your choice.
Make sure the port is unique per profile, or you can only use one at a time.
Now go to the Behavior tab.
Here, we need to craft an npt command that will get us access to RDP on the remote machine.
Breaking down this command:
Place this command in the "Before connecting" field.
Save the profile, then use it to connect. At first, you will see a popup window that Remmina opens when it runs the command. That window will automatically close if the command is successful, at which point it will start the RDP connection.
Create a new profile. There are four settings we should change on this screen:
Name: a nickname for your profile, anything you want.
Protocol: VNC
Server: The loopback host followed by a random free local port of your choice.
Make sure the port is unique per profile, or you can only use one at a time.
Now go to the Behavior tab.
Here, we need to craft an npt command that will get us access to RDP on the remote machine.
Breaking down this command:
Place this command in the "Before connecting" field.
Save the profile, then use it to connect. At first, you will see a popup window that Remmina opens when it runs the command. That window will automatically close if the command is successful, at which point it will start the VNC connection.
If you have trouble, try running the npt command in a terminal first. If you run into issues, then you know it is your npt command. If the command does work in a terminal, then it is likely something with your Remmina configuration, you may have to tweak additional settings.
How to install NoPorts when connecting from Linux to macOS
These initial steps set up the machine initiating the connection.
After setting up the machine you're connecting from, you'll configure the machine you're connecting to.
With both machines now configured, the final steps bring us back to the machine initiating the connection.
~/.local/bin/npp_atserver -a @<YOUR POLICY ATSIGN>SHOUT|2025-04-16 19:12:51.399918|PolicyServiceWithAtClient|Loading groups via AtClient
SHOUT|2025-04-16 19:12:52.293882|PolicyServiceWithAtClient|Load complete
SHOUT|2025-04-16 19:12:52.294012| npp |Daemon atSigns: {} Environment=delegate_policy="@policy_atsign_123"sudo systemctl daemon reload && sudo systemctl restart sshnpd.servicejournalctl -u sshnpd.service -fNov 10 23:54:17 atsign sshnpd[124155]: INFO|2025-11-10 23:54:17.310764| sshnpd |Sending heartbeat to policy service @tastelessbanana~/.local/bin/at_activate approve -a @<REPLACE_client> \
--arx noports \
--drx <client_device_name>Host localhost
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
IdentityFile ~/.ssh/id_ed25519
LogLevel QUIET#!/bin/bash
#
export USER=$USER
export SSHNPHOME=$HOME/.local/bin <--<default-location-for-SSHNP>
export HOSTDEVICE=<your-host-running-SSHNPD>
export CLIENTATSIGN=<your-local-atsign format @34mypersonalatsign>>
export HOSTATSIGN=<the-host-device-atsign format @55hostdeviceatsign>
export LOCALPORT=<the-port-ito-use-forconnection example 46393>
export SRVD=<atSign-of-srvd-daemon example @rv_eu or @rv_am or @rv_ap>
export NETA=<network-CIDR-style example 0/0 or 10.0.0.0/8>
export NETB=<network-CIDR-style example 172.16.0.0/16>
export NETC=<network-CIDR-style example 192.168.1.0/24>
#
echo ""
echo Starting Atsign SSHNP connects to $HOSTDEVICE on port 46393 for personal VPN
echo ""
#
$SSHNPHOME/sshnp --from $CLIENTATSIGN --to $HOSTATSIGN --srvd $SRVD --remote-user-name $USER --output-execution-command --idle-timeout 90 --device $HOSTDEVICE --local-port $LOCALPORT
sleep 3
sshuttle --dns -r [email protected]:$LOCALPORT $NETA $NETB $NETC
#sshnp -f @my_client -t @my_device -h @rv_am -d my_pi -o "-D 1080"./at_activate -a @my_noports_device./at_activate -a @my_noports_devicesudo vi /etc/systemd/system/sshnpd.servicesudo systemctl enable sshnpd.service
sudo systemctl start sshnpd.servicesudo systemctl status sshnpd.servicesudo journalctl -u sshnpd.service -fdebian@beaglebone:~$ ls -l ~/.ssh/
total 0
-rw-r--r-- 1 root root 0 Feb 18 00:28 authorized_keys
debian@beaglebone:~$ sudo chown debian:debian ~/.ssh/authorized_keys
debian@beaglebone:~$ ls -l ~/.ssh/
total 0
-rw-r--r-- 1 debian debian 0 Feb 18 00:28 authorized_keys
debian@beaglebone:~$ chmod 600 ~/.ssh/authorized_keysdebian@beaglebone:~$ ls -l ~/.ssh/
total 0
-rw------- 1 debian debian 0 Feb 18 00:28 authorized_keys
debian@beaglebone:~$sudo mkdir -p ~root/.ssh
sudo touch ~root/.ssh/authorized_keys
sudo chmod 600 ~root/.ssh/authorized_keys# PermitRootLogin prohibit-password./at_activate -a @my_noports_device./at_activate -a @my_noports_devicenano ~/.local/bin/sshnpd.shvi ~/.local/bin/sshnpd.shnohup &>/dev/null tmux new-session -d -s sshnpd && tmux send-keys -t sshnpd $HOME/.local/bin/sshnpd.sh C-mtmux a -t sshnpd./at_activate -a @my_noports_device./at_activate -a @my_noports_devicevi ~/.local/bin/sshnpd.shnohup $HOME/.local/bin/sshnpd.sh > $HOME/.sshnpd/logs/sshnpd.log 2> $HOME/.sshnpd/logs/sshnpd.err &tail -f $HOME/.sshnpd/logs/sshnpd.log
tail -f $HOME/.sshnpd/logs/sshnpd.errhttps://<GREEN Interface IP>:444useradd -d /home/atsign -m -U atsignsu - atsign
mkdir -p ~/.atsign/keys ~/.ssh
chmod 700 ~/.atsign ~/.atsign/keys ~/.ssh
touch ~/.ssh/authorized keys
chmod 600 ~/.ssh/authorized keys## Uncomment to allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALLgroupad sudo
usermod -a -G sudo atsignpasswd atsignsu - atsign
sudo -s curl -L https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-x64.tgz -o sshnp.tgz
tar zxvf sshnp.tgzcd sshnp
./install.sh tmux sshnpd~/.local/bin/sshnpd.shmanager_atsign="@cconstab" # MANDATORY: Manager/client address/Comma separated addresses (atSign/s)
device_atsign="@ssh_1" # MANDATORY: Device address (atSign)
device_name="ipfire01" # Device name
sudo mkdir -p /etc/pki/tls/certs
curl --etag-compare etag.txt --etag-save etag.txt --remote-name https://curl.se/ca/cacert.pem && sudo mv cacert.pem /etc/pki/tls/certs/ca-bundle.crtchmod 600 ~/.atsign/keys/*sudo vi /etc/fcron.allowroot
atsignsudo fcrontab -u atsign -e@reboot tmux new-session -d -s sshnpd && tmux send-keys -t sshnpd /home/atsign/.local/bin/sshnpd.sh C-m@reboot tmux new-session -d -s sshnpd && tmux send-keys -t sshnpd /home/atsign/.local/bin/sshnpd.sh C-m &sshnp -f @cconstab -t @ssh_1 -h @rv_am -d ipfire01 -i ~/.ssh/id_rsa -sIdentityFile ~/.ssh/id_rsaListenAddress 0.0.0.0ListenAddress localhostRELEASE="1.0.14"
ARCH=$(opkg print-architecture | grep ' 10$' | awk '{print $2}')
PACKAGE="csshnpd_${RELEASE}-1_${ARCH}.ipk"
wget -O ${PACKAGE} https://github.com/atsign-foundation/Atsign_OpenWRT_packages/releases/download/c${RELEASE}/${PACKAGE}
opkg install ${PACKAGE}config sshnpd
option atsign '@example_device'
option manager '@example_client'
option device 'rutx10'
option args ''
option otp '123456'
option enabled '1'at_activate approve -a @example_device --arx noports --drx rutx10service sshnpd startsshnp -f @example_client -t @example_device -d rutx10_remote -h rv_euapk update
apk add csshnpd









<DEVICE_NAME> with the name of the machine you are on
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <DEVICE_NAME> \
-n "sshnp:rw,sshrvd:rw"~/.local/bin/at_activate approve -a @<REPLACE>_np --arx noports --drx <DEVICE_NAME><DEVICE_NAME> with the name of the machine you are on
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <DEVICE_NAME> \
-n "sshnp:rw,sshrvd:rw"~/.local/bin/at_activate approve -a @<REPLACE>_np --arx noports --drx <DEVICE_NAME><DEVICE_NAME> with the name of the machine you are on
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <DEVICE_NAME> \
-n "sshnp:rw,sshrvd:rw"~/.local/bin/at_activate approve -a @<REPLACE>_np --arx noports --drx <DEVICE_NAME>Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
@<REPLACE_NAME> with the device name from Step 6.
That's it. You can start using NoPorts or explore some of the documented use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.

.\at_activate approve -a "@<REPLACE>_np" --arx NoPorts --drx <REPLACE_NAME>Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
@<REPLACE_NAME> with the device name from Step 6.
That's it. You can start using NoPorts or explore some of the documented use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.

.\at_activate approve -a "@<REPLACE>_np" --arx NoPorts --drx <REPLACE_NAME>

Username: The username of the account you want to log in as.
-p 3389
The remote port, 3389 is the canonical RDP port
-x
Tell npt to exit when connected (which tells remmina npt is ready for it to connect)
Username: The username of the account you want to login as.
-p 5900
The remote port, 5900 is the canonical VNC port on MacOS
-x
Tell npt to exit when connected (which tells remmina npt is ready for it to connect)
/usr/local/bin/npt
Run the npt command
-f @your_client
The "from" atSign (atSign of the current computer)
-t @your_device
The "to" atSign (atSign of the device you're connecting to)
-d device_name
The device name you gave when you setup sshnpd
-r @rv_am
The atSign of the relay you want to use
--lp 12345
The local port, must match the port we added on the basic page.
/usr/local/bin/npt
Run the npt command
-f @your_client
The "from" atSign (atSign of the current computer)
-t @your_device
The "to" atSign (atSign of the device you're connecting to)
-d device_name
The device name you gave when you setup sshnpd
-r @rv_am
The atSign of the relay you want to use
--lp 56789
The local port, must match the port we added on the basic page




which npt/usr/local/bin/npt/usr/local/bin/npt -f @your_client -t @your_device -d device_name -r @rv_am --lp 12345 -p 3389 -x/usr/local/bin/npt -f @your_client -t @your_device -d device_name -r @rv_am --lp 56789 -p 5900 -xrisc-v
x64
sshnp-macos-x64.zip (intel)
arm64
sshnp-macos-arm64.zip (apple)
arm
You are on Linux and have root access. (Recommended)
You have tmux installed, or can install it. (Deprecated)
If you do not have root access and cannot install tmux (Deprecated)
You want to manually setup the background service after downloading the binaries. (roll your own)
The install type
Enter device when prompted.
Your atSigns
Client atSign: e.g., @example01_np
Device atSign: e.g., @example02_np
Your device name
This should be the name of the machine you're currently installing on.
Run the following command to make an authorization request.
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
<PASSCODE> with the passcode generated in Step 4,
@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
Once you see this text, you're ready to continue to the next step.
Be sure to replace the following values:
@<REPLACE>_np with your device atSign,
@<REPLACE_NAME> with the device name from Step 6.
That's it. You can start using NoPorts or explore some of the documented use cases, including MCP, SSH, RDP, SFTP, Web Server, and SMB.
~/.local/bin/at_activate -a @<REPLACE>_np~/.local/bin/at_activate -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.sh~/.local/bin/at_activate otp -a @<REPLACE>_npcurl -L https://github.com/atsign-foundation/noports/releases/latest/download/universal.sh -o universal.shstat universal.shchmod u+x universal.sh
./universal.shSubmitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 seconds~/.local/bin/at_activate enroll -a @<REPLACE>_np \
-s <PASSCODE> \
-p noports \
-k ~/.atsign/keys/@<REPLACE>_np_key.atKeys \
-d <
~/.local/bin/at_activate approve -a @<REPLACE>_np --arx noports --drx <DEVICE_NAME>the noports daemon program (sshnpd) which runs on the device you want to ssh to
the noports client programs (sshnp/npt) which you run on the device you want to ssh from
the noports tcp rendezvous program (sshrvd)
if required a policy engine
The programs communicate via the atProtocol and the atClient SDKs; as a result, the payloads of the messages the programs send to each other are all end-to-end encrypted.
In brief
The client (sshnp/npt) creates a unique guid for the session
and sends a request notification to the sshrvd for a port1/port2 pair for this sessionId
The sshrvd
finds a pair of available ports
opens server sockets for both of them
Note: rvd will allow just a single client socket to connect to each server socket
and will bridge them together
sends response to the client
The client
receives the response notification from sshrvd (rv_host, rv_port_1, rv_port_2)
and sends a request notification to the sshnpd including the sessionId and the rv_host:rv_port_1 and a new ephemeral AES 256 key
The daemon (sshnpd)
opens a socket to the rv_host:rv_port_1 and authenticates
and opens a socket to its local sshd port
The client
Listens on a specified port and on connection encrypts traffic received with the AES key and forward on to the rv_host
The client displays a message to the user that they may now ssh -p $local_port $username@localhost, i.e. ssh -p 58358 gary@localhost in the example above, and exits
This high-level flow is visualized in the diagrams below.
NB Requests from unauthorized client atSigns are ignored. Note that one may also completely prevent requests from any other atSigns ever even reaching the daemon by using the atProtocol's config:allow list feature.
In the personal edition of noports, a daemon may have only a single authorized client atSign.
The Team and Enterprise editions will allow for multiple authorized client atSigns, controlled not by the daemon but by a separate noports authorization controller process, with its own atSign.
At any point the sshnpd or the srvd software rather than using a local configuration to manage access rights, can forward those questions to another atSign. That atSign can in turn pass those queries to a policy engine and reflect the answer back to the asking atSign. In the example above @relay and/or @server could ask if @client is allowed to access the service. This allows decisions to be made at the Policy plane level and provides operational segregation of duties.
In the following sequence diagram, atServer address lookup flows, authentication flows, key exchange flows, precise encryption mechanics and notification transmission flows are not covered in detail; those details are provided in the links provided in the "Further Details" section below.
Since the full details are provided in those other links, the client_1 -> atServer_1 -> atServer_2 -> client_2 message flows are abbreviated to @atSign_1 -> @atSign_2 in the sequence diagram. Thus, for example, sshnp (@client) encapsulates both the sshnp program and the sshnp atServer
Once the interactions above have completed
the sshnpd nor the sshnp programs are no longer involved
there is a new sshrv process running on the device host which pipes i/o between requested server:port and $rv_host:$rv_port_1
there is a client process running on the client host which provides the local port forwarding tunnel
User may now type "ssh -p $local_port username@localhost" or use a client application like and RDP client with traffic flowing
client ssh program <===>
$client_localhost:$local_port <===> bridged by client-side ssh tunnel to
$rv_host:$rv_port_2 <===> bridged by sshrvd to
In the sections above, we referred to "authentication", "sending notifications" and "receiving notifications", and we made the statement that "the payloads of the messages the programs send to each other are all end-to-end encrypted"
Here are some links to detailed diagrams covering
how encrypted data is exchanged (including how keys are exchanged)

sudo ./install.sh tmux sshnpdcurl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-x64.tgz -o sshnp.tgzcurl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-arm64.tgz -o sshnp.tgzcurl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-arm.tgz -o sshnp.tgzcurl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-riscv.tgz -o sshnp.tgzcurl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-macos-x64.zip -o sshnp.zipcurl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-macos-arm64.zip -o sshnp.ziptar -xf sshnp.tgzunzip sshnp.zipand sends a response notification to the sshnp client
$rv_host:$rv_port_1 <===> bridged by device-side sshrv to
$device_host:22 <===>
device sshd program


@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
keys: C:\Users\alice\.atsign\keys\@example02_np_key.atKeys
manager
manager: example01_np
manager: '@example01_np'
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 secondsnotepad C:\ProgramData\NoPorts\sshnpd.yaml
at_activate.exe enroll -a "@<REPLACE>_np" `
-s <PASSCODE> `
-p noports `
-k C:\Users\<USER>\.atsign\keys\@<REPLACE>_np_key.atKeys `
-d <DEVICE_NAME> `
-n "sshnp:rw,sshrvd:rw"@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
keys: C:\Users\alice\.atsign\keys\@example02_np_key.atKeys
manager
manager: example01_np
manager: '@example01_np'
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 secondsnotepad C:\ProgramData\NoPorts\sshnpd.yaml
at_activate.exe enroll -a "@<REPLACE>_np" `
-s <PASSCODE> `
-p noports `
-k C:\Users\<USER>\.atsign\keys\@<REPLACE>_np_key.atKeys `
-d <DEVICE_NAME> `
-n "sshnp:rw,sshrvd:rw"@<REPLACE>_np_key with your device atSign,
<DEVICE_NAME> with the name of the machine you are on
keys: C:\Users\alice\.atsign\keys\@example02_np_key.atKeys
manager
manager: example01_np
manager: '@example01_np'
Submitting enrollment request
Enrollment ID: ---------------------
Waiting for approval; will check every 10 secondsnotepad C:\ProgramData\NoPorts\sshnpd.yaml
at_activate.exe enroll -a "@<REPLACE>_np" `
-s <PASSCODE> `
-p noports `
-k C:\Users\<USER>\.atsign\keys\@<REPLACE>_np_key.atKeys `
-d <DEVICE_NAME> `
-n "sshnp:rw,sshrvd:rw"Python (version 3)
OpenSSH (acts as a proxy between NoPorts & PuTTY)
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 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.
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:
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:
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.
--- description: How to manage tons of NoPorts SSH connections with Putty icon: windows ---
This guide will help you set up some very minimal Python scripts to manage connections with NoPorts. In most cases only 4-5 lines of Python will be required to set up a new device.
Python (version 3)
OpenSSH (acts as a proxy between NoPorts & PuTTY)
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 set up your PuTTY session.
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.
To set up a new device, create a new python (.py) in the same folder where you created noports_base.py. Then copy the following file:
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:
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.
Common questions about NoPorts
If you have a question that needs answering, please do one of the following:
Create a new
Join and post to our 📑|forum channel
Typing is less fun after a few devices.
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"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()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()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()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()

localhost with the ipv4 (127.0.0.1) or ipv6 (::1) loopback address. However beware! All NoPorts tech defaults to doing lookups for localhost. If your system has both configured in /etc/hosts then NoPorts may resolve to the wrong address for which sshd is configured for.Host 127.0.0.1
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
IdentityFile ~/.ssh/GitHub_rsa
LogLevel QUIET-dDEVICE_NAME. Your hostnames may not match the requirements of the DEVICE_NAME flag.Lowercase Alphanumeric max 15 Characters Snake Case before version 5.0.3
Case insensitive Alphanumeric max 36 Chars Snake Case from version 5.0.3 onwards.
allows UUID snake cased device names.
Cut and paste this script and tailor it to your needs. Do not forget to chmod 500 or else it will not run! More details below on how to set things up, and a demo run, too, using Docker.
Each atSign has its own set of keys that are "cut" with at_activate. This will cut the keys for the atSign and place them in ~/.atsign/keys. Each machine requires the atKeys file to run sshnpd, so, we need to have a way to get them to each device. It is possible to ssh/scp them, but that becomes very cumbersome at scale. Instead, we encrypt the keys with AES256 and place them on a webserver. When the install script is run, it knows both the URL and the encryption password and can pull the atKeys file to the right place.
The steps are to (1) get the atKeys file as normal using at_activate, then (2) encrypt them using a command like this:
This command will ask you for a password which you will put in the install.sh file as ATKEY_PASSWORD.
You can then set up a simple http (the file is encrypted) server to serve the keys with. For example, a Python single line of code:
python3 -m http.server 8080 --bind 0
Alternatively, you can put the keys file on filebin.net and it will locate the file in a random URL which you can put into the install.sh file. For example:
https://filebin.net/s2w5r6gwemmz5kvi/_ssh_1_key.atKeys.aes
It is worth noting that the @ gets translated to a _ but that does not effect the script. Using this site has the advantage that the URL is hidden, and it uses TLS—plus you can delete the files once completed.
At this point you can derive the URL of the encrypted atKeys file and put it in the install.sh file headers.
The other variables should be straightforward enough.
The other variables set up the atSigns for the manager and device and for the device name itself. The device name by default uses the hostname using the shell command $(hostname) , but that only works if the hostname is compliant with the -d format of sshnpd. You can pick another way to identify the host or just make sure the hostname is compliant.
This is a simple matter now of getting the install.sh to the target device and running it. The needed files will be installed, the username name created, cronjobs put in place, and the 'sshnpd' will be started.
How you get the install.sh file to the target machine is going to vary depending on your environment. Using scp is a good option, as is using ssh or curl and pulling the file (using the same encryption method perhaps).
The install.sh script works fine on individual machines, but if you want to install on, say, 25 machines, this is how you do it.
First, you need to have ssh root access to the machines you want to install on. This SSH access will be removed as you do the install with this line uncommented:
If you pass 8 arguments into the install.sh they will be used rather than the hardcoded values. This allows you to pass in the values needed as the script is run QED.
For example:
./install.sh ubuntu changeme https://raw.githubusercontent.com/cconstab/sshnpd_config/main/config/sshnpd.sh http://192.168.1.61:8080/@ssh_1_key.atKeys.aes helloworld @cconstab @ssh_1 $(hostname)
Using Docker is the simple way to test any options first before moving to production.
Something like this will mount the script and start a basic Linux build:
docker run -it -v ./install.sh:/root/install.sh debian:trixie-slim
You can then cd and run the install.sh script. For example:
After the install has completed, you can su - to the USERNAME you chose and see tmux/sshnpd running.
On another machine, you can log in to the container using the select MANAGER_ATSIGN, remembering to give the daemon a ssh key and the username.
You are now logged into the container. If you need root access, you can use the password you chose to sudo -s
Feel free to adapt this outline to your specific needs and share your improvements back with the community.
#!/bin/bash
# Configure these variables to your liking or pass in args
if [ $# -ne 8 ]
then
# USERNAME & PASSWORD created with sudo priviledges by install.sh
export USERNAME="ubuntu"
export PASSWORD="changeme"
# URL of the config/sshnpd.sh file contained in this repo (this will change if repo is cloned)
export CONFIG_URL="https://gist.githubusercontent.com/cconstab/142c942ce0c8caa3348d0976a60fbfd1/raw/d243d64573bf2b7de5e827ff9b7b7f2f2413901b/gistfile1.txt"
# Remember to encrypt your keys!!!!
# Encrypt with
# openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -salt -in ~/.atsign/keys/@ssh_1_key.atKeys -out @ssh_1_key.atKeys.aes
# Test decrypt with
# openssl aes-256-cbc -d -salt -pbkdf2 -iter 1000000 -in ./@ssh_1_key.atKeys.aes -out ./@ssh_1_key.atKeys
export ATKEYS_URL="https://filebin.net/cpme4bhrqolyrnts/_ssh_1_key.atKeys.aes"
# This is the AES password you used to encrypt the above file
export ATKEY_PASSWORD="helloworld12345!"
# Manager atSign either a Single atSign or comma delimited list from sshnpd v5.0.3
export MANAGER_ATSIGN="@cconstab"
export DEVICE_ATSIGN="@ssh_1"
export DEVICE_NAME="$(hostname)"
else
export USERNAME=$1
export PASSWORD=$2
export CONFIG_URL=$3
export ATKEYS_URL=$4
export ATKEY_PASSWORD=$5
export MANAGER_ATSIGN=$6
export DEVICE_ATSIGN=$7
export DEVICE_NAME=$8
fi
####################################################################
# Get machine updated and with the needed packages #
####################################################################
apt update
apt install tmux openssh-server curl cron sudo -y
# create USERNAME with sudo priviledges
useradd -m -p $(openssl passwd -1 ${PASSWORD}) -s /bin/bash -G sudo ${USERNAME}
####################################################################
# start sshd listening on localhost only #
####################################################################
# Update the sshd config so it only runs on localhost
#sed -i 's/#ListenAddress 0.0.0.0/ListenAddress 127.0.0.1/' /etc/ssh/sshd_config
# restart sshd if your OS starts it on install
# e.g on Ubuntu/Debian
#systemctl restart ssh.service
# or Redhat/Centos
#systemctl restart sshd.service
####################################################################
# Start sshd Only needed if sshd is not started by default #
# for example a docker container #
# Remove these lines if the OS you are using starts up sshd itself #
####################################################################
# File needed for sshd to run
mkdir /run/sshd
# generate the sshd Keys
ssh-keygen -A
# Start sshd listening on localhost and with no password auth
/usr/sbin/sshd -D -o "ListenAddress 127.0.0.1" -o "PasswordAuthentication no" &
####################################################################
# Install sshnpd as the selected USERNAME #
####################################################################
su --whitelist-environment="MANAGER_ATSIGN,DEVICE_ATSIGN,ATKEY_PASSWORD,ATKEYS_URL,DEVICE_NAME" -c ' \
set -eux; \
case "$(dpkg --print-architecture)" in \
amd64) \
SSHNPD_IMAGE="https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-x64.tgz" ;; \
armhf) \
SSHNPD_IMAGE="https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-arm.tgz" ;; \
arm64) \
SSHNPD_IMAGE="https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-arm64.tgz" ;; \
riscv64) \
SSHNPD_IMAGE="https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-riscv.tgz" ;; \
*) \
echo "Unsupported architecture" ; \
exit 5;; \
esac; \
cd ; \
mkdir -p ~/.local/bin ; \
mkdir -p ~/.atsign/keys ; \
curl -fSL ${ATKEYS_URL} -o atKeys.aes ; \
openssl aes-256-cbc -d -salt -pbkdf2 -iter 1000000 -in ./atKeys.aes -out ~/.atsign/keys/${DEVICE_ATSIGN}_key.atKeys --pass env:ATKEY_PASSWORD ; \
chmod 600 ~/.atsign/keys/${DEVICE_ATSIGN}_key.atKeys ; \
curl -fSL $SSHNPD_IMAGE -o sshnp.tgz ; \
tar zxvf sshnp.tgz ;\
sshnp/install.sh tmux sshnpd ;\
curl --output ~/.local/bin/sshnpd.sh ${CONFIG_URL} ; \
sed -i "s/MANAGER_ATSIGN/$MANAGER_ATSIGN/" ~/.local/bin/sshnpd.sh ; \
sed -i "s/DEVICE_ATSIGN/$DEVICE_ATSIGN/" ~/.local/bin/sshnpd.sh ; \
sed -i "s/DEVICE_NAME/$DEVICE_NAME/" ~/.local/bin/sshnpd.sh ; \
# Uncomment this if you _want_ to use '-u' for sshnpd ; \
#sed -i "s/# u=\"-u\"/u=\"-u\"/" ~/.local/bin/sshnpd.sh ; \
# Uncomment this if you do _not_ want `-s` enabled (you would need to send ssh keys)
#sed -i "s/s=\"-s\"/# s=\"-s\"/" ~/.local/bin/sshnpd.sh ; \
rm -r sshnp ; \
rm sshnp.tgz atKeys.aes' $USERNAME
####################################################################
# Start sshnpd, the crontab entry will do this on reboots #
####################################################################
su - $USERNAME sh -c "/usr/bin/tmux new-session -d -s sshnpd && tmux send-keys -t sshnpd /home/ubuntu/.local/bin/sshnpd.sh C-m"
# Helpful to sleep if using Docker so container stays alive.
# sleep infinitymkdir enckeys
cd enckeys
openssl enc -aes-256-cbc -pbkdf2 -iter 1000000 -salt -in ~/.atsign/keys/@ssh_1_key.atKeys -out @ssh_1_key.atKeys.aesexport ATKEYS_URL="http://192.168.1.61:8080/@ssh_1_key.atKeys.aes"
# This is the AES password you used to encrypt the above file
export ATKEY_PASSWORD="helloworld12345!"export USERNAME=ubuntu
export PASSWORD="changeme"
export CONFIG_URL="https://raw.githubusercontent.com/cconstab/sshnpd_config/main/config/sshnpd.sh"#sed -i 's/#ListenAddress 0.0.0.0/ListenAddress 127.0.0.1/' /etc/ssh/sshd_config╰$ docker run -it -v ./install.sh:/root/install.sh debian:trixie-slim
root@f5040633c8a0:/# cd
root@f5040633c8a0:~# ls
install.sh
root@f5040633c8a0:~# ./install.sh root@f5040633c8a0:~# su - ubuntu
ubuntu@f5040633c8a0:~$ tmux ls
sshnpd: 1 windows (created Sun Mar 3 22:48:01 2024)
ubuntu@f5040633c8a0:~$ ~/.local/bin/sshnp -f @cconstab -t @ssh_1 -h @rv_am -s -i ~/.ssh/id_ed25519 -u ubuntu -d f5040633c8a0
2024-03-03 14:51:34.574057 : Resolving remote username for user session
2024-03-03 14:51:34.574107 : Resolving remote username for tunnel session
2024-03-03 14:51:34.574562 : Sharing ssh public key
2024-03-03 14:51:36.239757 : Fetching host and port from srvd
2024-03-03 14:51:39.239811 : Sending session request to the device daemon
2024-03-03 14:51:39.469112 : Waiting for response from the device daemon
2024-03-03 14:51:40.993543 : Received response from the device daemon
2024-03-03 14:51:40.994470 : Creating connection to socket rendezvous
2024-03-03 14:51:41.114766 : Starting tunnel session
2024-03-03 14:51:41.989428 : Starting user session
Linux f5040633c8a0 6.6.12-linuxkit #1 SMP Fri Jan 19 08:53:17 UTC 2024 aarch64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Mar 3 22:51:42 2024 from 127.0.0.1
-bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
ubuntu@f5040633c8a0:~$#!/bin/sh
# disable "var is referenced but not assigned" warning for template
# shellcheck disable=SC2154
# SCRIPT METADATA
binary_path="$HOME/.local/bin"
manager_atsign="@example_client" # MANDATORY: Manager/client address/Comma separated addresses (atSign/s)
device_atsign="@example_device" # MANDATORY: Device address (atSign)
device_name="default" # Device name
user="$(whoami)" # MANDATORY: Username
v="-v" # Comment to disable verbose logging
s="-s" # Comment to disable sending public keys
u="-u" # Comment to disable sending user information
delegate_policy=""
# END METADATA
sleep 10 # allow machine to bring up network
export USER="$user"
while true; do
# The line below runs the sshnpd service, with the options set above.
# You can edit this line to further customize the service to your needs.
"$binary_path"/sshnpd -a "$device_atsign" -m "$manager_atsign" -d "$device_name" "$delegate_policy" "$s" "$u" "$v"
sleep 10
done
#!/bin/sh
# disable "var is referenced but not assigned" warning for template
# shellcheck disable=SC2154
# SCRIPT METADATA
binary_path="$HOME/.local/bin"
manager_atsign="@example_client" # MANDATORY: Manager/client address/Comma separated addresses (atSign/s)
device_atsign="@example_device" # MANDATORY: Device address (atSign)
device_name="default" # Device name
user="$(whoami)" # MANDATORY: Username
v="-v" # Comment to disable verbose logging
s="-s" # Comment to disable sending public keys
u="-u" # Comment to disable sending user information
delegate_policy=""
# END METADATA
sleep 10 # allow machine to bring up network
export USER="$user"
while true; do
# The line below runs the sshnpd service, with the options set above.
# You can edit this line to further customize the service to your needs.
"$binary_path"/sshnpd -a "$device_atsign" -m "$manager_atsign" -d "$device_name" "$delegate_policy" "$s" "$u" "$v"
sleep 10
done
[Unit]
Description=Ssh No Ports Daemon
After=network-online.target
[Install]
WantedBy=multi-user.target
[Service]
Type=simple
Restart=always
RestartSec=3
KillMode=process
# The line below runs the sshnpd service, with the options set in
# /etc/systemd/system/sshnpd.d/override.conf.
# You can edit that config with: sudo systemctl edit sshnpd
ExecStart=/usr/local/bin/sshnpd -a "$device_atsign" -m "$manager_atsign" -d "$device_name" "$delegate_policy" "$s" "$u" "$v" "$additional_args"
You can download a release from GitHub, or see the table below to download the latest release for your platform.
x64
(intel)
arm64
(apple)
arm
x64:
curl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-x64.tgz -o sshnp.tgzarm64:
curl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-arm64.tgz -o sshnp.tgzarm:
curl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-arm.tgz -o sshnp.tgzrisc-v:
curl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-linux-riscv.tgz -o sshnp.tgzx64 (intel):
curl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-macos-x64.zip -o sshnp.ziparm64 (apple):
curl -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-macos-arm64.zip -o sshnp.zipx64:
curl.exe -fSL https://github.com/atsign-foundation/noports/releases/latest/download/sshnp-windows-x64.zip -o sshnp.zipIf you downloaded from GitHub, the file name may be slightly different.
First, change directories into the unpacked download:
Then run the installer:
This will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
First, change directories into the unpacked download:
Then run the installer:
This will install the binaries to ~/.local/bin.
Instead, if you'd like to install the binaries to /usr/local/bin, run the installer as root:
Windows doesn't have a dedicated installer at this time.
You can find sshnp.exe in the unpacked archive, you may move this binary to wherever you like.
This step is optional, but highly recommended.
If you chose not to install as root, you will need to add ~/.local/bin to your PATH.
Add the following line to your shell's rc file:
If you chose not to install as root, you will need to add ~/.local/bin to your PATH.
Add the following line to your shell's rc file:
If you don't own a pair of NoPorts addresses, please visit the registrar before continuing.
We will now activate the client address, you only need to activate the client address now. The device address should be activated during the device installation.
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
Now that you have at_activate installed, you can invoke the command with the name of the address you would like to activate:
The application will pause and wait for the input of a one time pin (OTP) before you can continue. You should receive this pin to the contact information associated with the registration of your noports address (i.e. email or text message).
***If you are using a gmail.com account we have seen that sometimes the OTP gets stuck in the SPAM or PROMOTIONS folder. If you do not see the OTP check those folders.
Once you receive the message, enter the pin into the application and press enter to continue. The application should proceed to create the cryptographic keys and store them at ~/.atsign/keys/@my_noports_client_key.atKeys.
An address can only be activated once, to install this address to future devices, you must copy this file to the device (see 3.b.).
If you have activated the client address before, you must copy the address from another machine where it's been activated.
The address will be located at ~/.atsign/keys/@my_noports_client_key.atKeys. Copy this file from your other machine to the same location on the machine that you are installing sshnpd on.
sshnp is ready to go, you can now proceed to installing your device, or if you've already done that, checkout our usage guide.
tar -xf sshnp.tgzunzip sshnp.zipExpand-Archive -Force .\sshnp.zipcd sshnp./install.sh sshnp && ./install.sh srvsudo ./install.sh sshnp && sudo ./install.sh srvexport PATH="$PATH:$HOME/.local/bin";export PATH="$PATH:$HOME/.local/bin";./at_activate -a @my_noports_client./at_activate -a @my_noports_devicerisc-v
cd sshnp./install.sh sshnp && ./install.sh srvsudo ./install.sh sshnp && sudo ./install.sh srv