duct_tape_coder
duct_tape_coder

Reputation: 494

NGINX: How do I remove a port when performing a reverse proxy?

I have an Nginx reverse proxy set up which is being used as an SSL offload for several servers such as confluence. I've got it successfully working for taking http://confluence and https://confluence but when I try to redirect http://confluence:8090, it tries to go to https://confluence:8090 and fails.

How can I remove the port from the URL?

The config below is a bit trimmed but maybe helpful? Is the $server_port bit in the headers causing the problem?

server {
    listen      8090;
    server_name confluence;

    return 301 https://confluence$request_uri;
}

server {
    listen      443 ssl http2;
    server_name confluence;
    location / {
        proxy_http_version 1.1;
        proxy_pass http://confbackend:8091
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $server_name:$server_port;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Upgrade $http_upgrade; #WebSocket Support
        proxy_set_header Connection $connection_upgrade; #WebSocket Support
   }
}

Seems like a lot of answers here involve http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect but I find no solace in that confusing mess.

I also would have thought you'd have a single server but I was trying the advice from https://serverfault.com/questions/815797/nginx-rewrite-to-new-protocol-and-port

I tried messing with the port_in_redirect off; option but maybe I was using it wrong?


EDIT 1: Add conf files

The files below are modifications from the Artifactory nginx setup. I used their setup initially and added additional conf files (in ./conf.d/) for other RP endpoints.

Confluence.conf

server {
  listen 8090 ssl http2;
  server_name confluence.domain.com confluence;
  ## return 301 https://confluence.domain.com$request_uri;
  proxy_redirect https://confluence.domain.com:8090 https://confluence.domain.com;
}

server {

  ## add ssl entries when https has been set in config
  ssl_certificate  /data/rpssl/confluence.pem;
  ssl_certificate_key  /data/rpssl/confluence_unencrypted.key;

  ## server configuration
  listen 443 ssl http2;
  server_name confluence.domain.com confluence;

  add_header Strict-Transport-Security max-age=31536000;

  if ($http_x_forwarded_proto = '') {
    set $http_x_forwarded_proto  $scheme;
  }
  ## Application specific logs
  access_log /var/log/nginx/confluence-access.log timing;
  error_log /var/log/nginx/confluence-error.log;
  client_max_body_size 0;

  proxy_read_timeout    1200;
  proxy_connect_timeout 240;

  location / {
    proxy_http_version  1.1;
    proxy_pass          http://backendconfluence.domain.com:8091;

    proxy_set_header    X-Forwarded-Host  $http_host;
    proxy_set_header    X-Forwarded-Proto $scheme;
    proxy_set_header    Host              $server_name:$server_port;
    proxy_set_header    X-Forwarded-For   $remote_addr;
    proxy_set_header    Upgrade           $http_upgrade; # WebSocket Support
    proxy_set_header    Connection        $connection_upgrade; # WebSocket support
  }
}

nginx.conf

# Main Nginx configuration file
worker_processes  4;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

worker_rlimit_nofile  4096;

events {
  worker_connections  2048;
}


http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;

  variables_hash_max_size 1024;
  variables_hash_bucket_size 64;
  server_names_hash_max_size 4096;
  server_names_hash_bucket_size 128;
  types_hash_max_size 2048;
  types_hash_bucket_size 64;
  proxy_read_timeout 2400s;
  client_header_timeout 2400s;
  client_body_timeout 2400s;
  proxy_connect_timeout 75s;
  proxy_send_timeout 2400s;
  proxy_buffer_size 32k;
  proxy_buffers 40 32k;
  proxy_busy_buffers_size 64k;
  proxy_temp_file_write_size 250m;
  proxy_http_version 1.1;
  client_body_buffer_size 128k;

  map $http_upgrade $connection_upgrade { #WebSocket support
    default upgrade;
    '' '';
  }

  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_x_forwarded_for"';

  log_format timing 'ip = $remote_addr '
  'user = \"$remote_user\" '
  'local_time = \"$time_local\" '
  'host = $host '
  'request = \"$request\" '
  'status = $status '
  'bytes = $body_bytes_sent '
  'upstream = \"$upstream_addr\" '
  'upstream_time = $upstream_response_time '
  'request_time = $request_time '
  'referer = \"$http_referer\" '
  'UA = \"$http_user_agent\"';

  access_log  /var/log/nginx/access.log  timing;

  sendfile        on;
  #tcp_nopush     on;

  keepalive_timeout  65;

  #gzip  on;

  include /etc/nginx/conf.d/*.conf;
}

Upvotes: 3

Views: 5604

Answers (1)

Tarun Lalwani
Tarun Lalwani

Reputation: 146510

Your problem is the STS header

add_header Strict-Transport-Security max-age=31536000;

When you add the STS header. The first request to http://example.com:8090 generates a redirect to https://example.com

This https://example.com then returns the STS header in the response and the browser remembers the example.com always needs to be served on https no matter what. The port doesn't make a difference

Now when you make another request to http://example.com:8090, STS kicks in and then converts it to https://example.com:8090, which is your problem here

Because a port can only serve http or https, you can't use 8090 to redirect http to https AND redirect https 8090 to https 443

Upvotes: 5

Related Questions