Skip to content

Latest commit

 

History

History
99 lines (59 loc) · 4.48 KB

SubscriptionServer.rst

File metadata and controls

99 lines (59 loc) · 4.48 KB

uWSGI Subscription Server

Some components of the uWSGI stack require a key-value mapping system.

For example the :doc:`FastRouter<FastRouter>` needs to know which server to contact for a specific request.

In big networks with a lot of nodes manually managing this configuration could be a proper pain in the ass. As uWSGI doesn't want to be a PITA, it implements a subscription system where the node itself announces its presence to Subscription Servers, which will in turn populate their internal dictionaries.

uwsgi --fastrouter :1717 --fastrouter-subscription-server 192.168.0.100:2626

This will run an uWSGI fastrouter on port 1717 and create an empty dictionary where the hostname is the key and the uwsgi address is the value.

To populate this dictionary you can contact 192.168.0.100:2626, the address of the subscription server.

For every key multiple addresses can exist, enabling round robin load balancing.

A node can announce its presence to a Subscription Server using the subscribe-to option.

uwsgi -s 192.168.0.10:3031 -w myapp -M --subscribe-to 192.168.0.100:2626:uwsgi.it

The FastRouter will map every request for uwsgi.it to 192.168.0.10:3031.

To now add a second node for uwsgi.it simply run it and subscribe:

uwsgi -s 192.168.0.11:3031 -w myapp -M --subscribe-to 192.168.0.100:2626:uwsgi.it

Dead nodes are automatically removed from the pool.

The subscription system is currently available for cluster joining (when multicast/broadcast is not available), the Fastrouter and HTTP.

That said, you can create an evented/fast_as_hell HTTP load balancer in no time.

uwsgi --http :80 --http-subscription-server 192.168.0.100:2626

Now simply subscribe your nodes to the HTTP subscription server.

Securing the Subscription System

The subscription system is meant for "trusted" networks. All of the nodes in your network can potentially make one goddamn mess with it.

If you are building an infrastructure for untrusted users or you simply need more control over who can subscribe to a Subscription Server you can use openssl rsa public/private key pairs for "signing" you subscription requests.

# First, create the private key for the subscriber. DO NOT SET A PASSPHRASE FOR THIS KEY.
openssl genrsa -out private.pem
# Generate the public key for the subscription server:
openssl rsa -pubout -out test.uwsgi.it_8000.pem -in private.pem

The keys must be named after the domain/key we are subscribing to serve, plus the .pem extension.

Note

If you're subscribing to a pool for an application listening on a specified port you need to use the domain_port.pem scheme for your key files. Generally all of the DNS-allowed chars are supported, all of the others are mapped to an underscore.

An example of an RSA protected server looks like this:

[uwsgi]
master = 1
http = :8000
http-subscription-server = 127.0.0.1:2626
subscriptions-sign-check = SHA1:/etc/uwsgi/keys

The last line tells uWSGI that public key files will be stored in /etc/uwsgi/keys.

At each subscription request the server will check for the availability of the public key file and use it, if available, to verify the signature of the packet. Packets that do not correctly verify are rejected.

On the client side you need to pass your private key along with other subscribe-to options. Here's an example:

[uwsgi]
socket = 127.0.0.1:8080
subscribe-to = 127.0.0.1:2626:test.uwsgi.it:8000,5,SHA1:/home/foobar/private.pem
psgi = test.psgi

Let's analyze the subscribe-to incantation:

  • 127.0.0.1:2626 is the subscription server we want to subscribe to.
  • test.uwsgi.it:8000 is the subscription key.
  • 5 is the modifier1 value for our psgi app
  • SHA1:/home/private/test.uwsgi.it_8000.pem is the <digest>:<rsa> couple for authenticating to the server (the <rsa> field is the private key path).

Note

Please make sure you're using the same digest method (SHA1 in the examples above) both on the server and on the client.

To avoid replay attacks, each subscription packet has an increasing number (normally the unix time) avoiding the allowance of duplicated packets. Even if an attacker manages to sniff a subscription packet it will be unusable as it is already processed previously. Obviously if someone manages to steal your private key he will be able to build forged packets.