Nginx 背后的 Tomcat:如何代理 HTTP 和 HTTPS,可能在非标准端口上?

Env*_*vek 5 tomcat reverse-proxy nginx

描述

我们正在为不同的客户端安装一些在 Nginx 后面运行 Tomcat 6 的应用程序。其中一些安装仅适用于 HTTP,有些仅适用于 HTTPS,或者两者兼而有之。由于缺少公共 IP,其中一个安装的 HTTP 和 HTTPS 在非标准端口(8070 和 8071)上运行。手头的应用程序在另一个应用程序中显示为 iframe。

当前行为

Tomcat 将所有 HTTPS 请求重定向到 HTTP(因此由于浏览器对混合内容的限制,iframe 中不会显示任何内容)。

当前配置

框架代码:

<iframe src="/saiku-ui">
Run Code Online (Sandbox Code Playgroud)

Tomcat的server.xml

<Connector port="8080" protocol="HTTP/1.1"/>
<!-- A bit later... -->
<Valve className="org.apache.catalina.valves.RemoteIpValve"
      remoteIpHeader="x-forwarded-for"
      protocolHeader="x-forwarded-proto"
    />
Run Code Online (Sandbox Code Playgroud)

Nginx虚拟主机:

server {
  listen 80;
  listen 443 ssl spdy;

  location /saiku-ui {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://saiku-server; # This is upstream name
    proxy_redirect off;
  }
}

upstream saiku-server {
  server ip.of.tomcat.server:8080;
}
Run Code Online (Sandbox Code Playgroud)

期望的行为

  1. Tomcat 应该在一个端口上侦听 HTTP 和 HTTPS 请求。

    如果有两个<Connector>标签,配置 Nginx 会困难得多。

  2. Tomcat 不应在模式之间重定向。

  3. Nginx 可以监听任意端口(例如listen 8071 ssl spdy;)。
  4. 由 Tomcat 生成的链接应该是相对的,或者包括 Nginx 提供的架构、主机和端口。

附加信息

我尝试将schemaproxyPort属性添加到<Connector>,之后Tomcat将始终从HTTP重定向到HTTPS(至少它更好)。

我无法谷歌这样的配置,也没有使用 Tomcat 的经验。请帮忙。

Env*_*vek 5

实际上我真正想要的是不可能的,因此需要Connector在 Nginx 中有两个单独的标签和两个上游,如下所示:

Tomcat的server.xml

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           proxyPort="80"
/>

<Connector port="8443" protocol="HTTP/1.1"
           connectionTimeout="20000"
           proxyPort="443"
           scheme="https" secure="true"
/>
Run Code Online (Sandbox Code Playgroud)

匹配 Nginx 配置:

server {
  listen 80;
  listen 443 ssl spdy;

  location /saiku-ui {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://saiku-server-$scheme; # This is upstream name, note the variable $scheme in it
    proxy_redirect off;
  }
}

upstream saiku-server-http {
  server     ip.of.tomcat.server:8080;
}

upstream saiku-server-https {
  server     ip.of.tomcat.server:8443;
}
Run Code Online (Sandbox Code Playgroud)

请注意,Tomcat 在 8080 和 8443 端口上接收纯 HTTP 流量(那里没有 SSL,它被 Nginx 终止),但对于 8443 端口上的连接,它将生成链接必须以https://而不是http://(通过属性scheme="https" secure="true")开头,并将插入链接端口,在proxyPort属性中指定。

Nginx 将终止 SSL 并通过saiku-server-https上游代理所有安全连接到 Tomcat 的 8443 端口,其中Nginx 请求变量https的值$scheme(见location块)