Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit 4116174

Browse files
committed
Add option to skip adding X-Forwarded-Proto header.
1 parent d031529 commit 4116174

4 files changed

Lines changed: 61 additions & 10 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ Settings in this part is immutable, you have to redeploy HAProxy service to make
185185
|MONITOR_URI| |the exact URI which we want to intercept to return HAProxy's health status instead of forwarding the request.See: http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-monitor-uri. Possible value: `/ping`|
186186
|OPTION|redispatch|comma-separated list of HAProxy `option` entries to the `default` section.|
187187
|RSYSLOG_DESTINATION|127.0.0.1|the rsyslog destination to where HAProxy logs are sent|
188+
|SKIP_FORWARDED_PROTO||If set to any value, HAProxy will not add an X-Forwarded- headers. This can be used when combining HAProxy with another load balancer|
188189
|SSL_BIND_CIPHERS| |explicitly set which SSL ciphers will be used for the SSL server. This sets the HAProxy `ssl-default-bind-ciphers` configuration setting.|
189190
|SSL_BIND_OPTIONS|no-sslv3|explicitly set which SSL bind options will be used for the SSL server. This sets the HAProxy `ssl-default-bind-options` configuration setting. The default will allow only TLSv1.0+ to be used on the SSL server.|
190191
|STATS_AUTH|stats:stats|username and password required to access the Haproxy stats.|

haproxy/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def parse_extra_frontend_settings(envvars):
5353
MONITOR_URI = os.getenv("MONITOR_URI")
5454
OPTION = os.getenv("OPTION", "redispatch, httplog, dontlognull, forwardfor")
5555
RSYSLOG_DESTINATION = os.getenv("RSYSLOG_DESTINATION", "127.0.0.1")
56+
SKIP_FORWARDED_PROTO = os.getenv("SKIP_FORWARDED_PROTO")
5657
SSL_BIND_CIPHERS = os.getenv("SSL_BIND_CIPHERS")
5758
SSL_BIND_OPTIONS = os.getenv("SSL_BIND_OPTIONS")
5859
STATS_AUTH = os.getenv("STATS_AUTH", "stats:stats")

haproxy/helper/frontend_helper.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from collections import OrderedDict
22

3-
from haproxy.config import EXTRA_BIND_SETTINGS, EXTRA_FRONTEND_SETTINGS, MONITOR_URI, MONITOR_PORT, MAXCONN
3+
from haproxy.config import EXTRA_BIND_SETTINGS, EXTRA_FRONTEND_SETTINGS, MONITOR_URI, MONITOR_PORT, MAXCONN, SKIP_FORWARDED_PROTO
44

55

66
def check_require_default_route(routes, routes_added):
@@ -95,11 +95,12 @@ def config_common_part(port, ssl_bind_string, vhosts):
9595
bind_string, ssl = get_bind_string(port, ssl_bind_string, vhosts)
9696
frontend_section.append("bind :%s" % bind_string)
9797

98-
# add x-forwarded-porto header
99-
if ssl:
100-
frontend_section.append("reqadd X-Forwarded-Proto:\ https")
101-
else:
102-
frontend_section.append("reqadd X-Forwarded-Proto:\ http")
98+
# add x-forwarded-porto header if not skipped
99+
if not SKIP_FORWARDED_PROTO:
100+
if ssl:
101+
frontend_section.append("reqadd X-Forwarded-Proto:\ https")
102+
else:
103+
frontend_section.append("reqadd X-Forwarded-Proto:\ http")
103104

104105
# add maxconn
105106
frontend_section.append("maxconn %s" % MAXCONN)
@@ -135,8 +136,13 @@ def get_bind_string(port, ssl_bind_string, vhosts):
135136
def config_default_frontend(ssl_bind_string):
136137
cfg = OrderedDict()
137138
monitor_uri_configured = False
138-
frontend = [("bind :80 %s" % EXTRA_BIND_SETTINGS.get('80', "")).strip(),
139-
"reqadd X-Forwarded-Proto:\ http", "maxconn %s" % MAXCONN]
139+
frontend = [("bind :80 %s" % EXTRA_BIND_SETTINGS.get('80', "")).strip()]
140+
141+
# add x-forwarded-porto header if not skipped
142+
if not SKIP_FORWARDED_PROTO:
143+
frontend.append("reqadd X-Forwarded-Proto:\ http")
144+
145+
frontend.append("maxconn %s" % MAXCONN)
140146

141147
if MONITOR_URI and MONITOR_PORT == '80':
142148
frontend.append("monitor-uri %s" % MONITOR_URI)
@@ -149,8 +155,13 @@ def config_default_frontend(ssl_bind_string):
149155
cfg["frontend default_port_80"] = frontend
150156

151157
if ssl_bind_string:
152-
ssl_frontend = [("bind :443 %s %s" % (ssl_bind_string, EXTRA_BIND_SETTINGS.get('443', ""))).strip(),
153-
"reqadd X-Forwarded-Proto:\ https", "maxconn %s" % MAXCONN]
158+
ssl_frontend = [("bind :443 %s %s" % (ssl_bind_string, EXTRA_BIND_SETTINGS.get('443', ""))).strip()]
159+
160+
# add x-forwarded-porto header if not skipped
161+
if not SKIP_FORWARDED_PROTO:
162+
ssl_frontend.append("reqadd X-Forwarded-Proto:\ https")
163+
164+
ssl_frontend.append("maxconn %s" % MAXCONN)
154165

155166
if MONITOR_URI and (MONITOR_PORT == '443'):
156167
ssl_frontend.append("monitor-uri %s" % MONITOR_URI)

tests/unit/helper/test_frontend_helper.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ def setUp(self):
1717
frontend_helper.EXTRA_BIND_SETTINGS = {"8888": "name http", "4443": "accept-proxy"}
1818
frontend_helper.MAXCONN = "55555"
1919
frontend_helper.EXTRA_FRONTEND_SETTINGS = {}
20+
frontend_helper.SKIP_FORWARDED_PROTO = None
2021

2122
def tearDown(self):
2223
frontend_helper.MONITOR_PORT = self.monitor_port
2324
frontend_helper.MONITOR_URI = self.monitor_uri
2425
frontend_helper.EXTRA_BIND_SETTINGS = self.extra_bind_settings
2526
frontend_helper.MAXCONN = self.maxconn
2627
frontend_helper.EXTRA_FRONTEND_SETTINGS = {}
28+
frontend_helper.SKIP_FORWARDED_PROTO = None
2729

2830
def test_config_frontend_with_virtual_host_without_monitoring_uri_added(self):
2931
vhosts = [{'service_alias': 'web-a', 'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '80'}]
@@ -185,6 +187,27 @@ def test_config_common_part_with_extra_frontend_sttings(self, mock_get_bind_stri
185187
self.assertFalse(monitor_uri_configured)
186188
frontend_helper.EXTRA_FRONTEND_SETTINGS = {}
187189

190+
@mock.patch("haproxy.helper.frontend_helper.get_bind_string")
191+
def test_config_common_part_without_forwarded_headers(self, mock_get_bind_string):
192+
mock_get_bind_string.return_value = ("80", False)
193+
frontend_helper.SKIP_FORWARDED_PROTO = 'true'
194+
frontend_section, monitor_uri_configured = config_common_part("80", "ssl crt /certs/", [])
195+
self.assertEqual(["bind :80",
196+
"maxconn 55555",
197+
"acl is_websocket hdr(Upgrade) -i WebSocket"],
198+
frontend_section)
199+
200+
@mock.patch("haproxy.helper.frontend_helper.get_bind_string")
201+
def test_config_common_part_without_forwarded_headers_with_ssl(self, mock_get_bind_string):
202+
mock_get_bind_string.return_value = ("9999 ssl crt /certs/", True)
203+
frontend_helper.SKIP_FORWARDED_PROTO = 'true'
204+
frontend_section, monitor_uri_configured = config_common_part("9999", "ssl crt /certs/", [])
205+
self.assertEqual(["bind :9999 ssl crt /certs/",
206+
'maxconn 55555',
207+
"monitor-uri %s" % frontend_helper.MONITOR_URI,
208+
"acl is_websocket hdr(Upgrade) -i WebSocket"],
209+
frontend_section)
210+
188211
def test_get_bind_string(self):
189212
vhosts = [{'service_alias': 'web-a', 'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '80'},
190213
{'service_alias': 'web-b', 'path': '', 'host': 'a.com', 'scheme': 'http', 'port': '8888'},
@@ -277,6 +300,21 @@ def test_config_default_front(self):
277300
'default_backend default_service'])]), cfg)
278301
self.assertTrue(monitor_uri_configured)
279302

303+
frontend_helper.SKIP_FORWARDED_PROTO = 'true'
304+
cfg, monitor_uri_configured = config_default_frontend("ssl crt /certs/")
305+
self.assertEqual(OrderedDict([('frontend default_port_80',
306+
['bind :80',
307+
'maxconn 55555',
308+
'reqadd header1 value1',
309+
'default_backend default_service']),
310+
('frontend default_port_443',
311+
['bind :443 ssl crt /certs/ accept-proxy',
312+
'maxconn 55555',
313+
'monitor-uri /ping',
314+
'reqadd header2 value2',
315+
'default_backend default_service'])]), cfg)
316+
self.assertTrue(monitor_uri_configured)
317+
280318
def test_config_common_part_with_monitor_uri(self):
281319
self.assertEqual(OrderedDict(), config_monitor_frontend(True))
282320
self.assertEqual(OrderedDict([('frontend monitor', ['bind :9999', 'monitor-uri /ping'])]),

0 commit comments

Comments
 (0)