Commit 7a2bd911 authored by Jérome Perrin's avatar Jérome Perrin

proftpd: new software

parent c8dd4471
Proftpd with sftp and (one) virtual user
http://www.proftpd.org/docs/
# Features
* sftp only is enabled
* partially uploadloaded are not visible thanks to [`HiddenStores`](http://proftpd.org/docs/directives/linked/config_ref_HiddenStores.html) ( in fact they are, but name starts with `.` )
* 5 failed login attempts will cause the host to be temporary banned
# TODO
* only password login is enabled. enabling [`SFTPAuthorizedUserKeys`](http://www.proftpd.org/docs/contrib/mod_sftp.html#SFTPAuthorizedUserKeys) seems to break password only login
* log rotation
* make sure SFTPLog is useful (seems very verbose and does not contain more than stdout)
* make it easier to add users
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# But avoid directories, they are not portable.
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[instance-profile]
filename = instance.cfg.in
md5sum = c5e0ab81a715391d3774093f402935cf
[proftpd-config-file]
filename = proftpd-config-file.cfg.in
md5sum = bb7c61f06859b6f8ee13f40ae583d7ce
[buildout]
parts =
promises
publish-connection-parameter
eggs-directory = {{ buildout['eggs-directory'] }}
develop-eggs-directory = {{ buildout['develop-eggs-directory'] }}
offline = true
[instance-parameter]
recipe = slapos.cookbook:slapconfiguration
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
[slap-configuration]
# apache-frontend reads from from a part named [slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
[directory]
recipe = slapos.cookbook:mkdirectory
home = ${buildout:directory}
etc = ${:home}/etc
var = ${:home}/var
log = ${:var}/log
srv = ${:home}/srv
service = ${:etc}/service
promise = ${:etc}/promise
proftpd-dir = ${:srv}/proftpd/
ssh-authorized-keys-dir = ${:etc}/authorized_keys/
[config-file]
recipe = slapos.recipe.template:jinja2
template = {{ buildout['parts-directory'] }}/${:_buildout_section_name_}/${:_buildout_section_name_}.cfg.in
rendered = ${directory:etc}/${:_buildout_section_name_}.cfg
mode = 0644
extensions = jinja2.ext.do
[check-port-listening-promise]
recipe = slapos.cookbook:check_port_listening
path = ${directory:promise}/${:_buildout_section_name_}
[proftpd-environment]
recipe = collective.recipe.environment
# This component depends on https://nexedi.erp5.net/bug_module/20180402-716ACB/ being fixed
[proftpd-grp]
recipe = collective.recipe.grp
[proftpd-password]
recipe = slapos.cookbook:generate.password
username = proftpd
bytes = 12
[proftpd]
ipv6 = ${instance-parameter:ipv6-random}
ipv4 = ${instance-parameter:ipv4-random}
host = ${:ipv6}
sftp-port = 8022
url = sftp://[${:host}]:${:sftp-port}
data-dir = ${directory:proftpd-dir}
user=${proftpd-environment:USER}
group=${proftpd-grp:GROUP}
sftp-log=${directory:log}/proftpd-sftp.log
xfer-log=${directory:log}/proftpd-xfer.log
ban-log=${directory:log}/proftpd-ban.log
ssh-host-rsa-key=${ssh-host-rsa-key:output}
ssh-host-dsa-key=${ssh-host-dsa-key:output}
ssh-host-ecdsa-key=${ssh-host-ecdsa-key:output}
ssh-authorized-keys-dir = ${directory:ssh-authorized-keys-dir}
ban-table=${directory:srv}/proftpd-ban-table
auth-user-file=${auth-user-file:output}
recipe = slapos.cookbook:wrapper
command-line =
{{ proftpd_bin }} --nodaemon --config ${proftpd-config-file:rendered}
wrapper-path = ${directory:service}/proftpd
[proftpd-listen-promise]
<= check-port-listening-promise
hostname = ${proftpd:ipv6}
port = ${proftpd:sftp-port}
[auth-user-file]
recipe = plone.recipe.command
output = ${directory:etc}/ftpd.passwd
command =
echo ${proftpd-password:passwd} | {{ ftpasswd_bin }} --stdin --passwd --name=${proftpd-password:username} --home=${proftpd:data-dir} --shell=/bin/false --uid=`id -u` --gid=`id -g` --file ${:output}
update-command = ${:command}
[ssh-keygen-base]
recipe = plone.recipe.command
output = ${directory:etc}/${:_buildout_section_name_}
command = {{ ssh_keygen_bin }} -f ${:output} -N '' ${:extra-args}
[ssh-host-rsa-key]
<=ssh-keygen-base
extra-args=-t rsa
[ssh-host-dsa-key]
<=ssh-keygen-base
extra-args=-t dsa
[ssh-host-ecdsa-key]
<=ssh-keygen-base
extra-args=-t ecdsa -b 521
[proftpd-config-file]
<= config-file
context =
section proftpd proftpd
key slapparameter_dict slap-configuration:configuration
[promises]
recipe =
instance-promises =
${proftpd-listen-promise:path}
[publish-connection-parameter]
recipe = slapos.cookbook:publish
url = ${proftpd:url}
user = ${proftpd-password:username}
password = ${proftpd-password:passwd}
ServerName "ProFTPD SlapOS"
ServerType standalone
DefaultServer on
MaxInstances 30
DefaultAddress {{ proftpd['ipv6'] }} {{ proftpd['ipv4']}}
Port {{ proftpd['sftp-port'] }}
User {{ proftpd['user'] }}
Group {{ proftpd['group'] }}
Umask 022
AllowOverwrite on
# SFTP
SFTPEngine on
SFTPHostKey {{ proftpd['ssh-host-rsa-key'] }}
SFTPHostKey {{ proftpd['ssh-host-dsa-key'] }}
SFTPHostKey {{ proftpd['ssh-host-ecdsa-key'] }}
#SFTPAuthorizedUserKeys file:{{ proftpd['ssh-authorized-keys-dir'] }}%u
# Logging
TransferLog {{ proftpd['xfer-log'] }}
SFTPLog {{ proftpd['sftp-log'] }}
BanLog {{ proftpd['ban-log'] }}
# Virtual users
RequireValidShell off
AuthUserFile {{ proftpd['auth-user-file'] }}
# Prevent partially uploaded files to be visible
HiddenStores on
DeleteAbortedStores on
# Limitations of running as non-root user
WtmpLog off
# ( we cannot use DefaultRoot ~ )
# Prevent user for escaping their home
<Directory />
<Limit ALL>
DenyAll
</Limit>
</Directory>
<Directory {{ proftpd['data-dir'] }}>
<Limit ALL>
AllowAll
</Limit>
</Directory>
# Ban failed logins
MaxLoginAttempts 1
BanEngine on
BanTable {{ proftpd['ban-table'] }}
# 5 failed login attemps in 5 minutes -> ban for 20 minutes
BanOnEvent MaxLoginAttempts 5/00:05:00 00:20:00 "Too many Failed Login Attempts"
BanControlsACLs all allow user {{ proftpd['user'] }}
[buildout]
extends =
../../stack/slapos.cfg
../../component/openssh/buildout.cfg
../../component/proftpd/buildout.cfg
buildout.hash.cfg
versions = versions
parts =
slapos-cookbook
proftpd-config-file
instance-profile
[download-file-base]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:filename}
download-only = true
mode = 0644
[proftpd-config-file]
<= download-file-base
[instance-profile]
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:filename}
rendered = ${buildout:directory}/instance.cfg
mode = 0644
extensions = jinja2.ext.do
context =
section buildout buildout
key proftpd_bin proftpd-output:proftpd
key ftpasswd_bin proftpd-output:ftpasswd
key ssh_keygen_bin openssh-output:keygen
[versions]
collective.recipe.environment = 1.1.0
collective.recipe.grp = 1.1.0
slapos.recipe.template = 4.3
plone.recipe.command = 1.1
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment