Commit 1794df1896eff59620e669ec5ddeba236a6ecc88
Committed by
Earth Ugat
1 parent
0975ffb2
Bump to v0.4.2. Add new site type 'webserver_basic', add mitigations for HTTPOXY attacks.
Showing
9 changed files
with
101 additions
and
17 deletions
| 1 | +## 0.4.2 - 2016-09-09 | ||
| 2 | +### Security | ||
| 3 | +- Add proxy and fastcgi directives to prevent HTTPOXY attacks as described [here](https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ "Mitigate HTTPOXY with Nginx") | ||
| 4 | + | ||
| 5 | +### Added | ||
| 6 | +- Add more appropriate keywords for virtual site types | ||
| 7 | +- Add a new site type `webserver_basic` with a customizable template | ||
| 8 | + | ||
| 1 | # 0.4.1 | 9 | # 0.4.1 |
| 2 | 10 | ||
| 3 | Add attribute to customize listen options for virtual host | 11 | Add attribute to customize listen options for virtual host |
| @@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
| 2 | 2 | ||
| 3 | Installs PHP5-FPM, Nginx, Postfix, and MariaDB client on a server. Also sets up webserver configs for all virtual servers, including TLS and basic auth. | 3 | Installs PHP5-FPM, Nginx, Postfix, and MariaDB client on a server. Also sets up webserver configs for all virtual servers, including TLS and basic auth. |
| 4 | 4 | ||
| 5 | -Can also auto-generate config files for certain site types, such as Wordpress, etc. (right now it's: `wordpress`, `basic`, and `webserver`). | 5 | +Can also auto-generate config files for certain site types, such as Wordpress, etc. (right now it's: `wordpress`, `basic_php`, `webserver_basic`, and `webserver_ws`). |
| 6 | 6 | ||
| 7 | ## Supported Platforms | 7 | ## Supported Platforms |
| 8 | 8 |
| @@ -150,12 +150,14 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [ | @@ -150,12 +150,14 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [ | ||
| 150 | # Each type element of this array is a hash containing different attributes. | 150 | # Each type element of this array is a hash containing different attributes. |
| 151 | # | 151 | # |
| 152 | # Mandatory attributes are: | 152 | # Mandatory attributes are: |
| 153 | - # :type => One of: 'basic' (basic PHP site) | 153 | + # :type => One of: 'basic_php' (basic PHP site) |
| 154 | # 'wordpress' (standard Wordpress site) | 154 | # 'wordpress' (standard Wordpress site) |
| 155 | - # 'webserver' (proxy webserver) | 155 | + # 'webserver_ws' (proxy webserver with websocket) |
| 156 | + # 'webserver_basic' (proxy generic webserver) | ||
| 156 | # :upstream_servers => An array containing upstream server endpoints. | 157 | # :upstream_servers => An array containing upstream server endpoints. |
| 157 | # Unix socket example: ['/var/run/php-fpm.sock'] | 158 | # Unix socket example: ['/var/run/php-fpm.sock'] |
| 158 | # Tcp port example: ['127.0.0.1:9000'] | 159 | # Tcp port example: ['127.0.0.1:9000'] |
| 160 | + # (This is optional for type 'webserver_basic') | ||
| 159 | # | 161 | # |
| 160 | # Optional attributes are: | 162 | # Optional attributes are: |
| 161 | # :subpath => A string of the form: 'news/blog'. | 163 | # :subpath => A string of the form: 'news/blog'. |
| @@ -179,15 +181,28 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [ | @@ -179,15 +181,28 @@ default['cfe-nginx-php-fpm']['nginx']['sites'] = [ | ||
| 179 | # or not. Default: false | 181 | # or not. Default: false |
| 180 | # | 182 | # |
| 181 | # Unique attributes for each type are indicated below: | 183 | # Unique attributes for each type are indicated below: |
| 182 | - # Basic PHP Site (:type => 'basic'): | 184 | + # Basic PHP Site (:type => 'basic_php'): |
| 183 | # :fastcgi_intercept_errors => Optional. Default: false | 185 | # :fastcgi_intercept_errors => Optional. Default: false |
| 184 | # Standard Wordpress Site (:type => 'wordpress'): | 186 | # Standard Wordpress Site (:type => 'wordpress'): |
| 185 | # :fastcgi_intercept_errors => Optional. Default: false | 187 | # :fastcgi_intercept_errors => Optional. Default: false |
| 186 | # :loginpage_statements => An array of strings to be put on the | 188 | # :loginpage_statements => An array of strings to be put on the |
| 187 | # config for the /wp-login.php | 189 | # config for the /wp-login.php |
| 188 | # and /wp-admin pages. Default: [] | 190 | # and /wp-admin pages. Default: [] |
| 189 | - # Proxy Webserver (:type => 'webserver'): | 191 | + # Proxy Websocket Webserver (:type => 'webserver_ws'): |
| 190 | # (none) | 192 | # (none) |
| 193 | + # Proxy Generic Webserver (:type => 'webserver_basic'): | ||
| 194 | + # :source => The name of the config template. | ||
| 195 | + # Default is 'inc_type_webserver_basic.erb'. | ||
| 196 | + # :cookbook => The name of the cookbook where the template | ||
| 197 | + # will be taken from. Default is this cookbook. | ||
| 198 | + # In combination with the :source attribute above, | ||
| 199 | + # any custom template in a wrapper cookbook can be | ||
| 200 | + # used. A template file 'inc_type_webserver_basic.erb' | ||
| 201 | + # exists as an example. | ||
| 202 | + # :custom_params => A hash that will be passed into the template | ||
| 203 | + # (along with the optional attributes mentioned | ||
| 204 | + # above) as the variable called cparams. | ||
| 205 | + # Default: {} | ||
| 191 | # | 206 | # |
| 192 | #:types => [] | 207 | #:types => [] |
| 193 | #} | 208 | #} |
| @@ -4,7 +4,7 @@ maintainer_email 'sysadmin@chromedia.com' | @@ -4,7 +4,7 @@ maintainer_email 'sysadmin@chromedia.com' | ||
| 4 | license 'Apache License' | 4 | license 'Apache License' |
| 5 | description 'Simplifies setup of Nginx+PHP-FPM in Chromedia.' | 5 | description 'Simplifies setup of Nginx+PHP-FPM in Chromedia.' |
| 6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) | 6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) |
| 7 | -version '0.4.1' | 7 | +version '0.4.2' |
| 8 | 8 | ||
| 9 | { | 9 | { |
| 10 | 'openssl' => '4.4.0', | 10 | 'openssl' => '4.4.0', |
| @@ -179,25 +179,27 @@ node[cb]['nginx']['sites'].each do |site| | @@ -179,25 +179,27 @@ node[cb]['nginx']['sites'].each do |site| | ||
| 179 | :log_static => stype_logstatic | 179 | :log_static => stype_logstatic |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | - site_upstreams.push( { | ||
| 183 | - :name => stype_ups, | ||
| 184 | - :servers => stype[:upstream_servers] || [] | ||
| 185 | - } ) | 182 | + if stype[:upstream_servers] && stype[:upstream_servers].length > 0 |
| 183 | + site_upstreams.push( { | ||
| 184 | + :name => stype_ups, | ||
| 185 | + :servers => stype[:upstream_servers] || [] | ||
| 186 | + } ) | ||
| 187 | + end | ||
| 186 | 188 | ||
| 187 | case stype[:type] | 189 | case stype[:type] |
| 188 | # BASIC PHP SITE | 190 | # BASIC PHP SITE |
| 189 | - when 'basic' | 191 | + when 'basic', 'basic_php' |
| 190 | vars[:index] = site_index | 192 | vars[:index] = site_index |
| 191 | vars[:fastcgi_intercept_errors] = | 193 | vars[:fastcgi_intercept_errors] = |
| 192 | stype.has_key?(:fastcgi_intercept_errors) ? | 194 | stype.has_key?(:fastcgi_intercept_errors) ? |
| 193 | stype[:fastcgi_intercept_errors] : false | 195 | stype[:fastcgi_intercept_errors] : false |
| 194 | 196 | ||
| 195 | - template "#{inc_dir}/inc_type_basic_#{site_sname}" do | 197 | + template "#{inc_dir}/type_basic_php_#{site_sname}" do |
| 196 | source 'inc_type_basic.erb' | 198 | source 'inc_type_basic.erb' |
| 197 | mode 0644 | 199 | mode 0644 |
| 198 | variables vars | 200 | variables vars |
| 199 | end | 201 | end |
| 200 | - site_includes.push("#{inc_dir}/inc_type_basic_#{site_sname}") | 202 | + site_includes.push("#{inc_dir}/type_basic_php_#{site_sname}") |
| 201 | 203 | ||
| 202 | # STANDARD WORDPRESS SITE | 204 | # STANDARD WORDPRESS SITE |
| 203 | when 'wordpress' | 205 | when 'wordpress' |
| @@ -214,9 +216,9 @@ node[cb]['nginx']['sites'].each do |site| | @@ -214,9 +216,9 @@ node[cb]['nginx']['sites'].each do |site| | ||
| 214 | end | 216 | end |
| 215 | site_includes.push("#{inc_dir}/inc_type_wordpress_#{site_sname}") | 217 | site_includes.push("#{inc_dir}/inc_type_wordpress_#{site_sname}") |
| 216 | 218 | ||
| 217 | - # REVERSE PROXY WEBSERVER | ||
| 218 | - when 'webserver' | ||
| 219 | - template "#{inc_dir}/inc_type_webserver_#{site_sname}" do | 219 | + # REVERSE PROXY WEBSERVER WITH WEBSOCKET |
| 220 | + when 'webserver', 'webserver_ws' | ||
| 221 | + template "#{inc_dir}/inc_type_webserver_ws_#{site_sname}" do | ||
| 220 | source 'inc_type_webserver.erb' | 222 | source 'inc_type_webserver.erb' |
| 221 | mode 0644 | 223 | mode 0644 |
| 222 | variables vars | 224 | variables vars |
| @@ -225,7 +227,19 @@ node[cb]['nginx']['sites'].each do |site| | @@ -225,7 +227,19 @@ node[cb]['nginx']['sites'].each do |site| | ||
| 225 | " default upgrade;\n"\ | 227 | " default upgrade;\n"\ |
| 226 | " '' close;\n"\ | 228 | " '' close;\n"\ |
| 227 | "}") | 229 | "}") |
| 228 | - site_includes.push("#{inc_dir}/inc_type_webserver_#{site_sname}") | 230 | + site_includes.push("#{inc_dir}/inc_type_webserver_ws_#{site_sname}") |
| 231 | + | ||
| 232 | + # GENERIC REVERSE PROXY WEBSERVER | ||
| 233 | + when 'webserver_basic' | ||
| 234 | + vars[:cparams] = stype[:custom_params] || {} | ||
| 235 | + | ||
| 236 | + template "#{inc_dir}/inc_type_webserver_basic_#{site_sname}" do | ||
| 237 | + source stype[:source] || 'inc_type_webserver_basic.erb' | ||
| 238 | + cookbook stype[:cookbook] || cookbook_name | ||
| 239 | + mode 0644 | ||
| 240 | + variables vars | ||
| 241 | + end | ||
| 242 | + site_includes.push("#{inc_dir}/inc_type_webserver_basic_#{site_sname}") | ||
| 229 | 243 | ||
| 230 | else | 244 | else |
| 231 | Chef::Log.error("Unknown site type: #{stype[:type]}") | 245 | Chef::Log.error("Unknown site type: #{stype[:type]}") |
| @@ -36,6 +36,9 @@ location ~ ^/<%= @subpath %>.+\.php(/|$) { | @@ -36,6 +36,9 @@ location ~ ^/<%= @subpath %>.+\.php(/|$) { | ||
| 36 | include fastcgi_params; | 36 | include fastcgi_params; |
| 37 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | 37 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
| 38 | 38 | ||
| 39 | + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | ||
| 40 | + fastcgi_param HTTP_PROXY ""; | ||
| 41 | + | ||
| 39 | fastcgi_pass <%= @upstream_name %>; | 42 | fastcgi_pass <%= @upstream_name %>; |
| 40 | } | 43 | } |
| 41 | 44 |
| @@ -22,8 +22,13 @@ location ~* ^/<%= @subpath %>.+\.(<%= @static_types.join('|') %>)$ { | @@ -22,8 +22,13 @@ location ~* ^/<%= @subpath %>.+\.(<%= @static_types.join('|') %>)$ { | ||
| 22 | 22 | ||
| 23 | <% end -%> | 23 | <% end -%> |
| 24 | location ~ ^/<%= @subpath %> { | 24 | location ~ ^/<%= @subpath %> { |
| 25 | + proxy_redirect off; | ||
| 25 | proxy_pass http://<%= @upstream_name %>; | 26 | proxy_pass http://<%= @upstream_name %>; |
| 26 | proxy_http_version 1.1; | 27 | proxy_http_version 1.1; |
| 28 | + | ||
| 29 | + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | ||
| 30 | + proxy_set_header Proxy ""; | ||
| 31 | + | ||
| 27 | proxy_set_header Upgrade $http_upgrade; | 32 | proxy_set_header Upgrade $http_upgrade; |
| 28 | proxy_set_header Connection $connection_upgrade; | 33 | proxy_set_header Connection $connection_upgrade; |
| 29 | proxy_set_header X-Real-IP $remote_addr; | 34 | proxy_set_header X-Real-IP $remote_addr; |
| 1 | +# Generated by Chef | ||
| 2 | +<% -%> | ||
| 3 | +<% # This is an example template. Use this as a guide for your wrapper.-%> | ||
| 4 | +<% # It expects a :cparams hash with the following keys:-%> | ||
| 5 | +<% # :proxy_host-%> | ||
| 6 | +<% # :proxy_port-%> | ||
| 7 | + | ||
| 8 | +<% if @static_types -%> | ||
| 9 | +# Send expires headers and (probably?) turn off 404 error logging. | ||
| 10 | +location ~* ^/<%= @subpath %>.+\.(<%= @static_types.join('|') %>)$ { | ||
| 11 | + expires max; | ||
| 12 | +<% unless @log_static -%> | ||
| 13 | + log_not_found off; | ||
| 14 | + access_log off; | ||
| 15 | +<% end -%> | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +<% end -%> | ||
| 19 | +location ~ ^/<%= @subpath %> { | ||
| 20 | + proxy_redirect off; | ||
| 21 | + proxy_pass http://<%= @cparams[:proxy_host] %>:<%= @cparams[:proxy_port] %>; | ||
| 22 | + proxy_set_header Connection ""; | ||
| 23 | + | ||
| 24 | + proxy_http_version 1.1; | ||
| 25 | + proxy_pass_request_headers on; | ||
| 26 | + | ||
| 27 | + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | ||
| 28 | + proxy_set_header Proxy ""; | ||
| 29 | + | ||
| 30 | + proxy_set_header X-Real-IP $remote_addr; | ||
| 31 | + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | ||
| 32 | + proxy_set_header Host $http_host; | ||
| 33 | +} |
| @@ -46,6 +46,9 @@ location ~ ^/<%= @subpath %>(wp-admin|wp-login\.php) { | @@ -46,6 +46,9 @@ location ~ ^/<%= @subpath %>(wp-admin|wp-login\.php) { | ||
| 46 | include fastcgi_params; | 46 | include fastcgi_params; |
| 47 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | 47 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
| 48 | 48 | ||
| 49 | + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | ||
| 50 | + fastcgi_param HTTP_PROXY ""; | ||
| 51 | + | ||
| 49 | fastcgi_pass <%= @upstream_name %>; | 52 | fastcgi_pass <%= @upstream_name %>; |
| 50 | } | 53 | } |
| 51 | } | 54 | } |
| @@ -65,6 +68,9 @@ location ~ ^/<%= @subpath %>.+\.php(/|$) { | @@ -65,6 +68,9 @@ location ~ ^/<%= @subpath %>.+\.php(/|$) { | ||
| 65 | include fastcgi_params; | 68 | include fastcgi_params; |
| 66 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | 69 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
| 67 | 70 | ||
| 71 | + # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | ||
| 72 | + fastcgi_param HTTP_PROXY ""; | ||
| 73 | + | ||
| 68 | fastcgi_pass <%= @upstream_name %>; | 74 | fastcgi_pass <%= @upstream_name %>; |
| 69 | } | 75 | } |
| 70 | 76 |