Documentation

4. 代理支持

代理服务器充当从其他服务器请求资源的客户端请求的中间人。客户端连接到代理服务器,请求不同的服务器提供某些服务或可用资源,代理服务器会评估请求,以简化和控制其复杂性。

注解

支持使用 SSL 卸载或使用处理 Tower SSL 的代理。需要配置代理/负载均衡器来传递远程主机信息。

将 SSL 卸载到负载均衡器或代理时,将 nginx_disable_https=true 设置为传递给设置 (setup) playbook 的额外变量。如需有关将额外变量应用到设置 (setup) playbook 的信息,请参阅 Playbook 设置

Tower 中的会话会在创建时关联一个 IP 地址。Tower 策略要求任何会话的使用都与原始关联的 IP 地址匹配。

要提供代理服务器支持,Tower 通过 Tower 设置(/etc/tower/conf.d/remote_host_headers.py)中的 REMOTE_HOST_HEADERS 列表变量处理代理请求(如 ALB、NLB、HAProxy、Squid、Nginx 和 tinyproxy)。默认情况下,REMOTE_HOST_HEADERS 设置为 ['REMOTE_ADDR', 'REMOTE_HOST']

要启用代理服务器支持,按如下所示设置 REMOTE_HOST_HEADERSREMOTE_HOST_HEADERS = ['HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR', 'REMOTE_HOST']

注解

新安装的 Ansible Tower 将不包含 remote_host_headers.py 文件。但是,您仍可在 Configure Tower 用户界面的系统设置中设置这些值。

_images/configure-tower-system.png

Tower 通过搜索 REMOTE_HOST_HEADERS 中的标头列表来确定远程主机的 IP 地址,直至找到第一个 IP 地址。

注解

使用以下逻辑构建标头名称:

除了 CONTENT_LENGTHCONTENT_TYPE,请求中的任何 HTTP 标头都转换成 META 键,方法是将所有字符转换为大写字母,用下划线替换任何连字符,并在名称中添加 HTTP_ 前缀。例如,标头调用的 X-Barkley 将映射到 META 键 HTTP_X_Barkley

如需 HTTP 请求和响应对象的更多信息,请参阅:https://docs.djangoproject.com/en/1.8/ref/request-response/#django.http.HttpRequest.META

注解

如果在负载均衡器中使用 SSL 终止,并将流量转发到 tower 节点上的不同端口 (443 -> 80),请相应地在 /etc/tower/conf.d/custom.py 在文件中设置以下值:

USE_X_FORWARDED_PORT = True
USE_X_FORWARDED_HOST = True

4.1. 配置已知的代理

当使用 REMOTE_HOST_HEADERS = ['HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR', 'REMOTE_HOST'] 配置 Tower 时,它假定 X-Forwarded-For 的值源自 Tower 前面的代理/负载均衡器。在不使用代理/负载均衡器时或代理没有验证标头仍可以访问 Tower 的情况下,X-Forwarded-For 很容易受欺骗来假冒原始 IP 地址。使用 REMOTE_HOST_HEADERS 设置中的 HTTP_X_FORWARDED_FOR 可能会形成潜在的安全漏洞,导致授予用户本不应具有的某些资源的访问权限。

要避免这种情况,您可以配置允许的“已知代理”的列表,即通过设置 API 进行 PROXY_IP_ALLOWED_LIST 设置。不在列表上的负载均衡器和主机将导致拒绝请求。

只有列表中的代理正确清除了标头输入并正确设置了等于客户端真实来源 IP 的 X-Forwarded-For 值时,PROXY_IP_ALLOWED_LIST 才有效;此设置的缺陷在于 Tower 能够依赖 PROXY_IP_ALLOWED_LIST 中的 IP/主机名来为 X-Forwarded-For 字段提供非伪值。

HTTP_X_FORWARDED_FOR **不应**配置为 REMOTE_HOST_HEADERS 中的项目,除非满足以下条件:

  • 您使用的是代理环境 w/ ssl 终止

  • 代理提供 X-Forwarded-For 标头的清理/验证以防止客户端伪造

  • /etc/tower/conf.d/remote_host_headers.py 定义 PROXY_IP_ALLOWED_LIST 只包含可信代理/负载均衡器的原始 IP。

注解

如果不需要让所有流量通过代理,那么您可以指定要在 no_proxy 字段中排除的 IP 方案。列表可以是 IP 范围或独立 IP,用逗号分开。本例以 JSON 格式显示指定 IP 范围:

"https_proxy": "example.proxy.com:8080",
"http_proxy": "example.proxy.com:8080",
"no_proxy": "10.0.0.0/8"

另外,带有 no_proxy 配置和 CIDR标记的 SCM 更新可能不适用于特定的 SCM。对 http_proxyno_proxy 的支持依赖于应用程序 (git|hg|svn) 中的实施。例如,git 不支持 no_proxy 的 CIDR 标记,因为 git 被其 C 库限制: https://curl.haxx.se/libcurl/c/CURLOPT_NOPROXY.html

4.2. 反向代理

如果您在反向代理后面,您可能想要为 HTTP_X_FORWARDED_FOR 设置标头字段设置。X-Forwarded-For (XFF) HTTP 标头字段标识通过 HTTP 代理服务器或负载均衡器连接到 web 服务器的客户端的原始 IP 地址。

REMOTE_HOST_HEADERS = ['HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR', 'REMOTE_HOST']

4.3. Websocket 配置

您应该考虑的一个关键配置是 websocket 设置,以便与您的 nginx/负载均衡器配置匹配。

Tower 节点通过 websocket 连接到所有其他 Tower 节点。这个连接用于将所有 websocket 发送的信息发送到所有其他 Tower 节点。这个连接是必需的,因为任何浏览器客户端 websocket 都可能订阅到运行在任何 Tower 节点上任何作业。换句话说,websocket 客户端并不是路由到特定的 Tower 节点。任何 Tower 节点都可以处理任何 websocket 请求。因此,每个 Tower 节点都必须了解所有面向所有客户端的 websocket 信息。

Tower 将通过数据库中的实例记录自动处理其他 Tower 节点的发现。*必须*告知 Tower 在建立 websocket 连接时端口、协议以及是否进行凭证验证的信息。这需要通过以下三个设置进行配置:

BROADCAST_WEBSOCKET_PROTOCOL = 'http'
BROADCAST_WEBSOCKET_PORT = 80
BROADCAST_WEBSOCKET_VERIFY_CERT = False

例如,在 Tower 前面进行 SSL 终止的拓扑结构,在负载均衡器级别应具有以下设置:

BROADCAST_WEBSOCKET_PROTOCOL = 'http'
BROADCAST_WEBSOCKET_PORT = 80

使用 nginx 在每个独立 Tower 节点上执行 SSL 的拓扑结构应包括以下设置:

BROADCAST_WEBSOCKET_PROTOCOL = 'https'
BROADCAST_WEBSOCKET_PORT = 443
BROADCAST_WEBSOCKET_VERIFY_CERT = True

注解

它是针对于,您的节点在一个私有的、可信任的子网(而非开放的互联网)中对 websocket 流量进行广播。因此,如果您为 websocket 广播关闭了 HTTPS,websocket 流量(主要是 Ansible playbook stdout)会在 Tower 节点间进行未加密的发送。