How to Change the SSH Port

Blog image

AI summary

Overview: The article is a practical guide for safely relocating the SSH listening port on Linux servers. It explains differences between service-managed and systemd socket-activated SSH, and outlines the required changes to SSH configuration, systemd socket units, host firewalls, SELinux port labeling, and cloud-provider network controls. It also summarizes validation steps, troubleshooting approaches, client-side configuration updates, and complementary SSH hardening measures.

Core message: Changing SSH to a nonstandard high port can markedly reduce automated attack noise but is not a substitute for strong authentication and access controls. Success depends on following a strict, test-first sequence—leave an active session open, open the new port in all relevant firewalls, validate configuration, restart or reload the appropriate unit, and confirm access from an independent connection—and pairing the port change with key-based auth, intrusion-prevention, and restrictive access policies.

Learn how to change the default SSH port on Linux safely without locking yourself out. This expert guide covers Ubuntu, Debian, Rocky Linux, AlmaLinux, firewalls, SELinux, and modern systemd socket activation, including Ubuntu 24.04 and Debian 13 configurations. Includes troubleshooting tips, security hardening recommendations, and real-world examples for production servers.

How to Change the SSH Port

Audience: Linux system administrators, DevOps engineers, and infrastructure engineers managing internet-facing servers.
Applies to: Ubuntu 22.04/24.04, Debian 12/13, Rocky Linux 8/9, AlmaLinux 8/9, RHEL 8/9, and any systemd-based distribution.

Overview

SSH listens on TCP port 22 by default, a well-known fact that makes it a perpetual target for automated credential-stuffing, dictionary attacks, and opportunistic vulnerability scanners. Relocating SSH to a non-standard high port is a low-effort, high-signal-to-noise hardening measure: it eliminates the overwhelming majority of automated noise without meaningfully impeding legitimate access.

This is a defense-in-depth measure, not a security boundary. A determined attacker running a full port scan (nmap -p-) will discover the service regardless. This technique is most valuable for:

  • Drastically reducing brute-force log pollution
  • Lowering exposure to exploit attempts targeting zero-days in specific sshd versions
  • Providing a secondary layer of obscurity alongside proper cryptographic and authentication hardening

It must be combined with key-based authentication, Fail2Ban or sshguard, disabled password authentication, and ideally IP allowlisting or MFA for administrative access.

Critical Rule Before You Begin

Never close your existing SSH session until the new port is fully validated from a second, independent connection.

A single misstep, a firewall rule applied before an sshd restart, a typo in sshd_config, a missed SELinux label can lock you out of a remote machine. The recovery path from a locked-out VPS varies from painful (console access via provider panel) to catastrophic (no out-of-band access).

Follow this order strictly:

  1. Keep the current session open
  2. Open the new port in the firewall first
  3. Apply the sshd configuration change
  4. Validate configuration syntax (sshd -t)
  5. Restart or reload the SSH service/socket
  6. Test from a second terminal
  7. Remove the old port 22 rule only after the new session succeeds

Step 1: Choosing a Port

Select a port in the range 1024–65535. Ports below 1024 are privileged and reserved; ports in the 49152–65535 range are designated ephemeral by IANA and may conflict with transient client connections on some systems.

Practical guidance:

  • Avoid ports already claimed by well-known services (3306/MySQL, 5432/Postgres, 6379/Redis, 8080/HTTP-alt, etc.)
  • Check whether your target port is already in use locally before committing:

ss -tulpn | grep ‘:2222’

  • Avoid port 2222 itself it is widely known as the “alternate SSH port” and included in many scan profiles.
  • A port in the 10000–50000 range that has no associated IANA service is a reasonable choice.

Step 2: Determine How SSH Is Managed on Your System

This is the most commonly skipped step, and it causes the most confusion. Modern Linux distributions have diverged on how they manage the SSH listening socket:

Traditional Model (ssh.service)

sshd starts at boot, binds to the configured port directly, and manages its own socket lifecycle. The port is determined exclusively by /etc/ssh/sshd_config.

Systemd Socket Activation Model (ssh.socket)

systemd owns and opens the listening socket. sshd is launched on-demand when a connection arrives. The listening port is controlled by the socket unit, not by sshd_config. Modifying sshd_config alone has no effect on which port the system actually accepts connections on.

Ubuntu 22.10+ and Debian 13 have moved toward socket activation by default. Ubuntu 24.04 uses it by default on new installs.

Check which model is active on your system:

systemctl is-active ssh.service

systemctl is-active ssh.socket

Possible states:

ssh.servicessh.socketModel
activeinactiveTraditional
inactiveactiveSocket activation
activeactiveTransitional/mixed — requires careful handling

Step 3: Modify the SSH Configuration

Regardless of which model is active, updating sshd_config is good practice — it ensures consistency if the service model ever changes, and it is required for traditional setups.

sudo nano /etc/ssh/sshd_config

Locate the Port directive. It is often commented out, which causes sshd to default to port 22:

#Port 22

Change it to your chosen port:

Port 2222

If you want SSH to listen on multiple ports simultaneously during a migration window (highly recommended for production systems), you can specify multiple Port directives:

Port 22

Port 2222

This lets you validate the new port before removing the old one, without needing two separate sshd processes.

Harden While You’re in the File

Since you have sshd_config open, apply the following hardening settings at the same time:

# Disable direct root login

PermitRootLogin no

# Disable password-based authentication (requires pre-deployed keys)

PasswordAuthentication no

ChallengeResponseAuthentication no

# Restrict which users can authenticate

AllowUsers deployer adminuser

# Reduce authentication timeout and retry limits

LoginGraceTime 30

MaxAuthTries 3

MaxSessions 5

# Disable unused authentication methods

KerberosAuthentication no

GSSAPIAuthentication no

# Restrict to strong key exchange, ciphers, and MACs (modern clients only)

KexAlgorithms curve25519-sha256,[email protected]

Ciphers [email protected],[email protected],[email protected]

MACs [email protected],[email protected]

Note on crypto policy: On RHEL-based systems using system-wide crypto policies (update-crypto-policies), manual cipher/kex overrides in sshd_config may conflict. Either configure via the policy subsystem or set CRYPTO_POLICY= in /etc/sysconfig/sshd to opt out.

Step 4: Validate the Configuration

Before touching any service, validate the configuration syntax. This catches errors that would otherwise cause sshd to fail to start, locking you out:

sudo sshd -t

No output means the configuration is syntactically valid. If errors are reported, fix them before proceeding.

For a more detailed parse of the effective configuration (including defaults and includes):

sudo sshd -T | grep -E ‘^(port|permitrootlogin|passwordauthentication|allowusers)’

Step 5: Configure the Firewall

The firewall must be updated before restarting SSH. Opening the new port first ensures you have a path in via the new port, even if something goes wrong during the service restart.

UFW (Ubuntu/Debian)

# Open the new port

sudo ufw allow 2222/tcp comment ‘SSH custom port’

# Verify it is listed

sudo ufw status verbose

# Only remove port 22 after successful validation

sudo ufw delete allow 22/tcp

sudo ufw delete allow OpenSSH

ufw rules are persistent across reboots by default. No additional step needed.

firewalld (Rocky Linux, AlmaLinux, RHEL, Fedora)

# Add the new port permanently

sudo firewall-cmd –permanent –add-port=2222/tcp

# Apply the permanent configuration to the running state

sudo firewall-cmd –reload

# Verify

sudo firewall-cmd –list-ports

# Remove port 22 after validation

sudo firewall-cmd –permanent –remove-service=ssh

sudo firewall-cmd –reload

A common mistake is running firewall-cmd without –permanent. This opens the port in the running configuration only; it is lost on the next reboot or firewall-cmd –reload.

iptables (Legacy Systems)

sudo iptables -A INPUT -p tcp –dport 2222 -j ACCEPT

sudo iptables -D INPUT -p tcp –dport 22 -j ACCEPT

# Persist (Debian/Ubuntu)

sudo iptables-save > /etc/iptables/rules.v4

# Persist (RHEL-based)

sudo service iptables save

Step 6: Configure SELinux (RHEL-Based Systems Only)

On systems with SELinux enforcing, the SSH daemon is constrained by the ssh_port_t type label. Even with a correct sshd_config and an open firewall rule, sshd will silently fail to bind to an unlabeled port it will either fall back to port 22 or refuse to start.

This step is mandatory on Rocky Linux, AlmaLinux, RHEL, CentOS Stream, and Fedora.

Check Whether SELinux Is Enforcing

getenforce

If the output is Enforcing, proceed. If Permissive or Disabled, this step is not required (but permissive mode still logs denials — check with ausearch -m avc).

Label the New Port

sudo semanage port -a -t ssh_port_t -p tcp 2222

If semanage is not available:

sudo dnf install -y policycoreutils-python-utils

Verify the Label

sudo semanage port -l | grep ssh_port_t

Expected output:

ssh_port_t    tcp    2222, 22

Verify No Denials After Restart

sudo ausearch -m avc -ts recent | grep sshd

If you see AVC denials related to the new port, the label was not applied correctly.

Step 7: Apply the Change — Traditional Mode

For systems running ssh.service (no socket activation):

# Reload configuration without dropping connections (preferred for production)

sudo systemctl reload ssh        # Debian/Ubuntu

sudo systemctl reload sshd       # RHEL-based

# Or do a full restart if reload is not supported

sudo systemctl restart ssh

sudo systemctl restart sshd

# Check service status

sudo systemctl status ssh

Confirm the port is now listening:

ss -lntp | grep sshd

Step 8: Apply the Change — Socket Activation Mode

On systems where ssh.socket is active (Ubuntu 22.10+, Ubuntu 24.04, Debian 13), sshd_config changes to Port do not affect the actual listening port. systemd owns the socket and passes it to sshd via socket activation. You must configure the socket unit directly.

Create a Systemd Override

sudo systemctl edit ssh.socket

This opens a drop-in override file at /etc/systemd/system/ssh.socket.d/override.conf. Add:

[Socket]

ListenStream=

ListenStream=2222

The first ListenStream= (empty) clears the inherited default value. The second sets the new port. Without the empty line, the new port is added to the existing ones rather than replacing them.

For dual-stack systems (both IPv4 and IPv6):

[Socket]

ListenStream=

ListenStream=0.0.0.0:2222

ListenStream=[::]:2222

Reload and Restart the Socket

sudo systemctl daemon-reload

sudo systemctl restart ssh.socket

Verify the Socket Is Listening

sudo systemctl status ssh.socket

ss -lntp | grep 2222

Handling Mixed ssh.service + ssh.socket

Some systems in a partially-migrated state may have both active simultaneously. The socket unit takes precedence for incoming connections, but the service may still hold port 22 open independently. If you see SSH listening on both ports from different processes:

# Identify what owns each port

ss -lntpe | grep -E ‘(:22|:2222)’

# Disable and stop the legacy service unit if socket activation is the target

sudo systemctl disable –now ssh.service

Step 9: Validate From a Second Terminal

Do not close your original session yet. Open a new terminal window and test:

ssh -p 2222 -v user@server-ip

The -v flag enables verbose output. If the connection fails, the output will identify whether the problem is network-level (connection refused/timeout), authentication, or host key verification.

Confirm no unexpected ports remain open:

ss -lntp | grep -E ‘(sshd|ssh)’

At this point you may remove the port 22 firewall rule (see Step 5) and optionally remove the Port 22 line from sshd_config if you had it set for dual-port testing.

Troubleshooting

SSH Still Listening on Port 22

Possible causes:

  • ssh.socket is active and was not reconfigured (the ListenStream override was not applied)
  • Both ssh.service and ssh.socket are running; the service is binding port 22 independently
  • A stale sshd process is still running (check with ps aux | grep sshd)
  • The systemctl daemon-reload step was skipped after editing the socket unit

Diagnostic commands:

# What process owns port 22?

ss -lntpe | grep ‘:22’

# Is the socket unit using the override?

systemctl cat ssh.socket

# Are there any lingering processes?

ps aux | grep ‘[s]shd’

Connection Refused on New Port

Work through the stack from bottom to top:

# 1. Is sshd actually listening?

ss -lntp | grep 2222

# 2. Is the firewall passing the traffic?

sudo ufw status          # or

sudo firewall-cmd –list-all

# 3. Is SELinux blocking the bind? (RHEL-based)

sudo ausearch -m avc -ts recent | grep sshd

# 4. What does the SSH daemon log show?

journalctl -u ssh -xe –since “5 minutes ago”

journalctl -u ssh.socket -xe –since “5 minutes ago”

Cloud Provider / External Firewalls

The OS-level firewall is only one layer. Many VPS and cloud providers operate external security groups or network ACLs that are entirely independent of the guest OS:

ProviderConsole Location
AWSEC2 → Security Groups
GCPVPC → Firewall Rules
AzureNetwork Security Groups
HetznerCloud Firewall (project level)
DigitalOceanNetworking → Firewalls
Linode/AkamaiCloud Firewalls

You must open the new SSH port in the provider’s control plane, in addition to the OS firewall, before the connection can reach sshd.

Updating Your SSH Client Configuration

To avoid typing -p 2222 on every connection, update ~/.ssh/config on your client machines:

Host myserver

    HostName 203.0.113.10

    User adminuser

    Port 2222

    IdentityFile ~/.ssh/id_ed25519

Pre-Removal Checklist

Before removing port 22 from both the firewall and sshd_config, verify every item:

  • [ ] New port accepts connections from a second terminal
  • [ ] ss -lntp confirms SSH is only listening on the new port
  • [ ] OS-level firewall rule for port 22 removed
  • [ ] Cloud/provider-level firewall updated
  • [ ] SELinux labels verified (RHEL-based)
  • [ ] sshd -t passes with the final configuration
  • [ ] ~/.ssh/config on all client machines updated
  • [ ] Runbooks, monitoring alerts, and bastion host configs updated to reference the new port
  • [ ] Any CI/CD pipelines or deployment tools updated

Additional SSH Hardening Recommendations

Changing the port is one layer. A properly hardened sshd_config should also include:

# Never permit root login directly

PermitRootLogin no

# Disable all password-based authentication

PasswordAuthentication no

ChallengeResponseAuthentication no

UsePAM yes

# Restrict to specific users or groups

AllowUsers deployer

# AllowGroups sshusers

# Short grace period for unauthenticated connections

LoginGraceTime 30

# Limit retry attempts to reduce brute-force window

MaxAuthTries 3

# Prevent X11 and agent forwarding unless explicitly needed

X11Forwarding no

AllowAgentForwarding no

# Disable TCP forwarding if not required

AllowTcpForwarding no

# Log verbosely for audit trail

LogLevel VERBOSE

# Drop idle sessions after inactivity

ClientAliveInterval 300

ClientAliveCountMax 2

# Restrict SSH protocol features to reduce attack surface

PermitEmptyPasswords no

PermitUserEnvironment no

Pair this with:

  • Fail2Ban with aggressive jails on the new port
  • Port knocking (knockd) or Single Packet Authorization (fwknop) for maximum obscurity
  • WireGuard or a VPN as the primary administrative access path, with SSH only exposed on the VPN interface
  • Ed25519 keys for all authentication (smaller, faster, and based on better math than RSA-2048)
  • Key rotation policy and revocation via authorized_keys management or a secrets manager

Secure Your Infrastructure with Advanced Hosting

Whether you manage a single VPS or an enterprise infrastructure, secure remote access is foundational to Linux server security.

Advanced Hosting provides:

  • High-performance VPS and dedicated servers
  • Enterprise-grade DDoS protection
  • Advanced networking and firewall options
  • Bare metal infrastructure
  • Managed hosting solutions
  • Low-latency global deployments

If you need reliable infrastructure for production Linux workloads, container platforms, virtualization, or secure SSH administration at scale, explore the solutions available at Advanced Hosting.

Does changing the SSH port actually improve security?

Changing the port does not harden SSH cryptographically, but it significantly reduces exposure to automated scanning and low-effort brute-force attacks targeting port 22. Most internet-wide attacks are opportunistic and focus on default configurations.

However, moving SSH to another port should always be combined with:

  • SSH key authentication
  • Fail2Ban or rate limiting
  • Disabling password authentication
  • Restricting login users
  • IP allowlists where possible

Think of it as reducing attack surface noise rather than replacing real authentication security.

What is the best port number for SSH?

There is no universally “best” SSH port.

Recommended practice:

  • Use a high, unassigned TCP port
  • Stay within 1024–65535
  • Avoid ports used by databases, web services, or orchestration systems

Good examples:

  • 2222
  • 22222
  • 50222

Avoid:

  • Common alternative SSH ports heavily scanned by bots
  • Ports already used by Docker, Kubernetes, game servers, or monitoring systems

Can changing the SSH port affect automation tools?

Yes. Any automation or orchestration platform that connects through SSH must be updated after the port change.

Common affected systems:

  • Ansible
  • Terraform provisioners
  • Jenkins agents
  • Git deployment hooks
  • Backup systems
  • Monitoring agents
  • CI/CD pipelines

For Ansible, specify the port in inventory:

ansible_host=server_ip ansible_port=2222

Should I completely disable port 22 afterward?

In most production environments, yes, after verifying the new port works correctly.

Leaving both ports active:

  • increases exposure
  • creates configuration ambiguity
  • weakens the purpose of the migration

However, temporary dual-port operation can be useful during staged migrations or infrastructure automation rollouts.

Can I run SSH on multiple ports simultaneously?

Yes.

OpenSSH supports multiple Port directives:

Port 22

Port 2222

This is commonly used during:

  • migration periods
  • phased firewall updates
  • temporary compatibility windows

Be aware that every exposed port increases the visible attack surface.

Does changing the SSH port affect SCP or SFTP?

Yes. SCP and SFTP both rely on SSH transport.

You must explicitly specify the custom port.

SCP example:

scp -P 2222 file.txt user@server:/tmp

SFTP example:

sftp -P 2222 user@server

Note that SCP uses uppercase -P, while SSH uses lowercase -p.

Related articles

1How to Create an LVM Partition in Linux

How to Create an LVM Partition in Linux

 Learn how to create an LVM partition in Linux using industry-standard tools and best practices for modern server environments. This step-by-step guide covers physical volumes, volume groups, logical volumes, filesystem creation, mounting, live storage expansion, and advanced LVM management techniques for Ubuntu, RHEL, VPS, and enterprise Linux systems. Whether you are deploying scalable storage for […]
1How to Upgrade a Server From Debian 10 (Buster) to Debian 12 (Bookworm)

How to Upgrade a Server From Debian 10 (Buster) to Debian 12 (Bookworm)

How to Upgrade a Server From Debian 10 (Buster) to Debian 12 (Bookworm) This guide covers the complete migration path from Debian 10 (Buster) to Debian 12 (Bookworm) via the mandatory intermediate release, Debian 11 (Bullseye). It addresses pre-upgrade auditing, backup and rollback architecture, the staged upgrade procedure, compatibility considerations for Bookworm, and post-upgrade verification. […]
1How to Fix the “nf_conntrack: table full” Error on Linux Servers

How to Fix the “nf_conntrack: table full” Error on Linux Servers

Experiencing nf_conntrack: table full, dropping packet errors? This expert guide explains how Linux connection tracking works, why conntrack tables overflow, and how to optimize Netfilter for high-traffic environments.  How to Fix the “nf_conntrack: table full” Error on Linux Servers When a Linux server begins logging messages such as: nf_conntrack: table full, dropping packet It indicates […]
1Digital Rights Management for Video Streaming Platforms

Digital Rights Management for Video Streaming Platforms

Digital Rights Management is often treated as a security checkbox: enable DRM, protect content, move on. In real-world video streaming, that assumption breaks quickly. DRM sits directly on the playback path, affects startup time, scales with concurrency, and fails in ways that look like video delivery problems, not security issues.
1How to Provision a Server Properly | Step-by-Step Infrastructure Guide

How to Provision a Server Properly | Step-by-Step Infrastructure Guide

Provisioning a server is often treated as a quick, automated step: click order, wait for Active, and move on. In reality, most infrastructure problems begin right there, when provisioning is mistaken for readiness.
1How to Point a Domain to a Dedicated Server IP (Step-by-Step)

How to Point a Domain to a Dedicated Server IP (Step-by-Step)

How to Point Your Domain Name to a Dedicated Server’s IP Address? Before changing any DNS records, it’s important to clearly understand what problem you are solving.At Advanced Hosting, most DNS-related incidents we see are caused not by mistakes in records, but by incorrect expectations about what DNS is supposed to do. This article removes […]