From cc2db04b47c5b5daf73873f3865da715812408db Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 18 May 2015 22:28:40 +0000 Subject: proxy_pass: allow filtering or overriding response headers We shouldn't blindly pass the "Server" tag through, since we may be proxying Apache instances and we don't want to misadvertise, either. IMHO, it is best to say nothing at all to save bandwidth and reduce the potential for attackers in case a vulnerability is discovered in yahns. --- lib/yahns/proxy_http_response.rb | 9 +++++++++ lib/yahns/proxy_pass.rb | 9 ++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb index 90a9395..cbdce6f 100644 --- a/lib/yahns/proxy_http_response.rb +++ b/lib/yahns/proxy_http_response.rb @@ -66,6 +66,7 @@ module Yahns::HttpResponse # :nodoc: env[REQUEST_METHOD] != HEAD flags = MSG_DONTWAIT alive = @hs.next? && self.class.persistent_connections + response_headers = env['yahns.proxy_pass.response_headers'] res = "HTTP/1.1 #{status}\r\n" headers.each do |key,value| # n.b.: headers is an Array of 2-element Arrays @@ -76,6 +77,14 @@ module Yahns::HttpResponse # :nodoc: flags |= MSG_MORE if have_body && value.to_i > 0 end + # response header mapping + case val = response_headers[key] + when :ignore + next + when String + value = val + end + res << "#{key}: #{value}\r\n" end diff --git a/lib/yahns/proxy_pass.rb b/lib/yahns/proxy_pass.rb index 15c9f53..89c6ef8 100644 --- a/lib/yahns/proxy_pass.rb +++ b/lib/yahns/proxy_pass.rb @@ -172,7 +172,7 @@ class Yahns::ProxyPass # :nodoc: end end # class ReqRes - def initialize(dest) + def initialize(dest, opts = {}) case dest when %r{\Aunix:([^:]+)(?::(/.*))?\z} path = $2 @@ -184,6 +184,12 @@ class Yahns::ProxyPass # :nodoc: else raise ArgumentError, "destination must be an HTTP URL or unix: path" end + @response_headers = opts[:response_headers] || {} + + # It's wrong to send the backend Server tag through. Let users say + # { "Server => "yahns" } if they want to advertise for us, but don't + # advertise by default (for security) + @response_headers['Server'] ||= :ignore init_path_vars(path) end @@ -237,6 +243,7 @@ class Yahns::ProxyPass # :nodoc: ctype = env["CONTENT_TYPE"] and req << "Content-Type: #{ctype}\r\n" clen = env["CONTENT_LENGTH"] and req << "Content-Length: #{clen}\r\n" input = chunked || (clen && clen.to_i > 0) ? env['rack.input'] : nil + env['yahns.proxy_pass.response_headers'] = @response_headers # finally, prepare to emit the headers rr.req_start(c, req << "\r\n".freeze, input, chunked) -- cgit v1.2.3-24-ge0c7