I have an HAProxy instance that is available from the web, and redirects incoming requests to my local app.
The communication between the client and my HAProxy can be secured via ssl but not necessarily, and I need to know at my application level if the communication is secure or not.
Unfortunately, from my understanding, the communication I get in my app is already "decrypted" from all the SSL communications, HAProxy handling the "SSL wrapping".
Is there a way to know for sure that the client is using SSL/TLS or no?
Thank you in advance.
Update The communication is not HTTP but TCP at HAProxy.
This is the purpose of the X-Forwarded-Proto.
You can make HAProxy insert that header if ssl traffic was decrypted by HAProxy:
http-request set-header X-Forwarded-Proto https if { ssl_fc }
Then your application will just have to check the X-Forwarded-Proto.
Related
AWS NLB supports TLS termination
https://aws.amazon.com/blogs/aws/new-tls-termination-for-network-load-balancers/
NLB being a Layer 4 load balancer I would expect it to work in a passthrough mode by directing the incoming packets to one of the backends without much of state maintenance (except for the flow tracking)
Are there any details available on how AWS implements the TLS termination in NLB ?
Is it possible to do it with open source tooling (like IPVS or haproxy) or AWS has some secret sauce here ?
The TLS termination itself is just what it says it is. TLS is a generic streaming protocol just like TCP one level up so you can unwrap it at the LB in a generic way. The magic is that they keep the IPs intact probably with very fancy routing magic, but it seems unlikely AWS will tell you how they did it.
In my SO question here, I have an example of how to terminate a TCP session in HAProxy and pass the unencrypted traffic to a backend.
In short, you need to use ssl in the frontend bind section and both frontend and backend configurations require use of tcp mode. Here is an example of terminating on port 443 and forwarding to port 4567.
frontend tcp-proxy
bind :443 ssl crt combined-cert-key.pem
mode tcp
default_backend bk_default
backend bk_default
mode tcp
server server1 1.2.3.4:4567
How can I achieve reverse SSL termination with ha proxy?
From my backend via HAproxy I need to a https enabled web service. How can I successfully proxy all traffic to that service via HAProxy?
Below results in Unable to communicate securely with peer: requested domain name does not match the server's certificate.
frontend foofront
bind 127.0.0.1:443
mode tcp
default_backend foo
backend fooback
mode tcp
balance leastconn
server foo foo.bar.com:443 check
With HAProxy you usually have two options for handling TLS-related scenarios. TLS Passthrough and TLS Termination.
TLS Passthrough
Looks like you're trying to do this in the example you gave.
In this mode, HAProxy does not touch traffic in any way, but is just forwarding it to the backend. When TLS is involved, that means that the backend has to have a proper certificate for a domain it's accessed from - if your HAProxy is handling traffic for myexample.com, backend servers will need to have appropriate certificates for myexample.com installed.
You can always check which certificate is served by using openssl s_client:
openssl s_client -connect localhost:443
TLS Termination
Alternatively, you can terminate TLS traffic on HAProxy itself. This will allow you to use any backend (both encrypted and unencrypted). In this case, HAProxy itself decrypts traffic for myexample.com and forwards it to backend.
In your case, configuration would look something like:
frontend foofront
bind 127.0.0.1:80
bind 127.0.0.1:443 ssl crt /path/to/cert/for/myexample.com
mode tcp
default_backend foo
backend foo
mode tcp
balance leastconn
server foo foo.bar.com:443 check ssl verify none # or verify all to enforce ssl checking
You can find more info on both approaches here.
Hope this helps.
I found some inconvenience in haproxy 1.5 when i try to configure SSL SNI.
There is a fragment of haproxy configuration: pastebin
I would like to pass client IP to backend. No matter how I configure reqadd / set-header X-Forwarded-For / Real-IP I always got a haproxy IP address in X-Forwarded-For.
Someone try to pass real IP with SSL SNI on HAProxy
? :/
From this configuration, you seem to be doing SNI-sniffing, yet all of the backends are looping back to HAProxy itself... which is not a case where SNI-sniffing is required. Perhaps I'm overlooking something else that would require this.
It should be apparent why you are getting the proxy's IP in X-Forwarded-For -- HAProxy is talking to itself. The first pass through the proxy is the client connection, as far as the proxy can determine on the second pass, because only the second pass is speaking HTTP. It only sees that an incoming TCP connection has arrived... from itself.
The solution is for the first-pass backend to pass the original client information using the Proxy Protocol and the second-pass frontend to decode it.
Add accept-proxy to the bind lines for the second-pass frontends, and add send-proxy to the server lines on the first-pass backends. This way, on the connection where HAProxy is talking to itself, the first-pass backend will send the Proxy protocol preamble and the second-pass frontend will decode the incoming value and place it in X-Forwarded-For.
I try to get Cloudflare work with my website.
I have my website running on port 80 and my api on port 8443.
My proxy doesn't have a ssl certificate, I rely only on the one on Cloudflare.
I have set ssl to flexible.
I can access my website, but when I make an API call to my api on port 8443, I have the following message : CloudFlare is unable to establish an SSL connection to the origin server.
Do I need to have a certificate on my proxy for the API ?
Thanks for your help.
It sounds like you're using Cloudflare's Flexible SSL option whereby traffic is unencrypted to the origin web server (but encrypted from Cloudflare's Edge to the end-user).
This setting will only work for port 443->80, not for the other ports Cloudflare supports like 2053 (or 8443 in your case).
If you want to serve SSL traffic through a port other than 443, you will need to ensure your web server is configured to work with Cloudflare in either Full or Full (Strict) SSL mode.
For more info:
What do the SSL options mean?
Okay, so I know that we can either forward HTTPS traffic via haproxy to backend servers intact or have SSL terminated at the proxy server, and let remaining course of the traffic be unencrypted. But is there a way to make haproxy work such that the traffic is decrypted at the server and recrypted before being sent to the backend nodes?
Basically I am getting half the job done with SSL termination, but I want traffic to be encrypted again once it leaves the proxy server.
Is this possible with haproxy on its own? or is there some other tool I could use in combination with haproxy to create and manage HTTPS/SSL sessions with backend servers?
Have you tried setting it up like this:
Haproxy terminates the SSL then, instead of forwarding the unencrypted traffic to your backend on a HTTP port, try forwarding it to a HTTPS port on the backend and wrap that in a self signed cert.
i.e:
SSL Traffic -> haproxy:443(domain cert) -> backend:443(internal cert)
I have set this up before and it worked fine