1. 从零搞懂银河麒麟 V10 上的 SSH 到底在干什么
1.1 SSH 解决的问题比你想的更基础
刚接触银河麒麟 V10 的人,尤其是从桌面环境转过来的,往往有一个误区:觉得图形界面点点鼠标就够了,命令行是"老古董"。但只要你的机器放到机房里、放到云端、放到隔壁工位的机架上,图形界面立刻就变得不现实——服务器没接显示器,你也没法每次都插键盘。这时候 SSH 就成了唯一可靠的入口。
SSH 全称 Secure Shell,中文一般叫"安全外壳协议"。它的核心价值就一句话:在不安全的网络上,建立一条加密的、可验证身份的远程登录通道。你可以把它理解成给两台机器之间挖了一条专用隧道,隧道里的数据全部被加密打包,中间任何节点截获到的都是乱码,同时两端还要互相确认"你确实是我认识的那台机器"。
在实际运维里,SSH 承载的工作远超"远程敲命令"这一件事。文件传输靠它(scp、sftp),Git 代码推送靠它(git 的 ssh 密钥认证),端口转发靠它(本地转发、远程转发、动态转发),自动化脚本批量执行靠它(ansible 默认就是走 SSH),甚至不少数据库管理工具、IDE 的远程开发功能,底层也都是 SSH 隧道。所以在银河麒麟 V10 上把 SSH 搭好、配稳,是后续所有远程工作的地基。
1.2 银河麒麟 V10 的 SSH 现状与版本背景
银河麒麟 V10 服务器版主要基于 RHEL 8 / openEuler 这一体系,包管理器用的是 dnf(兼容 yum),服务管理用 systemctl,日志主要落在 /var/log/secure 或者通过 journalctl 查看。桌面版在部分版本上偏向 Debian 体系,命令会略有差异,用之前先用cat /etc/os-release确认一下底子,这一步很多人会跳过,结果拿着一堆 rpm 命令在 apt 环境下折腾半天。
系统默认自带的 OpenSSH 版本,在 V10 各 SP 版本上不太一样,常见的是 7.9p1、8.0p1 或者 8.2p1 这一档。这个版本应付日常远程登录完全够用,但如果你所在的环境有等保合规扫描、漏洞基线检查,可能会要求把 OpenSSH 升到更新的版本,这时候就需要考虑升级或者源码编译。这也是为什么"银河麒麟 SSH 升级"这个词会被频繁搜到的原因。
提示:先执行
ssh -V和rpm -qa | grep openssh把当前版本摸清楚,再决定是"直接装"还是"先卸后升级"。盲目卸载系统自带的 openssh 有把自己锁在门外的风险,后面会专门讲怎么规避。
1.3 哪些人必须把这一篇吃透
第一类是刚接手国产化替代项目的运维,整机、整柜都是银河麒麟 V10,需要通过 SSH 做统一纳管;第二类是开发人员,代码在本地写、跑在麒麟服务器上,需要配好密钥免密登录、配置 VSCode 的 Remote-SSH 做远程开发;第三类是学生或者自学者,手上有麒麟 V10 的虚拟机镜像,想拿它练手 Linux 运维,SSH 是最先要打通的一环;第四类是系统集成人员,要在离线环境下给客户机器装 OpenSSH,处理一堆 rpm 依赖。
注意:本文不涉及任何绕过网络安全管控的内容,所有操作都限定在你自己拥有管理权限的机器上。生产环境做任何变更前,务必先在测试机或者快照环境里验证。
2. OpenSSH 的组件构成与装前必查项
2.1 别把 OpenSSH 当成一个软件,它是一套工具箱
很多人说"装 OpenSSH",其实 OpenSSH 是一整套程序集合,安装的时候要注意分清装哪几个包。银河麒麟 V10 上常见的几个包分别是:
| 包名 | 作用 | 是否必须 |
|---|---|---|
| openssh | 元包,会拉取下面几个 | 视情况 |
| openssh-server | 服务端,提供 sshd 守护进程 | 要远程连本机就必须装 |
| openssh-clients | 客户端,提供 ssh、scp、sftp 等命令 | 需要主动连别人就装 |
| openssh-askpass | 图形化密码输入框 | 基本不用 |
| openssh-keycat | 与密钥目录配合的辅助工具 | 一般不用 |
服务器要被人远程连,openssh-server是刚需;如果你还要从这台机器去连别的机器,openssh-clients也得装。两者经常一起装。查是否已安装,用rpm -qa | grep openssh,输出里能看到具体包名和版本。还要看 sshd 可执行文件在不在,which sshd或ls -l /usr/sbin/sshd,有说明服务端已经就位。
2.2 安装前必须确认的三件事
第一件事,确认有没有其他东西占着 22 端口。ss -tlnp | grep 22或者netstat -tlnp | grep :22,如果输出里不是 sshd 而是别的进程,就得先处理冲突,否则你装了服务也起不来。
第二件事,确认防火墙和安全机制的状态。银河麒麟 V10 默认可能开着 firewalld,也可能关了;SELinux 默认多半是 enforcing。这两样都会在你"服务明明起来了但连不上"的时候成为元凶。先用systemctl status firewalld和getenforce各看一眼,心里有数。
第三件事,确认软件源可用。联网环境执行dnf repolist看仓库列表是否正常拉取;离线环境则要提前准备对应的 rpm 包。这一步能省掉后面大量"装不上"的排查时间。
2.3 在线装还是离线装,先想清楚场景
这是新手最容易选错的地方。在线环境一律优先用包管理器,因为 dnf/yum 会自动解决依赖,升级、卸载、查版本都规范。离线环境(内网、涉密、无外网)才考虑手动传 rpm 包或者搭建本地源。而源码编译一般只在两种情况下用:一是要升级到比官方源更新的版本,二是要自定义编译参数(比如特定的加密库路径)。
我个人的建议是:能用官方源就用官方源,官方源版本满足不了合规要求再考虑源码编译,且一定要保留一份原版本作为回退方案。因为源码编译升级 OpenSSH,是需要连 OpenSSL 一起考虑的,一旦编译出来的 sshd 起不来,而旧版本又被覆盖了,你可能就只能进单用户模式或者挂载镜像救援了。
3. 银河麒麟 V10 上装 OpenSSH 的三条路线(附实操命令)
3.1 路线一:官方源在线安装,最省心
联网状态下,这是首选。先刷新一下元数据,再安装:
# 刷新仓库元数据 sudo dnf makecache # 安装服务端与客户端 sudo dnf install -y openssh-server openssh-clients # 部分版本习惯用 yum,效果一样 # sudo yum install -y openssh-server openssh-clients装完之后立刻验证,别急着配:
rpm -qa | grep openssh ssh -V ls -l /etc/ssh/正常情况下 /etc/ssh/ 下应该出现sshd_config(服务端配置)、ssh_config(客户端配置)、moduli、ssh_host_*_key(主机密钥对)等文件。主机密钥是 sshd 首次启动时自动生成的,如果这些 key 文件缺失,服务会起不来,需要手动生成(后面讲)。
这里有个很多人踩过的坑:如果系统里之前装过旧版本,直接dnf install会走升级流程,可能把旧配置文件替换成 .rpmsave 或者 .rpmnew 的备份形式。装完要ls /etc/ssh/看一眼有没有sshd_config.rpmnew之类的文件,如果有,需要手动比对新旧配置,把自定义的部分合并过去,否则你的自定义配置就"消失"了。
3.2 路线二:源码编译升级,为合规或新特性
当官方源版本太旧、扫描过不了的时候,就需要源码编译。以升级到一个较新的稳定版为例,大致流程是这样,但请务必在测试环境先跑通:
# 1. 安装编译依赖 sudo dnf install -y gcc gcc-c++ make zlib-devel pam-devel \ openssl-devel rpm-build perl # 2. 备份现有配置和二进制,这是保命操作 sudo cp -r /etc/ssh /etc/ssh.bak.$(date +%F) sudo cp /usr/sbin/sshd /usr/sbin/sshd.bak.$(date +%F) # 3. 编译安装 tar -zxvf openssh-*.tar.gz cd openssh-* ./configure --prefix=/usr \ --sysconfdir=/etc/ssh \ --with-pam \ --with-zlib \ --with-ssl-dir=/usr \ --with-md5-passwords make -j$(nproc) sudo make install编译参数里几个关键项解释一下:--sysconfdir=/etc/ssh是为了让配置文件还落在系统标准位置,避免和包管理器的路径打架;--with-pam是要用系统的 PAM 认证,不然很多账号认证机制会失效;--with-zlib和--with-ssl-dir关系到压缩和加密能力,缺了之后连接会报奇怪的错。
注意:源码编译前先
systemctl stop sshd,编译安装完成后不要立刻断开当前连接。正确做法是新开一个终端窗口去测试新 sshd 能不能连上,确认没问题再关闭老窗口。我见过太多次"编译完重启 sshd 结果自己掉线且连不回去"的事故。
3.3 路线三:离线 rpm 包安装,内网环境的必修课
离线环境的核心难点是依赖链。你只下一个 openssh-server 的 rpm 是没用的,它可能依赖 openssh、openssl-libs、libcrypto 等一堆东西。稳妥做法是在一台联网的、同版本同架构的麒麟 V10 上用dnf download把依赖一并拉下来:
# 在联网同构机器上下载所有依赖包 sudo dnf install -y --downloadonly --downloaddir=/tmp/ssh_pkgs \ openssh-server openssh-clients # 打包拷到目标机 cd /tmp && tar -czvf ssh_pkgs.tar.gz ssh_pkgs/ # 目标机上安装,让 dnf 从本地目录解决依赖 sudo dnf localinstall -y /path/to/ssh_pkgs/*.rpm # 或者用 rpm 逐个装(注意顺序,先装依赖) sudo rpm -ivh --nodeps *.rpm用dnf localinstall比直接用rpm -ivh更好,因为它会自己判断依赖顺序。用rpm的时候如果报"依赖 xxxx 未安装",就是把顺序搞反了或者缺包,需要逐个补齐。
还有一种更规范的做法是搭建本地 yum 源,把下载的 rpm 放进一个目录,用createrepo生成元数据,然后写一个 .repo 文件指向本地路径。这样以后装别的包也能用,一劳永逸。命令大致是:
sudo createrepo /opt/localrepo # 写 /etc/yum.repos.d/local.repo sudo dnf clean all && sudo dnf makecache3.4 安装后的第一轮验证
无论走哪条路线,装完都要做三位验证:
第一,二进制和配置到位:/usr/sbin/sshd -t检查配置文件语法,输出为空代表语法没问题,这是个非常好用的自检命令,改完配置必跑。
第二,服务能起:sudo systemctl start sshd && sudo systemctl status sshd,看到 active (running) 才算数。
第三,端口在听:ss -tlnp | grep sshd,能看到 0.0.0.0:22 或者 :::22 说明监听正常。
4. sshd 配置文件与服务的正确打开方式
4.1 核心配置参数逐个拆
银河麒麟 V10 上服务端主配置文件是/etc/ssh/sshd_config。这个文件看起来条目很多,实际日常要动的就那么十几条。我把最常用的一批整理成表:
| 参数 | 典型取值 | 作用与说明 |
|---|---|---|
| Port | 22 | 监听端口,改非标端口能减少扫端口骚扰 |
| ListenAddress | 0.0.0.0 | 监听地址,多网卡可指定某块 |
| PermitRootLogin | prohibit-password | 是否允许 root 直接登录,建议禁密码只留密钥 |
| PasswordAuthentication | yes/no | 是否允许密码认证,安全要求高时关掉 |
| PubkeyAuthentication | yes | 密钥认证开关,通常保持开启 |
| AuthorizedKeysFile | .ssh/authorized_keys | 公钥存放路径 |
| MaxAuthTries | 3~6 | 最大认证尝试次数,防暴力破解 |
| ClientAliveInterval | 60 | 服务端每 60 秒发心跳探测客户端 |
| ClientAliveCountMax | 3 | 3 次没响应就断开会话 |
| UseDNS | no | 关掉反向 DNS 查询,能显著加快登录速度 |
| GSSAPIAuthentication | no | 关掉 GSSAPI,减少无谓的认证延迟 |
| AllowUsers | user1 user2 | 白名单,只允许指定用户登录 |
其中UseDNS no和GSSAPIAuthentication no是最值得改的两条——它们解决的是"登录要卡好几秒"的经典问题。原因在于默认配置下 sshd 会尝试对客户端 IP 做反向解析,内网 DNS 不完善时就会等到超时才继续,表现出来就是输完密码后要愣半天才进 shell。
配置修改的规范流程是:改前备份 → 改 →sshd -t验证语法 → reload 而非 restart。reload 用systemctl reload sshd,它不中断已有连接,比 restart 温和。
4.2 服务管理与开机自启
服务操作本身不难,但顺序和习惯要养好:
sudo systemctl start sshd # 启动 sudo systemctl stop sshd # 停止 sudo systemctl restart sshd # 重启(断所有连接) sudo systemctl reload sshd # 重载配置(不断连接) sudo systemctl status sshd # 查看状态 sudo systemctl enable sshd # 开机自启 sudo systemctl is-enabled sshd # 查是否已自启生产环境我强烈建议只把enable和reload用熟,restart尽量少用在远程会话里。因为一旦新配置有问题导致服务起不来,重启就是把自己关在门外的操作。改配置就用 reload,绝大部分参数改动能生效。
4.3 防火墙与 SELinux 放行
服务起来了但连不上,八成卡在这两个地方。
防火墙(firewalld)放行 SSH:
sudo firewall-cmd --permanent --add-service=ssh # 如果改了非标端口,比如 2222 sudo firewall-cmd --permanent --add-port=2222/tcp sudo firewall-cmd --reload sudo firewall-cmd --list-all--add-service=ssh比--add-port=22/tcp更推荐,因为它绑定的是服务定义而不是硬端口,语义更清晰。如果你改了端口,记得两件事都做:sshd_config 里改 Port,防火墙里放行新端口,最好再把原来的 22 从防火墙里撤掉。
SELinux 这块,一般来说 SSH 本身的策略是开箱可用的,但如果你改了非标准端口,SELinux 会拦住:
# 查看 ssh 相关端口策略 sudo semanage port -l | grep ssh # 把新端口加入允许列表 sudo semanage port -a -t ssh_port_t -p tcp 2222如果semanage命令不存在,装policycoreutils-python-utils。实在排查不出来又急着验证,可以临时setenforce 0测试,但永久关闭 SELinux 是下策,最好还是把策略配对,因为这属于安全机制,关掉等于自己拆了门锁。
5. 密钥认证与客户端连接,把免密登录彻底配通
5.1 生成密钥对,选对算法和位数
密钥认证比密码认证安全得多,因为它抗暴力破解——密钥对里私钥不出本地,服务端只存公钥,攻击者拿不到私钥就无法登录。生成命令:
# RSA 算法 4096 位,兼容性最好 ssh-keygen -t rsa -b 4096 -C "kylin-v10-admin" # 或者用更现代、更短的 ed25519 ssh-keygen -t ed25519 -C "kylin-v10-admin"生成过程中会让你指定保存路径(默认~/.ssh/id_rsa)和设置 passphrase(私钥口令)。passphrase 建议设,它相当于给私钥文件再加一层密码,即使私钥文件泄露也还有一道防线;嫌每次都输麻烦的话可以用 ssh-agent 缓存。
算法选择上,ed25519 更短更快更安全,缺点是极老的系统可能不支持;RSA 4096 兼容性最广。两个都可以,看你对接的目标环境。生成后用ls -l ~/.ssh/能看到一对文件,id_rsa是私钥(权限必须 600),id_rsa.pub是公钥(可以随便传)。
注意:私钥文件权限绝不能是 644 或更松,sshd 会直接拒绝使用权限过宽的私钥,报错通常是 "Permissions 0644 for 'xxx' are too open"。修正是
chmod 600 ~/.ssh/id_rsa,同理~/.ssh目录通常是 700。
5.2 分发公钥,三条常用路子
第一条,用ssh-copy-id,最省事:
ssh-copy-id -i ~/.ssh/id_rsa.pub user@192.168.1.100 # 非标端口加 -p ssh-copy-id -i ~/.ssh/id_rsa.pub -p 2222 user@192.168.1.100它会自动把公钥追加到目标机的~/.ssh/authorized_keys,还会顺手修好目录和文件权限。这个工具能省掉后面一堆权限排错,强烈推荐。
第二条,手动粘贴。目标机上:
mkdir -p ~/.ssh && chmod 700 ~/.ssh echo "公钥内容" >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys第三条,批量场景用循环或者 ansible。用 bash 循环的时候注意引号和转义,公钥内容里有空格。
配完测试:ssh user@192.168.1.100,如果不再要密码直接进 shell,就成了。如果还要密码,先别怀疑密钥坏了,八成是权限问题——服务端 /home/user 目录不能是 777,.ssh必须 700,authorized_keys必须 600,这三处有一个不对认证就会静默失败。
5.3 客户端配置与几个提效技巧
把常用主机的连接信息写进~/.ssh/config,一条短命令就能连上:
Host kylin-web HostName 192.168.1.100 User admin Port 2222 IdentityFile ~/.ssh/id_rsa_kylin ServerAliveInterval 60配好之后ssh kylin-web就完事。ServerAliveInterval 60这条特别实用,它让客户端每 60 秒给服务端发心跳,防止长时间空闲被网络中间设备(比如防火墙 NAT 表)掐断连接,解决的就是"挂机一会儿就断"的老问题。
常用命令再列一下,方便形成肌肉记忆:
scp -P 2222 file.tar.gz admin@192.168.1.100:/data/ # 传文件到远端 scp -P 2222 admin@192.168.1.100:/data/log.txt ./ # 从远端拉文件 sftp -P 2222 admin@192.168.1.100 # 交互式传文件 ssh -L 8080:127.0.0.1:80 admin@192.168.1.100 # 本地端口转发注意 scp 和 ssh 的端口参数不一样,ssh 用-p,scp 用-P(大写),这是很多人第一次传文件失败的原因。
6. 安全加固与连不上时的排查实录
6.1 五个必做的加固项
在公网或者大内网暴露的机器,默认配置是偏宽松的,最好收一收。我按优先级列五条。
禁用 root 密码登录。在 sshd_config 里设PermitRootLogin prohibit-password,意思是 root 只能用密钥登录,不能用密码。更进一步是no,完全禁止 root 直接登录,改用普通用户登录后sudo提权,这样审计日志还能留下操作者身份。
关闭密码认证。PasswordAuthentication no,配合密钥登录。这一条能一次性挡掉绝大多数密码爆破。前提是先把密钥配好并验证能登录,再关密码,顺序错了就悲剧了。
限制可登录用户。AllowUsers admin deploy或者AllowGroups sshusers,白名单机制。这样即使系统里有一堆服务账号,也只有指定用户能远程登录。
限制认证次数和连接数。MaxAuthTries 3、MaxSessions 5、LoginGraceTime 30,压缩暴力破解的窗口。
改非标端口。把 Port 从 22 改成比如 2222,能过滤掉大量自动化扫描,属于"降低噪音"级别的措施,不是根本解决方案但值得做。
改完对照sshd -t验证,再 reload,然后新开窗口测试,稳妥。
6.2 连接问题的分层排查法
连不上分好几种表现,别一股脑乱试,按层排查效率最高。
第一种表现:ssh: connect to host xxx port 22: Connection timed out。超时通常意味着包根本没到或者被丢,排查顺序是网络层——先ping看通不通,再telnet 192.168.1.100 22或者nc -zv 192.168.1.100 22看端口通不通。不通就查防火墙、查 sshd 是否监听、查是不是被安全设备拦了。
第二种表现:connect to host xxx port 22: Connection refused。明确拒绝说明包到了,但没进程在听这个端口。多半是 sshd 没起或者监听在别的端口,systemctl status sshd和ss -tlnp | grep sshd各看一眼。
第三种表现:反复提示Permission denied (publickey,password)。这个最需要细心。要检查的包括:用户名对不对、密码对不对、公钥是否正确追加到 authorized_keys、权限是否正确、sshd_config 里 PubkeyAuthentication 是否开着、AllowUsers 是否把该用户放行了。
第四种表现:能登录但卡几十秒。这就是前面说的 UseDNS 和 GSSAPI 问题,改配置就好。
服务端日志主要在/var/log/secure,或者用journalctl -u sshd -f实时看。客户端想要详细调试信息,加-v、-vv、-vvv,能看到认证每一步的细节,排查密钥问题尤其有用。
6.3 常见问题速查表
| 现象 | 最可能原因 | 快速处置 |
|---|---|---|
| Connection timed out | 网络不通 / 防火墙拦截 | 查 ping、查防火墙、查监听 |
| Connection refused | sshd 未启动 / 端口不符 | systemctl status sshd |
| Permission denied | 权限 / 密钥 / 白名单问题 | ssh -vvv 看细节,查日志 |
| 登录卡顿数十秒 | DNS 反查 / GSSAPI | UseDNS no、GSSAPIAuthentication no |
| 密钥登录仍要密码 | 权限过宽 / 公钥没到位 | 目录 700、文件 600 |
| 断开后进程被终止 | 会话与终端绑定 | 用 nohup 或 tmux 保持 |
| 改端口后连不上 | SELinux 未放行 | semanage port -a |
| 无外网装不了 | 依赖缺失 | 离线下载全依赖再装 |
关于"命令执行过程中退出会不会继续"这个常见疑问,答案和是否用 SSH 有关:SSH 会话退出时,如果没有特殊处理,绑定在该会话上的进程通常会收到挂断信号而终止。想让长命令继续跑,用nohup cmd &、setsid,或者更推荐上tmux/screen,随时断开随时回来看,这才是运维的正确姿势。
6.4 两个我踩过坑才记住的细节
一个细节是改端口前先放行防火墙,顺序反了就是"配置改完,服务 reload,然后自己再也连不进去"。正确顺序是:先防火墙放行新端口 → 再 SELinux 加端口 → 再 sshd_config 改 Port → reload → 新窗口测试。老端口保留一段时间,确认新端口稳定后再撤。
另一个细节是离线升级 OpenSSH 千万别只盯着 openssh 自己的包,它对 openssl-libs 的版本是有要求的。升级前先rpm -q openssl-libs看清依赖,如果目标 openssh 需要更高的 openssl 版本,就要连着 openssl 一起从离线包里升,否则装到一半会卡在依赖报错上。这种"装到一半"的状态最麻烦,因为旧的被删了、新的没配上,sshd 可能直接起不来。
真遇到 sshd 起不来的极端情况,还有救急通道:通过机房的控制台、iKVM、串口或者云平台的 VNC 进去,或者以单用户 / 救援模式启动,把备份的/usr/sbin/sshd拷回去、把sshd_config恢复成备份版本,先把服务救活再重新排查。这也是为什么每一步变更前都要cp一份备份——备份就是你的后悔药。
最后分享一个我常用的小习惯:所有对 sshd 的配置改动,我都会在文件顶部或者行尾留一行注释,写上改动日期和原因。比如# 2024-06-01 改非标端口,配合防火墙策略。隔几个月回头看别人维护的机器,有这几行注释能省下大量猜测时间,这个习惯在多人协作的麒麟项目里尤其值钱。