Drop invalid requests either in the proxy or in studiobeta's nginx #82163

Closed
opened 2020-10-27 18:11:33 +01:00 by Anna Sirota · 4 comments
Owner
Requests with "unexpected" HTTP_HOSTs should not reach Django, here's example trace: https://sentry.io/organizations/blender-institute/issues/1984510038/?project=5476345&query=is%3Aunresolved See http://nginx.org/en/docs/http/request_processing.html#how_to_prevent_undefined_server_names
Author
Owner

Added subscriber: @railla

Added subscriber: @railla
Anna Sirota changed title from Drop invalid requests either in the proxy on in studiobeta's nginx to Drop invalid requests either in the proxy or in studiobeta's nginx 2020-10-30 09:33:49 +01:00
Author
Owner

Changed status from 'Needs Triage' to: 'Resolved'

Changed status from 'Needs Triage' to: 'Resolved'
Anna Sirota self-assigned this 2020-11-20 16:35:06 +01:00
Author
Owner

Added subscriber: @dr.sybren

Added subscriber: @dr.sybren
Author
Owner

This was a fun thing to solve: dropping HTTPS requests (or having a default server block for them) is not as easy as HTTP ones due to SNI matching.
The solution was to first

  1. generate a self-signed certificate
 `openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt`
  1. then define a valid ssl default_server block, so that the whole catch-all logic could be in one place in the top-level nginx config:
# /etc/nginx/nginx.conf
...
http {

    ...

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    - Drop any request without a sensible HTTP_HOST header matching
    - some other server block
    server {
        server_name _;
        listen      80  default_server;
        return      444;
    }

    - Drop any request without a sensible SNI matching some other
    - server block
    server {
        server_name _;
        listen      443 ssl default_server;
        ssl_certificate /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /etc/nginx/ssl/nginx.key;
        return      444;
    }
}

It is theoretically possible that there are browsers in the wild that don't implement SNI, but we decided not to worry about them.

Kudos to @dr.sybren for helping with this one 🎉

This was a fun thing to solve: dropping HTTPS requests (or having a default server block for them) is not as easy as [HTTP](http:*nginx.org/en/docs/http/request_processing.html#how_to_prevent_undefined_server_names) ones due to [SNI matching](https:*en.wikipedia.org/wiki/Server_Name_Indication). The solution was to first 1. generate a self-signed certificate ``` `openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt` ``` 2. then define a **valid** `ssl default_server` block, so that the whole catch-all logic could be in one place in the top-level nginx config: ``` # /etc/nginx/nginx.conf ... http { ... include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; - Drop any request without a sensible HTTP_HOST header matching - some other server block server { server_name _; listen 80 default_server; return 444; } - Drop any request without a sensible SNI matching some other - server block server { server_name _; listen 443 ssl default_server; ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key; return 444; } } ``` It is theoretically possible that there are browsers in the wild that don't implement SNI, but we decided not to worry about them. Kudos to @dr.sybren for helping with this one 🎉
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: studio/blender-studio#82163
No description provided.