SFTP详解
# 一、组件功能
安全文件传输协议SFTP(SSH File Transfer Protocol)是文件传输协议(FTP)的安全版本,也是SSH协议的一部分,可通过安全SHELL(SSH)数据流轻松进行数据传输和数据访问。SFTP也被称为SSH文件传输协议。它提供了一个安全的连接来传输文件,并在本地和远程系统上遍历文件系统。SFTP中的加密是通过SSH连接来完成的,文件可以通过WinSCP和SFTP客户端进行传输。
# 二、适用场景
SFTP服务使用标准的SFTP协议实现上传/下载数据,您也可以创建SFTP用户来实现精确的权限控制。在各个不同行业之间或公司不同部门之间进行数据交换时,SFTP服务器提供了一种安全、简单、高效的文件传输方式。
# 三、SFTP优势
- 安全:SFTP协议提供了一个安全通道,用于在网络上的主机之间传输文件。
- 易用:SFTP是SSH协议的一部分,它是一种远程登录信息。
- 权限控制:通过建立独立的ssh用户进行精准权限控制
- 兼容性:sftp适用于所有平台
- 可靠性:基于SSH来加密传输文件,可靠性高,可断点续传
# 四、SFTP原理

SFTP,代表SSH File Transfer传输Protocol协议,是类似于FTP的网络协议,它允许文件访问,传输和文件管理,但可以通过安全可靠的数据流。
与FTP不同,它不使用单独的命令和数据通道。相反,它在单个连接中以特殊格式的软件包传输文件。名称中的SSH代表Secure SHell协议,SFTP是该协议的扩展。使用SFTP协议时,这提供了更高的安全性。 您可以以与FTP相同的方式使用SFTP,最大的区别是安全连接。 Filezilla和Cyberduck还提供SFTP作为其免费软件包的一部分,您肯定会利用它。

连接到SFTP服务器时,它假定连接正在安全通道上运行。由于客户端用户身份可用于协议,因此无需客户端身份验证。
WordPress是一个很好的示例,该站点允许同时进行FTP和SFTP连接。尝试添加已保存到计算机或服务器的主题时,可能需要通过FTP或SFTP传输该主题。
这是为了避免WordPress拒绝主题在正常传输过程中可能需要的某些代码行。
# 五、SFTP与同类产品对比
最明显的区别就是定义。 SFTP是安全的网络协议,而FTP则不是。另一种可能是协议类型。 FTP是基于TCP / IP的协议。 SFTP是基于SSH的协议。
TCP / IP表示T传输C控制Protocol / I互联网P协议。换句话说,这是控制互联网上所有计算机之间通信的标准协议。

FTP在TCP端口21上建立其控制连接,而SFTP在客户端和服务器之间通过SSH协议建立的连接下传输文件。
FTP仅以纯文本格式发送数据,而SFTP在将其所有数据发送到主机之前对其进行加密。
SFTP还是一个独立的协议,它提供主机到主机的传输,而FTP是一个更为开放的协议。 FTP,Netscape创建了SSL,或S确保S火箭Layer(当前为TLS或Transport Layer S安全性)。然后将SSL应用于FTP以创建FTPS。
这允许通过两个安全变体使用FTP以安全的方式交换数据:FTPS隐式SSL和FTPS显式SSL。两者都使用SSL加密。
最后,大多数人唯一需要担心的唯一关键区别是SFTP提供了一种将文件从一台主机传输到另一台主机的安全方法。 FTP仅通过两个通道(命令和数据通道)提供标准的纯文本传输,而没有加密。
而vsftpd是一个软件程序,是(very secure FTP daemon)的缩写,是一款在Linux发行版中最受推崇的FTP服务器程序,特点是小巧轻快,安全易用,支持ftp协议,但是不支持sftp协议。
# 六、部署方案
# 1.裸金属部署
添加用户配置目录权限
[root@db1 conf]# groupadd sftp #新建用户组 [root@db1 conf]# useradd -g sftp -s /sbin/nologin -M hsi_ftp #添加用户 [root@db1 conf]# passwd hsi_ftp #设置密码 Changing password for user hsi_ftp. New password: Retype new password: passwd: all authentication tokens updated successfully. [root@db1 data]# mkdir -p /data/sftp/hsi_ftp [root@db1 data]# usermod -d /data/sftp/hsi_ftp hsi_ftp [root@db1 data]# chown root:sftp /data/sftp/ #根目录所有者必须是root否则无法登录 [root@db1 data]# chown hsi_ftp:sftp /data/sftp/hsi_ftp/ #修改权限1
2
3
4
5
6
7
8
9
10
11修改配置

[root@db1 data]# vi /etc/ssh/sshd_config 注释行 #Subsystem sftp /usr/libexec/openssh/sftp-server 末尾添加行 Subsystem sftp internal-sftp Match Group sftp ChrootDirectory /data/sftp ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no 重启 [root@db1 data]# service sshd restart1
2
3
4
5
6
7
8
9
10
11
12
13
14
15验证
yzb-book:~ yzb$ sftp hsi_ftp@192.168.10.15 hsi_ftp@192.168.10.15's password: Connected to hsi_ftp@192.168.10.15. sftp> ls hsi_ftp sftp> cd hsi_ftp sftp> put /Users/yzb/Downloads/dfcf.dmg ./ Uploading /Users/yzb/Downloads/dfcf.dmg to /hsi_ftp/./dfcf.dmg /Users/yzb/Downloads/dfcf.dmg 100% 28MB 11.0MB/s 00:02 sftp> ls dfcf.dmg sftp> rm dfcf.dmg Removing /hsi_ftp/dfcf.dmg sftp> ls sftp>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.k8s容器化部署
cat sftp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sftp
spec:
replicas: 2 #可自行修改副本的个数
selector:
matchLabels:
app: sftp
template:
metadata:
labels:
app: sftp
spec:
nodeSelector:
sftp: "true"
containers:
- command: ["/entrypoint", "$(user):$(passwd):::$(path)"]
image: atmoz/sftp:alpine-3
name: sftp
ports:
- containerPort: 22
hostPort: 32222
name: http
protocol: TCP
env:
- name: TZ
value: "CST-8"
- name: user
value: "sftp"
- name: passwd
value: "123456"
- name: path
value: "upload"
resources:
limits:
cpu: "1"
memory: 200Mi
requests:
cpu: "0.1"
memory: 100Mi
securityContext:
capabilities:
add: # 添加
- CAP_SYS_ADMIN
drop: # 删除
- KILL
volumeMounts:
- mountPath: /etc/ssh/ssh_host_ed25519_key
name: ssh-host-ed25519-key
- mountPath: /etc/ssh/ssh_host_rsa_key
name: ssh-host-rsa-key
- mountPath: "/opt/data"
name: data
# - mountPath: "/home/foo/"
# name: data
# - mountPath: "/home/bar/"
# name: data
- name: users
mountPath: /etc/sftp
- name: bindmount
mountPath: /etc/sftp.d
volumes:
- hostPath:
path: /etc/ssh/ssh_host_ed25519_key
name: ssh-host-ed25519-key
- hostPath:
path: /etc/ssh/ssh_host_rsa_key
name: ssh-host-rsa-key
- name: data
persistentVolumeClaim:
claimName: pvc-nfs
- name: users
configMap:
name: users-cm
- name: bindmount
configMap:
name: bindmount-cm
---
apiVersion: v1
data:
user.conf: |
foo:123:1001:100:/home/sftp/upload
bar:abc:1002:100:/home/sftp/upload
baz:xyz:1003:100
kind: ConfigMap
metadata:
name: user-cm
---
apiVersion: v1
data:
bind-mount.sh: |
#!/bin/bash
# File mounted as: /etc/sftp.d/bindmount.sh
# Just an example (make your own)
function bindmount() {
if [ -d "$1" ]; then
mkdir -p "$2"
fi
mount --bind $3 "$1" "$2"
}
# Remember permissions, you may have to fix them:
# chown -R :users /data/common
bindmount /opt/data /home/sftp/upload
bindmount /opt/data /home/foo/upload
bindmount /opt/data /home/bar/upload
kind: ConfigMap
metadata:
name: bindmount-cm
kubectl apply -f sftp.yaml
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# 七、高可用方案
SFTP是单节点的服务,本身不支持集群模式,但可组合keepalived、rsync,共享存储,负载均衡等组件,建立起SFTP的高可用方案

部署sftp 参考部署方案-裸金属部署章节(两台服务器都需要部署)
RSYNC编译安装
安装前提:需要保持双向同步的服务器主机时间同步 下载地址:https://download.samba.org/pub/rsync/src/rsync-3.1.3.tar.gz 解压编译安装 [root@db1 ~]# tar -zxvf rsync-3.1.3.tar.gz [root@db1 ~]# cd rsync-3.1.3 [root@db1 rsync-3.1.3]# ./configure --prefix=/usr/local/rsync --disable-ipv6 [root@db1 rsync-3.1.3]# make && make install [root@db1 rsync-3.1.3]# ln -s /usr/local/rsync/bin/rsync /usr/local/bin/rsync 简历需要同步的目录(客户端主机和服务端主机均需要建目录保持一致) [root@db1 rsync-3.1.3]# mkdir -p /data/sftp/hsi_ftp/upload/ [root@db1 rsync-3.1.3]# chown -R hsi_ftp:sftp /data/sftp/hsi_ftp/ [root@db1 rsync-3.1.3]# chmod -R 777 /data/sftp/hsi_ftp/ [root@db1 rsync-3.1.3]# vi /etc/xinetd.d/rsync 将disable = yes 改为 no1
2
3
4
5
6
7
8
9
10
11
12
13
14
15服务端配置,双向同步时2台服务器是客户端同时也都是服务端
[root@db1 sftp]# vi /usr/local/rsync/rsyncd.conf pid file = /var/run/rsyncd.pid port = 873 uid = hsi_ftp#服务端系统用户 gid = sftp#服务端系统用户组 use chroot = yes max connections = 5 timeout 600 lock file = /var/run/rsyncd.lock log file = /var/run/rsyncd.log #secrets file = /usr/local/rsync/rsyncd.secrets motd file = /etc/rsyncd.motd [hsi_sftp]#名称可以随意 path = /data/sftp/hsi_ftp/#需要同步的目录,拥有者和用户组必须和上面的pid,gid一致 #ignore errors read only = no#非只读 write only = no#非只写 list = yes hosts allow = * #hosts deny = 0.0.0.0/32 secrets file = /usr/local/rsync/rsyncd.secrets auth users = hsi_ftp #该用户系统中存在且对后面指定的备份目录拥有权限 comment = sftp hsi_sftp 配置帐号密码格式:帐号:密码 [root@db1 sftp]# vi /usr/local/rsync/rsyncd.secrets hsi_ftp:hsi_ftp 修改配置文件权限 [root@db1 sftp]# chmod 600 /usr/local/rsync/rsyncd.conf [root@db1 sftp]# chmod 600 /usr/local/rsync/rsyncd.secrets1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32客户端配置
客户端登录服务端密码,注意这里只写密码,和服务端的/usr/local/rsync/rsyncd.secrets文件对应 [root@db1 sftp]# vi /usr/local/rsync/rsyncd.pass hsi_ftp 修改密码配置文件权限,如果不修改则可能无法使用 [root@db1 sftp]# chmod 600 /usr/local/rsync/rsyncd.pass1
2
3
4
5
6测试
启动服务端 [root@db1 rsync]# rsync --daemon --config=/usr/local/rsync/rsyncd.conf [root@db2 ~]# rsync -avz --password-file=/usr/local/rsync/rsyncd.pass /data/sftp/hsi_ftp/ hsi_ftp@192.168.10.15::hsi_sftp sending incremental file list upload/ upload/rsyncd.conf1 sent 463 bytes received 39 bytes 334.67 bytes/sec total size is 492 speedup is 0.981
2
3
4
5
6
7
8
9
10
11
12INOTIFY-TOOLS安装(双向同步2台主机分别都要执行操作)
下载 [root@db1 upload]# wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz 解压 [root@db1 upload]# tar -zxvf inotify-tools-3.14.tar.gz [root@db1 upload]# cd inotify-tools-3.14 [root@db1 inotify-tools-3.14]# ./configure --prefix=/usr/local/inotify [root@db1 inotify-tools-3.14]# make && make install 检查是否安装成功 [root@db1 inotify-tools-3.14]# ls -alh /usr/local/inotify/bin/inotify* -rwxr-xr-x. 1 root root 44K Feb 28 14:38 /usr/local/inotify/bin/inotifywait -rwxr-xr-x. 1 root root 41K Feb 28 14:38 /usr/local/inotify/bin/inotifywatch 建立软连接 [root@db1 inotify-tools-3.14]# ln -s /usr/local/inotify/bin/inotifywait /usr/bin/inotifywait [root@db1 inotify-tools-3.14]# ln -s /usr/local/inotify/bin/inotifywatch /usr/bin/inotifywatch 配置rsync.sh同步监控脚本 [root@db1 inotify]# vi /usr/local/inotify/rsync.sh # 内容如下 #!/bin/bash src=/data/sftp/hsi_ftp/ #同步目录 des=hsi_sftp #视情况自己配置,注意与下面的rsync命令结合配置 user=hsi_ftp host="192.168.10.16" #服务端主机ip /usr/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e modify,delete,create,attrib $src | while read file do rsync -vzrtopg --delete --progress --password-file=/usr/local/rsync/rsyncd.pass $src $user@$host::$des echo "$file was rsynced" >> /tmp/rsync.log 2>&1 done [root@db1 inotify]# chmod +x /usr/local/inotify/rsync.sh nohup sh /usr/local/inotify/rsync.sh & #建立守护进程运行rsync.sh脚本 echo “nohup sh /usr/local/inotify/rsync.sh &” >> /etc/rc.local 测试:分别在2台机器/data/sftp/hsi_ftp/目录修改,新增,删除文件查看另一台服务器上是否也同步修改1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38KEEPALIVED配置 安装详见 HTTP://WWW.YANGZB.COM/ARTICLE/16
vi /usr/local/keepalived/etc/keepalived/keepalived.conf 后添加内容 virtual_server 192.168.10.160 22 { delay_loop 6 lb_algo rr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.10.15 22 { weight 1 TCP_CHECK { connect_timeout 3 retry 3 delay_before_retry 3 } } real_server 192.168.10.16 22 { weight 1 TCP_CHECK { connect_timeout 3 retry 3 delay_before_retry 3 } } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 八、监控方案
SFTP成熟的监控方案比较少,因sftp可监控项也比较少
下面以prometheus监控sftp为例,进行演示
采用https://github.com/billabongrob/sftp-exporter进行sftp指标采集
docker run -p 9816:9816 --env SFTPHOST=127.0.0.1 --env SFTPUSER=hsi_ftp --env SFTPPASS=123456 ghcr.io/billabongrob/sftp-exporter:latest
prometheus job 添加
- job_name: 'prome' static_configs: - targets: ['localhost:9816'] labels: id: sftp-instance instance: sftp1
2
3
4
5
6grafana dashboard
https://grafana.com/grafana/dashboards/15744-sftp-connectivity/

# 九、常见问题及解决方法
发布服务时文件启动pod异常排查
Kubectl logs pod名称 –n 分区名称查看 [root@vm-paasyy24-097 ~]# kubectl get po -n sftp-images NAME READY STATUS RESTARTS AGE sftp-image-7d4d766b94-ftl6b 1/1 Running 0 131m [root@vm-paasyy24-097 ~]# kubectl logs sftp-image-7d4d766b94-ftl6b -n sftp-images1
2
3
4
5或在kem上直接查看

日志中应该是如下报错

解决办法,密钥文件粘贴注意格式,粘贴到kem页面上注意最后一行加回车,避免pod无法启动或正常启动后登录sftp服务器上验证失败。
另外还有一种可能是转码问题,用文本编辑工具处理一下即可。
Sftp登录sftp服务器报密码错误排查
日志的结尾部分基本上是如下错误:
Unable to load host key "/etc/ssh/ssh_host_ed25519_key": invalid format Unable to load host key: /etc/ssh/ssh_host_ed25519_key Invalid user demo1-admin from 10.248.24.101 port 18416 Could not get shadow information for NOUSER1
2
3
4解决办法,这个就是ldap服务验证不通过,检查下启动deplayment的ldap相关的环境变量。一定要与kem服务器上application.properties文件中ldap配置部分一致。修改后重启即可。
ftp上传镜像到指定的目录上,未生成result结果文件,在镜像库中查不到
配置文件未正确挂载:
进入pod容器内或在kem上直接进入容器,查看容器内对应的配置文件,看有没有正常加载,或进入容器挂载在本地的日志的目前查看日志。 [root@vm-paasyy24-097 ~]# kubectl exec -it sftp-image-7d4d766b94-ftl6b -n sftp-images bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@sftp-image-7d4d766b94-ftl6b:/home# cd /opt/images/config root@sftp-image-7d4d766b94-ftl6b:/opt/images/config# ls -l total 0 lrwxrwxrwx 1 root root 17 Aug 6 15:09 config.ini -> ..data/config.ini lrwxrwxrwx 1 root root 25 Aug 6 15:09 harbor_config.conf -> ..data/harbor_config.conf lrwxrwxrwx 1 root root 27 Aug 6 15:09 ssh_host_ed25519_key -> ..data/ssh_host_ed25519_key lrwxrwxrwx 1 root root 23 Aug 6 15:09 ssh_host_rsa_key -> ..data/ssh_host_rsa_key root@sftp-image-7d4d766b94-ftl6b:/opt/images/config#1
2
3
4
5
6
7
8
9
10
11[root@vm-paasyy24-097 ftpdata]# cd logs [root@vm-paasyy24-097 logs]# ls -l total 5760 -rw-r--r-- 1 root root 0 Aug 6 14:59 images_error.log -rw-r--r-- 1 root root 4799150 Aug 6 17:50 images_info.log [root@vm-paasyy24-097 logs]# tail -f images_info.log 2021-08-06 17:50:32,690 - images_share_main.py[line:210] - INFO:事件触发租户为:pass-uer001-admin,项目为:wzk 2021-08-06 17:50:32,690 - images_share_main.py[line:210] - INFO:事件触发租户为:pass-uer001-admin,项目为:wzk 2021-08-06 17:50:32,691 - base.py[line:144] - INFO:Job "addImagesPath (trigger: interval[0:00:05], next run at: 2021-08-06 17:50:37 CST)" executed successfully 2021-08-06 17:50:32,702 - images_share_harbor_v2.py[line:91] - INFO:调用harbor:10.248.24.215:1121项目接口成功 2021-08-06 17:50:32,702 - images_share_push.py[line:138] - INFO:##############镜像上传harbor开始 2021-08-06 17:50:32############## 2021-08-06 17:50:32,702 - images_share_push.py[line:139] - INFO:获取项目列表返回值 200 2021-08-06 17:50:32,703 - images_share_push.py[line:142] - INFO:10.248.24.215:1121 harbor获取项目列表成功 2021-08-06 17:50:32,703 - images_share_push.py[line:149] - INFO:已存在的项目列表是 {'123': 11, 'eee': 12, 'google_containers': 6, 'kube_system': 5, 'library': 1, 'paas-admin': 4, 'paas-monitor': 3, 'test': 10, 'test1': 7, 'test2': 8} 2021-08-06 17:50:32,703 - images_share_push.py[line:151] - INFO:10.248.24.215:1121 harbor eee 项目已存在 2021-08-06 17:50:32,703 - images_share_push.py[line:237] - INFO:docker开始load镜像。。。。。 ^C [root@vm-paasyy24-097 logs]#1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18如果配置文件加载不正常,重新粘贴配置文件,注意格式。重启即可
配置文件正确挂载,但上传镜像后没有结果文件

如上图的错误为harbor_config.conf配置项未配置正确,harbor地址错误,修改为正确的harbor地址,上传镜像成功。

# 十、创建用户
使用用户组的概念可以更方便地管理多个SFTP用户。以下是基于用户组的SFTP用户创建步骤:
- 创建用户组
# 创建一个专门用于SFTP的用户组,例如 sftpUsers:
groupadd sftpUsers
2
- 创建用户并加入用户组
# 创建一个新用户(例如 sftpuser1),并将其加入 sftpUsers 组:
useradd -m -G sftpUsers sftpuser1
2
- 设置用户密码
# 为新用户设置密码:
passwd sftpuser1
2
- 创建SFTP根目录
# 为所有SFTP用户创建一个根目录,例如 /home/sftp:
mkdir -p /home/sftp
2
- 为每个用户创建子目录
# 在 /home/sftp 下为每个用户创建独立的子目录,例如 sftpuser1:
mkdir -p /home/sftp/sftpuser1/upload
2
- 设置目录权限
# 确保根目录的权限正确,子目录允许用户上传文件:
sudo chown root:root /home/sftp
sudo chmod 755 /home/sftp
sudo chown sftpuser1:sftpUsers /home/sftp/sftpuser1/upload
2
3
4
- 配置SSH
# 编辑SSH配置文件 /etc/ssh/sshd_config,(ctrl+o,确定键==保持,ctrl+X==退出)添加以下内容以限制 sftpUsers 组用户只能使用SFTP:
nano /etc/ssh/sshd_config
# 启用SFTP子系统(可选)
Subsystem sftp internal-sftp
# 添加或修改以下内容:
Match Group sftpUsers
ChrootDirectory /home/sftp/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
# %u 表示用户名,确保每个用户被限制在自己的目录中。
2
3
4
5
6
7
8
9
10
11
12
13
- 重启SSH服务
# 保存并关闭文件后,重启SSH服务:
systemctl restart sshd
2
- 测试SFTP连接
# 测试
sftp sftpuser1@localhost
2
- 添加更多用户
# 如果需要添加更多用户,重复以下步骤:
# 1.创建用户并加入 sftpUsers 组:
sudo useradd -m -G sftpUsers sftpuser2
# 2.设置密码:
sudo passwd sftpuser2
# 3.创建用户子目录并设置权限:
sudo mkdir -p /home/sftp/sftpuser2/upload
sudo chown sftpuser2:sftpUsers /home/sftp/sftpuser2/upload
2
3
4
5
6
7
8
9
10