Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Connecto

AirDrop-like SSH key pairing for your terminal.

Connecto eliminates the hassle of manual SSH key setup. Instead of copying IP addresses and managing keys by hand, simply run connecto listen on one machine and connecto pair on another. Done.

Features

  • mDNS Discovery - Automatically discover devices on your local network
  • VPN Support - Save subnets for cross-network discovery
  • Zero-config Pairing - Exchange SSH keys with a single command
  • Auto SSH Config - ssh hostname just works after pairing
  • Modern Cryptography - Uses Ed25519 by default (RSA-4096 also supported)
  • Cross-platform - Works on Linux, macOS, and Windows

How it works

┌─────────────────┐                    ┌─────────────────┐
│  Target Machine │                    │  Client Machine │
│                 │                    │                 │
│  connecto listen│◄───── mDNS ───────►│  connecto scan  │
│                 │                    │                 │
│                 │◄── TCP/8099 ──────►│  connecto pair 0│
│                 │                    │                 │
│  authorized_keys│                    │  ~/.ssh/config  │
│     updated     │                    │    updated      │
└─────────────────┘                    └─────────────────┘
                                              │
                                              ▼
                                       ssh mydesktop ✓
  1. Target runs connecto listen - advertises via mDNS
  2. Client runs connecto scan - discovers available devices
  3. Client runs connecto pair 0 - exchanges SSH keys
  4. Done - ssh hostname just works

Quick example

On the target machine (where you want to SSH into):

connecto listen

On the client machine (where you want to SSH from):

connecto scan
connecto pair 0
ssh mydesktop  # It just works!

Next steps

Installation

Connecto can be installed on macOS, Linux, and Windows.

macOS

brew install andreisuslov/connecto/connecto

Binary download

Download the latest release from GitHub Releases:

# Apple Silicon (M1/M2/M3)
curl -LO https://github.com/andreisuslov/connecto/releases/latest/download/connecto-aarch64-apple-darwin.tar.gz
tar xzf connecto-aarch64-apple-darwin.tar.gz
sudo mv connecto /usr/local/bin/

# Intel Mac
curl -LO https://github.com/andreisuslov/connecto/releases/latest/download/connecto-x86_64-apple-darwin.tar.gz
tar xzf connecto-x86_64-apple-darwin.tar.gz
sudo mv connecto /usr/local/bin/

Windows

Run in PowerShell as Administrator:

irm https://raw.githubusercontent.com/andreisuslov/connecto/main/install.ps1 | iex

This will:

  • Download the latest release
  • Install to C:\Program Files\Connecto
  • Add to PATH
  • Configure firewall rules for mDNS and the Connecto port

Chocolatey

choco install connecto

Manual installation

  1. Download connecto-x86_64-pc-windows-msvc.zip from GitHub Releases
  2. Extract to C:\Program Files\Connecto
  3. Add to PATH

Linux

Binary download

# x86_64
curl -LO https://github.com/andreisuslov/connecto/releases/latest/download/connecto-x86_64-unknown-linux-gnu.tar.gz
tar xzf connecto-x86_64-unknown-linux-gnu.tar.gz
sudo mv connecto /usr/local/bin/

From source

Requires Rust 1.70+:

git clone https://github.com/andreisuslov/connecto
cd connecto
cargo install --path connecto_cli

Verify installation

connecto --version

Shell completions

Enable tab completion for your shell:

# Bash
connecto completions bash >> ~/.bashrc

# Zsh
connecto completions zsh >> ~/.zshrc

# Fish
connecto completions fish > ~/.config/fish/completions/connecto.fish

# PowerShell
connecto completions powershell >> $PROFILE

Restart your shell or source the config file.

Firewall configuration

Connecto uses:

  • UDP 5353 for mDNS discovery
  • TCP 8099 for the pairing protocol

Linux (iptables)

sudo iptables -A INPUT -p udp --dport 5353 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8099 -j ACCEPT

Linux (firewalld)

sudo firewall-cmd --add-port=5353/udp --permanent
sudo firewall-cmd --add-port=8099/tcp --permanent
sudo firewall-cmd --reload

macOS

macOS typically allows these connections by default. If needed, add rules in System Preferences > Security & Privacy > Firewall.

Windows

The PowerShell installer automatically configures firewall rules. For manual setup:

New-NetFirewallRule -DisplayName "Connecto mDNS" -Direction Inbound -Protocol UDP -LocalPort 5353 -Action Allow
New-NetFirewallRule -DisplayName "Connecto TCP" -Direction Inbound -Protocol TCP -LocalPort 8099 -Action Allow

Quick start

Get SSH access between two machines in under a minute.

Prerequisites

Step 1: Start the Listener

On the target machine (the one you want to SSH into):

connecto listen

You’ll see:

  CONNECTO LISTENER

→ Device name: mydesktop
→ Port: 8099

Local IP addresses:
  • 192.168.1.55

✓ mDNS service registered - device is now discoverable

Listening for pairing requests on port 8099...

Step 2: Scan for Devices

On the client machine (the one you want to SSH from):

connecto scan

You’ll see:

  CONNECTO SCANNER

→ Scanning for devices...

✓ Found 1 device(s):

[0] mydesktop (192.168.1.55:8099)

To pair with a device, run: connecto pair <number>

Step 3: Pair

Still on the client machine:

connecto pair 0

You’ll see:

  CONNECTO PAIRING

→ Connecting to 192.168.1.55:8099...
→ Using Ed25519 key (modern, secure, fast)

✓ Pairing successful!

Key saved:
  • Private: /home/user/.ssh/connecto_mydesktop
  • Public:  /home/user/.ssh/connecto_mydesktop.pub

✓ Added to ~/.ssh/config as 'mydesktop'

You can now connect with:

  ssh mydesktop

Step 4: Connect!

ssh mydesktop

That’s it! The listener exits automatically after successful pairing.

What just happened?

  1. Listener advertised itself via mDNS on your local network
  2. Scanner discovered the listener and displayed it
  3. Pair command:
    • Generated a new Ed25519 SSH key pair
    • Sent the public key to the listener
    • Listener added it to ~/.ssh/authorized_keys
    • Client saved the private key and updated ~/.ssh/config

Alternative: Bidirectional sync

If you want both devices to be able to SSH to each other, use sync instead:

# Run on BOTH devices at the same time
connecto sync

This exchanges keys bidirectionally - after sync completes, both devices can SSH to each other. See sync command for details.

Next steps

VPN Setup

When devices are on different subnets (common with VPNs), mDNS discovery won’t work across subnets. Connecto provides a simple solution: save the remote subnet once, and scans will include it automatically.

The problem

┌─────────────────────────────────────────────────────────────┐
│                         VPN Network                          │
├─────────────────────────┬───────────────────────────────────┤
│   Subnet A: 10.0.1.0/24 │   Subnet B: 10.0.2.0/24          │
│                         │                                   │
│   ┌─────────────┐       │       ┌─────────────┐            │
│   │   Your Mac  │       │       │   Windows   │            │
│   │  10.0.1.50  │  ✗ mDNS ✗     │  10.0.2.100 │            │
│   └─────────────┘       │       └─────────────┘            │
│                         │                                   │
└─────────────────────────┴───────────────────────────────────┘

mDNS broadcasts don’t cross subnet boundaries, so connecto scan won’t find devices on other subnets.

The solution

Step 1: Find the remote subnet

Ask your colleague or check your VPN documentation for the subnet. Common formats:

  • 10.0.2.0/24 (256 addresses)
  • 192.168.100.0/24
  • 172.16.5.0/24

Step 2: Save the Subnet

connecto config add-subnet 10.0.2.0/24

You can add multiple subnets:

connecto config add-subnet 10.0.3.0/24
connecto config add-subnet 192.168.100.0/24

Step 3: Scan and Pair

Now connecto scan will automatically include saved subnets:

connecto scan
  CONNECTO SCANNER

→ Scanning for devices...

✓ Found 1 device(s):

[0] windows-workstation (10.0.2.100:8099)

Pair as usual:

connecto pair 0

Managing subnets

List saved subnets

connecto config list
Configured subnets:
  • 10.0.2.0/24
  • 10.0.3.0/24

Remove a subnet

connecto config remove-subnet 10.0.3.0/24

Config file location

connecto config path

The config file is stored at:

  • macOS/Linux: ~/.config/connecto/config.json
  • Windows: %APPDATA%\connecto\config.json

One-time subnet scan

If you don’t want to save a subnet permanently, use the --subnet flag:

connecto scan --subnet 10.0.2.0/24

You can specify multiple subnets:

connecto scan -s 10.0.2.0/24 -s 10.0.3.0/24

Listener VPN hint

When someone pairs from a different subnet, the listener shows a helpful message:

✓ Successfully paired with mac-laptop!
  → They can now SSH to this machine.

VPN/Cross-subnet connection detected!
  → Tell mac-laptop to save your subnet for future scans:
    connecto config add-subnet 10.0.1.0/24

Direct pairing

If you know the exact IP, skip scanning entirely:

connecto pair 10.0.2.100:8099

Troubleshooting

Scan takes too long

Scanning large subnets can take time. Connecto scans up to 100 IPs concurrently with 500ms timeout per IP.

For faster scans, use a smaller subnet if possible:

  • /24 = 254 IPs (~2-3 seconds)
  • /22 = 1022 IPs (~5-10 seconds)
  • /16 = 65534 IPs (not recommended)

Connection refused

Ensure:

  1. The target is running connecto listen
  2. Firewall allows TCP 8099
  3. VPN is connected and routing works

Test connectivity:

# Check if port is open
nc -zv 10.0.2.100 8099

listen

Start a listener to accept pairing requests.

Usage

connecto listen [OPTIONS]

Description

The listen command starts a pairing listener on the current machine. It:

  1. Advertises the device via mDNS on the local network
  2. Waits for incoming pairing requests on TCP port 8099
  3. Accepts public keys and adds them to ~/.ssh/authorized_keys
  4. Exits after successful pairing (unless --continuous is used)

Options

OptionDescription
-p, --port <PORT>Port to listen on (default: 8099)
-n, --name <NAME>Device name to advertise (default: hostname)
-c, --continuousKeep listening after successful pairing
--verifyRequire verification code for pairing

Examples

Basic usage

connecto listen

Output:

  CONNECTO LISTENER

→ Device name: mydesktop
→ Port: 8099

Local IP addresses:
  • 192.168.1.55

✓ mDNS service registered - device is now discoverable

Listening for pairing requests on port 8099...

Custom name and port

connecto listen --name workstation --port 9000

Continuous mode

Keep listening for multiple pairings:

connecto listen --continuous

What happens during pairing

  1. Client connects and sends their public key
  2. Listener adds the key to ~/.ssh/authorized_keys
  3. Listener sends back its hostname and username
  4. Both sides confirm success
  5. Listener exits (or continues if --continuous)

VPN/Cross-Subnet Detection

When a pairing comes from a different subnet, the listener displays a helpful message:

✓ Successfully paired with mac-laptop!
  → They can now SSH to this machine.

VPN/Cross-subnet connection detected!
  → Tell mac-laptop to save your subnet for future scans:
    connecto config add-subnet 10.0.1.0/24

Security notes

  • Only run listen when you intend to pair
  • The listener only accepts SSH public keys (not arbitrary data)
  • Keys are added to authorized_keys with a comment identifying Connecto
  • Stop the listener when done to prevent unwanted pairings

scan

Discover devices running connecto listen.

Usage

connecto scan [OPTIONS]

Description

The scan command discovers devices on your network that are running connecto listen. It uses:

  1. mDNS discovery - Finds devices advertising the _connecto._tcp service
  2. Subnet scanning - Scans saved subnets and optionally specified subnets

Options

OptionDescription
-s, --subnet <CIDR>Additional subnet to scan (can be repeated)
-t, --timeout <SECONDS>Scan timeout in seconds (default: 5)

Examples

Basic scan

connecto scan

Output:

  CONNECTO SCANNER

→ Scanning for devices...

✓ Found 2 device(s):

[0] mydesktop (192.168.1.55:8099)
[1] workstation (192.168.1.100:8099)

To pair with a device, run: connecto pair <number>

Scan additional subnet

connecto scan --subnet 10.0.2.0/24

Scan multiple subnets

connecto scan -s 10.0.2.0/24 -s 10.0.3.0/24

Discovery methods

mDNS Discovery

mDNS (multicast DNS) automatically finds devices on the same subnet. No configuration needed.

Limitations:

  • Only works within the same subnet
  • May be blocked by some network configurations

Subnet scanning

For VPN or cross-subnet scenarios, Connecto scans IP ranges directly.

Saved subnets are automatically included:

connecto config add-subnet 10.0.2.0/24
connecto scan  # Now includes 10.0.2.0/24

One-time subnets can be specified with --subnet:

connecto scan --subnet 10.0.2.0/24

Scan performance

Subnet SizeIPsApproximate Time
/242542-3 seconds
/221,0225-10 seconds
/1665,534Not recommended

Connecto scans up to 100 IPs concurrently with a 500ms timeout per IP.

No devices found?

If no devices are found:

  1. Ensure the target is running connecto listen
  2. Check firewall allows TCP 8099 and UDP 5353
  3. For VPN, add the remote subnet: connecto config add-subnet <CIDR>
  4. Try direct pairing: connecto pair <ip>:8099

See Troubleshooting for more help.

pair

Pair with a discovered device or direct IP.

Usage

connecto pair <TARGET>

Arguments

ArgumentDescription
TARGETDevice number from scan, or direct IP:port

Options

OptionDescription
-k, --key <PATH>Use existing SSH key instead of generating new
-c, --comment <TEXT>Custom key comment
--rsaGenerate RSA-4096 instead of Ed25519

Description

The pair command establishes SSH key-based authentication with a remote device:

  1. Generates a new Ed25519 SSH key pair
  2. Sends the public key to the target device
  3. Saves the private key to ~/.ssh/connecto_<hostname>
  4. Updates ~/.ssh/config for easy ssh hostname access

Examples

Pair by Device Number

After running connecto scan:

connecto pair 0

Output:

  CONNECTO PAIRING

→ Connecting to 192.168.1.55:8099...
→ Using Ed25519 key (modern, secure, fast)

✓ Pairing successful!

Key saved:
  • Private: /home/user/.ssh/connecto_mydesktop
  • Public:  /home/user/.ssh/connecto_mydesktop.pub

✓ Added to ~/.ssh/config as 'mydesktop'

You can now connect with:

  ssh mydesktop

Pair by IP Address

Skip scanning and pair directly:

connecto pair 192.168.1.55:8099

Or with just the IP (uses default port 8099):

connecto pair 192.168.1.55

What gets created

SSH key pair

  • Private key: ~/.ssh/connecto_<hostname>
  • Public key: ~/.ssh/connecto_<hostname>.pub

Keys use Ed25519 by default (modern, secure, fast).

SSH config entry

An entry is added to ~/.ssh/config:

# Added by Connecto
Host mydesktop
    HostName 192.168.1.55
    User john
    IdentityFile ~/.ssh/connecto_mydesktop
    IdentitiesOnly yes

This allows simple ssh mydesktop without specifying user, IP, or key.

Re-pairing

If you pair with a device that already has an entry:

  1. The old key files are overwritten
  2. The SSH config entry is updated
  3. A new key exchange occurs

This is useful when:

  • The remote machine was reinstalled
  • You want to refresh the keys
  • The IP address changed

Using existing keys

Instead of generating a new key for each pairing, you can use an existing SSH key.

One-time usage

connecto pair 0 --key ~/.ssh/id_ed25519

Set default key

Set a default key for all future pairings:

connecto config set-default-key ~/.ssh/id_ed25519

Now all connecto pair commands will use this key automatically.

Clear default key

Return to generating new keys:

connecto config clear-default-key

Priority order

When pairing, Connecto looks for keys in this order:

  1. --key flag (if specified)
  2. Config default key (if set)
  3. Generate new key (default behavior)

After pairing

Connect immediately:

ssh mydesktop

Or verify the pairing:

connecto test mydesktop

sync

Bidirectional SSH key pairing between two devices.

Usage

connecto sync [OPTIONS]

Description

The sync command enables two devices to simultaneously exchange SSH keys so both can SSH to each other. Unlike the listen + pair workflow which is one-directional (client can SSH to target), sync establishes bidirectional access.

Both devices run connecto sync at the same time, and they:

  1. Advertise via mDNS (_connecto-sync._tcp.local.)
  2. Scan for sync peers on the network
  3. When found, exchange SSH public keys
  4. Both add each other’s key to ~/.ssh/authorized_keys
  5. Both can now SSH to each other

Options

OptionDescription
-p, --port <PORT>Port to use for sync (default: 8099)
-n, --name <NAME>Custom device name (default: hostname)
-t, --timeout <SECS>Peer search timeout in seconds (default: 60)
--rsaUse RSA-4096 key instead of Ed25519
-k, --key <PATH>Use existing SSH key instead of generating new one

Examples

Basic usage

Run on both devices simultaneously:

# On Device A
connecto sync

# On Device B (at the same time)
connecto sync

Output on Device A:

  CONNECTO SYNC

→ Device name: device-a
→ Port: 8099
→ Timeout: 60s

Local IP addresses:
  • 192.168.1.100

→ Generating Ed25519 key for sync...
→ Key saved: /Users/alice/.ssh/connecto_sync_device-a

Waiting for sync peer...
Run 'connecto sync' on another device on the same network
Press Ctrl+C to cancel

→ Found peer: Device B (192.168.1.101:8099)
→ Connected to Device B
→ Received key from Device B: bob@device-b
→ Our key was accepted by peer

✓ Sync completed with Device B!
  → Bidirectional SSH access established.
  → You can SSH to them, and they can SSH to you.

Sync Summary:
  • Peer: Device B
  • User: bob
  • Address: 192.168.1.101:8099

Next steps:
  → SSH to peer: ssh device-b

✓ Sync successful!

With custom timeout

For slower networks:

connecto sync --timeout 120

Using an existing key

connecto sync --key ~/.ssh/my_existing_key

Using RSA instead of Ed25519

connecto sync --rsa

How it works

  1. Both devices advertise: Each device registers a sync service via mDNS
  2. Both devices search: Each device also searches for other sync services
  3. Priority determines initiator: Each device generates a random priority; the one that connects first becomes the initiator
  4. Key exchange: Initiator sends SyncHello with its public key, responder replies with SyncHelloAck containing its key
  5. Mutual installation: Both devices add the received key to their authorized_keys
  6. Confirmation: Both send SyncComplete to confirm success

Comparison with listen + pair

Aspectlisten + pairsync
DirectionOne-wayBidirectional
WorkflowRun listen on target, pair on clientRun sync on both
ResultClient can SSH to targetBoth can SSH to each other
Use caseSetting up access to a serverTwo peers that need mutual access

Protocol messages

The sync protocol uses these message types:

  • SyncHello: Contains version, device name, priority, public key, and SSH user
  • SyncHelloAck: Response with the peer’s public key and acceptance status
  • SyncComplete: Final confirmation of success or failure

Troubleshooting

Timeout waiting for sync peer

  • Ensure both devices are on the same network
  • Check that mDNS/Bonjour is not blocked by firewall
  • Try increasing the timeout: connecto sync --timeout 120

Connection refused

  • Make sure both devices start sync around the same time
  • Check that port 8099 is not in use by another service
  • Try a different port: connecto sync --port 9000

Keys not being added

  • Check write permissions on ~/.ssh/authorized_keys
  • Ensure ~/.ssh directory exists with proper permissions (700)

Security notes

  • Sync only with trusted devices on your local network
  • The sync protocol requires both parties to actively participate
  • Keys are generated fresh for each sync (unless --key is specified)
  • Only run sync when you intend to exchange keys with another device

hosts

List all paired hosts.

Usage

connecto hosts

Description

The hosts command displays all devices you’ve paired with using Connecto. It reads from ~/.ssh/config and shows hosts that have Connecto-generated keys.

Example

connecto hosts

Output:

  PAIRED HOSTS

[0] mydesktop
    → Host: 192.168.1.55
    → User: john
    → Key:  ~/.ssh/connecto_mydesktop

[1] workstation
    → Host: 10.0.2.100
    → User: admin
    → Key:  ~/.ssh/connecto_workstation

[2] laptop
    → Host: 192.168.1.42
    → User: alice
    → Key:  ~/.ssh/connecto_laptop

Output fields

FieldDescription
HostIP address or hostname of the remote machine
UserUsername for SSH connection
KeyPath to the private key file
CommandDescription
connecto test <host>Test SSH connection
connecto update-ip <host> <ip>Update host’s IP address
connecto unpair <host>Remove pairing
connecto exportBackup all pairings

unpair

Remove a paired host and delete its keys.

Usage

connecto unpair <HOST>

Arguments

ArgumentDescription
HOSTName of the paired host to remove

Description

The unpair command removes a pairing established by Connecto:

  1. Removes the host entry from ~/.ssh/config
  2. Deletes the private key (~/.ssh/connecto_<host>)
  3. Deletes the public key (~/.ssh/connecto_<host>.pub)

Example

connecto unpair mydesktop

Output:

  CONNECTO UNPAIR

→ Removing host: mydesktop

✓ Removed from ~/.ssh/config
✓ Deleted key: ~/.ssh/connecto_mydesktop
✓ Deleted key: ~/.ssh/connecto_mydesktop.pub

Host 'mydesktop' has been unpaired.

Notes

  • This only removes the local configuration
  • The public key remains in the remote machine’s ~/.ssh/authorized_keys
  • To fully revoke access, also remove the key from the remote machine

Re-pairing

After unpairing, you can pair again:

connecto scan
connecto pair 0

A new key pair will be generated and exchanged.

CommandDescription
connecto hostsList all paired hosts
connecto exportBackup pairings before removing

test

Test SSH connection to a paired host.

Usage

connecto test <HOST>

Arguments

ArgumentDescription
HOSTName of the paired host to test

Description

The test command verifies that SSH connectivity works to a paired host. It:

  1. Looks up the host in ~/.ssh/config
  2. Attempts an SSH connection
  3. Runs a simple command (echo "Connecto test successful")
  4. Reports success or failure

Example

Successful test

connecto test mydesktop

Output:

  CONNECTO TEST

→ Testing connection to: mydesktop

✓ Connection successful!
  → SSH to mydesktop is working.

Failed test

connecto test mydesktop

Output:

  CONNECTO TEST

→ Testing connection to: mydesktop

✗ Connection failed!
  → Error: Connection refused

Troubleshooting:
  • Check if the host is online
  • Verify the IP address: connecto hosts
  • Update IP if changed: connecto update-ip mydesktop <new-ip>

Common issues

ErrorCauseSolution
Connection refusedHost offline or SSH not runningStart the remote machine
Connection timed outWrong IP or network issueUpdate IP with connecto update-ip
Permission deniedKey not in authorized_keysRe-pair with connecto pair
Host key verification failedRemote host changedRemove from ~/.ssh/known_hosts
CommandDescription
connecto hostsList all paired hosts
connecto update-ipUpdate host’s IP address
connecto pairRe-establish pairing

update-ip

Update the IP address for a paired host.

Usage

connecto update-ip <HOST> <IP>

Arguments

ArgumentDescription
HOSTName of the paired host
IPNew IP address

Description

The update-ip command changes the IP address for a paired host in ~/.ssh/config. This is useful when:

  • A device gets a new DHCP lease
  • You’re switching between networks (home/office)
  • The VPN assigns a different IP

The SSH keys remain valid - only the IP changes.

Example

connecto update-ip mydesktop 10.0.2.50

Output:

  CONNECTO UPDATE-IP

→ Updating IP for: mydesktop
→ Old IP: 192.168.1.55
→ New IP: 10.0.2.50

✓ Updated successfully!

You can now connect with:

  ssh mydesktop

Finding the New IP

On the Remote Machine

# Linux/macOS
ip addr show | grep inet

# Windows
ipconfig

Using Connecto scan

If the remote is running connecto listen:

connecto scan

The scan results show the current IP.

Notes

  • The SSH keys are not affected
  • You don’t need to re-pair after updating the IP
  • Consider using static IPs or hostnames for frequently-changing devices
CommandDescription
connecto hostsView current IP addresses
connecto testVerify connection after update

export / import

Backup and restore paired hosts configuration.

Export

Usage

connecto export [OUTPUT]

Arguments

ArgumentDescription
OUTPUTOutput file path (optional, prints to stdout if omitted)

Description

Exports all paired hosts to a JSON file for backup or transfer to another machine.

Examples

Export to file:

connecto export ~/connecto-backup.json

Export to stdout:

connecto export

Pipe to clipboard (macOS):

connecto export | pbcopy

Export format

{
  "version": 1,
  "hosts": [
    {
      "host": "mydesktop",
      "hostname": "192.168.1.55",
      "user": "john",
      "identity_file": "~/.ssh/connecto_mydesktop"
    }
  ],
  "subnets": ["10.0.2.0/24", "10.0.3.0/24"]
}

Note: The export contains SSH config entries only, not the actual key files. To fully backup/restore, you should also copy the key files from ~/.ssh/.


Import

Usage

connecto import <FILE>

Arguments

ArgumentDescription
FILEPath to the export JSON file

Description

Imports paired hosts from a previously exported JSON file. This:

  1. Restores SSH key files
  2. Adds entries to ~/.ssh/config
  3. Restores saved subnets to config

Example

connecto import ~/connecto-backup.json

Output:

  CONNECTO IMPORT

→ Importing from: ~/connecto-backup.json

✓ Imported host: mydesktop
✓ Imported host: workstation
✓ Imported 2 subnets

Successfully imported 2 hosts.

Handling conflicts

If a host already exists:

  • Existing keys are preserved
  • The import skips that host
  • A warning is displayed

To replace an existing host, first unpair it:

connecto unpair mydesktop
connecto import backup.json

Use cases

Backup before reinstall

connecto export > ~/Dropbox/connecto-backup.json
# Reinstall OS
connecto import ~/Dropbox/connecto-backup.json

Transfer to new machine

# On old machine
connecto export > /tmp/connecto.json
scp /tmp/connecto.json newmachine:/tmp/

# On new machine
connecto import /tmp/connecto.json

Sync across machines

While not a true sync, you can share exports via cloud storage:

# Machine A
connecto export > ~/Dropbox/connecto.json

# Machine B
connecto import ~/Dropbox/connecto.json

Security notes

  • The export contains references to private keys (file paths), not the keys themselves
  • The actual key files in ~/.ssh/ should be backed up separately
  • For a complete backup, also copy the key files:
# Full backup
connecto export > connecto-backup.json
cp ~/.ssh/connecto_* ~/backup/
CommandDescription
connecto hostsList current pairings
connecto config listList saved subnets

config

Manage Connecto configuration.

Usage

connecto config <SUBCOMMAND>

Subcommands

SubcommandDescription
add-subnet <CIDR>Add a subnet to scan automatically
remove-subnet <CIDR>Remove a saved subnet
set-default-key <PATH>Set default SSH key for pairing
clear-default-keyClear the default SSH key
listList all configuration
pathShow config file location

add-subnet

Add a subnet that will be scanned automatically.

connecto config add-subnet 10.0.2.0/24

Output:

✓ Added subnet: 10.0.2.0/24

Useful for VPN networks where mDNS doesn’t work across subnets.


remove-subnet

Remove a previously saved subnet.

connecto config remove-subnet 10.0.2.0/24

Output:

✓ Removed subnet: 10.0.2.0/24

set-default-key

Set a default SSH key to use for all pairings.

connecto config set-default-key ~/.ssh/id_ed25519

Output:

✓ Default key set: /Users/john/.ssh/id_ed25519
  → All future pairings will use this key.

This is useful when you want to:

  • Reuse your existing SSH key across all devices
  • Use a single key for easier management
  • Avoid generating multiple Connecto-specific keys

clear-default-key

Remove the default SSH key setting.

connecto config clear-default-key

Output:

✓ Default key cleared.
  → Pairings will generate new keys again.

list

Show all configured subnets.

connecto config list

Output:

Configured subnets:
  • 10.0.2.0/24
  • 10.0.3.0/24
  • 192.168.100.0/24

path

Show where the config file is stored.

connecto config path

Output:

Config file: /Users/john/.config/connecto/config.json

Config file locations

PlatformPath
macOS~/.config/connecto/config.json
Linux~/.config/connecto/config.json
Windows%APPDATA%\connecto\config.json

Config file format

The config file is JSON:

{
  "subnets": [
    "10.0.2.0/24",
    "10.0.3.0/24"
  ],
  "default_key": "/Users/john/.ssh/id_ed25519"
}

You can edit it manually, but using the connecto config commands is recommended.


Use cases

VPN Setup

When connecting to machines on a VPN:

# Save the VPN subnet once
connecto config add-subnet 10.0.2.0/24

# Now scans include that subnet automatically
connecto scan

Multiple office networks

connecto config add-subnet 10.0.1.0/24   # Office A
connecto config add-subnet 10.0.2.0/24   # Office B
connecto config add-subnet 192.168.0.0/24 # Home

Scans will check all saved subnets regardless of which network you’re on.

CommandDescription
connecto scanScan for devices
connecto scan --subnetOne-time subnet scan

keys

Manage SSH keys.

GUI key management

The Connecto GUI provides a full-featured key management interface in the Keys tab:

Authorized keys

View and manage SSH keys that are authorized to connect to this machine. You can:

  • View key algorithm, fingerprint, and comment
  • Remove keys to revoke access

Local keys

View and manage SSH key pairs stored in ~/.ssh/:

  • List keys: See all local key pairs with algorithm, comment, and fingerprint
  • Copy path: Copy the public key path to clipboard
  • Rename: Rename key files (both private and public)
  • Delete: Remove key pairs permanently

Generate new key

Create new SSH key pairs:

  • Choose between Ed25519 (default) and RSA-4096
  • Set custom key name and comment
  • Keys are saved to ~/.ssh/

CLI key management

The CLI key management commands are planned for a future release.

Planned features

List keys

connecto keys list

Show all Connecto-generated SSH keys.

Rotate keys

connecto keys rotate <HOST>

Generate a new key pair for a host and update the remote authorized_keys.

Key info

connecto keys info <HOST>

Display key details (type, fingerprint, creation date).

Current CLI workarounds

List Connecto keys

ls -la ~/.ssh/connecto_*

View key fingerprint

ssh-keygen -lf ~/.ssh/connecto_mydesktop.pub

Manual key rotation

  1. Unpair the host: connecto unpair mydesktop
  2. Re-pair: connecto scan && connecto pair 0
CommandDescription
connecto hostsList paired hosts
connecto unpairRemove pairing
connecto pairEstablish new pairing

completions

Generate shell completion scripts.

Usage

connecto completions <SHELL>

Arguments

ArgumentDescription
SHELLTarget shell: bash, zsh, fish, or powershell

Description

Generates tab-completion scripts for your shell. After installation, pressing Tab will complete Connecto commands and options.

Installation

Bash

# Add to ~/.bashrc
connecto completions bash >> ~/.bashrc

# Or install system-wide
sudo connecto completions bash > /etc/bash_completion.d/connecto

Restart your shell or run:

source ~/.bashrc

Zsh

# Add to ~/.zshrc
connecto completions zsh >> ~/.zshrc

Or for Oh My Zsh:

connecto completions zsh > ~/.oh-my-zsh/completions/_connecto

Restart your shell or run:

source ~/.zshrc

Fish

connecto completions fish > ~/.config/fish/completions/connecto.fish

Completions are available immediately in new shells.

PowerShell

# Add to your profile
connecto completions powershell >> $PROFILE

# Reload profile
. $PROFILE

To find your profile path:

echo $PROFILE

Example usage

After installation:

connecto <Tab>
# Shows: config  export  hosts  import  listen  pair  scan  test  unpair  update-ip

connecto config <Tab>
# Shows: add-subnet  list  path  remove-subnet

connecto scan --<Tab>
# Shows: --subnet  --timeout

Troubleshooting

Bash completions not working

Ensure bash-completion is installed:

# macOS
brew install bash-completion

# Ubuntu/Debian
apt install bash-completion

Zsh completions not working

Ensure completion system is initialized. Add to ~/.zshrc:

autoload -Uz compinit && compinit

Fish completions not working

Check that the completions directory exists:

mkdir -p ~/.config/fish/completions

Configuration

Connecto stores configuration in platform-specific locations.

Config file location

PlatformPath
macOS~/.config/connecto/config.json
Linux~/.config/connecto/config.json
Windows%APPDATA%\connecto\config.json

Find your config path:

connecto config path

Config file format

{
  "subnets": [
    "10.0.2.0/24",
    "192.168.100.0/24"
  ],
  "default_key": "/Users/john/.ssh/id_ed25519"
}

Fields

FieldTypeDescription
subnetsstring[]CIDR ranges to scan automatically
default_keystring?Path to default SSH key for pairing (optional)

SSH Configuration

Connecto modifies ~/.ssh/config when pairing. Each paired host gets an entry:

# Added by Connecto
Host mydesktop
    HostName 192.168.1.55
    User john
    IdentityFile ~/.ssh/connecto_mydesktop
    IdentitiesOnly yes

Entry fields

FieldDescription
HostAlias used with ssh command
HostNameIP address or hostname
UserRemote username
IdentityFilePath to private key
IdentitiesOnlyUse only the specified key

SSH Keys

Keys are stored in the SSH directory:

PlatformDirectory
macOS/Linux~/.ssh/
Windows%USERPROFILE%\.ssh\

Key files

For each paired host:

  • ~/.ssh/connecto_<hostname> - Private key
  • ~/.ssh/connecto_<hostname>.pub - Public key

Key type

Connecto generates Ed25519 keys by default:

  • Modern elliptic curve cryptography
  • 256-bit security level
  • Small key size (compact authorized_keys)
  • Fast generation and authentication

Environment variables

VariableDescription
HOMEHome directory (Unix) - used to find ~/.ssh
USERPROFILEHome directory (Windows) - used to find .ssh

Ports

PortProtocolPurpose
5353UDPmDNS discovery
8099TCPPairing protocol

authorized_keys Format

When accepting a pairing, Connecto adds to ~/.ssh/authorized_keys:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG... connecto_laptop_2024-01-15

The comment includes:

  • connecto_ prefix for identification
  • Source hostname
  • Date of pairing

Protocol

Technical details of the Connecto pairing protocol.

Overview

Connecto uses a simple TCP-based protocol for key exchange:

┌────────────┐                    ┌────────────┐
│   Client   │                    │  Listener  │
│  (pair)    │                    │  (listen)  │
└─────┬──────┘                    └──────┬─────┘
      │                                   │
      │──── TCP Connect (port 8099) ─────>│
      │                                   │
      │──── HELLO <version> ─────────────>│
      │                                   │
      │<──── HELLO <version> ─────────────│
      │                                   │
      │──── PUBKEY <ssh-public-key> ─────>│
      │                                   │
      │<──── OK <hostname> <user> ────────│
      │                                   │
      │──── BYE ─────────────────────────>│
      │                                   │
      ×─────── Connection Closed ─────────×

Message format

All messages are newline-terminated strings:

COMMAND [ARGUMENTS...]\n

Messages

HELLO

Version handshake.

HELLO 1
FieldDescription
VersionProtocol version (currently 1)

PUBKEY

Client sends their SSH public key.

PUBKEY ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG... user@hostname
FieldDescription
KeyFull SSH public key in OpenSSH format

OK

Listener confirms successful pairing.

OK mydesktop john
FieldDescription
HostnameListener’s hostname
UserUsername for SSH connection

ERR

Error response.

ERR Invalid public key format
FieldDescription
MessageHuman-readable error description

BYE

Connection closing.

BYE

Discovery

mDNS

Connecto advertises via mDNS:

FieldValue
Service Type_connecto._tcp
Port8099
TXT Recordsversion=1

Devices respond to mDNS queries on UDP port 5353.

Subnet scanning

For cross-subnet discovery, Connecto scans IP ranges:

  1. Generate list of IPs from CIDR (e.g., 10.0.2.0/24 → 254 IPs)
  2. Attempt TCP connection to port 8099 on each IP
  3. 100 concurrent connections, 500ms timeout each
  4. Valid listeners respond to HELLO

Security considerations

What’s protected

  • Authentication: SSH keys provide cryptographic authentication
  • Integrity: SSH protocol ensures connection integrity
  • Authorization: Keys only added with physical/network access

What’s not protected

  • Initial Exchange: The pairing protocol itself is unencrypted
  • Network Eavesdropping: Public keys are sent in plaintext (this is safe - they’re public)
  • Man-in-the-Middle: No certificate verification during pairing

Recommendations

  • Only run listen on trusted networks
  • Verify the IP address before pairing
  • Use SSH host key verification after pairing
  • Review authorized_keys periodically

Wire format example

Complete pairing session:

CLIENT: HELLO 1
SERVER: HELLO 1
CLIENT: PUBKEY ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKx... user@laptop
SERVER: OK desktop john
CLIENT: BYE
[connection closed]

Future considerations

Potential protocol enhancements:

  • TLS encryption for the pairing channel
  • Challenge-response verification
  • QR code / out-of-band verification
  • Key rotation protocol

Security

Security model and best practices for Connecto.

Threat model

Protected against

ThreatProtection
Password guessingSSH key authentication only
Credential theftPrivate keys never leave the device
Replay attacksSSH protocol cryptographic protection
Network sniffingSSH encrypts all traffic after pairing

Not protected against

ThreatMitigation
Malicious network accessOnly pair on trusted networks
Physical device accessUse full-disk encryption
Compromised endpointsKeep systems updated

Key security

Key generation

  • Algorithm: Ed25519 (elliptic curve)
  • Security level: 128-bit equivalent
  • Key size: 256-bit private, 256-bit public

Ed25519 advantages:

  • No known practical attacks
  • Resistant to timing attacks
  • Small, fast signatures
  • Widely supported (OpenSSH 6.5+)

When to prefer RSA-4096

While Ed25519 is the default and recommended for most users, RSA-4096 may be preferred in certain scenarios:

ReasonDetails
Legacy compatibilitySystems running OpenSSH < 6.5 (pre-2014) or older embedded devices may not support Ed25519
Hardware security modulesSome older HSMs, smart cards, and hardware tokens only support RSA keys
Compliance requirementsCertain regulatory frameworks (e.g., older FIPS 140-2 configurations, some government standards) may mandate RSA
Conservative cryptographic choiceRSA has 40+ years of cryptanalysis; some organizations prefer battle-tested algorithms
Cross-platform interoperabilityBetter support across legacy SSH implementations, older libraries, and enterprise software

RSA-4096 trade-offs:

  • Slower: key generation, signing, and verification are significantly slower than Ed25519
  • Larger keys: 4096-bit keys vs 256-bit (affects storage and transmission)
  • More complex implementation: higher risk of implementation flaws (padding oracles, timing attacks)

To use RSA-4096 with Connecto, specify the key type during pairing:

connecto pair --key-type rsa <target>

Key storage

ComponentLocationPermissions
Private key~/.ssh/connecto_*600 (owner read/write)
Public key~/.ssh/connecto_*.pub644 (world readable)
Authorized keys~/.ssh/authorized_keys600

Key lifecycle

  1. Generation: Created fresh for each pairing
  2. Distribution: Public key sent to listener
  3. Storage: Private key saved locally, public key in authorized_keys
  4. Revocation: connecto unpair removes local keys; manual removal from authorized_keys

Network security

Pairing protocol

The pairing protocol is unencrypted but designed to be safe:

  • Only public keys are transmitted (safe to expose)
  • Connection requires network access (implicit trust boundary)
  • Short-lived listener (exits after pairing)

Ports used

PortProtocolPurposeExposure
5353UDPmDNSLocal network
8099TCPPairingLocal network
22TCPSSHConfigurable

Recommendations

  1. Firewall: Only allow 8099 during pairing
  2. VPN: Use VPN for cross-internet pairing
  3. Monitoring: Log authorized_keys changes

Best practices

Before pairing

-Verify you’re on a trusted network -Confirm the target IP is correct -Ensure the listener is running on the intended machine

After pairing

  • Test the connection: connecto test <host>
  • Verify SSH host key fingerprint on first connect
  • Stop the listener if still running

Ongoing

  • Periodically review ~/.ssh/authorized_keys
  • Remove unused pairings: connecto unpair <host>
  • Keep Connecto and SSH updated

Auditing

List Connecto keys

connecto hosts

View authorized_keys

grep connecto ~/.ssh/authorized_keys

Check key fingerprints

for key in ~/.ssh/connecto_*.pub; do
  echo "=== $key ==="
  ssh-keygen -lf "$key"
done

SSH connection logs

# macOS
log show --predicate 'process == "sshd"' --last 1h

# Linux
journalctl -u sshd --since "1 hour ago"

# Windows
Get-EventLog -LogName Security -InstanceId 4624 |
  Where-Object { $_.Message -like "*ssh*" }

Incident response

Suspected compromise

  1. Immediately: Remove unauthorized keys

    # Edit authorized_keys
    nano ~/.ssh/authorized_keys
    
  2. Audit: Check all Connecto pairings

    connecto hosts
    
  3. Revoke: Remove suspicious pairings

    connecto unpair <suspicious-host>
    
  4. Investigate: Check SSH logs for unauthorized access

Key rotation

To rotate keys for a host:

connecto unpair mydesktop
# Have target run: connecto listen
connecto scan
connecto pair 0

Comparison

vs password authentication

AspectPasswordConnecto (SSH keys)
Brute forceVulnerableImmune
Credential reuseCommonImpossible
PhishingPossibleDifficult
Setup complexityLowLow (with Connecto)

vs manual SSH keys

AspectManualConnecto
Key generationManualAutomatic
Key distributionCopy/pasteProtocol
Config setupManualAutomatic
DiscoveryManualmDNS

Troubleshooting

Common issues and solutions.

Discovery issues

“No devices found” during scan

Causes:

  1. Listener not running
  2. Firewall blocking mDNS or TCP
  3. Different subnets (VPN scenario)

Solutions:

  1. Verify listener is running:

    # On target machine
    connecto listen
    
  2. Check firewall:

    # Test mDNS (macOS/Linux)
    dns-sd -B _connecto._tcp
    
    # Test TCP port
    nc -zv <target-ip> 8099
    
  3. For VPN/cross-subnet:

    connecto config add-subnet 10.0.2.0/24
    connecto scan
    

Scan finds device but can’t connect

Causes:

  1. Firewall allows mDNS but blocks TCP
  2. Listener crashed after advertising

Solutions:

  1. Restart listener: connecto listen
  2. Check TCP connectivity: nc -zv <ip> 8099
  3. Review firewall rules for TCP 8099

Pairing issues

“Connection refused”

Causes:

  1. Listener not running
  2. Wrong port
  3. Firewall blocking TCP

Solutions:

# Verify listener is running
ps aux | grep connecto

# Check if port is listening
lsof -i :8099  # macOS/Linux
netstat -an | findstr 8099  # Windows

# Test connection
nc -zv <ip> 8099

“Connection timed out”

Causes:

  1. Wrong IP address
  2. Network routing issue
  3. Firewall dropping packets

Solutions:

# Verify IP is reachable
ping <ip>

# Check route
traceroute <ip>  # macOS/Linux
tracert <ip>     # Windows

“Permission denied” after pairing

Causes:

  1. Key not added to authorized_keys
  2. Wrong username
  3. SSH config issue

Solutions:

# On target machine, verify key was added
grep connecto ~/.ssh/authorized_keys

# Check permissions
ls -la ~/.ssh/
# Should be: authorized_keys 600, .ssh dir 700

# Test with verbose SSH
ssh -v <host>

SSH Issues

“Host key verification failed”

The remote host’s SSH server key changed.

Solutions:

# Remove old key
ssh-keygen -R <ip>

# Connect again (will prompt to accept new key)
ssh <host>

“Too many authentication failures”

SSH agent offering too many keys.

Solutions:

# Connect with specific key only
ssh -o IdentitiesOnly=yes -i ~/.ssh/connecto_<host> <host>

# Or update ~/.ssh/config (Connecto does this automatically):
# IdentitiesOnly yes

Can’t connect after IP change

Solutions:

# Update the IP
connecto update-ip <host> <new-ip>

# Verify
connecto test <host>

Platform-specific issues

macOS

mDNS not working:

# Check mDNS daemon
sudo launchctl list | grep mDNS

# Restart mDNS
sudo killall -HUP mDNSResponder

Firewall prompts:

  • Allow “connecto” in System Preferences → Security & Privacy → Firewall

Windows

Firewall blocking Connecto:

# Add firewall rules
New-NetFirewallRule -DisplayName "Connecto mDNS" -Direction Inbound -Protocol UDP -LocalPort 5353 -Action Allow
New-NetFirewallRule -DisplayName "Connecto TCP" -Direction Inbound -Protocol TCP -LocalPort 8099 -Action Allow

OpenSSH not installed:

# Check if OpenSSH is available
Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'

# Install OpenSSH Client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

SSH service not running:

# Start SSH agent
Start-Service ssh-agent
Set-Service ssh-agent -StartupType Automatic

Linux

mDNS/Avahi issues:

# Check Avahi daemon
systemctl status avahi-daemon

# Restart Avahi
sudo systemctl restart avahi-daemon

# Install if missing
sudo apt install avahi-daemon  # Debian/Ubuntu
sudo dnf install avahi         # Fedora

SELinux blocking SSH:

# Check SELinux status
getenforce

# Temporarily disable (for testing)
sudo setenforce 0

# Check audit log
sudo ausearch -m avc -ts recent

Config issues

Config file corrupted

Symptoms: Commands fail with JSON parse errors

Solution:

# Find config location
connecto config path

# Reset config (backup first)
mv ~/.config/connecto/config.json ~/.config/connecto/config.json.bak

SSH config conflicts

Symptoms: SSH uses wrong key or settings

Solution:

# Check for duplicate entries
grep -n "Host <hostname>" ~/.ssh/config

# Remove duplicates, keep Connecto entry
# Or manually merge settings

Getting help

Verbose output

Most commands support verbose mode (planned feature):

connecto scan -v
connecto pair -v 0

Debug information

Collect for bug reports:

# Version
connecto --version

# Config
connecto config list
connecto config path

# SSH config (remove sensitive info)
grep -A5 "# Added by Connecto" ~/.ssh/config

# System info
uname -a  # macOS/Linux
systeminfo | findstr /B /C:"OS"  # Windows

Reporting bugs

Report issues at: github.com/andreisuslov/connecto/issues

Include:

  1. Connecto version
  2. Operating system
  3. Steps to reproduce
  4. Error messages
  5. Relevant config (sanitized)