From 046c63d220b209c3633646ed551eafb6dbf0fc9f Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Wed, 14 Dec 2022 17:17:39 -0500 Subject: [PATCH] fix nginx config for disallowing default IP access --- etc/nginx/nginx.conf | 5 + etc/nginx/sites-available/default.conf | 31 ++- etc/nginx/sites-available/mastodon.conf | 262 ++++++++++++------------ scripts/upgrade.sh | 4 + 4 files changed, 160 insertions(+), 142 deletions(-) diff --git a/etc/nginx/nginx.conf b/etc/nginx/nginx.conf index 4862544..76247a6 100644 --- a/etc/nginx/nginx.conf +++ b/etc/nginx/nginx.conf @@ -31,6 +31,11 @@ http { access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; + # https://github.com/doorkeeper-gem/doorkeeper/issues/1554#issuecomment-1304606633 + # proxy_buffers 4 16k; + # proxy_buffer_size 16k; + # proxy_busy_buffers_size 32k; + # stats for prometheus nginx exporter server { listen 9181; diff --git a/etc/nginx/sites-available/default.conf b/etc/nginx/sites-available/default.conf index da59816..d63d439 100644 --- a/etc/nginx/sites-available/default.conf +++ b/etc/nginx/sites-available/default.conf @@ -1,15 +1,24 @@ -# don't respond to direct IP address requests: -# https://www.codedodle.com/disable-direct-ip-access-nginx.html +# catch-all nginx server server { - listen 80 default_server; - listen [::]:80 default_server; + listen 80 default_server; + listen [::]:80 default_server; - listen 443 default_server; - listen [::]:443 default_server; - - ssl_reject_handshake on; - - server_name _; - return 444; + server_name _; + return 444; +} + +server { + listen 443 default_server; + listen [::]:443 default_server; + + # intentionally cause an SSL error. this requires a snakeoil certificate, see: + # https://docs.j7k6.org/nginx-default-ssl-site/ + ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; + ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; + ssl_reject_handshake on; + include /etc/letsencrypt/options-ssl-nginx.conf; + + server_name _; + return 444; } diff --git a/etc/nginx/sites-available/mastodon.conf b/etc/nginx/sites-available/mastodon.conf index 87b9759..fb8fb1d 100644 --- a/etc/nginx/sites-available/mastodon.conf +++ b/etc/nginx/sites-available/mastodon.conf @@ -1,176 +1,176 @@ # heavily modified from https://github.com/mastodon/mastodon/blob/v4.0.2/dist/nginx.conf map $http_upgrade $connection_upgrade { - default upgrade; - '' close; + default upgrade; + '' close; } upstream backend { - server 127.0.0.1:3000 fail_timeout=0; + server 127.0.0.1:3000 fail_timeout=0; } upstream streaming { - server 127.0.0.1:4000 fail_timeout=0; + server 127.0.0.1:4000 fail_timeout=0; } proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=1g; server { - listen [::]:443 http2 ssl ipv6only=on; - listen 443 http2 ssl; + listen [::]:443 http2 ssl ipv6only=on; + listen 443 http2 ssl; - server_name fediverse.jarv.is; + server_name fediverse.jarv.is; - root /home/mastodon/live/public; + root /home/mastodon/live/public; - ssl_certificate /etc/letsencrypt/live/fediverse.jarv.is/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/fediverse.jarv.is/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/fediverse.jarv.is/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/fediverse.jarv.is/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot - # https://ssl-config.mozilla.org/#server=nginx&version=1.22.1&config=intermediate&openssl=1.1.1f&guideline=5.6 - ssl_stapling on; - ssl_stapling_verify on; - ssl_trusted_certificate /etc/letsencrypt/live/fediverse.jarv.is/chain.pem; + # https://ssl-config.mozilla.org/#server=nginx&version=1.22.1&config=intermediate&openssl=1.1.1f&guideline=5.6 + ssl_stapling on; + ssl_stapling_verify on; + ssl_trusted_certificate /etc/letsencrypt/live/fediverse.jarv.is/chain.pem; - keepalive_timeout 20; - sendfile on; - client_max_body_size 100m; + keepalive_timeout 20; + sendfile on; + client_max_body_size 100m; - gzip on; - gzip_disable "msie6"; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_buffers 16 8k; - gzip_http_version 1.1; - gzip_types application/atom+xml application/javascript application/json application/rss+xml - application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype - application/x-font-ttf application/x-javascript application/xhtml+xml application/xml - font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon - image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml; - gzip_min_length 256; + gzip on; + gzip_disable "msie6"; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types application/atom+xml application/javascript application/json application/rss+xml + application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype + application/x-font-ttf application/x-javascript application/xhtml+xml application/xml + font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon + image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml; + gzip_min_length 256; - # https://github.com/google/ngx_brotli#sample-configuration - # https://github.com/jakejarvis/mastodon-scripts/wiki/Brotli-compression-for-nginx - brotli on; - brotli_comp_level 4; - brotli_static on; - brotli_types application/atom+xml application/javascript application/json application/rss+xml - application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype - application/x-font-ttf application/x-javascript application/xhtml+xml application/xml - font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon - image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml; - brotli_min_length 256; + # https://github.com/google/ngx_brotli#sample-configuration + # https://github.com/jakejarvis/mastodon-scripts/wiki/Brotli-compression-for-nginx + brotli on; + brotli_comp_level 4; + brotli_static on; + brotli_types application/atom+xml application/javascript application/json application/rss+xml + application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype + application/x-font-ttf application/x-javascript application/xhtml+xml application/xml + font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon + image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml; + brotli_min_length 256; - # add shortcut to public Grafana dashboard - location ~ ^/dashboard/?$ { - return 302 https://grafana.pipe.fail/public-dashboards/b5ca7a7c8e844f90b0973d2ab02bad0a; - } + # add shortcut to public Grafana dashboard + location ~ ^/dashboard/?$ { + return 302 https://grafana.pipe.fail/public-dashboards/b5ca7a7c8e844f90b0973d2ab02bad0a; + } - # sends most paths to the backend proxy and ignores the location blocks below, except if - # the file exists in /home/mastodon/live - location / { - add_header Strict-Transport-Security "max-age=63072000" always; - try_files $uri @proxy; - } + # sends most paths to the backend proxy and ignores the location blocks below, except if + # the file exists in /home/mastodon/live + location / { + add_header Strict-Transport-Security "max-age=63072000" always; + try_files $uri @proxy; + } - # condensed version of original Mastodon nginx.conf - location ~ ^/(assets|avatars|emoji|headers|packs|shortcuts|sounds)/ { - add_header Cache-Control "public, max-age=2419200, must-revalidate"; # 28 days - add_header Strict-Transport-Security "max-age=63072000" always; - try_files $uri =404; - } + # condensed version of original Mastodon nginx.conf + location ~ ^/(assets|avatars|emoji|headers|packs|shortcuts|sounds)/ { + add_header Cache-Control "public, max-age=2419200, must-revalidate"; # 28 days + add_header Strict-Transport-Security "max-age=63072000" always; + try_files $uri =404; + } - # media uploads & cache (irrelevant if offloading to S3) - location ~ ^/system/ { - add_header Cache-Control "public, max-age=2419200, immutable"; # 28 days - add_header Strict-Transport-Security "max-age=63072000" always; - try_files $uri =404; - } + # media uploads & cache (irrelevant if offloading to S3) + location ~ ^/system/ { + add_header Cache-Control "public, max-age=2419200, immutable"; # 28 days + add_header Strict-Transport-Security "max-age=63072000" always; + try_files $uri =404; + } - # static files in root of /public (sw.js, favicon.ico, etc) that aren't covered above - location ~ ^/(.*\.(js|css|png|gif|jpg|txt|ico))$ { - add_header Cache-Control "public, max-age=604800, must-revalidate"; # 7 days - add_header Strict-Transport-Security "max-age=63072000" always; - try_files $uri @proxy; - } + # static files in root of /public (sw.js, favicon.ico, etc) that aren't covered above + location ~ ^/(.*\.(js|css|png|gif|jpg|txt|ico))$ { + add_header Cache-Control "public, max-age=604800, must-revalidate"; # 7 days + add_header Strict-Transport-Security "max-age=63072000" always; + try_files $uri @proxy; + } - location ^~ /api/v1/streaming { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Proxy ""; + location ^~ /api/v1/streaming { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Proxy ""; - proxy_pass http://streaming; - proxy_buffering off; - proxy_redirect off; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; + proxy_pass http://streaming; + proxy_buffering off; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; - # security headers - proxy_hide_header Strict-Transport-Security; - proxy_hide_header X-Powered-By; - add_header Strict-Transport-Security "max-age=63072000" always; + # security headers + proxy_hide_header Strict-Transport-Security; + proxy_hide_header X-Powered-By; + add_header Strict-Transport-Security "max-age=63072000" always; - # debugging headers - add_header Via "1.1 $proxy_host" always; + # debugging headers + add_header Via "1.1 $proxy_host" always; - tcp_nodelay on; - } + tcp_nodelay on; + } - location @proxy { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Proxy ""; - # uncomment to allow the 'Server: Mastodon' header to override nginx's: - # proxy_pass_header Server; + location @proxy { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Proxy ""; + # uncomment to allow the 'Server: Mastodon' header to override nginx's: + # proxy_pass_header Server; - proxy_pass http://backend; - proxy_buffering on; - proxy_redirect off; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; + proxy_pass http://backend; + proxy_buffering on; + proxy_redirect off; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; - proxy_cache CACHE; - proxy_cache_valid 200 7d; - proxy_cache_valid 410 24h; - proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; + proxy_cache CACHE; + proxy_cache_valid 200 7d; + proxy_cache_valid 410 24h; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; - # security headers - proxy_hide_header Referrer-Policy; - proxy_hide_header Strict-Transport-Security; - proxy_hide_header X-Powered-By; - proxy_hide_header X-Clacks-Overhead; - proxy_hide_header X-XSS-Protection; - add_header Referrer-Policy "strict-origin" always; - add_header Strict-Transport-Security "max-age=63072000" always; + # security headers + proxy_hide_header Referrer-Policy; + proxy_hide_header Strict-Transport-Security; + proxy_hide_header X-Powered-By; + proxy_hide_header X-Clacks-Overhead; + proxy_hide_header X-XSS-Protection; + add_header Referrer-Policy "strict-origin" always; + add_header Strict-Transport-Security "max-age=63072000" always; - # debugging headers - add_header Via "1.1 $proxy_host" always; - add_header X-Cache-Status $upstream_cache_status always; - add_header X-Got-Milk "2%" always; + # debugging headers + add_header Via "1.1 $proxy_host" always; + add_header X-Cache-Status $upstream_cache_status always; + add_header X-Got-Milk "2%" always; - tcp_nodelay on; - } + tcp_nodelay on; + } - error_page 404 500 501 502 503 504 /500.html; + error_page 404 500 501 502 503 504 /500.html; } server { - listen [::]:80; - listen 80; + listen [::]:80; + listen 80; - server_name fediverse.jarv.is; + server_name fediverse.jarv.is; - if ($host = fediverse.jarv.is) { - return 301 https://$host$request_uri; - } # managed by Certbot + if ($host = fediverse.jarv.is) { + return 301 https://$host$request_uri; + } # managed by Certbot - return 403; + return 403; } diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh index b64507c..973ab3b 100755 --- a/scripts/upgrade.sh +++ b/scripts/upgrade.sh @@ -32,6 +32,10 @@ fi # pull & apply latest patches . "$SCRIPTS_ROOT/scripts/apply_patches.sh" +# create blank custom.css (this overrides any CSS set in the admin panel, but if that's not being used, then +# this quickly saves a request to the backend) +sudo -u mastodon "$APP_ROOT/public/custom.css" + # set new ruby version RUBY_VERSION="$(sudo -u mastodon cat $APP_ROOT/.ruby-version)" sudo -u mastodon RUBY_CONFIGURE_OPTS=--with-jemalloc "$RBENV_ROOT/bin/rbenv" install "$RUBY_VERSION" || true