首页 / 资讯中心 / 文章详情

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

Ubuntu 20.04离线安装sshd实操:依赖收集、dpkg部署与排错指南 ★ FEATURED ARTICLE
简介面向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 路线Aapt-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-serverapt 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-serverapt才会把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 路线Bapt-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|Architecturedpkg-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.04openssh-server版本和libssl依赖会有差异最好找一台20.04的联网机器或容器来执行这套流程。3. 拷入内网机器并完成dpkg安装三步走完3.1 传输U盘、scp还是内网HTTPdeb包收集齐后要想办法把它弄进内网机器。传输方式按现场条件选服务器在跟前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 21sshd -V输出OpenSSH_8.2p1这类版本信息能确认安装流程真正完成。3.3 生成主机密钥并启动服务刚装的openssh-server在postinst脚本里会触发主机密钥生成但当你从模板或快照恢复系统或者ssh_host_*文件在安装前被清理过就可能出现服务起不来的情况。特征是systemctl start ssh执行后立刻失败journal日志里写sshd: no hostkeys found。生成主机密钥只有一条命令sudo ssh-keygen -Assh-keygen -A会一次生成sshd需要的所有主机密钥RSA、ECDSA、ED25519产物在/etc/ssh/ssh_host_*。生成后检查权限私钥必须是root:root且600公钥644sudo 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、PasswordAuthenticationsshd装好、服务能起来这只是开始。默认配置对生产内网来说偏松。改动配置文件前先备份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直接登录日常管理用普通用户加sudoPasswordAuthentication 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 sshreload和restart的区别要分清reload让正在跑的sshd重新读取配置不断开已有ssh会话restart会断开当前所有连接。在线改配置优先reload避免把自己踢在门外。改配置前一定要开一个备用会话防止改坏后锁在外面这是所有ssh维护人员的血泪经验。4.2 密钥认证把公钥装进authorized_keys并收紧权限既然关掉了密码登录就要把客户端的公钥放进目标用户的家目录。在目标用户下执行mkdir -p ~/.ssh chmod 700 ~/.ssh echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAxxxxxx adminworkstation ~/.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|:22status输出里Active: active (running)是关键行ss输出能看到sshd实际绑定的地址。如果sshd_config里写了ListenAddress 192.168.1.10ss输出只监听在那个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-pagerstatus看服务是否activess看端口是否监听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-serverapt就不会把它下载到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目录权限不能超过700authorized_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 BOMsshd解析时会失败。用file ~/.ssh/authorized_keys看格式dos2unix转一下再试。另外确认sshd_config里没写一个不存在的AuthorizedKeysFile路径默认的.ssh/authorized_keys一般不会有人改但模板机说不准。5.5 Connection refused 但服务明明在跑现象sshd显示activess也看到监听但客户端还是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 admin127.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校验值随身带、备用会话开着再改配置。这些习惯救过我很多次。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站