⬆️ ⬇️

Pure-FTPD with user storage in the MYSQL database

image

Previously, it was not once to set up an FTP server (for several minutes), and as it has historically happened, ProFtpd was the undisputed candidate. Since, in terms of security, this comrade had problems recently, he decided to try something else, and did not regret



My choice was a wonderful FTP server Pure-FTPd .

After installation you will receive the following set of functions:







FreeBSD is used as the OS. And so let's go! It is assumed that you have installed and configured MySql DBMS. Install Pure-FTPd from ports (after upgrading them)

cd /usr/ports/ftp/pure-ftpd make install clean 


I selected the following options



After installation create configs from default files

 cd /usr/local/etc/ cp pureftpd-mysql.conf.sample pureftpd-mysql.conf cp pure-ftpd.conf.sample pure-ftpd.conf 


Editing the main configuration file

pure-ftpd.conf
# Chroot`it all users in their folders

ChrootEveryone yes

')

# If “no” was selected in the previous option, then members of the next

# groups will not be chroot. All the rest - will be. If you do not want

# chroot`it all, then just unzip the ChrootEveryone and TrustedGID.

# TrustedGID 100



# Enable compatibility features for client curves

BrokenClientsCompatibility no



# Maximum number of simultaneous users

MaxClientsNumber 50



# Work in the background (daemon)

Daemonize yes



# Maximum number of simultaneous connections from one IP

MaxClientsPerIP 8



# If you want to log all client teams, then this

# paragraph must be "yes". If you need to log also

# server responses, then simply duplicate this item.

Verboselog no



# Show or not files starting with a dot, even when a client

# obviously does not say that this should be done, option "-a".

DisplayDotFiles yes



# Do not allow authenticated users - this FTP

# for anonymous clients only.

AnonymousOnly no



# Disable anonymously - FTP current for registered users.

NoAnonymous no



# Syslog tools (auth, authpriv, daemon, ftp, security, user, local *)

# Default - "ftp". “None” - disables logging.

Syslogfacility ftp



# Show any cookies? (Display fortune cookies)

# FortunesFile / usr / share / fortune / zippy



# Do not resolve hostnames in logs. Logs become less informative,

# but less resources are required. "Yes" - it makes sense to put on a very

# loaded servers, or when DNS is down.

DontResolve yes



# Maximum idle time (at the end of the connection breaks), in minutes

# (default = 15 minutes)

MaxIdleTime 15



# LDAP configuration file (see README.LDAP)

# LDAPConfigFile /etc/pureftpd-ldap.conf



# MySQL configuration file (see README.MySQL)

MySQLConfigFile /usr/local/etc/pureftpd-mysql.conf



# Postgres configuration file (see README.PGSQL)

# PGSQLConfigFile /etc/pureftpd-pgsql.conf



# database of PureDB users (see README.Virtual-Users)

# PureDB /etc/pureftpd.pdb



#path to pure-authd socket (see README.Authentication-Modules)

# ExtAuth /var/run/ftpd.sock



# If you need to enable PAM authentication, uncomment

# next line

# PAMAuthentication yes



# If you need system, Unix authentication (/ etc / passwd),

# uncomment the next line

# UnixAuthentication yes



# Please note that LDAPConfigFile, MySQLConfigFile,

# PAMAuthentication and UnixAuthentication can only be used

# once, but they can be used together. For example, if you

# use MySQLConfigFile, then UnixAuthentication, then there is a request

# to MySQL. If the user is not found in the database, then try

# system user in / etc / passwd and / etc / shadow. If SQL

# authentication fails due to incorrect password, something happens

# stop further search user. Authentication Methods

# will be used in the order they are set



# Limits of recursion of the 'ls' command. The first argument is the maximum number of files

# that will be shown. The second is the maximum number of subdirectories.

LimitRecursion 10,000 8



# Do anonymos have the right to create new directories?

AnonymousCanCreateDirs no



# If the system is loaded more than the value specified here, then

# anonymos can not download anything

MaxLoad 4



# Port range for passive connection. If you have a firewall chopping

# standard range

# PassivePortRange 30000 50,000



# Forced IP address in PASV / EPSV / SPSV responses. - for NAT.

# Symbolic hostnames are also taken for dynamic IP gateways

# ForcePassiveIP 192.168.0.1



# Upload / download ratio for anonymous.

# AnonymousRatio 1 10



# Upload / download ratio for all users.

# This directive does not override the previous one.

# UserRatio 1 10



# Forbid download files which are owned by “ftp”, i.e.

# Files have been uploaded but not approved by the local (local) admin.

AntiWarez yes



# IP address / port on which we are listening (default = all IP and port 21).

#Bind 192.168.254.254,21



# Maximum speed for anonymos in KB / s

# AnonymousBandwidth 8



# Maximum speed for all users (including anonymous users) in KB / s

# Use AnonymousBandwidth or UserBandwidth, use both,

# does not make sense.

# UserBandwidth 8



# Mask for created files. <umask for files>: <umask for directories>.

# 177: 077 - if you are paranoid :)

# umask is such a number, when subtracting which from the maximum (777) and

# get the right mask. those. for the case below, the masks will be, respectively:

# 644 for files, and 755 for directories

Umask 133: 022



# Minimum UID with which the user will be started.

# (In the native version there was 100. I put the tyschschu)

MinUID 1000



# Enable FXP transfer for authorized users.

AllowUserFXP no



# Allow FXP transmission for anonymous and non-anonymous.

AllowAnonymousFXP no



# Users cannot delete and modify files starting with a dot ('.')

# even if they are their owners. If TrustedGID is enabled, this group has

# access to these files.

ProhibitDotFilesWrite no



# Disable reading of files starting with a dot

ProhibitDotFilesRead no



# Never overwrite files. When the name for the uploaded file is already

# exists, it will be automatically renamed to file.1, file.2, file.3, ...

Autorename no



# Prevent anonymous users from uploading new files (no = upload allowed)

AnonymousCantUpload no



# Only connections to this IP address may not be anonymous. You

# can use this directive to use multiple IPs

# for anonymous FTP, and leave a private, secure IP for

# remote administration. also you can allow non-usable

# local IP (type 10.xxx) for authentication and leave public

# (for anonymous) FTP server on a different IP.

#TrustedIP 10.1.1.1



# If you want the PID to be added to each log line,

# then open the next line.

#LogPID yes



# Create an additional log file with a log in a format like “apache”:

# fw.c9x.org - jedi [13 / Dec / 1975: 19: 36: 39] "GET /icap.tar.bz2" 200 21808

# This log file can be processed by programs for

# analysis of the Apache logs.

# AltLog clf: /var/log/pureftpd.log



# Create an additional log file in a format that is optimized for

# statistical reports (hz how it is. It will be necessary to look)

# AltLog stats: /var/log/pureftpd.log



# Create another log with the transferred files in the W3C standard

# (compatible with many commercial analyzers)

# AltLog w3c: /var/log/pureftpd.log



# Disable the chmod command. Users will not be able to change permissions

# on files.

#NoChmod yes



# Allow users to upload but not delete files.

#KeepAllFiles yes



# Automatically create a user's home directory,

# if she is missing

#CreateHomeDir yes



# Enable virtual quota. The first number is the maximum number of files.

# The second number is the maximum size, in megabytes.

# So 1000: 10 limits each user 1000 files and 10 megs.

#Quota 1000: 10



# If pure-ftpd is compiled with support for standalone mode, you can change

# pid file location. The default position is /var/run/pure-ftpd.pid

#PIDFile /var/run/pure-ftpd.pid



# If pure-ftpd is compiled with pure-uploadscript support,

# this item allows you to write information about the new loaded

# files in /var/run/pure-ftpd.upload.pipe so that pure-uploadscript can

# read them and process the downloaded file.

#CallUploadScript yes



# This option is useful on servers where apload is allowed for anonymous.

# If / var / ftp is in a separate / var section, this allows

# save free space and protect log files. When the percentage

# fill more than specified here, apload automatic machine is prohibited.

MaxDiskUsage 99



# Set 'yes' in this option if you want to allow users

# rename files.

#NoRename yes



# Include 'customer proof': some kind of error, like 'chmod 0 public_html',

# when working together, chtol ... In short, this is not a bug but a feature ... :) And so that

# stupid clients didn’t bother your support, you need to put 'yes' in this

# paragraph. If clients have some knowledge of Unix, then this feature

# useless. If you have a hosting - turn it on.

# (the translation is almost verbatim - but I did not understand what I was talking about ...)

CustomerProof yes



# Number of parallel processes. Running current if the server was

# is compiled with the option '--with-peruserlimits' (there’s something about the fact that

# in most binary distributions it is).

# Format: <maximum sessions per user>: <maximum anonymos sessions>

# For example, 3:20 means that an authenticated user can have three

# active sessions. And for all anonymous - a maximum of 20 sessions.

#PerUserLimits 3:20



# When a file is uploaded to the server, and there is a previous version (with the same name),

# then the old file will not be deleted or truncated. Download will be made

# in a temporary file and at the end of the download will be produced atomic

# Switch to the new version of the file. For example, when loading large PHP

# script, apache will work with the old version until full download

# and immediately switch to a new one as current will be fully transmitted

# This option is incompatible with virtual quotas.

#NoTruncate yes



# This option can take three values:

# 0 - disable SSL / TLS encryption (by default).

# 1 - accept both encrypted and regular connections.

# 2 - reject connections that do not use SSL / TLS,

# including anonymous connections.

# Do not uncomment this blindly. Check that:

# 1) Server compiled with SSL / TLS support (--with-tls),

# 2) Put a valid certificate

# 3) Only compatible customers will login.

# Tls 1



# List of ciphers to be accepted for SSL / TLS connections

# Prefix -S: to completely disable SSL, but not TLS.

# TLSCipherSuite HIGH: MEDIUM: + TLSv1:! SSLv2: + SSLv3



# Listen to the current IPv4 address in standalone mode (i.e. IPv6 is disabled)

# By default, IPv4 and IPv6 are included.

IPV4Only yes



# Listen to the current IPv6 address in standalone mode (i.e. IPv4 is disabled)

# By default, IPv4 and IPv6 are included.

# IPV6Only yes



# UTF-8 support for file names (RFC 2640)

# Determine the encoding for the server's file system and, optionally,

# Default encoding for non-UTF-8 clients.

# Runs current if pure-ftpd is compiled with '--with-rfc2640'

FileSystemCharset utf-8

ClientCharset cp1251



as well as the config for Pure-FTPd to work with MySql database

pure-ftpd.conf
# MySQL config for pureftpd



# Optional: Name or IP of the MySQL server. Don't ask this

# item if a local unix socket is used.

#MYSQLServer 127.0.0.1



# Optional: The port on which MySQL hangs. Don't ask this

# item if a local unix socket is used.

#MYSQLPort 3306



# Optional: Sets the socket name mysql.sock if MySQL is on the same host.

MYSQLSocket /tmp/mysql.sock



# Required: user who climb in the database.

MYSQLUser pure-ftpd



# Required: the password of the user from whom we climb in MySQL.

MYSQLPassword pure-ftpd



# Required: DB we work with.

MYSQLDatabase pureftpd



# Required: how to save the password in the database

# Possible values: "cleartext", "crypt", "md5" and "password"

# ("Password" = MySQL password () function)

# You can use "any" to try "crypt", "md5" and "password"

MYSQLCrypt cleartext



# In the following directives, parts of the lines are replaced, up to

# query execution:

#

# \ L is replaced by the username that logs in.

# \ I is replaced by the IP address of the server on which the user climbs

# \ P is replaced by the port number with which the user connected.

# \ R is replaced by the user’s IP address.

# \ D is replaced by the IP address of the user, in the form of a long decimal number

# (e.g. 192.168.254.1 == 3232300545)

#

# You can set up relatively complex database checks using

# this set of variables. If you use one database on multiple servers,

# then "\ I" allows you to determine whether the user is breaking the server.



# Get a password from the database:

MYSQLGetPW SELECT `password` FROM` users` WHERE `user` =" \ L "AND` active` = '1'



# Get a username or UID

MYSQLGetUID SELECT `uid` FROM` users` WHERE `user` =" \ L "



# Optional: default UID - instead of checking for its extraction MYSQLGetUID

#MYSQLDefaultUID 1000



# Request to the database to get the name of the group or gid

MYSQLGetGID SELECT `gid` FROM` users` WHERE `user` =" \ L "



# Optional: default GID - instead of the query MYSQLGetGID

#MYSQLDefaultGID 1000



# Request a hamster

MYSQLGetDir SELECT `home` FROM` users` WHERE `user` =" \ L "



# Optional: Request for the maximum number of files from the user

# (I wonder - what is the deep meaning in it? To inode on

# server did not chase chol? :))

# Must be compiled with `virtual quotas support`.

MySQLGetQTAFS SELECT `QuotaFiles` FROM` users` WHERE `user` =" \ L "



# Optional: request for quota (disk usage)

# Number in megabytes.

# Pure-FTPd should be compiled with `virtual quotas support`.

MySQLGetQTASZ SELECT `QuotaSize FROM` users` WHERE `user` =" \ L "



# Optional: Relationships. Requests for download / upload ratio.

# Dol; It is compiled with this function.

MySQLGetRatio SELECT `ULRatio` FROM` users` WHERE `user` =" \ L "

MySQLGetRatioDL SELECT `DLRatio` FROM` users` WHERE `user` =" \ L "



# Optional: Channel width for user. Server must be

# compiled with this option. The value in KB / s.

MySQLGetBandwidthULULECT SELECT `ULBandwidth` FROM `users` WHERE` user` = "\ L"

MySQLGetBandwidthDL SELECT `DLBandwidth` FROM users WHERE` user` = "\ L"



# Release user from hamster (~). Never do this if:

# 1) You know exactly what you are doing.

# 2) Real and virtual users match.

#MySQLForceTildeExpansion 1



# If you updated the tables to transactional (Gemini,

# BerkeleyDB, Innobase ...), you can enable SQL transactions

# Leave locked out if using MyISAM databases,

# or the old version of MySQL (<3.23.x).

#MySQLTransactions On



Next, create the database itself ( pureftpd ) and a table with users ( users )

 CREATE TABLE `users` ( `User` varchar(50) NOT NULL DEFAULT '', `Password` varchar(250) DEFAULT '', `Uid` int(11) DEFAULT '10000', `Gid` int(11) DEFAULT '10000', `Dir` varchar(250) DEFAULT '', `QuotaFiles` int(11) DEFAULT NULL, `QuotaSize` int(11) DEFAULT '0', `ULRatio` int(11) DEFAULT '0', `DLRation` int(11) DEFAULT NULL, `ULBandwidth` int(11) DEFAULT '0', `DLBandwidth` int(11) DEFAULT '0', `Comment` tinytext, `active` int(11) DEFAULT '0', PRIMARY KEY (`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 


Add to /etc/rc.conf

 pureftpd_enable="YES" 


and run our FTP server

 /usr/local/etc/rc.d/pure-ftpd start Starting pureftpd. Running: /usr/local/sbin/pure-ftpd -g/var/run/pure-ftpd.pid -A -c50 -B -C10 -D -fftp -I15 -lmysql:/usr/local/etc/pureftpd-mysql.conf -L10000:8 -m4 -s -U133:022 -u80 -k99 -Z -8utf-8 -9cp1251 


It would seem that everything. It remains to get the user to the users table (specify login, password, home directory) and try to connect. But I was not bothered by the issue of restricting access to the user by his IP address. In the classic case, the ip field is added to the user table, and the sql query for MYSQLGetPW in pureftpd-mysql.conf takes the following form



 SELECT Password FROM users WHERE User='\L' AND ip='\R' 


But he does not suit me. Firstly, for each user you need to set the IP address from which he will connect, and secondly, you can set only one single IP. In real life, only certain users need to bind to IP's, and the ability to specify the n-th number of IP addresses for one user.



MySql syntax includes program flow control functions, among which we need the IF function



Create an IP table

 CREATE TABLE `ip` ( `user` varchar(200) DEFAULT NULL, `ip` varchar(16) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 


We give the sql query for MYSQLGetPW to the following form:

  SELECT IF((SELECT COUNT(`user`) FROM ip WHERE user='\L')=0, (SELECT Password FROM users WHERE User='\L'), (SELECT users.Password FROM users,ip WHERE users.User='\L' AND ip.ip='\R' AND ip.user='\L')) 


In the end result, all users for whom no entries in the IP table will be authenticated without checking for an IP address, and for those users who are registered in the IP table, they will check what IP address they are trying to connect to, and you can set unlimited number of IP addresses for one login

Source: https://habr.com/ru/post/183170/



All Articles