go 访问 sftp 服务 github.com/pkg/sftp 的使用踩坑,连接未关闭(含 sftp 服务测试环境搭建)

news2025/9/8 18:42:49

前言

最近在使用 sftp 服务时,被告知发起了海量的连接,直接把服务器搞崩,ip 被封了。

这是啥情况?

golang 写的代码,我就正常的访问 sftp 服务,连接使用过后也都关闭了,咋会出现连接一直连着没关的情况呢?

原因分析

先上代码,主要使用了开源库 github.com/pkg/sftp

package main

import (
	"fmt"
	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
	"time"
)

func main() {
	ticker := time.NewTicker(time.Second)
	for range ticker.C {
		client, err := createDefaultSftpClient()
		if err != nil {
			panic(err)
		}

		// 演示用
		wd, err := client.Getwd()
		if err != nil {
			panic(err)
		}
		fmt.Println(wd)

		client.Close()
	}
}

func createSFTPClient(user, pwd, host, port string, pemBytes []byte) (*ssh.Client, *sftp.Client, error) {
	var authMethods []ssh.AuthMethod
	if pwd != "" {
		authMethods = append(authMethods, ssh.Password(pwd))
	}
	if len(pemBytes) > 0 {
		signer, err := ssh.ParsePrivateKey(pemBytes)
		if err != nil {
			return nil, nil, err
		}
		authMethods = append(authMethods, ssh.PublicKeys(signer))
	}

	config := &ssh.ClientConfig{
		User:            user,
		Auth:            authMethods,
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	conn, err := ssh.Dial("tcp", host+":"+port, config)
	if err != nil {
		return nil, nil, err
	}

	client, err := sftp.NewClient(conn)
	if err != nil {
		return nil, nil, err
	}
	return conn, client, nil
}

var defaultSftpPemBytes = []byte(``)

func createDefaultSftpClient() (*sftp.Client, error) {
	_, client, err := createSFTPClient("foo", "test", "127.0.0.1", "2222", defaultSftpPemBytes)
	return client, err
}

本篇的测试环境是 windows,当上述程序跑起来后,查看本机 2222 端口的使用情况(netstat -ano | findstr 2222),这一看,果然是好多连接啊。为什么我的 client 已经 Close 了还是会有这么多连接未关闭呢?
在这里插入图片描述

想必细心的朋友们已经发现了问题,我故意给 createSFTPClient 返回了两个连接,一个是 ssh.Client 还有一个是 sftp.Client,但是 createDefaultSftpClient 只返回了 sftp.Client

查看 github.com/pkg/sftp 源码发现:

  • sftp.NewClient 会调用 SSH 连接的 NewSession 方法创建一个新会话,但不会持有 SSH 连接的所有权。
  • sftpClient.Close() 仅关闭 SFTP 会话的 Channel,而 SSH 连接的生命周期由调用方(即 sshClient)控制。

原因就是 ssh.Client 创建了没有关闭,必须要显示调用 sshClient.Close()!!!

搭建测试 sftp 服务

使用 docker 镜像 atmoz/sftp 搭建 sftp 服务。

docker-compose.yaml

version: '3.8'

services:
  sftp:
    image: atmoz/sftp
    volumes:
      - ./atmoz_data:/home/foo/uploads
    # - ./atmoz_ssh_keys:/home/foo/.ssh/keys # 支持密钥登录
    command: foo:test:1001  # 用户名:空密码:UID:GID
    ports:
      - "2222:22"

这里我踩了两个坑

  1. linux 环境下,服务启动后,尝试创建目录时报错 mkdir /test: permission denied。 是因为宿主机目录的权限或所有权未与容器内用户的 UID/GID 匹配。例如,容器内用户 UID 为 1001,但宿主机目录所有者是 root,导致权限冲突。可以调整宿主机目录的权限 chown -R 1001:1001 /宿主机目录/atmoz_data
  2. 若需支持密钥登录,需将上述的 docker-compose.yamlvolumes 的注释去掉。注意:宿主机的 atmoz_ssh_keys 目录下一定要把自己生成的 ssh key 公钥放进去,不然会报错
[/usr/local/bin/create-sftp-user] Parsing user data: "foo:test:1001"
cat: '/home/foo/.ssh/keys/*': No such file or directory

因为使用 atmoz/sftp 镜像时,若在 command 中定义了用户 foo:test:1001,镜像会自动执行以下操作:

  • 创建用户 foo(UID 1001)
  • 尝试从 /home/foo/.ssh/keys/ 目录加载公钥文件(*.pubauthorized_keys)。
  • 将公钥写入 /home/foo/.ssh/authorized_keys

由于将容器内的 /home/foo/.ssh/keys/ 目录映射出去了,但是有没放密钥文件进去,找不到文件,所以就直接报错了。

这里还有一点,atmoz/sftp 搭建的服务应该是不支持 Ed25519 类型的密钥的,可以使用 rsa

ssh-keygen -t rsa -b 4096

总结

本文主要分析了使用 go 三方库 github.com/pkg/sftp 访问 sftp 服务出现大量的连接未关闭的异常情况,需要显式调用 sshClient.Close()

接着介绍了如何使用 docker 搭建 sftp 服务,一个权限,一个密钥,需要注意。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2386783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux多线程(二)之进程vs线程

文章目录 Linux进程VS线程进程和线程进程的多个线程共享关于进程线程的问题 重谈地址空间Linux线程周边的概念 Linux进程VS线程 进程和线程 进程是资源分配的基本单位(进程是承担分配系统资源的基本实体) 执行流也是资源!线程是进程内部的执…

【HW系列】—web常规漏洞(文件上传漏洞)

文章目录 一、简介二、危害三、文件检测方式分类四、判断文件检测方式五、文件上传绕过技术六、漏洞防御措施 一、简介 文件上传漏洞是指Web应用程序在处理用户上传文件时,未对文件类型、内容、路径等进行严格校验和限制,导致攻击者可上传恶意文件&…

如何实现 C/C++ 与 Python 的通信

C/C 与 Python 的通信可以通过多种方式实现,如使用 C API、Ctypes、Cython、SWIG、Python.h 或基于共享库的调用等。其中,使用 Ctypes 方式最为简便,适合快速调用已有的 C 函数库。例如,通过将 C 代码编译为动态链接库&#xff08…

好用但不常用的Git配置

参考文章 文章目录 tag标签分支新仓库默认分支推送 代码合并冲突处理默认diff算法 tag标签 默认是以字母顺序排序,这会导致一些问题,比如0.5.101排在0.5.1000之后。为了解决这个问题,我们可以把默认排序改为数值排序 git config --global t…

ULVAC VWR-400M/ERH 真空蒸发器 Compact Vacuum Evaporator DEPOX (VWR-400M/ERH)

ULVAC VWR-400M/ERH 真空蒸发器 Compact Vacuum Evaporator DEPOX (VWR-400M/ERH)

PPT连同备注页(演讲者模式)一块转为PDF

首先,进入创建PDF/XPS: 然后进入选项: 发布选项-发布内容里选备注页: 导出的原始结果是这样的: 这个时候裁剪一下,范围为所有页面: 最终结果: 如果导出不选“备注页”而是只勾选“包…

项目三 - 任务8:实现词频统计功能

本项目旨在实现一个词频统计功能,通过读取文本文件并利用Java编程技巧处理和分析文本数据。首先,使用BufferedReader逐行读取文件内容,然后通过String.split(" ")方法将每行文本分割成单词数组。接下来,采用HashMap来存…

ollama list模型列表获取 接口代码

ollama list模型列表获取 接口代码 curl http://localhost:11434/v1/modelscoding package hcx.ollama;/*** ClassName DockerOllamaList* Description TODO* Author dell* Date 2025/5/26 11:31* Version 1.0**/import java.io.BufferedReader; import java.io.InputStreamR…

OPC Client第5讲(wxwidgets):初始界面的事件处理;按照配置文件初始化界面的内容

接上一讲,即实现下述界面的事件处理代码;并且按照配置文件初始化界面的内容(三、) 事件处理的基础知识,见下述链接五、 OPC Client第3讲(wxwidgets):wxFormBuilder;基础…

【C++进阶篇】初识哈希

哈希表深度剖析:原理、冲突解决与C容器实战 一. 哈希1.1 哈希概念1.2 哈希思想1.3 常见的哈希函数1.3.1 直接定址法1.3.2 除留余数法1.3.3 乘法散列法(了解)1.3.4 平方取中法(了解) 1.4 哈希冲突1.4.1 冲突原因1.4.2 解…

Spring Boot——自动配置

目录 1.bean加载方式 1.1XML方式声明bean 1.2 xml 注解方式声明bean 1.3通过Configuration和Bean 1.4使用Import注解 1.5使用上下文对象在容器初始化完毕后注入bean 1.6使用ImportSelector接口 1.7实现ImportBeanDefinitionRegistrar接口 1.8bean加载方式(…

使用 Vuex 实现用户注册与登录功能

引言 在构建具有用户认证功能的应用时,Vuex 可以用来管理用户的登录状态和相关信息。以下是如何使用 Vuex 来实现用户注册与登录功能的概述。 🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端…

进程通信(管道,共享内存实现)

01. 进程通信简介 进程通信工具分为数据传输工具和共享内存两类。这里我们讨论进程通信工具(IPC)里面的管道、system V和共享内存。在理解阶层通信之间,我们先了解用户空间缓冲区和内核空间缓冲区两个概念。 1.1 用户空间缓冲区 存在于用户态的进程用户空间&#…

电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测

电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测 目录 电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测预测效果基本描述程序设计参考资料 预测效果 基本描述 电池预测 | 第28讲 基于CNN-GRU的锂电池剩余寿命预测 运行环境Matlab2023b及以上,锂电池剩余寿…

快速上手SHELL脚本常用命令

一、设置主机名称 1.修改文件方式 重启后生效 2.命令修改 重启shell后生效 二、网卡管理nmcli 1.查看网卡 2.设置网卡 详细配置:快速上手Linux联网管理-CSDN博客 三、简单处理字符 1.打印连续数字 2.设置字体颜色 \033[颜色代号m 3.反向打印文件内容 tac&a…

【自然语言处理与大模型】大模型Agent四大的组件

大模型Agent是基于大型语言模型构建的智能体,它们能够模拟独立思考过程,灵活调用各类工具,逐步达成预设目标。这类智能体的设计旨在通过感知、思考与行动三者的紧密结合来完成复杂任务。下面将从大模型大脑(LLM)、规划…

小巧高效的目录索引生成软件

软件介绍 本文介绍的软件名为Snap2html,是一款树形目录索引生成工具。 软件大小与便捷性 Snap2html这款软件已完成汉化,其体积仅170kb,小巧无比,且无需安装,可直接投入使用。 软件使用方法 该软件操作简便&#xf…

云原生架构设计相关原则

文章目录 前言云原生架构概述云原生架构的核心原则一切皆服务原则自动化原则韧性和容错原则可观测性原则 云原生架构原则的实践意义 前言 大家好,我是沛哥儿。今天想和大家深入探讨一下云原生架构的相关原则。在如今数字化飞速发展的时代,云原生架构已经…

华为云Flexus+DeepSeek征文 | Flexus X实例助力 Dify-LLM 一键部署:性能跃升与成本优化的革新实践

引言 在AI大模型应用快速普及的背景下,企业对低门槛部署、高性能算力与成本可控的需求日益迫切。华为云推出的Flexus X实例,作为专为AI工作负载优化的新一代算力底座,通过1.6倍算力提升、关键业务6倍加速、综合降本30%等核心优势&#xff0c…

数据库blog7_MySql的下载与配置准备

🌿MySql下载 🍂1.应用版本选择 选择社区版,免费适合初学者 相关链接下载页面下载界面介绍 🍂2.OS版本选择 根据自己的OS类型(Windows/Linux(CentOS/Ubuntu …)/macOS)选择对应版本…