Skip to content

WAF and network

This page describes advanced options that are usually enabled after the basic virtual host is already working.

HTTP client configuration (upstream object)

Section titled “HTTP client configuration (upstream object)”
var backend1_upstream: [
url: "https://backend1.example.com"
web_client_config: [
http_version: "http1"
request_headers: [ Host: "backend1.example.com" ]
tls_backend: "grasshopper"
pool_max_idle_per_host: 100
pool_idle_timeout: 15.0
connect_timeout: 5.0
timeout: 10.0
read_timeout: 0.1
]
]
[
general: [
address: "127.0.0.1"
mode: "https"
port: 8443
]
localhost: [
/: [
reverse_proxy: backend1_upstream
]
]
]

It is not recommended to compress already compressed formats such as png, jpg, webp, or mp4: this gives almost no gain and increases CPU usage. zstd is usually a good speed-to-compression tradeoff, but check support on clients and in your infrastructure.

compression: [
compression_type: "zstd"
compression_level: 15
]
  • compression_type: gzip, brotli, deflate, zstd
  • compression_level: 1-15

webp_convert: [
quality: 7.0
min_size_to_convert: "1KB"
]

WebP conversion is useful for websites with many images and repeated traffic.
For dynamic content or CPU-constrained environments, enable it carefully and start with moderate quality.


cache: [
provider: "inmemory"
fallback: "redis"
redis_urls: [ "redis://127.0.0.1:6379" ]
content_types: [ "text/html" "text/css" "text/javascript" "application/javascript" "application/json" "image/png" "image/jpeg" "image/gif" "image/webp" "image/svg+xml" "font/ttf" "font/otf" "font/woff" "font/woff2" "audio/mpeg" "audio/ogg" "video/mp4" "video/webm" ]
headers: [ "ETag" "Accept" "Range" ]
max_body_size: "10GB"
capacity: "1GB"
cache_ttl: 86400
]
  • provider: inmemory | filesystem | redis
  • cache_dir: path for the filesystem provider
  • cache_ttl: lifetime in seconds

Available with the STANDART plan and above.

video_cache: [
provider: "filesystem"
fallback: "inmemory"
cache_dir: "meshgate_cache/video_cache"
headers: [ "ETag" "Accept" "Range" ]
max_body_size: "10GB"
capacity: "1GB"
cache_ttl: 86400
]

Format: selector:attribute:prefix, multiple rules separated by commas.

rewrite_rules: "[href]:href:/cdn, [src]:src:/img"

response_headers: [alt-svc: "h3=:443; ma=86400"]

  • allow, block, drop
  • challenge, captcha
  • redirect(url), render(path), proxy(url)
  • template(path), inject(path)
  • obfuscate, sqlcheck
  • ratelimit (with parameters)
KeyWireshark / fieldDescription
Methodhttp.request.methodHTTP method
UriPathhttp.request.uri.pathURI path
UriQueryhttp.request.uri.queryquery string
HttpVersionhttp.request.versionHTTP version
Ja3http.request.ja3JA3 fingerprint
Ja3Sorthttp.request.ja3_sortsorted JA3
SrcIpip.srcclient IP
SrcPortip.src.portclient port
SrcCountryip.src.geocountry
SrcAsnip.src.asnASN
Headershttp.request.headersheaders

Priority: not/! -> and/&& -> xor -> or/||.

Use parentheses when combining operators.

http.request.method eq 'POST'
and http.request.uri.path contains '/admin'
and (ip.src.country eq 'RU' or ip.src.country eq 'UA')
waf_rules: [
allow_from_local_addr: [
priority: 0
expr: "ip.src eq 10.0.0.1"
action: "allow"
]
block_post_requests: [
priority: 1
expr: "http.request.method eq 'POST'"
action: "block"
]
rate_limit_no_cache_requests: [
priority: 3
expr: "http.request.headers['pragma'] eq 'no-cache'"
action: ratelimit : [
requests: 60
burst: 5
seconds: 1
action: block: 3600
by_ip: true
by_fingerprint: false
]
]
redirect_to_google: [
priority: 4
expr: "http.request.uri.path eq '/google'"
action: redirect: "https://google.com"
]
]

  • hosts — list of TCP/UDP upstreams
  • algorithmRR | WRR | Hash
[
general: [
address: "127.0.0.1"
mode: "tcp"
port: 8443
]
algorithm: "RR"
hosts: [
"1.1.1.1:80"
"1.0.1.0:80"
]
]
[
general: [
address: "127.0.0.1"
mode: "udp"
port: 5353
]
algorithm: "RR"
hosts: [
["1.1.1.1:53" 1]
["1.0.1.0:53" 2]
]
]
[
general: [
address: "127.0.0.1"
mode: "tcp"
port: 8443
]
hosts: [
"1.1.1.1:80"
]
]
[
general: [
address: "127.0.0.1"
mode: "udp"
port: 5353
]
hosts: [
"1.1.1.1:53"
]
]