HAProxy redirecting http to https (ssl) - http

I'm using HAProxy for load balancing and only want my site to support https. Thus, I'd like to redirect all requests on port 80 to port 443.
How would I do this?
Edit: We'd like to redirect to the same url on https, preserving query params. Thus, http://foo.com/bar would redirect to https://foo.com/bar

I found this to be the biggest help:
Use HAProxy 1.5 or newer, and simply add the following line to the frontend config:
redirect scheme https code 301 if !{ ssl_fc }

I don't have enough reputation to comment on a previous answer, so I'm posting a new answer to complement Jay Taylor's answer. Basically his answer will do the redirect, an implicit redirect though, meaning it will issue a 302 (temporary redirect), but since the question informs that the entire website will be served as https, then the appropriate redirect should be a 301 (permanent redirect).
redirect scheme https code 301 if !{ ssl_fc }
It seems a small change, but the impact might be huge depending on the website, with a permanent redirect we are informing the browser that it should no longer look for the http version from the start (avoiding future redirects) - a time saver for https sites. It also helps with SEO, but not dividing the juice of your links.

To redirect all traffic:
redirect scheme https if !{ ssl_fc }
To redirect a single url (In case of multiple frontend/backend)
redirect scheme https if { hdr(Host) -i www.mydomain.com } !{ ssl_fc }

The best guaranteed way to redirect everything http to https is:
frontend http-in
bind *:80
mode http
redirect scheme https code 301
This is a little fancier using ‘code 301′, but might as well let the client know it’s permanent. The ‘mode http’ part is not essential with default configuration, but can’t hurt. If you have mode tcp in defaults section (like I did), then it’s necessary.

According to http://parsnips.net/haproxy-http-to-https-redirect/ it should be as easy as configuring your haproxy.cfg to contain the follow.
#---------------------------------------------------------------------
# Redirect to secured
#---------------------------------------------------------------------
frontend unsecured *:80
redirect location https://foo.bar.com
#---------------------------------------------------------------------
# frontend secured
#---------------------------------------------------------------------
frontend secured *:443
mode tcp
default_backend app
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
mode tcp
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check

A slight variation of user2966600's solution...
To redirect all except a single URL (In case of multiple frontend/backend):
redirect scheme https if !{ hdr(Host) -i www.mydomain.com } !{ ssl_fc }

Like Jay Taylor said, HAProxy 1.5-dev has the redirect scheme configuration directive, which accomplishes exactly what you need.
However, if you are unable to use 1.5, and if you're up for compiling HAProxy from source, I backported the redirect scheme functionality so it works in 1.4. You can get the patch here: http://marc.info/?l=haproxy&m=138456233430692&w=2

frontend unsecured *:80
mode http
redirect location https://foo.bar.com

redirect statement is legacy
use http-request redirect instead
acl http ssl_fc,not
http-request redirect scheme https if http

In newer versions of HAProxy it is recommended to use
http-request redirect scheme https if !{ ssl_fc }
to redirect http traffic to https.

Can be done like this -
frontend http-in
bind *:80
mode http
redirect scheme https code 301
Any traffic hitting http will redirect to https

acl host-example hdr(host) -i www.example.com
# for everything not https
http-request redirect scheme https code 301 unless { ssl_fc }
# for anything matching acl
http-request redirect scheme https code 301 if host-example !{ ssl_fc }

If you want to rewrite the url, you have to change your site virtualhost adding this lines:
### Enabling mod_rewrite
Options FollowSymLinks
RewriteEngine on
### Rewrite http:// => https://
RewriteCond %{SERVER_PORT} 80$
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,NC,L]
But, if you want to redirect all your requests on the port 80 to the port 443 of the web servers behind the proxy, you can try this example conf on your haproxy.cfg:
##########
# Global #
##########
global
maxconn 100
spread-checks 50
daemon
nbproc 4
############
# Defaults #
############
defaults
maxconn 100
log global
mode http
option dontlognull
retries 3
contimeout 60000
clitimeout 60000
srvtimeout 60000
#####################
# Frontend: HTTP-IN #
#####################
frontend http-in
bind *:80
option logasap
option httplog
option httpclose
log global
default_backend sslwebserver
#########################
# Backend: SSLWEBSERVER #
#########################
backend sslwebserver
option httplog
option forwardfor
option abortonclose
log global
balance roundrobin
# Server List
server sslws01 webserver01:443 check
server sslws02 webserver02:443 check
server sslws03 webserver03:443 check
I hope this help you

Why don't you use ACL's to distinguish traffic? on top of my head:
acl go_sslwebserver path bar
use_backend sslwebserver if go_sslwebserver
This goes on top of what Matthew Brown answered.
See the ha docs , search for things like hdr_dom and below to find more ACL options. There are plenty of choices.

Add this into the HAProxy frontend config:
acl http ssl_fc,not
http-request redirect scheme https if http
HAProxy - Redirecting HTTP Requests

Simply:
frontend incoming_requsts
bind *:80
bind *:443 ssl crt *path_to_cert*.**pem**
**http-request redirect scheme https unless { ssl_fc }**
default_backend k8s_nodes

Related

Nginx as proxy : how to exclude specific folder under https but not under http

I can rewrite some specific http folders to https folders, but i can't rewrite all https except these specific folders from https to http; i'm stuck in a loop
Using NGinx 1.12 as a proxy, handling both http and https
i have one server section to handle http 80 and one server section to handle https (i know they can be together in the same section).
both of them are beginning that way
location / {
proxy_pass
server {
listen 80;
i have
location ~ ^/(xxx|yyy|zzz)/.*$ {
rewrite ^ https://www.example.com$uri permanent;
}
and anytime i'm in http, it is redirecting to https fine for the xxx,yyy and zzz folders. so far, so good.
but under server {
listen 443 ssl;
, i would like to redirect everything except the xxx,yyy,zzz folder to go back to http.
I did try to do the reverse in the https section meaning :
location / {
rewrite ^ http://www.example.com$uri permanent;
}
and
location ~ ^/(xxx|yyy|zzz)/.*$ {
#do nothing
}
but it is not working, either i get a 404 error or a loop
The only solution i found as Nginx is a proxy is making Apache handling the redirect on its side.
so,
a. nginx 80 is redirecting to nginx 443 specific folders.
b. all https is redirect by nginx 443 to apache 443, and then in apache 443 conf i do a test, if it the specific folders, i stop, and otherwise i redirect to nginx 80.
It's working, but i'm sure it is possible to make nginx handle it and avoid this 1 loop. if someone as a beautiful answer :-)

Nginx https proxy pass - zanata

i have a central reverse proxy with nginx, and inside of my environment i have a unified development tool like this:
dev.mycompany.com.br
and some applications like jenkins, artifactory.. working very well
dev.mycompany.com.br/jenkins
dev.mycompany.com.br/artifactory
but now i tryed to add another application (zanata) working in my docker server listening in following address: http://192.168.4.240:8080/zanata
in dev.conf in my nginx server i added the follow configuration for reverse proxy:
location /zanata {
proxy_pass http://192.168.4.240:8080/zanata/;
but returns blank page and 404 http code in access log.
if i remove /zanata like this:
proxy_pass http://192.168.4.240:8080/;
working fine and go to the wildfly welcome page.
somebody have a idea for this work this configuration?
thanks!
I think yo use https on top of your proxy and when zanata redirect it replaces the protocol by http.
curl -vvv https://myserver.com/zanata to see that.
edit your proxy to redirect http to https and it should work.
something like this :
server {
listen 80;`
server_name myserver.com;
return 301 https://$server_name$request_uri;
}

Single haproxy instance running on http as well as tcp mode

I have two web applications running on a server inside two separate docker containers, one of them is running on play framework server (java), while other is running on nginx (php). I am doing ssl termination in http mode at haproxy for the play app. I want to handle the ssl termination for other app at nginx.
Is it possible to configure haproxy in such a way, so that one front-end forwards the request in tcp mode, and another in http mode. Below is how my haproxy.cfg would look like.
frontend http-in
mode http
bind *:80
redirect scheme https code 301 if !{ ssl_fc }
frontend https-in
# bind *:80
bind *:443 ssl crt /etc/ssl/certs/my_certificate_file.pem
reqadd X-Forwarded-Proto:\ https
# redirect scheme https code 301 if !{ ssl_fc }
mode http
option httpclose
option forwardfor
# Define hosts based on domain names
acl host_test_ssh hdr(host) -i playapp.domain.com
## figure out backend to use based on domainname
use_backend testssh if host_test_ssh
frontend http-in-other
bind *:80
mode tcp
option tcplog
redirect scheme https if !{ ssl_fc }
frontend https-in-estore
bind *:443
mode tcp
option tcplog
# Define hosts based on domain names
acl host_test_ssh hdr(host) -i nginxapp.domain2.com
## figure out backend to use based on domainname
use_backend other if host_test_ssh
I have not tried this but based on the documentation of 1.5 it should work. http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4.2-mode

Forcing HTTPS when using opsworks nginx and ELB to terminate SSL

Using Opsworks standard setup/recipes for a Rails app served via Unicorn/nginx layer. SSL is terminated at the Elastic Load Balancer - so traffic to the rails app from ELB is always http. So far so good. I would like to have any request to http://domain.com to be redirected to https://domain.com
ELB has two listeners - one with port 80, and one 443.
I know that if I were running my own nginx I could setup a redirect rule... However, i want to stay within the opsworks way of doing things if possible.
I think the only way to do this in OpsWorks is to create a custom recipe that modifies /etc/nginx/sites-available/#{application}. In your custom cookbook:
somecookbook/recipes/nginx.rb
node[:deploy].each do |application, deploy|
service "nginx" do
supports :status => true
action :nothing
end
# Add HTTP => HTTPS redirect
template "/tmp/http_redirect.conf" do
source "nginx/http_redirect.conf.erb"
end
execute "redirect HTTP to HTTPS" do
cwd "/etc/nginx/sites-available"
command "cat #{application} /tmp/http_redirect.conf > /tmp/#{application}.conf && cat /tmp/#{application}.conf > #{application}"
notifies :restart, "service[nginx]", :immediately
end
end
end
Then in the config:
somecookbook/templates/default/nginx/http_redirect.conf.erb
server {
listen 80;
rewrite ^(.*) https://$host$1 permanent;
}
I'm pretty sure you have to use nginx on your app server to handle the redirect http -> https.
Here are a two methods to solve this.
redirect all requests from 80 to https:
server {
listen 80;
return 301 https://example.com/$request_uri;
}
ELB supports a header called X-FORWARDED-PROTO.
All HTTPS requests going through the ELB will have the value of X-FORWARDED-PROTO = “HTTPS” :
server {
listen 80;
location / {
if ($http_x_forwarded_proto != 'https') {
rewrite ^ https://$host$request_uri? permanent;
}
}
}

How to configure Nginx behind a corporate proxy

Is there an equivalent of apache's ProxyRemote directive for NginX?
So the scenario is I am behind a corporate proxy and I want to do proxy passes for various services with NginX. I would do it in Apache with the following:
ProxyPass /localStackOverflow/ https://stackoverflow.com/
ProxyPassReverse /localStackOverflow/ https://stackoverflow.com/
ProxyRemote https://stackoverflow.com/ http://(my corporate proxy IP)
I know I need the proxy_pass directive in NginX but can't find what I would use for the ProxyRemote.
Thanks
Not sure how #tacos response can work - possibly something I'm missing but the only way I could sort of get this to work was by rewriting the url and passing on to the corporate proxy. This is shown below:
http {
server {
listen 80;
location / {
rewrite ^(.*)$ "http://www.externalsite.com$1" break;
proxy_pass http://corporate-proxy.mycorp.com:8080;
}
}
}
This works, but does rewrite the url, not sure if this is important to the original use-case..
The servers you proxy behind an Nginx front-end web server are referred to as upstream servers. You will want to refer to the documentation for the HttpUpstreamModule. It's very similair to what you are familiar with. If you don't need load-balancing, you just setup the one upstream server in the configuration and it will serve your purpose.

Resources