现在的情况:
我有一个 Triple-O OpenStack 安装 (Liberty),其中甚至“公共”网络也位于私有环境 (10.24.7.0/24 网络) 中。访问该网络的唯一方法是通过网关主机。我想使用反向代理使 Horizon 可从互联网访问。出于安全考虑,所有外部通信都应通过 HTTPS 加密。反向代理应用作 SSL 终止主机,所有内部流量都应未加密。
OpenStack 部署未配置为使用 SSL/TLS,并且不知道“公共”网络实际上并不是公共的。
我目前正在尝试使用 Nginx 作为反向代理,但如果其他反向代理软件能够解决我的问题,那么也可以使用它们。
网关主机运行的是 RHEL 7.2,Nginx 从官方 Nginx repo 安装,版本号 1.11.1(主线)。
网关.example.com是示例中使用的 FQDN,
1.2.3.4是示例中使用的网关主机的外部 IP 地址
10.24.7.9是 Triple-O 安装的“公共”端点
迄今的工作:
http://gateway.example.com
加载 index.html,可以从中下载用于签署服务器证书的 CA 的证书。- 由于 OpenStack 安装不知道它位于 SSL 终端点后面,因此我必须重写内容中的链接。这是通过两个 sub_filter 指令完成的,一个是通用的 (
sub_filter 'http://$host' 'https://$host';
),另一个是替换 OpenStack 端点 IP (sub_filter 'http://10.24.7.9' 'https://$host';
) - Horizon 的功能
console
允许用户通过 Horizon 中嵌入的 NoVNC 连接到实例的串行控制台。NoVNC 使用 websockets 在浏览器和实例运行的物理主机之间建立双向 TCP 连接。为了支持此功能,我必须配置 Nginx 以允许 HTTP 连接升级并监听端口 6080。 iptables
允许端口 80、443 和 6080 上的流量。
问题:
- 在显示实例详细信息的 Horizon 页面上,不会显示选项卡的主体(概览、日志、控制台、操作日志),而是重复选项卡行,并且仅显示概览选项卡的内容。
- 实例控制台连接失败,错误代码为 1006。(检索到使控制台显示在其自己的浏览器选项卡中所需的 URL,并将
nova get-vnc-console <ID> novnc
端点 IP 替换为 FQDN。)我怀疑此错误是由于从 HTTP1.1 升级到 websocket 标准的连接包含有关“公共”接口的信息,该接口无法直接从浏览器访问,或者由于配置的服务器地址/主机名(“公共”)与请求中的地址(代理名称/IP)不匹配,NoVNC 软件拒绝了连接。这两种情况都是推测。
Nginx 配置文件
ssl_certificate /etc/nginx/certs/gateway.example.com.crt;
ssl_certificate_key /etc/nginx/certs/gateway.example.com.key;
ssl_dhparam /etc/nginx/certs/dh.pem;
ssl_protocols TLSv1.2 TLSv1.1;
ssl_ciphers AES256+EECDH:AES128+EECDH:!aNULL:!eNULL:!ECDSA:!SHA:!DSS;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server { # http
server_name gateway.example.com localhost 1.2.3.4;
listen *:80;
root /usr/share/nginx/html;
location / {
index index.html;
}
location ~ ^/dashboard {
return 302 `https://$host$request_uri`;
}
location ~ ^/console {
return 302 `https://$host:6080$request_uri`;
}
location ~ ^/websockify {
return 302 `https://$host:6080$request_uri`;
}
}
server { # https
server_name gateway.example.com localhost 1.2.3.4;
listen *:443;
ssl on;
location / {
sub_filter '`http://10.24.7.9`' '`https://$host`';
sub_filter '`http://$host`' '`https://$host`';
sub_filter_last_modified on;
sub_filter_once off;
sub_filter_types *;
proxy_pass `http://10.24.7.9/$uri`;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}
server { # https on port 6080 for novnc
server_name gateway.example.com localhost 1.2.3.4;
listen *:6080;
ssl on;
location / {
proxy_pass `http://10.24.7.9:6080/$uri`;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_connect_timeout 90;
# proxy_send_timeout 90;
# proxy_read_timeout 90;
}
}
有人有这种设置的工作配置吗?我想坚持使用 Nginx,但可以更改为 Apache 或任何其他可以提供解决方案的软件。
编辑:澄清 CA 的使用,增加了有关 NoVNC 连接失败的怀疑
答案1
我也解决了第一个问题。这种奇怪行为的原因是反向代理丢弃了请求的查询部分(? 后面的所有内容)。这又是由于错误配置的 proxy_pass 行造成的。
解决方案是/$uri
从配置文件中的两个 proxy_pass 行中删除(详细信息请参阅http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass)。
这是一个可行的解决方案:
ssl_certificate /etc/nginx/certs/gateway.example.com.crt;
ssl_certificate_key /etc/nginx/certs/gateway.example.com.key;
ssl_dhparam /etc/nginx/certs/dh.pem;
ssl_protocols TLSv1.2 TLSv1.1;
ssl_ciphers AES256+EECDH:AES128+EECDH:!aNULL:!eNULL:!ECDSA:!SHA:!DSS;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server { # http
server_name gateway.example.com localhost 1.2.3.4;
listen *:80;
root /usr/share/nginx/html;
location / {
index index.html;
}
location ~ ^/dashboard {
return 302 `https://$host$request_uri`;
}
location ~ ^/console {
return 302 `https://$host:6080$request_uri`;
}
location ~ ^/websockify {
return 302 `https://$host:6080$request_uri`;
}
}
server { # https
server_name gateway.example.com localhost 1.2.3.4;
listen *:443;
ssl on;
location / {
sub_filter '`http://10.24.7.9`' '`https://$host`';
sub_filter '`http://$host`' '`https://$host`';
sub_filter_last_modified on;
sub_filter_once off;
sub_filter_types *;
proxy_pass `http://10.24.7.9`;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin `http://$host`;
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}
server { # https on port 6080 for novnc
server_name gateway.example.com localhost 1.2.3.4;
listen *:6080;
ssl on;
location / {
proxy_pass `http://10.24.7.9:6080`;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin `http://$host`;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_connect_timeout 90;
# proxy_send_timeout 90;
# proxy_read_timeout 90;
}
}
答案2
通过更改一些配置选项,我能够解决第二个问题(错误 1006)。由于另一个问题仍然存在,我无法确认 NoVNC 控制台是否在 Horizon UI 中工作,但当我直接调用 NoVNC URL 时,我获得了连接并可以与实例交互。
这是迄今为止可行的解决方案:
ssl_certificate /etc/nginx/certs/gateway.example.com.crt;
ssl_certificate_key /etc/nginx/certs/gateway.example.com.key;
ssl_dhparam /etc/nginx/certs/dh.pem;
ssl_protocols TLSv1.2 TLSv1.1;
ssl_ciphers AES256+EECDH:AES128+EECDH:!aNULL:!eNULL:!ECDSA:!SHA:!DSS;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server { # http
server_name gateway.example.com localhost 1.2.3.4;
listen *:80;
root /usr/share/nginx/html;
location / {
index index.html;
}
location ~ ^/dashboard {
return 302 `https://$host$request_uri`;
}
location ~ ^/console {
return 302 `https://$host:6080$request_uri`;
}
location ~ ^/websockify {
return 302 `https://$host:6080$request_uri`;
}
}
server { # https
server_name gateway.example.com localhost 1.2.3.4;
listen *:443;
ssl on;
location / {
sub_filter '`http://10.24.7.9`' '`https://$host`';
sub_filter '`http://$host`' '`https://$host`';
sub_filter_last_modified on;
sub_filter_once off;
sub_filter_types *;
proxy_pass `http://10.24.7.9/$uri`;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin `http://$host`;
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}
server { # https on port 6080 for novnc
server_name gateway.example.com localhost 1.2.3.4;
listen *:6080;
ssl on;
location / {
proxy_pass `http://10.24.7.9:6080/$uri`;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin `http://$host`;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_connect_timeout 90;
# proxy_send_timeout 90;
# proxy_read_timeout 90;
}
}
总结
更改:
在端口 443 和 6080 的两个服务器块中我都添加了proxy_set_header Origin http://$host;
。不知道这到底是做什么的,但它解决了我的问题。
这仍然留给我第一个问题。
答案3
我在为此苦苦挣扎了一段时间后偶然发现了这一点。这真的帮了我大忙。但是 nginx 不喜欢 http://$host 等周围的 ` 引号。当你删除它们时,它就可以正常工作了。例如,这对我来说是一个有效的配置:
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/cert.key;
ssl_ciphers HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
server { # http
server_name openstack.example.com;
listen *:80;
location / {
return 302 https://$host$request_uri;
}
location ~ ^/console {
return 302 https://$host:6080$request_uri;
}
location ~ ^/websockify {
return 302 https://$host:6080$request_uri;
}
}
server { # https
server_name openstack.example.com;
listen *:443;
ssl on;
location / {
sub_filter 'http://192.168.0.200:6080' 'https://$host:6080';
sub_filter 'http://$host:6080' 'https://$host:6080';
sub_filter_last_modified on;
sub_filter_once off;
sub_filter_types *;
proxy_pass http://192.168.0.200;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin http://$host;
proxy_set_header Accept-Encoding "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}
server { # https on port 6080 for novnc
server_name openstack.example.com;
listen *:6080;
ssl on;
location / {
proxy_pass http://192.168.0.200:6080;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header Origin http://$host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}
我发布此信息是因为也许有人正在寻找更新的答案。