ssh详解
SSH(Secure Shell)是一种加密网络协议,用于在不安全的网络(如互联网)上安全地进行远程登录、命令执行、文件传输等操作。它取代了早期不安全的明文协议(如 Telnet、FTP、rlogin),是系统管理员、开发者和IT运维人员必备的核心工具。
一、核心功能与用途
- 安全远程登录: 登录到远程服务器执行命令(替代 Telnet)。
- 安全文件传输:
scp(Secure Copy):基于 SSH 的命令行文件传输工具。sftp(SSH File Transfer Protocol):提供类似 FTP 的交互式文件传输接口。rsync over SSH:高效的文件同步工具,利用 SSH 加密传输。
- 端口转发 / 隧道:
- 本地端口转发: 将本地端口映射到远程服务器的端口(访问本地端口即访问远程服务)。
- 远程端口转发: 将远程服务器端口映射到本地端口(让远程访问本地服务)。
- 动态端口转发: 创建 SOCKS 代理,将所有流量通过 SSH 服务器转发。
- 安全执行远程命令: 无需登录交互式 Shell,直接在远程执行单条命令。
- 安全 X11 转发: 在本地显示运行在远程服务器上的图形界面程序(需要 X Server)。
- 代理转发: 允许通过跳板机(Bastion Host/Jump Server)连接到无法直接访问的内网服务器。
二、核心组件
- SSH 客户端: 发起连接请求的程序(如
ssh,scp,sftp, PuTTY, SecureCRT, MobaXterm)。 - SSH 服务器: 接收连接请求并处理的后台程序(通常称为
sshd)。 - 密钥对:
- 公钥: 放置在远程服务器上(
~/.ssh/authorized_keys)。 - 私钥: 严格保管在本地客户端(
~/.ssh/id_rsa,~/.ssh/id_ed25519等),通常设置权限600。
- 公钥: 放置在远程服务器上(
三、工作原理(SSHv2)
- TCP 连接建立: 客户端连接到服务器的 22 端口(默认)。
- 协议版本协商: 客户端和服务端协商使用 SSH 协议版本(强烈推荐使用 SSH-2)。
- 密钥交换: 使用 Diffie-Hellman 等算法协商出一个临时的会话密钥。此过程确保即使攻击者截获了交换信息,也无法计算出会话密钥(前向保密)。
- 服务端认证:
- 服务端向客户端发送其 主机密钥(公钥)。
- 客户端检查此密钥是否在已知信任列表(
~/.ssh/known_hosts)中。 - 如果是首次连接,客户端会提示用户验证并确认接受该主机密钥(防止中间人攻击)。
- 用户认证:
- 密码认证: 用户输入密码,密码通过加密通道传输到服务端验证。
- 公钥认证(推荐):
- 客户端告知服务端其想使用的公钥 ID。
- 服务端检查该公钥是否在用户的
authorized_keys文件中。 - 服务端生成一个随机数,用该公钥加密,发送给客户端。
- 客户端用对应的私钥解密,将结果发回服务端。
- 服务端验证结果正确则认证成功。
- 其他方式:键盘交互认证(用于一次性密码)、基于主机的认证(较少用)。
- 加密通道建立: 使用协商好的会话密钥和对称加密算法(如 AES, ChaCha20)加密后续所有通信。
- 数据完整性: 使用 HMAC(基于哈希的消息认证码)算法(如 SHA-256)保证传输的数据未被篡改。
- 会话复用: 通过
ControlMaster和ControlPath配置,复用已建立的连接,避免重复认证开销。
四、基本用法(命令行客户端)
-
基本远程登录:
ssh username@hostname_or_ip # 例如:ssh alice@server.example.com- 首次连接会提示确认主机密钥指纹。
- 然后提示输入用户
alice在server.example.com上的密码(如果未配置公钥)。
-
指定端口: 如果服务端 SSH 端口不是 22:
ssh -p 2222 username@hostname -
使用公钥登录:
- 在本地生成密钥对:
ssh-keygen -t ed25519(推荐) 或ssh-keygen -t rsa -b 4096。 - 将公钥 (
~/.ssh/id_ed25519.pub) 内容追加到远程服务器的用户家目录下的~/.ssh/authorized_keys文件中。- 手动复制粘贴。
- 使用
ssh-copy-id工具自动完成:
ssh-copy-id -i ~/.ssh/id_ed25519.pub username@hostname - 登录时不再需要输入密码(除非私钥设置了密码短语)。
- 在本地生成密钥对:
-
执行远程命令:
ssh username@hostname 'command_to_run' # 例如:ssh alice@server.example.com 'ls -l /tmp' -
文件传输:
- scp (复制文件):
# 复制本地文件到远程 scp /path/to/local/file username@hostname:/path/to/remote/directory # 复制远程文件到本地 scp username@hostname:/path/to/remote/file /path/to/local/directory # 指定端口:scp -P 2222 ... # 递归复制目录:scp -r ... - sftp (交互式文件传输):
sftp username@hostname sftp> put localfile [remotepath] # 上传 sftp> get remotefile [localpath] # 下载 sftp> ls # 列出远程目录 sftp> lls # 列出本地目录 sftp> cd, lcd, mkdir, rmdir, ... # 类似 FTP 命令 sftp> exit / bye
- scp (复制文件):
五、端口转发(隧道)
-
本地端口转发: 将本地端口绑定到远程服务的端口。
- 场景: 访问远程服务器内部网络的服务(如数据库)。
- 命令:
ssh -L [bind_address:]local_port:remote_host:remote_port username@ssh_server - 示例: 将本地
3307端口映射到远程服务器内网主机db.internal的3306(MySQL) 端口:ssh -L 3307:db.internal:3306 alice@jumpserver.example.com- 访问本地的
127.0.0.1:3307即访问jumpserver能访问到的db.internal:3306。
- 访问本地的
-
远程端口转发: 将远程服务器端口绑定到本地服务的端口。
- 场景: 将本地开发环境暴露给外部访问(临时演示)、让内网服务被外网访问。
- 命令:
ssh -R [bind_address:]remote_port:local_host:local_port username@ssh_server - 示例: 将远程服务器
jumpserver的8080端口映射到本地127.0.0.1:3000(本地 Web 服务):ssh -R 8080:localhost:3000 alice@jumpserver.example.com- 访问
jumpserver.example.com:8080即访问本地的localhost:3000。
- 访问
- 注意: 默认远程服务器只监听
127.0.0.1(localhost),如需外部访问,需在服务端sshd_config中设置GatewayPorts yes并重启sshd。
-
动态端口转发: 创建 SOCKS 代理服务器。
- 场景: 所有应用程序流量通过 SSH 服务器转发,绕过本地网络限制或加密流量。
- 命令:
ssh -D [bind_address:]local_socks_port username@ssh_server - 示例: 在本地
1080端口启动 SOCKS5 代理:ssh -D 1080 alice@proxy.example.com- 在浏览器或系统网络设置中配置代理为
SOCKS5,地址127.0.0.1,端口1080,则所有流量通过proxy.example.com加密转发。
- 在浏览器或系统网络设置中配置代理为
六、配置文件
-
客户端全局配置:
/etc/ssh/ssh_config -
客户端用户配置:
~/.ssh/config(非常常用,简化连接)Host myserver # 别名 HostName server.example.com # 真实主机名/IP User alice # 登录用户名 Port 2222 # 端口 IdentityFile ~/.ssh/id_ed25519_myserver # 指定私钥 # 其他选项: ForwardAgent, LocalForward, Compression, ServerAliveInterval... Host internal-* ProxyJump jumpserver.example.com # 通过跳板机连接 User bob Host internal-db HostName 192.168.1.100- 使用:
ssh myserver,ssh internal-db
- 使用:
-
服务端配置:
/etc/ssh/sshd_config(修改后需重启sshd服务)- 关键配置项:
Port:监听端口。PermitRootLogin:是否允许 root 登录 (推荐no或prohibit-password)。PasswordAuthentication:是否允许密码认证 (推荐no,强制使用公钥)。PubkeyAuthentication:是否启用公钥认证 (推荐yes)。AllowUsers/AllowGroups:限制可登录的用户/组。X11Forwarding:是否允许 X11 转发。PermitEmptyPasswords:是否允许空密码 (必须no)。ClientAliveInterval/ClientAliveCountMax:保持连接活跃设置。
- 关键配置项:
七、最佳安全实践
- 强制使用 SSHv2: 禁用过时且不安全的 SSHv1。
- 禁用密码登录: 仅允许公钥认证。这是防止暴力破解密码的最有效手段 (
PasswordAuthentication no)。 - 禁用 Root 直接登录: 使用普通用户登录后
sudo(PermitRootLogin no或prohibit-password)。 - 使用强密码/密码短语: 保护私钥和用户账户。
- 限制访问来源: 使用防火墙 (iptables, ufw, firewalld) 限制 SSH 端口访问 IP。
- 更改默认端口: 减少自动化扫描攻击 (但非绝对安全,需结合其他措施)。
- 使用非标准用户: 避免使用
admin,administrator,test等常见用户名。 - 保持软件更新: 及时更新 SSH 客户端和服务端 (
openssh-server,openssh-client)。 - 监控日志: 定期检查
/var/log/auth.log或/var/log/secure中的 SSH 登录尝试。 - 使用 Fail2ban: 自动封禁多次登录失败的 IP 地址。
- 谨慎使用代理转发 (
ForwardAgent): 仅在完全信任目标服务器时使用。
八、高级技巧/应用场景
ssh-agent和ssh-add: 管理私钥密码短语,避免多次输入。- 多因素认证 (MFA): 结合 Google Authenticator 等为 SSH 登录增加一层保护。
- Git over SSH: Git 远程仓库使用 SSH URL (
git@github.com:user/repo.git)。 sshfs: 使用 FUSE 将远程目录挂载到本地文件系统。- 远程调试/服务管理:
ssh -t myserver 'sudo systemctl status nginx; journalctl -u nginx -f' - 连接调试: 使用
-v(verbose) 参数诊断连接问题:ssh -vvv username@hostname
总结
SSH 是安全远程管理的基石。理解其核心原理(加密、认证、隧道)、熟练掌握基本命令(登录、scp/sftp、端口转发)和配置文件 (~/.ssh/config, /etc/ssh/sshd_config),并遵循严格的安全实践(禁用密码、禁用root登录、更新、监控),是高效、安全使用 SSH 的关键。它的灵活性和强大功能使其成为连接和管理远程系统的首选工具。

浙公网安备 33010602011771号