commit 0e9d62e219f59390f6a4f93974668a29c7683345 Author: javara999 Date: Thu Sep 3 10:06:30 2026 +0900 Add malware-watch installer bundle diff --git a/.env b/.env new file mode 100644 index 0000000..b753356 --- /dev/null +++ b/.env @@ -0,0 +1,15 @@ +# malware-watch installer configuration +# Replace these placeholders before installation. +DISCORD_WEBHOOK='디스코드웹훅URL' +ABUSECH_AUTH_KEY='abuse.ch api 키' + +CPU_THRESHOLD=150 +ALERT_SCORE=60 +CRITICAL_SCORE=100 +COOLDOWN_SECONDS=1800 + +CLAMAV_VERSION=1.4.6 +CLAMAV_URL='' +INSTALL_CLAMAV=1 +RUN_FRESHCLAM_NOW=0 +SEND_INSTALL_TEST=0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f63682 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.log +.env.local diff --git a/README.md b/README.md new file mode 100644 index 0000000..44181fe --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# malware-watch installer + +Files: +- `install.sh` — installs malware-watch, abuse.ch feeds, automatic quarantine, IOC firewall blocking, and optional official ClamAV. +- `.env` — private Discord Webhook / abuse.ch Auth-Key and tuning values. + +Install: +```bash +cd /app/malware-watch +sudo ./install.sh +``` + +Useful logs: +```bash +journalctl -u malware-watch.service -f +journalctl -u malware-feed-update.service +journalctl -u clamav-risk-scan.service +journalctl -u clamav-deep-scan.service +journalctl -u clamav-freshclam-local.service +``` + +The `.env` file is mode 600 and is ignored by Git. diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..9b0184f --- /dev/null +++ b/install.sh @@ -0,0 +1,683 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="${ENV_FILE:-$SCRIPT_DIR/.env}" + +log(){ printf '[malware-watch] %s\n' "$*"; } +die(){ printf '[malware-watch] ERROR: %s\n' "$*" >&2; exit 1; } + +if [[ ${EUID:-$(id -u)} -ne 0 ]]; then + exec sudo -E bash "$0" "$@" +fi + +[[ -r "$ENV_FILE" ]] || die "Missing $ENV_FILE" +set -a +# shellcheck disable=SC1090 +. "$ENV_FILE" +set +a + +: "${DISCORD_WEBHOOK:?DISCORD_WEBHOOK is required in .env}" +: "${ABUSECH_AUTH_KEY:?ABUSECH_AUTH_KEY is required in .env}" +CPU_THRESHOLD="${CPU_THRESHOLD:-150}" +ALERT_SCORE="${ALERT_SCORE:-60}" +CRITICAL_SCORE="${CRITICAL_SCORE:-100}" +COOLDOWN_SECONDS="${COOLDOWN_SECONDS:-1800}" +CLAMAV_VERSION="${CLAMAV_VERSION:-1.4.6}" +CLAMAV_URL="${CLAMAV_URL:-}" +INSTALL_CLAMAV="${INSTALL_CLAMAV:-1}" +RUN_FRESHCLAM_NOW="${RUN_FRESHCLAM_NOW:-0}" +SEND_INSTALL_TEST="${SEND_INSTALL_TEST:-0}" + +case "$DISCORD_WEBHOOK$ABUSECH_AUTH_KEY" in + *"'"*) die "Secrets containing a single quote are not supported by this installer" ;; +esac + +command -v systemctl >/dev/null || die "systemd is required" +command -v apt-get >/dev/null || die "This installer currently supports Debian/Ubuntu (apt)" + +log "Installing base dependencies" +apt-get update -y +DEBIAN_FRONTEND=noninteractive apt-get install -y \ + ca-certificates curl python3 iproute2 procps util-linux iptables coreutils + +install -d -m 700 /etc/malware-watch /var/lib/malware-watch /var/lib/malware-watch/feeds +install -d -m 700 /root/security-evidence/malware-watch /root/security-evidence/quarantine + +BACKUP="/root/security-evidence/malware-watch/install-backup-$(date +%Y%m%d-%H%M%S)" +install -d -m 700 "$BACKUP" +for f in \ + /etc/malware-watch/config \ + /usr/local/sbin/malware-watch.py \ + /usr/local/sbin/malware-quarantine.py \ + /usr/local/sbin/malware-feed-update.py \ + /usr/local/sbin/clamav-watch-scan.sh \ + /usr/local/sbin/block-malware-iocs; do + [[ -e "$f" ]] && cp -a "$f" "$BACKUP/" || true +done + +umask 077 +{ + printf "CPU_THRESHOLD='%s'\n" "$CPU_THRESHOLD" + printf "ALERT_SCORE='%s'\n" "$ALERT_SCORE" + printf "CRITICAL_SCORE='%s'\n" "$CRITICAL_SCORE" + printf "COOLDOWN_SECONDS='%s'\n" "$COOLDOWN_SECONDS" + printf "ABUSECH_AUTH_KEY='%s'\n" "$ABUSECH_AUTH_KEY" + printf "DISCORD_WEBHOOK='%s'\n" "$DISCORD_WEBHOOK" +} > /etc/malware-watch/config +chmod 600 /etc/malware-watch/config + +install_payload(){ + local dest="$1" mode="$2" + base64 -d > "$dest" + chmod "$mode" "$dest" + chown root:root "$dest" +} + +install_payload /usr/local/sbin/malware-watch.py 700 <<'B64_MALWARE_WATCH' +IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwppbXBvcnQgb3MscmUsanNvbix0aW1lLGhhc2hsaWIsc29j +a2V0LHN1YnByb2Nlc3Msc2hsZXgKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCkNGRz0nL2V0Yy9t +YWx3YXJlLXdhdGNoL2NvbmZpZyc7IEJBU0U9UGF0aCgnL3Zhci9saWIvbWFsd2FyZS13YXRjaCcp +OyBGRUVEUz1CQVNFLydmZWVkcyc7IFNUQVRFPUJBU0UvJ3N0YXRlLmpzb24nOyBFVklEPVBhdGgo +Jy9yb290L3NlY3VyaXR5LWV2aWRlbmNlL21hbHdhcmUtd2F0Y2gnKQpLTk9XTj0oJ3htcmlnJywn +eGFybScsJ2tpbnNpbmcnLCdrZGV2dG1wZnNpJywnd2F0Y2hib2cnLCdtaW5lcmQnLCdjcHVtaW5l +cicsJ21vbmVyb29jZWFuJywnY3J5cHRvbWluZXInKQpURU1QPSgnL3RtcC8nLCcvdmFyL3RtcC8n +LCcvZGV2L3NobS8nKQoKZGVmIGNmZygpOgogZD17fQogZm9yIGxpbmUgaW4gb3BlbihDRkcsZXJy +b3JzPSdpZ25vcmUnKToKICBpZiAnPScgaW4gbGluZSBhbmQgbm90IGxpbmUubHN0cmlwKCkuc3Rh +cnRzd2l0aCgnIycpOgogICBrLHY9bGluZS5yc3RyaXAoJ1xuJykuc3BsaXQoJz0nLDEpOyBkW2td +PXYKIHJldHVybiBkCgpkZWYgbG9hZGoocCxkZWZhdWx0KToKIHRyeTogcmV0dXJuIGpzb24ubG9h +ZChvcGVuKHApKQogZXhjZXB0IEV4Y2VwdGlvbjogcmV0dXJuIGRlZmF1bHQKCmRlZiBzYXZlaihw +LG9iaik6CiB0PXN0cihwKSsnLnRtcCc7IGpzb24uZHVtcChvYmosb3Blbih0LCd3Jyksc2VwYXJh +dG9ycz0oJywnLCc6JykpOyBvcy5jaG1vZCh0LDBvNjAwKTsgb3MucmVwbGFjZSh0LHApCgpkZWYg +c2hhMjU2KHBhdGgpOgogaD1oYXNobGliLnNoYTI1NigpCiB3aXRoIG9wZW4ocGF0aCwncmInLGJ1 +ZmZlcmluZz0wKSBhcyBmOgogIHdoaWxlIFRydWU6CiAgIGI9Zi5yZWFkKDEwMjQqMTAyNCkKICAg +aWYgbm90IGI6IGJyZWFrCiAgIGgudXBkYXRlKGIpCiByZXR1cm4gaC5oZXhkaWdlc3QoKQoKZGVm +IGFsZXJ0KHdlYmhvb2ssdGV4dCk6CiBwYXlsb2FkPWpzb24uZHVtcHMoeydjb250ZW50Jzp0ZXh0 +fSxlbnN1cmVfYXNjaWk9RmFsc2UpCiByPXN1YnByb2Nlc3MucnVuKFsnY3VybCcsJy1zUycsJy1v +JywnL2Rldi9udWxsJywnLXcnLCcle2h0dHBfY29kZX0nLCctQScsJ01vemlsbGEvNS4wIChjb21w +YXRpYmxlOyBtYWx3YXJlLXdhdGNoLzIuMCknLCctSCcsJ0NvbnRlbnQtVHlwZTogYXBwbGljYXRp +b24vanNvbicsJy0tZGF0YScscGF5bG9hZCx3ZWJob29rXSx0ZXh0PVRydWUsY2FwdHVyZV9vdXRw +dXQ9VHJ1ZSx0aW1lb3V0PTIwKQogcmV0dXJuIHIuc3Rkb3V0LnN0cmlwKCkgaW4gKCcyMDAnLCcy +MDQnKQoKZGVmIGV2aWRlbmNlKHBpZCxpbmZvKToKIHRzPXRpbWUuc3RyZnRpbWUoJyVZJW0lZC0l +SCVNJVMnKTsgZD1FVklEL2Yne3RzfS1waWR7cGlkfSc7IGQubWtkaXIocGFyZW50cz1UcnVlLGV4 +aXN0X29rPVRydWUpCiAoZC8nc3VtbWFyeS5qc29uJykud3JpdGVfdGV4dChqc29uLmR1bXBzKGlu +Zm8sZW5zdXJlX2FzY2lpPUZhbHNlLGluZGVudD0yKSkKIGZvciBzcmMsbmFtZSBpbiBbKGYnL3By +b2Mve3BpZH0vc3RhdHVzJywnc3RhdHVzJyksKGYnL3Byb2Mve3BpZH0vY2dyb3VwJywnY2dyb3Vw +JyksKGYnL3Byb2Mve3BpZH0vbWFwcycsJ21hcHMnKV06CiAgdHJ5OiAoZC9uYW1lKS53cml0ZV90 +ZXh0KG9wZW4oc3JjLGVycm9ycz0ncmVwbGFjZScpLnJlYWQoKSkKICBleGNlcHQgRXhjZXB0aW9u +OiBwYXNzCiB0cnk6IChkLyduZXR3b3JrLnR4dCcpLndyaXRlX3RleHQoc3VicHJvY2Vzcy5jaGVj +a19vdXRwdXQoWydzcycsJy10bnAnXSx0ZXh0PVRydWUsc3RkZXJyPXN1YnByb2Nlc3MuREVWTlVM +TCkpCiBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiBvcy5jaG1vZChkLDBvNzAwKQogcmV0dXJuIHN0 +cihkKQoKYz1jZmcoKTsgdGhyZXNob2xkPWZsb2F0KGMuZ2V0KCdDUFVfVEhSRVNIT0xEJywnMTUw +JykpOyBtaW5zY29yZT1pbnQoYy5nZXQoJ0FMRVJUX1NDT1JFJywnNjAnKSk7IGNyaXRpY2FsPWlu +dChjLmdldCgnQ1JJVElDQUxfU0NPUkUnLCcxMDAnKSk7IGNvb2xkb3duPWludChjLmdldCgnQ09P +TERPV05fU0VDT05EUycsJzE4MDAnKSk7IHdlYmhvb2s9Yy5nZXQoJ0RJU0NPUkRfV0VCSE9PSycs +JycpCnRmPWxvYWRqKEZFRURTLyd0aHJlYXRmb3guanNvbicse30pLmdldCgnaW9jcycse30pOyBi +YWQ9c2V0KHRmLmtleXMoKSk7IG1iPWxvYWRqKEZFRURTLydtYWx3YXJlYmF6YWFyLmpzb24nLHt9 +KS5nZXQoJ2hhc2hlcycse30pCnN0PWxvYWRqKFNUQVRFLHsnYWxlcnRzJzp7fSwnaGFzaGNhY2hl +Jzp7fX0pOyBub3c9dGltZS50aW1lKCk7IGhvc3Q9c29ja2V0LmdldGhvc3RuYW1lKCk7IGZpbmRp +bmdzPXt9CgojIHByb2Nlc3Mgc25hcHNob3QKb3V0PXN1YnByb2Nlc3MuY2hlY2tfb3V0cHV0KFsn +cHMnLCctZW8nLCdwaWQ9LHBjcHU9LHVzZXI9LGNvbW09LGFyZ3M9J10sdGV4dD1UcnVlLGVycm9y +cz0ncmVwbGFjZScpCmZvciBsaW5lIGluIG91dC5zcGxpdGxpbmVzKCk6CiBtPXJlLm1hdGNoKHIn +XHMqKFxkKylccysoWzAtOS5dKylccysoXFMrKVxzKyhcUyspXHMrKC4qKScsbGluZSkKIGlmIG5v +dCBtOiBjb250aW51ZQogcGlkPWludChtLmdyb3VwKDEpKTsgY3B1PWZsb2F0KG0uZ3JvdXAoMikp +OyB1c2VyLGNvbW0sYXJncz1tLmdyb3VwKDMpLG0uZ3JvdXAoNCksbS5ncm91cCg1KQogaWYgcGlk +PT1vcy5nZXRwaWQoKTogY29udGludWUKIGV4ZT0nJzsgZGVsZXRlZD1GYWxzZQogdHJ5OgogIGV4 +ZT1vcy5yZWFkbGluayhmJy9wcm9jL3twaWR9L2V4ZScpOyBkZWxldGVkPWV4ZS5lbmRzd2l0aCgn +IChkZWxldGVkKScpCiBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiBsb3c9KGNvbW0rJyAnK2FyZ3Mr +JyAnK2V4ZSkubG93ZXIoKTsgc2NvcmU9MDsgcmVhc29ucz1bXQogaWYgYW55KHggaW4gbG93IGZv +ciB4IGluIEtOT1dOKTogc2NvcmUrPTYwOyByZWFzb25zLmFwcGVuZCgna25vd24gbWluZXIvbWFs +d2FyZSBuYW1lJykKIGlmIGV4ZS5zdGFydHN3aXRoKFRFTVApOiBzY29yZSs9NDA7IHJlYXNvbnMu +YXBwZW5kKCdleGVjdXRhYmxlIGZyb20gdGVtcCBkaXJlY3RvcnknKQogaWYgZGVsZXRlZDogc2Nv +cmUrPTUwOyByZWFzb25zLmFwcGVuZCgnZGVsZXRlZCBleGVjdXRhYmxlIHN0aWxsIHJ1bm5pbmcn +KQogaWYgY3B1Pj10aHJlc2hvbGQ6IHNjb3JlKz0yMDsgcmVhc29ucy5hcHBlbmQoZidoaWdoIENQ +VSB7Y3B1Oi4xZn0lJykKIGg9Jyc7IGNsZWFuZXhlPWV4ZS5yZXBsYWNlKCcgKGRlbGV0ZWQpJywn +JykKIGlmIGNsZWFuZXhlIGFuZCBvcy5wYXRoLmlzZmlsZShjbGVhbmV4ZSk6CiAgdHJ5OgogICBz +PW9zLnN0YXQoY2xlYW5leGUpOyBjaz1mJ3tjbGVhbmV4ZX18e3Muc3Rfc2l6ZX18e2ludChzLnN0 +X210aW1lKX0nOyBoYz1zdFsnaGFzaGNhY2hlJ10uZ2V0KGNrKQogICBpZiBoYzogaD1oYwogICBl +bGlmIHMuc3Rfc2l6ZSA8PSAyNjg0MzU0NTY6CiAgICBoPXNoYTI1NihjbGVhbmV4ZSk7IHN0Wydo +YXNoY2FjaGUnXVtja109aAogICBpZiBoIGluIG1iOiBzY29yZSs9MTAwOyByZWFzb25zLmFwcGVu +ZCgnTWFsd2FyZUJhemFhciBTSEEyNTYgbWF0Y2gnKQogIGV4Y2VwdCBFeGNlcHRpb246IHBhc3MK +IGlmIHNjb3JlOiBmaW5kaW5nc1twaWRdPXsncGlkJzpwaWQsJ2NwdSc6Y3B1LCd1c2VyJzp1c2Vy +LCdjb21tJzpjb21tLCdhcmdzJzphcmdzWzo1MDBdLCdleGUnOmV4ZSwnc2hhMjU2JzpoLCdzY29y +ZSc6c2NvcmUsJ3JlYXNvbnMnOnJlYXNvbnMsJ2lvY19oaXRzJzpbXX0KCiMgb3V0Ym91bmQgZXN0 +YWJsaXNoZWQgVENQIHZzIFRocmVhdEZveCBJT0MgdmFsdWVzCnRyeToKIHNzPXN1YnByb2Nlc3Mu +Y2hlY2tfb3V0cHV0KFsnc3MnLCctSHRucCcsJ3N0YXRlJywnZXN0YWJsaXNoZWQnXSx0ZXh0PVRy +dWUsZXJyb3JzPSdyZXBsYWNlJyxzdGRlcnI9c3VicHJvY2Vzcy5ERVZOVUxMKQogZm9yIGxpbmUg +aW4gc3Muc3BsaXRsaW5lcygpOgogIHBhcnRzPWxpbmUuc3BsaXQoKQogIGlmIGxlbihwYXJ0cyk8 +NTogY29udGludWUKICBwZWVyPXBhcnRzWzRdOyBwbT1yZS5zZWFyY2gocidwaWQ9KFxkKyknLGxp +bmUpCiAgaWYgbm90IHBtOiBjb250aW51ZQogIHBpZD1pbnQocG0uZ3JvdXAoMSkpOyBwZWVyX2lw +PXBlZXIucnNwbGl0KCc6JywxKVswXS5zdHJpcCgnW10nKTsgaGl0PU5vbmUKICBpZiBwZWVyIGlu +IGJhZDogaGl0PXBlZXIKICBlbGlmIHBlZXJfaXAgaW4gYmFkOiBoaXQ9cGVlcl9pcAogIGlmIGhp +dDoKICAgZj1maW5kaW5ncy5zZXRkZWZhdWx0KHBpZCx7J3BpZCc6cGlkLCdjcHUnOjAsJ3VzZXIn +Oic/JywnY29tbSc6Jz8nLCdhcmdzJzonJywnZXhlJzonJywnc2hhMjU2JzonJywnc2NvcmUnOjAs +J3JlYXNvbnMnOltdLCdpb2NfaGl0cyc6W119KQogICBmWydzY29yZSddKz04MDsgZlsncmVhc29u +cyddLmFwcGVuZCgnVGhyZWF0Rm94IG5ldHdvcmsgSU9DICcraGl0KTsgZi5zZXRkZWZhdWx0KCdp +b2NfaGl0cycsW10pLmFwcGVuZChoaXQpCmV4Y2VwdCBFeGNlcHRpb246IHBhc3MKCnNlbnQ9MApx +dWFyYW50aW5lZD0wCmZvciBwaWQsZiBpbiBmaW5kaW5ncy5pdGVtcygpOgogaWYgZlsnc2NvcmUn +XSA8IG1pbnNjb3JlOiBjb250aW51ZQogbWJfbWF0Y2g9J01hbHdhcmVCYXphYXIgU0hBMjU2IG1h +dGNoJyBpbiBmWydyZWFzb25zJ10KIG1pbmVyX21hdGNoPSdrbm93biBtaW5lci9tYWx3YXJlIG5h +bWUnIGluIGZbJ3JlYXNvbnMnXQogYmVoYXZpb3JfbWF0Y2g9YW55KHguc3RhcnRzd2l0aCgnZXhl +Y3V0YWJsZSBmcm9tIHRlbXAgZGlyZWN0b3J5Jykgb3IgeC5zdGFydHN3aXRoKCdkZWxldGVkIGV4 +ZWN1dGFibGUnKSBvciB4LnN0YXJ0c3dpdGgoJ2hpZ2ggQ1BVICcpIGZvciB4IGluIGZbJ3JlYXNv +bnMnXSkKIHRmX2hpdHM9Zi5nZXQoJ2lvY19oaXRzJyxbXSkKIGNvbmZpcm1lZD1tYl9tYXRjaCBv +ciAobWluZXJfbWF0Y2ggYW5kIGJvb2wodGZfaGl0cykgYW5kIGJlaGF2aW9yX21hdGNoKQogcmVz +cG9uc2U9e30KIGV2PScnCiBpZiBjb25maXJtZWQ6CiAgY21kPVsnL3Vzci9sb2NhbC9zYmluL21h +bHdhcmUtcXVhcmFudGluZS5weScsJy0tcGlkJyxzdHIocGlkKSwnLS1yZWFzb24nLCc7ICcuam9p +bihmWydyZWFzb25zJ10pXQogIGNsZWFuZXhlPWYuZ2V0KCdleGUnLCcnKS5yZXBsYWNlKCcgKGRl +bGV0ZWQpJywnJykKICBpZiBjbGVhbmV4ZTogY21kICs9IFsnLS1maWxlJyxjbGVhbmV4ZV0KICBm +b3IgaGl0IGluIHRmX2hpdHM6IGNtZCArPSBbJy0taW9jJyxoaXRdCiAgdHJ5OgogICByPXN1YnBy +b2Nlc3MucnVuKGNtZCx0ZXh0PVRydWUsY2FwdHVyZV9vdXRwdXQ9VHJ1ZSx0aW1lb3V0PTQ1KQog +ICBpZiByLnN0ZG91dC5zdHJpcCgpOiByZXNwb25zZT1qc29uLmxvYWRzKHIuc3Rkb3V0LnN0cmlw +KCkuc3BsaXRsaW5lcygpWy0xXSkKICAgZXY9cmVzcG9uc2UuZ2V0KCdldmlkZW5jZScsJycpCiAg +IGlmIHJlc3BvbnNlLmdldCgnb2snKTogcXVhcmFudGluZWQrPTEKICBleGNlcHQgRXhjZXB0aW9u +IGFzIGU6CiAgIHJlc3BvbnNlPXsnb2snOkZhbHNlLCdlcnJvcic6c3RyKGUpfQogZWxpZiBmWydz +Y29yZSddPj1jcml0aWNhbDoKICB0cnk6IGV2PWV2aWRlbmNlKHBpZCxmKQogIGV4Y2VwdCBFeGNl +cHRpb246IHBhc3MKIGtleT1oYXNobGliLnNoYTI1Nigoc3RyKHBpZCkrJ3wnK2YuZ2V0KCdleGUn +LCcnKSsnfCcrJywnLmpvaW4oc29ydGVkKGZbJ3JlYXNvbnMnXSkpKS5lbmNvZGUoKSkuaGV4ZGln +ZXN0KCkKIGlmIG5vdy1mbG9hdChzdFsnYWxlcnRzJ10uZ2V0KGtleSwwKSkgPCBjb29sZG93bjog +Y29udGludWUKIGxldmVsPSdDT05GSVJNRUQvQVVUTy1RVUFSQU5USU5FRCcgaWYgY29uZmlybWVk +IGFuZCByZXNwb25zZS5nZXQoJ29rJykgZWxzZSAoJ0NSSVRJQ0FMJyBpZiBmWydzY29yZSddPj1j +cml0aWNhbCBlbHNlICdISUdIJykKIG1zZz0oZifwn5qoICoqTWFsd2FyZSBXYXRjaCB7bGV2ZWx9 +KipcblNlcnZlcjogYHtob3N0fWAgIFNjb3JlOiAqKntmWyJzY29yZSJdfSoqXG5QSUQ6IGB7cGlk +fWAgIENQVTogYHtmWyJjcHUiXX0lYCAgVXNlcjogYHtmWyJ1c2VyIl19YFxuUHJvY2VzczogYHtm +WyJjb21tIl19YFxuRXhlOiBge2ZbImV4ZSJdIG9yICJ1bmtub3duIn1gXG5SZWFzb25zOiAnKycs +ICcuam9pbihmWydyZWFzb25zJ10pKQogaWYgZi5nZXQoJ3NoYTI1NicpOiBtc2crPWYnXG5TSEEy +NTY6IGB7Zlsic2hhMjU2Il19YCcKIGlmIGNvbmZpcm1lZDoKICBhY3RzPXJlc3BvbnNlLmdldCgn +YWN0aW9ucycsW10pIGlmIGlzaW5zdGFuY2UocmVzcG9uc2UsZGljdCkgZWxzZSBbXQogIGlmIGFj +dHM6IG1zZys9J1xuQWN0aW9uczogJysnLCAnLmpvaW4oYWN0c1s6OF0pCiAgaWYgcmVzcG9uc2Uu +Z2V0KCdjb250YWluZXInKTogbXNnKz1mJ1xuQ29udGFpbmVyIGlzb2xhdGVkOiBge3Jlc3BvbnNl +WyJjb250YWluZXIiXX1gJwogIGlmIG5vdCByZXNwb25zZS5nZXQoJ29rJyk6IG1zZys9ZidcbkF1 +dG8tcmVzcG9uc2UgRVJST1I6IGB7cmVzcG9uc2UuZ2V0KCJlcnJvciIsInVua25vd24iKX1gJwog +aWYgZXY6IG1zZys9ZidcbkV2aWRlbmNlOiBge2V2fWAnCiBpZiB3ZWJob29rIGFuZCBhbGVydCh3 +ZWJob29rLG1zZ1s6MTkwMF0pOiBzdFsnYWxlcnRzJ11ba2V5XT1ub3c7IHNlbnQrPTEKCiMgcHJ1 +bmUgc3RhdGUKc3RbJ2FsZXJ0cyddPXtrOnYgZm9yIGssdiBpbiBzdFsnYWxlcnRzJ10uaXRlbXMo +KSBpZiBub3ctZmxvYXQodik8NjA0ODAwfQppZiBsZW4oc3RbJ2hhc2hjYWNoZSddKT41MDAwOiBz +dFsnaGFzaGNhY2hlJ109ZGljdChsaXN0KHN0WydoYXNoY2FjaGUnXS5pdGVtcygpKVstMzAwMDpd +KQpzYXZlaihTVEFURSxzdCkKcHJpbnQoanNvbi5kdW1wcyh7J2ZpbmRpbmdzJzpsZW4oZmluZGlu +Z3MpLCdhbGVydHNfc2VudCc6c2VudCwncXVhcmFudGluZWQnOnF1YXJhbnRpbmVkLCd0aHJlYXRm +b3hfaW9jcyc6bGVuKGJhZCksJ21hbHdhcmViYXphYXJfaGFzaGVzJzpsZW4obWIpfSxzZXBhcmF0 +b3JzPSgnLCcsJzonKSkpCg== +B64_MALWARE_WATCH + +install_payload /usr/local/sbin/malware-quarantine.py 700 <<'B64_MALWARE_QUARANTINE' +IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwppbXBvcnQgYXJncGFyc2UsIGhhc2hsaWIsIGlwYWRkcmVz +cywganNvbiwgb3MsIHJlLCBzaHV0aWwsIHNpZ25hbCwgc3VicHJvY2VzcywgdGltZQpmcm9tIHBh +dGhsaWIgaW1wb3J0IFBhdGgKCkJBU0U9UGF0aCgnL3Zhci9saWIvbWFsd2FyZS13YXRjaCcpCkVW +SUQ9UGF0aCgnL3Jvb3Qvc2VjdXJpdHktZXZpZGVuY2UvbWFsd2FyZS13YXRjaCcpClFVQVI9UGF0 +aCgnL3Jvb3Qvc2VjdXJpdHktZXZpZGVuY2UvcXVhcmFudGluZScpCkJMT0NLRUQ9UGF0aCgnL2V0 +Yy9tYWx3YXJlLXdhdGNoL2Jsb2NrZWQtaW9jcy50eHQnKQoKCmRlZiBydW4oY21kLCB0aW1lb3V0 +PTIwKToKICAgIHRyeToKICAgICAgICByPXN1YnByb2Nlc3MucnVuKGNtZCx0ZXh0PVRydWUsY2Fw +dHVyZV9vdXRwdXQ9VHJ1ZSx0aW1lb3V0PXRpbWVvdXQpCiAgICAgICAgcmV0dXJuIHIucmV0dXJu +Y29kZSxyLnN0ZG91dCxyLnN0ZGVycgogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAg +IHJldHVybiAyNTUsJycsc3RyKGUpCgpkZWYgc2hhMjU2KHBhdGgpOgogICAgaD1oYXNobGliLnNo +YTI1NigpCiAgICB3aXRoIG9wZW4ocGF0aCwncmInLGJ1ZmZlcmluZz0wKSBhcyBmOgogICAgICAg +IGZvciBiIGluIGl0ZXIobGFtYmRhOmYucmVhZCgxMDI0KjEwMjQpLGInJyk6IGgudXBkYXRlKGIp +CiAgICByZXR1cm4gaC5oZXhkaWdlc3QoKQoKZGVmIGNvbnRhaW5lcl9pZChwaWQpOgogICAgdHJ5 +OiBkYXRhPVBhdGgoZicvcHJvYy97cGlkfS9jZ3JvdXAnKS5yZWFkX3RleHQoZXJyb3JzPSdpZ25v +cmUnKQogICAgZXhjZXB0IEV4Y2VwdGlvbjogcmV0dXJuICcnCiAgICBwYXRzPVtyJy9kb2NrZXIv +KFswLTlhLWZdezEyLDY0fSkoPzokfC8pJyxyJ2RvY2tlci0oWzAtOWEtZl17MTIsNjR9KVwuc2Nv +cGUnLHInL2RvY2tlci8oWzAtOWEtZl17MTIsNjR9KSQnXQogICAgZm9yIHAgaW4gcGF0czoKICAg +ICAgICBtPXJlLnNlYXJjaChwLGRhdGEscmUuTSkKICAgICAgICBpZiBtOiByZXR1cm4gbS5ncm91 +cCgxKQogICAgcmV0dXJuICcnCgpkZWYgY2FwdHVyZV9wcm9jZXNzKHBpZCxkKToKICAgIGZvciBz +cmMsbmFtZSBpbiBbKGYnL3Byb2Mve3BpZH0vc3RhdHVzJywnc3RhdHVzJyksKGYnL3Byb2Mve3Bp +ZH0vY2dyb3VwJywnY2dyb3VwJyksKGYnL3Byb2Mve3BpZH0vbWFwcycsJ21hcHMnKSwoZicvcHJv +Yy97cGlkfS9jbWRsaW5lJywnY21kbGluZScpXToKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJh +dz1QYXRoKHNyYykucmVhZF9ieXRlcygpCiAgICAgICAgICAgIChkL25hbWUpLndyaXRlX2J5dGVz +KHJhdykKICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCgpkZWYgY2FwdHVyZV9nbG9iYWwo +ZCk6CiAgICBmb3IgY21kLG5hbWUgaW4gWyhbJ3BzJywnLWVmd3cnXSwncHMudHh0JyksKFsnc3Mn +LCctdG5wJ10sJ25ldHdvcmsudHh0JyldOgogICAgICAgIHJjLG91dCxlcnI9cnVuKGNtZCkKICAg +ICAgICAoZC9uYW1lKS53cml0ZV90ZXh0KG91dCtlcnIsZXJyb3JzPSdyZXBsYWNlJykKCmRlZiBi +bG9ja19pb2MoaW9jLGFjdGlvbnMsZHJ5KToKICAgIHJhdz0oaW9jIG9yICcnKS5zdHJpcCgpCiAg +ICBpZiBub3QgcmF3OiByZXR1cm4KICAgIGhvc3Q9cmF3CiAgICBpZiByYXcuc3RhcnRzd2l0aCgn +WycpIGFuZCAnXTonIGluIHJhdzogaG9zdD1yYXdbMTpyYXcuaW5kZXgoJ10nKV0KICAgIGVsaWYg +cmF3LmNvdW50KCc6Jyk9PTEgYW5kIHJhdy5yc3BsaXQoJzonLDEpWzFdLmlzZGlnaXQoKTogaG9z +dD1yYXcucnNwbGl0KCc6JywxKVswXQogICAgdHJ5OiBpcD1zdHIoaXBhZGRyZXNzLmlwX2FkZHJl +c3MoaG9zdCkpCiAgICBleGNlcHQgRXhjZXB0aW9uOiByZXR1cm4KICAgIGFjdGlvbnMuYXBwZW5k +KCdibG9ja2VkX2lvYzonK2lwKQogICAgaWYgZHJ5OiByZXR1cm4KICAgIEJMT0NLRUQucGFyZW50 +Lm1rZGlyKHBhcmVudHM9VHJ1ZSxleGlzdF9vaz1UcnVlKQogICAgdmFscz1bXQogICAgaWYgQkxP +Q0tFRC5leGlzdHMoKTogdmFscz1beC5zdHJpcCgpIGZvciB4IGluIEJMT0NLRUQucmVhZF90ZXh0 +KCkuc3BsaXRsaW5lcygpIGlmIHguc3RyaXAoKV0KICAgIGlmIGlwIG5vdCBpbiB2YWxzOgogICAg +ICAgIHdpdGggb3BlbihCTE9DS0VELCdhJykgYXMgZjogZi53cml0ZShpcCsnXG4nKQogICAgICAg +IG9zLmNobW9kKEJMT0NLRUQsMG82MDApCiAgICBydW4oWycvdXNyL2xvY2FsL3NiaW4vYmxvY2st +bWFsd2FyZS1pb2NzJ10pCgpkZWYgbmV1dHJhbGl6ZV9wZXJzaXN0ZW5jZShleGUsZXZkaXIsYWN0 +aW9ucyxkcnkpOgogICAgaWYgbm90IGV4ZSBvciBub3QgZXhlLnN0YXJ0c3dpdGgoJy8nKTogcmV0 +dXJuCiAgICBjYW5kaWRhdGVzPVtdCiAgICByb290cz1bUGF0aCgnL2V0Yy9jcm9udGFiJyksUGF0 +aCgnL2V0Yy9jcm9uLmQnKSxQYXRoKCcvdmFyL3Nwb29sL2Nyb24vY3JvbnRhYnMnKSxQYXRoKCcv +ZXRjL3N5c3RlbWQvc3lzdGVtJyksUGF0aCgnL2V0Yy9yYy5sb2NhbCcpXQogICAgZm9yIHJvb3Qg +aW4gcm9vdHM6CiAgICAgICAgaWYgcm9vdC5pc19maWxlKCk6IGNhbmRpZGF0ZXMuYXBwZW5kKHJv +b3QpCiAgICAgICAgZWxpZiByb290LmlzX2RpcigpOgogICAgICAgICAgICB0cnk6CiAgICAgICAg +ICAgICAgICBjYW5kaWRhdGVzICs9IFtwIGZvciBwIGluIHJvb3Qucmdsb2IoJyonKSBpZiBwLmlz +X2ZpbGUoKSBhbmQgcC5zdGF0KCkuc3Rfc2l6ZSA8PSAyKjEwMjQqMTAyNF0KICAgICAgICAgICAg +ZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwogICAgcGRpcj1ldmRpci8ncGVyc2lzdGVuY2UnOyBwZGly +Lm1rZGlyKGV4aXN0X29rPVRydWUpCiAgICBmb3IgcCBpbiBjYW5kaWRhdGVzOgogICAgICAgIHRy +eToKICAgICAgICAgICAgdHh0PXAucmVhZF90ZXh0KGVycm9ycz0naWdub3JlJykKICAgICAgICAg +ICAgaWYgZXhlIG5vdCBpbiB0eHQ6IGNvbnRpbnVlCiAgICAgICAgICAgIHNhZmU9cC5uYW1lLnJl +cGxhY2UoJy8nLCdfJykKICAgICAgICAgICAgc2h1dGlsLmNvcHkyKHAscGRpci8oc2FmZSsnLmJl +Zm9yZScpKQogICAgICAgICAgICBpZiAnL3N5c3RlbWQvc3lzdGVtLycgaW4gc3RyKHApIGFuZCBw +LnN1ZmZpeCBpbiAoJy5zZXJ2aWNlJywnLnRpbWVyJywnLnNvY2tldCcsJy5wYXRoJyk6CiAgICAg +ICAgICAgICAgICB1bml0PXAubmFtZQogICAgICAgICAgICAgICAgYWN0aW9ucy5hcHBlbmQoJ2Rp +c2FibGVkX3BlcnNpc3RlbmNlX3VuaXQ6Jyt1bml0KQogICAgICAgICAgICAgICAgaWYgbm90IGRy +eToKICAgICAgICAgICAgICAgICAgICBydW4oWydzeXN0ZW1jdGwnLCdkaXNhYmxlJywnLS1ub3cn +LHVuaXRdKQogICAgICAgICAgICAgICAgICAgIHE9cC53aXRoX25hbWUocC5uYW1lKycubWFsd2Fy +ZS13YXRjaC1kaXNhYmxlZCcpCiAgICAgICAgICAgICAgICAgICAgdHJ5OiBvcy5yZXBsYWNlKHAs +cSkKICAgICAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICAgICAgICAg +ICAgICAgICAgcnVuKFsnc3lzdGVtY3RsJywnZGFlbW9uLXJlbG9hZCddKQogICAgICAgICAgICBl +bHNlOgogICAgICAgICAgICAgICAgYWN0aW9ucy5hcHBlbmQoJ2Rpc2FibGVkX3BlcnNpc3RlbmNl +X2ZpbGU6JytzdHIocCkpCiAgICAgICAgICAgICAgICBpZiBub3QgZHJ5OgogICAgICAgICAgICAg +ICAgICAgIGxpbmVzPVtdCiAgICAgICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdHh0LnNwbGl0 +bGluZXMoVHJ1ZSk6CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIGV4ZSBpbiBsaW5lIGFuZCBu +b3QgbGluZS5sc3RyaXAoKS5zdGFydHN3aXRoKCcjJyk6CiAgICAgICAgICAgICAgICAgICAgICAg +ICAgICBsaW5lcy5hcHBlbmQoJyMgbWFsd2FyZS13YXRjaCBkaXNhYmxlZDogJytsaW5lKQogICAg +ICAgICAgICAgICAgICAgICAgICBlbHNlOiBsaW5lcy5hcHBlbmQobGluZSkKICAgICAgICAgICAg +ICAgICAgICBwLndyaXRlX3RleHQoJycuam9pbihsaW5lcykpCiAgICAgICAgZXhjZXB0IEV4Y2Vw +dGlvbjogcGFzcwoKZGVmIHF1YXJhbnRpbmVfaG9zdF9maWxlKHBhdGgsZXZkaXIsYWN0aW9ucyxk +cnkpOgogICAgcD1QYXRoKHBhdGgpCiAgICBpZiBub3QgcC5pc19maWxlKCk6IHJldHVybiAnJwog +ICAgdHJ5OiBoPXNoYTI1NihwKQogICAgZXhjZXB0IEV4Y2VwdGlvbjogaD0ndW5rbm93bicKICAg +IGFjdGlvbnMuYXBwZW5kKCdxdWFyYW50aW5lX2ZpbGU6JytzdHIocCkpCiAgICBpZiBkcnk6IHJl +dHVybiBzdHIocCkKICAgIFFVQVIubWtkaXIocGFyZW50cz1UcnVlLGV4aXN0X29rPVRydWUpOyBv +cy5jaG1vZChRVUFSLDBvNzAwKQogICAgYmFja3VwPWV2ZGlyLygnc2FtcGxlLScrcC5uYW1lKQog +ICAgdHJ5OiBzaHV0aWwuY29weTIocCxiYWNrdXApOyBvcy5jaG1vZChiYWNrdXAsMG80MDApCiAg +ICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICBkZXN0PVFVQVIvKHRpbWUuc3RyZnRpbWUoJyVZ +JW0lZC0lSCVNJVMnKSsnLScraFs6MTZdKyctJytwLm5hbWUpCiAgICB0cnk6CiAgICAgICAgc2h1 +dGlsLm1vdmUoc3RyKHApLHN0cihkZXN0KSk7IG9zLmNobW9kKGRlc3QsMG8wMDApOyByZXR1cm4g +c3RyKGRlc3QpCiAgICBleGNlcHQgRXhjZXB0aW9uOiByZXR1cm4gJycKCmRlZiBtYXRjaGluZ19w +aWRzKHBhdGgpOgogICAgb3V0PVtdCiAgICB0cnk6IHRhcmdldD1vcy5wYXRoLnJlYWxwYXRoKHBh +dGgpCiAgICBleGNlcHQgRXhjZXB0aW9uOiByZXR1cm4gb3V0CiAgICBmb3IgZW50IGluIFBhdGgo +Jy9wcm9jJykuaXRlcmRpcigpOgogICAgICAgIGlmIG5vdCBlbnQubmFtZS5pc2RpZ2l0KCk6IGNv +bnRpbnVlCiAgICAgICAgdHJ5OgogICAgICAgICAgICBleD1vcy5yZWFkbGluayhlbnQvJ2V4ZScp +LnJlcGxhY2UoJyAoZGVsZXRlZCknLCcnKQogICAgICAgICAgICBpZiBvcy5wYXRoLnJlYWxwYXRo +KGV4KT09dGFyZ2V0OiBvdXQuYXBwZW5kKGludChlbnQubmFtZSkpCiAgICAgICAgZXhjZXB0IEV4 +Y2VwdGlvbjogcGFzcwogICAgcmV0dXJuIG91dAoKZGVmIHN0b3BfcGlkKHBpZCxhY3Rpb25zLGRy +eSk6CiAgICBpZiBwaWQ8PTEgb3IgcGlkPT1vcy5nZXRwaWQoKTogcmV0dXJuCiAgICBhY3Rpb25z +LmFwcGVuZCgnc3RvcHBlZF9waWQ6JytzdHIocGlkKSkKICAgIGlmIGRyeTogcmV0dXJuCiAgICB0 +cnk6IG9zLmtpbGwocGlkLHNpZ25hbC5TSUdTVE9QKQogICAgZXhjZXB0IEV4Y2VwdGlvbjogcmV0 +dXJuCiAgICB0cnk6IG9zLmtpbGwocGlkLHNpZ25hbC5TSUdDT05UKTsgb3Mua2lsbChwaWQsc2ln +bmFsLlNJR1RFUk0pCiAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCiAgICBmb3IgXyBpbiByYW5n +ZSgzMCk6CiAgICAgICAgaWYgbm90IFBhdGgoZicvcHJvYy97cGlkfScpLmV4aXN0cygpOiByZXR1 +cm4KICAgICAgICB0aW1lLnNsZWVwKDAuMSkKICAgIHRyeTogb3Mua2lsbChwaWQsc2lnbmFsLlNJ +R0tJTEwpCiAgICBleGNlcHQgRXhjZXB0aW9uOiBwYXNzCgpkZWYgaGFuZGxlX2NvbnRhaW5lcihj +aWQscGlkLGV4ZSxldmRpcixhY3Rpb25zLGRyeSk6CiAgICBhY3Rpb25zLmFwcGVuZCgnaXNvbGF0 +ZWRfY29udGFpbmVyOicrY2lkWzoxMl0pCiAgICBpZiBkcnk6IHJldHVybgogICAgZm9yIGNtZCxu +YW1lIGluIFsoWydkb2NrZXInLCdpbnNwZWN0JyxjaWRdLCdkb2NrZXItaW5zcGVjdC5qc29uJyks +KFsnZG9ja2VyJywnbG9ncycsJy0tdGFpbCcsJzUwMCcsY2lkXSwnZG9ja2VyLWxvZ3MudHh0Jyks +KFsnZG9ja2VyJywnZGlmZicsY2lkXSwnZG9ja2VyLWRpZmYudHh0JyldOgogICAgICAgIHJjLG91 +dCxlcnI9cnVuKGNtZCwzMCk7IChldmRpci9uYW1lKS53cml0ZV90ZXh0KG91dCtlcnIsZXJyb3Jz +PSdyZXBsYWNlJykKICAgIGlmIGV4ZSBhbmQgZXhlLnN0YXJ0c3dpdGgoJy8nKToKICAgICAgICBk +ZXN0PWV2ZGlyLygnY29udGFpbmVyLXNhbXBsZS0nK1BhdGgoZXhlKS5uYW1lKQogICAgICAgIHJ1 +bihbJ2RvY2tlcicsJ2NwJyxjaWQrJzonK2V4ZSxzdHIoZGVzdCldLDMwKQogICAgICAgIGlmIGRl +c3QuZXhpc3RzKCk6CiAgICAgICAgICAgIHRyeTogb3MuY2htb2QoZGVzdCwwbzQwMCkKICAgICAg +ICAgICAgZXhjZXB0IEV4Y2VwdGlvbjogcGFzcwogICAgcnVuKFsnZG9ja2VyJywndXBkYXRlJywn +LS1yZXN0YXJ0PW5vJyxjaWRdLDIwKQogICAgcnVuKFsnZG9ja2VyJywnc3RvcCcsJy10JywnMTAn +LGNpZF0sMjApCgpkZWYgbWFpbigpOgogICAgYXA9YXJncGFyc2UuQXJndW1lbnRQYXJzZXIoKQog +ICAgYXAuYWRkX2FyZ3VtZW50KCctLXBpZCcsdHlwZT1pbnQsZGVmYXVsdD0wKQogICAgYXAuYWRk +X2FyZ3VtZW50KCctLWZpbGUnLGRlZmF1bHQ9JycpCiAgICBhcC5hZGRfYXJndW1lbnQoJy0tcmVh +c29uJyxkZWZhdWx0PSdjb25maXJtZWQgbWFsd2FyZScpCiAgICBhcC5hZGRfYXJndW1lbnQoJy0t +aW9jJyxhY3Rpb249J2FwcGVuZCcsZGVmYXVsdD1bXSkKICAgIGFwLmFkZF9hcmd1bWVudCgnLS1k +cnktcnVuJyxhY3Rpb249J3N0b3JlX3RydWUnKQogICAgYT1hcC5wYXJzZV9hcmdzKCkKICAgIEVW +SUQubWtkaXIocGFyZW50cz1UcnVlLGV4aXN0X29rPVRydWUpOyBvcy5jaG1vZChFVklELDBvNzAw +KQogICAgZXZkaXI9RVZJRC8odGltZS5zdHJmdGltZSgnJVklbSVkLSVIJU0lUycpKyctcXVhcmFu +dGluZScrKGYnLXBpZHthLnBpZH0nIGlmIGEucGlkIGVsc2UgJycpKQogICAgZXZkaXIubWtkaXIo +bW9kZT0wbzcwMCkKICAgIGFjdGlvbnM9W10KICAgIGV4ZT1hLmZpbGUKICAgIGlmIGEucGlkIGFu +ZCBub3QgZXhlOgogICAgICAgIHRyeTogZXhlPW9zLnJlYWRsaW5rKGYnL3Byb2Mve2EucGlkfS9l +eGUnKS5yZXBsYWNlKCcgKGRlbGV0ZWQpJywnJykKICAgICAgICBleGNlcHQgRXhjZXB0aW9uOiBl +eGU9JycKICAgIGluZm89eyd0aW1lc3RhbXAnOnRpbWUudGltZSgpLCdyZWFzb24nOmEucmVhc29u +LCdwaWQnOmEucGlkLCdmaWxlJzpleGUsJ2lvY3MnOmEuaW9jLCdkcnlfcnVuJzphLmRyeV9ydW59 +CiAgICAoZXZkaXIvJ3JlcXVlc3QuanNvbicpLndyaXRlX3RleHQoanNvbi5kdW1wcyhpbmZvLGlu +ZGVudD0yKSk7IG9zLmNobW9kKGV2ZGlyLydyZXF1ZXN0Lmpzb24nLDBvNjAwKQogICAgY2FwdHVy +ZV9nbG9iYWwoZXZkaXIpCiAgICBpZiBhLnBpZDogY2FwdHVyZV9wcm9jZXNzKGEucGlkLGV2ZGly +KQogICAgY2lkPWNvbnRhaW5lcl9pZChhLnBpZCkgaWYgYS5waWQgZWxzZSAnJwogICAgaWYgYS5w +aWQgYW5kIG5vdCBhLmRyeV9ydW46CiAgICAgICAgdHJ5OiBvcy5raWxsKGEucGlkLHNpZ25hbC5T +SUdTVE9QKTsgYWN0aW9ucy5hcHBlbmQoJ2Zyb3plbl9waWQ6JytzdHIoYS5waWQpKQogICAgICAg +IGV4Y2VwdCBFeGNlcHRpb246IHBhc3MKICAgIGZvciBpb2MgaW4gYS5pb2M6IGJsb2NrX2lvYyhp +b2MsYWN0aW9ucyxhLmRyeV9ydW4pCiAgICBpZiBjaWQ6CiAgICAgICAgaGFuZGxlX2NvbnRhaW5l +cihjaWQsYS5waWQsZXhlLGV2ZGlyLGFjdGlvbnMsYS5kcnlfcnVuKQogICAgZWxzZToKICAgICAg +ICBwaWRzPXNldCgoW2EucGlkXSBpZiBhLnBpZCBlbHNlIFtdKSArIChtYXRjaGluZ19waWRzKGV4 +ZSkgaWYgZXhlIGVsc2UgW10pKQogICAgICAgIG5ldXRyYWxpemVfcGVyc2lzdGVuY2UoZXhlLGV2 +ZGlyLGFjdGlvbnMsYS5kcnlfcnVuKQogICAgICAgIGZvciBwIGluIHNvcnRlZCh4IGZvciB4IGlu +IHBpZHMgaWYgeCk6IHN0b3BfcGlkKHAsYWN0aW9ucyxhLmRyeV9ydW4pCiAgICAgICAgaWYgZXhl +OiBxdWFyYW50aW5lX2hvc3RfZmlsZShleGUsZXZkaXIsYWN0aW9ucyxhLmRyeV9ydW4pCiAgICBy +ZXN1bHQ9eydvayc6VHJ1ZSwnZXZpZGVuY2UnOnN0cihldmRpciksJ2NvbnRhaW5lcic6Y2lkWzox +Ml0gaWYgY2lkIGVsc2UgJycsICdhY3Rpb25zJzphY3Rpb25zLCdkcnlfcnVuJzphLmRyeV9ydW59 +CiAgICAoZXZkaXIvJ3Jlc3VsdC5qc29uJykud3JpdGVfdGV4dChqc29uLmR1bXBzKHJlc3VsdCxp +bmRlbnQ9MikpOyBvcy5jaG1vZChldmRpci8ncmVzdWx0Lmpzb24nLDBvNjAwKQogICAgcHJpbnQo +anNvbi5kdW1wcyhyZXN1bHQsc2VwYXJhdG9ycz0oJywnLCc6JykpKQoKaWYgX19uYW1lX189PSdf +X21haW5fXyc6IG1haW4oKQo= +B64_MALWARE_QUARANTINE + +install_payload /usr/local/sbin/malware-feed-update.py 700 <<'B64_MALWARE_FEED_UPDATE' +IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwppbXBvcnQganNvbiwgb3MsIHN5cywgdGltZSwgdGVtcGZp +bGUsIHVybGxpYi5yZXF1ZXN0LCB1cmxsaWIucGFyc2UKQkFTRT0nL3Zhci9saWIvbWFsd2FyZS13 +YXRjaCcKRkVFRFM9QkFTRSsnL2ZlZWRzJwpvcy5tYWtlZGlycyhGRUVEUywgZXhpc3Rfb2s9VHJ1 +ZSkKa2V5PW9zLmVudmlyb24uZ2V0KCdBQlVTRUNIX0FVVEhfS0VZJywnJykuc3RyaXAoKQppZiBu +b3Qga2V5OgogICAgcHJpbnQoJ0FCVVNFQ0hfQVVUSF9LRVkgbWlzc2luZycsIGZpbGU9c3lzLnN0 +ZGVycikKICAgIHN5cy5leGl0KDIpCgpkZWYgZmV0Y2godXJsLCBwYXlsb2FkLCBpc19qc29uKToK +ICAgIGlmIGlzX2pzb246CiAgICAgICAgZGF0YT1qc29uLmR1bXBzKHBheWxvYWQpLmVuY29kZSgp +CiAgICAgICAgY3R5cGU9J2FwcGxpY2F0aW9uL2pzb24nCiAgICBlbHNlOgogICAgICAgIGRhdGE9 +dXJsbGliLnBhcnNlLnVybGVuY29kZShwYXlsb2FkKS5lbmNvZGUoKQogICAgICAgIGN0eXBlPSdh +cHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnCiAgICByZXE9dXJsbGliLnJlcXVlc3Qu +UmVxdWVzdCh1cmwsZGF0YT1kYXRhLGhlYWRlcnM9eydBdXRoLUtleSc6a2V5LCdDb250ZW50LVR5 +cGUnOmN0eXBlLCdVc2VyLUFnZW50JzonbWFsd2FyZS13YXRjaC8yJ30sbWV0aG9kPSdQT1NUJykK +ICAgIHdpdGggdXJsbGliLnJlcXVlc3QudXJsb3BlbihyZXEsdGltZW91dD00NSkgYXMgcjoKICAg +ICAgICByZXR1cm4ganNvbi5sb2FkKHIpCgpkZWYgc2F2ZShwYXRoLG9iaik6CiAgICBmZCx0bXA9 +dGVtcGZpbGUubWtzdGVtcChwcmVmaXg9Jy50bXAtJyxkaXI9RkVFRFMpCiAgICB3aXRoIG9zLmZk +b3BlbihmZCwndycpIGFzIGY6CiAgICAgICAganNvbi5kdW1wKG9iaixmLHNlcGFyYXRvcnM9KCcs +JywnOicpKQogICAgb3MuY2htb2QodG1wLDBvNjAwKQogICAgb3MucmVwbGFjZSh0bXAscGF0aCkK +CnRmPWZldGNoKCdodHRwczovL3RocmVhdGZveC1hcGkuYWJ1c2UuY2gvYXBpL3YxLycseydxdWVy +eSc6J2dldF9pb2NzJywnZGF5cyc6N30sVHJ1ZSkKaWYgdGYuZ2V0KCdxdWVyeV9zdGF0dXMnKSE9 +J29rJzoKICAgIHJhaXNlIFJ1bnRpbWVFcnJvcignVGhyZWF0Rm94IHN0YXR1cz0nK3N0cih0Zi5n +ZXQoJ3F1ZXJ5X3N0YXR1cycpKSkKaW9jcz17fQpmb3IgeCBpbiB0Zi5nZXQoJ2RhdGEnKSBvciBb +XToKICAgIHZhbD0oeC5nZXQoJ2lvYycpIG9yICcnKS5zdHJpcCgpCiAgICBpZiB2YWw6CiAgICAg +ICAgaW9jc1t2YWxdPXsnaW9jX3R5cGUnOnguZ2V0KCdpb2NfdHlwZScpLCd0aHJlYXRfdHlwZSc6 +eC5nZXQoJ3RocmVhdF90eXBlJyksJ21hbHdhcmUnOnguZ2V0KCdtYWx3YXJlX3ByaW50YWJsZScp +IG9yIHguZ2V0KCdtYWx3YXJlJyksJ2ZpcnN0X3NlZW4nOnguZ2V0KCdmaXJzdF9zZWVuJyl9CnNh +dmUoRkVFRFMrJy90aHJlYXRmb3guanNvbicseyd1cGRhdGVkJzppbnQodGltZS50aW1lKCkpLCdp +b2NzJzppb2NzfSkKCm1iPWZldGNoKCdodHRwczovL21iLWFwaS5hYnVzZS5jaC9hcGkvdjEvJyx7 +J3F1ZXJ5JzoncmVjZW50X2RldGVjdGlvbnMnLCdob3Vycyc6JzE2OCd9LEZhbHNlKQppZiBtYi5n +ZXQoJ3F1ZXJ5X3N0YXR1cycpIG5vdCBpbiAoJ29rJywnbm9fcmVzdWx0cycpOgogICAgcmFpc2Ug +UnVudGltZUVycm9yKCdNYWx3YXJlQmF6YWFyIHN0YXR1cz0nK3N0cihtYi5nZXQoJ3F1ZXJ5X3N0 +YXR1cycpKSkKaGFzaGVzPXt9CmZvciB4IGluIG1iLmdldCgnZGF0YScpIG9yIFtdOgogICAgaD0o +eC5nZXQoJ3NoYTI1Nl9oYXNoJykgb3IgJycpLmxvd2VyKCkKICAgIGlmIGxlbihoKT09NjQ6CiAg +ICAgICAgaGFzaGVzW2hdPXsnc2lnbmF0dXJlJzp4LmdldCgnc2lnbmF0dXJlJyksJ2ZpbGVfbmFt +ZSc6eC5nZXQoJ2ZpbGVfbmFtZScpLCdmaXJzdF9zZWVuJzp4LmdldCgnZmlyc3Rfc2VlbicpfQpz +YXZlKEZFRURTKycvbWFsd2FyZWJhemFhci5qc29uJyx7J3VwZGF0ZWQnOmludCh0aW1lLnRpbWUo +KSksJ2hhc2hlcyc6aGFzaGVzfSkKcHJpbnQoanNvbi5kdW1wcyh7J3RocmVhdGZveF9pb2NzJzps +ZW4oaW9jcyksJ21hbHdhcmViYXphYXJfaGFzaGVzJzpsZW4oaGFzaGVzKX0sc2VwYXJhdG9ycz0o +JywnLCc6JykpKQo= +B64_MALWARE_FEED_UPDATE + +install_payload /usr/local/sbin/clamav-watch-scan.sh 700 <<'B64_CLAMAV_WATCH_SCAN' +IyEvYmluL2Jhc2gKc2V0IC11Ck1PREU9IiR7MTotcXVpY2t9IgpDRkc9L2V0Yy9tYWx3YXJlLXdh +dGNoL2NvbmZpZwpEQkRJUj0vdmFyL2xpYi9jbGFtYXYKRVZJRD0vcm9vdC9zZWN1cml0eS1ldmlk +ZW5jZS9tYWx3YXJlLXdhdGNoClNUQVRFPS92YXIvbGliL21hbHdhcmUtd2F0Y2gvY2xhbWF2LWFs +ZXJ0LnN0YXRlCkxPQ0s9L3J1bi9jbGFtYXYtd2F0Y2gubG9jawpDTEFNPS91c3IvbG9jYWwvYmlu +L2NsYW1zY2FuCgpleGVjIDk+IiRMT0NLIgpmbG9jayAtbiA5IHx8IHsgZWNobyAiQ0xBTUFWX1NL +SVAgcmVhc29uPXNjYW5fYWxyZWFkeV9ydW5uaW5nIG1vZGU9JE1PREUiOyBleGl0IDA7IH0KCmlm +ICEgZmluZCAiJERCRElSIiAtbWF4ZGVwdGggMSAtdHlwZSBmIFwoIC1uYW1lICcqLmN2ZCcgLW8g +LW5hbWUgJyouY2xkJyBcKSAtcHJpbnQgLXF1aXQgMj4vZGV2L251bGwgfCBncmVwIC1xIC47IHRo +ZW4KICBlY2hvICJDTEFNQVZfU0tJUCByZWFzb249ZGF0YWJhc2Vfbm90X3JlYWR5IG1vZGU9JE1P +REUiCiAgZXhpdCAwCmZpCgppZiBbICEgLXIgIiRDRkciIF07IHRoZW4KICBlY2hvICJDTEFNQVZf +RVJST1IgY29uZmlnX3VucmVhZGFibGUiCiAgZXhpdCAyCmZpCnNldCAtYQouICIkQ0ZHIgpzZXQg +K2EKCmlmIFsgIiRNT0RFIiA9ICJkZWVwIiBdOyB0aGVuCiAgVEFSR0VUUz0oL2V0YyAvdXNyL2xv +Y2FsIC9vcHQgL3Jvb3QgL2hvbWUgL2FwcCkKZWxzZQogIFRBUkdFVFM9KC90bXAgL3Zhci90bXAg +L2Rldi9zaG0pCmZpCgpFWElTVElORz0oKQpmb3IgcCBpbiAiJHtUQVJHRVRTW0BdfSI7IGRvIFsg +LWUgIiRwIiBdICYmIEVYSVNUSU5HKz0oIiRwIik7IGRvbmUKWyAkeyNFWElTVElOR1tAXX0gLWd0 +IDAgXSB8fCBleGl0IDAKClRNUD0kKG1rdGVtcCAvdG1wL2NsYW1hdi13YXRjaC5YWFhYWFgpCnRy +YXAgJ3JtIC1mICIkVE1QIicgRVhJVAoKQVJHUz0oLS1kYXRhYmFzZT0iJERCRElSIiAtLXJlY3Vy +c2l2ZT15ZXMgLS1jcm9zcy1mcz1ubyAtLWluZmVjdGVkIC0tbm8tc3VtbWFyeSAtLW1heC1maWxl +c2l6ZT0xMDBNIC0tbWF4LXNjYW5zaXplPTIwME0gLS1tYXgtcmVjdXJzaW9uPTMwIC0tZXhjbHVk +ZS1kaXI9J14vcm9vdC9zZWN1cml0eS1ldmlkZW5jZSgvfCQpJykKaWYgWyAiJE1PREUiID0gImRl +ZXAiIF07IHRoZW4KICBBUkdTKz0oLS1leGNsdWRlLWRpcj0nKF58Lykobm9kZV9tb2R1bGVzfFwu +Z2l0fFwuY2FjaGV8Y2FjaGV8Q2FjaGV8X19weWNhY2hlX198dmVudnxcLnZlbnYpKC98JCknKQpm +aQoKc2V0ICtlCm5pY2UgLW4gMTUgaW9uaWNlIC1jIDMgIiRDTEFNIiAiJHtBUkdTW0BdfSIgIiR7 +RVhJU1RJTkdbQF19IiA+IiRUTVAiIDI+JjEKUkM9JD8Kc2V0IC1lCkZPVU5EPSQoZ3JlcCAnIEZP +VU5EJCcgIiRUTVAiIDI+L2Rldi9udWxsIHx8IHRydWUpCgppZiBbIC1uICIkRk9VTkQiIF07IHRo +ZW4KICBta2RpciAtcCAiJEVWSUQiCiAgY2htb2QgNzAwICIkRVZJRCIKICBUUz0kKGRhdGUgKyVZ +JW0lZC0lSCVNJVMpCiAgT1VUPSIkRVZJRC8ke1RTfS1jbGFtYXYtJHtNT0RFfS5sb2ciCiAgY3Ag +IiRUTVAiICIkT1VUIgogIGNobW9kIDYwMCAiJE9VVCIKICBRTE9HPSIkT1VULnF1YXJhbnRpbmUu +anNvbmwiCiAgOiA+ICIkUUxPRyIKICB3aGlsZSBJRlM9IHJlYWQgLXIgSElUOyBkbwogICAgRklM +RT0ke0hJVCUlOiAqfQogICAgU0lHPSR7SElUIyo6IH0KICAgIFsgLWYgIiRGSUxFIiBdIHx8IGNv +bnRpbnVlCiAgICAvdXNyL2xvY2FsL3NiaW4vbWFsd2FyZS1xdWFyYW50aW5lLnB5IC0tZmlsZSAi +JEZJTEUiIC0tcmVhc29uICJDbGFtQVYgY29uZmlybWVkOiAkU0lHIiA+PiAiJFFMT0ciIDI+JjEg +fHwgdHJ1ZQogIGRvbmUgPDxFT0ZfRk9VTkQKJEZPVU5ECkVPRl9GT1VORAogIGNobW9kIDYwMCAi +JFFMT0ciCiAgRlA9JChwcmludGYgJyVzXG4nICIkRk9VTkQiIHwgc2hhMjU2c3VtIHwgYXdrICd7 +cHJpbnQgJDF9JykKICBMQVNURlA9Jyc7IExBU1RUUz0wCiAgaWYgWyAtciAiJFNUQVRFIiBdOyB0 +aGVuIHJlYWQgLXIgTEFTVEZQIExBU1RUUyA8ICIkU1RBVEUiIHx8IHRydWU7IGZpCiAgTk9XPSQo +ZGF0ZSArJXMpCiAgaWYgWyAiJEZQIiAhPSAiJExBU1RGUCIgXSB8fCBbICQoKE5PVy1MQVNUVFMp +KSAtZ2UgODY0MDAgXTsgdGhlbgogICAgU0hPUlQ9JChwcmludGYgJyVzXG4nICIkRk9VTkQiIHwg +aGVhZCAtMTAgfCBoZWFkIC1jIDEzMDApCiAgICBNU0c9IvCfmqggKipDbGFtQVYgTUFMV0FSRSBE +RVRFQ1RFRCoqClNlcnZlcjogXGAkKGhvc3RuYW1lKVxgClNjYW46IFxgJE1PREVcYAoKXGBcYFxg +CiRTSE9SVApcYFxgXGAKRXZpZGVuY2U6IFxgJE9VVFxgXG5RdWFyYW50aW5lIGxvZzogXGAkUUxP +R1xgIgogICAgUEFZTE9BRD0kKHByaW50ZiAnJXMnICIkTVNHIiB8IHB5dGhvbjMgLWMgJ2ltcG9y +dCBqc29uLHN5czsgcHJpbnQoanNvbi5kdW1wcyh7ImNvbnRlbnQiOnN5cy5zdGRpbi5yZWFkKCl9 +LCBlbnN1cmVfYXNjaWk9RmFsc2UpKScpCiAgICBDT0RFPSQoY3VybCAtc1MgLW8gL2Rldi9udWxs +IC13ICcle2h0dHBfY29kZX0nIC1BICdNb3ppbGxhLzUuMCAoY29tcGF0aWJsZTsgbWFsd2FyZS13 +YXRjaC8yLjApJyAtSCAnQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uJyAtLWRhdGEgIiRQ +QVlMT0FEIiAiJHtESVNDT1JEX1dFQkhPT0s6LX0iIHx8IHRydWUpCiAgICBpZiBbICIkQ09ERSIg +PSAiMjAwIiBdIHx8IFsgIiRDT0RFIiA9ICIyMDQiIF07IHRoZW4KICAgICAgcHJpbnRmICclcyAl +c1xuJyAiJEZQIiAiJE5PVyIgPiAiJFNUQVRFIgogICAgICBjaG1vZCA2MDAgIiRTVEFURSIKICAg +IGZpCiAgICBlY2hvICJDTEFNQVZfQUxFUlQgbW9kZT0kTU9ERSBodHRwPSRDT0RFIGV2aWRlbmNl +PSRPVVQiCiAgZWxzZQogICAgZWNobyAiQ0xBTUFWX0RFVEVDVEVEX0RVUExJQ0FURSBtb2RlPSRN +T0RFIGV2aWRlbmNlPSRPVVQiCiAgZmkKICBleGl0IDEKZmkKCmlmIFsgIiRSQyIgLWd0IDEgXTsg +dGhlbgogIGVjaG8gIkNMQU1BVl9TQ0FOX0VSUk9SIG1vZGU9JE1PREUgcmM9JFJDIgogIHRhaWwg +LTIwICIkVE1QIgogIGV4aXQgIiRSQyIKZmkKCmVjaG8gIkNMQU1BVl9PSyBtb2RlPSRNT0RFIgpl +eGl0IDAK +B64_CLAMAV_WATCH_SCAN + +install_payload /usr/local/sbin/block-malware-iocs 700 <<'B64_BLOCK_MALWARE_IOCS' +IyEvYmluL3NoCnNldCAtZXUKRj0vZXRjL21hbHdhcmUtd2F0Y2gvYmxvY2tlZC1pb2NzLnR4dApb +IC1yICIkRiIgXSB8fCBleGl0IDAKd2hpbGUgSUZTPSByZWFkIC1yIGlwOyBkbwogIFsgLW4gIiRp +cCIgXSB8fCBjb250aW51ZQogIGlwdGFibGVzIC1DIE9VVFBVVCAtZCAiJGlwIiAtaiBSRUpFQ1Qg +Mj4vZGV2L251bGwgfHwgaXB0YWJsZXMgLUkgT1VUUFVUIDEgLWQgIiRpcCIgLWogUkVKRUNUCiAg +aWYgaXB0YWJsZXMgLW5MIERPQ0tFUi1VU0VSID4vZGV2L251bGwgMj4mMTsgdGhlbgogICAgaXB0 +YWJsZXMgLUMgRE9DS0VSLVVTRVIgLWQgIiRpcCIgLWogUkVKRUNUIDI+L2Rldi9udWxsIHx8IGlw +dGFibGVzIC1JIERPQ0tFUi1VU0VSIDEgLWQgIiRpcCIgLWogUkVKRUNUCiAgZmkKZG9uZSA8ICIk +RiIK +B64_BLOCK_MALWARE_IOCS + + +python3 -m py_compile /usr/local/sbin/malware-watch.py /usr/local/sbin/malware-quarantine.py /usr/local/sbin/malware-feed-update.py +bash -n /usr/local/sbin/clamav-watch-scan.sh + +if [[ "$INSTALL_CLAMAV" == "1" ]]; then + arch="$(uname -m)" + case "$arch" in + aarch64|arm64) clam_arch="aarch64" ;; + x86_64|amd64) clam_arch="x86_64" ;; + *) die "Unsupported ClamAV architecture: $arch" ;; + esac + + if ! /usr/local/bin/clamscan --version 2>/dev/null | grep -q "ClamAV $CLAMAV_VERSION"; then + log "Installing official ClamAV $CLAMAV_VERSION for $clam_arch" + deb="$(mktemp /tmp/clamav.XXXXXX.deb)" + url="${CLAMAV_URL:-https://www.clamav.net/downloads/production/clamav-${CLAMAV_VERSION}.linux.${clam_arch}.deb}" + curl -fL --retry 3 --retry-delay 2 -o "$deb" "$url" + systemctl disable --now clamav-freshclam 2>/dev/null || true + DEBIAN_FRONTEND=noninteractive apt-get remove -y \ + clamav clamav-freshclam clamav-base libclamav9 libclamav11 2>/dev/null || true + DEBIAN_FRONTEND=noninteractive apt-get install -y "$deb" + rm -f "$deb" + fi + + [[ -x /usr/local/bin/clamscan ]] || die "Official ClamAV clamscan not found after installation" + [[ -f /usr/local/etc/freshclam.conf.sample ]] || die "freshclam.conf.sample not found" + install -d -o clamav -g clamav -m 755 /var/lib/clamav + cp /usr/local/etc/freshclam.conf.sample /usr/local/etc/freshclam.conf + sed -i 's/^Example/#Example/' /usr/local/etc/freshclam.conf + cat >> /usr/local/etc/freshclam.conf <<'EOF_FRESH' +DatabaseDirectory /var/lib/clamav +DatabaseOwner clamav +Checks 12 +EOF_FRESH + chmod 644 /usr/local/etc/freshclam.conf +fi + +cat > /etc/systemd/system/malware-watch.service <<'EOF' +[Unit] +Description=Malware Watch realtime detector +After=network-online.target docker.service +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/malware-watch.py +User=root +Nice=10 +IOSchedulingClass=best-effort +IOSchedulingPriority=7 +EOF + +cat > /etc/systemd/system/malware-watch.timer <<'EOF' +[Unit] +Description=Run Malware Watch every minute + +[Timer] +OnBootSec=2min +OnUnitActiveSec=1min +AccuracySec=5s +Persistent=true + +[Install] +WantedBy=timers.target +EOF + +cat > /etc/systemd/system/malware-feed-update.service <<'EOF' +[Unit] +Description=Malware Watch abuse.ch feed updater +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +EnvironmentFile=/etc/malware-watch/config +ExecStart=/usr/local/sbin/malware-feed-update.py +User=root +EOF + +cat > /etc/systemd/system/malware-feed-update.timer <<'EOF' +[Unit] +Description=Update malware threat feeds every 6 hours + +[Timer] +OnBootSec=5min +OnUnitActiveSec=6h +RandomizedDelaySec=5min +Persistent=true + +[Install] +WantedBy=timers.target +EOF + +cat > /etc/systemd/system/block-malware-iocs.service <<'EOF' +[Unit] +Description=Restore malware IOC firewall blocks +After=network-online.target docker.service +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/block-malware-iocs +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +EOF + +if [[ "$INSTALL_CLAMAV" == "1" ]]; then +cat > /etc/systemd/system/clamav-freshclam-local.service < /etc/systemd/system/clamav-freshclam-local.timer <<'EOF' +[Unit] +Description=Update ClamAV signatures every 2 hours + +[Timer] +OnBootSec=15min +OnUnitActiveSec=2h +RandomizedDelaySec=5min +Persistent=true + +[Install] +WantedBy=timers.target +EOF + +cat > /etc/systemd/system/clamav-risk-scan.service <<'EOF' +[Unit] +Description=ClamAV high-risk path scan +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/clamav-watch-scan.sh quick +User=root +Nice=15 +IOSchedulingClass=idle +SuccessExitStatus=1 +EOF + +cat > /etc/systemd/system/clamav-risk-scan.timer <<'EOF' +[Unit] +Description=Hourly ClamAV scan of high-risk temporary paths + +[Timer] +OnBootSec=20min +OnUnitActiveSec=1h +RandomizedDelaySec=5min +Persistent=true + +[Install] +WantedBy=timers.target +EOF + +cat > /etc/systemd/system/clamav-deep-scan.service <<'EOF' +[Unit] +Description=ClamAV daily low-priority server scan +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/clamav-watch-scan.sh deep +User=root +Nice=19 +IOSchedulingClass=idle +SuccessExitStatus=1 +EOF + +cat > /etc/systemd/system/clamav-deep-scan.timer <<'EOF' +[Unit] +Description=Daily ClamAV low-priority server scan + +[Timer] +OnCalendar=*-*-* 04:30:00 +RandomizedDelaySec=15min +Persistent=true + +[Install] +WantedBy=timers.target +EOF +fi + +systemctl daemon-reload +systemctl enable --now malware-watch.timer malware-feed-update.timer block-malware-iocs.service +if [[ "$INSTALL_CLAMAV" == "1" ]]; then + systemctl enable --now clamav-freshclam-local.timer clamav-risk-scan.timer clamav-deep-scan.timer +fi + +log "Updating abuse.ch feeds" +if ! systemctl start malware-feed-update.service; then + log "WARNING: abuse.ch feed update failed; timer will retry" +fi + +if [[ "$INSTALL_CLAMAV" == "1" && "$RUN_FRESHCLAM_NOW" == "1" ]]; then + log "Trying initial ClamAV signature update" + systemctl start clamav-freshclam-local.service || log "WARNING: freshclam failed; timer will retry" +fi + +systemctl start malware-watch.service || true + +if [[ "$SEND_INSTALL_TEST" == "1" ]]; then + payload="$(python3 - <<'PYMSG' +import json,socket +print(json.dumps({'content':f'✅ malware-watch install OK | server: {socket.gethostname()}'},ensure_ascii=False)) +PYMSG +)" + curl -sS -o /dev/null -A 'Mozilla/5.0 (compatible; malware-watch/2.0)' \ + -H 'Content-Type: application/json' --data "$payload" "$DISCORD_WEBHOOK" || true +fi + +log "Installation complete" +/usr/local/sbin/malware-watch.py || true +systemctl list-timers --all --no-pager | grep -E 'malware-watch|malware-feed-update|clamav-(freshclam-local|risk-scan|deep-scan)' || true