CentOS搭建SFTP服务器步骤详解
1. 查看SSH版本
# ssh -V
OpenSSH_6.6.1p1, OpenSSL 1.0.1e-fips 11 Feb 2013
2. SSH 服务器配置
要想查看所有的服务器配置项请参考 sshd_config(5)
以下配置启用了sftp server,并且使用用户名/密码方式进行认证。
# $OpenBSD: sshd_config,v 1.93 2014/01/10 05:59:19 djm Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/local/bin:/usr/bin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# The default requires explicit activation of protocol 1
Protocol 2
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
##HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
##HostKey /etc/ssh/ssh_host_ecdsa_key
##HostKey /etc/ssh/ssh_host_ed25519_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024
# Ciphers and keying
#RekeyLimit default none
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
SyslogFacility AUTHPRIV
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#RSAAuthentication yes
#PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
##AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
PasswordAuthentication yes
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
#KerberosUseKuserok yes
# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
#GSSAPIEnablek5users no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
# problems.
UsePAM yes
#AllowAgentForwarding yes
AllowTcpForwarding no
#GatewayPorts no
X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
##UsePrivilegeSeparation sandbox # Default for new installations.
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
##Banner /etc/ssh/ssh_login_banner
# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
# override default of no subsystems
#Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
3. 创建sftp用户的步骤
3.1 创建用户组
# groupadd sftp
3.2 创建用户主目录
# 主目录
# mkdir -p /export/Data/cfs/edi/sftp/sftpuser
# 子目录
# mkdir -p /export/Data/cfs/edi/sftp/sftpuser/upload
# mkdir -p /export/Data/cfs/edi/sftp/sftpuser/download
3.3 创建用户
# 创建用户 sftpuser, 指定分组 sftp,主目录 /export/Data/cfs/edi/sftp/sftpuser
# useradd -g sftp -s /bin/false -d /export/Data/cfs/edi/sftp/sftpuser -M sftpuser
# 设置用户 sftpuser 的密码为 password
# echo password | passwd --stdin sftpuser
3.4 设置目录权限
# 改变主目录owner为root
# chown root:root /export/Data/cfs/edi/sftp/sftpuser
# 改变子目录owner为sftpuser
# chown sftpuser:sftp /export/Data/cfs/edi/sftp/sftpuser/*
# 设置分组的读写权限
# chmod -R g+w,g+r /export/Data/cfs/edi/sftp/sftpuser/*
3.5 修改sshd_config配置
在sshd_config文件末尾追加以下内容
Match user sftpuser
ChrootDirectory /export/Data/cfs/edi/sftp/sftpuser/
ForceCommand internal-sftp
4. 重启sshd服务
# service sshd restart
5. 验证sftp
5.1 如果连接后报错Connection reset by peer
# sftp sftpuser@sftp-server
sftpuser@sftp-server's password:
Write failed: Broken pipe
Couldn't read packet: Connection reset by peer
这个问题的原因是ChrootDirectory的权限问题,你设定的目录必须是root用户所有,否则就会出现问题。所以请确保sftp用户根目录的所有人是root, 权限是 750 或者 755。
注意以下两点原则:
- 目录开始一直往上到系统根目录为止的目录拥有者都只能是 root,用户组可以不是 root。
- 目录开始一直往上到系统根目录为止都不可以具有群组写入权限
5.2 查看文件
# sftp sftpuser@11.56.1.201
sftpuser@sftp-server-ip's password:
Connected to sftp-server-ip.
sftp> ls
download upload
5.2 文件上传
sftp> put text.txt upload/text.txt
Uploading text.txt to /upload/text.txt
text.txt 100% 5 0.0KB/s 00:00
sftp> ls upload
upload/text.txt
5.3 文件下载
sftp> get upload/text.txt text-3.txt
Fetching /upload/text.txt to text-3.txt
/upload/text.txt 100% 5 0.0KB/s 00:00
sftp> !ls
cfs-client text-2.txt text-3.txt text.txt
sftp>
6. 自动创建用户脚本
#!/usr/bin/env python
import os
import subprocess
import sys
def mkdir_user_chroot(diroot): # mkdir user chroot
res = {}
sftp_chroot = "/export/sftp"
user_chroot = "%s/%s" % (sftp_chroot, diroot)
mkdir_cmd = "/usr/bin/mkdir -p %s" % user_chroot
if os.path.exists(user_chroot):
res["code"] = 1
res["msg"] = "catalog: %s is exists, add user faild" % diroot
else:
status, output = subprocess.getstatusoutput(mkdir_cmd)
if status == 0:
res["code"] = 0
res["msg"] = "catalog: %s create ok" % (diroot)
else:
res["code"] = 1
res["msg"] = "catalog: %s create faild, add user faild" % diroot
return res
def change_user_own(user, diroot): # change own
res = {}
sftp_chroot = "/export/sftp"
change_cmd = "cd %s;/usr/bin/chown root.root %s" % (sftp_chroot, diroot)
status, output = subprocess.getstatusoutput(change_cmd)
if status == 0:
res["code"] = 0
res["msg"] = "author ok"
else:
res["code"] = 1
res["msg"] = "autor faild"
return res
def add_user(user, password, diroot): # add user and pass for user
sftp_chroot = "/export/sftp"
res = {}
add_cmd = "/usr/sbin/useradd -g sftp -s /bin/false -d %s/%s -M %s" % (sftp_chroot, diroot, user)
chpass_cmd = "/usr/bin/echo %s | passwd --stdin %s" % (password, user)
status, output = subprocess.getstatusoutput(add_cmd)
if status == 0:
status, output = subprocess.getstatusoutput(chpass_cmd)
if status == 0:
res["code"] = 0
res["msg"] = "add user: %s ok,pass: %s" % (user, password)
else:
res["code"] = 1
res["msg"] = "user: %s is exist,add user error" % user
return res
def modife_sshd_config(user, diroot): # modife sshd_config
sftp_chroot = "/export/sftp"
sftp_file = "/export/Data/cfs/config/sftp/sshd_config"
new_line = "Match user %s\nChrootDirectory %s/%s\nForceCommand internal-sftp\n" % (user, sftp_chroot, diroot)
with open(sftp_file, "a+") as config:
config.write(new_line);
config.write("\n");
def modify_user_list(user, password, diroot):
new_line = "%s:%s:%s" % (user, password, diroot)
sftp_user = "/export/Data/cfs/config/sftp/sftp_user"
with open(sftp_user, "a+") as user:
user.write(new_line);
user.write("\n");
def restart_sshd():
re_cmd = "/home/admin/start.sh 2>&1"
os.system(re_cmd)
def main(user, diroot, password): # main fun
result = {}
stat = mkdir_user_chroot(diroot)
if stat["code"] == 0:
add_res = add_user(user, password, diroot)
if add_res["code"] == 0:
own_res = change_user_own(user, diroot)
if own_res["code"] == 0:
modife_sshd_config(user, diroot)
modify_user_list(user, password, diroot)
restart_sshd()
result["code"] = 0
result["msg"] = "sftp_user: %s add ok and password: %s" % (user, password)
else:
result["code"] = 1
result["msg"] = own_res["msg"]
else:
result["code"] = 1
result["msg"] = add_res["msg"]
else:
result["msg"] = stat["msg"]
return result
if __name__ == "__main__":
user = sys.argv[1]
password = sys.argv[2]
diroot = sys.argv[3]
print (main(user, diroot, password))
参考
Host Key
Understanding Secure Shell Host Keys
SSH - Host Key (or Ssh Public Key)
Linux(CentOS)上配置 SFTP