Skip to content

nginx: random vhost is used as default_server if no default set #392886

Open
@azrdev

Description

@azrdev

Nixpkgs version

  • Stable (24.11)

Describe the bug

As documented upstream I observed in a nixos config (which didn't mention nginx, but pulled it via the nextcloud module, and thus had no ngnix virtualHost entry with default = true):

nginx tests only the request’s header field “Host” to determine which server the request should be routed to. […] the default server is the first one — which is nginx’s standard default behaviour. It can also be set explicitly which server should be default, with the default_server parameter

This lead to all kinds of requests (e.g. vulnerability scans / malicious actors doing HTTP(s) requests with Host: <public IPv4>) arriving at the nextcloud php server, which I consider a security risk. It would be even worse if one had nginx reverse-proxy an application which relies on the proxy filtering bogus virtual hostnames.

Steps to reproduce

a config with no nginx except the following should reproduce the behavior

services.nginx.virtualHosts."dummy" = {};

A curl -v http://<hostname>/ should be visible in journalctl -u nginx as arriving at the "dummy" vhost. A curl -v http://<IP of the nginx machine>/ too, errorneously.

Expected behaviour

When no vhost is marked with default = true the module should generate a default blackhole config

Screenshots

No response

Relevant log output

Sep 09 01:03:41 servername Nextcloud[1471]: {"reqId":"4V3c7d2pBKuEebCFv69c","level":1,"time":"2024-09-08T23:03:41+00:00","remoteAddr":"185.224.128.59","user":"--","app":"core","method":"GET","url":"/cgi-bin/luci/;stok=/locale","message":"Trusted domain error. \"185.224.128.59\" tried to access using \"redacted.public.ipv4.address\" as host.","userAgent":"Go-http-client/1.1","version":"29.0.6.1","data":{"app":"core"}}

Additional context

I added the blackhole vhost by hand to fix the problem until the module does.

My first approach covers HTTP but doesn't work for HTTPS unless one creates a real ssl certificate in nix config:

services.nginx.virtualHosts."_" = {
  default = true;
  addSSL = true;
  sslCertificate = pkgs.writeText "dummy-certificate" ''''; # argument required by nixos module
  sslCertificateKey = pkgs.writeText "dummy-certificate" ''''; # argument required by nixos module
  extraConfig = ''
    # instruct nginx to close the connection without sending a response to the client
    return 444;
    # for SSL: after SNI is read, before needing a certificate. see <https://serverfault.com/a/631073/>
    ssl_reject_handshake on;
  '';
};

this succeeds in nixos-rebuild but then fails the nginx.service

So I have to retreat to verbatim nginx config. This works for now, but I think it's only a workaround:

  services.nginx.appendHttpConfig = ''
      server {
        listen 80 default_server ;
        listen 443 ssl default_server ;
        server_name _ ;  # invalid, only react as fallback (default_server)
        return 444 ;  # HTTP: TCP reset
        ssl_reject_handshake on;  # HTTPS (after SNI): TCP reset
      }
    '';

Caveat (as already documented upstream): ssl_reject_handshake requires use of SNI for the server with HTTPS.

System metadata

  • system: "x86_64-linux"
  • host os: Linux 6.6.83, NixOS, 24.11 (Vicuna), 24.11.715908.7105ae395770
  • multi-user?: yes
  • sandbox: yes
  • version: nix-env (Nix) 2.24.12
  • channels(root): "nixos-24.11"
  • nixpkgs: /nix/var/nix/profiles/per-user/root/channels/nixos

Notify maintainers

@fpletz
@RaitoBezarius
@dasJ
@Conni2461
@helsinki-Jo
@ulrikstrid


Note for maintainers: Please tag this issue in your pull request description. (i.e. Resolves #ISSUE.)

I assert that this issue is relevant for Nixpkgs

Is this issue important to you?

Add a 👍 reaction to issues you find important.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions