news 2026/10/19 8:48:28

Ubuntu下SFTP文件传输全攻略:服务端配置、客户端使用与安全实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu下SFTP文件传输全攻略:服务端配置、客户端使用与安全实践

说实话,我在日常运维里用得最多的文件传输方式,还真不是FTP,也不是各种网盘,而是SFTP。这东西基于SSH协议,一条命令就能把文件从本地扔到远端服务器,或者从服务器拉回本地,全程加密,不需要额外开端口、不用单独装服务端软件,安全性也有底。今天这篇就围绕Ubuntu系统里的SFTP文件传输,从服务端怎么配、客户端怎么用,到权限、密钥、脚本化,再到我实际踩过的坑,一次性完整梳理一遍。无论你是刚开始接触Linux的新手,还是被权限问题折腾过几次的运维,这篇都能给你一些可以直接用的东西。

1. 为什么是SFTP:方案选型的底层逻辑

1.1 SFTP到底是什么

SFTP全称是SSH File Transfer Protocol,注意它和FTP(File Transfer Protocol)虽然名字很像,但完全是两码事。FTP是基于TCP 21端口、明文传输的古老协议,而SFTP是SSH协议的一部分,默认走22端口,传输过程中所有数据都是加密的。换句话说,只要你的服务器开着SSH服务,就天然具备SFTP能力,不需要安装任何额外的FTP服务器软件。

从协议栈的角度看,SFTP并不是独立跑在某个端口上的协议,而是在SSH连接建立之后,通过SSH加密通道里单独开一条会话来做文件操作。所以它的安全模型、认证体系、密钥管理,全都复用SSH已有的那一套。这也带来一个非常实际的好处:只要服务器能SSH登录,SFTP传输大概率就是通的,完全不用像传统FTP那样处理主动模式、被动模式、额外端口段开放这类破事。

这个特性在日常工作中非常实用。我见过太多人一提到文件传输就想着装一个FTP服务,结果折腾半天配置,还要担心密码在网络上明文传来传去——抓包工具一看,账号密码全裸奔,太吓人了。其实换成SFTP,这些问题从源头就消失了。

1.2 和常见传输方式比一比

为了说清楚SFTP的位置,我把常用的几种远程文件传输方式放在一起做了个对比:

方式端口加密特点适合场景
FTP21/20否老牌协议,兼容性好内网明文传输,公共下载站
FTPS21/990是FTP加TLS,配置复杂对FTP有依赖且需要加密的遗留系统
SFTP22是基于SSH,配置简单,天然加密Linux服务器之间、本地上传下载
SCP22是基于SSH,只支持文件复制一次性复制单个或整目录文件
rsync22(走SSH)是增量同步,断点续传目录镜像、增量备份

从这个表能看出来,SFTP在加密和易用性之间取得了很好的平衡。SCP虽然也基于SSH,但它不支持像SFTP那样交互式浏览远端目录、删除文件、修改权限,也不支持断点续传;rsync更偏向同步场景,而不是"我想看看远端目录里有什么文件再决定下载哪个"这种交互操作。SFTP最接近传统FTP的使用体验,又保住了SSH的安全底座,这决定了它在日常运维里不可替代的位置。

1.3 适合谁用、解决什么问题

SFTP适用的场景非常广:把本地的压缩包上传到服务器部署、把服务器上的日志文件拉下来排查问题、在两台Linux机器之间交换文件、给某个项目目录做远程备份,这些都能用SFTP稳稳拿下。它对开发者、运维、甚至只用过图形界面的人都友好,因为命令行操作足够简单,图形客户端也是一抓一大把。

我自己用得最多的是三个场景:一是服务器维护时上传配置文件、下载日志;二是给旧服务器做目录归档备份;三是配合密钥登录实现脚本化定时拉取数据。后面这些内容里,我会把每个场景对应的操作和配置都拆开讲,照着做基本就能复现。

2. 服务端准备:Ubuntu上把SFTP服务拉起来

2.1 安装SSH服务并确认状态

绝大多数Ubuntu Server默认不会安装openssh-server,所以第一步是装包。在Ubuntu上用apt一条命令就能搞定:

sudo apt update sudo apt install openssh-server -y

装完以后,确认服务是否在运行:

sudo systemctl status ssh

正常情况下能看到active (running)。要注意的是,Ubuntu里这个服务单元名叫ssh,不是sshd,有些教程写成sshd会查不到服务。如果没跑起来,执行start即可:

sudo systemctl start ssh sudo systemctl enable ssh

enable这步非常关键,不执行的话服务器重启后SSH服务不会自动启动,你的SFTP就彻底失联了。查看监听端口用:

ss -tlnp | grep sshd

看到22端口处于LISTEN状态,说明服务已经就绪。顺便说一句,ss命令比老的netstat更轻量,Ubuntu 18.04以后默认就有,不用额外装net-tools。

2.2 用户与目录规划

SFTP服务的用户管理,我推荐的做法是不要直接拿root账号传文件,而是在系统里创建专用账号。这里有两种常见方案:一种是给个人账号直接开SSH权限,正常登录后用SFTP在自己的家目录里操作;另一种是创建一个只能SFTP、不能SSH登录的受限账号,专门给某个项目或某个目录用。

第一种最简单,用adduser建一个用户并设置密码即可,它默认在/home/用户名下拥有读写权限。第二种更适合给只需要传文件的同事或者外部协作者使用。这类账号我一般这样建:

sudo adduser sftpuser

按提示设置密码、填写用户信息(可以直接回车跳过),账号就建好了。接下来要把这个账号圈在指定目录里,这就涉及目录规划的问题。

我习惯把这类用户的根目录统一放在某个专门的数据目录下,比如/data/sftp-home,而不是散落在/home里。这样隔离、备份、管理都方便。目录结构大概是:

/data/sftp-home └── incoming # 用户可写入的业务目录

根目录给root,业务子目录给用户,这个分层后面配置权限时至关重要。

2.3 限制用户只能SFTP不能SSH登录

如果希望这个账号只能SFTP传文件,不能登录shell,那就需要修改/etc/ssh/sshd_config。我在配置里最常加的是这一段:

Match Group sftpusers ChrootDirectory /data/sftp-home ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no

先说明一下思路。Match Group表示后面的配置只对sftpusers这个用户组生效,所以需要先把用户加进组:

sudo groupadd sftpusers sudo usermod -aG sftpusers sftpuser

ChrootDirectory的作用是把用户的活动范围限制在指定目录里,用户登录后看到的根目录就是这个目录,没法跑到系统其它地方去,安全隔离效果很好。ForceCommand internal-sftp强制该用户执行SFTP子系统,即使尝试SSH登录,也会被弹回SFTP环境。AllowTcpForwarding和X11Forwarding关闭是为了禁掉端口转发和图形转发,减少攻击面。

这样配置之后,sftpuser只能在这一个目录里上传、下载、删除文件,其它任何系统路径都碰不到,对多人协作场景特别实用。

2.4 配置项逐条解读

这里有几个配置项必须专门讲清楚,不然很容易踩坑。

  • Subsystem sftp /usr/lib/openssh/sftp-server:这是系统默认的SFTP子系统定义。有些教程会让你改成internal-sftp,意思是让sshd内置的SFTP实现来干活,少一次外部程序调用,也更方便配合ChrootDirectory使用。在上面Match组里已经写了ForceCommand internal-sftp,所以一般不用动全局Subsystem行。

  • ChrootDirectory目录的属主必须是root,而且这个目录不能被用户写,否则SSH服务会直接拒绝连接。这是很多人配置完成后反复报错的头号原因。目录权限建议755,属主必须是root:root。

  • 如果要在隔离目录里让用户能上传文件,ChrootDirectory本身由root拥有且不可写,那就在它下面建一个子目录(比如/data/sftp-home/incoming),把这个子目录的属主改成sftpuser,权限设成755或750。用户进来以后只能在incoming里写,看到的界面就是一个干净的隔离空间。

改完配置一定要先检查语法:

sudo sshd -t

没有输出就代表配置文件没有语法错误,然后重载服务:

sudo systemctl reload ssh

重载不影响已建立的连接,生产环境里也可以放心用。到这里服务端就已经能提供服务了,可以先用本机测试一下:

sftp sftpuser@127.0.0.1

能进到sftp>提示符,就说明服务端OK。

3. 客户端实操:命令行与图形化两手抓

3.1 命令行sftp基础操作

Ubuntu自带sftp命令行工具,用法和FTP命令很像,会一套就能顺手操作另一套。最常见的连接方式:

sftp user@remote_host

连接成功后进入sftp>交互界面。下面这些命令我几乎每天都要敲,整理成一份速查清单:

  • ls:列出远端当前目录的文件
  • ll:列出带详情,相当于ls -l
  • cd:切换远端目录
  • pwd:显示远端当前目录
  • lls:列出本地当前目录文件
  • lcd:切换本地目录
  • lpwd:显示本地当前目录
  • put localfile:上传本地文件到远端当前目录
  • get remotefile:下载远端文件到本地当前目录
  • mput *.log:批量上传匹配通配符的文件
  • mget *.tar.gz:批量下载匹配通配符的文件
  • mkdir / rmdir:在远端创建/删除目录
  • rm:删除远端文件
  • chmod / chown:修改远端文件的权限和属主(在权限允许范围内)
  • !command:在本地执行shell命令,比如!ls
  • bye / exit:退出

一个很实用的技巧是,在连接命令里直接指定远端路径,减少进界面后的目录切换次数。比如:

sftp user@remote_host:/var/log

连接后直接进入远端的/var/log目录,马上就能ll看日志文件。指定端口连接加-l参数:

sftp -P 2222 user@remote_host

注意,sftp命令行用的是大写P指定端口,和ssh的小写-p不一样。我刚用的时候在这上面栽过跟头,连写错两次才意识到。

3.2 批量传输与脚本化

如果每天都要定时从服务器拉数据,手工敲sftp太浪费精力。sftp支持批处理模式,把要执行的命令写进一个文本文件,然后用-b参数跑:

sftp -b batch.txt user@remote_host

batch.txt内容示例:

lcd /home/user/backup cd /data/export mget *.csv bye

这样就能一次性把远端/data/export下所有csv文件下载到本地backup目录。写脚本时注意一个细节:批处理模式下如果某条命令失败,默认会继续往下执行,只是返回码可能非零。如果想出错就停,在命令前加-:

-mget *.csv

表示这条命令出错时终止批处理。

还有个更稳妥的做法是用rsync走SSH,因为rsync支持增量传输和断点续传,适合大文件或频繁同步的场景。比如:

rsync -avz --partial user@remote_host:/data/export/ /home/user/backup/

--partial参数很关键,它允许rsync保留传输中断的临时文件,下次运行可以直接续传。如果传输中途网络断了,重新跑一次就能接着来,不用从头传。

对于需要无人值守的脚本化传输,配合SSH密钥登录是最佳方案,具体配置我放在第4节单独展开。这里要额外提醒一句:千万别用expect之类的工具自动填充密码,密码会出现在进程参数或脚本文件里,等于把钥匙挂在门上。

3.3 图形化客户端的使用

不习惯命令行的人,Ubuntu桌面环境下可以直接在文件管理器里访问SFTP。打开自带的Files文件管理器,在地址栏输入:

sftp://user@remote_host/data/export

它会提示输入密码(如果配置了密钥则直接进入),然后就能像本地文件夹一样浏览和拖拽文件。这个方式非常适合偶尔传几个文件、不想记命令的场景。

第三方图形客户端也有很多选择,比如FileZilla这类跨平台工具,左边本地目录、右边远端目录,上传下载直接拖,还能排队传多个文件。这类工具本质上也是SFTP协议,所以只要服务端配置好了,客户端几乎不用额外设置——选择SFTP协议、填上主机名、用户名、密码或密钥即可。

我个人的习惯是:日常维护和脚本任务用命令行,偶尔需要快速浏览远端目录结构、或者要把服务器上的文件拖给同事看,就用文件管理器或图形客户端。两条路都顺手,也互为备份。命令行出问题时还有图形界面兜底,反之亦然。

4. 密钥认证与免密传输

4.1 生成密钥对

每次传文件都要输密码,一方面麻烦,另一方面脚本里不好处理密码,明文存密码更是安全大忌。SSH密钥认证就是为了解决这个问题而存在的。第一步在本地生成密钥对:

ssh-keygen -t ed25519 -C "sftp-backup-key"

一路回车就行,默认生成在~/.ssh/目录下。id_ed25519是私钥,绝对不要外传;id_ed25519.pub是公钥,可以放到服务器上。选ed25519是因为它比传统RSA更短更快,安全性也足够。如果远端是比较老的系统只支持RSA,就改用:

ssh-keygen -t rsa -b 4096 -C "sftp-backup-key"

生成时如果设置了passphrase(口令短语),每次使用私钥都要输入一次。要是担心私钥泄露,可以设一个;要是想要完全免密自动化,就不设。折中方案是用ssh-agent缓存口令,这个后面讲。

4.2 下发公钥与权限要求

把公钥安装到服务器上有标准做法。如果服务器有ssh-copy-id工具,直接:

ssh-copy-id user@remote_host

它会提示输入一次密码,然后把本地公钥追加到远端~/.ssh/authorized_keys里,顺便把权限设置好。没有ssh-copy-id就手动来:

cat ~/.ssh/id_ed25519.pub | ssh user@remote_host "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

这条命令看起来长,其实做了四件事:在远端创建.ssh目录、设置700权限、把公钥追加到authorized_keys、把authorized_keys设为600。权限搞错的话,OpenSSH出于安全考虑会直接忽略这个密钥文件,导致认证失败。这是新手最容易忽略的细节。

密钥相关的权限要求可以整理成一张表,照着核对就行:

项目路径权限属主
远端家目录~755用户
远端.ssh目录~/.ssh700用户
远端密钥文件~/.ssh/authorized_keys600用户
本地私钥~/.ssh/id_ed25519600本机用户

4.3 实测效果与注意事项

配好密钥后,再执行sftp连接就不会提示输入密码:

sftp user@remote_host

直接进入sftp>提示符,非常顺滑。配合cron定时任务,就能实现无人值守的文件拉取。需要注意几个点:

  • 私钥文件权限必须是600或更严格,否则ssh会提示bad permissions并拒绝使用。
  • 如果本地有多个密钥,连接时用-i指定:
sftp -i ~/.ssh/another_key user@remote_host
  • 如果生成密钥时设置了passphrase,又不想每次输入,可以用ssh-agent缓存:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519

之后当前会话内再连sftp就不会反复要口令了。

  • 定期检查服务器上的authorized_keys,删除不认识的条目。我习惯每季度过一遍,把离职人员或废弃设备的密钥清理掉。这个习惯看着琐碎,关键时刻能避免安全事件。

5. 常见问题与排查技巧实录

5.1 连不上服务器的排查路径

Connection refused或者超时,是出现频率最高的问题。我的排查顺序是固定的,从本机到服务器逐层来。

第一步,确认端口能访问:

telnet remote_host 22

如果提示Connection refused,说明服务器上SSH服务没起来或端口不对;如果是超时,大概率是防火墙挡了。到服务器上检查服务状态:

sudo systemctl status ssh sudo ss -tlnp | grep :22

第二步,检查防火墙。Ubuntu上常用ufw,确认22端口已放行:

sudo ufw status sudo ufw allow 22/tcp

如果改过端口,比如改成2222,那就要allow 2222/tcp,客户端连接时带-P 2222。

第三步,用详细日志模式定位认证阶段的问题:

sftp -v user@remote_host

-v会输出连接过程中的所有调试信息,能看到底是卡在DNS解析、TCP连接、密钥交换还是密码认证哪一步。这个方法在排查"服务器感觉能通,但就是连不上"的诡异问题时尤其好用。有一次我花了一个多小时排查一个客户端的连接问题,最后用-v发现是本地DNS解析把目标主机名解析到了内网IP,机器在另一个网段,自然连不上。

5.2 权限报错的根因分析

配置了ChrootDirectory后,最常见的报错是连接一建立就断开,或者提示Received message too long。原因基本就是我前面说的:ChrootDirectory目录必须是root所有,且不能是用户可写。目录权限不满足要求时,sshd会直接拒绝或断开连接。查看系统日志能确认:

sudo journalctl -u ssh -n 50

或者直接看/var/log/auth.log里的sshd记录。看到类似fatal: bad ownership or modes for chroot directory这样的信息,就是权限问题无疑。解决办法:

sudo chown root:root /data/sftp-home sudo chmod 755 /data/sftp-home

还有一类权限问题是用户连上了,但上传文件时报Permission denied。这时候要检查目标子目录的属主和权限,确认用户有没有写权限:

ls -ld /data/sftp-home/incoming

如果是root所有且只读,用chown把目录交给sftpuser即可。记住一个核心原则:隔离目录(chroot根)给root,业务目录(用户可写的实际空间)给用户。

5.3 传输中断与速度慢的处理思路

大文件传一半断网是最让人抓狂的。SFTP本身不支持断点续传,这是协议层面的限制,所以遇到大文件我一般直接改用rsync走SSH链路,加上--partial和--append-verify参数,中断后重新执行就能从断点继续。实际测试中,一个大文件截断到一半之后重新同步,rsync只传输剩余部分,效率提升非常明显。

速度慢的话,先排除网络本身的因素,再用压缩和连接复用改善。在SFTP里没有现成的压缩参数,但改用rsync时可以加-z参数启用压缩传输,对文本类文件效果明显;如果是已经压缩过的包,就别加-z了,反而增加CPU开销。另外,在本地~/.ssh/config里开启连接复用,能省掉反复握手的时间:

Host remote_host ControlMaster auto ControlPath ~/.ssh/controlmaster-%r@%h:%p ControlPersist 600

这样同一时间多开几个sftp会话,后续的连接会复用已有连接,省去重新握手和认证的时间,实测对频繁小文件操作提升特别明显。

5.4 文件名编码与特殊字符问题

中文文件名在SFTP传输中经常出现乱码,尤其是从Windows客户端连Linux服务器时。根因是两端默认字符编码不一致,Windows那边常常是GBK/GB2312,Linux默认UTF-8。解决思路是让两端统一用UTF-8,或者让客户端做编码转换。实测下来,FileZilla这类图形客户端在设置里调整字符编码选项,能解决大部分乱码问题。

如果文件名里带空格或特殊字符,命令行下操作时记得用引号包起来:

get "report 2024 final.zip"

通配符批量操作时也要小心,mget按远端shell的通配符规则展开,先ll确认一下匹配范围再执行,避免误传一堆预期之外的文件。我吃过一次亏:mget *.tar把当天的备份包和上个月的备份包全拉下来了,本地磁盘差点撑爆。

5.5 换端口后的SFTP访问

如果不希望用默认22端口暴露SSH服务,可以把端口改到高位,比如2222。方法是修改/etc/ssh/sshd_config:

Port 2222

然后重载服务。改完之后,客户端连接就要带-P参数:

sftp -P 2222 user@remote_host

图形客户端在站点管理器里也要填对应端口。改端口确实能降低一部分扫描攻击的噪音,但真正的安全靠的是密钥认证和防火墙白名单,不要误以为改了端口就万事大吉。另外,改端口前务必确认防火墙规则和selinux(如果启用的话)都允许新端口,否则改完把自己锁在外面,那就只能去机房或者带外管理口救人了。

6. 写在最后:几个趁手的习惯

做运维这行,文件传输是绕不开的日常操作。SFTP好用的地方在于,它依托SSH生态,服务端、客户端、密钥体系、权限模型全部是现成的,你不需要为了传文件专门引入一套新工具、新端口、新协议。我这些年用下来的体会是:小文件随手sftp,大文件和同步任务交给rsync,密钥认证一定要配上,ChrootDirectory能隔离就隔离。把这几点做好,服务器的文件传输这条链路基本就能安稳跑很久。

最后再分享一个小技巧:如果经常在服务器和本地之间来回传文件,可以在~/.ssh/config里给服务器配一个别名,把复杂的连接信息固化起来。比如在本地~/.ssh/config里写:

Host backup-server HostName 192.168.1.100 User sftpuser Port 22 IdentityFile ~/.ssh/id_ed25519

配置之后,直接sftp backup-server就能连上,不用每次写一长串参数。多台服务器、多个密钥的场景下,这个文件能把连接管理得明明白白。我是在第三次因为记错端口而连不上之后才养成的习惯,早该这么做。

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

Function Calling与MCP:大模型工具调用的底层逻辑与实战指南

先说个我最近挺有感触的事。上个月某团队找到我,说他们的内部知识助手要做“工单自动处理”,模型答完话之后最好能直接调接口、改状态、发通知。我一听就知道绕不开两个词:Function Calling和MCP。这几年,凡是真正在做大模型应用的…

作者头像 李华
网站建设 2026/10/19 8:47:42

Zynq-7000上实时FPGA脉冲压缩工程(巴克码/LFM)

简介:本资源为FPGA脉压工程的完整实现方案,面向数字电路设计初学者、嵌入式信号处理学习者及雷达/通信方向实践工程师,聚焦于FPGA平台上的脉冲压缩(脉压)算法落地与硬件协同验证。压缩包共739个文件,176.42…

作者头像 李华
网站建设 2026/10/19 8:47:36

基于Pytorch构建LSTM进行时间序列预测的完整实践指南

最近在处理一批传感器采集到的时序数据时,我把“时间序列数据处理1——基于Pytorch构建长短时记忆网络(LSTM)”这套完整流程又从头到尾梳理了一遍。这篇文章就是把我在项目里的实践过程、选型理由和踩过的坑整理出来,内容覆盖数据…

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

open-code-review:面向工程落地的可编程代码审查CLI

1. 这不是又一个“AI代码审查”玩具:open-code-review 的真实定位与生存逻辑你肯定见过太多打着“AI code review”旗号的工具——点开网页,粘贴几行代码,等30秒,弹出几句泛泛而谈的“建议添加类型注解”“考虑使用更语义化的变量…

作者头像 李华
网站建设 2026/10/19 8:47:18

NVMe驱动中SGL描述符构建与调试实战

有一次我在改一个NVMe驱动的IO路径,把一直沿用的PRP换成了SGL。结果性能没有变好,反而时不时冒出一个状态码,命令提交直接失败。排查到最后,问题出在我把SGL描述符当PRP列表那样用,直接往DPTR里塞了一个数据块描述符&a…

作者头像 李华
网站建设 2026/10/19 8:47:10

用Transformer搭建中英互译系统:核心原理与工程实践

1. 项目概述与设计思路1.1 为什么文本翻译选 Transformer 而不是 LSTM前阵子我在本机搭了一套中英文本翻译演示系统,跑通之后最大的感触是:如果放在几年前,拿循环神经网络做同一个任务,光是把代码调成能并行训练这一步&#xff0c…

作者头像 李华