Collect GravityZone Cloud events (antimalware, firewall, ransomware, incidents…) in Logsign as syslog, through Bitdefender's Event Push Service Connector.
How it works
GravityZone Cloud cannot send events to a syslog server directly; it only delivers them as HTTPS POST requests. A small Linux server sits in between: the connector receives the events from GravityZone over HTTPS and forwards them to Logsign as syslog.
GravityZone Cloud (Event Push Service) → HTTPS :60001 → Firewall / NAT → Connector (gz-evpsc, Ubuntu 24.04) → syslog TCP :515 / UDP :514 → Logsign SIEM
The direction matters: the Bitdefender cloud opens the connection, from the internet inwards. The connector therefore needs a publicly reachable IP (or a NAT rule). Logsign does not need to be exposed at all; the connector only has to reach it over the internal network.
Requirements
| Component | Requirement |
|---|---|
| Connector server | Ubuntu 24.04 LTS, amd64 (fresh installation; the Bitdefender repository publishes no ARM packages) · 1 CPU · 2 GB RAM · 80 GB disk · 1 Gbit NIC. This sizing covers about 15,000 endpoints; CPU and network usage grow with the number of endpoints. |
| Network | A TCP port above 1024 on your public IP (or FQDN) NATed to the connector. This guide uses 60001. The connector needs internet access (Bitdefender repository and API) and access to Logsign on 515/TCP (or 514/UDP). |
| GravityZone | A cloud console user who can create API keys (the key needs the Event Push Service API enabled). |
| Logsign | The Bitdefender GravityZone source (Vendor Bitdefender / Product GravityZone, CEF). It ships with the product. |
Why the port must be above 1024: the service does not run as root but as the bitdefender-evpsc user, and a non-root process cannot listen on ports below 1024.
Step 0 — Define your values once
The environment-specific values are written to a file once; every later command reads them from there, so you never have to edit a command by hand.
On the connector server, change the first three lines to match your environment and run:
LOGSIGN_IP='10.10.6.207' # Logsign SIEM IP address
CONNECTOR_PORT='60001' # port GravityZone connects to (>1024)
PUBLIC_URL='https://203.0.113.10:60001/api' # public IP or FQDN + NAT port + /api
# Generate the connector password (a random value, DIFFERENT from the GravityZone API key)
CONNECTOR_AUTH="Basic $(printf 'logsign:%s' "$(openssl rand -hex 16)" | base64 -w 0)"
# Save the values to a file only you can read
( umask 077; cat > ~/gz-evpsc.env <<EOF
LOGSIGN_IP='${LOGSIGN_IP}'
CONNECTOR_PORT='${CONNECTOR_PORT}'
PUBLIC_URL='${PUBLIC_URL}'
CONNECTOR_AUTH='${CONNECTOR_AUTH}'
EOF
)
cat ~/gz-evpsc.env⚠ Why CONNECTOR_AUTH starts with "Basic ": the connector compares the
Authorizationheader of each request with the stored value character by character. A missingBasicprefix, a case difference or a single extra space results in401 Invalid Authentication Credentials. That is why the same value is carried from this file into the configuration, the test and the GravityZone settings.
The file is created with umask 077 so that only you can read it. The umask is kept inside the parentheses (a subshell): if it stayed in your shell, sudo ./config.sh in step 3 would also write config.json readable by root only, and the service, which runs as bitdefender-evpsc, could not start.
Step 1 — Firewall and NAT
NAT 60001/TCP on your public IP to 60001/TCP on the connector server. Allow the rule only from the Bitdefender addresses below; the Event Push Service connects from these addresses.
- 34.148.142.174
- 34.126.111.12
- 34.48.74.208
- 35.198.138.109
- 35.246.228.213
- 35.234.118.64
- 34.159.83.241
- 34.159.47.15
- 34.159.150.228
- 34.85.152.87
- 34.85.155.173
- 34.90.162.143
- 34.91.218.129
- 35.204.90.200
- 34.90.110.196
- 34.147.0.186
- 34.129.193.31
- 35.186.164.19
- 34.85.235.116
- 5.135.193.99
Internally, 515/TCP must be open from the connector to Logsign; 514/UDP if you use UDP.
Step 2 — Install the connector
Add the Bitdefender repository together with its signing key and install the package:
sudo install -d -m 0755 /etc/apt/keyrings curl -fsSL https://download.bitdefender.com/repos/gzrepos.key.asc | sudo tee /etc/apt/keyrings/bitdefender-gz.asc > /dev/null echo "deb [signed-by=/etc/apt/keyrings/bitdefender-gz.asc] http://download.bitdefender.com/repos/deb-hydra24-evpsc/ bitdefender non-free" | sudo tee /etc/apt/sources.list.d/bitdefender-gz-evpsc.list sudo apt update sudo apt install -y gz-evpsc
Do not install Node.js separately:
gz-evpsc1.1.0 is a Node.js service. The Bitdefender repository brings Node.js itself (nodejs 26.x, nodesource) together with its helper packages; they are built against Ubuntu 24.04 libraries, which is why Bitdefender requires 24.04. Do not install Node.js from any other source (snap, a different nodesource repository); the versions can conflict.
Check that the package came from the right repository:
apt-cache policy gz-evpsc | head -4 node --version
# expected: gz-evpsc: Installed: 1.1.0-1 ... v26.2.0
Step 3 — Configure and start the connector
config.sh resolves its file paths relative to its own directory, so change into that directory first; run from anywhere else, it writes the configuration and certificates to the wrong place.
source ~/gz-evpsc.env cd /opt/bitdefender/gz-evpsc sudo ./config.sh "$CONNECTOR_PORT" 515 Tcp "$LOGSIGN_IP" "$CONNECTOR_AUTH" config.json sudo systemctl enable --now gz-evpsc sudo systemctl restart gz-evpsc
Logsign also listens on UDP/514. To use UDP, write 514 Udp instead of 515 Tcp in the config.sh line:
source ~/gz-evpsc.env cd /opt/bitdefender/gz-evpsc sudo ./config.sh "$CONNECTOR_PORT" 514 Udp "$LOGSIGN_IP" "$CONNECTOR_AUTH" config.json sudo systemctl restart gz-evpsc
TCP is recommended: if Logsign cannot be reached, the connector logs an error. With UDP, an event dropped on the way is lost without a trace.
| Parameter | Value in this guide | Description |
|---|---|---|
PORT |
60001 |
Port GravityZone connects to; the connector listens for HTTPS on it. |
SYSLOGPORT |
515 |
Logsign's syslog port: 515 for TCP, 514 for UDP. |
TRANSPORT |
Tcp |
Tcp or Udp, spelled exactly like this (first letter capital only). TCP or tcp raises no error but silently falls back to UDP; UDP sent to 515 never reaches Logsign. |
TARGET |
Logsign IP | Address of the SIEM that receives the syslog. |
AUTH |
Basic … |
Connector password generated in step 0. Must be different from the GravityZone API key. |
CONFIG_FILENAME |
config.json |
Do not change. The service unit reads this file name; with any other name the service starts with an old or empty configuration. |
Check that the service is up and listening:
source ~/gz-evpsc.env systemctl is-active gz-evpsc sudo ss -ltnp | grep ":$CONNECTOR_PORT" sudo tail -n 20 /opt/bitdefender/var/log/gz-evpsc/log.txt
# expected:
active
LISTEN 0 511 *:60001 *:* users:(("node",...))
...
Listening on port 60001Optional: CA-signed certificate
On its first run, config.sh generates a self-signed certificate named CN=gz-evpsc (valid for 30 days, the openssl default). With requireValidSslCertificate:false in GravityZone the connection keeps working after it expires. For production, Bitdefender recommends a certificate from a public CA:
sudo cp your.key /opt/bitdefender/gz-evpsc/api/config/server.key sudo cp your.crt /opt/bitdefender/gz-evpsc/api/config/server.crt # including the chain (fullchain) sudo chown bitdefender-evpsc:bitdefender-evpsc /opt/bitdefender/gz-evpsc/api/config/server.* sudo systemctl restart gz-evpsc
In that case set requireValidSslCertificate to true in step 7. The Bitdefender cloud cannot validate a certificate signed by an internal (private) CA; keep the value false then.
Step 4 — Add the source in Logsign
The device that sends syslog to Logsign is the connector server, not the cloud. Add a new source in the Logsign UI (Data Collection):
| Field | Value |
|---|---|
| Vendor / Product |
Bitdefender / GravityZone
|
| IP | The connector server's internal IP address (the address it reaches Logsign from) |
| Collector | Syslog |
Step 5 — Test the connector locally
Without touching GravityZone, send sample CEF events to Logsign through the connector. The test events are written to a file first, so no quoting can break on the command line.
source ~/gz-evpsc.env
cat > /tmp/gz-test.json <<'EOF'
{
"cef": "0",
"events": [
"CEF:0|Bitdefender|GravityZone|6.4.0-8|70000|Registration|3|BitdefenderGZModule=registration dvchost=TEST_ENDPOINT BitdefenderGZComputerFQDN=test.example.com dvc=192.168.1.2",
"CEF:0|Bitdefender|GravityZone|6.4.0-8|35|Product ModulesStatus|5|BitdefenderGZModule=modules dvchost=TEST_ENDPOINT BitdefenderGZComputerFQDN=test.example.com dvc=192.168.1.2"
]
}
EOF
curl -k -sS -o /dev/null -w 'HTTP %{http_code}\n' \
-H "Authorization: $CONNECTOR_AUTH" \
-H 'Content-Type: application/json' \
--data-binary @/tmp/gz-test.json \
"https://127.0.0.1:$CONNECTOR_PORT/api"# expected: HTTP 200
After the 200, the events show up in Logsign within seconds, under the source you added in step 4:
Test events in Logsign.
| Result | Meaning |
|---|---|
HTTP 401 |
The password does not match. You may have run config.sh without sourcing the file from step 0. Check: sudo grep authentication_string /opt/bitdefender/gz-evpsc/api/config/config.json
|
Connection refused |
The service is not running or listens on a different port. Check the log file (step 3). |
| 200, but nothing in Logsign | Syslog does not reach Logsign. Error from syslog network in the connector log means it cannot connect to 515/TCP (firewall or TARGET IP). On Logsign, run tcpdump -ni any tcp port 515 and host <connector-ip> (udp port 514 for UDP); if packets arrive but no events appear, check the source IP (step 4). |
Step 6 — Create the GravityZone API key
GravityZone also has to be told where to send the events. This setting is not available in the UI; it is configured through the API only. First create an API key:
Sign in to cloudgz.gravityzone.bitdefender.com with an authorized user and open My Account from the user menu in the upper-right corner.
In the Control Center API section at the bottom of the page, note the Access URL, then click Add.
Give the key a description and enable only the Event Push Service API. No other API is needed; extra permissions only increase the damage if the key leaks.
⚠ The key is shown only once. After you close the window, GravityZone cannot display it again. Copy it and save it right away with the command below.
On the connector server, save the key and the Access URL you noted above. The command asks for the key without echoing it:
read -rsp 'GravityZone API key: ' GZ_API_KEY; echo GZ_API_URL='https://cloudgz.gravityzone.bitdefender.com/api' # Access URL from the My Account page # Bitdefender format: "<key>:" (colon APPENDED to the key), THEN base64 GZ_API_AUTH="Basic $(printf '%s:' "$GZ_API_KEY" | base64 -w 0)" printf "GZ_API_URL='%s'\nGZ_API_AUTH='%s'\n" "$GZ_API_URL" "$GZ_API_AUTH" >> ~/gz-evpsc.env unset GZ_API_KEY
⚠ The order matters: the colon is appended to the key before base64 encoding (
key:→ base64). Appending the colon to the base64 output, or leaving it out, results in401.
Step 7 — Point GravityZone to the connector
setPushEventSettings tells GravityZone where to send the events, with which password and in which format. The url and authorization values are filled in automatically from the file created in step 0:
source ~/gz-evpsc.env
cat > /tmp/gz-push.json <<EOF
{
"id": "1",
"jsonrpc": "2.0",
"method": "setPushEventSettings",
"params": {
"status": 1,
"serviceType": "cef",
"serviceSettings": {
"url": "${PUBLIC_URL}",
"authorization": "${CONNECTOR_AUTH}",
"requireValidSslCertificate": false
},
"subscribeToEventTypes": {
"adcloudgz": true, "antiexploit": true, "aph": true, "av": true, "avc": true,
"dp": true, "endpoint-moved-in": true, "endpoint-moved-out": true,
"exchange-malware": true, "exchange-user-credentials": true, "fw": true,
"hd": true, "hwid-change": true, "install": true, "modules": true,
"network-monitor": true, "network-sandboxing": true, "new-incident": true,
"ransomware-mitigation": true, "registration": true, "supa-update-status": true,
"sva": true, "sva-load": true, "task-status": true,
"troubleshooting-activity": true, "uc": true, "uninstall": true
}
}
}
EOF
curl --tlsv1.2 -sS -X POST "$GZ_API_URL/v1.0/jsonrpc/push" \
-H "Authorization: $GZ_API_AUTH" \
-H 'Content-Type: application/json' \
--data-binary @/tmp/gz-push.json; echo# expected:
{"id":"1","jsonrpc":"2.0","result":true}requireValidSslCertificate: keep it false while the connector uses its self-signed certificate (the default). Set it to true if you installed a public CA certificate (step 3).
Step 8 — Verify
The setting can take about 10 minutes to take effect. Then read back the cloud-side settings:
source ~/gz-evpsc.env
curl --tlsv1.2 -sS -X POST "$GZ_API_URL/v1.0/jsonrpc/push" \
-H "Authorization: $GZ_API_AUTH" \
-H 'Content-Type: application/json' \
--data-binary '{"id":"3","jsonrpc":"2.0","method":"getPushEventSettings","params":{}}'; echoThe response should show "status":1, "serviceType":"cef" and your own url (the authorization field is masked as ********). Then send a real test event from the cloud:
source ~/gz-evpsc.env
curl --tlsv1.2 -sS -X POST "$GZ_API_URL/v1.0/jsonrpc/push" \
-H "Authorization: $GZ_API_AUTH" \
-H 'Content-Type: application/json' \
--data-binary '{"id":"4","jsonrpc":"2.0","method":"sendTestPushEvent","params":{"eventType":"av"}}'; echoThe response contains the sample event that was sent (EICAR-Test-File (not a virus), "_testEvent_":true). Unlike the local test in step 5, this event comes from the Bitdefender cloud through your NAT. If it appears in Logsign, the whole chain works:
The cloud test event in Logsign: EventSource.Vendor=Bitdefender, Product=GravityZone, PrefixID=4221.
You can also confirm in the log file that the event reached the connector:
sudo grep -E 'Event key|Sent to syslog|Invalid|Error' /opt/bitdefender/var/log/gz-evpsc/log.txt | tail -n 20
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| Local test works, nothing arrives from the cloud | Inbound access problem. Run sudo tcpdump -ni any tcp port 60001 on the connector and repeat sendTestPushEvent. No packets: the NAT rule or the IP allow list is missing (step 1). Packets arrive but no events: look for Invalid Authentication in the log file; the password sent in step 7 differs from the one in the configuration. |
| Some events arrive, others do not | Some of the 20 addresses from step 1 are missing from the NAT rule; the Event Push Service sends from more than one address. |
setPushEventSettings returns 401 / authorization error |
The GravityZone API key is encoded incorrectly (colon order in step 6), or the key does not have the Event Push Service API enabled. |
Unable to locate package gz-evpsc |
The server is not amd64 (ARM), or apt update could not read the repository line. The Bitdefender repository publishes amd64 packages only. |
apt install fails on dependencies |
The server is not Ubuntu 24.04, or Node.js was installed from another source. Start from a fresh 24.04 installation. |
NO_PUBKEY / signature error |
The key line in step 2 was skipped, or the signed-by path is mistyped. Key fingerprint: C532 9775 381A 091A 268B F331 887A 41B4 AF60 56F5. |
| Service keeps restarting |
config.sh was probably run outside /opt/bitdefender/gz-evpsc (the certificate files are not found). Repeat step 3 from that directory. |
Sources: Bitdefender — Event Push Service connector · setPushEventSettings
Verified 2026-09-21: steps 0–5 run on a fresh Ubuntu 24.04 (amd64) · gz-evpsc 1.1.0-1 · syslog TCP/515 and UDP/514