Improve warnings.

This commit is contained in:
Adam Outler
2025-10-17 16:36:48 -04:00
parent dc444117b6
commit d11c9d7c4a
9 changed files with 111 additions and 37 deletions

View File

@@ -137,8 +137,10 @@ COPY --from=builder --chown=20212:20212 ${VIRTUAL_ENV} ${VIRTUAL_ENV}
# although it may be quicker to do it before the copy, it keeps the image # although it may be quicker to do it before the copy, it keeps the image
# layers smaller to do it after. # layers smaller to do it after.
RUN apk add libcap && \ RUN apk add libcap && \
setcap cap_net_raw+ep /bin/busybox && \
setcap cap_net_raw,cap_net_admin+eip /usr/bin/nmap && \ setcap cap_net_raw,cap_net_admin+eip /usr/bin/nmap && \
setcap cap_net_raw,cap_net_admin+eip /usr/bin/arp-scan && \ setcap cap_net_raw,cap_net_admin+eip /usr/bin/arp-scan && \
setcap cap_net_raw,cap_net_admin,cap_net_bind_service+eip /usr/bin/nbtscan && \
setcap cap_net_raw,cap_net_admin+eip /usr/bin/traceroute && \ setcap cap_net_raw,cap_net_admin+eip /usr/bin/traceroute && \
setcap cap_net_raw,cap_net_admin+eip ${VIRTUAL_ENV_BIN}/scapy && \ setcap cap_net_raw,cap_net_admin+eip ${VIRTUAL_ENV_BIN}/scapy && \
/bin/sh /build/init-nginx.sh && \ /bin/sh /build/init-nginx.sh && \

View File

@@ -12,8 +12,8 @@ services:
cap_add: # Add only the necessary capabilities cap_add: # Add only the necessary capabilities
- NET_ADMIN # Required for ARP scanning - NET_ADMIN # Required for ARP scanning
- NET_RAW # Required for raw socket operations - NET_RAW # Required for raw socket operations
security_opt: # Security options for the container - NET_BIND_SERVICE # Required to bind to privileged ports (nbtscan)
- no-new-privileges:true # Prevent privilege escalation
volumes: volumes:
- type: volume - type: volume
source: netalertx_config source: netalertx_config

View File

@@ -12,6 +12,7 @@ echo '
set -u set -u
bash /services/check-root.sh
bash /services/check-cap.sh bash /services/check-cap.sh
bash /services/check-ramdisk.sh bash /services/check-ramdisk.sh
bash /services/check-first-run-config.sh bash /services/check-first-run-config.sh

View File

@@ -2,6 +2,6 @@
# app-check.sh - Ensures /app/api/table_settings.json exists # app-check.sh - Ensures /app/api/table_settings.json exists
if [ ! -f /app/api/table_settings.json ]; then if [ ! -f /app/api/table_settings.json ]; then
mkdir -p /app/api # mkdir -p /app/api
echo -ne '{}' > /app/api/table_settings.json # echo -ne '{}' > /app/api/table_settings.json
fi fi

View File

@@ -6,20 +6,26 @@
ERROR_OUTPUT=$(nmap --privileged -sS -p 20211 127.0.0.1 2>&1 >/dev/null) ERROR_OUTPUT=$(nmap --privileged -sS -p 20211 127.0.0.1 2>&1 >/dev/null)
EXIT_CODE=$? EXIT_CODE=$?
# If the exit code is exactly 126 AND the error message contains a known permission error... # Flag common capability errors regardless of exact exit code.
if [ "$EXIT_CODE" -eq 126 ] && \ if [ "$EXIT_CODE" -ne 0 ] && \
echo "$ERROR_OUTPUT" | grep -q -e "Operation not permitted" -e "requires root privileges" echo "$ERROR_OUTPUT" | grep -q -e "Operation not permitted" -e "requires root privileges"
then then
# ...then print the detailed warning. YELLOW=$(printf '\033[1;33m')
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️" >&2 RESET=$(printf '\033[0m')
echo " ATTENTION: This container is running without elevated" >&2 >&2 printf "%s" "${YELLOW}"
echo " network privileges (NET_RAW/NET_ADMIN)." >&2 >&2 cat <<'EOF'
echo "" >&2 ══════════════════════════════════════════════════════════════════════════════
echo " Advanced network tools that require raw socket access," >&2 ⚠️ ATTENTION: Raw network capabilities are missing.
echo " like 'nmap -sS', will fail." >&2
echo "" >&2 Tools that rely on NET_RAW/NET_ADMIN/NET_BIND_SERVICE (e.g. nmap -sS,
echo " To fix this, restart the container with the following flags:" >&2 arp-scan, nbtscan) will not function. Restart the container with:
echo " --cap-add=NET_RAW --cap-add=NET_ADMIN" >&2
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️" >&2 --cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=NET_BIND_SERVICE
Without those caps, NetAlertX cannot inspect your network. Fix it before
trusting any results.
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
exit 1 exit 1
fi fi

View File

@@ -5,6 +5,17 @@
if [ ! -f /app/config/app.conf ]; then if [ ! -f /app/config/app.conf ]; then
mkdir -p /app/config mkdir -p /app/config
cp /app/back/app.conf /app/config/app.conf cp /app/back/app.conf /app/config/app.conf
echo "🆕 First run detected: Default configuration initialized." >&2 CYAN='\033[1;36m'
RESET='\033[0m'
>&2 printf "%s" "${CYAN}"
>&2 cat <<'EOF'
══════════════════════════════════════════════════════════════════════════════
🆕 First run detected. Default configuration written to /app/config/app.conf.
Review your settings in the UI or edit the file directly before trusting
this instance in production.
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
fi fi

View File

@@ -5,7 +5,18 @@
# if the db exists, exit # if the db exists, exit
test -f "${NETALERTX_DB_FILE}" && exit 0 test -f "${NETALERTX_DB_FILE}" && exit 0
echo "First run detected, creating initial database schema in ${NETALERTX_DB_FILE}" CYAN='\033[1;36m'
RESET='\033[0m'
>&2 printf "%s" "${CYAN}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
🆕 First run detected. Building initial database schema in ${NETALERTX_DB_FILE}.
Do not interrupt this step. Once complete, consider backing up the fresh
database before onboarding sensitive networks.
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
# Write all text to db file until we see "end-of-database-schema" # Write all text to db file until we see "end-of-database-schema"
cat << end-of-database-schema > ${NETALERTX_DB_FILE} cat << end-of-database-schema > ${NETALERTX_DB_FILE}

View File

@@ -1,31 +1,43 @@
#!/bin/sh #!/bin/sh
# ramdisk-check.sh - Verify critical paths are backed by ramdisk and warn on fallback storage. # storage-check.sh - Verify critical paths use dedicated mounts.
warn_if_not_ramdisk() { warn_if_not_dedicated_mount() {
path="$1" path="$1"
if awk -v target="${path}" '$5 == target {found=1} END {exit found ? 0 : 1}' /proc/self/mountinfo; then
if cat /proc/mounts| grep ${path} | grep -qE 'tmpfs|ramfs'; then
return 0 return 0
fi fi
cat >&2 <<EOF failures=1
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ YELLOW=$(printf '\033[1;33m')
ATTENTION: ${path} is not on a ramdisk. RESET=$(printf '\033[0m')
Mount this folder inside the container as tmpfs or ramfs. >&2 printf "%s" "${YELLOW}"
>&2 cat <<EOF
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: ${path} is not mounted separately inside this container.
NetAlertX expects this location to live in memory for fast reads and writes. NetAlertX runs as a single unprivileged process and pounds this directory
Running it on disk will severely degrade performance for every user. with writes. Leaving it on the container overlay will thrash storage and
slow the stack.
Fix: Please mount ${path} as tmpfs/ramfs. Fix: mount ${path} explicitly — tmpfs for ephemeral data, or bind/volume if
eg. --mount type=tmpfs,destination=${path} you want to preserve history:
Restart the container after adding the ramdisk mount. --mount type=tmpfs,destination=${path}
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ # or
--mount type=bind,src=/path/on/host,dst=${path}
Apply the mount and restart the container.
══════════════════════════════════════════════════════════════════════════════
EOF EOF
exit 1 >&2 printf "%s" "${RESET}"
} }
warn_if_not_ramdisk "${NETALERTX_API}" failures=0
warn_if_not_ramdisk "${NETALERTX_LOG}" warn_if_not_dedicated_mount "${NETALERTX_API}"
warn_if_not_dedicated_mount "${NETALERTX_LOG}"
if [ "${failures}" -ne 0 ]; then
exit 1
fi
if [ ! -f "${SYSTEM_NGINIX_CONFIG}/conf.active" ]; then if [ ! -f "${SYSTEM_NGINIX_CONFIG}/conf.active" ]; then
echo "Note: Using default listen address ${LISTEN_ADDR}:${PORT} (no ${SYSTEM_NGINIX_CONFIG}/conf.active override)." echo "Note: Using default listen address ${LISTEN_ADDR}:${PORT} (no ${SYSTEM_NGINIX_CONFIG}/conf.active override)."

View File

@@ -0,0 +1,31 @@
#!/bin/sh
# check-root.sh - ensure the container is not running as root.
CURRENT_UID="$(id -u)"
if [ "${CURRENT_UID}" -eq 0 ]; then
YELLOW=$(printf '\033[1;33m')
RESET=$(printf '\033[0m')
>&2 printf "%s" "${YELLOW}"
>&2 cat <<'EOF'
══════════════════════════════════════════════════════════════════════════════
⚠️ ATTENTION: NetAlertX is running as root (UID 0).
This defeats every hardening safeguard built into the image. You just
handed a high-value network monitoring appliance full control over your
host. If an attacker compromises NetAlertX now, the entire machine goes
with it.
Run the container as the dedicated 'netalertx' user instead:
* Keep the default USER in the image (20211:20211), or
* In docker-compose.yml, remove any 'user:' override that sets UID 0.
Bottom line: never run security tooling as root unless you are actively
trying to get pwned.
══════════════════════════════════════════════════════════════════════════════
EOF
>&2 printf "%s" "${RESET}"
exit 1
fi
exit 0