Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
••••••
Sichere ProgrammierungLast week in Agent Security 1: We are not-a-mused!(29.09.2026 um 02:15 Uhr)
••••••••••
Sichere ProgrammierungLast week in Agent Security 1: We are not-a-mused!(29.09.2026 um 02:15 Uhr)
••••
Intelligence View
⚡ tsecurity.de Intelligence

SSH and SCP in 2026: Configuration, Security Hardening, and Advanced Tips

SSH and SCP: What They Are and Why They Still Matter SSH (Secure Shell) is the standard protocol for encrypted remote access to Linux and Unix systems. Git over SSH, CI/CD deploy pipelines, tunneling database connections, and ad hoc…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!




SSH and SCP: What They Are and Why They Still Matter



SSH (Secure Shell) is the standard protocol for encrypted remote access to Linux and Unix systems. Git over SSH, CI/CD deploy pipelines, tunneling database connections, and ad hoc server administration all run on top of it. SCP (Secure Copy Protocol) is the companion tool for transferring files over an SSH connection. While OpenSSH has deprecated the legacy SCP protocol in favor of SFTP internals, the scp command-line interface remains widely used.



This guide covers SSH and SCP usage in 2026: modern key types, effective SSH configurations, server hardening, tunneling, and CI/CD integration. Whether you manage a handful of virtual machines or orchestrate access across a fleet of Kubernetes nodes, the fundamentals here apply.






SSH Fundamentals: Protocol and Authentication



SSH operates as a client-server protocol over TCP, defaulting to port 22. When you run ssh user@host, the following sequence occurs under the hood:





  1. TCP connection. The client opens a TCP connection to the server on port 22 (or whatever port is configured).


  2. Protocol version exchange. Both sides announce supported SSH protocol versions. Modern systems use version 2 exclusively.


  3. Key exchange (KEX). The client and server negotiate a shared session key. In OpenSSH 9.x, the default is [email protected], a hybrid algorithm combining classical X25519 elliptic-curve Diffie-Hellman with the NTRU Prime post-quantum key encapsulation mechanism. Even if a quantum computer eventually breaks X25519, the session key remains secure as long as NTRU Prime holds.


  4. Server authentication. The server presents its host key. The client checks this against its known_hosts file. If the key has changed, the client refuses to connect -- protection against man-in-the-middle attacks.


  5. User authentication. The client proves its identity using public key authentication, password, keyboard-interactive, GSSAPI (Kerberos), or certificate-based authentication.


  6. Session establishment. The server allocates a pseudo-terminal or executes a command. All traffic is encrypted with the negotiated session key.






Authentication Methods in Practice



Public key authentication is the standard for production environments. Password authentication is acceptable for initial setup but should be disabled once keys are configured.





  • Public key authentication -- The client proves possession of a private key through a cryptographic challenge-response without transmitting the key itself. The default and recommended method.


  • Password authentication -- The client sends a password over the encrypted channel. Vulnerable to brute-force attacks. Should be disabled on internet-facing servers.


  • Certificate-based authentication -- Both host and user present certificates signed by a trusted CA, eliminating the need to distribute authorized_keys and known_hosts across your infrastructure. Covered in the CI/CD section below.


  • FIDO2/WebAuthn hardware keys -- OpenSSH 8.2+ supports FIDO2 security keys (YubiKey, SoloKey, Google Titan) as SSH keys. The private key material never leaves the hardware device.






Key Management: Generating, Storing, and Rotating SSH Keys






Generating Ed25519 Keys



Ed25519 is the recommended key type for SSH in 2026. It produces compact 256-bit keys that are faster to generate and verify than RSA, with a simpler implementation and fewer opportunities for side-channel attacks. Unless a specific compatibility requirement forces RSA, use Ed25519.




# Generate an Ed25519 key pair
ssh-keygen -t ed25519 -C "[email protected]"

# If you need to specify a custom path
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "[email protected]"

# For legacy systems that require RSA, use at minimum 4096 bits
ssh-keygen -t rsa -b 4096 -C "[email protected]"






Always set a passphrase on your private key. A passphrase-protected key means that even if someone obtains the key file, they cannot use it without the passphrase. Combined with ssh-agent, you only need to type the passphrase once per session.






ssh-agent: Avoiding Passphrase Fatigue



ssh-agent is a daemon that holds your decrypted private keys in memory. Once you add a key to the agent, you can authenticate to any server that trusts that key without re-entering your passphrase.




# Start the agent (many desktop environments do this automatically)
eval "$(ssh-agent -s)"

# Add your key (will prompt for passphrase)
ssh-add ~/.ssh/id_ed25519

# List loaded keys
ssh-add -l

# Add a key with a lifetime (auto-removes after 8 hours)
ssh-add -t 8h ~/.ssh/id_ed25519

# Remove all keys from the agent
ssh-add -D






The -t flag is particularly useful for security-conscious workflows. Setting a lifetime means your keys are automatically unloaded from memory after a set period, reducing the window of exposure if your workstation is compromised while unlocked.






FIDO2 Hardware Keys



FIDO2 security keys provide the strongest form of SSH key protection. The private key is generated on the hardware device and cannot be extracted -- not by malware, not by a compromised operating system, not even by the user. OpenSSH supports two FIDO2 key types:




# Generate an Ed25519 key backed by a FIDO2 device
# -O resident stores the key handle on the device itself (discoverable credential)
ssh-keygen -t ed25519-sk -O resident -C "[email protected]"

# Generate an ECDSA key backed by a FIDO2 device (wider hardware compatibility)
ssh-keygen -t ecdsa-sk -C "[email protected]"

# Require user verification (PIN + touch) for every authentication
ssh-keygen -t ed25519-sk -O resident -O verify-required -C "[email protected]"






With -O resident, the key handle is stored on the device, so you can move between workstations by plugging in your key and running ssh-add -K. The -O verify-required option adds a PIN check on top of the physical touch, giving you two-factor authentication for every SSH connection.






Post-Quantum Considerations



The default key exchange in OpenSSH 9.x already uses a hybrid post-quantum/classical construction, protecting session confidentiality against "harvest now, decrypt later" attacks. However, authentication keys (Ed25519, RSA) are not yet post-quantum resistant. The OpenSSH project is tracking NIST post-quantum signature standards (ML-DSA, formerly CRYSTALS-Dilithium). For most organizations, the default KEX configuration provides adequate forward secrecy, and switching authentication key types can wait until post-quantum signatures are production-ready.






Key Rotation



SSH keys should be rotated periodically, especially for service accounts and deploy keys. A practical rotation process looks like this:




  1. Generate a new key pair.

  2. Add the new public key to authorized_keys on all target hosts (or issue a new certificate if using certificate-based auth).

  3. Test the new key by connecting with ssh -i ~/.ssh/id_ed25519_new user@host.

  4. Update your SSH config to point to the new key.

  5. Remove the old public key from all target hosts.

  6. Delete or archive the old private key.



For infrastructure at scale, managing authorized_keys files manually is unsustainable. SSH certificates (covered in the CI/CD section) solve this by issuing short-lived credentials from a central authority, eliminating the need to touch individual servers during rotation.






SSH Config File Mastery



The client configuration file at ~/.ssh/config lets you define host-specific settings once instead of typing long commands with multiple flags.






Basic Structure






# ~/.ssh/config

# Global defaults (apply to all connections)
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
IdentitiesOnly yes

# Production bastion host
Host bastion-prod
HostName bastion.prod.example.com
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519_prod

# Application server (accessed through bastion)
Host app-prod-*
HostName %h.internal.example.com
User deploy
ProxyJump bastion-prod
IdentityFile ~/.ssh/id_ed25519_prod

# Staging environment (different key, different user)
Host *.staging.example.com
User staging-deploy
IdentityFile ~/.ssh/id_ed25519_staging
StrictHostKeyChecking accept-new

# Personal server
Host personal
HostName 203.0.113.42
User admin
IdentityFile ~/.ssh/id_ed25519_personal






With this configuration, connecting to a production app server behind the bastion is simply:




ssh app-prod-web01






SSH resolves %h to app-prod-web01, sets the hostname to app-prod-web01.internal.example.com, and automatically tunnels through bastion-prod. No manual proxy commands, no remembering which key goes where.






ProxyJump: Modern Bastion Access



ProxyJump replaced the older ProxyCommand directive for connecting through bastion hosts. It is simpler to configure and supports chaining.




# Single jump
Host internal-server
HostName 10.0.1.50
ProxyJump bastion.example.com

# Multi-hop: client -> bastion1 -> bastion2 -> target
Host deep-internal
HostName 10.0.2.100
ProxyJump bastion1.example.com,bastion2.internal.example.com

# Command-line equivalent (no config needed)
ssh -J bastion.example.com [email protected]

# Multi-hop on the command line
ssh -J bastion1.example.com,bastion2.internal.example.com [email protected]






An important security note: ProxyJump creates a direct encrypted channel from your client to the final destination. The bastion host forwards TCP traffic but cannot see the contents of your SSH session to the target server. This is a meaningful improvement over agent forwarding, which exposes your private key to the bastion host's memory.






ControlMaster: Connection Multiplexing



SSH multiplexing allows multiple sessions to share a single TCP connection. This speeds up repeated connections (no handshake, key exchange, or authentication for subsequent sessions) and is especially valuable with Ansible, rsync, or other tools that open many short-lived SSH sessions.




# ~/.ssh/config -- Enable multiplexing globally
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600









# Create the sockets directory
mkdir -p ~/.ssh/sockets






ControlMaster auto creates a master connection if none exists, or reuses one that does. ControlPath specifies the Unix socket location (%r = user, %h = host, %p = port). ControlPersist 600 keeps the master alive for 10 minutes after the last session disconnects.




# Check the status of a multiplexed connection
ssh -O check bastion-prod

# Manually close a multiplexed connection
ssh -O exit bastion-prod









SCP Usage and Modern Alternatives



SCP copies files between hosts over SSH. Its syntax mirrors cp with the addition of user@host: prefixes for remote paths.






Basic SCP Commands






# Copy a local file to a remote server
scp ./deploy.tar.gz deploy@app-prod-web01:/opt/releases/

# Copy a remote file to local
scp deploy@app-prod-web01:/var/log/app.log ./

# Copy an entire directory recursively
scp -r ./config/ deploy@app-prod-web01:/opt/app/config/

# Copy between two remote hosts (traffic goes through your local machine)
scp deploy@host1:/data/backup.sql deploy@host2:/data/backup.sql

# Specify a custom SSH key and port
scp -i ~/.ssh/id_ed25519_prod -P 2222 ./file.txt deploy@bastion:/tmp/

# Use compression for large text files
scp -C ./large-logfile.txt deploy@host:/tmp/









Why SCP Is Deprecated (and Why It Still Works)



OpenSSH 9.0 changed SCP's default behavior: it now uses the SFTP protocol internally instead of the legacy SCP/RCP protocol. The old SCP protocol had security issues -- it relied on the remote shell to interpret filenames, which could lead to unexpected behavior with specially crafted filenames. The command-line interface (scp) remains unchanged; only the underlying transfer protocol switched to SFTP. If you encounter a legacy server that does not support SFTP, you can force the old protocol with scp -O (capital O).






rsync Over SSH: The Better Alternative



For most file transfer tasks beyond simple one-off copies, rsync over SSH is superior to SCP:




# Sync a directory to a remote host (only transfers changed files)
rsync -avz --progress -e ssh ./project/ deploy@host:/opt/project/

# Use a specific SSH key and port
rsync -avz -e "ssh -i ~/.ssh/id_ed25519_prod -p 2222" ./project/ deploy@host:/opt/project/

# Dry run -- see what would be transferred without actually doing it
rsync -avzn ./project/ deploy@host:/opt/project/

# Exclude files from the transfer
rsync -avz --exclude='*.log' --exclude='.git/' ./project/ deploy@host:/opt/project/

# Delete files on the remote that no longer exist locally (mirror)
rsync -avz --delete ./project/ deploy@host:/opt/project/






The key advantages of rsync are delta transfers (only changed portions of files are sent), the ability to resume interrupted transfers, and the --delete flag for true directory synchronization. SCP always copies entire files, making it wasteful for large directories that change incrementally.






Server Hardening: sshd_config Best Practices



A default OpenSSH server configuration is permissive by design. For any production or internet-facing server, you need to lock it down: disable everything you do not need, restrict what remains to minimum required access.








# /etc/ssh/sshd_config -- Hardened configuration for production servers

# Protocol and port
Port 2222
AddressFamily inet
ListenAddress 0.0.0.0

# Authentication
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 20
PermitEmptyPasswords no

# User and group restrictions
AllowUsers deploy monitor
DenyUsers root admin

# Session security
ClientAliveInterval 300
ClientAliveCountMax 2
MaxSessions 5
MaxStartups 10:30:60

# Forwarding restrictions
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
PermitTunnel no

# Logging
LogLevel VERBOSE
SyslogFacility AUTH

# Misc hardening
Banner /etc/ssh/banner.txt
HostbasedAuthentication no
IgnoreRhosts yes
UseDNS no






After editing sshd_config, always validate the configuration before restarting the service:




# Test configuration for syntax errors
sudo sshd -t

# Restart the SSH service (on systemd-based systems)
sudo systemctl restart sshd

# IMPORTANT: Keep your current session open and test with a new connection
# before closing it. If the config is broken, you could lock yourself out.









fail2ban: Automated Brute-Force Protection



Even with password authentication disabled, SSH brute-force attempts generate log noise and consume resources. fail2ban monitors log files and temporarily bans IP addresses that exhibit suspicious behavior.




# Install fail2ban
sudo apt install fail2ban # Debian/Ubuntu
sudo dnf install fail2ban # RHEL/Fedora

# Create a local configuration override
sudo tee /etc/fail2ban/jail.local > /dev/null << 'EOF'
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
banaction = iptables-multiport
EOF

# Start and enable fail2ban
sudo systemctl enable --now fail2ban

# Check banned IPs
sudo fail2ban-client status sshd









SSH Tunneling and Port Forwarding



SSH tunneling lets you securely access services not directly reachable from your network -- databases behind firewalls, internal web applications, admin interfaces -- by forwarding traffic through an SSH connection.






Local Port Forwarding






# Access a remote PostgreSQL database (port 5432) through an SSH tunnel
ssh -L 5432:db.internal:5432 [email protected]

# Forward multiple ports in a single command
ssh -L 5432:db.internal:5432 -L 6379:redis.internal:6379 [email protected]

# Run the tunnel in the background without opening a shell
ssh -fNL 5432:db.internal:5432 [email protected]









Remote Port Forwarding






# Expose local port 3000 (your dev server) on the remote server's port 8080
ssh -R 8080:localhost:3000 [email protected]









Dynamic Port Forwarding (SOCKS Proxy)






# Create a SOCKS5 proxy on local port 1080
ssh -D 1080 [email protected]

# Use with curl
curl --proxy socks5h://localhost:1080 http://internal-dashboard.example.com:8080

# Background version
ssh -fND 1080 [email protected]









SSH in CI/CD and Automation



Automated systems -- CI/CD pipelines, configuration management tools, deployment scripts -- need to authenticate over SSH without human interaction. This requires careful key management to avoid creating persistent, overprivileged credentials that become security liabilities.






Deploy Keys



A deploy key is an SSH key pair where the public key is added to a specific repository or server, and the private key is stored as a CI/CD secret. Best practices for deploy keys:




  • Generate one key per repository per environment (do not share keys across repos or environments).

  • Use read-only deploy keys for pull operations; only grant write access when the pipeline needs to push.

  • Store the private key in your CI/CD platform's secret management, never in the repository itself.

  • Set the command= option in authorized_keys to restrict what a deploy key can execute on the server.




# authorized_keys entry that restricts a deploy key to a specific command
command="/opt/deploy/run.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3Nz... deploy-pipeline@ci









SSH Certificates: Scalable Authentication



SSH certificates solve the scalability problem of authorized_keys: instead of adding each user's public key to every server, you set up a CA that signs user keys. Servers trust the CA, and any signed key is accepted.




# Step 1: Generate a CA key pair (do this once, guard the private key carefully)
ssh-keygen -t ed25519 -f /etc/ssh/ca_user_key -C "SSH User CA"

# Step 2: Sign a user's public key to create a certificate
ssh-keygen -s /etc/ssh/ca_user_key \
-I "[email protected]" \
-n deploy,monitor \
-V +12h \
-z 1001 \
~/.ssh/id_ed25519.pub

# Step 3: Configure the server to trust the CA
# Add to /etc/ssh/sshd_config:
# TrustedUserCAKeys /etc/ssh/ca_user_key.pub

# Step 4: Inspect a certificate
ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub






The -V +12h flag is the critical piece: it issues a certificate that expires in 12 hours. This means that even if the certificate is stolen, the window of exposure is limited.






SSH in a Kubernetes World



In a well-architected Kubernetes environment, you rarely SSH into individual nodes. You interact with workloads through kubectl exec, kubectl logs, and kubectl port-forward. But SSH has not disappeared -- it has moved to different layers of the stack.






kubectl exec vs SSH



kubectl exec provides shell access to containers through the Kubernetes API server, but it is not a full replacement for SSH:





  • kubectl exec works at the container level. You are inside the container's filesystem and namespace, not on the underlying node.


  • SSH to nodes is still needed for node-level troubleshooting: kernel issues, kubelet debugging, container runtime problems, network stack inspection, and hardware diagnostics.


  • Security model differences: kubectl exec is authorized by Kubernetes RBAC. SSH is authorized by the node's local auth configuration. These are independent systems with different audit trails.






Bastion Patterns for Kubernetes Clusters






# SSH config for a Kubernetes cluster with a bastion
Host k8s-bastion
HostName bastion.k8s.example.com
User ops
IdentityFile ~/.ssh/id_ed25519_k8s
LocalForward 6443 k8s-api.internal:6443

Host k8s-node-*
HostName %h.internal.k8s.example.com
User ops
ProxyJump k8s-bastion
IdentityFile ~/.ssh/id_ed25519_k8s









Putting It All Together: A Practical Checklist





  1. Use Ed25519 keys for all new key generation.


  2. Protect private keys with passphrases and use ssh-agent with time-limited key loading.


  3. Consider FIDO2 hardware keys for high-privilege access.


  4. Write an SSH config file. Define hosts, keys, ProxyJump chains, and multiplexing settings.


  5. Disable password authentication on all servers.


  6. Restrict SSH access with AllowUsers or AllowGroups. Disable root login.

  7. Use ProxyJump instead of agent forwarding.


  8. Deploy fail2ban on internet-facing servers.


  9. Use SSH certificates for automation. Short-lived certificates are more secure than long-lived deploy keys.


  10. Prefer rsync over SCP for file transfers.


  11. Enable connection multiplexing (ControlMaster) for hosts you connect to frequently.


  12. Keep OpenSSH updated. The post-quantum key exchange in 9.x is on by default.



SSH has been the backbone of remote system administration for nearly three decades. The ecosystem continues to evolve -- post-quantum cryptography, hardware-backed keys, certificate-based authentication, zero-trust access -- but the fundamentals remain the same. Master your config, harden your servers, manage your keys, and SSH will remain the most reliable tool in your infrastructure toolkit.

2. Cyber Threat Intelligence & Forensik

IoC Intelligence (1 Indikatoren)
203[.]0[.]113[.]42
CTI Threat Relationship Graph6 Knoten / 5 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten SSH and SCP in 2026: Configuration, Security Hardening, and Advanced Tips

Thematisch verwandte Begriffe: 2026, Configuration, Security, Hardening · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-101916 | @grpc/grpc-js implements the core functionality of gRPC purely in JavaS…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag