├── .gitignore ├── eicar.com ├── go-clamav-rest ├── go.mod ├── README.md ├── Dockerfile ├── main.go ├── go.sum └── server │ └── server.go ├── clamd.conf ├── readyness.sh ├── Dockerfile ├── docker-entrypoint.sh ├── LICENSE.md ├── examples ├── clamd-api.yaml └── kubernetes.md ├── code_of_conduct.md ├── .drone.yml ├── README.md ├── k8s └── clamd-api.yaml ├── ci-build.sh └── freshclam.conf /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | eicar.com 3 | -------------------------------------------------------------------------------- /eicar.com: -------------------------------------------------------------------------------- 1 | X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* -------------------------------------------------------------------------------- /go-clamav-rest/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/asmith030/go-clamav-rest 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e 7 | github.com/sirupsen/logrus v1.4.2 8 | ) 9 | -------------------------------------------------------------------------------- /clamd.conf: -------------------------------------------------------------------------------- 1 | LogFile /dev/stdout 2 | LogTime yes 3 | LogClean yes 4 | LogSyslog no 5 | LogVerbose yes 6 | DatabaseDirectory /var/lib/clamav 7 | LocalSocket /var/run/clamav/clamd.socket 8 | TCPSocket 3310 9 | Foreground yes 10 | -------------------------------------------------------------------------------- /readyness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if freshclam | grep -q 'bytecode.cvd already up-to-date'; then 6 | echo "freshclam running successfully" 7 | if clamdscan eicar.com | grep -q 'Infected files: 1'; then 8 | echo "Clamd running successfully" 9 | exit 0 10 | else 11 | echo "Clamd not running" 12 | exit 1 13 | fi 14 | else 15 | echo "freshclam not running" 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /go-clamav-rest/README.md: -------------------------------------------------------------------------------- 1 | ## go-clamav-rest 2 | 3 | Clamav proxy based on https://github.com/solita/clamav-rest/ and implemented in golang 4 | 5 | ### Usage 6 | 7 | ``` 8 | Usage of go-clamav-rest: 9 | -host string 10 | Address of the clamd instance (default "localhost") 11 | -listenPort int 12 | TCP port that we should listen on (default 8080) 13 | -maxFileMem int 14 | Maximum memory used to store uploaded files (excess is written to disk) (default 128) 15 | -port int 16 | TCP port of the clamd instance (default 3310) 17 | ``` 18 | -------------------------------------------------------------------------------- /go-clamav-rest/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.13 as builder 2 | 3 | WORKDIR /go/src/github.com/asmith030/go-clamav-rest 4 | 5 | COPY go.mod go.sum main.go ./ 6 | 7 | COPY server/ ./server/ 8 | 9 | RUN CGO_ENABLED=0 GOOS=linux go install -v \ 10 | github.com/asmith030/go-clamav-rest 11 | 12 | FROM alpine:3.11.3 13 | RUN apk --no-cache add ca-certificates 14 | 15 | RUN addgroup -g 1000 -S app && \ 16 | adduser -u 1000 -S app -G app 17 | 18 | USER 1000 19 | 20 | COPY --from=builder /go/bin/go-clamav-rest /go-clamav-rest 21 | 22 | EXPOSE 8080 23 | 24 | ENTRYPOINT ["/go-clamav-rest"] 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.11 2 | 3 | ENV CLAM_VERSION=0.102.1-r0 4 | 5 | RUN apk add --no-cache clamav=$CLAM_VERSION clamav-libunrar=$CLAM_VERSION 6 | 7 | # Add clamav user 8 | RUN adduser -S -G clamav -u 1000 clamav_user -h /var/lib/clamav && \ 9 | mkdir -p /var/lib/clamav && \ 10 | mkdir /usr/local/share/clamav && \ 11 | chown -R clamav_user:clamav /var/lib/clamav /usr/local/share/clamav /etc/clamav 12 | 13 | # Configure Clam AV... 14 | COPY --chown=clamav_user:clamav ./*.conf /etc/clamav/ 15 | COPY --chown=clamav_user:clamav eicar.com / 16 | COPY --chown=clamav_user:clamav ./readyness.sh / 17 | 18 | # permissions 19 | RUN mkdir /var/run/clamav && \ 20 | chown clamav_user:clamav /var/run/clamav && \ 21 | chmod 750 /var/run/clamav 22 | 23 | USER 1000 24 | 25 | # initial update of av databases 26 | RUN freshclam 27 | 28 | VOLUME /var/lib/clamav 29 | COPY --chown=clamav_user:clamav docker-entrypoint.sh / 30 | 31 | ENTRYPOINT ["/docker-entrypoint.sh"] 32 | 33 | EXPOSE 3310 34 | -------------------------------------------------------------------------------- /go-clamav-rest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | "time" 8 | 9 | "github.com/asmith030/go-clamav-rest/server" 10 | "github.com/sirupsen/logrus" 11 | ) 12 | 13 | var ( 14 | host = flag.String("host", "localhost", "Address of the clamd instance") 15 | port = flag.Int("port", 3310, "TCP port of the clamd instance") 16 | listenPort = flag.Int("listenPort", 8080, "TCP port that we should listen on") 17 | maxFileMem = flag.Int64("maxFileMem", 128, "Maximum memory used to store uploaded files (excess is written to disk)") 18 | ) 19 | 20 | func newLogger() *logrus.Logger { 21 | var logger = logrus.New() 22 | logger.Out = os.Stderr 23 | jsonFormatter := new(logrus.JSONFormatter) 24 | jsonFormatter.TimestampFormat = time.RFC3339Nano 25 | logger.Formatter = jsonFormatter 26 | logger.Level = logrus.InfoLevel 27 | return logger 28 | } 29 | 30 | func main() { 31 | flag.Parse() 32 | logger := newLogger() 33 | 34 | server.RunHTTPListener( 35 | fmt.Sprintf("tcp://%v:%d", *host, *port), 36 | *listenPort, *maxFileMem, logger) 37 | } 38 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # bootstrap clam av service and clam av database updater 3 | set -m 4 | 5 | function process_file() { 6 | if [[ ! -z "$1" ]]; then 7 | local SETTING_LIST=$(echo "$1" | tr ',' '\n' | grep "^[A-Za-z][A-Za-z]*=.*$") 8 | local SETTING 9 | 10 | for SETTING in ${SETTING_LIST}; do 11 | # Remove any existing copies of this setting. We do this here so that 12 | # settings with multiple values (e.g. ExtraDatabase) can still be added 13 | # multiple times below 14 | local KEY=${SETTING%%=*} 15 | sed -i $2 -e "/^${KEY} /d" 16 | done 17 | 18 | for SETTING in ${SETTING_LIST}; do 19 | # Split on first '=' 20 | local KEY=${SETTING%%=*} 21 | local VALUE=${SETTING#*=} 22 | echo "${KEY} ${VALUE}" >> "$2" 23 | done 24 | fi 25 | } 26 | 27 | process_file "${CLAMD_SETTINGS_CSV}" /etc/clamav/clamd.conf 28 | process_file "${FRESHCLAM_SETTINGS_CSV}" /etc/clamav/freshclam.conf 29 | 30 | # start in background 31 | freshclam -d & 32 | clamd 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2015 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /examples/clamd-api.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: clamav 5 | labels: 6 | name: clamav 7 | spec: 8 | replicas: 1 9 | selector: 10 | name: clamav 11 | template: 12 | metadata: 13 | labels: 14 | name: clamav 15 | spec: 16 | containers: 17 | - name: clamd 18 | image: quay.io/ukhomeofficedigital/clamav:v0.1.1 19 | env: 20 | - name: UPDATE 21 | value: "false" 22 | ports: 23 | - containerPort: 3200 24 | name: api 25 | protocol: TCP 26 | volumeMounts: 27 | - mountPath: /var/lib/clamav 28 | name: avdata 29 | livenessProbe: 30 | exec: 31 | command: 32 | - /readyness.sh 33 | initialDelaySeconds: 20 34 | timeoutSeconds: 2 35 | - name: freshclam 36 | image: quay.io/ukhomeofficedigital/clamav:v0.1.1 37 | env: 38 | - name: UPDATE_ONLY 39 | value: "true" 40 | volumeMounts: 41 | - mountPath: /var/lib/clamav 42 | name: avdata 43 | livenessProbe: 44 | exec: 45 | command: 46 | - /readyness.sh 47 | initialDelaySeconds: 20 48 | timeoutSeconds: 2 49 | volumes: 50 | - name: avdata 51 | source: 52 | emptyDir: {} 53 | -------------------------------------------------------------------------------- /go-clamav-rest/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e h1:rcHHSQqzCgvlwP0I/fQ8rQMn/MpHE5gWSLdtpxtP6KQ= 4 | github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e/go.mod h1:Byz7q8MSzSPkouskHJhX0er2mZY/m0Vj5bMeMCkkyY4= 5 | github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 6 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 10 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 11 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 12 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 13 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 14 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= 15 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | -------------------------------------------------------------------------------- /examples/kubernetes.md: -------------------------------------------------------------------------------- 1 | # Example use in Kubernetes 2 | 3 | ## Example POD with two processes 4 | 5 | This example will create a single POD with two containers: 6 | 7 | * clamd - will run the api 8 | * freshclam - will ensure the api has upto date virus definitions 9 | 10 | ```yaml 11 | apiVersion: v1 12 | kind: ReplicationController 13 | metadata: 14 | name: clamav 15 | labels: 16 | name: clamav 17 | spec: 18 | replicas: 1 19 | selector: 20 | name: clamav 21 | template: 22 | metadata: 23 | labels: 24 | name: clamav 25 | spec: 26 | containers: 27 | - name: clamd 28 | image: quay.io/ukhomeofficedigital/clamav:v1.6.1 29 | env: 30 | - name: UPDATE 31 | value: "false" 32 | ports: 33 | - containerPort: 3200 34 | name: api 35 | protocol: TCP 36 | volumeMounts: 37 | - mountPath: /var/lib/clamav 38 | name: avdata 39 | livenessProbe: 40 | exec: 41 | command: 42 | - /readyness.sh 43 | initialDelaySeconds: 20 44 | timeoutSeconds: 2 45 | - name: freshclam 46 | image: quay.io/ukhomeofficedigital/clamav:v1.6.1 47 | env: 48 | - name: UPDATE_ONLY 49 | value: "true" 50 | volumeMounts: 51 | - mountPath: /var/lib/clamav 52 | name: avdata 53 | livenessProbe: 54 | exec: 55 | command: 56 | - /readyness.sh 57 | initialDelaySeconds: 20 58 | timeoutSeconds: 2 59 | volumes: 60 | - name: avdata 61 | source: 62 | emptyDir: {} 63 | ``` 64 | -------------------------------------------------------------------------------- /code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of fostering an open and 4 | welcoming community, we pledge to respect all people who contribute through reporting issues, 5 | posting feature requests, updating documentation, submitting pull requests or patches, and other 6 | activities. 7 | 8 | We are committed to making participation in this project a harassment-free experience for everyone, 9 | regardless of level of experience, gender, gender identity and expression, sexual orientation, 10 | disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. 11 | 12 | Examples of unacceptable behavior by participants include: 13 | 14 | * The use of sexualized language or imagery 15 | * Personal attacks 16 | * Trolling or insulting/derogatory comments 17 | * Public or private harassment 18 | * Publishing other's private information, such as physical or electronic addresses, without explicit 19 | permission 20 | * Other unethical or unprofessional conduct. 21 | 22 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, 23 | code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By 24 | adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently 25 | applying these principles to every aspect of managing this project. Project maintainers who do not 26 | follow or enforce the Code of Conduct may be permanently removed from the project team. 27 | 28 | This code of conduct applies both within project spaces and in public spaces when an individual is 29 | representing the project or its community. 30 | 31 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an 32 | issue or contacting one or more of the project maintainers. 33 | 34 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), 35 | version 1.2.0, available at 36 | [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) 37 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | pipeline: 2 | 3 | test_build: 4 | image: docker:18.09 5 | environment: 6 | - DOCKER_HOST=tcp://172.17.0.1:2375 7 | commands: 8 | - apk add --no-cache bash sed grep bc coreutils curl 9 | - ./ci-build.sh 10 | when: 11 | event: push 12 | 13 | scan-clamav: 14 | image: quay.io/ukhomeofficedigital/anchore-submission:latest 15 | image_name: clamav 16 | when: 17 | event: push 18 | 19 | scan-clamav-rest: 20 | image: quay.io/ukhomeofficedigital/anchore-submission:latest 21 | image_name: go-clamav-rest 22 | when: 23 | event: push 24 | 25 | build_clamav: 26 | image: docker:18.09 27 | environment: 28 | - DOCKER_HOST=tcp://172.17.0.1:2375 29 | commands: 30 | - docker build -t clamav:$${DRONE_COMMIT_SHA} . 31 | when: 32 | branch: master 33 | event: [push, tag] 34 | 35 | build_clamav-rest: 36 | image: docker:18.09 37 | environment: 38 | - DOCKER_HOST=tcp://172.17.0.1:2375 39 | commands: 40 | - docker build -t go-clamav-rest:$${DRONE_COMMIT_SHA} go-clamav-rest 41 | when: 42 | branch: master 43 | event: [push, tag] 44 | 45 | clamav_to_quay: 46 | image: docker:18.09 47 | secrets: 48 | - clamav_repo_token 49 | environment: 50 | - DOCKER_HOST=tcp://172.17.0.1:2375 51 | commands: 52 | - docker login -u="ukhomeofficedigital+drone" -p=$${CLAMAV_REPO_TOKEN} quay.io 53 | - docker tag clamav:$${DRONE_COMMIT_SHA} quay.io/ukhomeofficedigital/clamav:$${DRONE_COMMIT_SHA} 54 | - docker tag clamav:$${DRONE_COMMIT_SHA} quay.io/ukhomeofficedigital/clamav:latest 55 | - docker push quay.io/ukhomeofficedigital/clamav:$${DRONE_COMMIT_SHA} 56 | - docker push quay.io/ukhomeofficedigital/clamav:latest 57 | when: 58 | branch: master 59 | event: push 60 | 61 | clamav-rest_to_quay: 62 | image: docker:18.09 63 | secrets: 64 | - clamav_repo_token 65 | environment: 66 | - DOCKER_HOST=tcp://172.17.0.1:2375 67 | commands: 68 | - docker login -u="ukhomeofficedigital+drone" -p=$${CLAMAV_REPO_TOKEN} quay.io 69 | - docker tag go-clamav-rest:$${DRONE_COMMIT_SHA} quay.io/ukhomeofficedigital/go-clamav-rest:$${DRONE_COMMIT_SHA} 70 | - docker tag go-clamav-rest:$${DRONE_COMMIT_SHA} quay.io/ukhomeofficedigital/go-clamav-rest:latest 71 | - docker push quay.io/ukhomeofficedigital/go-clamav-rest:$${DRONE_COMMIT_SHA} 72 | - docker push quay.io/ukhomeofficedigital/go-clamav-rest:latest 73 | when: 74 | branch: master 75 | event: push 76 | 77 | tagged_clamav_to_quay: 78 | image: docker:18.09 79 | secrets: 80 | - clamav_repo_token 81 | environment: 82 | - DOCKER_HOST=tcp://172.17.0.1:2375 83 | commands: 84 | - docker login -u="ukhomeofficedigital+drone" -p=$${CLAMAV_REPO_TOKEN} quay.io 85 | - docker tag clamav:$${DRONE_COMMIT_SHA} quay.io/ukhomeofficedigital/clamav:$${DRONE_TAG} 86 | - docker push quay.io/ukhomeofficedigital/clamav:$${DRONE_TAG} 87 | when: 88 | event: tag 89 | 90 | tagged_clamav-rest_to_quay: 91 | image: docker:18.09 92 | secrets: 93 | - clamav_repo_token 94 | environment: 95 | - DOCKER_HOST=tcp://172.17.0.1:2375 96 | commands: 97 | - docker login -u="ukhomeofficedigital+drone" -p=$${CLAMAV_REPO_TOKEN} quay.io 98 | - docker tag go-clamav-rest:$${DRONE_COMMIT_SHA} quay.io/ukhomeofficedigital/go-clamav-rest:$${DRONE_TAG} 99 | - docker push quay.io/ukhomeofficedigital/go-clamav-rest:$${DRONE_TAG} 100 | when: 101 | event: tag 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker ClamAV 2 | 3 | Docker container for starting a [ClamAV](http://www.clamav.net/) daemon. 4 | 5 | ## Getting Started 6 | 7 | These instructions will cover how to start a container both in Docker and within a [Kubernetes][Kubernetes link] cluster. 8 | 9 | ### Prerequisites 10 | 11 | In order to run this container you'll need docker installed. 12 | 13 | * [Windows](https://docs.docker.com/windows/started) 14 | * [OS X](https://docs.docker.com/docker-for-mac/) 15 | * [Linux](https://docs.docker.com/linux/started/) 16 | 17 | Optionally: 18 | 19 | * A [Kubernetes][Kubernetes link] cluster to enable Kubernetes api discovery of other nodes. 20 | 21 | ### Usage 22 | 23 | The example below will start a single ClamAV instance. 24 | 25 | ``` 26 | docker run --name clamav -d -p 3310:3310 quay.io/ukhomeofficedigital/clamav:latest 27 | ``` 28 | 29 | To use with [Kubernetes][Kubernetes link] see the [kubernetes examples](examples/kubernetes.md). 30 | 31 | 32 | #### Environment Variables 33 | 34 | The variables and the defaults are shown below. 35 | By default, the container does not depend on [Kubernetes][Kubernetes link]. 36 | 37 | * `CLAMD_SETTINGS_CSV="LogVerbose=yes,VirusEvent=/custom_alert.sh"` See [clamd.conf](http://linux.die.net/man/5/clamd.conf) for more details 38 | and see [./clamd.conf](./clamd.conf) for the default settings. 39 | To use specify a CSV of settings using Key=Value (not Key Value as the clamd.conf file) e.g. `"CLAMD_SETTINGS_CSV='Setting=value'"` 40 | Note, clamd has already been configured appropriately for a container but some useful settings include: 41 | * `VirusEvent=/path/to/alert_script.sh` If mounted in the container, will provide a custom alert facility 42 | * `LogClean=yes` Will log every scan performed 43 | * `FRESHCLAM_SETTINGS_CSV="LogVerbose=yes"` See [freshclam.conf](http://linux.die.net/man/5/freshclam.conf) for more details 44 | and see [./freshclam.conf](freshclam.conf) for the default settings. See above for how this works. 45 | * `UPDATE=true` (default) will start freshclam daemon in background to watch for update antivirus definitions 46 | `UPDATE=false` will watch for first successful update from separate sidecar container before starting 47 | * `UPDATE_ONLY=true` configure as a sidecar container and run the update process in the foreground 48 | `UPDATE_ONLY=false` (default) will run clamd and freshclam as normal. 49 | 50 | #### Ports 51 | 52 | This container exposes: 53 | 54 | * `3310` - Access the [Clam AV API](http://linux.die.net/man/8/clamd). 55 | 56 | ## Contributing 57 | 58 | Feel free to submit pull requests and issues. If it's a particularly large PR, you may wish to discuss 59 | it in an issue first. 60 | 61 | Please note that this project is released with a [Contributor Code of Conduct](code_of_conduct.md). 62 | By participating in this project you agree to abide by its terms. 63 | 64 | ## Versioning 65 | 66 | We use [SemVer](http://semver.org/) for versioning. For the versions available, see the 67 | [tags on this repository](https://github.com/UKHomeOffice/docker-clamav/tags). 68 | 69 | ## Authors 70 | 71 | * **Lewis Marshall** - *Initial work* - [Lewis Marshall](https://github.com/LewisMarshall) 72 | 73 | See also the list of [contributors](https://github.com/UKHomeOffice/docker-clamav/contributors) who 74 | participated in this project. 75 | 76 | ## License 77 | 78 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. 79 | 80 | ## Acknowledgments 81 | 82 | * http://www.clamav.net/ 83 | 84 | ## TODO: 85 | 86 | * Ensure the DB access doesn't need to be for user 999 (so the volume can be mounted)... 87 | * Long startup time, see point above. 88 | * Add testing for Travis 89 | 90 | 91 | [Kubernetes link]: https://kubernetes.io/ 92 | -------------------------------------------------------------------------------- /k8s/clamd-api.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: clamav 5 | labels: 6 | name: clamav 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | name: clamav 12 | template: 13 | metadata: 14 | labels: 15 | name: clamav 16 | spec: 17 | volumes: 18 | - name: secrets 19 | emptyDir: {} 20 | - name: ca-bundle 21 | secret: 22 | secretName: ca-bundle 23 | containers: 24 | - name: vault-side-kick 25 | image: quay.io/ukhomeofficedigital/vault-sidekick:v0.3.1 26 | imagePullPolicy: Always 27 | resources: 28 | limits: 29 | memory: "100Mi" 30 | cpu: 100m 31 | requests: 32 | memory: "50Mi" 33 | cpu: 100m 34 | args: 35 | - -output=/etc/secrets 36 | - -ca-cert=/ca/caroot.bundle 37 | - -cn=pki:services/${NAMESPACE}/pki/issue/default:common_name=clamav.${NAMESPACE}.svc.cluster.local,file=/etc/secrets/nginx,fmt=cert 38 | env: 39 | - name: VAULT_ADDR 40 | value: "https://vault.vault.svc.cluster.local:8200" 41 | - name: VAULT_TOKEN 42 | valueFrom: 43 | secretKeyRef: 44 | name: store-token 45 | key: token 46 | - name: NAMESPACE 47 | valueFrom: 48 | fieldRef: 49 | fieldPath: metadata.namespace 50 | volumeMounts: 51 | - mountPath: /etc/secrets 52 | name: secrets 53 | - name: ca-bundle 54 | mountPath: /ca 55 | - name: nginx 56 | image: quay.io/ukhomeofficedigital/nginx-proxy:v1.7.0 57 | imagePullPolicy: Always 58 | env: 59 | - name: PROXY_SERVICE_HOST 60 | value: 'http://127.0.0.1' 61 | - name: PROXY_SERVICE_PORT 62 | value: '8080' 63 | - name: NAXSI_USE_DEFAULT_RULES 64 | value: 'FALSE' 65 | - name: ENABLE_UUID_PARAM 66 | value: 'FALSE' 67 | - name: CLIENT_MAX_BODY_SIZE 68 | value: '10' 69 | - name: SSL_CERT 70 | value: /etc/secrets/nginx.crt 71 | - name: SSL_KEY 72 | value: /etc/secrets/nginx.key 73 | ports: 74 | - name: https 75 | containerPort: 443 76 | resources: 77 | limits: 78 | cpu: 100m 79 | memory: 400M 80 | volumeMounts: 81 | - mountPath: /etc/secrets 82 | name: secrets 83 | - name: clamd-rest 84 | image: quay.io/ukhomeofficedigital/go-clamav-rest:{{.DRONE_COMMIT_SHA}} 85 | imagePullPolicy: Always 86 | ports: 87 | - containerPort: 8080 88 | name: api 89 | protocol: TCP 90 | readinessProbe: 91 | httpGet: 92 | path: /healthz 93 | port: 8080 94 | initialDelaySeconds: 60 95 | timeoutSeconds: 10 96 | periodSeconds: 30 97 | failureThreshold: 10 98 | resources: 99 | limits: 100 | cpu: 400m 101 | memory: 1000M 102 | - name: clamd 103 | image: quay.io/ukhomeofficedigital/clamav:{{.DRONE_COMMIT_SHA}} 104 | imagePullPolicy: Always 105 | ports: 106 | - containerPort: 3310 107 | name: api 108 | protocol: TCP 109 | readinessProbe: 110 | exec: 111 | command: 112 | - /readyness.sh 113 | initialDelaySeconds: 90 114 | timeoutSeconds: 10 115 | periodSeconds: 30 116 | failureThreshold: 10 117 | resources: 118 | limits: 119 | cpu: 500m 120 | memory: 1000M 121 | -------------------------------------------------------------------------------- /ci-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | TAG=clamav 6 | COUNT=0 7 | PORT=3310 8 | 9 | function tear_down() { 10 | if [ "${TEAR_DOWN}" == "true" ]; then 11 | if docker ps -a | grep ${INSTANCE} &>/dev/null ; then 12 | if docker ps | grep ${INSTANCE} &>/dev/null ; then 13 | ${SUDO_CMD} docker stop ${INSTANCE} 14 | fi 15 | ${SUDO_CMD} docker rm ${INSTANCE} 16 | fi 17 | fi 18 | } 19 | 20 | function wait_until_started() { 21 | max_retries=10 22 | wait_time=${WAIT_TIME:-30} 23 | retries=0 24 | cmd="$*" 25 | if [[ $cmd == WARNING* ]]; then 26 | cmd="" 27 | fi 28 | while ! eval $cmd; do 29 | echo "waiting for command to succeed ('$cmd')" 30 | ((retries++)) 31 | if ((retries==max_retries)); then 32 | echo "Test Failed" 33 | return 1 34 | fi 35 | sleep "$wait_time" 36 | done 37 | echo "Test Succeeded" 38 | return 0 39 | } 40 | 41 | # Removes any old containers and images (to avoid container name conflicts) 42 | function clean_up() { 43 | if docker ps -a --filter "name=clamav" | grep clamav &>/dev/null; then 44 | echo "Removing old clamav container..." 45 | docker stop clamav &>/dev/null && docker rm clamav &>/dev/null 46 | else 47 | echo "No clamav container found." 48 | fi 49 | 50 | if docker ps -a --filter "name=go-clamav-rest" | grep go-clamav-rest &>/dev/null; then 51 | echo "Removing old clamav-rest container..." 52 | docker stop go-clamav-rest &>/dev/null && docker rm go-clamav-rest &>/dev/null 53 | else 54 | echo "No clamav-rest container found." 55 | fi 56 | 57 | action="$*" 58 | if [[ "$action" == "delete-images" ]]; then 59 | if docker images clamav | grep clamav &>/dev/null; then 60 | echo "Removing clamav image..." 61 | docker rmi clamav 62 | else 63 | echo "No clamav image found." 64 | fi 65 | 66 | if docker images go-clamav-rest | grep go-clamav-rest &>/dev/null; then 67 | echo "Removing clamav-rest image..." 68 | docker rmi go-clamav-rest 69 | else 70 | echo "No clamav-rest image found." 71 | fi 72 | fi 73 | } 74 | 75 | echo "========" 76 | echo "REMOVING OLD CONTAINERS AND IMAGES..." 77 | echo "========" 78 | clean_up 79 | 80 | echo "========" 81 | echo "BUILD..." 82 | echo "========" 83 | ${SUDO_CMD} docker build -t ${TAG} . 84 | 85 | echo "==========" 86 | echo "STARTING CLAMAV CONTAINER..." 87 | echo "==========" 88 | docker run -d --name=clamav -p ${PORT}:3310 ${TAG} 89 | 90 | echo "==========" 91 | echo "TESTING FRESHCLAM PROCESS..." 92 | echo "==========" 93 | 94 | RUN_FRESHCLAM_TEST='docker exec -t clamav sh -c "freshclam" | grep -q "bytecode.cvd already up-to-date"' 95 | if ! wait_until_started "${RUN_FRESHCLAM_TEST}"; then 96 | echo "Error, not started in time..." 97 | docker logs clamav 98 | exit 1 99 | fi 100 | 101 | echo "==========" 102 | echo "TESTING CLAMD PROCESS..." 103 | echo "==========" 104 | 105 | RUN_CLAMD_TEST='docker exec -t clamav sh -c "clamdscan /eicar.com" | grep -q "Infected files: 1"' 106 | if ! wait_until_started "${RUN_CLAMD_TEST}"; then 107 | echo "Error, not started in time..." 108 | docker logs clamav 109 | exit 1 110 | fi 111 | 112 | #testing clamd-rest container. 113 | echo "==========" 114 | echo "TESTING REST API..." 115 | echo "==========" 116 | 117 | docker build -t go-${TAG}-rest go-clamav-rest 118 | 119 | #start container. 120 | docker run -id -p 8080:8080 --name=go-clamav-rest --link clamav:clamav go-clamav-rest -host clamav 121 | sleep 30 #wait for app to start 122 | 123 | REST_CMD=$(curl -w %{http_code} -s --output /dev/null 172.17.0.1:8080) 124 | VIRUS_TEST=$(curl -s -F "name=test-virus" -F "file=@eicar.com" 172.17.0.1:8080/scan | grep -o false) 125 | 126 | if [ $REST_CMD == "200" ]; then 127 | if [ $VIRUS_TEST == "false" ]; then 128 | echo "SUCCESS rest api working and detecting viruses correctly" 129 | clean_up 130 | exit 0 131 | fi 132 | echo "FAILED rest api not detecting correctly" 133 | exit 1 134 | fi 135 | 136 | echo "rest api not starting." 137 | exit 1 138 | -------------------------------------------------------------------------------- /go-clamav-rest/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/http" 7 | 8 | "github.com/dutchcoders/go-clamd" 9 | "github.com/sirupsen/logrus" 10 | ) 11 | 12 | func RunHTTPListener(clamd_address string, port int, max_file_mem int64, logger *logrus.Logger) error { 13 | m := http.NewServeMux() 14 | hh := &healthHandler{ 15 | healthy: false, 16 | logger: logger, 17 | } 18 | m.Handle("/healthz", hh) 19 | m.Handle("/", &pingHandler{ 20 | address: clamd_address, 21 | logger: logger, 22 | }) 23 | m.Handle("/scan", &scanHandler{ 24 | address: clamd_address, 25 | max_file_mem: max_file_mem, 26 | logger: logger, 27 | }) 28 | m.Handle("/scanReply", &scanReplyHandler{ 29 | address: clamd_address, 30 | max_file_mem: max_file_mem, 31 | logger: logger, 32 | }) 33 | logger.Infof("Starting the webserver on port %v", port) 34 | lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) 35 | if err != nil { 36 | return err 37 | } 38 | hh.healthy = true 39 | return http.Serve(lis, m) 40 | } 41 | 42 | type healthHandler struct { 43 | healthy bool 44 | logger *logrus.Logger 45 | } 46 | 47 | func (hh *healthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 48 | if hh.healthy { 49 | hh.logger.Infof("health check: ok") 50 | w.WriteHeader(http.StatusOK) 51 | w.Write([]byte("Healthy\n")) 52 | return 53 | } 54 | hh.logger.Infof("health check: not ok") 55 | w.WriteHeader(http.StatusInternalServerError) 56 | w.Write([]byte("Unhealthy\n")) 57 | } 58 | 59 | type pingHandler struct { 60 | address string 61 | logger *logrus.Logger 62 | } 63 | 64 | func (ph *pingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 65 | c := clamd.NewClamd(ph.address) 66 | err := c.Ping() 67 | if err != nil { 68 | ph.logger.Infof("ping: not responding") 69 | w.WriteHeader(http.StatusOK) 70 | w.Write([]byte("Clamd responding: false\n")) 71 | return 72 | } else { 73 | w.WriteHeader(http.StatusOK) 74 | ph.logger.Infof("ping: responding") 75 | w.Write([]byte("Clamd responding: true\n")) 76 | return 77 | } 78 | } 79 | 80 | type scanHandler struct { 81 | address string 82 | max_file_mem int64 83 | logger *logrus.Logger 84 | } 85 | 86 | func (sh *scanHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 87 | err := r.ParseMultipartForm(sh.max_file_mem * 1024 * 1024) 88 | 89 | if err != nil { 90 | w.WriteHeader(http.StatusInternalServerError) 91 | w.Write([]byte("not okay")) 92 | } 93 | 94 | files := r.MultipartForm.File["file"] 95 | 96 | if len(files) == 0 { 97 | w.WriteHeader(http.StatusOK) 98 | w.Write([]byte("empty file\n")) 99 | return 100 | } 101 | 102 | f, err := files[0].Open() 103 | defer f.Close() 104 | 105 | if err != nil { 106 | w.WriteHeader(http.StatusInternalServerError) 107 | w.Write([]byte("not okay")) 108 | } 109 | 110 | c := clamd.NewClamd(sh.address) 111 | response, err := c.ScanStream(f, make(chan bool)) 112 | 113 | if err != nil { 114 | w.WriteHeader(http.StatusInternalServerError) 115 | w.Write([]byte("not okay")) 116 | } 117 | 118 | result := <-response 119 | w.WriteHeader(http.StatusOK) 120 | if result.Status == "FOUND" { 121 | sh.logger.Infof("Scanning %v: found", files[0].Filename) 122 | w.Write([]byte("Everything ok : false\n")) 123 | } else { 124 | sh.logger.Infof("Scanning %v: clean", files[0].Filename) 125 | w.Write([]byte("Everything ok : true\n")) 126 | } 127 | 128 | return 129 | } 130 | 131 | type scanReplyHandler struct { 132 | address string 133 | max_file_mem int64 134 | logger *logrus.Logger 135 | } 136 | 137 | func (srh *scanReplyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 138 | err := r.ParseMultipartForm(srh.max_file_mem * 1024 * 1024) 139 | 140 | if err != nil { 141 | w.WriteHeader(http.StatusInternalServerError) 142 | w.Write([]byte("not okay")) 143 | } 144 | 145 | files := r.MultipartForm.File["file"] 146 | 147 | if len(files) == 0 { 148 | w.WriteHeader(http.StatusOK) 149 | w.Write([]byte("empty file\n")) 150 | return 151 | } 152 | 153 | f, err := files[0].Open() 154 | defer f.Close() 155 | 156 | if err != nil { 157 | w.WriteHeader(http.StatusInternalServerError) 158 | w.Write([]byte("not okay")) 159 | } 160 | 161 | c := clamd.NewClamd(srh.address) 162 | response, err := c.ScanStream(f, make(chan bool)) 163 | 164 | if err != nil { 165 | w.WriteHeader(http.StatusInternalServerError) 166 | w.Write([]byte("not okay")) 167 | } 168 | 169 | result := <-response 170 | w.WriteHeader(http.StatusOK) 171 | srh.logger.Infof("Scanning %v and returning reply", files[0].Filename) 172 | w.Write([]byte(result.Raw)) 173 | return 174 | } 175 | -------------------------------------------------------------------------------- /freshclam.conf: -------------------------------------------------------------------------------- 1 | ## 2 | ## Example config file for freshclam 3 | ## Please read the freshclam.conf(5) manual before editing this file. 4 | ## 5 | 6 | 7 | # Comment or remove the line below. 8 | 9 | # Path to the database directory. 10 | # WARNING: It must match clamd.conf's directive! 11 | # Default: hardcoded (depends on installation options) 12 | DatabaseDirectory /var/lib/clamav 13 | 14 | # Path to the log file (make sure it has proper permissions) 15 | # Default: disabled 16 | # UpdateLogFile /dev/stdout 17 | 18 | # Maximum size of the log file. 19 | # Value of 0 disables the limit. 20 | # You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes) 21 | # and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). 22 | # in bytes just don't use modifiers. If LogFileMaxSize is enabled, 23 | # log rotation (the LogRotate option) will always be enabled. 24 | # Default: 1M 25 | #LogFileMaxSize 2M 26 | 27 | # Log time with each message. 28 | # Default: no 29 | LogTime yes 30 | 31 | # Enable verbose logging. 32 | # Default: no 33 | LogVerbose yes 34 | 35 | # Use system logger (can work together with UpdateLogFile). 36 | # Default: no 37 | LogSyslog no 38 | 39 | # Specify the type of syslog messages - please refer to 'man syslog' 40 | # for facility names. 41 | # Default: LOG_LOCAL6 42 | #LogFacility LOG_MAIL 43 | 44 | # Enable log rotation. Always enabled when LogFileMaxSize is enabled. 45 | # Default: no 46 | #LogRotate yes 47 | 48 | # This option allows you to save the process identifier of the daemon 49 | # Default: disabled 50 | #PidFile /var/run/freshclam.pid 51 | 52 | # By default when started freshclam drops privileges and switches to the 53 | # "clamav" user. This directive allows you to change the database owner. 54 | # Default: clamav (may depend on installation options) 55 | DatabaseOwner clamav 56 | 57 | # Use DNS to verify virus database version. Freshclam uses DNS TXT records 58 | # to verify database and software versions. With this directive you can change 59 | # the database verification domain. 60 | # WARNING: Do not touch it unless you're configuring freshclam to use your 61 | # own database verification domain. 62 | # Default: current.cvd.clamav.net 63 | #DNSDatabaseInfo current.cvd.clamav.net 64 | 65 | # Uncomment the following line and replace XY with your country 66 | # code. See http://www.iana.org/cctld/cctld-whois.htm for the full list. 67 | # You can use db.XY.ipv6.clamav.net for IPv6 connections. 68 | DatabaseMirror db.uk.clamav.net 69 | 70 | # database.clamav.net is a round-robin record which points to our most 71 | # reliable mirrors. It's used as a fall back in case db.XY.clamav.net is 72 | # not working. DO NOT TOUCH the following line unless you know what you 73 | # are doing. 74 | DatabaseMirror database.clamav.net 75 | 76 | # How many attempts to make before giving up. 77 | # Default: 3 (per mirror) 78 | #MaxAttempts 5 79 | 80 | # With this option you can control scripted updates. It's highly recommended 81 | # to keep it enabled. 82 | # Default: yes 83 | #ScriptedUpdates yes 84 | 85 | # By default freshclam will keep the local databases (.cld) uncompressed to 86 | # make their handling faster. With this option you can enable the compression; 87 | # the change will take effect with the next database update. 88 | # Default: no 89 | #CompressLocalDatabase no 90 | 91 | # With this option you can provide custom sources (http:// or file://) for 92 | # database files. This option can be used multiple times. 93 | # Default: no custom URLs 94 | #DatabaseCustomURL http://myserver.com/mysigs.ndb 95 | #DatabaseCustomURL file:///mnt/nfs/local.hdb 96 | 97 | # This option allows you to easily point freshclam to private mirrors. 98 | # If PrivateMirror is set, freshclam does not attempt to use DNS 99 | # to determine whether its databases are out-of-date, instead it will 100 | # use the If-Modified-Since request or directly check the headers of the 101 | # remote database files. For each database, freshclam first attempts 102 | # to download the CLD file. If that fails, it tries to download the 103 | # CVD file. This option overrides DatabaseMirror, DNSDatabaseInfo 104 | # and ScriptedUpdates. It can be used multiple times to provide 105 | # fall-back mirrors. 106 | # Default: disabled 107 | #PrivateMirror mirror1.mynetwork.com 108 | #PrivateMirror mirror2.mynetwork.com 109 | 110 | # Number of database checks per day. 111 | # Default: 12 (every two hours) 112 | #Checks 24 113 | 114 | # Proxy settings 115 | # Default: disabled 116 | #HTTPProxyServer myproxy.com 117 | #HTTPProxyPort 1234 118 | #HTTPProxyUsername myusername 119 | #HTTPProxyPassword mypass 120 | 121 | # If your servers are behind a firewall/proxy which applies User-Agent 122 | # filtering you can use this option to force the use of a different 123 | # User-Agent header. 124 | # Default: clamav/version_number 125 | #HTTPUserAgent SomeUserAgentIdString 126 | 127 | # Use aaa.bbb.ccc.ddd as client address for downloading databases. Useful for 128 | # multi-homed systems. 129 | # Default: Use OS'es default outgoing IP address. 130 | #LocalIPAddress aaa.bbb.ccc.ddd 131 | 132 | # Send the RELOAD command to clamd. 133 | # Default: no 134 | #NotifyClamd /path/to/clamd.conf 135 | 136 | # Run command after successful database update. 137 | # Default: disabled 138 | #OnUpdateExecute command 139 | 140 | # Run command when database update process fails. 141 | # Default: disabled 142 | #OnErrorExecute command 143 | 144 | # Run command when freshclam reports outdated version. 145 | # In the command string %v will be replaced by the new version number. 146 | # Default: disabled 147 | #OnOutdatedExecute command 148 | 149 | # Don't fork into background. 150 | # Default: no 151 | Foreground yes 152 | 153 | # Enable debug messages in libclamav. 154 | # Default: no 155 | #Debug yes 156 | 157 | # Timeout in seconds when connecting to database server. 158 | # Default: 30 159 | #ConnectTimeout 60 160 | 161 | # Timeout in seconds when reading from database server. 162 | # Default: 30 163 | #ReceiveTimeout 60 164 | 165 | # With this option enabled, freshclam will attempt to load new 166 | # databases into memory to make sure they are properly handled 167 | # by libclamav before replacing the old ones. 168 | # Default: yes 169 | #TestDatabases yes 170 | 171 | # When enabled freshclam will submit statistics to the ClamAV Project about 172 | # the latest virus detections in your environment. The ClamAV maintainers 173 | # will then use this data to determine what types of malware are the most 174 | # detected in the field and in what geographic area they are. 175 | # Freshclam will connect to clamd in order to get recent statistics. 176 | # Default: no 177 | #SubmitDetectionStats /path/to/clamd.conf 178 | 179 | # Country of origin of malware/detection statistics (for statistical 180 | # purposes only). The statistics collector at ClamAV.net will look up 181 | # your IP address to determine the geographical origin of the malware 182 | # reported by your installation. If this installation is mainly used to 183 | # scan data which comes from a different location, please enable this 184 | # option and enter a two-letter code (see http://www.iana.org/domains/root/db/) 185 | # of the country of origin. 186 | # Default: disabled 187 | #DetectionStatsCountry country-code 188 | 189 | # This option enables support for our "Personal Statistics" service. 190 | # When this option is enabled, the information on malware detected by 191 | # your clamd installation is made available to you through our website. 192 | # To get your HostID, log on http://www.stats.clamav.net and add a new 193 | # host to your host list. Once you have the HostID, uncomment this option 194 | # and paste the HostID here. As soon as your freshclam starts submitting 195 | # information to our stats collecting service, you will be able to view 196 | # the statistics of this clamd installation by logging into 197 | # http://www.stats.clamav.net with the same credentials you used to 198 | # generate the HostID. For more information refer to: 199 | # http://www.clamav.net/documentation.html#cctts 200 | # This feature requires SubmitDetectionStats to be enabled. 201 | # Default: disabled 202 | #DetectionStatsHostID unique-id 203 | 204 | # This option enables support for Google Safe Browsing. When activated for 205 | # the first time, freshclam will download a new database file (safebrowsing.cvd) 206 | # which will be automatically loaded by clamd and clamscan during the next 207 | # reload, provided that the heuristic phishing detection is turned on. This 208 | # database includes information about websites that may be phishing sites or 209 | # possible sources of malware. When using this option, it's mandatory to run 210 | # freshclam at least every 30 minutes. 211 | # Freshclam uses the ClamAV's mirror infrastructure to distribute the 212 | # database and its updates but all the contents are provided under Google's 213 | # terms of use. See http://www.google.com/transparencyreport/safebrowsing 214 | # and http://www.clamav.net/documentation.html#safebrowsing 215 | # for more information. 216 | # Default: disabled 217 | #SafeBrowsing yes 218 | 219 | # This option enables downloading of bytecode.cvd, which includes additional 220 | # detection mechanisms and improvements to the ClamAV engine. 221 | # Default: enabled 222 | #Bytecode yes 223 | 224 | # Download an additional 3rd party signature database distributed through 225 | # the ClamAV mirrors. 226 | # This option can be used multiple times. 227 | #ExtraDatabase dbname1 228 | #ExtraDatabase dbname2 229 | --------------------------------------------------------------------------------