使用 Azure Storage Account 搭建 SFTP 服务器

2025-03-19#Azure#SFTP

Azure Storage Account 提供了 SFTP 的特性,可使用 Blob Container 作为数据存储,然后通过 SFTP 协议对外提供服务。在生产应用中,除了提供基本的文件上传下载之外,还要考虑其他的非功能需求。本文简要记录实战中的经验。

基本介绍 🔗

官网文档见 《SSH File Transfer Protocol (SFTP) support for Azure Blob Storage》

认证方式 🔗

与其他的 SFTP 服务器类型,基于 Storage Account 的 SFTP 提供了密码认证和公钥认证。除此之外,需要注意:

  • SFTP 的用户叫做 Local User,与 Azure 中的其他服务无关。
  • 在创建 Local User 时,可指定用户名。但它只是登录 SFTP 登录名的一部分,完整的登录名是 {storageAccoutName}.{containerName}.{localUserName}@{storageAccoutName}.blob.core.windows.net;如果设置了 Local User 的 Home Directory(以 /{containerName}/ 开头),那么登录名中可省略 {containerName}。这个登录名着实有点儿长。
  • 在使用密码认证时,密码是 Azure 生成的,无法自行指定。
  • 在使用公钥认证时,使用 Azure 所支持算法,见《Supported algorithms》

权限控制 🔗

针对每个用户,可指定容器级别的权限,见文档 《Container permissions》。这种方式无法支持目录级别和文件级别的权限控制。

Azure 还支持细粒度的 ACL。类似于 Linux 的权限模型。目前处于 Preview 阶段。

IP 访问限制 🔗

如果期望对访问SFTP的客户端IP进行限制。为此,可利用 Storage Account 的“IP网络规则”特性来设置白名单:要么设置公网IP或者IP段,以允许来自互联网主机的访问;要么设置虚拟网络,以允许来自内部虚拟网络的访问。

但是,IP限制这个特性本身,有一些限制,尤其是:当Azure中的服务访问Storage Account,并且它们都在同一个 Region 时候,这些服务使用 私有的 Azure IP 地址通信。比如,当虚拟机上的应用访问同一个Region的Storage Account时候,会使用私有IP进行访问。因此无法将其IP添加到IP白名单中。这对同一个账户下的服务来说问题倒不大,因为可以使用虚拟网络进行限制。

但是,如果客户端位于另一个Azure租户的子网中,该客户端的子网开启了 Service Endpoint Microsoft.Storage,并与 Storage Account 在同一个Azure地区或者在配对的地区中,那么这个客户端就会使用私有 IP 进行通信;如果客户端所在的子网启用了跨地区的 Service Endpoint,即 Microsoft.Storage.Global, (见《Azure Storage cross-region service endpoints》),那么客户端也会使用私有 IP 进行通信。此时,在 Azure Portal 上是无法将另一个租户的子网添加到 Storage Account 的防火墙白名单的。但好消息是,虽然无法在 Azure Portal中添加,但可使用命令行或者代码添加。

更多的有关使用IP网络规则的限制见文档《Restrictions for IP network rules》

日志和指标 🔗

如果想记录 SFTP 服务的访问日志,可在 Storage Account 的 Diagnostic Settings 中添加日志和指标。这些日志和指标可存储到Log Analytics Workspace、Storage Account、Azure Event Hubs 以及 Azure Monitor partner solutions 。

如果想将日志存储到 Log Analytics Workspace,那么可以通过如下步骤:

  1. 创建一个 Log Analytics Workspace
  2. 在 Storage Account 中创建一个针对 blob 的 Diagnostic Setting。日志类别有 StorageReadStorageWriteStorageDelete;指标类别有 CapacityTransaction。并将日志和指标存储到第1步创建的 Log Analytics Workspace

如果通过代码创建 Diagnostic Setting,那么注意 resource_uri 的值为 {storageAccount.id}/blobServices/default

然后,就可以在 Azure Monitor 中查询日志。比如想查找连接 SFTP 的日志(该日志中包含客户端IP,可用户排查IP规则相关问题),可使用:

StorageBlobLogs
| where OperationName == "SftpConnect"
| take 10