A Go-based proxy server for InfluxDB v1 that filters and rejects expensive queries to protect your database from performance issues.
- Query Filtering: Automatically rejects queries without time filters
- Time Range Validation: Prevents queries with excessively long time ranges
- Measurement Control: Optional whitelist of allowed measurement names
- Configurable Rules: Customizable filtering rules via configuration file
- Performance Protection: Guards against expensive operations that could impact database performance
- Logging: Comprehensive logging of filtered queries and proxy activity
- Health Checks: Built-in health check endpoints
- Metrics: Metrics endpoint for monitoring
- IP Blacklisting: Configure IP addresses/CIDR ranges that should go through the filtering rules
- IP Whitelisting: Configure trusted IP addresses/CIDR ranges that bypass all filtering rules
Clone the repository:
git clone https://github.com/greyorange-labs/influxdb-proxy.git
cd influxdb-proxy
Install dependencies:
go mod download
Configure the proxy by editing config.yaml
:
influxdb:
host: "localhost"
port: 8086
username: ""
password: ""
database: ""
proxy:
port: 8087
host: "localhost"
base_path: "/" # Base path for all routes (default: "/")
# Example: "/proxy" makes endpoints available at /proxy/query, /proxy/write, etc.
whitelisted_ips: # IPs that bypass all filtering rules
# - "192.168.1.100" # Example: specific IP
# - "10.0.0.0/8" # Example: CIDR range
# - "127.0.0.1" # Example: localhost
blacklisted_ips: # IPs that are filtered even when disable_query_filtering is true
# - "192.168.1.50" # Example: specific IP to always filter
# - "172.16.0.0/12" # Example: CIDR range to always filter
influxdb_client:
timeout_seconds: 120 # Max timeout (default: 120 seconds)
idle_connection_pool_size: 200 # How many idle connections to keep to InfluxDB
max_concurrent_connections: 400 # Max active connections to InfluxDB
read_timeout_seconds: 60 # HTTP read timeout
idle_timeout_seconds: 120 # HTTP idle timeout (keep-alive)
server_timeouts: # HTTP server timeout settings (defaults to 2x client timeouts)
# read_timeout_seconds: 60 # Server read timeout (default: 2x client read timeout)
# write_timeout_seconds: 240 # Server write timeout (default: 2x client write timeout)
# idle_timeout_seconds: 240 # Server idle timeout (default: 2x client idle timeout)
## Request throttling settings
throttling:
max_concurrent_requests: 100 # Max concurrent requests to InfluxDB (default: 100)
request_timeout_seconds: 30 # Timeout for throttled requests (default: 30)
# Path to external filtering rules file
# If specified, this file will be loaded for filtering rules
# If not specified, inline filtering rules will be used
filtering_rules_file: "filtering_rules.yaml"
# filtering_rules:
require_time_filter: true
max_time_range_hours: 840 # 35 days max time range
warn_query_duration_hours: 336 # Warn if query takes longer than 14 days
warn_on_regex_usage: true # Log warning when queries use regex operators (=~ or !~)
block_regex_usage: false # Block queries with regex operators
block_wildcard_select: false # Block SELECT * without LIMIT
block_unlimited_group_by: false # Block GROUP BY without LIMIT or time bucketing
block_expensive_shows: false # Block SHOW SERIES without LIMIT
max_show_series_limit: 10000 # Max LIMIT for SHOW SERIES queries
max_offset_limit: 10000 # Maximum allowed OFFSET value in queries (0 = disabled)
allowed_measurements: # If not empty, only allow queries on these measurements
# - "cpu" # Example: allow queries on 'cpu' measurement
# - "memory" # Example: allow queries on 'memory' measurement
blocked_functions:
# - "count(*)" # Block count(*) without WHERE clause
blocked_statements:
- "DELETE" # Block DELETE statements
# - "DROP" # Block DROP statements
require_time_filter: true
max_time_range_hours: 840 # 35 days max time range
# Performance filtering
block_wildcard_select: false # Block SELECT * without LIMIT
block_unlimited_group_by: false # Block GROUP BY without LIMIT or time bucketing
block_expensive_shows: false # Block SHOW SERIES without LIMIT
max_show_series_limit: 10000 # Max LIMIT for SHOW SERIES queries
# Measurement-based filtering
allowed_measurements: # If not empty, only allow queries on these measurements
# - "cpu" # Example: allow queries on 'cpu' measurement
# - "memory" # Example: allow queries on 'memory' measurement
# - "disk" # Example: allow queries on 'disk' measurement
# Function/statement filtering
blocked_functions:
# - "count(*)" # Block count(*) without WHERE clause
blocked_statements:
- "DELETE" # Block DELETE statements
- "DROP" # Block DROP statements
logging:
level: "info"
format: "json" # json or text
metrics:
enabled: true
Run the proxy:
go run cmd/proxy/main.go
The proxy uses a YAML configuration file (config.yaml
) with the following main sections:
influxdb.host
: Hostname of the target InfluxDB instanceinfluxdb.port
: Port of the target InfluxDB instanceinfluxdb.username
: InfluxDB username (optional)influxdb.password
: InfluxDB password (optional)influxdb.database
: Default database name (optional)
proxy.port
: Port for the proxy server (default: 8087)proxy.host
: Host interface to bind to (default: "localhost")proxy.base_path
: Base path prefix for all routes (default: "/")- Example: Setting to "/proxy" makes endpoints available at
/proxy/query
,/proxy/write
, etc. - Useful for mounting the proxy behind reverse proxies or in containerized environments
- Example: Setting to "/proxy" makes endpoints available at
proxy.disable_query_filtering
: Disable all query filtering (default: false)proxy.whitelisted_ips
: List of IP addresses/CIDR ranges that bypass all filtering rulesproxy.blacklisted_ips
: List of IP addresses/CIDR ranges that are filtered even whendisable_query_filtering
is true
proxy.influxdb_client.timeout_seconds
: Maximum timeout in seconds (default: 120)proxy.influxdb_client.idle_connection_pool_size
: Number of idle connections to keep to InfluxDB (default: 200)proxy.influxdb_client.max_concurrent_connections
: Maximum active connections to InfluxDB (default: 400)proxy.influxdb_client.read_timeout_seconds
: HTTP read timeout for requests (default: 60)proxy.influxdb_client.idle_timeout_seconds
: HTTP idle timeout for keep-alive connections (default: 120)
proxy.server_timeouts.read_timeout_seconds
: HTTP server read timeout (default: 2x InfluxDB client read timeout)proxy.server_timeouts.write_timeout_seconds
: HTTP server write timeout (default: 2x InfluxDB client write timeout)proxy.server_timeouts.idle_timeout_seconds
: HTTP server idle timeout (default: 2x InfluxDB client idle timeout)
proxy.filtering_rules.require_time_filter
: Require time filters in queriesproxy.filtering_rules.max_time_range_hours
: Maximum allowed time range (default: 840 hours/35 days)proxy.filtering_rules.warn_query_duration_hours
: Warn if query duration exceeds threshold (default: 336 hours/14 days)proxy.filtering_rules.warn_on_regex_usage
: Log warning when queries use regex operators (=~ or !~)proxy.filtering_rules.block_regex_usage
: Block queries with regex operatorsproxy.filtering_rules.block_wildcard_select
: Block SELECT * without LIMITproxy.filtering_rules.block_unlimited_group_by
: Block GROUP BY without LIMIT or time bucketingproxy.filtering_rules.block_expensive_shows
: Block SHOW SERIES without LIMITproxy.filtering_rules.max_show_series_limit
: Maximum LIMIT for SHOW SERIES queriesproxy.filtering_rules.max_offset_limit
: Maximum allowed OFFSET value in queries (0 = disabled)proxy.filtering_rules.allowed_measurements
: Whitelist of allowed measurement names (if specified, only these are allowed)proxy.filtering_rules.blocked_functions
: List of blocked functionsproxy.filtering_rules.blocked_statements
: List of blocked SQL statements (all others allowed by default)
logging.level
: Log level (debug, info, warn, error)logging.format
: Log format (json or text)
metrics.enabled
: Enable/disable metrics collection (endpoint: /proxy_metrics)
The proxy exposes all InfluxDB v1 endpoints with optional base path prefix.
POST /query
- Execute InfluxDB queries (with filtering)GET /proxy_health
- Health check endpointGET /proxy_metrics
- Prometheus-style metrics endpoint (if enabled)- All other REST endpoints exposed by InfluxDB v1 (e.g.,
/write
,/ping
,/health
)
POST /proxy/query
- Execute InfluxDB queries (with filtering)GET /proxy/proxy_health
- Health check endpointGET /proxy/proxy_metrics
- Prometheus-style metrics endpoint (if enabled)- All other REST endpoints exposed by InfluxDB v1 (e.g.,
/proxy/write
,/proxy/ping
,/proxy/health
)
Note: The base path allows you to mount the proxy under a specific URL prefix, useful for:
- Reverse proxy configurations
- API gateways
- Containerized deployments with path-based routing
The proxy applies the following filtering rules:
- IP Whitelisting: IPs in the
whitelisted_ips
list bypass all filtering rules - Global Filtering Disable: When
disable_query_filtering
is true, filtering is disabled for all IPs except those inblacklisted_ips
- IP Blacklisting: IPs in the
blacklisted_ips
list are always filtered, even whendisable_query_filtering
is true - Time Filter Requirement: Queries must include a time filter (WHERE time > ... AND time < ...)
- Time Range Limit: Time range cannot exceed the configured maximum (default: 35 days)
- Query Duration Warning: Log warnings for queries that exceed the configured duration threshold (default: 14 days)
- Regex Usage Control: Option to warn about or block queries using regex operators (=~ or !~)
- Measurement Filtering: If
allowed_measurements
is configured, only queries on those measurements are allowed - Expensive Function Detection: Blocks queries with expensive functions without proper constraints
- SHOW Series Limits: Controls SHOW SERIES queries with configurable limits
- Wildcard SELECT Protection: Can block SELECT * queries without LIMIT clauses
- GROUP BY Protection: Can block unlimited GROUP BY queries
- Statement Blocking: Only blocks statements explicitly listed in
blocked_statements
(all others allowed by default) - OFFSET Limiting: Can limit maximum OFFSET values to prevent expensive pagination
- External Filtering Rules: Support for loading filtering rules from an external YAML file
When configuring IP filtering, it's important to understand the precedence order:
whitelisted_ips
and blacklisted_ips
, the whitelist takes precedence and the IP will bypass all filtering rules.
Processing Order:
- First, blacklisted IPs are checked (only when
disable_query_filtering
is true) - Then, whitelisted IPs are checked (always processed)
- Finally, normal filtering rules apply
Example:
proxy:
disable_query_filtering: true
whitelisted_ips:
- "192.168.1.100" # This IP will bypass ALL filtering
blacklisted_ips:
- "192.168.1.100" # This will be ignored due to whitelist precedence
In this case, 192.168.1.100
will bypass all filtering rules because it's whitelisted, even though it's also in the blacklist.
.
├── cmd/
│ └── proxy/ # Main application entry point
├── internal/
│ ├── banner/ # Application banner and logo
│ ├── config/ # Configuration management
│ ├── filter/ # Query filtering logic
│ ├── proxy/ # HTTP proxy implementation
│ └── influxdb/ # InfluxDB client wrapper
├── config.yaml # Default configuration
├── docker-compose.yml # For testing with InfluxDB
└── README.md
└── ARCHITECTURE.md
...
go build -o influxdb-proxy cmd/proxy/main.go
go test ./...
Use the included docker-compose.yml
to run the proxy with a test InfluxDB instance:
docker-compose up
MIT License