haproxy bind multiple ports for https forwarding - ssl

I'am trying to forward 2 https ports to 2 different destinations but the haproxy service fails to start. When i use simple http all is ok. Does Haproxy support 2 https ports or something am doing wrong?. Below is my haproxy configuration for this.
frontend https1
bind *:9444 ssl crt /etc/haproxy/ssl/server.pem
mode http
use_backend bk1_https
frontend https2
bind *:9443 ssl crt /etc/haproxy/ssl/server2.pem
mode http
use_backend bk2_https
backend bk1_https
balance first
server server1 IP1:9444 check ssl verify none
backend bk2_https
balance first
server server1 Ip1:9443 check ssl verify none

Related

HAProxy TCP (443) Loadbalancing with different backend ports

I'm implementing a Frontend Loadbalancer which passthrough the traffic coming to port 80 and 443 to different backend ports. SSL termination is happening in the backend and HAproxy should not engage with anything other than forwarding the traffic coming to the frontend port 80 and 443 to the respective backend ports.
Port 80 forwarding seems fine and 443 is not working as expected and giving SSL handshake failure. Even my backend service is not coming up on the web browser with a warning saying this is not trusted. I have no clue why this is happening and my HAProxy experience is not that high and below is the current configuration. Please correct me if I'm wrong.
HAProxy is installed on Ubuntu 18.04.5 LTS
Config after the defaults section
frontend k8s_lb
mode tcp
bind x.x.x.x:80
default_backend kube_minions
frontend k8s_lb_https
mode tcp
bind x.x.x.x:443
default_backend kube_minions_https
backend kube_minions
mode tcp
balance roundrobin
server k8s_worker-01 x.x.x.x:32080
server k8s_worker-02 x.x.x.x:32080
backend kube_minions_https
mode tcp
balance roundrobin
server k8s_worker-01 x.x.x.x:32443
server k8s_worker-02 x.x.x.x:32443
The backend story:
I have a k8s cluster and traefik ingress which is running as a DaemonSet on each and every node, and minions are my backend servers. CertManager is in place to do the cert automation with Let's encrypt ACME protocol in the ingress resources, hence SSL termination should be happening through the ingress resources.
I have completed the certificates and everything seems perfect as I have already implemented a similar setup on AWS with a TCP loadbalancer and everything is perfectly working and running prod workloads.
So, I need to mention that backend services are all good and up and running. In this I replaced the AWS loadbalancer with HAProxy and need to implement the same.
Please assist me to fix this as I'm struggling with this and still no luck with the issue.
Thank you.
Sorry, I was able to figure it out and there is nothing to do with traefik and HAProxy for this SSL issue. My Client's DNS is configured in CloudFlare and they have enabled the universal SSL and it caused the issue.
I checked with a new DNS record from route53 working as expected so my HAProxy config do what I need.

Is there a way to use a forwarding proxy as a backend (including authentication) in HAProxy?

I am quite new to HAProxy and want to achieve the following setup / packet flow:
Client -> HAProxy (as reverse proxy) -> Forwarding Proxy (HAProxy, IIS, Squid...) -> Internet -> server.example.com
I would like to have encrypted connections with TLS/SSL from the Client -> HAProxy and from HAProxy -> server.example.com
This means, that the forwarding proxy needs to support the HTTP CONNECT method, to establish a TCP tunnel and transmits packets without trying to interpret them. Over this TCP port I should be able to send bytes to server.example.com - TLS/SSL encrypted, so HTTPS.
Furthermore it could be, that authentication against the forwarding proxy is needed e.g. HTTP Basic authentication.
The software stack of my test setup is as follows:
Client Firefox 76.0.1
HA-Proxy version 1.6.3 2015/12/25
Squid Cache: Version 3.5.27
I have setup this HAProxy configuration:
global
# Standard settings
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
# Tuning
maxconn 2000
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-options no-sslv3
# Ensure a secure enough DH paramset
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
# Redispatch 503 errors on backends, reducing the number of 503 reaching clients
option redispatch
# We want to stall clients for as long as possible, before giving
# up with 503:
timeout connect 5m
# Clients must be acceptably responsive
timeout client 1m
# Server not as much...
timeout server 5m
# HTTPS server
frontend https-in
bind :443 ssl crt-ignore-err all crt /etc/haproxy/ssl/certkey.pem
# Don't serve HTTP directly, but redirect to same URL in https
redirect scheme https code 301 if !{ ssl_fc }
default_backend backend-proxy
backend backend-proxy
# Create the Authorization / Proxy-Authorization header value
# echo -n "user:password" | base64
http-request add-header Proxy-Authorization "Basic dXNlcjpwYXNzd29yZA=="
# We need to use the CONNECT method
http-request set-method CONNECT
# The proxyserver needs to know the full server name
http-request set-path server.example.com:443
server proxy 192.168.1.1:8080
In my test setup I use a Squid server as a forwarding proxy with the following configuration:
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 443 # https
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
auth_param basic program /usr/lib/squid3/basic_ncsa_auth /etc/squid/squid-passwd
acl basic_client proxy_auth REQUIRED
http_access deny !basic_client
http_access allow basic_client
http_access deny all
http_port 8080
coredump_dir /var/spool/squid
Using the Squid forwarding proxy in a regular browser on the same subnet including authentication works fine.
So when the first request comes in from the Client at the HAProxy it gets forwarded via the backend backend-proxy to the Forward Proxy (Squid). The CONNECT succeeds, as I see in the Squid log.
1591166403.966 60146 192.168.1.10 TCP_TUNNEL/200 39 CONNECT server.example.com:443 test HIER_DIRECT/6.7.8.9 -
(IP addresses were replaced with generic values)
The HAProxy log shows, that the correct backend is used:
Jun 3 08:39:57 localhost haproxy[3547]: 192.168.1.20:39398 [03/Jun/2020:08:38:56.855] https-in~ backend-proxy/proxy 154/0/13/209/60375 200 39 - - ---- 0/0/0/0/0 0/0 "GET /someurl HTTP/1.1"
(IP addresses were replaced with generic values)
So far so good. But I am unable to establish a successful communication to server.example.com from my Client. I think I have to use a second/other backend, which will not mangle the requests any more (exchange method and path) but instead use the given TCP port from the forwarding proxy to transmit the request.
How can I save the 'state' of the communication to my backend / proxy server in HAProxy, so the request could be resend to another backend?
How to extract and use the TCP port from the response of the Forwarding Proxy?
Is there a way to check, if the TCP tunnel on the Forwarding Proxy is still opened or do I need to request it using CONNECT every time before I want to use it?
EDIT:
I solved the situation by using stunnel as an intermediary to handle the TCP tunnel creation with CONNECT against the Forwarding Proxy.
If you have an upstream HTTP proxy (like squid) (not a socks proxy) and you want to have haproxy accept connections and open the tunnel thru the upstream proxy (such that the haproxy clients do not support doing so themselves via http/CONNECT method) on behalf of the clients, then this functionality does not exist in haproxy today.
I crated a branch that does this via server keyword proxy-tunnel.
The below example config will behave such that clients of haproxy that connect to port 20025 (haproxy) will result in haproxy establishing a http/CONNECT tunnel via the upstream proxy 172.16.0.99:50443 to 172.16.0.2:2023:
listen SMTP-20025
bind 0.0.0.0:20025
server TEST_SERVERVIA_PROXY 172.16.0.2:2023 proxy-tunnel 172.16.0.99:50443

HAPROXY roundrobin DNS on backend server domain

I have read allot of posts and tried several things, but can't seem to get what I want working and stable.
I have HAproxy setup as a pure proxy. The IP/domain of the HAproxy passes ALL to the backend server.
My issues is that the backend server domain has 2 IPs in DNS:
1.1.1.1
2.2.2.2
When the provider switches or removes an IP, HAproxy does not update to the "new" IP and gives a backend not reachable error in the logs:
Message from syslogd#localhost at Jul 18 16:15:02 ...
haproxy[3233]: backend b-http has no server available!
But there is a valid and working server on one of the ips. A restart which forces HAproxy to do a lookup normally fixes this, but I'd prefer for it to be automatic.
On HAproxy version haproxy-1.5.18 I have:
frontend f-http
bind :80
default_backend b-http
backend b-http
option forwardfor
server web-1 domain.com:80 check
I have tried on HAproxy version haproxy-1.7.8-1 I have:
resolvers public-dns
nameserver dns2 8.8.8.8:53
nameserver dns1 8.8.4.4:53
hold valid 10s
frontend f-http
bind :80
default_backend b-http
backend b-http
option forwardfor
server web-1 domain.com:80 resolvers public-dns check
As above dig on domain.com would return 2 A records. I'm thinking that there must be some config which will continue to check the IPs for a valid/working IP and start to use that one on the fly.
Any help is very much appreciated.

haproxy reverse ssl termination

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.

HAProxy http check on for ssl?

I have some web servers which are MySQL backend. An HAProxy is in front of those web servers. All the web servers are using https.
I tried to use the http check option on both http and https to make sure if the database connection was lost, the HAProxy will failover to another node. My haproxy configuration file:
global
log /dev/log local0
maxconn 4096
#debug
#quiet
user haproxy
group haproxy
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen http
bind *:80
mode http
balance roundrobin
stats enable
stats auth haproxy:haproxy
cookie JSESSIONID prefix
stick on src table https
option http-server-close
option forwardfor
default-server inter 5s fall 2
option httpchk
http-check expect ! string Database\ error
server sitea 192.168.0.20 cookie sitea check port 80
server siteb 192.168.0.21 cookie siteb check port 80
listen https
bind *:443
mode tcp
balance roundrobin
stick-table type ip size 5000k expire 2h store conn_cur
stick on src
option tcplog
option ssl-hello-chk
default-server inter 5s fall 2
option httpchk
http-check expect ! string Database\ error
server sitea 192.168.0.20:443 check ssl verify none
server siteb 192.168.0.21:443 check ssl verify none
Look at the last two lines. If I specified "ssl verify none", my HAProxy can successfully check both Apache and MySQL status. However, I can't open the webpage via https(it prompts me This site can’t provide a secure connection. ERR_SSL_PROTOCOL_ERROR).
If I remove that parameter, the webpage can be opened again, but all the https servers status become DOWN in the HAProxy.
P.S. I'm using self-signed certificate currently, because I'm still on testing.
I have found the solution: since I am using https on apache nodes, I have to copy ssl certificates content to haproxy. To do that, copy and merge both private key and the certificate content issued by the CA into one single file(In my case, I put it into /etc/haproxy/haproxy.pem).
Modify the haproxy configuration, change
bind *:443
To
bind *:443 ssl crt /etc/haproxy/haproxy.pem