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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值