关于 ssh-configuration
面向管理员和团队的 OpenSSH 生产环境配置技能,涵盖密钥管理、加固、堡垒机访问、隧道和故障排查,用于管理远程访问。
主要功能
- 01SSH 密钥生成与限制
- 02客户端和服务端配置
- 03加固 sshd 设置
- 04堡垒机与跳板模式
- 05端口转发与多路复用
- 06连接故障排查
适用场景
- 01保护 Linux 服务器的 SSH 访问
- 02经由堡垒机访问内网主机
- 03通过隧道连接远程服务
- 04诊断认证或连接失败
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill ssh-configuration安装后在 Claude Code 中输入/ssh-configuration确认已加载。
详细介绍
SSH 配置
用于生产环境的安全 SSH 服务端和客户端配置,包括密钥管理、强化版 sshd 设置、堡垒主机架构、隧道和多路复用。
适用场景
- 为 Linux 或 Unix 服务器设置安全的远程访问
- 强化 SSH 守护进程配置,以满足合规要求
- 配置用于访问专用网络的堡垒主机/跳板主机
- 创建用于安全端口转发的 SSH 隧道
- 为团队或自动化部署管理 SSH 密钥
- 排查连接、身份验证或性能问题
前提条件
- 本地已安装 OpenSSH 客户端(运行
ssh -V验证) - 目标服务器已安装 OpenSSH 服务端(
sshd) - 拥有服务器上的 root 或 sudo 访问权限,以修改 sshd_config
- 防火墙规则允许 TCP 端口 22(或自定义 SSH 端口)
密钥生成与管理
# Generate an Ed25519 key (recommended -- fast, secure, short)
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519
# Generate an RSA 4096-bit key (for legacy compatibility)
ssh-keygen -t rsa -b 4096 -C "[email protected]" -f ~/.ssh/id_rsa_legacy
# Generate a key with a custom comment and no passphrase (CI/CD use only)
ssh-keygen -t ed25519 -C "ci-deploy-key" -f ~/.ssh/ci_deploy -N ""
# Copy public key to a remote server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# Manually append a public key (when ssh-copy-id is unavailable)
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# List fingerprints of keys on the agent
ssh-add -l
# Start the SSH agent and add a key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Add a key with a lifetime (auto-removed after 8 hours)
ssh-add -t 28800 ~/.ssh/id_ed25519
# Remove all keys from the agent
ssh-add -D
# Convert an OpenSSH key to PEM format (for tools that need it)
ssh-keygen -p -m PEM -f ~/.ssh/id_rsa_legacy
# Show the public key fingerprint (SHA256)
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# Rotate a key: generate new, deploy, then revoke old
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "[email protected] rotated $(date +%Y-%m)"
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@server
# After verifying the new key works, remove the old public key from authorized_keys on the server
SSH 客户端配置(~/.ssh/config)
# Global defaults applied to all hosts
Host *
AddKeysToAgent yes
IdentitiesOnly yes
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
Compression yes
# Production servers via bastion
Host bastion
HostName bastion.example.com
User ops
IdentityFile ~/.ssh/id_ed25519
Port 22
Host prod-web-*
User deploy
IdentityFile ~/.ssh/id_ed25519
ProxyJump bastion
Port 22
Host prod-web-1
HostName 10.0.1.10
Host prod-web-2
HostName 10.0.1.11
# Staging accessed directly
Host staging
HostName staging.example.com
User deploy
IdentityFile ~/.ssh/id_ed25519_staging
# Database tunnel through bastion
Host db-tunnel
HostName 10.0.2.50
User dba
ProxyJump bastion
LocalForward 5432 localhost:5432
# GitHub deploy key
Host github-deploy
HostName github.com
User git
IdentityFile ~/.ssh/github_deploy_key
IdentitiesOnly yes
# Connection multiplexing for faster repeated connections
Host fast-*
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
# Create the sockets directory for multiplexing
mkdir -p ~/.ssh/sockets
chmod 700 ~/.ssh/sockets
强化版服务端配置(/etc/ssh/sshd_config)
# /etc/ssh/sshd_config -- hardened configuration
# -----------------------------------------------
# Listen on a non-default port (obscurity, not security -- combine with firewall)
Port 22
# Protocol and key exchange
Protocol 2
KexAlgorithms curve25519-sha256,[email protected],diffie-hellman-group16-sha512
Ciphers [email protected],[email protected],[email protected]
MACs [email protected],[email protected]
# Authentication
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30
# Restrict users and groups
AllowGroups ssh-users ops-team
# AllowUsers deploy admin
# Disable unused authentication methods
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
# Forwarding controls
AllowTcpForwarding yes
AllowAgentForwarding no
X11Forwarding no
PermitTunnel no
# Security hardening
ClientAliveInterval 300
ClientAliveCountMax 2
UsePAM yes
UseDNS no
PermitEmptyPasswords no
PermitUserEnvironment no
# Logging
SyslogFacility AUTH
LogLevel VERBOSE
# SFTP subsystem
Subsystem sftp /usr/lib/openssh/sftp-server -f AUTH -l INFO
# Match block: restrict deploy user to SFTP only
Match User sftponly
ForceCommand internal-sftp
ChrootDirectory /home/%u
AllowTcpForwarding no
AllowAgentForwarding no
X11Forwarding no
# Validate configuration before restarting
sshd -t
# Restart sshd to apply changes
systemctl restart sshd
# Always keep an existing session open while testing
# Open a NEW terminal to verify you can still connect before closing the old one
堡垒主机设置
# On the bastion server, restrict forwarding to internal subnets only
# /etc/ssh/sshd_config addition on bastion:
AllowTcpForwarding yes
PermitOpen 10.0.0.0/8:22 10.0.0.0/8:5432
# Disable shell access for jump-only users
Match User jump-user
PermitTTY no
ForceCommand /usr/sbin/nologin
AllowTcpForwarding yes
# Connect through the bastion from a client in one command
ssh -J [email protected] [email protected]
# Equivalent using ProxyCommand (older SSH versions)
ssh -o ProxyCommand="ssh -W %h:%p [email protected]" [email protected]
# Multi-hop: client -> bastion -> app-server -> db-server
ssh -J ops@bastion,[email protected] [email protected]
SSH 隧道
# Local port forward: access remote service on localhost
# Access remote PostgreSQL (10.0.2.50:5432) via bastion at localhost:5432
ssh -L 5432:10.0.2.50:5432 [email protected] -N
# Remote port forward: expose local service to the remote network
# Make local dev server (localhost:3000) available on server port 8080
ssh -R 8080:localhost:3000 user@server -N
# Dynamic SOCKS proxy: route all traffic through the server
ssh -D 1080 user@server -N
# Then configure browser or apps to use SOCKS5 proxy at localhost:1080
# Tunnel with a background process
ssh -fN -L 5432:10.0.2.50:5432 [email protected]
# Find and kill the tunnel later
ps aux | grep "ssh -fN" | grep -v grep
kill <pid>
# Autossh for persistent tunnels (auto-reconnects)
autossh -M 0 -f -N -L 5432:10.0.2.50:5432 [email protected] \
-o "ServerAliveInterval=30" -o "ServerAliveCountMax=3"
Agent 转发(谨慎使用)
# Enable agent forwarding for a single connection
ssh -A user@bastion
# From the bastion, your local keys are available to authenticate further
ssh [email protected] # Uses your local key via the agent
# SECURITY WARNING: Agent forwarding exposes your keys to anyone with root
# on the intermediate host. Prefer ProxyJump instead.
# Safer alternative: ProxyJump does not expose the agent
ssh -J ops@bastion [email protected]
authorized_keys 中的 SSH 密钥限制
# Restrict a key to a specific command only (backup key)
command="/usr/local/bin/run-backup.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... [email protected]
# Restrict a key to specific source IPs
from="10.0.0.0/24,192.168.1.0/24" ssh-ed25519 AAAA... [email protected]
# Read-only SFTP key with chroot
command="internal-sftp",no-port-forwarding,no-pty ssh-ed25519 AAAA... [email protected]
故障排查
| 症状 | 诊断命令 | 常见解决方法 |
|---|---|---|
| 连接被拒绝 | 在服务器上运行 ss -tlnp | grep 22 | 确保 sshd 正在运行;检查防火墙规则 |
| 权限被拒绝(publickey) | ssh -vvv user@server | 确认密钥已添加到 authorized_keys,权限为 600/700 |
| 主机密钥验证失败 | ssh-keygen -R server | 移除过期的主机密钥;验证服务器身份 |
| 连接超时 | ssh -o ConnectTimeout=5 user@server | 检查网络路径、安全组和 NACL |
| SSH 登录缓慢 | 检查 sshd_config 中的 UseDNS | 设置 UseDNS no;检查反向 DNS |
| 管道中断/会话断开 | 在配置中添加 ServerAliveInterval 60 | 在客户端和服务端配置 keepalive |
| Agent 转发无法使用 | 在堡垒主机上运行 ssh-add -l | 确保使用了 -A 标志,且 Agent 已加载密钥 |
| 隧道端口已被占用 | ss -tlnp | grep <port> | 结束现有隧道,或使用其他本地端口 |
相关技能
linux-administration-- Linux 系统管理概述user-management-- 管理通过 SSH 连接的用户systemd-services-- 将 sshd 作为 systemd 服务进行管理performance-tuning-- 调整网络以提升 SSH 性能
评论
支持 Markdown