Back to site

Documentation

Installation and usage guide for the DenyGrid agent and its plugins.

Installing the agent

Prerequisites

Automatic installation

With enrollment key (recommended)

Get your enrollment key from My profile → Machine enrollment key in the dashboard, then:

# Install the agent with automatic enrollment (no admin approval needed)
curl -sSL https://denygrid.com/client/install.sh | sudo bash -s -- --key VOTRE_CLE

# Install all plugins
curl -sSL https://denygrid.com/client/update_plugins.sh | sudo bash
With the enrollment key, the machine is automatically approved and linked to your account. The API key is generated and configured without any action.

Without enrollment key (admin approval)

# Install the agent + systemd service
curl -sSL https://denygrid.com/client/install.sh | sudo bash

# Install all plugins
curl -sSL https://denygrid.com/client/update_plugins.sh | sudo bash
Without an enrollment key, the machine appears as "pending approval" in the dashboard. An administrator must approve it manually.

The agent is installed in /opt/security-monitor/ and creates a systemd service security-monitor.

Manual installation

mkdir -p /opt/security-monitor
cd /opt/security-monitor
curl -sSL https://denygrid.com/client/agent.py -o agent.py
curl -sSL https://denygrid.com/client/config.json.example -o config.json
chmod 600 config.json
# Edit config.json with your API key
nano config.json

Configuration

The file /opt/security-monitor/config.json holds the entire configuration:

{
  "api_url": "https://denygrid.com/api",
  "api_key": "",
  "enrollment_key": "",
  "machine_alias": "Production Server",
  "scan_interval": 60,
  "auto_register": true,
  "auto_update": true,
  "verify_ssl": true,
  "plugins": {
    "http":     { "enabled": true },
    "firewall": { "enabled": true },
    "ftp":      { "enabled": false },
    "smtp":     { "enabled": false },
    "mysql":    { "enabled": false },
    "pam":      { "enabled": false }
  }
}
OptionDescriptionDefault
api_urlURL of the DenyGrid server API
api_keyAPI key (generated automatically after enrollment)empty
enrollment_keyEnrollment key for auto-approval (from My profile)empty
machine_aliasName shown in the dashboardhostname
scan_intervalCollection frequency in seconds60
auto_registerAutomatic machine registrationtrue
auto_updateAutomatic agent updatetrue
verify_sslVerify the server's SSL certificatetrue
The enrollment key is available in the dashboard: My profile → Machine enrollment key. If you use the --key option at install time, the API key is generated and configured automatically. Without an enrollment key, the machine requires manual approval by an administrator. You can regenerate your key at any time from your profile (the old one will be invalidated).

Updating

WhatCommand
Agent only curl -sSL https://denygrid.com/client/update_agent.sh | sudo bash
All plugins curl -sSL https://denygrid.com/client/update_plugins.sh | sudo bash
Specific plugin curl -sSL .../client/install_plugin_http.sh | sudo bash

The update script creates an automatic backup and preserves the configuration.

SSH plugin built-in

SSH collection is built into the agent — no plugin to enable.

Event typeDescription
ssh_failedFailed login attempt
ssh_invalid_userNon-existent user
ssh_successSuccessful login
ssh_closedConnection closed

Log sources: /var/log/auth.log, /var/log/secure, journalctl -u sshd

HTTP / WordPress plugin enabled by default

Analyzes Apache and Nginx logs to detect web attacks, scans, CVEs and WordPress attempts.

Configuration

"http": {
  "enabled": true,
  "auto_discover": true,    // auto-scan of log directories
  "log_paths": [],           // manual paths (optional)
  "max_log_files": 100,
  "scan_threshold": 10,      // 404 threshold for scan detection
  "scan_window": 60          // window in seconds
}

Event types

EventDescription
http_sql_injectionSQL injection attempt
http_xss_attemptXSS attempt
http_suspicious_pathSuspicious path (traversal, config...)
http_scan_detectedDirectory scan (404 burst)
http_ddos_detectedDDoS (100+ req/5min per IP)
http_slowloris_detectedSlowloris attack
http_backdoor_detectedBackdoor access attempt
http_cve_*CVE exploitation (Log4j, Spring4Shell...)
wp_login_failedFailed WordPress login
wp_xmlrpc_attackXML-RPC attack
wp_brute_forcewp-login brute force
wp_plugin_scanWordPress plugin scan
wp_shell_uploadShell upload attempt

Scanned directories: /var/log/apache2, /var/log/nginx, /var/log/httpd

CrowdSec lists: 1080+ patterns included (587 user-agents, 209 backdoors, 93 sensitive data, CVEs).

FTP plugin opt-in

Monitors vsftpd, proftpd and pure-ftpd.

Enabling

# Via the installation script (recommended)
curl -sSL https://denygrid.com/client/install_plugin_ftp.sh | sudo bash

# Or manually in config.json
"ftp": { "enabled": true }
EventDescription
ftp_failedFailed login
ftp_invalid_userNon-existent user
ftp_successSuccessful login
ftp_connectIncoming connection

SMTP plugin opt-in

Monitors Postfix, Exim4, Sendmail and Dovecot. 18 detection patterns covering authentication, relay, spam and scans.

Enabling

"smtp": { "enabled": true }

Event types

EventDescription
smtp_auth_failedSASL authentication failure
smtp_auth_abortAuthentication aborted
smtp_brute_forceBrute force detected (5+ failures/IP)
smtp_relay_deniedRelay attempt denied
smtp_relay_scanOpen relay scan (3+ attempts)
smtp_scan_detectedSMTP scan
smtp_spam_attemptSpam attempt (10+ sends)
smtp_rate_abuseRate limit exceeded
smtp_tls_errorTLS error
smtp_helo_rejectedHELO/EHLO rejected

Sources: /var/log/mail.log, /var/log/maillog, journalctl -u postfix -u exim4

MySQL plugin opt-in

Monitors MySQL and MariaDB: authentication failures, SQL injections, privilege abuse.

Enabling

"mysql": {
  "enabled": true,
  "monitor_queries": false   // true = also monitors dangerous queries
}

Event types

EventDescription
mysql_auth_failedAccess denied
mysql_brute_forceBrute force detected
mysql_root_attemptroot login from the network
mysql_sql_injectionDangerous query (DROP, LOAD DATA...)
mysql_privilege_abusePrivilege escalation
mysql_connect_scanMySQL port scan

Sources: /var/log/mysql/error.log, /var/log/mariadb/mariadb.log, journalctl -u mysql -u mariadb

PAM / System plugin opt-in

Monitors system authentications: sudo, su, cron, PAM sessions.

Enabling

"pam": {
  "enabled": true,
  "monitor_cron_exec": false  // true = monitors cron executions
}

Event types

EventDescription
pam_auth_failedPAM authentication failure
pam_brute_forcePAM brute force detected
pam_sudo_failedsudo command denied
pam_su_failedUser switch denied
pam_account_lockedAccount locked
pam_account_expiredAccount expired
system_login_failedSystem login failure

Sources: /var/log/auth.log, /var/log/secure, journalctl -t sudo -t su -t login

Firewall plugin enabled by default

Automatically applies dashboard bans via iptables. Fetches the blacklist every 5 minutes.

Configuration

"firewall": {
  "enabled": true,
  "check_interval": 300,    // seconds between each sync
  "backend": "iptables",
  "auto_unban": true,        // auto-unban when removed from the dashboard
  "chain_name": "SECURITY_MONITOR"
}

Verification

# View the active rules
iptables -L SECURITY_MONITOR -n -v

# Count the banned IPs
iptables -L SECURITY_MONITOR -n | grep DROP | wc -l
The Firewall plugin requires root privileges and iptables installed.

MikroTik / RouterOS v7 gateway

Monitor one or more MikroTik (RouterOS v7) routers without installing anything on them. A connector runs on a Linux VM or host: it reads each router's log through the RouterOS API, reports intrusion attempts to DenyGrid, and pushes the resulting bans into an address-list on the router.

How it works

  1. Each router is enrolled as a full DenyGrid machine.
  2. The connector reads /log and extracts login failures (SSH, Winbox, FTP, Telnet, API, web).
  3. DenyGrid decides the bans (reputation, classification, autoban) — server-side logic is unchanged.
  4. Bans (single IPs and /24 ranges) are pushed to the address-list with a timeout matching the ban duration.
  5. Your router therefore benefits from the whole DenyGrid network intelligence, not just its own detections.

Requirements

1. Prepare the router

Repeat on every router. Replace A.B.C.D with the IP address of the host running the connector.

RouterOS permissions are policy-based, with no per-command ACL. Least privilege is therefore achieved with a restricted group, an account locked to the connector's IP, and the API service restricted to that same IP. This account cannot open a shell, manage users, or read secrets.

Least-privilege group

/user group add name=denygrid-api \
  policy=read,write,api \
  comment="DenyGrid connector - least privilege"

Service account, locked to the connector's IP

/user add name=denygrid-svc group=denygrid-api \
  password="STRONG_PASSWORD" \
  address=A.B.C.D/32 \
  comment="DenyGrid connector"

Enable the encrypted binary API (port 8729)

/certificate add name=denygrid-api common-name=router days-valid=3650
/certificate sign denygrid-api

/ip service set api-ssl certificate=denygrid-api disabled=no address=A.B.C.D/32

This uses the dedicated binary API: the web service (www/www-ssl) stays disabled. Since the certificate is self-signed, keep "verify_tls": false for this router in the connector configuration.

Login failure logging

/system logging action set memory memory-lines=1000

RouterOS already logs login failures. Increasing the buffer depth avoids losing attempts between two polls.

Blocking rule

// gateway
/ip firewall raw add chain=prerouting action=drop \
  src-address-list=denygrid-blocked comment=denygrid-managed

The connector creates this rule automatically on its first run — you do not need to enter it. It sits in raw/prerouting, so banned IPs are dropped before connection tracking, which also protects routed traffic — the network behind the router.

2. Install the connector

On the Linux VM. The installer detects whether it runs as root or unprivileged, installs dependencies in an isolated Python environment, generates the configuration interactively (enrollment key, then first router), and sets up the service.

With root privileges (system-wide install, systemd service)

curl -sSLO https://denygrid.com/client/mikrotik-connector/install.sh
chmod +x install.sh && sudo ./install.sh

Without any privileges (installs into your home directory)

curl -sSLO https://denygrid.com/client/mikrotik-connector/install.sh
chmod +x install.sh && ./install.sh

On a host without sudo, become root with su - then run the installer.

What the installer does in each context

RootNon-root
Directory/opt/denygrid-mikrotik$HOME/denygrid-mikrotik
Dependenciesisolated Python environment (venv)venv, otherwise pip --user
Accountdedicated denygrid system accountthe current user
Servicesystemduser systemd, otherwise @reboot cron

3. Add more routers

A single connector monitors as many routers as needed. The command is interactive and restarts the service.

sudo ./install.sh --add-router

Check that it works

  1. Each router shows up under Machines, with a mikrotik/… agent version.
  2. Trigger a failed SSH login on the router: the attempt should appear under Events within a minute.
  3. On the router, the ban list should fill up:
    /ip firewall address-list print count-only where list=denygrid-blocked
  4. Follow the connector's activity:
    journalctl -u denygrid-mikrotik -f

Available settings

The config.json file is generated by the installer. These per-router options are optional — the defaults suit most setups.

OptionDefaultPurpose
poll_interval60Log polling period, in seconds.
sync_interval300Minimum interval between two full address-list synchronisations. Reading the whole list is expensive: spacing it out keeps attempt reporting responsive.
push_delay_ms5Pause between two writes to the router, to avoid overloading it during a large batch of additions.
timeout_refresh_interval3600Refresh interval for the ban durations already in place.
address_listdenygrid-blockedName of the address-list managed on the router.
service_mapRouterOS service → DenyGrid event type mapping.

Good to know

Downloads

Auto-ban

The system automatically detects malicious IPs and bans them according to rules configurable from the dashboard (Menu → Auto-ban).

Default rules

RuleThresholdWindowBan duration
SSH Brute Force3 events15 min5 days
HTTP CVE3 events15 min30 days
HTTP attacks5 events15 min7 days
FTP Brute Force5 events30 min1 day
SMTP Brute Force5 events15 min1 day
SMTP Scan3 events15 min7 days
SMTP Relay Abuse5 events30 min2 days
SMTP Spam / Rate10 events1h7 days

Advanced options

Troubleshooting

The agent does not start

# Check the status
systemctl status security-monitor

# View the logs
journalctl -u security-monitor -f

# Test manually
python3 /opt/security-monitor/agent.py

Plugins do not load

# Check the logs
journalctl -u security-monitor | grep -i plugin

# Check permissions
ls -la /opt/security-monitor/plugins/

# Update the plugin system
curl -sSL https://denygrid.com/client/update_agent.sh | sudo bash

IPs are not banned automatically

The dashboard is slow

Buffer stuck

# Check the buffer size
ls -lh /opt/security-monitor/log_buffer.json

# If too large, reset it
sudo systemctl stop security-monitor
sudo rm /opt/security-monitor/log_buffer.json
sudo systemctl start security-monitor
DenyGrid Security Monitor — Back to siteDashboard