写在前面
你可能听说过 FTP ,那你听说过SFTP吗?
介绍
SFTP是Secure File Transfer Protocol的缩写,安全文件传送协议。
可以为传输文件提供一种安全的加密方法。sftp 与 ftp 有着几乎一样的语法和功能。
SFTP 为 SSH的一部分,是一种传输档案至 Blogger 伺服器的安全方式。其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接操作,所以从某种意义上来说,SFTP并不像一个服务器程序,而更像是一个客户端程序。
SFTP同样是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。
部署sftp
使用docker方式进行部署
启动docker服务
使用命令systemctl start docker
启动docker
安装sftp服务
直接使用命令下载并安装
docker run --name mysftp -p 1022:22 -d atmoz/sftp test:test:::upload
- –name mysftp 容器名称
- test:test:::upload 其中test为用户名,test为密码,upload为上传的文件会保存到容器里面的/home/foo/upload目录里面
- -p 1022:22 将宿主机的22端口映射到容器的22端口,这样方位宿主机的22端口则会转发到容器的22端口上
- -d atmoz/sftp 使用dockup hub中的atmoz/sftp镜像创建容器
通过以上命令构建的sftp容器,用户上传的文件会存放在容器里面中,如果容器删除,则上传文件将会丢失。
查看sftp是否运行
上传下载
使用xshell
1.新建连接,ip填写宿主机ip,端口号填写宿主机映射后的端口1022
2.填写用户名和密码,test/test上一步创建
3.协议选择SFTP
4.点击确定即可
tips:上传前,可以先指定本地路径,也可以直接使用绝对路径,这里设置了本地路径
sftp:/> lcd
弹窗对话框之后,选择一个目录
下载文件
测试,从sftp上下载文件可以,命令:
#进入sftp下载目录
sftp:/> cd upload
#使用get命令下载文件
sftp:/upload> get aa.md
上传文件
#首先要进入sftp的上传目录(重要)
sftp:/> cd upload
#使用命令上传文件,或者直接拖入xshell
sftp:/upload> put test.txt
上传后到sftp服务器上看一下文件
root@4afae9d36aea:/# cd /home/test/upload
root@4afae9d36aea:/home/test/upload# ls
test.txt
遇到的问题
上传到sftp,提示文件无写权限,报错信息如下:
# 上传文件
sftp:/> put test.txt
#报错日志
sftp: cannot open /test.txt to write
解决方法:需要先进入sftp服务的upload目录
使用命令工具
命令主要是针对linux操作系统而言,若在win系统中建议使用客户端,win系统中可以使用git bash命令工具
#连接sftp服务
$ sftp -oPort=1022 test@192.168.191.128
#授权,输入yes
The authenticity of host '[192.168.191.128]:1022 ([192.168.191.128]:1022)' can't be established.
ED25519 key fingerprint is SHA256:Iwk+gbfgrdYEP1JB+giTvMdaLfmeXFGVVntUdF8EIYk.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[192.168.191.128]:1022' (ED25519) to the list of known hosts.
#输入密码,输入时密码不显示
test@192.168.191.128's password:
Connected to test@192.168.191.128.
s cd upload #cd 到uload目录
s get aa.md # 使用get命令从目录中下载文件
Fetching /upload/aa.md to aa.md
s
sftp常用命令
cd 路径 更改远程目录到“路径”
lcd 路径 更改本地目录到“路径”
chgrp group path 将文件“path”的组更改为“group”
chmod mode path 将文件“path”的权限更改为“mode”
chown owner path 将文件“path”的属主更改为“owner”
exit 退出 sftp
help 显示这个帮助文本
get 远程路径 下载文件
ln existingpath linkpath 符号链接远程文件
ls [选项] [路径] 显示远程目录列表
lls [选项] [路径] 显示本地目录列表
mkdir 路径 创建远程目录
lmkdir 路径 创建本地目录
mv oldpath newpath 移动远程文件
open [用户@]主机[:端口] 连接到远程主机
put 本地路径 上传文件
pwd 显示远程工作目录
lpwd 打印本地工作目录
quit 退出 sftp
rmdir 路径 移除远程目录
lrmdir 路径 移除本地目录
rm 路径 删除远程文件
lrm 路径 删除本地文件
symlink existingpath linkpath 符号链接远程文件
version 显示协议版本
shell脚本
#对脚本文件进行授权
chmod +x ./folder.sh
mirror的用法:
mirror [OPTS] [source [target]]
-c,--continue 续传上次的任务
-e,--delete 删除远程目录上不存在的文件
--delete-first 在传输新文件之前删除旧的文件
--depth-first 进入下一层目录优先于文件传输
-s,--allow-suid 根据远程站点设置suid/sgid比特位
--allow-chown 尝试将自己设置为文件所有者和所有组
--ascii 使用ascii方式传输(隐含了--ignore-size)
--ignore-time 决定是否下载时忽略时间因素
--ignore-size 决定是否下载时忽略文件大小因素
--only-missing 只下载缺少的文件
--only-existing 只下载已经存在于目标文件夹中的文件
-n,--only-newer 只下载新文件(-c参数无法工作)
--no-empty-dirs 不创建空文件夹(隐含了--depth-first)
-r,--no-recursion 不进入子文件夹
--no-symlinks 不创建符号链接
-p,--no-perms 不设置文件权限
--no-umask 不使用文件预设权限
-R,--reverse 反向镜像(上传文件)#用于上传文件
-L,--dereference 将符号链接作为文件下载
-N,--newer-than=SPEC 只下载比指定时间晚的文件
--on-change=CMD 只要有文件或文件夹存在差异就执行命令CMD
--older-than=SPEC 只下载比指定时间早的文件
--size-range=RANGE 只下载大小在指定区间上的文件
-P,--parallel[=N] 并行下载N个文件
--use-pget[-n=N] 使用pget传输每个文件
--loop 循环知道找不到差异
-i RX,--include RX 包括相匹配的文件 #使用正则
-x RX,--exclude RX 不包括相匹配的文件
-I GP,--include-glob GP 包括相匹配的文件 #使用通配符
-X GP,--exclude-glob GP 不包括相匹配的文件
-v,--verbose[=level] 冗长操作
--log=FILE 将执行的lftp命令写入文件FILE
--script=FILE 将lftp命令写入文件FILE,但不执行
--just-print, --dry-run 与--script=-相同
--use-cache 使用缓存目录列表
--Remove-source-files 传输完成后删除源文件
-a 与--allow-chown --allow-suid --no-umask相同
mirror一些示例
lftp -u ${sftp_user},${password} sftp://${host}:${port}<<EOF
mput ${localFile} #将本地localFile文件上传到sftp中(支持通配符)
mirror -R ${localDir} ${remoteDir} #将本地localDir中的文件或目录上传到sftp服务端的remoteDire中
mirror -R -I b*.zip ${localDir} ${remoteDir} #将本地localDir中的b.*zip文件上传到sftp remoteDire中
mirror -R --only-newer --only-missing -I b*.zip ${localDir} ${remoteDir} #将本地localDir中的b.*zip文件上传到sftp
批量下载
主要是使用mirror命令,并使用通配符的方式实现批量下载
#用户名
USER="test"
PASSWORD="test"
#从远程接收的本地目录
LOCAL_DIR="/var/test/shell/test/"
#FTP目录
FTP_DIR="/upload"
HOST="192.168.191.128"
PORT=1022
#登录sftp
lftp -u ${USER},${PASSWORD} sftp://${HOST}:${PORT} <<EOF
#提前设置ftp目录和本地目录,在使用mirror命令时,不用考虑源目录和目标目录的位置,mirror命令会自动识别
#设置远程FTP目录
cd ${FTP_DIR}
#设置本地目录
lcd ${LOCAL_DIR}
#下载文件名称a*.md的文件
mirror -I a*.md
by
EOF
jsch类库
简介
JSch 是SSH2的一个纯Java实现。它允许你连接到一个 sshd 服务器,使用端口转发,X11转发,文件传输等等。你可以将它的功能集成到你自己的程序中,同时该项目也提供一个J2ME版本用来在手机上直连SSHD服务器。
说白了就是以 Java 的方式通过 jsch 连接,来对服务器进行操作。
JSch 是一个纯粹的用 Java 实现 SSH 功能的 Java library。如果要知道 Jsch 的功能需先了解一下 SSH。SSH是一个安全协议,用来在不同系统或者服务器之间进行安全连接,在连接和传送数据的过程中会进行加密。SSH一般是基于客户端的或者Linux命令行,比如 window 通过 OpenSSH、putty等客户端的工具,在linux上可以通过ssh username@host命令进行连接。但是如果在Java中如何实现SSH呢?这时候便是通过JSCH来实现此的功能。
JSch库可以实现Java连接Linux服务器并操作命令、文件等,支持常用的各种授权模式。官网:http://www.jcraft.com/jsch/
类似C#中的SSH.Net框架。在Java中,类似的库还有:Apache Mina SSHD http://mina.apache.org/sshd-project/
Jsch 的认证方式
1、Jsch提供了四种认证机制:
- password 密码方式
- publickey(DSA,RSA) 公私钥方式
- keyboard-interactive
- gss-api-with-mic
常见的认证方式为password认证,但是本文接下来主要讨论基于publickey认证。对于后面两种认证方式感兴趣的朋友可以去查阅相关资料,本文将不做讨论。
2、配置SSH免密步骤概述
- 在linux下执行ssh-keygen -t rsa 生成一对对应公私钥。
- 把公钥复制到将要连接的目标服务器上,放到对应用户的.ssh目录下。
- 进入到.ssh中:cd ~/.ssh,并公钥导入到authorized_keys信任列表:cat 公钥 >> authorized_key
- 更新权限:chmod 600 authorized_keys,自此SSH免密登录配置完成。
主机公钥确认 StrictHostKeyChecking
StrictHostKeyChecking=no
最不安全的级别,当然也没有那么多烦人的提示了,相对安全的内网测试时建议使用。如果连接server的key在本地不存在,那么就自动添加到文件中(默认是known_hosts),并且给出一个警告。StrictHostKeyChecking=ask
默认的级别,就是出现刚才的提示了。如果连接和key不匹配,给出提示,并拒绝登录。StrictHostKeyChecking=yes
最安全的级别,如果连接与key不匹配,就拒绝连接,不会提示详细信息。
示例代码
从sftp下载代码
添加依赖:
implementation 'com.jcraft:jsch:0.1.55'
public static void main(String[] args) {
String username = "test";
String password = "test";
String remoteServerIp = "192.168.191.128";
int remotePort = 1022;
JSch jsch = new JSch();
try {
Session session = jsch.getSession(username, remoteServerIp, remotePort);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(password);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;
//下载文件
sftpChannel.get("/upload/test.txt", "E:\\桌面\\新建文件夹 (2)");
// Vector ls = sftpChannel.ls("");
sftpChannel.exit();
session.disconnect();
} catch (JSchException e) {
//To change body of catch statement use File | Settings | File Templates.
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
}
}
FTP与SFTP对比
FTP和SFTP区别如下图:
小结
对安全性要求比较高的话,推荐使用SFTP协议,对传输速度要求比较高的话推荐采用FTP协议。
SFTP常用于Linux操作系统需要有一定的Linux基础,FTP主要用于Windows操作系统,配置比较简单。TFTP协议目前用的比较少,了解就行了。
The end.