This is a setup guide for a simple upload server with ClamAV
virus scanning function.
The sample application is written in Typescript
but it also work on any NodeJS
application.
Dockerfile This Dockerfile install virus scanner ClamAV
and supervisor
also it is based on node. If your application is Java or any other languages, you can replace the FROM
line.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 FROM node:8 MAINTAINER Yeung Yiu Hung <hkclex@gmail.com>ENV DEBIAN_VERSION jessieRUN echo "deb http://http.debian.net/debian/ $DEBIAN_VERSION main contrib non-free" > /etc/apt/sources.list && \ echo "deb http://http.debian.net/debian/ $DEBIAN_VERSION -updates main contrib non-free" >> /etc/apt/sources.list && \ echo "deb http://security.debian.org/ $DEBIAN_VERSION /updates main contrib non-free" >> /etc/apt/sources.list && \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y -qq \ clamav-daemon \ clamav-freshclam \ libclamunrar7 \ supervisor \ wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* RUN wget -O /var/lib/clamav/main.cvd http://database.clamav.net/main.cvd && \ wget -O /var/lib/clamav/daily.cvd http://database.clamav.net/daily.cvd && \ wget -O /var/lib/clamav/bytecode.cvd http://database.clamav.net/bytecode.cvd && \ chown clamav:clamav /var/lib/clamav/*.cvd RUN mkdir /var/run/clamav && \ chown clamav:clamav /var/run/clamav && \ chmod 750 /var/run/clamav RUN sed -i 's/^Foreground .*$/Foreground true/g' /etc/clamav/clamd.conf && \ echo "TCPSocket 3310" >> /etc/clamav/clamd.conf && \ sed -i 's/^Foreground .*$/Foreground true/g' /etc/clamav/freshclam.conf VOLUME ["/var/lib/clamav" ] WORKDIR /server COPY . /server RUN npm install && npm run postinstall COPY ./configs/supervisord.conf /etc/supervisor/conf.d/supervisord-nodejs.conf EXPOSE 3000 CMD ["/usr/bin/supervisord" , "-n" ]
supervisor.conf supervisor
is a service that let you run multiple service at once. In our case we need freshclam
for updating virus database, clamd
as our virus scanner and node
for our server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 [supervisord] nodaemon=true [program:clamd] directory=/ command=clamd & autostart=true autorestart=true stderr_logfile=/var/log/supervisor/%(program_name)s.log stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 redirect_stderr=true [program:freshclam] directory=/ command=freshclam -d autostart=true autorestart=true stderr_logfile=/var/log/supervisor/%(program_name)s.log stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 redirect_stderr=true [program:fileservice] directory=/server command=npm run debug autostart=true autorestart=true stderr_logfile=/var/log/supervisor/%(program_name)s.log stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 redirect_stderr=true
Server Code Here is a simple upload server in Typescript
You will need:
1 npm i multer clamav.js express --save
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 import express from "express" ;import multer = require ("multer" );import * as stream from "stream" ;import clamav from "clamav.js" ;import { RequestHandler } from "express-serve-static-core" ;import { read } from "fs" ;var upload = multer({ storage: multer.memoryStorage() }); export class Application { private app = express(); version(): string { return "1.0" ; } start() { console .log("Application Started" ); this .app.post("/photos/upload" , upload.single("photo" ), function ( req, res, next ) { const readStream = new stream.Readable(); readStream.push(req.file.buffer); readStream.push(null ); clamav .createScanner(3310 , "127.0.0.1" ) .scan(readStream, function (err, object, malicious ) { if (err) { console .log(object.path + ": " + err); next(err); } else if (malicious) { console .log(object.path + ": " + malicious + " FOUND" ); next(new Error ("Virus Detected" )); } else { console .log(object.path + ": OK" ); res.send("OK" ); } }); }); this .app.use(function (err, req, res, next ) { if (err !== null ) { console .log(err); res.send({ result: "fail" , error: err.message }); } else { next(); } }); this .app.listen(3000 , function ( ) { console .log("Server listening on port 3000" ); }); } stop(): boolean { return true ; } } const app = new Application();app.start();
Testing it You can upload a file to /photos/upload
with this content to test the virus scanner
1 X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
You can find the complete project here: https://github.com/darkcl/simple-upload