better-semaphore-handling

This commit is contained in:
SkyperTHC 2022-08-02 11:07:05 +01:00
parent 0b5ad0012a
commit 7b70a9e052
No known key found for this signature in database
GPG Key ID: A9BD386DF9113CD6
5 changed files with 97 additions and 40 deletions

@ -37,7 +37,7 @@ http {
index index.html index.htm;
}
location / {
root /srv/www;
root /sec/www;
index index.html index.htm;
autoindex on;
#autoindex_exact_size off;

@ -1,11 +1,11 @@
version: "3.7"
services:
# EncFS for /onion and /everyone
sf-encfs:
# EncFS for /onion
sf-encfs-www:
build: encfs
image: sf-encfs
restart: ${SF_RESTART:-on-failure}
init: true
cap_add:
- SYS_ADMIN
security_opt:
@ -13,14 +13,35 @@ services:
environment:
- SF_SEED
- SF_DEBUG
command: ["/mount.sh", "server"]
command: ["/mount.sh", "server", "www"]
network_mode: none
devices:
- "/dev/fuse:/dev/fuse"
volumes:
- "${SF_BASEDIR:-.}/config/etc/seed:/config/etc/seed"
- "${SF_BASEDIR:-.}/data/sf:/encfs/raw"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/sf:/encfs/sec:shared"
- "${SF_BASEDIR:-.}/data/www-root:/raw"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/www-root:/sec:shared"
# EncFS for /everyone
sf-encfs-everyone:
build: encfs
image: sf-encfs
restart: ${SF_RESTART:-on-failure}
cap_add:
- SYS_ADMIN
security_opt:
- apparmor:unconfined
environment:
- SF_SEED
- SF_DEBUG
command: ["/mount.sh", "server", "everyone"]
network_mode: none
devices:
- "/dev/fuse:/dev/fuse"
volumes:
- "${SF_BASEDIR:-.}/config/etc/seed:/config/etc/seed"
- "${SF_BASEDIR:-.}/data/everyone-root:/raw"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/everyone-root:/sec:shared"
dns-doh:
image: crazymax/cloudflared
@ -152,7 +173,7 @@ services:
ipv4_address: 172.20.0.110
depends_on:
- dnsmasq
- sf-encfs
- sf-encfs-everyone
restart: ${SF_RESTART:-on-failure}
init: true
dns: 255.255.255.255
@ -176,21 +197,21 @@ services:
- "${SF_BASEDIR:-.}/config/etc/seed:/config/etc/seed"
- "${SF_BASEDIR:-.}/config/etc/info:/config/etc/info:ro"
- "${SF_BASEDIR:-.}/sfbin:/sf/bin:ro"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/sf:/sec:slave"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/everyone-root:/sec:slave"
- "/var/run/docker.sock:/var/run/docker.sock"
nginx:
image: nginx
restart: ${SF_RESTART:-on-failure}
depends_on:
- sf-encfs
entrypoint: ["/wait_semaphore.sh", "/srv/www/.IS-ENCRYPTED", "nginx", "-g", "daemon off;"]
- sf-encfs-www
entrypoint: ["/sf/bin/wait_semaphore.sh", "/sec/.IS-ENCRYPTED", "nginx", "-g", "daemon off;"]
dns: 255.255.255.255
networks:
nginx-net:
volumes:
- "${SF_BASEDIR:-.}/sfbin/wait_semaphore.sh:/wait_semaphore.sh"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/sf/onion-www:/srv/www:slave,ro"
- "${SF_BASEDIR:-.}/sfbin/wait_semaphore.sh:/sf/bin/wait_semaphore.sh"
- "${SF_SHMDIR:-/dev/shm/sf}/encfs-sec/www-root:/sec:slave,ro"
- "${SF_BASEDIR:-.}/config/etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
networks:

@ -11,12 +11,20 @@ CR="\e[1;31m" # red
# CC="\e[1;36m" # cyan
# CN="\e[0m" # none
do_exit()
{
fusermount -zu /sec
[[ -n $cpid ]] && kill "$cpid" # This will unmount
unset cpid
[[ -n "$PASSFILE" ]] && [[ -e "$PASSFILE" ]] && rm -rf "${PASSFILE:?}"
exit "$1"
}
# Handle SIGTERM. Send TERM to encfs when docker-compose shuts down, unmount
# and exit.
_term()
{
[[ -z $cpid ]] && exit
kill "$cpid" # This will unmount
do_exit 0
}
create_load_seed()
@ -39,34 +47,51 @@ sf_server_init()
ENCFS_SERVER_PASS=$(echo -n "EncFS-SERVER-PASS-${SF_SEED}" | sha512sum | base64 | tr -dc '[:alpha:]' | head -c 24)
}
# The server needs to be initialized differently. All instances are started
# from docker compose. Some are started before EncFS can mount the directory.
# NgingX is a good example. Thus Nginx needs to check unti IS-ENCRYPTED.TXT
# NgingX is a good example. Thus Nginx needs to check until .ENCRYPTED.TXT
# appears and exit otherwise.
# We must start EncFS as a child so that we can use 'wait $cpid' or otherwise
# we dont get the SIGTERM when the intance shuts down (sleep does not get it)
# and encfs would get a SIGKILL (e.g. thus not able to unmount /sec)
sf_server()
{
sf_server_init
echo "THIS-IS-NOT-ENCRYPTED *** DO NOT USE *** " >/encfs/sec/IS-NOT-ENCRYPTED.txt
encfs --standard -o nonempty -o allow_other -f --extpass="echo \"${ENCFS_SERVER_PASS}\"" "/encfs/raw" "/encfs/sec" -- -o noexec,noatime &
[[ -f /sec/.IS-ENCRYPTED ]] && rm -f /sec/.IS-ENCRYPTED
echo "THIS-IS-NOT-ENCRYPTED *** DO NOT USE *** " >/sec/IS-NOT-ENCRYPTED.txt || { echo "Could not create Markfile"; exit 138; }
PASSFILE="/dev/shm/pass.txt"
echo "${ENCFS_SERVER_PASS}" >"${PASSFILE}"
bash -c "exec -a '[encfs-${2:-BAD}]' encfs -f --standard --public -o nonempty -S \"/raw\" \"/sec\" -- -o noexec,noatime" <"${PASSFILE}" &
cpid=$!
# Wait until it's mounted. Then mark directories with .IS-ENCRYPTED
# Wait until /sec is mounted. Then mark directories with .IS-ENCRYPTED
while :; do
[[ ! -e /encfs/sec/IS-NOT-ENCRYPTED.txt ]] && break
[[ ! -e /sec/IS-NOT-ENCRYPTED.txt ]] && break
kill -0 $cpid || do_exit 128 # bash or EncFS died
sleep 0.5
done
[[ ! -d /encfs/sec/onion-www ]] && mkdir /encfs/sec/onion-www
[[ ! -d /encfs/sec/everyone ]] && mkdir /encfs/sec/everyone
touch /encfs/sec/onion-www/.IS-ENCRYPTED
touch /encfs/sec/.IS-ENCRYPTED
# We must delete PASSFILE _after_ mounting is complete.
# Otherwise 'bash' starts in the background (but before it calls EncFS) and the current (parent)
# bash would delete the filename
rm -f "${PASSFILE:?}"
[[ -n $2 ]] && [[ ! -d "/sec/${2}" ]] && mkdir "/sec/${2}"
touch /sec/.IS-ENCRYPTED
wait $cpid # SIGTERM will wake us
# SIGTERM or wrong SF_SEED
echo -e "${CR}[$cpid] EncFS EXITED with $?..."
do_exit 0 # exit with 0: Do not restart.
fusermount -zu /encfs/sec
exit 0
# BusyBox cant use custom process name for 'sleep':
# exec -a [sleep-1234] sleep infinity => applet not found
# bash executes 'sleep' (symlink to /bin/busybox) with with argv[0] == [sleep-1234]
# Dont use 'exec'. SIGTERM needs to return to this bash so we can
# terminate encfs.
}
# Wait until MARKFILE (on /sec cleartext) has disappeared.
@ -87,7 +112,7 @@ check_markfile()
}
# For the 'server'
[[ "$1" = "server" ]] && sf_server
[[ "$1" = "server" ]] && sf_server "$@"
RAWDIR="/encfs/raw/user-${LID}"
# SECDIR="/encfs/sec/user-${LID}" # typically on host: /dev/shm/encfs-sec/user-${LID}
@ -101,9 +126,10 @@ echo "THIS-IS-NOT-ENCRYPTED *** DO NOT USE *** " >"${SECDIR}/THIS-DIRECTORY-IS-N
PASSFILE="/dev/shm/pass-${LID}.txt"
echo "${LENCFS_PASS}" >"${PASSFILE}"
bash -c "exec -a '[encfs-${LID}]' encfs --standard --public -o nonempty -o allow_other -S \"${RAWDIR}\" \"${SECDIR}\" <\"${PASSFILE}\""
bash -c "exec -a '[encfs-${LID}]' encfs --standard --public -o nonempty -S \"${RAWDIR}\" \"${SECDIR}\" <\"${PASSFILE}\""
ret=$?
rm -f "${PASSFILE:?}"
# encfs --standard --public -o nonempty -o allow_other --extpass="echo \"${LENCFS_PASS}\"" "${RAWDIR}" "${SECDIR}"
[[ $ret -ne 0 ]] && exit 124
# Give segfaultsh time to start guest shell instance
sleep 5
@ -116,7 +142,6 @@ while :; do
done
echo "Unmounting lg-${LID} [${SECDIR}]"
# fusermount -zuq "${SECDIR}" || echo "fusermount: Error ($?)"
fusermount -zu "${SECDIR}" || echo "fusermount: Error ($?)"
rmdir "${SECDIR:-/dev/null/BAD}" 2>/dev/null
echo "DONE"

@ -198,7 +198,8 @@ MARKFILE="THIS-DIRECTORY-IS-NOT-ENCRYPTED--DO-NOT-USE.txt"
[[ -z $SF_SEED ]] && ERREXIT 244 "SF_SEED= is not set."
[[ -f "/sec/IS-NOT-ENCRYPTED.txt" ]] && ERREXIT 243 "System not ready yet (wrong EncFS password. Please inform the admin to set correct SF_SEED)"
# Check if share got unmounted (e.g. EncFS died)
[[ ! -f "/sec/.IS-ENCRYPTED" ]] && ERREXIT 243 "System not ready yet (wrong EncFS password. Please inform the admin to set correct SF_SEED)"
mk_hostname
@ -324,6 +325,8 @@ exec_devnull docker run \
--init \
--name "lg-${LID}" \
--init \
`# --cap-drop=NET_RAW \ --Needed for ping etc. ` \
--cap-drop=MKNOD \
--net sf-guest \
--dns "${SF_DNS:-BAD}" \
--env SF_SEC="${SF_SEC}" \
@ -344,8 +347,8 @@ exec_devnull docker run \
--mount type=bind,source="${SF_SHMDIR}/run/vpn,target=/sf/run/vpn,readonly" \
--mount type=bind,source="${SF_SHMDIR}/run/gsnc/access-22.txt,target=/sf/run/gsnc-access-22.txt,readonly" \
-v "${SF_SHMDIR}/encfs-sec/user-${LID}:/sec:slave" \
-v "${SF_SHMDIR}/encfs-sec/sf/everyone:/everyone:slave" \
-v "${SF_SHMDIR}/encfs-sec/sf/onion-www/${SF_HOSTNAME,,}:/onion:slave" \
-v "${SF_SHMDIR}/encfs-sec/everyone-root/everyone:/everyone:slave" \
-v "${SF_SHMDIR}/encfs-sec/www-root/www/${SF_HOSTNAME,,}:/onion:slave" \
--mount type=bind,source="${SF_BASEDIR}/config/etc/info/WARNING---SHARED-BETWEEN-ALL-SERVERS---README.txt,target=/everyone/WARNING---SHARED-BETWEEN-ALL-SERVERS---README.txt,readonly" \
-d \
"sf-guest${SF_GUEST_CONTAINER_NAME_SUFFIX}" /sf/bin/sf-destructor.sh || ERREXIT 251 "Failed to set up guest instance..."

@ -2,16 +2,24 @@
# EXIT unless "$2" exists.
#
# This is used by Nginx to keep restarting until the EncFS
# is fully mounted.
# This is used by Nginx and sf-host to wait until EncFS
# has fully mounted the encrypted drives.
trap "exit 255" SIGTERM
sem="$1"
shift 1
# echo "Waiting for Semaphore '${sem}' before starting '$*'"
[[ -e "${sem}" ]] && exec "$@"
sleep 1
echo "Semaphore '${sem}' does not yet exist. Exiting. Will Restart."
[[ ! -f "${sem}" ]] && echo "Waiting for Semaphore '${sem}' before starting '$*'"
n=0
while :; do
[[ -n $SF_DEBUG ]] && echo "Round #${n}"
[[ -e "${sem}" ]] && { echo "Found after #${n} rounds..."; exec "$@"; }
n=$((n+1))
[[ $n -gt 10 ]] && break
sleep 1
done
echo "Semaphore '${sem}' does not yet exist. Exiting."
exit 123