2

I have a small Spring Boot app that I would like to run locally on my server, this server runs a few other things so the services are all behind an nginx reverse proxy, which is port forwarded out my network pointed to by my DNS.

I have run my app on the server and accessing it over 192.168.x.x:80 works fine. However when I put it through my reverse proxy and access it over my domain it breaks.

The nature of the break seems to be spring security as it should redirect me to my /login page but it does not. The message I get in my server console is this:

org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the header value "??????" is not allowed.

This is what leads me to suspect there is something funny going on with the reverse proxy doing something to the headers but I am no expert in this.

My nginx setup is as follows:

server{

location / {
    proxy_pass_header Authorization;
    proxy_pass http://$upstream;
    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_http_version 1.1;
    proxy_set_header Connection    ^`^|   ^`^};
    proxy_buffering off;
    client_max_body_size 0;
    proxy_read_timeout 36000s;
    proxy_redirect off;
}


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/myapp.mydomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/myapp.mydomain.com/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

}

server {
    if ($host = myapp.mydomain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


listen 80;
    return 404; # managed by Certbot


}

I added server.use-forward-headers=true to the application.properties but that has not seemed to do anything.

If you can help with this it would be very appreciated, thank you.

1 Answer 1

7

By default the StrictHttpFirewall is used. This implementation rejects requests that appear to be malicious, e.g non-ASCII characters or strings without MIME header encoding. If it is too strict for your needs, then you can customize what types of requests are rejected.

This is standard behaviour in Spring Security 5.4 to which Spring Boot 2.4 upgraded. This is mentioned in the Spring Security documentation which also provides some information about configuring the behaviour

public class SecurityConfig extends WebSecurityConfigurerAdapter {
  ...
  @Override
  public void configure(WebSecurity web) {
      StrictHttpFirewall firewall = new StrictHttpFirewall();

      firewall.setAllowUrlEncodedSlash(true);
      firewall.setAllowBackSlash(true);
      firewall.setAllowUrlEncodedPercent(true);
      firewall.setAllowUrlEncodedPeriod(true);
      firewall.setAllowSemicolon(true);

      // Allow UTF-8 values
      Pattern allowed = Pattern.compile("[\\p{IsAssigned}&&[^\\p{IsControl}]]*");
      firewall.setAllowedHeaderValues((header) -> {
          String parsed = new String(header.getBytes(ISO_8859_1), UTF_8);
          return allowed.matcher(parsed).matches();
      });

      web.httpFirewall(firewall);
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.