mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-29 02:53:52 +00:00 
			
		
		
		
	nginx: Add an option which defaults loadbalancer requests to https.
In some cases, it is not possible to configure the load-balancer to add an X-Forwarded-Proto header. If Zulip is serving its traffic over HTTP, it will rightly error out, since it cannot guarantee that its response will be served over an encrypted connection. Add a new `loadbalancer.rejects_http_requests` settings which serves as a way for the operator to swear that the load-balancer will *never* serve responses from Zulip over an unencrypted connection. In most cases, this is because the load-balancer is configured to have port 80 always serve an HTTP 301 redirect to the same URL over HTTPS. Properly configuring the proxy to send `X-Forwarded-Proto` is always a better solution than using this configuration parameter, so use of this should be viewed as a last resort.
This commit is contained in:
		
				
					committed by
					
						 Tim Abbott
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							b047c4d322
						
					
				
				
					commit
					3ec896ebda
				
			| @@ -244,6 +244,11 @@ things you need to be careful about when configuring it: | |||||||
|    connection mechanism from your proxy to Zulip. Note that the proxies _must_ |    connection mechanism from your proxy to Zulip. Note that the proxies _must_ | ||||||
|    set the header, overriding any existing values, not add a new header. |    set the header, overriding any existing values, not add a new header. | ||||||
|  |  | ||||||
|  |    If your proxy _cannot_ set the `X-Forwarded-Proto` header, you can opt to do | ||||||
|  |    all HTTP-to-HTTPS redirection at the load-balancer level, and set | ||||||
|  |    [`loadbalancer.rejects_http_requests` in `zulip.conf`][no-proto-header]; but | ||||||
|  |    note the important security caveats for that in its documentation. | ||||||
|  |  | ||||||
| 1. Configure your proxy to pass along the `Host:` header as was sent | 1. Configure your proxy to pass along the `Host:` header as was sent | ||||||
|    from the client, not the internal hostname as seen by the proxy. |    from the client, not the internal hostname as seen by the proxy. | ||||||
|    If this is not possible, you can set `USE_X_FORWARDED_HOST = True` |    If this is not possible, you can set `USE_X_FORWARDED_HOST = True` | ||||||
| @@ -272,4 +277,5 @@ things you need to be careful about when configuring it: | |||||||
|    with multiple IPs for your Zulip machine; sometimes this happens with |    with multiple IPs for your Zulip machine; sometimes this happens with | ||||||
|    IPv6 configuration). |    IPv6 configuration). | ||||||
|  |  | ||||||
|  | [no-proto-header]: system-configuration.md#rejects_http_requests | ||||||
| [nginx-proxy-longpolling-config]: https://github.com/zulip/zulip/blob/main/puppet/zulip/files/nginx/zulip-include-common/proxy_longpolling | [nginx-proxy-longpolling-config]: https://github.com/zulip/zulip/blob/main/puppet/zulip/files/nginx/zulip-include-common/proxy_longpolling | ||||||
|   | |||||||
| @@ -370,6 +370,16 @@ Comma-separated list of IP addresses or netmasks of external load balancers | |||||||
| whose `X-Forwarded-For` and `X-Forwarded-Proto` should be respected. These can | whose `X-Forwarded-For` and `X-Forwarded-Proto` should be respected. These can | ||||||
| be individual IP addresses, or CIDR IP address ranges. | be individual IP addresses, or CIDR IP address ranges. | ||||||
|  |  | ||||||
|  | #### `rejects_http_requests` | ||||||
|  |  | ||||||
|  | Set to a true value if incoming requests from load loadbalancer's IP addresses | ||||||
|  | which do not contain an `X-Forwarded-Proto` should be assumed to have come into | ||||||
|  | them over HTTPS. This setting _is a security vulnerability_ unless the load | ||||||
|  | balancer unilaterally rejects unencrypted HTTP connections, or responds to them | ||||||
|  | with 301 status codes. Note that Zulip's HSTS headers are not sufficient | ||||||
|  | protection here, since API clients do not respect them; the load balancer _must | ||||||
|  | not_ send any requests to Zulip which came in unencrypted. | ||||||
|  |  | ||||||
| ### `[http_proxy]` | ### `[http_proxy]` | ||||||
|  |  | ||||||
| #### `host` | #### `host` | ||||||
|   | |||||||
| @@ -56,6 +56,7 @@ class zulip::nginx { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   $loadbalancers = split(zulipconf('loadbalancer', 'ips', ''), ',') |   $loadbalancers = split(zulipconf('loadbalancer', 'ips', ''), ',') | ||||||
|  |   $lb_rejects_http_requests = zulipconf('loadbalancer', 'rejects_http_requests', false) | ||||||
|   file { '/etc/nginx/zulip-include/trusted-proto': |   file { '/etc/nginx/zulip-include/trusted-proto': | ||||||
|     ensure  => file, |     ensure  => file, | ||||||
|     require => Package[$zulip::common::nginx], |     require => Package[$zulip::common::nginx], | ||||||
|   | |||||||
| @@ -31,14 +31,19 @@ geo $remote_addr $is_from_proxy { | |||||||
| # We set $trusted_x_forwarded_proto in two steps because `geo` does | # We set $trusted_x_forwarded_proto in two steps because `geo` does | ||||||
| # not support variable interpolation in the value, but does support | # not support variable interpolation in the value, but does support | ||||||
| # CIDR notation, which the loadbalancer list may use. | # CIDR notation, which the loadbalancer list may use. | ||||||
| map $is_x_forwarded_proto_trusted $trusted_x_forwarded_proto { | map "$is_x_forwarded_proto_trusted:$http_x_forwarded_proto" $trusted_x_forwarded_proto { | ||||||
|     0 $scheme; |     "~^0:" $scheme; | ||||||
|     1 $http_x_forwarded_proto; | <%- if @lb_rejects_http_requests -%> | ||||||
|  |     "~^1:$" "https"; | ||||||
|  | <% end -%> | ||||||
|  |     "~^1:" $http_x_forwarded_proto; | ||||||
| } | } | ||||||
|  |  | ||||||
| map "$is_from_proxy:$is_x_forwarded_proto_trusted:$http_x_forwarded_proto" $x_proxy_misconfiguration { | map "$is_from_proxy:$is_x_forwarded_proto_trusted:$http_x_forwarded_proto" $x_proxy_misconfiguration { | ||||||
|     "~^0:0:" "Incorrect reverse proxy IPs set in Zulip (try $remote_addr?); see https://zulip.readthedocs.io/en/latest/production/reverse-proxies.html"; |     "~^0:0:" "Incorrect reverse proxy IPs set in Zulip (try $remote_addr?); see https://zulip.readthedocs.io/en/latest/production/reverse-proxies.html"; | ||||||
|  | <%- if not @lb_rejects_http_requests -%> | ||||||
|     "~^0:1:$" "No X-Forwarded-Proto header sent from trusted proxy $realip_remote_addr; see example configurations in https://zulip.readthedocs.io/en/latest/production/reverse-proxies.html"; |     "~^0:1:$" "No X-Forwarded-Proto header sent from trusted proxy $realip_remote_addr; see example configurations in https://zulip.readthedocs.io/en/latest/production/reverse-proxies.html"; | ||||||
|  | <% end -%> | ||||||
|     default ""; |     default ""; | ||||||
| } | } | ||||||
| <% end %> | <% end %> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user