1 Commits

Author SHA1 Message Date
Tim Robinson
a77eae39d3 Fix code styling 2017-07-29 13:11:44 +10:00
11 changed files with 63 additions and 187 deletions

7
.gitignore vendored
View File

@@ -1,7 +0,0 @@
*.swp
srv/
config/
logs/
data/
.env
vsftpd.pem

View File

@@ -1,36 +1,24 @@
FROM debian:stable
FROM debian:jessie
LABEL maintainer="Luca Derderian <luca@wululu.de>"
LABEL version="${VERSION:-2.0}"
RUN groupadd -g 48 ftp && \
useradd --no-create-home --home-dir /srv -s /bin/false --uid 48 --gid 48 -c 'ftp daemon' ftp
ARG FTP_UID=48
ARG FTP_GID=48
RUN set -x \
&& groupadd -g ${FTP_GID} ftp \
&& useradd --no-create-home --home-dir /srv -s /bin/false --uid ${FTP_UID} --gid ${FTP_GID} -c 'ftp daemon' ftp \
;
RUN apt-get update \
&& apt-get install -y --no-install-recommends vsftpd db5.3-util whois \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN set -x \
&& apt-get update \
&& apt-get -y full-upgrade \
&& apt-get install -y --no-install-recommends vsftpd db-util whois gettext-base \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
;
RUN mkdir -p /var/run/vsftpd/empty /etc/vsftpd/user_conf /var/ftp /srv && \
touch /var/log/vsftpd.log && \
rm -rf /srv/ftp
RUN set -x \
&& mkdir -p /var/run/vsftpd/empty /etc/vsftpd/user_conf /var/ftp /srv /templates \
&& touch /var/log/vsftpd.log \
&& rm -rf /srv/ftp \
;
COPY vsftpd*.conf /templates/
COPY vsftpd*.conf /etc/
COPY vsftpd_virtual /etc/pam.d/
COPY *.sh /
VOLUME ["/etc/vsftpd", "/srv"]
EXPOSE 21
EXPOSE 21 4559 4560 4561 4562 4563 4564
ENTRYPOINT ["/entry.sh"]
CMD ["vsftpd"]
CMD ["vsftpd"]

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2019 Volt Grid Pty Ltd
Copyright (c) 2015 Volt Grid Pty Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -19,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,43 +1,22 @@
NAME := vsftpd
TAG := latest
IMAGE_NAME := panubo/$(NAME)
docker_tag = panubo/vsftpd
.PHONY: build build-local bash run run-ssl help push clean
help:
@printf "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)\n"
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
APP_HOST := localhost
endif
ifeq ($(UNAME_S),Darwin)
APP_HOST := $(shell docker-machine ip default)
endif
build: ## Build for publishing
docker build --pull -t $(IMAGE_NAME):$(TAG) .
build-local: ## Builds with local users UID and GID
docker build --build-arg FTP_UID=$(shell id -u) --build-arg FTP_GID=$(shell id -g) -t $(IMAGE_NAME):$(TAG) .
build:
docker build -t $(docker_tag) .
bash:
docker run --rm -it $(IMAGE_NAME):$(TAG) bash
docker run --rm -it $(docker_tag) bash
env:
@echo "FTP_USER=ftp" >> .env
@echo "FTP_PASSWORD=ftp" >> .env
vsftpd.pem:
openssl req -new -newkey rsa:2048 -days 365 -nodes -sha256 -x509 -keyout vsftpd.pem -out vsftpd.pem -subj '/CN=self_signed'
run: env
$(eval ID := $(shell docker run -d --env-file .env -v $(shell pwd)/srv:/srv ${IMAGE_NAME}:${TAG}))
run:
$(eval ID := $(shell docker run -d ${docker_tag}))
$(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID}))
@echo "Running ${ID} @ ftp://${IP}"
@docker attach ${ID}
@docker kill ${ID}
run-ssl: env vsftpd.pem
$(eval ID := $(shell docker run -d --env-file .env -v $(shell pwd)/srv:/srv -v $(PWD)/vsftpd.pem:/etc/ssl/certs/vsftpd.crt -v $(PWD)/vsftpd.pem:/etc/ssl/private/vsftpd.key ${IMAGE_NAME}:${TAG} vsftpd /etc/vsftpd_ssl.conf))
$(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID}))
@echo "Running ${ID} @ ftp://${IP}"
@docker attach ${ID}
@docker kill ${ID}
push: ## Pushes the docker image to hub.docker.com
docker push $(IMAGE_NAME):$(TAG)
clean: ## Remove built images
docker rmi $(IMAGE_NAME):$(TAG)

View File

@@ -1,63 +1,38 @@
# VSFTPD Docker Image
This is a micro-service image for VSFTPD.
[![Docker Repository on Quay.io](https://quay.io/repository/panubo/vsftpd/status "Docker Repository on Quay.io")](https://quay.io/repository/panubo/vsftpd)
[![](https://badge.imagelayers.io/panubo/vsftpd:latest.svg)](https://imagelayers.io/?images=panubo/vsftpd:latest)
It is a fork from [panubo's docker-vsftpd](https://github.com/panubo/docker-vsftpd) (thanks!) and slightly modified to suit my needs:
* Update base image to `debian:latest`
* Support for configurable min and max port in passive mode
by templating the config files (via envsubst)
This is a micro-service image for VSFTPD.
There are a few limitations but it will work if you are using host networking
`--net host` or have a direct/routed network between the Docker container and
the client.
## Virtual Users
## Virtual User
This VSFTPD container uses virtual users. Each user that logs in will have the same system UID and GID. The real users has UID and GID of 48:48 by default, however using build-args this can be changed when building the container.
For example use `--build-arg FTP_UID=1000 --build-arg FTP_GID=1000` to set the UID and GID to 1000:1000.
The FTP user has been set to uid 48 and gid 48.
## Options
The following environment variables are accepted.
- `FTP_USER`: Sets the default FTP user
- `FTP_USER`: Sets the default FTP user
- `FTP_PASSWORD`: Plain text password (not recommended), or
- `FTP_PASSWORD`: Plain text password, or
- `FTP_PASSWORD_HASH`: Sets the password for the user specified by `FTP_USER`. This
- `FTP_PASSWORD_HASH`: Sets the password for the user specified above. This
requires a hashed password such as the ones created with `mkpasswd -m sha-512`
which is in the _whois_ debian package.
- `FTP_USER_*`: Adds multiple users. Value must be in the form of `username:hash`. Should not be used in conjunction with `FTP_USER` and `FTP_PASSWORD(_HASH)`.
- `FTP_USER_*`: Adds mutliple users. Value must be in the form of `username:hash`. Should not be used in conjunction with `FTP_USER` and `FTP_PASSWORD(_HASH)`.
- `FTP_USERS_ROOT`: if set the vsftpd `local_root` will be set to `/srv/$USER` so each user is chrooted to their own directory instead of a shared one.
- `FTP_CHOWN_ROOT`: if set `chown` will be run against `/srv` setting the FTP user and group as owner and group of the directory. _Note: chown is run non-recursively ie. will only chown the root`_
- `FTP_PASV_ADDRESS`: override the IP address that vsftpd will advertise in
response to the PASV command
- `FTP_PASV_MIN_PORT`: Minimum port for passive mode (remember to bind the ports if not used with compose file)
- `FTP_PASV_MAX_PORT`: Maximum port for passive mode (remember to bind the ports if not used with compose file)
- `FTP_USERS_ROOT`: sets `local_root=/srv/$USER` so each user is chrooted to their own directory instead of a shared one.
## Usage Example
### Docker Compose
First, setup your .env file by copying the sample file and modifying it to suit your needs.
```
cp env.sample .env
vi .env
```
Then run the stack
```
docker compose up -d
```
### Docker
```
docker run --rm -it -p 21:21 -p 4559-4564:4559-4564 -e FTP_USER=ftp -e FTP_PASSWORD=ftp docker.io/panubo/vsftpd:latest
docker run --rm -it -p 21:21 -p 4559:4559 -p 4560:4560 -p 4561:4561 -p 4562:4562 -p 4563:4563 -p 4564:4564 -e FTP_USER=panubo -e FTP_PASSWORD=panubo panubo/vsftpd
```
## SSL Usage
@@ -70,19 +45,5 @@ This example assumes the ssl cert and key are in the same file and are mounted
into the container read-only.
```
docker run --rm -it \
-e FTP_USER=panubo -e FTP_PASSWORD_HASH='$6$XWpu...DwK1' \
-v `pwd`/server.pem:/etc/ssl/certs/vsftpd.crt:ro \
-v `pwd`/server.pem:/etc/ssl/private/vsftpd.key:ro \
docker.io/panubo/vsftpd vsftpd /etc/vsftpd_ssl.conf
docker run --rm -it -e FTP_USER=panubo -e FTP_PASSWORD_HASH='$6$XWpu...DwK1' -v `pwd`/server.pem:/etc/ssl/certs/vsftpd.crt:ro -v `pwd`/server.pem:/etc/ssl/private/vsftpd.key:ro panubo/vsftpd vsftpd /etc/vsftpd_ssl.conf
```
## Security
Currently `allow_writeable_chroot` is turned ON, however this isn't recommended as a security precaution. We might look at making this configurable in the future. The main consequence of turning this off is that the `local_root` can not be writable by the FTP user.
See [serverfault: vsftp: whu is allow_writable_chroot=YES a bad idea?](https://serverfault.com/q/743949/259651)
## Logs
To get the FTP logs mount `/var/log` outside of the container. For example add `-v /var/log/ftp:/var/log` to your `docker run ...` command or use `docker compose`.

View File

@@ -1,13 +1,12 @@
#!/usr/bin/env bash
# Adds a virtual ftp user to /etc/vsftpd/virtual-users.db
set -e
[[ "${DEBUG}" == "true" ]] && set -x
[[ "${DEBUG}" == 'true' ]] && set -x
DB="/etc/vsftpd/virtual-users.db"
DB=/etc/vsftpd/virtual-users.db
if [[ "${#}" -lt 2 ]] || [[ "${#}" -gt 3 ]]; then
if [[ "$#" -lt 2 || "$#" -gt 3 ]]; then
echo "Usage: $0 [-d] <user> <password>" >&2
echo >&2
echo "[ -d ] Delete the database first" >&2
@@ -21,4 +20,4 @@ if [[ "${1}" == "-d" ]]; then
shift
fi
printf '%s\n%s\n' "${1}" "${2}" | db_load -T -t hash "${DB}"
echo -e "${1}\n${2}" | db5.3_load -T -t hash "${DB}"

View File

@@ -1,16 +0,0 @@
services:
vsftpd:
container_name: vsftpd
image: wululu/vsftpd:${VERSION:-2.0}
build:
context: .
args:
VERSION: ${VERSION:-2.0}
volumes:
- ./data:/srv
- ./config:/etc/vsftpd
- ./logs:/var/log
ports:
- "${FTP_PORT:-21}:21"
- "${FTP_PASV_MIN_PORT:-4559}-${FTP_PASV_MAX_PORT:-4564}:${FTP_PASV_MIN_PORT:-4559}-${FTP_PASV_MAX_PORT:-4564}"
env_file: .env

View File

@@ -1,44 +1,29 @@
#!/usr/bin/env bash
# vsftpd container entrypoint script
set -e
[[ "${DEBUG}" == "true" ]] && set -x
# Replace variables in config files
for file in /templates/*; do
if [[ -f "$file" ]]; then
filename=$(basename "$file")
envsubst < "$file" > "/etc/$filename"
echo "Created /etc/${filename}"
fi
done
[[ "${DEBUG}" == 'true' ]] && set -x
# Generate password if hash not set
if [[ -n "${FTP_PASSWORD}" ]] && [[ -z "${FTP_PASSWORD_HASH}" ]]; then
FTP_PASSWORD_HASH="$(echo "${FTP_PASSWORD}" | mkpasswd -s -m sha-512)"
if [[ ! -z "${FTP_PASSWORD}" && -z "${FTP_PASSWORD_HASH}" ]]; then
FTP_PASSWORD_HASH=$(echo "${FTP_PASSWORD}" | mkpasswd -s -m sha-512)
fi
if [[ -n "${FTP_USER}" ]] || [[ -n "${FTP_PASSWORD_HASH}" ]]; then
if [[ ! -z "${FTP_USER}" && ! -z "${FTP_PASSWORD_HASH}" ]]; then
echo "Adding user ${FTP_USER}"
/add-virtual-user.sh -d "${FTP_USER}" "${FTP_PASSWORD_HASH}"
fi
# Support multiple users
while read -r user; do
IFS=: read -r name pass <<< "${!user}"
while read user; do
IFS=: read name pass <<< "${!user}"
echo "Adding user ${name}"
/add-virtual-user.sh "${name}" "${pass}"
done < <(env | grep "FTP_USER_" | sed 's/^\(FTP_USER_[a-zA-Z0-9]*\)=.*/\1/')
# Support user directories
if [[ -n "${FTP_USERS_ROOT}" ]]; then
# shellcheck disable=SC2016
sed -i 's/local_root=.*/local_root=\/srv\/$USER/' /etc/vsftpd*.conf
fi
# Manage /srv permissions
if [[ -n "${FTP_CHOWN_ROOT}" ]]; then
chown ftp:ftp /srv
if [[ ! -z "${FTP_USERS_ROOT}" ]]; then
sed -i 's/local_root=.*/local_root=\/srv\/$USER/' "/etc/vsftpd*.conf"
fi
vsftpd_stop() {
@@ -53,13 +38,13 @@ vsftpd_stop() {
echo "Done"
}
if [[ "${1}" == "vsftpd" ]]; then
if [[ "$1" == "vsftpd" ]]; then
trap vsftpd_stop SIGINT SIGTERM
echo "Running ${*}"
"${@}" &
pid="${!}"
echo "Running $@"
$@ &
pid="$!"
echo "${pid}" > /var/run/vsftpd/vsftpd.pid
wait "${pid}" && exit ${?}
wait "${pid}" && exit $?
else
exec "${@}"
exec "$@"
fi

View File

@@ -1,11 +0,0 @@
COMPOSE_PROJECT_NAME=vsftpd
VERSION=2.0
FTP_USER=
FTP_PASSWORD=
FTP_PORT=
FTP_PASV_ADDRESS=
FTP_PASV_MIN_PORT=
FTP_PASV_MAX_PORT=

View File

@@ -34,6 +34,5 @@ hide_ids=YES
connect_from_port_20=YES
listen=YES
tcp_wrappers=YES
pasv_address=${FTP_PASV_ADDRESS}
pasv_min_port=${FTP_PASV_MIN_PORT}
pasv_max_port=${FTP_PASV_MAX_PORT}
pasv_min_port=4559
pasv_max_port=4564

View File

@@ -15,7 +15,6 @@ user_sub_token=$USER
#local_root=/srv/$USER
local_root=/srv/
userlist_enable=NO
allow_writeable_chroot=YES
# Logging
log_ftp_protocol=YES
@@ -34,9 +33,8 @@ hide_ids=YES
connect_from_port_20=YES
listen=YES
tcp_wrappers=YES
pasv_address=${FTP_PASV_ADDRESS}
pasv_min_port=${FTP_PASV_MIN_PORT}
pasv_max_port=${FTP_PASV_MAX_PORT}
pasv_min_port=4559
pasv_max_port=4564
# SSL
ssl_enable=Yes