news 2026/10/8 20:30:08

Ubuntu 20.04离线安装sshd实操:依赖收集、dpkg部署与排错指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 20.04离线安装sshd实操:依赖收集、dpkg部署与排错指南

简介:面向Ubuntu 20.04 LTS桌面版的SSH服务离线安装包,专为无法连接外网的服务器或内网环境准备。桌面版默认不预装sshd,远程管理、文件传输和自动化运维都会受限,该资源可直接解决离线环境下openssh-server的部署难题。压缩包共4个文件,包含3个deb安装包和1个sh安装脚本,整体仅1.05MB,小巧实用。其中openssh-server、openssh-client与openssh-sftp-server分别对应核心服务、客户端连接和SFTP传输组件,sh脚本用于快速执行安装与配置,降低手动输入命令的出错概率。目前已有1251人学习下载,适合系统管理员、运维工程师以及需要在无网络环境中搭建远程管理通道的Ubuntu用户。通过该包可一次性完成SSH服务安装、依赖处理与启动配置,省去逐一下载依赖包和排查依赖关系的麻烦,显著提升离线部署效率,是内网环境初始化与批量交付时的实用工具。

1. Ubuntu 20.04的sshd离线安装包:内网机器装上ssh的第一步

生产内网里刚拆箱的Ubuntu 20.04服务器,很多机房出于安全要求不允许它连外网。这时候想在机器上开ssh服务,apt install openssh-server根本走不通——源不通、DNS解析失败,甚至连apt update都会超时。与其花一下午折腾换源,不如直接用离线安装包方案:在另一台同版本联网机器上用apt把openssh-server及其依赖全部拉成.deb文件,拷入内网后用dpkg安装。我会按“收集依赖包→拷贝传输→dpkg落库→配置sshd→排坑验证”的顺序,把整个流程写透。这个方案适合机房部署、等保整改、临时应急三类场景,新手照着做能一次装好,熟手也能看到依赖计算和密钥管理的边界。

2. 在联网机器上收集sshd离线包:两条路线怎么选

2.1 路线A:apt-get --download-only 拉依赖,省心但要注意补包

openssh-server不是自包含的包,它依赖openssh-client、openssh-sftp-server,还有libssl1.1、libpam0g、libkrb5-3、zlib1g这一串运行库。如果只下载主包就拷贝到内网机器,dpkg会在安装时立刻报dependency problems。所以离线安装的第一步,是把整套依赖闭环收集齐。这一步也是整个流程里最容易翻车的地方。方法分两条路线:一条用apt的下载缓存省事,一条用apt-rdepends把依赖树完整展开。

在联网机器上,保持和目标服务器一样的Ubuntu 20.04版本,依次执行:

sudo apt clean sudo apt update sudo apt-get install --download-only openssh-server

apt clean先把/var/cache/apt/archives里的历史残留清掉,避免目录里混进与本次无关的旧deb。接着apt update刷新软件源索引。最后这条命令的意思是:计算安装openssh-server时需要的全部依赖包,只下载、不安装。下载产物统一放在/var/cache/apt/archives/下。

ls -lh /var/cache/apt/archives/*.deb

你会看到openssh-server本体、openssh-client、openssh-sftp-server,以及运行库的deb全部出现在目录里。这里有个前提:联网机器原本没有装过openssh-server,apt才会把openssh-server本体下载下来。如果联网机器已经装过且是最新版本,这条命令会提示“已是最新版”,什么也不下。处理办法是把关键包强制重新下载:

sudo apt-get install --reinstall --download-only \ openssh-server openssh-client openssh-sftp-server

加--reinstall之后,apt会无视“已安装”状态,把这三个关键的deb重新拉一遍。依赖包仍然只在系统缺失时下载,所以依赖闭包的机制不受影响。整理一下目录就可以打包:

mkdir -p ~/sshd-offline cp /var/cache/apt/archives/*.deb ~/sshd-offline/

为什么不用apt download?它只会下载你指定的包,不帮你算依赖;依赖关系复杂时手工补容易漏。路线A的价值是让apt的依赖解析器替你干这件事,代价是只下载“当前系统缺失”的包,可能在目标机器上缺个别包,需要用dpkg的报错反推。

2.2 路线B:apt-rdepends 展开完整依赖树,一个包都不放过

如果你手头的联网机器和目标服务器的基础环境差异大,路线A有缺包风险。此时我更偏向用apt-rdepends把依赖树完整铺开,宁多勿缺。apt-rdepends会递归打印一个包的所有依赖,输出里每个顶层包名独占一行,依赖以缩进形式跟在下面。

sudo apt-get install -y apt-rdepends mkdir -p ~/sshd-offline cd ~/sshd-offline for pkg in $(apt-rdepends openssh-server | grep -v '^ ' | sort -u); do apt download "$pkg" || echo "download failed: $pkg" done

这段脚本的核心是grep -v '^ ',它把以空格开头的依赖行全部剔除,只保留顶格输出的包名,再用sort -u去重。得到的包名列表包含openssh-server的全部递归依赖,libc6、libssl1.1、libkrb5-3这些基础库都在里面。apt download会在当前目录逐个下载对应deb,个别包因源里缺失或版本冲突下载失败时,脚本会打印download failed加包名,方便回头处理。

注意apt-rdepends默认只跟踪Depends关系,不带上Recommends建议安装的包。对sshd来说这恰好有好处:少装一个非必需推荐包,离线环境更干净。下载完成后用ls *.deb | wc -l统计包数量,对照包名清单确认没漏。

2.3 校验包信息与架构,打包前做最后一道确认

收集完几十个deb后,别急着打包。先抽查几个关键包的元信息,确认架构和版本:

dpkg-deb -I ~/sshd-offline/openssh-server_*.deb | grep -E 'Package|Version|Architecture'

dpkg-deb -I查看deb包内部控制信息,不安装也能读到Package、Version、Architecture字段。x86_64服务器上Architecture应该是amd64;如果在ARM服务器上装,需要下载arm64架构的deb,这一步能提前拦住拿错包的情况。再给每个deb生成校验值,拷贝到内网后用来比对文件是否损坏:

cd ~/sshd-offline md5sum *.deb > ~/md5sums.txt

最后把所有包和校验文件打进一个tar包:

cd ~ tar czf sshd-offline.tar.gz sshd-offline/ md5sums.txt ls -lh sshd-offline.tar.gz

打成单个tar再拷贝,是离线部署里很省事的习惯:U盘拷、scp传、放到内网HTTP服务器上让人wget,都是一个文件的事,不会出现拷了一堆deb结果少一个的尴尬。tar.gz比未压缩的tar小不少,几十个deb通常只有几MB到十几MB。如果联网机器是22.04而目标机器是20.04,openssh-server版本和libssl依赖会有差异,最好找一台20.04的联网机器或容器来执行这套流程。

3. 拷入内网机器并完成dpkg安装:三步走完

3.1 传输:U盘、scp还是内网HTTP

deb包收集齐后,要想办法把它弄进内网机器。传输方式按现场条件选:服务器在跟前,U盘拷贝最快;服务器在机房但网络直通,scp或rsync更顺;两边不直通,就放到内网一台HTTP服务器上,在目标机器上wget。关键是拷贝后立刻做校验,别等到dpkg失败才怀疑文件损坏。

U盘场景举例:tar包拷进U盘后,插到目标机器上。先找到挂载点:

lsblk -o NAME,LABEL,MOUNTPOINT sudo mount /dev/sdb1 /mnt

解压并校验:

mkdir -p ~/pkgs && cd ~/pkgs tar xzf /mnt/sshd-offline.tar.gz cd sshd-offline md5sum -c ../md5sums.txt

这里md5sum -c会用之前记录的哈希逐一比对当前目录下的deb,输出OK说明文件完好。如果校验失败,说明U盘拷贝过程有坏道或文件不完整,直接换一条传输路径,不要继续装。scp传输同理,传完在目标机器上跑一遍md5sum -c。

3.2 dpkg -i安装:一次给足所有包

校验完成后进入安装环节。安装前先看目标机器有没有残留的ssh相关包:

dpkg -l | grep -E 'openssh|ssh'

如果之前装过一半,先清理干净再装,避免版本残留。确认干净后执行:

cd ~/pkgs/sshd-offline sudo dpkg -i ./*.deb

这里./*.deb会把目录里所有deb一次性交给dpkg。dpkg处理多个包时会尽量按依赖顺序安装,如果A依赖B且B也在列表里,dpkg会先装B。这也是为什么强调一次给足所有包,分批dpkg -i大概率翻车。这条命令顺利跑完没有报错,直接拉起服务:

sudo systemctl enable ssh sudo systemctl restart ssh systemctl status ssh --no-pager

如果dpkg在安装过程中报dependency problems,先看它缺哪个包,从联网机器补下对应deb,再回来接着装。不要在装了一半的系统上反复跑apt-get install -f,离线机器上这条命令通常会因为网络超时失败。安装完成后确认版本:

dpkg -l | grep openssh-server /usr/sbin/sshd -V 2>&1

sshd -V输出OpenSSH_8.2p1这类版本信息,能确认安装流程真正完成。

3.3 生成主机密钥并启动服务

刚装的openssh-server在postinst脚本里会触发主机密钥生成,但当你从模板或快照恢复系统,或者ssh_host_*文件在安装前被清理过,就可能出现服务起不来的情况。特征是systemctl start ssh执行后立刻失败,journal日志里写sshd: no hostkeys found。生成主机密钥只有一条命令:

sudo ssh-keygen -A

ssh-keygen -A会一次生成sshd需要的所有主机密钥:RSA、ECDSA、ED25519,产物在/etc/ssh/ssh_host_*。生成后检查权限,私钥必须是root:root且600,公钥644:

sudo chown root:root /etc/ssh/ssh_host_* sudo chmod 600 /etc/ssh/ssh_host_* sudo chmod 644 /etc/ssh/ssh_host_*.pub

然后启动并设置开机自启:

sudo systemctl restart ssh sudo systemctl enable ssh sudo systemctl status ssh --no-pager

最后用ss -tlnp | grep :22确认端口在监听。这一步同时确认了sshd绑定地址和端口是否正确,如果输出为空,说明服务还没真正起来。

4. sshd_config与服务管理:装完别急着连,先调三个参数

4.1 三个必调参数:Port、PermitRootLogin、PasswordAuthentication

sshd装好、服务能起来,这只是开始。默认配置对生产内网来说偏松。改动配置文件前先备份:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

然后用sed统一调整三项。实际项目里我一般这样改:

sudo sed -E -i \ -e 's/^#?Port .*/Port 2222/' \ -e 's/^#?PermitRootLogin .*/PermitRootLogin no/' \ -e 's/^#?PasswordAuthentication .*/PasswordAuthentication no/' \ /etc/ssh/sshd_config

每条sed的含义:^#?匹配行首可能存在的注释符号,匹配到就把整行替换;Port 2222把ssh监听端口从默认22改成2222,能减少大量针对22端口的扫描流量;PermitRootLogin no禁止root直接登录,日常管理用普通用户加sudo;PasswordAuthentication no强制走密钥认证,杜绝密码爆破。如果内网环境确实需要密码登录,把最后一项改成yes即可,但生产环境不建议。

Port不是简单的端口美化,它牵扯防火墙放行。Ubuntu默认AppArmor对sshd端口策略比较宽,但用了UFW就必须同步放行:

sudo ufw allow 2222/tcp sudo ufw allow OpenSSH # 保留22的规则,避免回退麻烦

每次改完配置,重载前先跑配置测试:

sudo sshd -t echo $?

sshd -t只校验配置语法,不实际启动服务,exit code为0说明配置合法。此时再重载:

sudo systemctl reload ssh

reload和restart的区别要分清:reload让正在跑的sshd重新读取配置,不断开已有ssh会话;restart会断开当前所有连接。在线改配置优先reload,避免把自己踢在门外。改配置前一定要开一个备用会话,防止改坏后锁在外面,这是所有ssh维护人员的血泪经验。

4.2 密钥认证:把公钥装进authorized_keys并收紧权限

既然关掉了密码登录,就要把客户端的公钥放进目标用户的家目录。在目标用户下执行:

mkdir -p ~/.ssh chmod 700 ~/.ssh echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAxxxxxx admin@workstation' >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys

注意这不是生成密钥,而是把已生成的公钥内容追加到authorized_keys。chmod 700 ~/.ssh和chmod 600 ~/.ssh/authorized_keys是必须的:sshd默认开了StrictModes,如果.ssh目录或authorized_keys文件对组和其他用户可写,sshd会直接拒绝用这个公钥登录。这防的是密钥文件被篡改,别图省事关掉StrictModes。

authorized_keys的格式是<密钥类型> <base64密钥内容> <备注>。之前在Windows或Mac上生成过密钥,把.pub文件内容复制过来即可。一个用户最好只保留一个常用公钥,内网换电脑后及时删掉旧条目,避免“以为只有自己在用,结果某台退役笔记本里还留着私钥”。密钥类型上推荐ed25519,比RSA短且安全强度足够。

4.3 用systemd管理ssh服务的开机自启与状态确认

Ubuntu 20.04的openssh-server安装后会自动创建ssh.service并加入multi-user.target。确认开机自启用:

systemctl is-enabled ssh

输出enabled说明随系统启动,如果是disabled或static,执行:

sudo systemctl enable ssh

日常巡检状态,看两个东西:

systemctl status ssh --no-pager ss -tlnp | grep -E ':2222|:22'

status输出里Active: active (running)是关键行;ss输出能看到sshd实际绑定的地址。如果sshd_config里写了ListenAddress 192.168.1.10,ss输出只监听在那个IP,服务就是正常的。如果预期全网卡监听却只看到127.0.0.1,回ListenAddress检查。

有个容易忽略的细节:Ubuntu 20.04上systemctl既认sshd.service也认ssh.service,因为sshd.service是指向ssh.service的符号链接。但Debian系传统service命令只认ssh。跨机器排查时,先systemctl status ssh,看到不存在再试sshd,别一上来就抱怨机器有问题。

5. 离线装sshd避坑与常见问题排查:5个翻车点一条条过

5.1 客户端报“the ssh or sshd service is unavailable”

现象:从Windows的OpenSSH客户端去连刚装好的Ubuntu,报The ssh or sshd service is unavailable,或者直接Connection refused。

原因:这个报错字面意思容易让人以为是Windows侧服务问题,但实际上绝大多数情况是Ubuntu侧的sshd根本没在监听。离线安装时,sshd服务没被enable、配置文件被改坏、或者端口被防火墙拦掉,客户端表现都一样。

解决:回到Ubuntu服务器上依次看三件事:

systemctl status ssh --no-pager ss -tlnp | grep :22 sudo journalctl -u ssh -n 30 --no-pager

status看服务是否active,ss看端口是否监听,journal看最近日志。最常见的结果是sshd没起来,或起来了但bind失败。bind失败时journal里会写error: Bind to port 22 on 0.0.0.0 failed: Permission denied,这时排查是不是别的进程占用了22端口,或者ListenAddress写了不存在的IP。

5.2 dpkg: dependency problems 依赖缺失

现象:sudo dpkg -i ./*.deb执行到一半,报openssh-server depends on openssh-sftp-server; however: Package openssh-sftp-server is not installed。

原因:使用路线A下载时,如果联网机器上已经装有openssh-sftp-server,apt就不会把它下载到archives目录。拷贝到内网后,内网机器缺这个包,dpkg立刻翻车。这是离线安装最典型的“以为带齐了,其实缺一个”。

解决:先看报错缺哪个包,回到联网机器上单独补:

apt download openssh-sftp-server

把补下的deb拷进内网,先装它,再回头跑主包的dpkg -i。如果缺的是一串依赖包,别一个个折腾,直接用第2章路线B的apt-rdepends脚本把整个闭包重拉一遍,重新打包拷进去。

5.3 sshd: no hostkeys found 服务起不来

现象:systemctl restart ssh后立刻失败,journal里写sshd: no hostkeys found。

原因:从云镜像或虚拟机模板克隆出来的机器,镜像制作者出于安全考虑删掉了/etc/ssh/ssh_host_*,但openssh-server的postinst已经运行过,安装新包时不会重新生成主机密钥。sshd启动时找不到任何主机密钥,拒绝启动。

解决:手动生成:

sudo ssh-keygen -A sudo systemctl restart ssh

生成后检查权限,私钥600、公钥644、属主root:root。之前生成过但权限不对,也会触发StrictModes拒绝启动,用chmod收拢权限再重启。从模板克隆的机器即使能起sshd,多台克隆机器主机密钥相同,客户端会报host key mismatch。上线前对每台克隆机执行ssh-keygen -A并重启sshd,是必须做的动作。

5.4 Permission denied (publickey) 密钥登录失败

现象:手上有正确的私钥,服务端公钥也放进了authorized_keys,但ssh登录还是被拒,客户端日志停在Permission denied (publickey)。

原因:八成是authorized_keys路径或权限问题。sshd的StrictModes要求用户家目录不能对其他人可写,.ssh目录权限不能超过700,authorized_keys权限不能超过600。家目录、.ssh、authorized_keys三层权限任何一层不合规都会拒绝。

解决:在目标用户下执行:

chmod 700 ~ chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys sudo systemctl restart ssh

如果authorized_keys用FTP或Windows记事本传上去,可能带CRLF换行或UTF-8 BOM,sshd解析时会失败。用file ~/.ssh/authorized_keys看格式,dos2unix转一下再试。另外确认sshd_config里没写一个不存在的AuthorizedKeysFile路径,默认的.ssh/authorized_keys一般不会有人改,但模板机说不准。

5.5 Connection refused 但服务明明在跑

现象:sshd显示active,ss也看到监听,但客户端还是Connection refused。

原因:看监听地址和客户端连接地址是否匹配。sshd_config里如果设置了ListenAddress 192.168.1.10,它只监听那个内网IP。客户端用服务器另一个IP去连,自然被拒绝。另一种情况是ufw或云安全组只放行了一部分来源IP。

解决:先用ss确认实际监听地址,再对照客户端用的目标地址:

ss -tlnp | grep sshd sudo ufw status verbose

如果ufw active且没有放行规则,执行sudo ufw allow 22/tcp或按来源网段放行。云上机器还要检查安全组入站规则。调试技巧:客户端用ssh -v看握手到哪一步,如果卡在connect to host ... port 22: Connection refused是网络层问题;如果已经Connecting但没有后续,才是服务层问题。

6. 从ssh -v验证到一键批量部署:两个能省事的习惯

6.1 用ssh -v验证握手和认证全链路

安装配置完成后,别急着收工。用调试模式连一次自己,确认整个链路是通的:

ssh -v admin@127.0.0.1 -p 2222

输出里三个关键节点:第一是debug1: Connecting to 127.0.0.1 [127.0.0.1] port 2222,说明TCP能通;第二是debug1: Server host key: ssh-ed25519 SHA256:xxxx,说明主机密钥正常;第三是debug1: Authentication succeeded (publickey),说明公钥认证通过。走到第三步,离线安装就算真成功了。如果卡在第二步之前,先查网络和端口;如果卡在第三步,回头查第5章的权限问题。ssh -v不够就上ssh -vvv,把密钥协商细节全打出来,错误信息会精确到Offering public key这一层。

6.2 把离线安装做成一条脚本:批量部署更省心

给多台内网机器装sshd时,手动敲dpkg命令容易犯迷糊。把整个流程收成一个脚本,放在tar包里一起拷进去:

#!/bin/bash set -euo pipefail cd "$(dirname "$0")" tar xzf sshd-offline.tar.gz cd sshd-offline md5sum -c ../md5sums.txt || exit 1 sudo dpkg -i ./*.deb sudo ssh-keygen -A || true sudo systemctl enable ssh sudo systemctl restart ssh sudo ufw allow 2222/tcp || true sleep 1 systemctl is-active ssh || exit 1

脚本逻辑不复杂:解包、校验、安装、生成密钥、启动服务、放行防火墙。set -euo pipefail保证任何一步失败就中断,不会留下半装状态;ssh-keygen -A || true允许目标机器已有密钥时跳过;最后用systemctl is-active自检,输出active说明成功。我把这个脚本和tar包一起放在U盘里,到现场执行bash deploy_sshd.sh一步到位。这几年在内网装过几十次sshd,最深的一条教训是:宁可多带十个依赖包,也别少带一个;包目录整体打包、md5校验值随身带、备用会话开着再改配置。这些习惯救过我很多次。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 20:29:07

UL 2941-2023深度解读:分布式能源与逆变器网络安全评估要点

简介&#xff1a;UL 2941-2023中文版是关于分布式能源和基于逆变器资源&#xff08;IBR&#xff09;的网络安全调查大纲&#xff0c;面向智能电网设备制造商、系统集成商和运维人员&#xff0c;用于评估网络连接的逆变器、监控控制器等设备的最低网络安全要求。文档未涉及功能测…

作者头像 李华
网站建设 2026/10/8 20:29:05

Agent-Reach:构建大模型可靠触达层,解决AI Agent集成落地难题

去年有个项目让我印象特别深&#xff1a;公司内部想做一个能查订单、查物流、还能自动触发审批流程的AI助手&#xff0c;模型选型、提示词调优都挺顺利&#xff0c;Demo演示效果也不错。但一接入真实业务系统就完全失控——不是权限校验不对&#xff0c;就是接口返回的字段和预…

作者头像 李华
网站建设 2026/10/8 20:28:10

UEditor批量Word编辑实战:混合解析与公式表格处理

做互联网公司内部的内容后台、OA系统或者知识库&#xff0c;总会撞上同一个需求&#xff1a;运营拿着一堆Word文档&#xff0c;往网页编辑器里一拖&#xff0c;要求格式不丢、图片能传、表格能改&#xff0c;最好连公式都给你还原出来。很多团队第一个想到的就是UEditor&#x…

作者头像 李华
网站建设 2026/10/8 20:27:55

用C#开发西门子PLC调试助手:S7协议通讯与批量读写实战

1. 项目背景与整体设计思路 1.1 做电气调试这么久&#xff0c;为什么还要自己写一个PLC小助手 先交代一下我为什么动手做这个软件。干自动化这一行&#xff0c;现场调试的日子大家都懂&#xff1a;笔记本里装着一整套TIA博图或者Step7&#xff0c;改程序、下程序、监控变量&am…

作者头像 李华
网站建设 2026/10/8 20:25:15

macOS运维实战:SecureCRT for Mac的会话管理、日志与自动化脚本

简介&#xff1a;SecureCRT for Mac 是 macOS 平台上一款常用的 SSH/Telnet 终端连接工具&#xff0c;面向需要远程管理 Linux 服务器、网络设备或运行命令行程序的开发与运维人员。资源包共 822 个文件&#xff0c;压缩后约 30.45MB&#xff0c;主要包含 htm 格式的帮助文档、…

作者头像 李华
网站建设 2026/10/8 20:24:23

Agent-Reach:大模型时代AI Agent工具调用连接层的架构与实践

1. 项目定位&#xff1a;为什么我会做 Agent-Reach 这个项目 做 Agent 开发这两年&#xff0c;我最大的感受是&#xff1a;模型能力本身已经不是瓶颈了&#xff0c;真正卡住项目的是 Agent 和外部世界的连接。你有一个聪明的 Agent&#xff0c;但它调用不了公司内部的订单接口&…

作者头像 李华