Compare commits
20 Commits
5eaede5ca8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
3f6d7c34d5
|
|||
|
76f62bafb1
|
|||
|
9c460b101e
|
|||
|
a4203ed149
|
|||
|
f799ffadb4
|
|||
|
7758e98bd3
|
|||
|
25eb14f93b
|
|||
|
f4c0042ab2
|
|||
|
6ed58a676f
|
|||
|
799895baa0
|
|||
|
dcf768fd21
|
|||
|
9137f439f1
|
|||
|
fade210106
|
|||
|
e1e1e1ee29
|
|||
|
8dcdd4a30a
|
|||
|
8289114ee6
|
|||
|
9fca459f93
|
|||
|
d5c00a0308
|
|||
|
08134aefa5
|
|||
|
e92da50d28
|
166
.drone.yml
166
.drone.yml
@@ -1,166 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: linux-amd64
|
||||
|
||||
platform:
|
||||
arch: amd64
|
||||
os: linux
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
dry_run: true
|
||||
repo: docker.asperti.com/paspo/ftps
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
||||
- name: build_and_publish
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
force_tag: true
|
||||
password:
|
||||
from_secret: docker_password
|
||||
registry: docker.asperti.com
|
||||
repo: docker.asperti.com/paspo/ftps
|
||||
username:
|
||||
from_secret: docker_username
|
||||
tags:
|
||||
- ${DRONE_TAG}-linux-amd64
|
||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-amd64
|
||||
- ${DRONE_SEMVER_MAJOR}-linux-amd64
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
- name: build_and_publish2
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
force_tag: true
|
||||
password:
|
||||
from_secret: gitea_docker_password
|
||||
registry: git.asperti.com
|
||||
repo: git.asperti.com/paspo/docker-ftps
|
||||
username:
|
||||
from_secret: gitea_docker_username
|
||||
tags:
|
||||
- ${DRONE_TAG}-linux-amd64
|
||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-amd64
|
||||
- ${DRONE_SEMVER_MAJOR}-linux-amd64
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: linux-arm64
|
||||
|
||||
platform:
|
||||
arch: arm64
|
||||
os: linux
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: plugins/docker:linux-arm64
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
dry_run: true
|
||||
repo: docker.asperti.com/paspo/ftps
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
||||
- name: build_and_publish
|
||||
image: plugins/docker:linux-arm64
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
force_tag: true
|
||||
password:
|
||||
from_secret: docker_password
|
||||
registry: docker.asperti.com
|
||||
repo: docker.asperti.com/paspo/ftps
|
||||
username:
|
||||
from_secret: docker_username
|
||||
tags:
|
||||
- ${DRONE_TAG}-linux-arm64
|
||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-arm64
|
||||
- ${DRONE_SEMVER_MAJOR}-linux-arm64
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
- name: build_and_publish2
|
||||
image: plugins/docker:linux-arm64
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
force_tag: true
|
||||
password:
|
||||
from_secret: gitea_docker_password
|
||||
registry: git.asperti.com
|
||||
repo: git.asperti.com/paspo/docker-ftps
|
||||
username:
|
||||
from_secret: gitea_docker_username
|
||||
tags:
|
||||
- ${DRONE_TAG}-linux-arm64
|
||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-arm64
|
||||
- ${DRONE_SEMVER_MAJOR}-linux-arm64
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: manifest
|
||||
|
||||
steps:
|
||||
- name: manifest
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
force_tag: true
|
||||
ignore_missing: true
|
||||
spec: manifest.tmpl
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
tags:
|
||||
- latest
|
||||
- ${DRONE_TAG}
|
||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}
|
||||
- ${DRONE_SEMVER_MAJOR}
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
- name: manifest2
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
force_tag: true
|
||||
ignore_missing: true
|
||||
spec: manifest2.tmpl
|
||||
username:
|
||||
from_secret: gitea_docker_username
|
||||
password:
|
||||
from_secret: gitea_docker_password
|
||||
tags:
|
||||
- latest
|
||||
- ${DRONE_TAG}
|
||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}
|
||||
- ${DRONE_SEMVER_MAJOR}
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
depends_on:
|
||||
- linux-amd64
|
||||
- linux-arm64
|
||||
73
.gitea/workflows/build_and_publish.yaml
Normal file
73
.gitea/workflows/build_and_publish.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: Container Publish
|
||||
|
||||
env:
|
||||
REGISTRY: docker.asperti.com
|
||||
REPOSITORY: paspo/ftps
|
||||
|
||||
on:
|
||||
push:
|
||||
schedule:
|
||||
- cron: "0 12 * * 3"
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
workflow_run:
|
||||
workflows: [vulnscan.yaml]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
on-success-skip:
|
||||
runs-on:
|
||||
labels: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- run: exit_with_success
|
||||
|
||||
build-image:
|
||||
runs-on:
|
||||
labels: [ubuntu-latest, "arch-${{ matrix.arch }}"]
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [amd64, arm64]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and publish
|
||||
run: |
|
||||
docker build \
|
||||
--tag ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }} \
|
||||
--platform linux/${{ matrix.arch }} --no-cache -f Dockerfile .
|
||||
docker push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }}
|
||||
|
||||
manifest:
|
||||
name: update docker manifest
|
||||
needs: build-image
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
|
||||
steps:
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: latest
|
||||
run: |
|
||||
docker manifest create \
|
||||
${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest \
|
||||
--amend ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-amd64 \
|
||||
--amend ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-arm64
|
||||
docker manifest push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest
|
||||
64
.gitea/workflows/vulnscan.yaml
Normal file
64
.gitea/workflows/vulnscan.yaml
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
name: Vulnerability Scan
|
||||
|
||||
env:
|
||||
REGISTRY: docker.asperti.com
|
||||
REPOSITORY: paspo/ftps
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 14 * * *"
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
workflow_run:
|
||||
workflows: [build_and_publish.yaml]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
scan:
|
||||
name: Daily Vulnerability Scan
|
||||
runs-on:
|
||||
labels: [ubuntu-latest, "arch-${{ matrix.arch }}"]
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [amd64, arm64]
|
||||
|
||||
steps:
|
||||
- name: Pull docker image
|
||||
run: docker pull ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest
|
||||
|
||||
- name: Setup trivy
|
||||
run: |
|
||||
echo "Installing Trivy for arch: $(uname -m)"
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
wget -O /tmp/trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.2/trivy_0.58.2_Linux-64bit.deb ;;
|
||||
aarch64)
|
||||
wget -O /tmp/trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.2/trivy_0.58.2_Linux-ARM64.deb ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
dpkg -i /tmp/trivy.deb
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
id: scan
|
||||
run: |
|
||||
trivy --server ${{ secrets.TRIVY_SERVER }} --token ${{ secrets.TRIVY_TOKEN }} image --format json ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest > trivy-results.json
|
||||
|
||||
# if some vulnerability is found, we fail
|
||||
- name: check output
|
||||
id: vulncount
|
||||
run: |
|
||||
echo "VULNCOUNT=$(jq '.Results[0].Vulnerabilities|length' trivy-results.json)" >> ${GITHUB_OUTPUT}
|
||||
if [ $(jq '.Results[0].Vulnerabilities|length' trivy-results.json) -ne "0" ] ; then exit 1 ; fi
|
||||
|
||||
- name: send telegram notification
|
||||
if: failure()
|
||||
uses: appleboy/telegram-action@master
|
||||
with:
|
||||
to: ${{ secrets.TELEGRAM_TO }}
|
||||
token: ${{ secrets.TELEGRAM_TOKEN }}
|
||||
format: markdown
|
||||
message: |
|
||||
Found **${{ steps.vulncount.outputs.VULNCOUNT }}** vulnerabilities in `${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest`
|
||||
@@ -1,9 +1,15 @@
|
||||
FROM alpine:latest
|
||||
|
||||
RUN \
|
||||
apk -U add proftpd proftpd-mod_tls proftpd-mod_ifsession proftpd-utils openssl perl acme.sh && \
|
||||
apk --no-cache upgrade && \
|
||||
apk --no-cache add proftpd proftpd-mod_tls proftpd-mod_ifsession \
|
||||
proftpd-mod_deflate proftpd-mod_geoip proftpd-mod_sql_sqlite \
|
||||
proftpd-utils openssl perl acme.sh lftp sqlite && \
|
||||
mkdir -p /var/run/proftpd /etc/proftpd/custom.conf.d/
|
||||
|
||||
COPY rootfs /
|
||||
|
||||
HEALTHCHECK --interval=2m --timeout=3s \
|
||||
CMD /app/healthcheck.sh || exit 1
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
|
||||
52
README.md
52
README.md
@@ -144,3 +144,55 @@ docker exec -ti my-ftps ftpasswd --passwd --name=paolo --uid=1000 --home=/home/p
|
||||
```
|
||||
|
||||
You also have to create and chown the user's home folder.
|
||||
|
||||
## sql db for user authentication
|
||||
|
||||
It is possible to use a sqlite db for user authentication, just add `SQLITE_AUTH=1` to the environment:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
services:
|
||||
ftps-server:
|
||||
image: docker.asperti.com/paspo/ftps
|
||||
restart: always
|
||||
ports:
|
||||
- "21:21"
|
||||
- "20:20"
|
||||
- "21210-21220:21210-21220"
|
||||
volumes:
|
||||
- "/srv/ftps/auth:/auth"
|
||||
- "/srv/ftps/conf:/etc/proftpd/custom.conf.d:ro"
|
||||
- "/srv/ftps/data:/home"
|
||||
- "/etc/letsencrypt:/certs:ro"
|
||||
environment:
|
||||
- SQLITE_AUTH=1
|
||||
- MASQUERADE=ftp.mydomain.com
|
||||
- PASSIVEPORTS_START=21210
|
||||
- PASSIVEPORTS_END=21220
|
||||
- MAXCLIENTS=500
|
||||
- MAXCLIENTSPERHOST=100
|
||||
- TLS_CERT=/certs/live/ftp.mydomain.com/cert.pem
|
||||
- TLS_KEY=/certs/live/ftp.mydomain.com/privkey.pem
|
||||
- TLS_CHAIN=/certs/live/ftp.mydomain.com/chain.pem
|
||||
```
|
||||
|
||||
Now, instead of using `/auth/passwd`, proftpd is using `/auth/ftpd.db`.
|
||||
To create a new user, you must now update this db.
|
||||
|
||||
To create a new user:
|
||||
|
||||
```bash
|
||||
docker exec -ti my-ftps sqlite3 sqlite3 /auth/ftpd.db <<EOF
|
||||
INSERT OR IGNORE INTO users (userid,passwd,uid,gid,homedir,shell) VALUES ('new_user','',1000,1000,'/home/new_user','/bin/false');
|
||||
INSERT OR IGNORE INTO groups (groupname,gid,members) VALUES ('new_user',1000,'new_user');
|
||||
EOF
|
||||
```
|
||||
|
||||
To update a password:
|
||||
|
||||
```bash
|
||||
PASSWD_SHA=$(echo -n ChangeThisPass | mkpasswd -m sha512)
|
||||
docker exec -ti my-ftps sqlite3 sqlite3 /auth/ftpd.db <<EOF
|
||||
UPDATE users SET passwd='$PASSWD_SHA' WHERE userid='new_user';
|
||||
EOF
|
||||
```
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
image: docker.asperti.com/paspo/ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: docker.asperti.com/paspo/ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: docker.asperti.com/paspo/ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
variant: v8
|
||||
architecture: arm64
|
||||
os: linux
|
||||
@@ -1,19 +0,0 @@
|
||||
image: git.asperti.com/paspo/docker-ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: git.asperti.com/paspo/docker-ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: git.asperti.com/paspo/docker-ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
variant: v8
|
||||
architecture: arm64
|
||||
os: linux
|
||||
@@ -23,6 +23,8 @@ if [ ! -f "/acme/cert/cert.pem" ] ; then
|
||||
--key-file /acme/cert/privkey.pem \
|
||||
--fullchain-file /acme/cert/chain.pem \
|
||||
--reloadcmd /app/acme-refresh-cert.sh ${ACME_EMAIL}
|
||||
echo "Certificate ready"
|
||||
else
|
||||
/app/acme-refresh-cert.sh
|
||||
echo "Certificate ready"
|
||||
fi
|
||||
|
||||
@@ -3,3 +3,6 @@
|
||||
if [ "$ENABLE_ACME" = "1" ] ; then
|
||||
/usr/bin/acme.sh --cron --home /acme
|
||||
fi
|
||||
|
||||
############ RELOAD
|
||||
pidof proftpd >/dev/null && killall -HUP proftpd
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
############ CREATE DIRS
|
||||
mkdir -p /auth /logs
|
||||
chown proftpd /auth /logs
|
||||
chmod u+rw /auth /logs
|
||||
chmod g-w /auth /logs
|
||||
|
||||
############ MASQUERADE
|
||||
MASQUERADE=${MASQUERADE:-127.0.0.1}
|
||||
echo "MasqueradeAddress ${MASQUERADE}" > /etc/proftpd/conf.d/masquerade.conf
|
||||
@@ -29,6 +35,42 @@ else
|
||||
/app/cert-init.sh
|
||||
fi
|
||||
|
||||
############ INIT DB if needed
|
||||
SQLITE_AUTH=${SQLITE_AUTH:-no}
|
||||
if [ "$SQLITE_AUTH" = "1" ] ; then
|
||||
if [ ! -f /auth/ftpd.db ] ; then
|
||||
sqlite3 /auth/ftpd.db < /app/init.sql
|
||||
fi
|
||||
fi
|
||||
|
||||
############ GENERATE RANDOM PASSWORD FOR HEALTHCHECK
|
||||
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 20 > /app/healthcheck.pwd
|
||||
chmod 600 /app/healthcheck.pwd
|
||||
|
||||
############ UPDATE HEALTHCHECK CREDS
|
||||
HEALTHCHECK_UID=1999
|
||||
mkdir -p /home/healthcheck
|
||||
chown ${HEALTHCHECK_UID}:${HEALTHCHECK_UID} /home/healthcheck
|
||||
if [ "$SQLITE_AUTH" = "1" ] ; then
|
||||
PASSWD_SHA=$(cat /app/healthcheck.pwd | mkpasswd -m sha512)
|
||||
sqlite3 /auth/ftpd.db <<EOF
|
||||
INSERT OR IGNORE INTO users (userid,passwd,uid,gid,homedir,shell) VALUES ('healthcheck','',${HEALTHCHECK_UID},${HEALTHCHECK_UID},'/home/healthcheck','/bin/false');
|
||||
INSERT OR IGNORE INTO groups (groupname,gid,members) VALUES ('healthcheck',${HEALTHCHECK_UID},'healthcheck');
|
||||
UPDATE users SET passwd='$PASSWD_SHA' WHERE userid='healthcheck';
|
||||
EOF
|
||||
else
|
||||
cat /app/healthcheck.pwd | ftpasswd --stdin --passwd --name=healthcheck \
|
||||
--uid=${HEALTHCHECK_UID} \
|
||||
--home=/home/healthcheck --sha512 --shell=/bin/false --file=/auth/passwd
|
||||
fi
|
||||
|
||||
############ CONFIGURE AUTH
|
||||
if [ "$SQLITE_AUTH" = "1" ] ; then
|
||||
echo "AuthOrder mod_sql.c" > /etc/proftpd/conf.d/auth.conf
|
||||
else
|
||||
echo "AuthOrder mod_auth_file.c" > /etc/proftpd/conf.d/auth.conf
|
||||
fi
|
||||
|
||||
############ START CRON
|
||||
crond -b
|
||||
|
||||
|
||||
7
rootfs/app/healthcheck.sh
Executable file
7
rootfs/app/healthcheck.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
USER=healthcheck
|
||||
LFTP_PASSWORD=$(cat /app/healthcheck.pwd)
|
||||
|
||||
lftp -e "set ssl-allow true; set ftp:ssl-force true; set ftp:passive-mode true; set ssl:verify-certificate false; set net:timeout 5; set net:max-retries 1; open -u ${USER},${LFTP_PASSWORD} ftp://127.0.0.1; ls; bye" > /dev/null
|
||||
echo $?
|
||||
14
rootfs/app/init.sql
Normal file
14
rootfs/app/init.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
CREATE TABLE `users` (
|
||||
userid VARCHAR(30) NOT NULL UNIQUE,
|
||||
passwd VARCHAR(80) NOT NULL,
|
||||
uid INTEGER UNIQUE,
|
||||
gid INTEGER,
|
||||
homedir VARCHAR(255),
|
||||
shell VARCHAR(255),
|
||||
last_accessed DATETIME
|
||||
);
|
||||
CREATE TABLE `groups` (
|
||||
groupname VARCHAR(30) NOT NULL UNIQUE,
|
||||
gid INTEGER NOT NULL,
|
||||
members VARCHAR(255)
|
||||
);
|
||||
@@ -1,4 +1,3 @@
|
||||
AuthOrder mod_auth_file.c
|
||||
AuthUserFile /auth/passwd
|
||||
RequireValidShell off
|
||||
ScoreBoardFile /run/proftpd/scoreboard
|
||||
@@ -23,4 +22,28 @@ DefaultRoot ~
|
||||
DelayTable /run/proftpd/proftpd.delay
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_deflate.c>
|
||||
DeflateEngine on
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_sql.c>
|
||||
<IfModule mod_sql_sqlite.c>
|
||||
SQLBackend sqlite3
|
||||
SQLConnectInfo /auth/ftpd.db
|
||||
SQLEngine On
|
||||
SQLAuthenticate users
|
||||
SQLAuthTypes OpenSSL Crypt
|
||||
SQLUserInfo users userid passwd uid gid homedir shell
|
||||
SQLGroupInfo groups groupname gid members
|
||||
|
||||
SQLNamedQuery last_accessed UPDATE "last_accessed = DATETIME('now') WHERE userid='%u'" users
|
||||
SQLLog PASS last_accessed
|
||||
SQLMinId 33
|
||||
SQLDefaultUID 33
|
||||
SQLDefaultGID 33
|
||||
|
||||
RequireValidShell off
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
Include /etc/proftpd/custom.conf.d/
|
||||
|
||||
56
rootfs/etc/proftpd/proftpd.conf
Normal file
56
rootfs/etc/proftpd/proftpd.conf
Normal file
@@ -0,0 +1,56 @@
|
||||
# This is the directory where DSO modules reside
|
||||
ModulePath /usr/lib/proftpd
|
||||
|
||||
# Allow only user root to load and unload modules, but allow everyone
|
||||
# to see which modules have been loaded
|
||||
ModuleControlsACLs insmod,rmmod allow user root
|
||||
ModuleControlsACLs lsmod allow user *
|
||||
|
||||
Include /etc/proftpd/modules.d/
|
||||
|
||||
ServerName "ProFTPD Default Installation"
|
||||
ServerType standalone
|
||||
|
||||
# Port 21 is the standard FTP port.
|
||||
Port 21
|
||||
|
||||
# Don't use IPv6 support by default.
|
||||
UseIPv6 off
|
||||
|
||||
# Umask 022 is a good standard umask to prevent new dirs and files
|
||||
# from being group and world writable.
|
||||
Umask 022
|
||||
|
||||
# To prevent DoS attacks, set the maximum number of child processes
|
||||
# to 30. If you need to allow more than 30 concurrent connections
|
||||
# at once, simply increase this value. Note that this ONLY works
|
||||
# in standalone mode, in inetd mode you should use an inetd server
|
||||
# that allows you to limit maximum number of processes per service
|
||||
# (such as xinetd).
|
||||
MaxInstances 30
|
||||
|
||||
# Set the user and group under which the server will run.
|
||||
User proftpd
|
||||
Group proftpd
|
||||
|
||||
# To cause every FTP user to be "jailed" (chrooted) into their home
|
||||
# directory, uncomment this line.
|
||||
#DefaultRoot ~
|
||||
|
||||
# Normally, we want files to be overwriteable.
|
||||
AllowOverwrite on
|
||||
|
||||
DefaultServer on
|
||||
ShowSymlinks on
|
||||
|
||||
TimeoutNoTransfer 600
|
||||
TimeoutStalled 600
|
||||
TimeoutIdle 1200
|
||||
|
||||
DisplayLogin welcome.msg
|
||||
DisplayChdir .message true
|
||||
ListOptions "-l"
|
||||
|
||||
DenyFilter \*.*/
|
||||
|
||||
Include /etc/proftpd/conf.d/
|
||||
4
rootfs/etc/shells
Normal file
4
rootfs/etc/shells
Normal file
@@ -0,0 +1,4 @@
|
||||
# valid login shells
|
||||
/bin/sh
|
||||
/bin/ash
|
||||
/bin/false
|
||||
Reference in New Issue
Block a user