Protecting a non-forging node
Setting up a blockchain application behind a reverse proxy
There are times whereby it maybe desirable to run a blockchain application behind a reverse proxy for SSL termination, rate limiting, and other reasons.
We highly recommended running a reverse proxy for a public web service.
HAProxy is one such reverse proxy.
An HAProxy configuration has 4 sections, and is explained here .
The relevant sections to be aware of here are the frontend
and backend
.
Firstly, it is recommended to start with a very basic config snippet and then build up from there.
For this example to work, it is assumed that the application uses the default configuration for the WebSocket port, which is If a different port has been configured, then replace it with |
frontend f_klayr
mode http
bind :80 (1)
use_backend b_klayr_ws (2)
backend b_klayr_ws
server klayr_ws 127.0.0.1:8080 (3)
1 | A new bind line is added, and creates a listener on port 80. |
2 | use_backend defines the backend which responds to incoming requests. |
3 | server sets the backend server and expects a name as first argument, and the IP and port as second argument. |
This does nothing more than process proxy requests coming in at port 80 to your blockchain application WebSocket port.
SSL Termination
it is possible to add SSL termination by telling it to listen on port 443, and specifying the certificate in the frontend section:
frontend f_klayr
mode http
bind [::]:443 ssl crt /etc/haproxy/ssl/cert.pem alpn h2,http/1.1 (1)
bind [::]:80 (2)
http-response set-header Strict-Transport-Security max-age=15768000 (3)
redirect scheme https code 301 (4)
use_backend b_klayr_ws
1 | A new bind line is added, which performs the following:
|
2 | The bind lines were changed so that HAProxy will also listen on ipv6. |
3 | The Strict-Transport-Security response header is set to tell web browsers to only access this site over HTTPS. |
4 | A permanent redirect is created for anyone connecting over http to connect via https. |
Rate Limiting
HAProxy is very configurable when it comes to rate limiting. We’ll provide a specific example here.
Recommended additional reading:
|
frontend f_klayr
mode http
bind [::]:443 ssl crt /etc/haproxy/ssl/cert.pem alpn h2,http/1.1
bind [::]:80
http-response set-header Strict-Transport-Security max-age=15768000
redirect scheme https code 301
rate-limit sessions 500 (1)
stick-table type ipv6 size 200k expire 10m store gpc0 (2)
acl repeat_abuses src_get_gpc0(f_klayr) gt 2 (3)
tcp-request content track-sc0 src (4)
tcp-request content reject if repeat_abuses (5)
use_backend b_klayr_ws
backend b_klayr_ws
stick-table type ipv6 size 200k expire 2m store conn_rate(10s) (6)
tcp-request content track-sc1 src (7)
acl exceeds_conn_rate sc1_conn_rate gt 50 (8)
acl mark_repeat_abuses sc0_inc_gpc0 gt 0 (9)
http-request deny deny_status 429 if exceeds_conn_rate mark_repeat_abuses (10)
server klayr_ws 127.0.0.1:8080
This is somewhat of a 3-pronged approach to rate limiting.
rate-limit sessions 500
limits the number of new sessions per second.
New sessions are queued and accepted in line with the set value, which can be adjusted as necessary.
The rest of the changes here tell HAProxy to track the connection rate (over a rolling 10 seconds), of up 200k connecting IP addresses, the entries of which will expire after 2 minutes. If the connection rate of an IP exceeds 50 connections per 10 seconds, a 429 response gets returned and a global counter for that IP gets incremented, to track repeat abuses. If an IP exceeds this threshold more than twice in a 10 minute period, new connections from that IP will be silently dropped.
Multiple Backends
So far, the examples have been just for proxying the Klayr WebSocket RPC (Remote-Procedure-Call), endpoint.
The example below will proxy both the WebSocket RPC endpoint and the HTTP API endpoint by hostname (http.klayr.example
is a placeholder for whatever your domain is).
For this example to work, it is assumed that the application has the HTTP API enabled with the HTTP port set to 4000 (which is the default value). If a different port has been configured, then replace it with |
It is possible to have multiple backends that get served using all kinds of different criteria.
Commonly, this is done by the Host
header to serve more than one site.
This can be performed as shown below:
frontend f_klayr
mode http
bind [::]:443 ssl crt /etc/haproxy/ssl/cert.pem alpn h2,http/1.1
bind [::]:80
http-response set-header Strict-Transport-Security max-age=15768000
redirect scheme https code 301
rate-limit sessions 500
stick-table type ipv6 size 200k expire 10m store gpc0
acl repeat_abuses src_get_gpc0(f_klayr) gt 2
tcp-request content track-sc0 src
tcp-request content reject if repeat_abuses
acl host_http hdr(host) http.klayr.example
use_backend b_klayr_http if host_http
default_backend b_klayr_ws
backend b_klayr_ws
stick-table type ipv6 size 200k expire 2m store conn_rate(10s)
tcp-request content track-sc1 src
acl exceeds_conn_rate sc1_conn_rate gt 50
acl mark_repeat_abuses sc0_inc_gpc0 gt 0
http-request deny deny_status 429 if exceeds_conn_rate mark_repeat_abuses
server klayr_ws 127.0.0.1:8080
backend b_klayr_http
stick-table type ipv6 size 200k expire 2m store conn_rate(10s)
tcp-request content track-sc2 src
acl exceeds_conn_rate sc2_conn_rate gt 50
acl mark_repeat_abuses sc0_inc_gpc0 gt 0
http-request deny deny_status 429 if exceeds_conn_rate mark_repeat_abuses
server klayr_http 127.0.0.1:4000
If multiple domains are used with SSL termination, your certificate will either have to be for those multiple domains or you will need to have multiple certificates, which can be specified with crt-list instead of crt (https://www.haproxy.com/documentation/aloh
|